diff --git a/src/app/modules/dashboard/dashboard-collapse.ts b/src/app/modules/dashboard/dashboard-collapse.ts
new file mode 100644
index 00000000..c8ec4e3b
--- /dev/null
+++ b/src/app/modules/dashboard/dashboard-collapse.ts
@@ -0,0 +1,77 @@
+/*
+ * 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 {Animation, AnimationController} from '@ionic/angular';
+import {NgZone} from '@angular/core';
+
+export class DashboardCollapse {
+ collapseAnimation: Animation;
+
+ nextFrame: number;
+
+ constructor(
+ private animationControl: AnimationController,
+ private zone: NgZone,
+ scrollContainer: HTMLElement,
+ toolbar: HTMLElement,
+ schedule: HTMLElement,
+ ) {
+ this.zone
+ .runOutsideAngular(async () => {
+ this.collapseAnimation = this.animationControl
+ .create()
+ .duration(1000)
+ .addAnimation([
+ this.animationControl
+ .create()
+ .addElement(toolbar)
+ .fromTo('transform', 'translateY(0)', 'translateY(-32px)'),
+ this.animationControl
+ .create()
+ .addElement(toolbar.querySelector(':scope > ion-img')!)
+ .fromTo('transform', 'scale(1)', 'scale(0.35)'),
+ this.animationControl
+ .create()
+ .addElement(schedule)
+ .fromTo(
+ 'transform',
+ 'translateY(0) scaleY(1)',
+ 'translateY(-75px) scaleY(0.8)',
+ ),
+ this.animationControl
+ .create()
+ .addElement(schedule.querySelectorAll(':scope > a > *'))
+ .fromTo('transform', 'scaleY(1)', `scaleY(${1 / 0.8})`),
+ ]);
+ this.collapseAnimation.progressStart(true, 0);
+
+ const element = scrollContainer;
+ let pos = element.scrollTop;
+ const animate = () => {
+ if (pos !== element.scrollTop) {
+ pos = element.scrollTop;
+ this.collapseAnimation.progressStep(element.scrollTop / 172);
+ }
+ this.nextFrame = requestAnimationFrame(animate);
+ };
+ this.nextFrame = requestAnimationFrame(animate);
+ })
+ .then();
+ }
+
+ destroy() {
+ cancelAnimationFrame(this.nextFrame);
+ }
+}
diff --git a/src/app/modules/dashboard/dashboard.collapse.component.scss b/src/app/modules/dashboard/dashboard.collapse.component.scss
new file mode 100644
index 00000000..978d6268
--- /dev/null
+++ b/src/app/modules/dashboard/dashboard.collapse.component.scss
@@ -0,0 +1,47 @@
+/*!
+ * 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';
+
+@include ion-md-down {
+ ion-toolbar, .logo, .schedule, .schedule > a > * {
+ will-change: transform;
+ }
+
+ .logo {
+ transform-origin: center right;
+ }
+
+ .schedule {
+
+ > a {
+ > * {
+ transform-origin: center;
+ }
+
+ > ion-label:first-child {
+ transform-origin: bottom;
+ }
+
+ > ion-label:last-child {
+ transform-origin: top;
+ }
+
+ > ion-icon:first-child {
+ transform-origin: top;
+ }
+ }
+ }
+}
diff --git a/src/app/modules/dashboard/dashboard.component.html b/src/app/modules/dashboard/dashboard.component.html
index f77b9756..f70340d5 100644
--- a/src/app/modules/dashboard/dashboard.component.html
+++ b/src/app/modules/dashboard/dashboard.component.html
@@ -1,54 +1,57 @@
-
-
+
+ {{
+ 'dashboard.header.title' | daytimeKey | translate
+ }}
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/app/modules/dashboard/dashboard.component.scss b/src/app/modules/dashboard/dashboard.component.scss
index 19b2df8c..12f677ab 100644
--- a/src/app/modules/dashboard/dashboard.component.scss
+++ b/src/app/modules/dashboard/dashboard.component.scss
@@ -1,23 +1,28 @@
/*!
* 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 '../../../theme/util/mixins';
+:host ion-header {
+ z-index: 1;
+}
+
:host ion-toolbar:last-of-type {
--padding-top: var(--spacing-md);
- --padding-bottom: 0;
+ --padding-bottom: var(--spacing-md);
+ z-index: -1;
ion-icon {
margin-right: var(--spacing-sm);
@@ -38,65 +43,27 @@
aspect-ratio: 1/1;
object-position: right;
margin-left: auto;
- margin-right: var(--spacing-sm);
-
- @include phoneLandscape {
- width: auto;
- height: 50px;
- }
-
- @include phonePortraitSmall {
- width: auto;
- height: 50px;
- }
+ margin-right: 0;
}
}
ion-content {
--background: var(--ion-color-light);
- --overflow: hidden;
-
- .scrollable-container {
- overflow: hidden auto;
- height: 100%;
- padding-top: 122px;
-
- @media (max-width: 440px) {
- padding-top: 140px;
- }
-
- @include ion-md-up {
- padding-top: 0;
- padding-bottom: 122px;
- }
- }
-
- @include phoneLandscape {
- --overflow: hidden auto;
-
- .scrollable-container {
- overflow: initial;
- height: initial;
- padding-top: 0;
- padding-bottom: 0;
- }
- }
}
.schedule {
- position: fixed;
width: 100%;
z-index: 3;
background: var(--ion-color-primary);
display: flex;
justify-content: space-between;
gap: var(--spacing-md);
- padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-xl);
+ padding: var(--spacing-sm);
+ padding-top: 0;
@include ion-md-up {
position: unset;
width: unset;
- z-index: unset;
height: calc(var(--tablet-top-bar-height) + (2 * var(--spacing-xl)));
margin: 0;
padding: var(--spacing-xl);
@@ -113,22 +80,25 @@ ion-content {
}
a:first-child {
- border: 2px solid var(--ion-color-primary-tint);
text-align: center;
flex: 0 0 auto;
aspect-ratio: 1;
box-sizing: content-box;
max-height: 60px;
+ overflow: hidden;
+ border: 2px solid var(--ion-color-primary-tint);
@include phoneLandscape {
height: auto;
}
+ }
+
+ a:first-child {
+ justify-content: space-around;
+ align-items: center;
+ gap: var(--spacing-sm);
- ion-icon {
- margin: auto auto var(--spacing-xs);
- }
ion-label {
- margin: 0 auto auto;
font-size: var(--font-size-xxs);
font-weight: var(--font-weight-semi-bold);
}
@@ -142,6 +112,7 @@ ion-content {
flex: 1 1 65%;
background: var(--linear-gradient);
justify-content: center;
+ z-index: 1;
@include ion-md-up {
flex: 1 1 100%;
@@ -156,10 +127,12 @@ ion-content {
font-weight: var(--font-weight-bold);
line-height: 1.4;
}
+
ion-label:first-child {
text-transform: uppercase;
color: var(--ion-color-secondary);
}
+
ion-label:nth-child(2n) {
font-size: var(--font-size-lg);
font-weight: var(--font-weight-semi-bold);
@@ -173,6 +146,7 @@ ion-content {
&.section-extended {
padding-right: 0;
+
ion-icon[name='edit'] {
margin-right: var(--spacing-md);
}
@@ -232,6 +206,7 @@ ion-searchbar {
input {
padding: var(--spacing-lg);
}
+
ion-icon {
left: auto;
right: var(--spacing-lg);
diff --git a/src/app/modules/dashboard/dashboard.component.ts b/src/app/modules/dashboard/dashboard.component.ts
index 03ae27d7..8157993d 100644
--- a/src/app/modules/dashboard/dashboard.component.ts
+++ b/src/app/modules/dashboard/dashboard.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.
@@ -12,7 +12,14 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see .
*/
-import {Component, OnInit, OnDestroy} from '@angular/core';
+import {
+ Component,
+ ElementRef,
+ NgZone,
+ OnDestroy,
+ OnInit,
+ ViewChild,
+} from '@angular/core';
import {Router} from '@angular/router';
import {Location} from '@angular/common';
import {Subscription} from 'rxjs';
@@ -22,11 +29,18 @@ import {SplashScreen} from '@capacitor/splash-screen';
import {DataRoutingService} from '../data/data-routing.service';
import {ScheduleProvider} from '../calendar/schedule.provider';
+import {AnimationController, IonContent} from '@ionic/angular';
+import {DashboardCollapse} from './dashboard-collapse';
+
+// const scrollTimeline = new ScrollTimeline();
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
- styleUrls: ['./dashboard.component.scss'],
+ styleUrls: [
+ './dashboard.component.scss',
+ '/dashboard.collapse.component.scss',
+ ],
})
export class DashboardComponent implements OnInit, OnDestroy {
/**
@@ -34,6 +48,14 @@ export class DashboardComponent implements OnInit, OnDestroy {
*/
subscriptions: Subscription[] = [];
+ @ViewChild('toolbar', {read: ElementRef}) toolbarRef: ElementRef;
+
+ @ViewChild('schedule', {read: ElementRef}) scheduleRef: ElementRef;
+
+ @ViewChild('ionContent') ionContentRef: IonContent;
+
+ collapseAnimation: DashboardCollapse;
+
/**
* UUID subscription
*/
@@ -44,6 +66,11 @@ export class DashboardComponent implements OnInit, OnDestroy {
*/
private uuids: SCUuid[];
+ /**
+ * Enable header animation
+ */
+ isHeaderAnimated = true;
+
/**
* Next event in calendar
*/
@@ -66,6 +93,8 @@ export class DashboardComponent implements OnInit, OnDestroy {
private scheduleProvider: ScheduleProvider,
protected router: Router,
public location: Location,
+ private animationControl: AnimationController,
+ private zone: NgZone,
) {
this.subscriptions.push(
this.dataRoutingService.itemSelectListener().subscribe(item => {
@@ -82,6 +111,14 @@ export class DashboardComponent implements OnInit, OnDestroy {
},
);
await SplashScreen.hide();
+
+ this.collapseAnimation = new DashboardCollapse(
+ this.animationControl,
+ this.zone,
+ await this.ionContentRef.getScrollElement(),
+ this.toolbarRef.nativeElement,
+ this.scheduleRef.nativeElement,
+ );
}
async loadNextEvent() {
@@ -103,5 +140,6 @@ export class DashboardComponent implements OnInit, OnDestroy {
sub.unsubscribe();
}
this._uuidSubscription.unsubscribe();
+ this.collapseAnimation.destroy();
}
}
diff --git a/src/app/modules/dashboard/section/section.component.scss b/src/app/modules/dashboard/section/section.component.scss
index 0ccc6415..5ae00030 100644
--- a/src/app/modules/dashboard/section/section.component.scss
+++ b/src/app/modules/dashboard/section/section.component.scss
@@ -17,7 +17,7 @@
:host {
display: block;
- padding: var(--spacing-md) var(--spacing-md) var(--spacing-sm);
+ padding: var(--spacing-sm) var(--spacing-md) var(--spacing-sm);
@include ion-md-up {
padding: var(--spacing-lg) var(--spacing-xxl) var(--spacing-sm);
@@ -40,28 +40,13 @@
}
}
- // TODO
- &:first-of-type {
- padding-top: var(--spacing-lg);
- }
-
& > ion-label:first-child {
font-family: var(--headline-font-family);
- font-size: var(--font-size-lg);
font-weight: var(--font-weight-bold);
- font-stretch: condensed;
- text-transform: uppercase;
- margin-bottom: var(--spacing-xs);
-
- width: 100%;
- display: flex;
- flex-direction: revert;
- justify-content: space-between;
ion-icon {
color: var(--ion-color-medium-shade);
position: relative;
- bottom: var(--spacing-sm);
margin-block: auto;
cursor: pointer;
diff --git a/src/app/modules/dashboard/sections/news-section/news-section.component.ts b/src/app/modules/dashboard/sections/news-section/news-section.component.ts
index 6e9b3423..f46c4010 100644
--- a/src/app/modules/dashboard/sections/news-section/news-section.component.ts
+++ b/src/app/modules/dashboard/sections/news-section/news-section.component.ts
@@ -43,10 +43,10 @@ export class NewsSectionComponent extends NewsPageComponent implements OnInit {
enabled: true,
sticky: true,
},
- width: 240,
+ width: 300,
breakpoints: {
768: {
- width: 280,
+ width: 380,
},
},
};
diff --git a/src/app/modules/dashboard/sections/search-section/search-section.component.html b/src/app/modules/dashboard/sections/search-section/search-section.component.html
index 2f01484a..0cd4964c 100644
--- a/src/app/modules/dashboard/sections/search-section/search-section.component.html
+++ b/src/app/modules/dashboard/sections/search-section/search-section.component.html
@@ -26,7 +26,8 @@
[(ngModel)]="searchTerm"
>