Skip to content

Commit a1d6570

Browse files
committed
Add mobile menu component with responsive design and navigation links
1 parent 57f4f94 commit a1d6570

7 files changed

Lines changed: 290 additions & 2 deletions

File tree

src/app/app.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,10 @@ header {
269269
flex-shrink: 1;
270270
box-sizing: border-box;
271271
}
272+
273+
.app-mobilemenu {
274+
flex-basis: 96px;
275+
flex-grow: 0;
276+
flex-shrink: 1;
277+
box-sizing: border-box;
278+
}

src/app/app.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ <h3><span *ngIf="profile?.name">&#64;</span>{{ profile?.name }}</h3>
175175
</div>
176176
<mat-divider></mat-divider>
177177
<mat-nav-list>
178-
<a class="nav-link"[routerLink]="['/p', appState.getPublicKey()]" mat-menu-item (click)="toggleProfileMenu()" [routerLinkActiveOptions]="{ exact: true }" routerLinkActive="active">
178+
<a class="nav-link" [routerLink]="['/p', appState.getPublicKey()]" mat-menu-item (click)="toggleProfileMenu()" [routerLinkActiveOptions]="{ exact: true }" routerLinkActive="active">
179179
<mat-icon>person</mat-icon>
180180
<span>{{ 'App.ViewProfile' | translate }}</span>
181181
</a>
@@ -213,6 +213,10 @@ <h3><span *ngIf="profile?.name">&#64;</span>{{ profile?.name }}</h3>
213213
<router-outlet></router-outlet>
214214
</div>
215215
<app-media-player class="app-mediaplayer" *ngIf="options.values.showMediaPlayer"></app-media-player>
216+
217+
@if ((isHandset$ | async) === true) {
218+
<app-mobile-menu class="app-mobilemenu"></app-mobile-menu>
219+
}
216220
</div>
217221
</mat-sidenav-content>
218222
</mat-sidenav-container>

src/app/app.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import { MatSliderModule } from '@angular/material/slider';
6969
import { MediaPlayerComponent } from './shared/media-player/media-player';
7070
import { NgxLoadingButtonsModule } from 'ngx-loading-buttons';
7171
import { LoggerService } from './services/logger';
72+
import { MobileMenuComponent } from './shared/mobile-menu/mobile-menu';
7273

