diff --git a/client/stillbox/src/app/version/checker.service.spec.ts b/client/stillbox/src/app/version/checker.service.spec.ts
new file mode 100644
index 0000000..d240a50
--- /dev/null
+++ b/client/stillbox/src/app/version/checker.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { CheckerService } from './checker.service';
+
+describe('CheckerService', () => {
+ let service: CheckerService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(CheckerService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/client/stillbox/src/app/version/checker.service.ts b/client/stillbox/src/app/version/checker.service.ts
new file mode 100644
index 0000000..39176bb
--- /dev/null
+++ b/client/stillbox/src/app/version/checker.service.ts
@@ -0,0 +1,42 @@
+import { Injectable } from '@angular/core';
+import { SwUpdate } from '@angular/service-worker';
+import { Subscription } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class CheckerService {
+ updateAvailable = false;
+ versionSub!: Subscription;
+
+ doUpdate() {}
+
+ constructor(private swUpd: SwUpdate) {
+ this.checkUpdate();
+ }
+
+ checkUpdate() {
+ this.versionSub?.unsubscribe();
+ if (!this.swUpd.isEnabled) {
+ return;
+ }
+ this.versionSub = this.swUpd.versionUpdates.subscribe((evt) => {
+ switch (evt.type) {
+ case 'VERSION_DETECTED':
+ console.log('Detected new version ${evt.version.hash}');
+ break;
+ case 'VERSION_READY':
+ console.log(`Current app version: ${evt.currentVersion.hash}`);
+ console.log(
+ `New app version ready for use: ${evt.latestVersion.hash}`,
+ );
+ this.updateAvailable = true;
+ break;
+ case 'VERSION_INSTALLATION_FAILED':
+ console.log(
+ `Failed to install app version '${evt.version.hash}': ${evt.error}`,
+ );
+ }
+ });
+ }
+}
diff --git a/client/stillbox/src/app/version/update-nag/update-nag.component.html b/client/stillbox/src/app/version/update-nag/update-nag.component.html
new file mode 100644
index 0000000..d9a3ee9
--- /dev/null
+++ b/client/stillbox/src/app/version/update-nag/update-nag.component.html
@@ -0,0 +1,6 @@
+@if (checkerSvc.updateAvailable) {
+
+
New version available!
+
+
+}
diff --git a/client/stillbox/src/app/version/update-nag/update-nag.component.scss b/client/stillbox/src/app/version/update-nag/update-nag.component.scss
new file mode 100644
index 0000000..f43ba2c
--- /dev/null
+++ b/client/stillbox/src/app/version/update-nag/update-nag.component.scss
@@ -0,0 +1,32 @@
+@media screen and (max-width: 768px) {
+ .updater {
+ width: 100%;
+ }
+}
+
+@media not screen and (max-width: 768px) {
+ .updater {
+ width: 400px;
+ position: absolute;
+ bottom: 20px;
+ left: 20px;
+ height: 80px;
+ }
+}
+
+.updater {
+ display: flex;
+ align-items: center;
+ background-color: #311818;
+ padding-right: 20px;
+}
+
+.updater p {
+ flex: 2 0;
+ margin-left: 20px;
+}
+
+.updater button {
+ flex: 0 0 100px;
+ justify-content: flex-end;
+}
diff --git a/client/stillbox/src/app/version/update-nag/update-nag.component.spec.ts b/client/stillbox/src/app/version/update-nag/update-nag.component.spec.ts
new file mode 100644
index 0000000..4acd841
--- /dev/null
+++ b/client/stillbox/src/app/version/update-nag/update-nag.component.spec.ts
@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { UpdateNagComponent } from './update-nag.component';
+
+describe('UpdateNagComponent', () => {
+ let component: UpdateNagComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [UpdateNagComponent],
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(UpdateNagComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/client/stillbox/src/app/version/update-nag/update-nag.component.ts b/client/stillbox/src/app/version/update-nag/update-nag.component.ts
new file mode 100644
index 0000000..0a592d2
--- /dev/null
+++ b/client/stillbox/src/app/version/update-nag/update-nag.component.ts
@@ -0,0 +1,16 @@
+import { Component } from '@angular/core';
+import { CheckerService } from '../checker.service';
+
+@Component({
+ selector: 'app-update-nag',
+ imports: [],
+ templateUrl: './update-nag.component.html',
+ styleUrl: './update-nag.component.scss',
+})
+export class UpdateNagComponent {
+ constructor(public checkerSvc: CheckerService) {}
+
+ update() {
+ this.checkerSvc.doUpdate();
+ }
+}