Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const routes: Routes = [
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)
// },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { ClientDetailsPage } from './client-details.page';

const routes: Routes = [
{
path: '',
component: ClientDetailsPage
}
];

@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class ClientDetailsPageRoutingModule {}
20 changes: 20 additions & 0 deletions src/app/pages/clients/client-details/client-details.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { IonicModule } from '@ionic/angular';

import { ClientDetailsPageRoutingModule } from './client-details-routing.module';

import { ClientDetailsPage } from './client-details.page';

@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
ClientDetailsPageRoutingModule
],
declarations: [ClientDetailsPage]
})
export class ClientDetailsPageModule {}
54 changes: 54 additions & 0 deletions src/app/pages/clients/client-details/client-details.page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title>client-details</ion-title>
</ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">client-details</ion-title>
</ion-toolbar>
</ion-header>

<ion-list *ngIf="serverState | async as state">
<ion-item>
<ion-label>
<h2>Client ID: {{ id }}</h2>
</ion-label>
</ion-item>
<ion-item >
<ion-input type="text" placeholder="Enter client name" [(ngModel)]="client.config.name" (ngModelChange)="setClientName()"></ion-input>
</ion-item>

<ng-container *ngIf="state.server.groups">
<ng-container *ngFor="let group of state.server.groups">
<ng-container *ngFor="let client of group.clients">
<ion-item *ngIf="client.id === id">
<ion-label>
<h2>{{ client.id }}</h2>
<p>Group: {{ group.name || group.id }}</p>
<p>Volume: {{ client.config.volume.percent || 'N/A' }}%</p>
<p>Last Seen: {{ client.lastSeen.sec * 1000 | date }}</p>
<p>Connected: {{ client.connected }}</p>
</ion-label>
</ion-item>
</ng-container>
</ng-container>
</ng-container>
</ion-list>

<ion-accordion-group *ngIf="client">
<ion-accordion value="{{ client.id }}">
<ion-item slot="header">
<ion-label>
<h2>{{ client.id }}</h2>
<p>{{ client.connected}}</p>
</ion-label>
</ion-item>
<ion-item slot="content" lines="none" color="dark">
<pre>{{ client| json }}</pre>
</ion-item>
</ion-accordion>
</ion-accordion-group>
</ion-content>
Empty file.
17 changes: 17 additions & 0 deletions src/app/pages/clients/client-details/client-details.page.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ClientDetailsPage } from './client-details.page';

describe('ClientDetailsPage', () => {
let component: ClientDetailsPage;
let fixture: ComponentFixture<ClientDetailsPage>;

beforeEach(() => {
fixture = TestBed.createComponent(ClientDetailsPage);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
70 changes: 70 additions & 0 deletions src/app/pages/clients/client-details/client-details.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { Client, SnapCastServerStatusResponse } from 'src/app/model/snapcast.model';
import { SnapcastService } from 'src/app/services/snapcast.service';

@Component({
selector: 'app-client-details',
templateUrl: './client-details.page.html',
styleUrls: ['./client-details.page.scss'],
standalone: false
})
export class ClientDetailsPage implements OnInit {


id?: string;

serverState?: Observable<SnapCastServerStatusResponse>;
client?: Client;


constructor(
private avtivateRoute: ActivatedRoute,
private snapcastService: SnapcastService
) { }

async ngOnInit() {
this.serverState = this.snapcastService.state$;
this.id = this.avtivateRoute.snapshot.paramMap.get('id') || undefined;
if (!this.id) {
console.error('ClientDetailsPage: No ID found in route parameters');
return;
}
console.log('ClientDetailsPage: ID from route parameters:', this.id);
this.subscribeToClient();
}

subscribeToClient() {
if (!this.id) {
console.error('ClientDetailsPage: No ID available to subscribe to client');
return;
}
this.serverState.subscribe((state) => {
this.client = state.server.groups.flatMap(group => group.clients).find(client => client.id === this.id);
if (!this.client) {
console.error(`ClientDetailsPage: Client with ID ${this.id} not found in server state`);
} else {
console.log('ClientDetailsPage: Found client:', this.client);
}
});
}

setClientName() {
if (!this.client || !this.client.id) {
console.error('ClientDetailsPage: No client or client ID available to set name');
return;
}
this.snapcastService.setClientName(this.client.id, this.client.config.name).subscribe({
next: () => {
console.log(`ClientDetailsPage: Successfully set name for client ${this.client.id} to ${name}`);
},
error: (err) => {
console.error(`ClientDetailsPage: Failed to set name for client ${this.client.id}`, err);
}
});
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<ion-select slot="end" interface="action-sheet" [(ngModel)]="group.clients" multiple="true"
placeholder="Select Clients">
<ion-select-option *ngFor="let client of group.clients" [value]="client">
{{ client.id }}
{{ client.config.name || client.id }}
</ion-select-option>
</ion-select>
</ion-item>
Expand Down
12 changes: 6 additions & 6 deletions src/app/pages/devices/devices.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ <h2>{{ group.name || group.id }}</h2>
<ion-list-header>
<ion-label>Clients</ion-label>
</ion-list-header>
<ng-container *ngFor="let group of state.server.groups">
<ng-container *ngFor="let group of state.server.groups">
<ng-container *ngFor="let client of group.clients">
<ion-item [routerLink]="['/tabs/devices', client.id]">
<ion-item [routerLink]="['/tabs/clients', client.id]">
<ion-label>
<h2>{{ client.id }}</h2>
<h2> {{ client.config.name || client.id }}
</h2>
<p>Group: {{ group.name || group.id }}</p>
<p>Volume: {{ client.config.volume.percent || 'N/A' }}%</p>
<p>Last Seen: {{ client.lastSeen.sec *1000 | date }}</p>
<p>Connected: {{ client.connected }}</p>

</ion-label>
</ion-item>
</ng-container>

</ng-container>
</ng-container>

</ion-list>
</div>
<ng-template #noState>
Expand Down
12 changes: 11 additions & 1 deletion src/app/services/snapcast.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,16 @@ export class SnapcastService implements OnDestroy {

}

setClientName(clientId: string, name: string): Observable<void> {
return this.rpc('Client.SetName', { id: clientId, name }).pipe(
map((): void => void 0),
catchError(err => {
console.error(`SnapcastService: Failed to set name for client ${clientId}`, err);
return throwError(() => err);
})
);
}

// TODO ... Implement other action methods like.
// They just need to call `this.rpc` with the correct parameters.

Expand All @@ -376,7 +386,7 @@ export class SnapcastService implements OnDestroy {
return this.state$.pipe(map(state => state?.server?.groups.flatMap(g => g.clients).find(c => c.id === clientId)));
}

// TODO: ... other get... methods ...
// TODO: ... other get methods ...



Expand Down
12 changes: 12 additions & 0 deletions src/app/tabs/tabs-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ const routes: Routes = [
}
]
},
{
path: 'clients',
children: [
// { 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: 'menu',
loadChildren: () => import('../pages/menu/menu.module').then(m => m.MenuPageModule)
Expand Down