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"
+ }
+ ]
+}