7374
@Component({
7475
selector: 'app-root',
@@ -118,7 +119,7 @@ import { LoggerService } from './services/logger';
118119
FormsModule,
119120
ReactiveFormsModule,
120121
NgxLoadingButtonsModule,
121-
122+
MobileMenuComponent
122123
],
123124
templateUrl: './app.html',
124125
styleUrls: ['./app.css'],
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
.media-player {
2+
display: flex;
3+
flex-direction: row;
4+
height: 96px;
5+
background-color: var(--mat-sidenav-container-background-color, var(--mat-sys-surface));
6+
}
7+
8+
.mobile-nav-button {
9+
padding: 4px;
10+
line-height: 1;
11+
font-size: 12px;
12+
}
13+
14+
.mobile-nav-button {
15+
flex: 1;
16+
min-width: 0;
17+
}
18+
19+
.mobile-nav-button-content {
20+
display: flex;
21+
flex-direction: column;
22+
align-items: center;
23+
}
24+
25+
.mobile-footer {
26+
justify-content: space-around;
27+
padding: 0;
28+
height: 56px;
29+
}
30+
31+
.media-player-small {
32+
height: env(titlebar-area-height, 33px) !important;
33+
}
34+
35+
/* .draggable {
36+
-webkit-app-region: drag;
37+
flex-grow: 2;
38+
flex-shrink: 1;
39+
} */
40+
41+
.media-controls-container {
42+
align-self: center;
43+
flex: 2 2 auto;
44+
-webkit-app-region: no-drag;
45+
}
46+
47+
.media-audio-container {
48+
align-self: center;
49+
flex: 2 2 auto;
50+
}
51+
52+
.media-player-small .media-controls-container {
53+
align-self: flex-start;
54+
}
55+
56+
.media-player-small .media-controls {
57+
flex-grow: 0;
58+
flex-shrink: 0;
59+
text-align: left;
60+
}
61+
62+
.media-info {
63+
/* flex: 0 1 auto; */
64+
flex: 1 1 calc(33%);
65+
display: flex;
66+
flex-direction: row;
67+
}
68+
69+
.media-controls {
70+
/* flex: 2 2 auto; */
71+
flex: 2 2 auto;
72+
width: 360px;
73+
74+
text-align: center;
75+
justify-content: center;
76+
display: flex;
77+
flex-direction: column;
78+
/* padding-top: 1.4em; */
79+
}
80+
81+
.media-player-small .media-controls {
82+
width: auto;
83+
}
84+
85+
.media-audio {
86+
/* padding-top: 1.4em; */
87+
padding-right: 1.4em;
88+
flex: 1 1 calc(33%);
89+
display: flex;
90+
text-align: right;
91+
}
92+
93+
.music-album {
94+
height: 100%;
95+
}
96+
97+
.music-title {
98+
font-size: 0.8em;
99+
overflow: hidden;
100+
text-overflow: ellipsis;
101+
display: -webkit-box;
102+
-webkit-line-clamp: 2; /* number of lines to show */
103+
line-clamp: 2;
104+
-webkit-box-orient: vertical;
105+
font-weight: 700;
106+
margin-bottom: 0.4em;
107+
}
108+
109+
.music-artist {
110+
color: rgba(255, 255, 255, 0.5);
111+
font-size: 0.65em;
112+
overflow: hidden;
113+
text-overflow: ellipsis;
114+
display: -webkit-box;
115+
-webkit-line-clamp: 1; /* number of lines to show */
116+
line-clamp: 1;
117+
-webkit-box-orient: vertical;
118+
}
119+
120+
.media-info-text {
121+
padding: 0.8em;
122+
align-self: center;
123+
}
124+
125+
.media-timeline {
126+
width: 100%;
127+
display: flex;
128+
flex-direction: row;
129+
font-size: 0.8em;
130+
131+
justify-content: center;
132+
}
133+
134+
.media-timeline-1 {
135+
flex: 1 1 auto;
136+
width: 100px;
137+
align-self: center;
138+
}
139+
140+
.media-timeline-2 {
141+
flex: 2 2 auto;
142+
align-self: center;
143+
}
144+
145+
.media-timeline-3 {
146+
flex: 1 1 auto;
147+
width: 100px;
148+
align-self: center;
149+
}
150+
151+
/* .media-slider {
152+
transform: scale(0.5);
153+
} */
154+
155+
/* @media only screen and (max-height: 200px) {
156+
.media-player {
157+
position: absolute;
158+
top: 0;
159+
left: 0;
160+
right: 0;
161+
height: 100%;
162+
width: 100%;
163+
z-index: 1000;
164+
}
165+
}
166+
167+
@media only screen and (max-width: 780px) {
168+
.hide-small {
169+
display: none !important;
170+
}
171+
} */
172+
173+
.youtube-video {
174+
width: 100%;
175+
display: inline-block;
176+
margin-top: 0.2em;
177+
aspect-ratio: 16 / 9;
178+
}
179+
180+
.media-player-large {
181+
height: 256px;
182+
}
183+
184+
.media-player-maximized {
185+
position: absolute;
186+
top: 0;
187+
bottom: 0;
188+
right: 0;
189+
z-index: 1000;
190+
height: 100%;
191+
}
192+
193+
.floating-maximize {
194+
position: absolute;
195+
right: 10px;
196+
top: 80px;
197+
z-index: 1001;
198+
}
199+
200+
.media-player-logo {
201+
margin-left: 6px;
202+
}
203+
204+
@media only screen and (min-height: 201px) {
205+
.media-player-logo {
206+
display: none;
207+
}
208+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<div class="mobile-menu media-player-small">
2+
3+
<mat-toolbar class="mobile-footer" color="primary">
4+
<button
5+
mat-button
6+
class="mobile-nav-button"
7+
[routerLink]="['/feed']">
8+
<div class="mobile-nav-button-content">
9+
<mat-icon>notes</mat-icon>
10+
<span>{{ 'App.Feed' | translate }}</span>
11+
</div>
12+
</button>
13+
<button
14+
mat-button
15+
class="mobile-nav-button"
16+
[routerLink]="['/people']">
17+
<div style="display: flex; flex-direction: column; align-items: center;">
18+
<mat-icon>people</mat-icon>
19+
<span>{{ 'App.People' | translate }}</span>
20+
</div>
21+
</button>
22+
<button
23+
mat-button
24+
class="mobile-nav-button"
25+
[routerLink]="['/notifications']">
26+
<div style="display: flex; flex-direction: column; align-items: center;">
27+
<mat-icon>notifications</mat-icon>
28+
<span>{{ 'App.Notifications' | translate }}</span>
29+
</div>
30+
</button>
31+
<button
32+
mat-button
33+
class="mobile-nav-button"
34+
[routerLink]="['/p', appState.getPublicKey()]">
35+
<div style="display: flex; flex-direction: column; align-items: center;">
36+
<mat-icon>person</mat-icon>
37+
<span>{{ 'App.Profile' | translate }}</span>
38+
</div>
39+
</button>
40+
</mat-toolbar>
41+
42+
</div>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Component, inject, Input } from '@angular/core';
2+
import { MatIconModule } from '@angular/material/icon';
3+
import { CommonModule } from '@angular/common';
4+
import { MatSliderModule } from '@angular/material/slider';
5+
import { FormsModule } from '@angular/forms';
6+
import { MatButtonModule } from '@angular/material/button';
7+
import { RouterModule } from '@angular/router';
8+
import { MatToolbarModule } from '@angular/material/toolbar';
9+
import { TranslateModule } from '@ngx-translate/core';
10+
import { ApplicationState } from 'src/app/services/applicationstate';
11+
12+
@Component({
13+
selector: 'app-mobile-menu',
14+
templateUrl: './mobile-menu.html',
15+
styleUrls: ['./mobile-menu.css'],
16+
imports: [MatToolbarModule, TranslateModule, RouterModule, MatButtonModule, MatIconModule, CommonModule, MatSliderModule, FormsModule],
17+
})
18+
export class MobileMenuComponent {
19+
@Input() miniplayer = false;
20+
21+
appState = inject(ApplicationState);
22+
23+
constructor() {}
24+
25+
}

src/assets/i18n/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"Followers": "Followers",
2222
"Following": "Following",
2323
"ViewProfile": "View profile",
24+
"Profile": "Profile",
2425
"EditProfile": "Edit profile",
2526
"Badges": "Badges",
2627
"Settings": "Settings",

0 commit comments

Comments
 (0)