diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts index 4c862ebf..035ddb28 100644 --- a/src/lib/appManagers/appDialogsManager.ts +++ b/src/lib/appManagers/appDialogsManager.ts @@ -83,6 +83,7 @@ import apiManagerProxy from "../mtproto/mtprotoworker"; import filterAsync from "../../helpers/array/filterAsync"; import forEachReverse from "../../helpers/array/forEachReverse"; import indexOfAndSplice from "../../helpers/array/indexOfAndSplice"; +import whichChild from "../../helpers/dom/whichChild"; export const DIALOG_LIST_ELEMENT_TAG = 'A'; @@ -299,6 +300,17 @@ export class AppDialogsManager { (window as any).addElement = add; } */ + rootScope.addEventListener('premium_toggle', async(isPremium) => { + if(isPremium) { + return; + } + + const isFolderAvailable = await this.managers.filtersStorage.isFilterIdAvailable(this.filterId); + if(!isFolderAvailable) { + selectTab(whichChild(this.filtersRendered[FOLDER_ID_ALL].menu), false); + } + }); + rootScope.addEventListener('state_cleared', () => { const clearCurrent = REAL_FOLDERS.has(this.filterId); //setTimeout(() => @@ -331,13 +343,19 @@ export class AppDialogsManager { const foldersScrollable = new ScrollableX(this.folders.menuScrollContainer); bottomPart.prepend(this.folders.menuScrollContainer); - const selectTab = this.selectTab = horizontalMenu(this.folders.menu, this.folders.container, (id, tabContent, animate) => { + const selectTab = this.selectTab = horizontalMenu(this.folders.menu, this.folders.container, async(id, tabContent) => { /* if(id !== 0) { id += 1; } */ + id = +tabContent.dataset.filterId || FOLDER_ID_ALL; + const isFilterAvailable = REAL_FOLDERS.has(id) || await this.managers.filtersStorage.isFilterIdAvailable(id); + if(!isFilterAvailable) { + return false; + } + const wasFilterId = this.filterId; if(!IS_MOBILE_SAFARI) { if(id) { diff --git a/src/lib/appManagers/appImManager.ts b/src/lib/appManagers/appImManager.ts index e2469db3..87e6d6f3 100644 --- a/src/lib/appManagers/appImManager.ts +++ b/src/lib/appManagers/appImManager.ts @@ -205,6 +205,10 @@ export class AppImManager extends EventListenerBase<{ this.setSettings(); rootScope.addEventListener('settings_updated', this.setSettings); + rootScope.addEventListener('premium_toggle', (isPremium) => { + document.body.classList.toggle('is-premium', isPremium); + }); + useHeavyAnimationCheck(() => { animationIntersector.setOnlyOnePlayableGroup('lock'); animationIntersector.checkAnimations(true); diff --git a/src/lib/appManagers/appUsersManager.ts b/src/lib/appManagers/appUsersManager.ts index 780706f8..09168c6c 100644 --- a/src/lib/appManagers/appUsersManager.ts +++ b/src/lib/appManagers/appUsersManager.ts @@ -133,6 +133,8 @@ export class AppUsersManager extends AppManager { this.users[user.id] = user; this.setUserNameToCache(user); + this.checkPremium(user); + if(state.contactsListCachedTime && (user.pFlags.contact || user.pFlags.mutual_contact)) { this.pushContact(user.id); @@ -540,9 +542,20 @@ export class AppUsersManager extends AppManager { this.rootScope.dispatchEvent('peer_title_edit', user.id.toPeerId()); } + this.checkPremium(user); this.setUserToStateIfNeeded(user); } + private checkPremium(user: User) { + if(user.pFlags.self) { + const isPremium = !!user.pFlags.premium; + if(this.rootScope.premium !== isPremium) { + this.rootScope.premium = isPremium; + this.rootScope.dispatchEvent('premium_toggle', isPremium); + } + } + } + private setUserToStateIfNeeded(user: User) { if(this.peersStorage.isPeerNeeded(user.id.toPeerId())) { this.storage.set({ diff --git a/src/lib/mtproto/apiManager.ts b/src/lib/mtproto/apiManager.ts index 283073c5..54a1558b 100644 --- a/src/lib/mtproto/apiManager.ts +++ b/src/lib/mtproto/apiManager.ts @@ -130,6 +130,15 @@ export class ApiManager extends ApiManagerMethods { /// #endif } + protected after() { + this.apiUpdatesManager.addMultipleEventsListeners({ + updateConfig: () => { + this.getConfig(); + this.getAppConfig(true); + } + }); + } + //private lol = false; // constructor() { diff --git a/src/lib/rootScope.ts b/src/lib/rootScope.ts index 1f7cb343..64ef3da5 100644 --- a/src/lib/rootScope.ts +++ b/src/lib/rootScope.ts @@ -138,7 +138,9 @@ export type BroadcastEvents = { 'logging_out': void, - 'payment_sent': {peerId: PeerId, mid: number} + 'payment_sent': {peerId: PeerId, mid: number}, + + 'premium_toggle': boolean }; export type BroadcastEventsListeners = { diff --git a/src/lib/storages/filters.ts b/src/lib/storages/filters.ts index 871326be..0973ed96 100644 --- a/src/lib/storages/filters.ts +++ b/src/lib/storages/filters.ts @@ -51,22 +51,7 @@ export default class FiltersStorage extends AppManager { this.apiUpdatesManager.addMultipleEventsListeners({ updateDialogFilter: this.onUpdateDialogFilter, - updateDialogFilters: (update) => { - //console.warn('updateDialogFilters', update); - - const oldFilters = copy(this.filters); - - this.getDialogFilters(true).then((filters) => { - for(const _filterId in oldFilters) { - const filterId = +_filterId; - if(!filters.find((filter) => filter.id === filterId)) { // * deleted - this.onUpdateDialogFilter({_: 'updateDialogFilter', id: filterId}); - } - } - - this.onUpdateDialogFilterOrder({_: 'updateDialogFilterOrder', order: filters.map((filter) => filter.id)}); - }); - }, + updateDialogFilters: this.onUpdateDialogFilters, updateDialogFilterOrder: this.onUpdateDialogFilterOrder }); @@ -91,6 +76,10 @@ export default class FiltersStorage extends AppManager { } }); */ + this.rootScope.addEventListener('premium_toggle', () => { + this.onUpdateDialogFilters({_: 'updateDialogFilters'}); + }); + return this.appStateManager.getState().then((state) => { const filtersArr = this.prependFilters(state.filtersArr); filtersArr.map((filter) => { @@ -174,6 +163,23 @@ export default class FiltersStorage extends AppManager { this.pushToState(); }; + private onUpdateDialogFilters = (update: Update.updateDialogFilters) => { + //console.warn('updateDialogFilters', update); + + const oldFilters = copy(this.filters); + + this.getDialogFilters(true).then((filters) => { + for(const _filterId in oldFilters) { + const filterId = +_filterId; + if(!filters.find((filter) => filter.id === filterId)) { // * deleted + this.onUpdateDialogFilter({_: 'updateDialogFilter', id: filterId}); + } + } + + this.onUpdateDialogFilterOrder({_: 'updateDialogFilterOrder', order: filters.map((filter) => filter.id)}); + }); + }; + private onUpdateDialogFilterOrder = (update: Update.updateDialogFilterOrder) => { //console.log('updateDialogFilterOrder', update); @@ -533,4 +539,20 @@ export default class FiltersStorage extends AppManager { this.pushToState(); } } + + public async isFilterIdAvailable(filterId: number) { + if(REAL_FOLDERS.has(filterId)) { + return true; + } + + const isPremium = this.rootScope.premium; + let isFolderAvailable = isPremium; + if(!isPremium) { + const config = await this.apiManager.getAppConfig(); + const limit = config.dialog_filters_limit_default; + isFolderAvailable = this.filtersArr.filter((filter) => !REAL_FOLDERS.has(filter.id)).slice(0, limit).some((filter) => filter.id === filterId); + } + + return isFolderAvailable; + } } diff --git a/src/scss/mixins/_premium.scss b/src/scss/mixins/_premium.scss new file mode 100644 index 00000000..e6a77f5a --- /dev/null +++ b/src/scss/mixins/_premium.scss @@ -0,0 +1,17 @@ +/* + * https://github.com/morethanwords/tweb + * Copyright (C) 2019-2021 Eduard Kuzmenko + * https://github.com/morethanwords/tweb/blob/master/LICENSE + */ + +@mixin premium($not: false) { + @if $not { + body:not(.is-premium) & { + @content; + } + } @else { + body.is-premium & { + @content; + } + } +} diff --git a/src/scss/partials/_leftSidebar.scss b/src/scss/partials/_leftSidebar.scss index e8fdbbf5..11d1c06e 100644 --- a/src/scss/partials/_leftSidebar.scss +++ b/src/scss/partials/_leftSidebar.scss @@ -610,6 +610,15 @@ } } +// #folders-tabs { +// @include premium(true) { +// .menu-horizontal-div-item:nth-child(n+12) { +// pointer-events: none; +// opacity: .2; +// } +// } +// } + .edit-profile-container { .scroll-wrapper { width: 100%; diff --git a/src/scss/style.scss b/src/scss/style.scss index 6d7c8f9f..209c7df7 100644 --- a/src/scss/style.scss +++ b/src/scss/style.scss @@ -48,6 +48,7 @@ $chat-input-inner-padding-handhelds: .25rem; @import "mixins/respondTo"; @import "mixins/textOverflow"; @import "mixins/animationLevel"; +@import "mixins/premium"; :root { --vh: 1vh;