diff --git a/CHANGELOG.md b/CHANGELOG.md index b0847c2..68ad304 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## [0.2.2] - 2025-08-12 + +### Added +- Add missing android icon +- Add Android assets +- Add terms of service +- Add privacy policy + +### Fixed +- Fix navigation for iPad +- Adapt device detail navigation to prevent screen squeeze +- Fix navigation issues resulting in cropped of screens +- Hide modal when user leaves tab view +- Fix webview serving over https while snapcast websocket is not served over wss + +### Changed +- Make "stream" routing standalone +- Adapt client navigation +- Format changelog + +### Removed +- Remove deprecated getclient func +- Remove codeql.yml workflow + ## [0.2.1] - 2025-08-01 ### Added diff --git a/assets/icon_background.png b/assets/icon-background.png similarity index 100% rename from assets/icon_background.png rename to assets/icon-background.png diff --git a/assets/icon_foreground.png b/assets/icon-foreground.png similarity index 100% rename from assets/icon_foreground.png rename to assets/icon-foreground.png diff --git a/assets/icon-foreground_512.png b/assets/icon-foreground_512.png new file mode 100644 index 0000000..e508e2d Binary files /dev/null and b/assets/icon-foreground_512.png differ diff --git a/assets/icon_only.png b/assets/icon-only.png similarity index 100% rename from assets/icon_only.png rename to assets/icon-only.png diff --git a/assets/splash_dark.png b/assets/splash-dark.png similarity index 100% rename from assets/splash_dark.png rename to assets/splash-dark.png diff --git a/capacitor.config.ts b/capacitor.config.ts index 33f1083..1acf5b0 100644 --- a/capacitor.config.ts +++ b/capacitor.config.ts @@ -1,9 +1,23 @@ import type { CapacitorConfig } from '@capacitor/cli'; +import { KeyboardResize, KeyboardStyle } from '@capacitor/keyboard'; + const config: CapacitorConfig = { appId: 'ch.byrds.beatnik', appName: 'Beatnik', - webDir: 'www' + webDir: 'www', + // handle insecure websocket connections + server: { + androidScheme: 'http', + cleartext: true + }, + plugins: { + Keyboard: { + resize: KeyboardResize.Body, + style: KeyboardStyle.Dark, + resizeOnFullScreen: true, + }, + }, }; export default config; diff --git a/package-lock.json b/package-lock.json index 799dd79..3969dd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "beatnik", - "version": "0.2.1", + "version": "0.2.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "beatnik", - "version": "0.2.1", + "version": "0.2.2", "dependencies": { "@angular/animations": "^19.0.0", "@angular/common": "^19.0.0", diff --git a/package.json b/package.json index f831572..030d08a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "beatnik", - "version": "0.2.1", + "version": "0.2.2", "author": "byrds & bytes gmbh", "homepage": "https://beatnik.ch", "scripts": { diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index a4aa6b9..705ed98 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -6,35 +6,68 @@ const routes: Routes = [ path: '', loadChildren: () => import('./tabs/tabs.module').then(m => m.TabsPageModule) }, - // { - // path: 'streams', - // loadChildren: () => import('./pages/streams/streams.module').then( m => m.StreamsPageModule) - // }, - // { - // path: 'dashboard', - // loadChildren: () => import('./pages/dashboard/dashboard.module').then( m => m.DashboardPageModule) - // }, { path: 'server-status', - loadChildren: () => import('./pages/server-status/server-status.module').then( m => m.ServerStatusPageModule) + loadChildren: () => import('./pages/server-status/server-status.module').then(m => m.ServerStatusPageModule) }, - // { - // path: 'client-details', - // loadChildren: () => import('./pages/client-details/client-details.module').then( m => m.ClientDetailsPageModule) - // }, - // { - // path: 'settings', - // loadChildren: () => import('./pages/settings/settings.module').then( m => m.SettingsPageModule) - // }, - // { - // path: 'stream-details', - // loadChildren: () => import('./pages/streams/stream-details/stream-details.module').then( m => m.StreamDetailsPageModule) - // }, - // { - // path: 'menu', - // loadChildren: () => import('./pages/menu/menu.module').then( m => m.MenuPageModule) - // }, - + { + path: 'devices', + children: [ + { + path: '', + loadChildren: () => import('./pages/devices/devices.module').then(m => m.DevicesPageModule) + }, + { + path: ':id', + loadChildren: () => import('./pages/devices/device-details/device-details.module').then(m => m.DeviceDetailsPageModule) + } + ] + }, + { + path: 'clients', + children: [ + { + path: ':id', + loadChildren: () => import('./pages/clients/client-details/client-details.module').then(m => m.ClientDetailsPageModule) + } + ] + }, + { + path: 'streams', + children: [ + { + path: '', + loadChildren: () => import('./pages/streams/streams.module').then(m => m.StreamsPageModule) + }, + { + path: ':id', + loadChildren: () => import('./pages/streams/stream-details/stream-details.module').then(m => m.StreamDetailsPageModule) + } + ] + }, + { + path: 'menu', + children: [ + { + path: '', + loadChildren: () => import('./pages/menu/menu.module').then(m => m.MenuPageModule) + }, + + + + // { + // path: 'about', + // loadChildren: () => import('./pages/about/about.module').then(m => m.AboutPageModule) + // } + + ] + }, + { + path: 'settings', + loadChildren: () => import('./pages/settings/settings.module').then(m => m.SettingsPageModule) + }, + + ]; @NgModule({ imports: [ @@ -42,4 +75,4 @@ const routes: Routes = [ ], exports: [RouterModule] }) -export class AppRoutingModule {} +export class AppRoutingModule { } diff --git a/src/app/components/player-toolbar/player-toolbar.component.html b/src/app/components/player-toolbar/player-toolbar.component.html index c513a4e..32f7f95 100644 --- a/src/app/components/player-toolbar/player-toolbar.component.html +++ b/src/app/components/player-toolbar/player-toolbar.component.html @@ -1,3 +1,4 @@ + @@ -46,4 +47,5 @@

