feat: tab navigation bar animations and state

This commit is contained in:
Rainer Killinger
2022-09-23 16:34:07 +02:00
parent b2cc1fd91f
commit 7ecba0b781
32 changed files with 615 additions and 182 deletions

View File

@@ -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();

View File

@@ -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 <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
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,

View File

@@ -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,
);
}

View File

@@ -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,
);
}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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;
};
}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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

View File

@@ -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 <https://www.gnu.org/licenses/>.
~ You should have received a copy of the GNU General Public License along with
~ this program. If not, see <https://www.gnu.org/licenses/>.
-->
<stapps-context contentId="data-list"></stapps-context>
@@ -50,6 +50,8 @@
}}</ion-button>
<ion-button
[routerLink]="['/hebis-search/' + (queryText || '')]"
[skipLocationChange]="true"
[routerAnimation]="routeAnimation"
fill="outline"
size="large"
>{{ 'hebisSearch.type' | translate }}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
import {SCThings} from '@openstapps/core';
export abstract class SearchProvider {
abstract fetchAndUpdateItems(append: boolean): Promise<void> | void;
abstract route(item: SCThings): Promise<void> | void;
}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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,
);
}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
import {Injectable} from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class HebisSearchProvider {}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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,
);
}

View File

@@ -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 <https://www.gnu.org/licenses/>.
-->
<ion-header>
<ion-toolbar color="primary" mode="ios">
<ion-buttons slot="start">
@@ -23,6 +38,7 @@
<ion-buttons class="ion-justify-content-between">
<ion-button
[routerLink]="['/search/' + (queryText || '')]"
[routerAnimation]="routeAnimation"
fill="outline"
size="large"
>{{ 'search.type' | translate }}

View File

@@ -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 <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
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],

View File

@@ -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 <https://www.gnu.org/licenses/>.
-->
<ion-split-pane contentId="main" when="md">
<ion-menu
menuId="main"
@@ -9,11 +24,7 @@
<ion-header>
<ion-toolbar color="primary" mode="ios">
<ion-buttons slot="start"></ion-buttons>
<ion-title
class="clickable"
[routerLink]="['/']"
[routerDirection]="'root'"
>
<ion-title class="clickable" rootLink="/">
<ion-img src="assets/imgs/header.svg" class="logo"></ion-img>
</ion-title>
</ion-toolbar>
@@ -25,17 +36,12 @@
{{ category.translations[language].name | titlecase }}
</ion-label>
</ion-list-header>
<ion-menu-toggle auto-hide="false" *ngFor="let item of category.items">
<ion-item
[routerDirection]="'root'"
[routerLink]="['/' + item.route]"
>
<ion-icon slot="end" [name]="item.icon"></ion-icon>
<ion-label>
{{ item.translations[language].title | titlecase }}
</ion-label>
</ion-item>
</ion-menu-toggle>
<ion-item *ngFor="let item of category.items" [rootLink]="item.route">
<ion-icon slot="end" [name]="item.icon"></ion-icon>
<ion-label>
{{ item.translations[language].title | titlecase }}
</ion-label>
</ion-item>
</ion-list>
</ion-content>
</ion-menu>

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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 {}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
@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;
}
}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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();
}
}
}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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 {}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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;
};
}

View File

@@ -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 <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
: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);
}
}
}
}*/

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
import {Component} from '@angular/core';
import {
SCAppConfigurationMenuCategory,

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
/* eslint-disable @typescript-eslint/no-explicit-any */
import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
import {TestBed, waitForAsync} from '@angular/core/testing';

View File

@@ -0,0 +1,37 @@
<!--
~ 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 <https://www.gnu.org/licenses/>.
-->
<ion-tab-bar slot="bottom">
<ion-tab-button rootLink="/dashboard" redirectedFrom="/" tab="dashboard">
<ion-icon name="home"></ion-icon>
<ion-label>{{ 'tabs.home' | translate }}</ion-label>
</ion-tab-button>
<ion-tab-button rootLink="/canteen">
<ion-icon name="local_cafe"></ion-icon>
<ion-label>{{ 'tabs.canteens' | translate }}</ion-label>
</ion-tab-button>
<ion-tab-button rootLink="/schedule">
<ion-icon name="school"></ion-icon>
<ion-label>{{ 'tabs.schedule' | translate }}</ion-label>
</ion-tab-button>
<ion-tab-button rootLink="/map">
<ion-icon name="map"></ion-icon>
<ion-label>{{ 'tabs.map' | translate }}</ion-label>
</ion-tab-button>
<ion-tab-button rootLink="/profile">
<ion-icon name="account_circle"></ion-icon>
<ion-label>{{ 'tabs.profile' | translate }}</ion-label>
</ion-tab-button>
</ion-tab-bar>

View File

@@ -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 {}

View File

@@ -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 <https://www.gnu.org/licenses/>.
*/
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 {}

View File

@@ -1,51 +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 <https://www.gnu.org/licenses/>.
-->
<a
[routerDirection]="'root'"
[routerLink]="['/dashboard']"
routerLinkActive="active"
>
<ion-icon [name]="'home'"></ion-icon>
<ion-label>{{ 'tabs.home' | translate }}</ion-label>
</a>
<a
[routerDirection]="'root'"
[routerLink]="['/canteen']"
routerLinkActive="active"
>
<ion-icon [name]="'local_cafe'"></ion-icon>
<ion-label>{{ 'tabs.canteens' | translate }}</ion-label>
</a>
<a
[routerDirection]="'root'"
[routerLink]="['/schedule']"
routerLinkActive="active"
>
<ion-icon [name]="'school'"></ion-icon>
<ion-label>{{ 'tabs.schedule' | translate }}</ion-label>
</a>
<a [routerDirection]="'root'" [routerLink]="['/map']" routerLinkActive="active">
<ion-icon [name]="'map'"></ion-icon>
<ion-label>{{ 'tabs.map' | translate }}</ion-label>
</a>
<a
[routerDirection]="'root'"
[routerLink]="['/profile']"
routerLinkActive="active"
>
<ion-icon [name]="'account_circle'"></ion-icon>
<ion-label>{{ 'tabs.profile' | translate }}</ion-label>
</a>