diff --git a/src/core/components/tabs/core-tabs.html b/src/core/components/tabs/core-tabs.html index 6e2a54fac..fd8cbfd53 100644 --- a/src/core/components/tabs/core-tabs.html +++ b/src/core/components/tabs/core-tabs.html @@ -18,7 +18,7 @@ {{ tab.title | translate}} {{ tab.badge }} - + diff --git a/src/core/components/tabs/tabs.ts b/src/core/components/tabs/tabs.ts index 734139814..d5f79b184 100644 --- a/src/core/components/tabs/tabs.ts +++ b/src/core/components/tabs/tabs.ts @@ -33,6 +33,9 @@ import { CoreConstants } from '@/core/constants'; import { CoreUtils } from '@services/utils/utils'; import { NavigationOptions } from '@ionic/angular/providers/nav-controller'; import { Params } from '@angular/router'; +import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons'; +import { CoreDomUtils } from '@/core/services/utils/dom'; +import { StackEvent } from '@ionic/angular/directives/navigation/stack-utils'; /** * This component displays some top scrollable tabs that will autohide on vertical scroll. @@ -105,6 +108,7 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe protected isInTransition = false; // Weather Slides is in transition. protected slidesSwiper: any; protected slidesSwiperLoaded = false; + protected stackEventsSubscription?: Subscription; constructor( protected element: ElementRef, @@ -151,6 +155,21 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe return; } + this.stackEventsSubscription = this.ionTabs!.outlet.stackEvents.subscribe(async (stackEvent: StackEvent) => { + if (this.isCurrentView) { + const content = stackEvent.enteringView.element.querySelector('ion-content'); + + this.showHideNavBarButtons(stackEvent.enteringView.element.tagName); + if (content) { + const scroll = await content.getScrollElement(); + content.scrollEvents = true; + content.addEventListener('ionScroll', (e: CustomEvent): void => { + this.showHideTabs(e, scroll); + }); + } + } + }); + this.tabBarElement = this.element.nativeElement.querySelector('ion-tab-bar'); this.tabsElement = this.element.nativeElement.querySelector('ion-tabs'); @@ -576,19 +595,29 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe this.selectedIndex = index; this.ionChange.emit(selectedTab); - - const content = this.ionTabs!.outlet.nativeEl.querySelector('ion-content'); - - if (content) { - const scroll = await content.getScrollElement(); - content.scrollEvents = true; - content.addEventListener('ionScroll', (e: CustomEvent): void => { - this.showHideTabs(e, scroll); - }); - } } } + /** + * Get all child core-navbar-buttons and show or hide depending on the page state. + * We need to use querySelectorAll because ContentChildren doesn't work with ng-template. + * https://github.com/angular/angular/issues/14842 + * + * @param activatedPageName Activated page name. + */ + protected showHideNavBarButtons(activatedPageName: string): void { + const elements = this.ionTabs!.outlet.nativeEl.querySelectorAll('core-navbar-buttons'); + const domUtils = CoreDomUtils.instance; + elements.forEach((element) => { + const instance: CoreNavBarButtonsComponent = domUtils.getInstanceByElement(element); + + if (instance) { + const pagetagName = element.closest('.ion-page')?.tagName; + instance.forceHide(activatedPageName != pagetagName); + } + }); + } + /** * Adapt tabs to a window resize. */ @@ -607,6 +636,7 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe if (this.resizeFunction) { window.removeEventListener('resize', this.resizeFunction); } + this.stackEventsSubscription?.unsubscribe(); } } diff --git a/src/core/features/courses/pages/dashboard/dashboard.html b/src/core/features/courses/pages/dashboard/dashboard.html index a2a6c650c..53ab4c47d 100644 --- a/src/core/features/courses/pages/dashboard/dashboard.html +++ b/src/core/features/courses/pages/dashboard/dashboard.html @@ -1,3 +1,16 @@ + + + + + + + + + diff --git a/src/core/features/courses/pages/dashboard/dashboard.page.ts b/src/core/features/courses/pages/dashboard/dashboard.page.ts index 458512990..16382a526 100644 --- a/src/core/features/courses/pages/dashboard/dashboard.page.ts +++ b/src/core/features/courses/pages/dashboard/dashboard.page.ts @@ -12,25 +12,93 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { NavController } from '@ionic/angular'; + +import { CoreCourses, CoreCoursesProvider } from '../../services/courses'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; +import { CoreSites } from '@services/sites'; /** - * Page that displays the Home. + * Page that displays the dashboard page. */ @Component({ selector: 'page-core-courses-dashboard', templateUrl: 'dashboard.html', styleUrls: ['dashboard.scss'], }) -export class CoreCoursesDashboardPage implements OnInit { +export class CoreCoursesDashboardPage implements OnInit, OnDestroy { + + searchEnabled = false; + downloadEnabled = false; + downloadCourseEnabled = false; + downloadCoursesEnabled = false; + downloadEnabledIcon = 'far-square'; + + protected updateSiteObserver?: CoreEventObserver; siteName = 'Hello world'; + constructor( + protected navCtrl: NavController, + ) { } + /** * Initialize the component. */ ngOnInit(): void { - // @todo + this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite(); + this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite(); + this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite(); + + // Refresh the enabled flags if site is updated. + this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { + this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite(); + this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite(); + this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite(); + + this.switchDownload(this.downloadEnabled && this.downloadCourseEnabled && this.downloadCoursesEnabled); + }, CoreSites.instance.getCurrentSiteId()); } + /** + * Toggle download enabled. + */ + toggleDownload(): void { + this.switchDownload(!this.downloadEnabled); + } + + /** + * Convenience function to switch download enabled. + * + * @param enable If enable or disable. + */ + protected switchDownload(enable: boolean): void { + this.downloadEnabled = (this.downloadCourseEnabled || this.downloadCoursesEnabled) && enable; + this.downloadEnabledIcon = this.downloadEnabled ? 'far-check-square' : 'far-square'; + CoreEvents.trigger(CoreCoursesProvider.EVENT_DASHBOARD_DOWNLOAD_ENABLED_CHANGED, { enabled: this.downloadEnabled }); + } + + /** + * Open page to manage courses storage. + */ + manageCoursesStorage(): void { + // @todo this.navCtrl.navigateForward(['/courses/storage']); + } + + /** + * Go to search courses. + */ + openSearch(): void { + this.navCtrl.navigateForward(['/courses/search']); + } + + /** + * Component being destroyed. + */ + ngOnDestroy(): void { + this.updateSiteObserver?.off(); + } + + } diff --git a/src/core/features/courses/pages/my-courses/my-courses.html b/src/core/features/courses/pages/my-courses/my-courses.html index b2fcc7e56..6cbd9c972 100644 --- a/src/core/features/courses/pages/my-courses/my-courses.html +++ b/src/core/features/courses/pages/my-courses/my-courses.html @@ -10,16 +10,16 @@ - - - - - - {{downloadAllCoursesBadge}} - + + + + + {{downloadAllCoursesBadge}} diff --git a/src/core/features/mainmenu/pages/home/home.html b/src/core/features/mainmenu/pages/home/home.html index d3248c03a..ad107680e 100644 --- a/src/core/features/mainmenu/pages/home/home.html +++ b/src/core/features/mainmenu/pages/home/home.html @@ -9,14 +9,6 @@ - - - - - - diff --git a/src/core/features/mainmenu/pages/home/home.page.ts b/src/core/features/mainmenu/pages/home/home.page.ts index a8a1887f7..41c78cc17 100644 --- a/src/core/features/mainmenu/pages/home/home.page.ts +++ b/src/core/features/mainmenu/pages/home/home.page.ts @@ -12,14 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit } from '@angular/core'; -import { NavController } from '@ionic/angular'; +import { Component, OnInit, ViewChild } from '@angular/core'; import { Subscription } from 'rxjs'; import { CoreSites } from '@services/sites'; import { CoreHomeDelegate, CoreHomeHandlerToDisplay } from '../../services/home.delegate'; -import { CoreCourses } from '@features/courses/services/courses'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; +import { CoreTabsComponent } from '@components/tabs/tabs'; /** * Page that displays the Home. @@ -31,20 +30,19 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events'; }) export class CoreHomePage implements OnInit { + @ViewChild(CoreTabsComponent) tabsComponent?: CoreTabsComponent; + + siteName!: string; tabs: CoreHomeHandlerToDisplay[] = []; loaded = false; selectedTab?: number; - searchEnabled = false; - downloadCourseEnabled = false; - downloadCoursesEnabled = false; protected subscription?: Subscription; protected updateSiteObserver?: CoreEventObserver; constructor( protected homeDelegate: CoreHomeDelegate, - protected navCtrl: NavController, ) { this.loadSiteName(); } @@ -53,20 +51,12 @@ export class CoreHomePage implements OnInit { * Initialize the component. */ ngOnInit(): void { - this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite(); - this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite(); - this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite(); - this.subscription = this.homeDelegate.getHandlersObservable().subscribe((handlers) => { handlers && this.initHandlers(handlers); }); // Refresh the enabled flags if site is updated. this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { - this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite(); - this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite(); - this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite(); - this.loadSiteName(); }, CoreSites.instance.getCurrentSiteId()); } @@ -114,17 +104,17 @@ export class CoreHomePage implements OnInit { } /** - * Open page to manage courses storage. + * User entered the page. */ - manageCoursesStorage(): void { - // @todo this.navCtrl.navigateForward(['/courses/storage']); + ionViewDidEnter(): void { + this.tabsComponent?.ionViewDidEnter(); } /** - * Go to search courses. + * User left the page. */ - openSearch(): void { - this.navCtrl.navigateForward(['/courses/search']); + ionViewDidLeave(): void { + this.tabsComponent?.ionViewDidLeave(); } } diff --git a/src/core/features/sitehome/pages/index/index.html b/src/core/features/sitehome/pages/index/index.html index 58715be87..ba85e91f8 100644 --- a/src/core/features/sitehome/pages/index/index.html +++ b/src/core/features/sitehome/pages/index/index.html @@ -1,3 +1,16 @@ + + + + + + + + + diff --git a/src/core/features/sitehome/pages/index/index.page.ts b/src/core/features/sitehome/pages/index/index.page.ts index 482d234d4..a9aa029c1 100644 --- a/src/core/features/sitehome/pages/index/index.page.ts +++ b/src/core/features/sitehome/pages/index/index.page.ts @@ -12,16 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; -import { IonRefresher } from '@ionic/angular'; +import { IonRefresher, NavController } from '@ionic/angular'; import { CoreSite, CoreSiteConfig } from '@classes/site'; import { CoreCourse, CoreCourseSection } from '@features/course/services/course'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreSites } from '@services/sites'; import { CoreSiteHome } from '@features/sitehome/services/sitehome'; -// import { CoreCourseHelperProvider } from '@features/course/services/helper'; +import { CoreCourses, CoreCoursesProvider } from '@features//courses/services/courses'; +import { CoreEventObserver, CoreEvents } from '@singletons/events'; +import { CoreCourseHelper } from '@features/course/services/course.helper'; /** * Page that displays site home index. @@ -30,9 +32,8 @@ import { CoreSiteHome } from '@features/sitehome/services/sitehome'; selector: 'page-core-sitehome-index', templateUrl: 'index.html', }) -export class CoreSiteHomeIndexPage implements OnInit { +export class CoreSiteHomeIndexPage implements OnInit, OnDestroy { - // @todo @Input() downloadEnabled: boolean; // @todo @ViewChild(CoreBlockCourseBlocksComponent) courseBlocksComponent: CoreBlockCourseBlocksComponent; dataLoaded = false; @@ -44,13 +45,19 @@ export class CoreSiteHomeIndexPage implements OnInit { items: string[] = []; siteHomeId?: number; currentSite?: CoreSite; + searchEnabled = false; + downloadEnabled = false; + downloadCourseEnabled = false; + downloadCoursesEnabled = false; + downloadEnabledIcon = 'far-square'; + + protected updateSiteObserver?: CoreEventObserver; constructor( protected route: ActivatedRoute, + protected navCtrl: NavController, // @todo private prefetchDelegate: CoreCourseModulePrefetchDelegate, - ) { - - } + ) {} /** * Page being initialized. @@ -58,13 +65,26 @@ export class CoreSiteHomeIndexPage implements OnInit { ngOnInit(): void { const navParams = this.route.snapshot.queryParams; + this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite(); + this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite(); + this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite(); + + // Refresh the enabled flags if site is updated. + this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { + this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite(); + this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite(); + this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite(); + + this.switchDownload(this.downloadEnabled && this.downloadCourseEnabled && this.downloadCoursesEnabled); + }, CoreSites.instance.getCurrentSiteId()); + this.currentSite = CoreSites.instance.getCurrentSite()!; this.siteHomeId = this.currentSite.getSiteHomeId(); const module = navParams['module']; if (module) { // @todo const modParams = navParams.get('modParams'); - // courseHelper.openModule(module, this.siteHomeId, undefined, modParams); + // CoreCourseHelper.instance.openModule(module, this.siteHomeId, undefined, modParams); } this.loadContent().finally(() => { @@ -92,8 +112,8 @@ export class CoreSiteHomeIndexPage implements OnInit { this.section = config.numsections ? sections.find((section) => section.section == 1) : undefined; if (this.section) { this.section.hasContent = false; - /* @todo this.section.hasContent = this.courseHelper.sectionHasContent(this.section); - this.hasContent = this.courseHelper.addHandlerDataForModules( + this.section.hasContent = CoreCourseHelper.instance.sectionHasContent(this.section); + /* @todo this.hasContent = CoreCourseHelper.instance.addHandlerDataForModules( [this.section], this.siteHomeId, undefined, @@ -152,4 +172,43 @@ export class CoreSiteHomeIndexPage implements OnInit { }); } + /** + * Toggle download enabled. + */ + toggleDownload(): void { + this.switchDownload(!this.downloadEnabled); + } + + /** + * Convenience function to switch download enabled. + * + * @param enable If enable or disable. + */ + protected switchDownload(enable: boolean): void { + this.downloadEnabled = (this.downloadCourseEnabled || this.downloadCoursesEnabled) && enable; + this.downloadEnabledIcon = this.downloadEnabled ? 'far-check-square' : 'far-square'; + CoreEvents.trigger(CoreCoursesProvider.EVENT_DASHBOARD_DOWNLOAD_ENABLED_CHANGED, { enabled: this.downloadEnabled }); + } + + /** + * Open page to manage courses storage. + */ + manageCoursesStorage(): void { + // @todo this.navCtrl.navigateForward(['/courses/storage']); + } + + /** + * Go to search courses. + */ + openSearch(): void { + this.navCtrl.navigateForward(['/courses/search']); + } + + /** + * Component being destroyed. + */ + ngOnDestroy(): void { + this.updateSiteObserver?.off(); + } + }