{{ stream.properties.metadata.title }}

-
\ No newline at end of file + +
\ No newline at end of file diff --git a/src/app/components/snapcast-group-preview/snapcast-group-preview.component.ts b/src/app/components/snapcast-group-preview/snapcast-group-preview.component.ts index d8c5ba1..96c2bc0 100644 --- a/src/app/components/snapcast-group-preview/snapcast-group-preview.component.ts +++ b/src/app/components/snapcast-group-preview/snapcast-group-preview.component.ts @@ -51,7 +51,7 @@ export class SnapcastGroupPreviewComponent implements OnInit, OnChanges { } // Navigate to the group details page using the group's ID // Assuming you have a route set up for group details like '/group-details/:id' - this.router.navigate(['tabs/dashboard/devices', this.group.id]); + this.router.navigate(['devices', this.group.id]); } checkClientOnlineState(client: any): string { diff --git a/src/app/pages/clients/client-details/client-details.page.html b/src/app/pages/clients/client-details/client-details.page.html index cb26a39..d96a9a3 100644 --- a/src/app/pages/clients/client-details/client-details.page.html +++ b/src/app/pages/clients/client-details/client-details.page.html @@ -1,5 +1,8 @@ + + + client-details diff --git a/src/app/pages/dashboard/dashboard.page.html b/src/app/pages/dashboard/dashboard.page.html index b076a12..a279ade 100644 --- a/src/app/pages/dashboard/dashboard.page.html +++ b/src/app/pages/dashboard/dashboard.page.html @@ -24,7 +24,7 @@
{{numberOfPlayingClients +"/"+ totalClients}} Client(s) playing
- +
{{lastServerResponseDeltaInSeconds < 240?'Online':'Offline'}}: {{lastServerResponseTime | diff --git a/src/app/pages/devices/devices.page.html b/src/app/pages/devices/devices.page.html index 5b4f2fe..64ab481 100644 --- a/src/app/pages/devices/devices.page.html +++ b/src/app/pages/devices/devices.page.html @@ -15,7 +15,7 @@ Device Groups - +

{{ group.name || group.id }}

Clients: {{ group.clients.length }}

@@ -27,7 +27,7 @@

{{ group.name || group.id }}

- +

{{ client.config.name || client.id }}

diff --git a/src/app/pages/menu/menu-routing.module.ts b/src/app/pages/menu/menu-routing.module.ts index ad46526..9a48245 100644 --- a/src/app/pages/menu/menu-routing.module.ts +++ b/src/app/pages/menu/menu-routing.module.ts @@ -7,14 +7,6 @@ const routes: Routes = [ { path: '', component: MenuPage - }, - { - path: 'settings', - loadChildren: () => import('../settings/settings.module').then(m => m.SettingsPageModule) - }, - { - path: 'server-status', - loadChildren: () => import('../server-status/server-status.module').then(m => m.ServerStatusPageModule) } ]; diff --git a/src/app/pages/menu/menu.page.html b/src/app/pages/menu/menu.page.html index 1d8398f..cb0ae27 100644 --- a/src/app/pages/menu/menu.page.html +++ b/src/app/pages/menu/menu.page.html @@ -13,7 +13,7 @@ - + Settings diff --git a/src/app/pages/server-status/server-status.page.html b/src/app/pages/server-status/server-status.page.html index 44fc149..90afb6c 100644 --- a/src/app/pages/server-status/server-status.page.html +++ b/src/app/pages/server-status/server-status.page.html @@ -1,5 +1,8 @@ + + + Snapcast Server Status diff --git a/src/app/pages/settings/settings.page.html b/src/app/pages/settings/settings.page.html index 71f134a..0c925f9 100644 --- a/src/app/pages/settings/settings.page.html +++ b/src/app/pages/settings/settings.page.html @@ -1,5 +1,8 @@ + + + Settings @@ -14,10 +17,12 @@ - + - + diff --git a/src/app/pages/streams/stream-details/stream-details.page.html b/src/app/pages/streams/stream-details/stream-details.page.html index f859335..5a1b9c8 100644 --- a/src/app/pages/streams/stream-details/stream-details.page.html +++ b/src/app/pages/streams/stream-details/stream-details.page.html @@ -1,5 +1,8 @@ + + + stream-details diff --git a/src/app/pages/streams/streams.page.html b/src/app/pages/streams/streams.page.html index d83f397..f52c921 100644 --- a/src/app/pages/streams/streams.page.html +++ b/src/app/pages/streams/streams.page.html @@ -12,14 +12,14 @@ - -
+ +
Inactive Streams -
+
diff --git a/src/app/tabs/tabs-routing.module.ts b/src/app/tabs/tabs-routing.module.ts index 61d4d84..b9f9add 100644 --- a/src/app/tabs/tabs-routing.module.ts +++ b/src/app/tabs/tabs-routing.module.ts @@ -15,10 +15,10 @@ const routes: Routes = [ path: '', loadChildren: () => import('../pages/streams/streams.module').then(m => m.StreamsPageModule) }, - { - path: ':id', - loadChildren: () => import('../pages/streams/stream-details/stream-details.module').then(m => m.StreamDetailsPageModule) - } + // { + // path: ':id', + // loadChildren: () => import('../pages/streams/stream-details/stream-details.module').then(m => m.StreamDetailsPageModule) + // } ] }, @@ -42,10 +42,10 @@ const routes: Routes = [ path: '', loadChildren: () => import('../pages/devices/devices.module').then(m => m.DevicesPageModule) }, - { - path: ':id', - loadChildren: () => import('../pages/devices/device-details/device-details.module').then(m => m.DeviceDetailsPageModule) - } + // { + // path: ':id', + // loadChildren: () => import('../pages/devices/device-details/device-details.module').then(m => m.DeviceDetailsPageModule) + // } ] }, { @@ -54,10 +54,10 @@ const routes: Routes = [ // { path: '', // loadChildren: () => import('../pages/clients/clients.module').then(m => m.ClientsPageModule) // }, - { - path: ':id', - loadChildren: () => import('../pages/clients/client-details/client-details.module').then(m => m.ClientDetailsPageModule) - } + // { + // path: ':id', + // loadChildren: () => import('../pages/clients/client-details/client-details.module').then(m => m.ClientDetailsPageModule) + // } ] }, { diff --git a/src/app/tabs/tabs.page.html b/src/app/tabs/tabs.page.html index e3a919b..8134411 100644 --- a/src/app/tabs/tabs.page.html +++ b/src/app/tabs/tabs.page.html @@ -1,23 +1,6 @@ -
- - - - - - - - - diff --git a/src/app/tabs/tabs.page.ts b/src/app/tabs/tabs.page.ts index 6e4efab..f2aa907 100644 --- a/src/app/tabs/tabs.page.ts +++ b/src/app/tabs/tabs.page.ts @@ -1,6 +1,7 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { GestureController } from '@ionic/angular'; +import { GestureController, ModalController } from '@ionic/angular'; import { SnapcastService } from '../services/snapcast.service'; +import { PlayerToolbarComponent } from '../components/player-toolbar/player-toolbar.component'; @Component({ selector: 'app-tabs', @@ -10,22 +11,48 @@ import { SnapcastService } from '../services/snapcast.service'; }) export class TabsPage implements OnInit, AfterViewInit { - isModalOpen = true; + isModalOpen:boolean = false; - - constructor(private snapcastService: SnapcastService) {} + + constructor( + private modalController: ModalController) { } ngOnInit(): void { - + + } + + ionViewWillEnter() { + this.createPlayerModal(); } - ionViewDidEnter() { - // this.snapcastService.connect(); + + ionViewWillLeave() { + console.log('ionViewWillLeave'); + this.isModalOpen = false; + this.modalController.dismiss(); + console.log('Modal closed'); } ngAfterViewInit() { } - + async createPlayerModal() { + const modal = await this.modalController.create({ + component: PlayerToolbarComponent, + cssClass: 'player-modal', + animated: true, + keyboardClose: true, + showBackdrop: false, + backdropDismiss: false, + initialBreakpoint: 0.25, + breakpoints: [0.05, 0.25, 0.5, 0.75], + backdropBreakpoint: 0.75, + + }); + await modal.present(); + this.isModalOpen = true; + } + + } diff --git a/src/assets/icons/icon-128.webp b/src/assets/icons/icon-128.webp new file mode 100644 index 0000000..ca56db9 Binary files /dev/null and b/src/assets/icons/icon-128.webp differ diff --git a/src/assets/icons/icon-192.webp b/src/assets/icons/icon-192.webp new file mode 100644 index 0000000..8cfa302 Binary files /dev/null and b/src/assets/icons/icon-192.webp differ diff --git a/src/assets/icons/icon-256.webp b/src/assets/icons/icon-256.webp new file mode 100644 index 0000000..be6834d Binary files /dev/null and b/src/assets/icons/icon-256.webp differ diff --git a/src/assets/icons/icon-48.webp b/src/assets/icons/icon-48.webp new file mode 100644 index 0000000..67f2b51 Binary files /dev/null and b/src/assets/icons/icon-48.webp differ diff --git a/src/assets/icons/icon-512.webp b/src/assets/icons/icon-512.webp new file mode 100644 index 0000000..9664901 Binary files /dev/null and b/src/assets/icons/icon-512.webp differ diff --git a/src/assets/icons/icon-72.webp b/src/assets/icons/icon-72.webp new file mode 100644 index 0000000..bae6caf Binary files /dev/null and b/src/assets/icons/icon-72.webp differ diff --git a/src/assets/icons/icon-96.webp b/src/assets/icons/icon-96.webp new file mode 100644 index 0000000..0ff38c9 Binary files /dev/null and b/src/assets/icons/icon-96.webp differ diff --git a/src/manifest.webmanifest b/src/manifest.webmanifest new file mode 100644 index 0000000..62eba34 --- /dev/null +++ b/src/manifest.webmanifest @@ -0,0 +1,46 @@ +{ + "icons": [ + { + "src": "assets/icons/icon-48.webp", + "type": "image/png", + "sizes": "48x48", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-72.webp", + "type": "image/png", + "sizes": "72x72", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-96.webp", + "type": "image/png", + "sizes": "96x96", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-128.webp", + "type": "image/png", + "sizes": "128x128", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-192.webp", + "type": "image/png", + "sizes": "192x192", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-256.webp", + "type": "image/png", + "sizes": "256x256", + "purpose": "any maskable" + }, + { + "src": "assets/icons/icon-512.webp", + "type": "image/png", + "sizes": "512x512", + "purpose": "any maskable" + } + ] +}