diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index a7a1465c..44d54290 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -24,6 +24,7 @@ dependencies { implementation project(':capacitor-share') implementation project(':capacitor-splash-screen') implementation project(':capacitor-status-bar') + implementation project(':hugotomazi-capacitor-navigation-bar') implementation project(':transistorsoft-capacitor-background-fetch') implementation project(':capacitor-secure-storage-plugin') implementation "com.android.support:support-v4:27.+" diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 7f2554b1..4b0f6e3c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,22 @@ + + - + diff --git a/android/app/src/main/assets/capacitor.plugins.json b/android/app/src/main/assets/capacitor.plugins.json index 8f279473..fcbe05b4 100644 --- a/android/app/src/main/assets/capacitor.plugins.json +++ b/android/app/src/main/assets/capacitor.plugins.json @@ -59,6 +59,10 @@ "pkg": "@capacitor/status-bar", "classpath": "com.capacitorjs.plugins.statusbar.StatusBarPlugin" }, + { + "pkg": "@hugotomazi/capacitor-navigation-bar", + "classpath": "br.com.tombus.capacitor.plugin.navigationbar.NavigationBarPlugin" + }, { "pkg": "@transistorsoft/capacitor-background-fetch", "classpath": "com.transistorsoft.bgfetch.capacitor.BackgroundFetchPlugin" diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index ae1f29c2..8ff9e6b1 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -47,6 +47,9 @@ project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capa include ':capacitor-status-bar' project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android') +include ':hugotomazi-capacitor-navigation-bar' +project(':hugotomazi-capacitor-navigation-bar').projectDir = new File('../node_modules/@hugotomazi/capacitor-navigation-bar/android') + include ':transistorsoft-capacitor-background-fetch' project(':transistorsoft-capacitor-background-fetch').projectDir = new File('../node_modules/@transistorsoft/capacitor-background-fetch/android') diff --git a/package-lock.json b/package-lock.json index 68da6d18..d8a75ed7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2774,6 +2774,11 @@ "@hapi/hoek": "^9.0.0" } }, + "@hugotomazi/capacitor-navigation-bar": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hugotomazi/capacitor-navigation-bar/-/capacitor-navigation-bar-2.0.0.tgz", + "integrity": "sha512-hebf0ixGPugiZfH6g7HS/hrDzkKmNdJV/pV2jUz5lfoZXFMjE+7aeAr1AqwW6EGNej65WcEP8VUL5YUc3wSCjw==" + }, "@humanwhocodes/config-array": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", @@ -3899,6 +3904,26 @@ "traverse": "0.6.6", "uuid": "8.3.2", "wait-on": "6.0.1" + }, + "dependencies": { + "@openstapps/core": { + "version": "0.69.0", + "resolved": "https://registry.npmjs.org/@openstapps/core/-/core-0.69.0.tgz", + "integrity": "sha512-IaUb10IfldokrqopdqsyHl5j3rVvg8CA10s2E+WpVOjgkXnW8SP9jVg5AP0jx3vgN3e0xHsrPtvrZWTPgyoSRQ==", + "requires": { + "@openstapps/core-tools": "0.32.0", + "@types/geojson": "1.0.6", + "@types/json-patch": "0.0.30", + "@types/json-schema": "7.0.11", + "@types/node": "14.18.24", + "fast-deep-equal": "3.1.3", + "http-status-codes": "2.2.0", + "json-patch": "0.7.0", + "json-schema": "0.4.0", + "rfdc": "1.3.0", + "ts-optchain": "0.1.8" + } + } } }, "@openstapps/configuration": { diff --git a/package.json b/package.json index 1c13eb31..cc3ede64 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "@openstapps/api": "0.43.0", "@openstapps/configuration": "0.33.0", "@openstapps/core": "0.70.0", + "@hugotomazi/capacitor-navigation-bar": "2.0.0", "@transistorsoft/capacitor-background-fetch": "1.0.0", "capacitor-secure-storage-plugin": "0.8.0", "cordova-plugin-calendar": "5.1.6", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index c285a323..08f61fdd 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 StApps + * Copyright (C) 2022 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. @@ -22,6 +22,7 @@ import {environment} from '../environments/environment'; import {StatusBar, Style} from '@capacitor/status-bar'; import {Capacitor} from '@capacitor/core'; import {ScheduleSyncService} from './modules/background/schedule/schedule-sync.service'; +import {NavigationBar} from '@hugotomazi/capacitor-navigation-bar'; import {Keyboard, KeyboardResize} from '@capacitor/keyboard'; /** @@ -99,6 +100,11 @@ export class AppComponent implements AfterContentInit { .trim(), }); await StatusBar.setStyle({style: Style.Dark}); + await NavigationBar.setColor({ + color: getComputedStyle(document.documentElement) + .getPropertyValue('--ion-background-color') + .trim(), + }); } await this.authNotificationsInit(); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index da50a840..eea76755 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,16 +1,16 @@ /* * Copyright (C) 2022 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ import { CommonModule, @@ -64,8 +64,7 @@ import {FavoritesModule} from './modules/favorites/favorites.module'; import {ProfilePageModule} from './modules/profile/profile.module'; import {FeedbackModule} from './modules/feedback/feedback.module'; import {DebugDataCollectorService} from './modules/data/debug-data-collector.service'; -import {Browser} from './util/browser.factory'; -import {browserFactory} from './util/browser.factory'; +import {Browser, browserFactory} from './util/browser.factory'; import {AuthModule} from './modules/auth/auth.module'; import {BackgroundModule} from './modules/background/background.module'; import {LibraryModule} from './modules/library/library.module'; @@ -77,6 +76,7 @@ import {SCSettingValue} from '@openstapps/core'; import {DefaultAuthService} from './modules/auth/default-auth.service'; import {PAIAAuthService} from './modules/auth/paia/paia-auth.service'; import {IonIconModule} from './util/ion-icon/ion-icon.module'; +import {NavigationModule} from './modules/menu/navigation/navigation.module'; registerLocaleData(localeDe); @@ -170,6 +170,7 @@ export function createTranslateLoader(http: HttpClient) { FeedbackModule, MapModule, MenuModule, + NavigationModule, NewsModule, ScheduleModule, SettingsModule, diff --git a/src/app/modules/dashboard/sections/favorites-section/favorites-section.component.ts b/src/app/modules/dashboard/sections/favorites-section/favorites-section.component.ts index 59453f10..5ee6fbd0 100644 --- a/src/app/modules/dashboard/sections/favorites-section/favorites-section.component.ts +++ b/src/app/modules/dashboard/sections/favorites-section/favorites-section.component.ts @@ -14,7 +14,7 @@ */ import {Component, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; -import {AlertController} from '@ionic/angular'; +import {AlertController, AnimationController} from '@ionic/angular'; import {combineLatest} from 'rxjs'; import { debounceTime, @@ -58,6 +58,7 @@ export class FavoritesSectionComponent positionService: PositionService, private favoritesService: FavoritesService, configProvider: ConfigProvider, + animationController: AnimationController, ) { super( alertController, @@ -70,6 +71,7 @@ export class FavoritesSectionComponent route, positionService, configProvider, + animationController, ); } diff --git a/src/app/modules/dashboard/sections/mensa-section/mensa-section.component.ts b/src/app/modules/dashboard/sections/mensa-section/mensa-section.component.ts index 7a4d55ba..40f36089 100644 --- a/src/app/modules/dashboard/sections/mensa-section/mensa-section.component.ts +++ b/src/app/modules/dashboard/sections/mensa-section/mensa-section.component.ts @@ -14,7 +14,11 @@ */ import {Component} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; -import {AlertController, ModalController} from '@ionic/angular'; +import { + AlertController, + AnimationController, + ModalController, +} from '@ionic/angular'; import {combineLatest, Subscription} from 'rxjs'; import { debounceTime, @@ -58,6 +62,7 @@ export class MensaSectionComponent extends FoodDataListComponent { public modalController: ModalController, protected favoritesService: FavoritesService, configProvider: ConfigProvider, + animationController: AnimationController, ) { super( alertController, @@ -70,6 +75,7 @@ export class MensaSectionComponent extends FoodDataListComponent { route, positionService, configProvider, + animationController, ); } diff --git a/src/app/modules/data/list/search-page-switch-animation.ts b/src/app/modules/data/list/search-page-switch-animation.ts new file mode 100644 index 00000000..5bde4a72 --- /dev/null +++ b/src/app/modules/data/list/search-page-switch-animation.ts @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +import type {AnimationBuilder} from '@ionic/angular'; +import {AnimationController} from '@ionic/angular'; +import type {AnimationOptions} from '@ionic/angular/providers/nav-controller'; + +/** + * + */ +export function searchPageSwitchAnimation( + animationController: AnimationController, +): AnimationBuilder { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (_baseElement: HTMLElement, options: AnimationOptions | any) => { + const rootTransition = animationController + .create() + .duration(options.duration ?? 200) + .easing('ease'); + + const enterTransition = animationController + .create() + .fromTo('opacity', '0', '1') + .addElement(options.enteringEl); + const exitTransition = animationController + .create() + .fromTo('opacity', '1', '1') + .addElement(options.leavingEl); + console.log(options.enteringEl.querySelector('stapps-data-list')); + const contentSlide = animationController + .create() + .fromTo('transform', 'translateX(600px)', 'translateX(0px)') + .addElement(options.enteringEl.querySelector('stapps-data-list')); + + rootTransition.addAnimation([ + enterTransition, + exitTransition, + contentSlide, + ]); + return rootTransition; + }; +} diff --git a/src/app/modules/data/list/search-page.component.ts b/src/app/modules/data/list/search-page.component.ts index 3fb37433..9dda6c8f 100644 --- a/src/app/modules/data/list/search-page.component.ts +++ b/src/app/modules/data/list/search-page.component.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 StApps + * Copyright (C) 2022 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. @@ -12,10 +12,14 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input, OnInit, OnDestroy} from '@angular/core'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {Keyboard} from '@capacitor/keyboard'; -import {AlertController} from '@ionic/angular'; +import { + AlertController, + AnimationBuilder, + AnimationController, +} from '@ionic/angular'; import { SCFacet, SCFeatureConfiguration, @@ -33,6 +37,7 @@ import {DataRoutingService} from '../data-routing.service'; import {DataProvider} from '../data.provider'; import {PositionService} from '../../map/position.service'; import {ConfigProvider} from '../../config/config.provider'; +import {searchPageSwitchAnimation} from './search-page-switch-animation'; /** * SearchPageComponent queries things and shows list of things as search results and filter as context menu @@ -138,6 +143,8 @@ export class SearchPageComponent implements OnInit, OnDestroy { */ subscriptions: Subscription[] = []; + routeAnimation: AnimationBuilder; + /** * Injects the providers and creates subscriptions * @@ -163,7 +170,10 @@ export class SearchPageComponent implements OnInit, OnDestroy { private readonly route: ActivatedRoute, protected positionService: PositionService, private readonly configProvider: ConfigProvider, - ) {} + animationController: AnimationController, + ) { + this.routeAnimation = searchPageSwitchAnimation(animationController); + } /** * Fetches items with set query configuration diff --git a/src/app/modules/data/list/search-page.html b/src/app/modules/data/list/search-page.html index 63f14845..201f28cd 100644 --- a/src/app/modules/data/list/search-page.html +++ b/src/app/modules/data/list/search-page.html @@ -1,16 +1,16 @@ @@ -50,6 +50,8 @@ }} {{ 'hebisSearch.type' | translate }} diff --git a/src/app/modules/data/list/search-provider.ts b/src/app/modules/data/list/search-provider.ts new file mode 100644 index 00000000..b088485d --- /dev/null +++ b/src/app/modules/data/list/search-provider.ts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +import {SCThings} from '@openstapps/core'; + +export abstract class SearchProvider { + abstract fetchAndUpdateItems(append: boolean): Promise | void; + + abstract route(item: SCThings): Promise | void; +} diff --git a/src/app/modules/favorites/favorites-page.component.ts b/src/app/modules/favorites/favorites-page.component.ts index f76b76a1..f89055a7 100644 --- a/src/app/modules/favorites/favorites-page.component.ts +++ b/src/app/modules/favorites/favorites-page.component.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 StApps + * Copyright (C) 2022 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. @@ -13,7 +13,7 @@ * this program. If not, see . */ import {Component, OnInit} from '@angular/core'; -import {AlertController} from '@ionic/angular'; +import {AlertController, AnimationController} from '@ionic/angular'; import {ActivatedRoute, Router} from '@angular/router'; import {NGXLogger} from 'ngx-logger'; import { @@ -61,6 +61,7 @@ export class FavoritesPageComponent positionService: PositionService, private favoritesService: FavoritesService, configProvider: ConfigProvider, + animationController: AnimationController, ) { super( alertController, @@ -73,6 +74,7 @@ export class FavoritesPageComponent route, positionService, configProvider, + animationController, ); } diff --git a/src/app/modules/hebis/hebis-search.provider.ts b/src/app/modules/hebis/hebis-search.provider.ts new file mode 100644 index 00000000..5f7c0465 --- /dev/null +++ b/src/app/modules/hebis/hebis-search.provider.ts @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +import {Injectable} from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class HebisSearchProvider {} diff --git a/src/app/modules/hebis/list/hebis-search-page.component.ts b/src/app/modules/hebis/list/hebis-search-page.component.ts index ee2a7ca1..27a66184 100644 --- a/src/app/modules/hebis/list/hebis-search-page.component.ts +++ b/src/app/modules/hebis/list/hebis-search-page.component.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 StApps + * Copyright (C) 2022 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. @@ -12,9 +12,9 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ -import {Component, Input, OnInit, OnDestroy} from '@angular/core'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; -import {AlertController} from '@ionic/angular'; +import {AlertController, AnimationController} from '@ionic/angular'; import {NGXLogger} from 'ngx-logger'; import {combineLatest} from 'rxjs'; import {debounceTime, distinctUntilChanged, startWith} from 'rxjs/operators'; @@ -73,6 +73,7 @@ export class HebisSearchPageComponent route: ActivatedRoute, protected positionService: PositionService, configProvider: ConfigProvider, + animationController: AnimationController, ) { super( alertController, @@ -85,6 +86,7 @@ export class HebisSearchPageComponent route, positionService, configProvider, + animationController, ); } diff --git a/src/app/modules/hebis/list/hebis-search-page.html b/src/app/modules/hebis/list/hebis-search-page.html index cded27ca..3e5ff5b6 100644 --- a/src/app/modules/hebis/list/hebis-search-page.html +++ b/src/app/modules/hebis/list/hebis-search-page.html @@ -1,3 +1,18 @@ + + @@ -23,6 +38,7 @@ {{ 'search.type' | translate }} diff --git a/src/app/modules/menu/menu.module.ts b/src/app/modules/menu/menu.module.ts index fb04d040..9402cac3 100644 --- a/src/app/modules/menu/menu.module.ts +++ b/src/app/modules/menu/menu.module.ts @@ -1,16 +1,16 @@ /* * Copyright (C) 2022 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; @@ -22,16 +22,14 @@ import {TranslateModule} from '@ngx-translate/core'; import {SettingsModule} from '../settings/settings.module'; import {ContextMenuComponent} from './context/context-menu.component'; import {ContextMenuService} from './context/context-menu.service'; -import {NavigationComponent} from './navigation/navigation.component'; -import {TabsModule} from './tabs/tabs.module'; import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; /** * Menu module */ @NgModule({ - declarations: [NavigationComponent, ContextMenuComponent], - exports: [NavigationComponent, ContextMenuComponent], + declarations: [ContextMenuComponent], + exports: [ContextMenuComponent], imports: [ CommonModule, IonIconModule, @@ -40,7 +38,6 @@ import {IonIconModule} from '../../util/ion-icon/ion-icon.module'; RouterModule, SettingsModule, TranslateModule.forChild(), - TabsModule, LayoutModule, ], providers: [ContextMenuService], diff --git a/src/app/modules/menu/navigation/navigation.html b/src/app/modules/menu/navigation/navigation.html index 9afe439e..e4f8ea98 100644 --- a/src/app/modules/menu/navigation/navigation.html +++ b/src/app/modules/menu/navigation/navigation.html @@ -1,3 +1,18 @@ + + - + @@ -25,17 +36,12 @@ {{ category.translations[language].name | titlecase }} - - - - - {{ item.translations[language].title | titlecase }} - - - + + + + {{ item.translations[language].title | titlecase }} + + diff --git a/src/app/modules/menu/navigation/navigation.module.ts b/src/app/modules/menu/navigation/navigation.module.ts new file mode 100644 index 00000000..6e6211d2 --- /dev/null +++ b/src/app/modules/menu/navigation/navigation.module.ts @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +import {NgModule} from '@angular/core'; +import {RootLinkDirective} from './root-link.directive'; +import {NavigationComponent} from './navigation.component'; +import {TabsComponent} from './tabs.component'; +import {CommonModule} from '@angular/common'; +import {IonicModule} from '@ionic/angular'; +import {IonIconModule} from '../../../util/ion-icon/ion-icon.module'; +import {TranslateModule} from '@ngx-translate/core'; +import {RouterModule} from '@angular/router'; + +@NgModule({ + declarations: [RootLinkDirective, NavigationComponent, TabsComponent], + imports: [ + CommonModule, + IonicModule, + IonIconModule, + TranslateModule, + RouterModule, + ], + exports: [TabsComponent, RootLinkDirective, NavigationComponent], +}) +export class NavigationModule {} diff --git a/src/app/modules/menu/navigation/navigation.scss b/src/app/modules/menu/navigation/navigation.scss index a0d8d0c3..b4aee603 100644 --- a/src/app/modules/menu/navigation/navigation.scss +++ b/src/app/modules/menu/navigation/navigation.scss @@ -1,7 +1,21 @@ +/*! + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + @import '../../../../theme/util/mixins'; :host { - ion-split-pane { margin-bottom: calc(var(--ion-tabbar-height) + env(safe-area-inset-bottom)); @@ -32,3 +46,16 @@ } } } + +ion-router-outlet { + background: white; +} + +.link-active > * { + color: var(--ion-color-primary); + + ::ng-deep stapps-icon { + --fill: 1; + } +} + diff --git a/src/app/modules/menu/navigation/root-link.directive.ts b/src/app/modules/menu/navigation/root-link.directive.ts new file mode 100644 index 00000000..bc235e12 --- /dev/null +++ b/src/app/modules/menu/navigation/root-link.directive.ts @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +import { + Directive, + ElementRef, + Input, + OnDestroy, + OnInit, + Renderer2, +} from '@angular/core'; +import {AnimationController, NavController} from '@ionic/angular'; +import {Router, RouterEvent} from '@angular/router'; +import {tabsTransition} from './tabs-transition'; +import {Subscription} from 'rxjs'; + +@Directive({ + selector: '[rootLink]', +}) +export class RootLinkDirective implements OnInit, OnDestroy { + @Input() rootLink: string; + + @Input() redirectedFrom: string; + + dispose: () => void; + + subscriptions: Subscription[] = []; + + private readonly classNames = ['tab-selected', 'link-active']; + + private needsInit = true; + + constructor( + private element: ElementRef, + private renderer: Renderer2, + private navController: NavController, + private router: Router, + private animationController: AnimationController, + ) {} + + ngOnInit() { + const animation = tabsTransition(this.animationController); + this.renderer.setAttribute(this.element.nativeElement, 'button', ''); + + this.subscriptions.push( + this.router.events.subscribe(event => { + if ( + event instanceof RouterEvent && + // @ts-expect-error access private member + (this.navController.direction === 'root' || this.needsInit) + ) { + if ( + event.url === this.rootLink || + (this.redirectedFrom && event.url === this.redirectedFrom) + ) { + this.setActive(); + } else { + this.setInactive(); + } + this.needsInit = false; + } + }), + ); + + this.dispose = this.renderer.listen( + this.element.nativeElement, + 'click', + () => { + this.setActive(); + this.navController.setDirection('root', true, 'back', animation); + void this.router.navigate([this.rootLink]); + }, + ); + } + + setActive() { + for (const className of this.classNames) { + this.renderer.addClass(this.element.nativeElement, className); + } + } + + setInactive() { + for (const className of this.classNames) { + this.renderer.removeClass(this.element.nativeElement, className); + } + } + + ngOnDestroy() { + this.dispose(); + for (const subscription of this.subscriptions) { + subscription.unsubscribe(); + } + } +} diff --git a/src/app/modules/menu/navigation/tabs-routing.module.ts b/src/app/modules/menu/navigation/tabs-routing.module.ts new file mode 100644 index 00000000..7b675a26 --- /dev/null +++ b/src/app/modules/menu/navigation/tabs-routing.module.ts @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +import {NgModule} from '@angular/core'; +import {RouterModule, Routes} from '@angular/router'; + +const routes: Routes = [ + { + path: '', + redirectTo: '/dashboard', + pathMatch: 'full', + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class TabsRoutingModule {} diff --git a/src/app/modules/menu/navigation/tabs-transition.ts b/src/app/modules/menu/navigation/tabs-transition.ts new file mode 100644 index 00000000..06825bea --- /dev/null +++ b/src/app/modules/menu/navigation/tabs-transition.ts @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +import type {AnimationBuilder} from '@ionic/angular'; +import {AnimationController} from '@ionic/angular'; +import type {AnimationOptions} from '@ionic/angular/providers/nav-controller'; + +/** + * + */ +export function tabsTransition( + animationController: AnimationController, +): AnimationBuilder { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (_baseElement: HTMLElement, options: AnimationOptions | any) => { + const duration = options.duration || 350; + const contentExitDuration = options.contentExitDuration || 100; + + const rootTransition = animationController.create().duration(duration); + + const enterTransition = animationController + .create() + .fromTo('opacity', '1', '1') + .addElement(options.enteringEl); + const exitZIndex = animationController + .create() + .beforeStyles({zIndex: 0}) + .afterClearStyles(['zIndex']) + .addElement(options.leavingEl); + const exitTransition = animationController + .create() + .duration(contentExitDuration * 2) + .easing('cubic-bezier(0.87, 0, 0.13, 1)') + .fromTo('opacity', '1', '0') + .addElement(options.leavingEl.querySelector('ion-header')); + const contentExit = animationController + .create() + .easing('linear') + .duration(contentExitDuration) + .fromTo('opacity', '1', '0') + .addElement( + options.leavingEl.querySelectorAll(':scope > *:not(ion-header)'), + ); + const contentEnter = animationController + .create() + .delay(contentExitDuration) + .duration(duration - contentExitDuration) + .easing('cubic-bezier(0.16, 1, 0.3, 1)') + .fromTo('transform', 'scale(1.025)', 'scale(1)') + .fromTo('opacity', '0', '1') + .addElement( + options.enteringEl.querySelectorAll(':scope > *:not(ion-header)'), + ); + + rootTransition.addAnimation([ + enterTransition, + contentExit, + contentEnter, + exitTransition, + exitZIndex, + ]); + return rootTransition; + }; +} diff --git a/src/app/modules/menu/tabs/tabs.component.scss b/src/app/modules/menu/navigation/tabs.component.scss similarity index 55% rename from src/app/modules/menu/tabs/tabs.component.scss rename to src/app/modules/menu/navigation/tabs.component.scss index cd51a59e..e898b864 100644 --- a/src/app/modules/menu/tabs/tabs.component.scss +++ b/src/app/modules/menu/navigation/tabs.component.scss @@ -1,19 +1,31 @@ /*! * Copyright (C) 2022 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . */ :host { + position: absolute; + bottom: 0; + left: 0; + right: 0; + z-index: 100; +} + +.tab-selected ::ng-deep stapps-icon { + --fill: 1; +} + +/*:host { display: flex; flex-direction: row; background: var(--ion-color-primary-contrast); @@ -36,8 +48,7 @@ background: var(--ion-color-primary-contrast); text-decoration: none; - &:focus, - &.active{ + &.active-root-link { color: var(--ion-color-medium-contrast); ion-icon ::ng-deep stapps-icon { @@ -48,10 +59,11 @@ ion-icon { font-size: 28px; } + ion-label { text-transform: uppercase; font-size: var(--font-size-xs); font-weight: var(--font-weight-semi-bold); } } -} +}*/ diff --git a/src/app/modules/menu/tabs/tabs.component.ts b/src/app/modules/menu/navigation/tabs.component.ts similarity index 72% rename from src/app/modules/menu/tabs/tabs.component.ts rename to src/app/modules/menu/navigation/tabs.component.ts index 13278ab9..0b3f851a 100644 --- a/src/app/modules/menu/tabs/tabs.component.ts +++ b/src/app/modules/menu/navigation/tabs.component.ts @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2022 StApps + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + import {Component} from '@angular/core'; import { SCAppConfigurationMenuCategory, diff --git a/src/app/modules/menu/tabs/tabs.spec.ts b/src/app/modules/menu/navigation/tabs.spec.ts similarity index 99% rename from src/app/modules/menu/tabs/tabs.spec.ts rename to src/app/modules/menu/navigation/tabs.spec.ts index 7483e0e7..354e89bb 100644 --- a/src/app/modules/menu/tabs/tabs.spec.ts +++ b/src/app/modules/menu/navigation/tabs.spec.ts @@ -1,6 +1,5 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ /* - * Copyright (C) 2018, 2019 StApps + * Copyright (C) 2022 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. @@ -13,6 +12,8 @@ * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ + +/* eslint-disable @typescript-eslint/no-explicit-any */ import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; import {TestBed, waitForAsync} from '@angular/core/testing'; diff --git a/src/app/modules/menu/navigation/tabs.template.html b/src/app/modules/menu/navigation/tabs.template.html new file mode 100644 index 00000000..b3176106 --- /dev/null +++ b/src/app/modules/menu/navigation/tabs.template.html @@ -0,0 +1,37 @@ + + + + + + {{ 'tabs.home' | translate }} + + + + {{ 'tabs.canteens' | translate }} + + + + {{ 'tabs.schedule' | translate }} + + + + {{ 'tabs.map' | translate }} + + + + {{ 'tabs.profile' | translate }} + + diff --git a/src/app/modules/menu/tabs/tabs-routing.module.ts b/src/app/modules/menu/tabs/tabs-routing.module.ts deleted file mode 100644 index fe136b93..00000000 --- a/src/app/modules/menu/tabs/tabs-routing.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {NgModule} from '@angular/core'; -import {RouterModule, Routes} from '@angular/router'; - -const routes: Routes = [ - { - path: '', - redirectTo: '/dashboard', - pathMatch: 'full', - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class TabsRoutingModule {} diff --git a/src/app/modules/menu/tabs/tabs.module.ts b/src/app/modules/menu/tabs/tabs.module.ts deleted file mode 100644 index 078afd81..00000000 --- a/src/app/modules/menu/tabs/tabs.module.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2022 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -import {NgModule} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {RouterModule} from '@angular/router'; -import {IonicModule} from '@ionic/angular'; - -import {TabsComponent} from './tabs.component'; - -import {TranslateModule} from '@ngx-translate/core'; -import {IonIconModule} from '../../../util/ion-icon/ion-icon.module'; - -@NgModule({ - imports: [ - CommonModule, - IonicModule, - IonIconModule, - TranslateModule, - RouterModule, - ], - declarations: [TabsComponent], - exports: [TabsComponent], -}) -export class TabsModule {} diff --git a/src/app/modules/menu/tabs/tabs.template.html b/src/app/modules/menu/tabs/tabs.template.html deleted file mode 100644 index 949d2f00..00000000 --- a/src/app/modules/menu/tabs/tabs.template.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - {{ 'tabs.home' | translate }} - - - - {{ 'tabs.canteens' | translate }} - - - - {{ 'tabs.schedule' | translate }} - - - - {{ 'tabs.map' | translate }} - - - - {{ 'tabs.profile' | translate }} -