diff --git a/backend/player/player.go b/backend/player/player.go
index 356902b..1be6729 100644
--- a/backend/player/player.go
+++ b/backend/player/player.go
@@ -174,9 +174,9 @@ func (p *Player) MuteToggle() error {
}
// return the current position as an int between 0 and 100 to work with progress bar easily.
-func (p *Player) CurrentPosition() (float64, error) {
- pos := 100.0 * float64(p.seeker.Position()) / float64(p.seeker.Len())
- return pos, nil
+func (p *Player) CurrentPosition() (int, error) {
+ pos := math.Round(100.0 * float64(p.seeker.Position()) / float64(p.seeker.Len()))
+ return int(pos), nil
}
// TODO: double check best type for percentage parameter
diff --git a/frontend/package.json b/frontend/package.json
index 617c590..0c3aa62 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -5,6 +5,8 @@
"preview": "vite preview"
},
"dependencies": {
+ "@lit-labs/signals": "^0.1.2",
+ "@shoelace-style/shoelace": "^2.20.1",
"lit": "^3.2.1"
},
"devDependencies": {
diff --git a/frontend/package.json.md5 b/frontend/package.json.md5
index ff4b82a..edbaca1 100755
--- a/frontend/package.json.md5
+++ b/frontend/package.json.md5
@@ -1 +1 @@
-ca82a2e81936c5ea9427701a4c3665d9
\ No newline at end of file
+fe84e1d3c95156e7d4a63999d84646b1
\ No newline at end of file
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index a50355a..ffa6d10 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -8,6 +8,12 @@ importers:
.:
dependencies:
+ '@lit-labs/signals':
+ specifier: ^0.1.2
+ version: 0.1.2
+ '@shoelace-style/shoelace':
+ specifier: ^2.20.1
+ version: 2.20.1(@floating-ui/utils@0.2.9)(@types/react@19.1.0)
lit:
specifier: ^3.2.1
version: 3.2.1
@@ -31,6 +37,10 @@ packages:
resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==}
engines: {node: '>=6.9.0'}
+ '@ctrl/tinycolor@4.1.0':
+ resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==}
+ engines: {node: '>=14'}
+
'@emmetio/extract-abbreviation@0.1.6':
resolution: {integrity: sha512-Ce3xE2JvTSEbASFbRbA1gAIcMcZWdS2yUYRaQbeM0nbOzaZrUYfa3ePtcriYRZOZmr+CkKA+zbjhvTpIOAYVcw==}
@@ -184,9 +194,26 @@ packages:
cpu: [x64]
os: [win32]
+ '@floating-ui/core@1.6.9':
+ resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==}
+
+ '@floating-ui/dom@1.6.13':
+ resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==}
+
+ '@floating-ui/utils@0.2.9':
+ resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
+
+ '@lit-labs/signals@0.1.2':
+ resolution: {integrity: sha512-hkOL0ua4ILeHlaJ8IqFKS+Y+dpYznWaDhdikzwt3zJ1/LPz3Etft4OPIMoltzbBJS5pyXPRseD/uWRlET3ImEA==}
+
'@lit-labs/ssr-dom-shim@1.3.0':
resolution: {integrity: sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==}
+ '@lit/react@1.0.7':
+ resolution: {integrity: sha512-cencnwwLXQKiKxjfFzSgZRngcWJzUDZi/04E0fSaF86wZgchMdvTyu+lE36DrUfvuus3bH8+xLPrhM1cTjwpzw==}
+ peerDependencies:
+ '@types/react': 17 || 18 || 19
+
'@lit/reactive-element@2.0.4':
resolution: {integrity: sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==}
@@ -302,9 +329,22 @@ packages:
cpu: [x64]
os: [win32]
+ '@shoelace-style/animations@1.2.0':
+ resolution: {integrity: sha512-avvo1xxkLbv2dgtabdewBbqcJfV0e0zCwFqkPMnHFGbJbBHorRFfMAHh1NG9ymmXn0jW95ibUVH03E1NYXD6Gw==}
+
+ '@shoelace-style/localize@3.2.1':
+ resolution: {integrity: sha512-r4C9C/5kSfMBIr0D9imvpRdCNXtUNgyYThc4YlS6K5Hchv1UyxNQ9mxwj+BTRH2i1Neits260sR3OjKMnplsFA==}
+
+ '@shoelace-style/shoelace@2.20.1':
+ resolution: {integrity: sha512-FSghU95jZPGbwr/mybVvk66qRZYpx5FkXL+vLNpy1Vp8UsdwSxXjIHE3fsvMbKWTKi9UFfewHTkc5e7jAqRYoQ==}
+ engines: {node: '>=14.17.0'}
+
'@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+ '@types/react@19.1.0':
+ resolution: {integrity: sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w==}
+
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
@@ -348,6 +388,14 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ composed-offset-position@0.0.6:
+ resolution: {integrity: sha512-Q7dLompI6lUwd7LWyIcP66r4WcS9u7AL2h8HaeipiRfCRPLMWqRx8fYsjb4OHi6UQFifO7XtNC2IlEJ1ozIFxw==}
+ peerDependencies:
+ '@floating-ui/utils': ^0.2.5
+
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
debug@4.4.0:
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
engines: {node: '>=6.0'}
@@ -477,6 +525,9 @@ packages:
resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
engines: {node: ^10 || ^12 || >=14}
+ qr-creator@1.0.0:
+ resolution: {integrity: sha512-C0cqfbS1P5hfqN4NhsYsUXePlk9BO+a45bAQ3xLYjBL3bOIFzoVEjs79Fado9u9BPBD3buHi3+vY+C8tHh4qMQ==}
+
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
@@ -499,6 +550,9 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ signal-polyfill@0.2.2:
+ resolution: {integrity: sha512-p63Y4Er5/eMQ9RHg0M0Y64NlsQKpiu6MDdhBXpyywRuWiPywhJTpKJ1iB5K2hJEbFZ0BnDS7ZkJ+0AfTuL37Rg==}
+
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@@ -658,6 +712,8 @@ snapshots:
dependencies:
regenerator-runtime: 0.14.1
+ '@ctrl/tinycolor@4.1.0': {}
+
'@emmetio/extract-abbreviation@0.1.6': {}
'@esbuild/aix-ppc64@0.25.1':
@@ -735,8 +791,28 @@ snapshots:
'@esbuild/win32-x64@0.25.1':
optional: true
+ '@floating-ui/core@1.6.9':
+ dependencies:
+ '@floating-ui/utils': 0.2.9
+
+ '@floating-ui/dom@1.6.13':
+ dependencies:
+ '@floating-ui/core': 1.6.9
+ '@floating-ui/utils': 0.2.9
+
+ '@floating-ui/utils@0.2.9': {}
+
+ '@lit-labs/signals@0.1.2':
+ dependencies:
+ lit: 3.2.1
+ signal-polyfill: 0.2.2
+
'@lit-labs/ssr-dom-shim@1.3.0': {}
+ '@lit/react@1.0.7(@types/react@19.1.0)':
+ dependencies:
+ '@types/react': 19.1.0
+
'@lit/reactive-element@2.0.4':
dependencies:
'@lit-labs/ssr-dom-shim': 1.3.0
@@ -813,8 +889,30 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.37.0':
optional: true
+ '@shoelace-style/animations@1.2.0': {}
+
+ '@shoelace-style/localize@3.2.1': {}
+
+ '@shoelace-style/shoelace@2.20.1(@floating-ui/utils@0.2.9)(@types/react@19.1.0)':
+ dependencies:
+ '@ctrl/tinycolor': 4.1.0
+ '@floating-ui/dom': 1.6.13
+ '@lit/react': 1.0.7(@types/react@19.1.0)
+ '@shoelace-style/animations': 1.2.0
+ '@shoelace-style/localize': 3.2.1
+ composed-offset-position: 0.0.6(@floating-ui/utils@0.2.9)
+ lit: 3.2.1
+ qr-creator: 1.0.0
+ transitivePeerDependencies:
+ - '@floating-ui/utils'
+ - '@types/react'
+
'@types/estree@1.0.6': {}
+ '@types/react@19.1.0':
+ dependencies:
+ csstype: 3.1.3
+
'@types/trusted-types@2.0.7': {}
'@vscode/web-custom-data@0.4.13': {}
@@ -857,6 +955,12 @@ snapshots:
color-name@1.1.4: {}
+ composed-offset-position@0.0.6(@floating-ui/utils@0.2.9):
+ dependencies:
+ '@floating-ui/utils': 0.2.9
+
+ csstype@3.1.3: {}
+
debug@4.4.0:
dependencies:
ms: 2.1.3
@@ -997,6 +1101,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ qr-creator@1.0.0: {}
+
queue-microtask@1.2.3: {}
regenerator-runtime@0.14.1: {}
@@ -1035,6 +1141,8 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
+ signal-polyfill@0.2.2: {}
+
source-map-js@1.2.1: {}
string-width@4.2.3:
diff --git a/frontend/src/components/audio-player/seekbar/seek-bar.ts b/frontend/src/components/audio-player/seekbar/seek-bar.ts
index 53b9112..1db3a7b 100644
--- a/frontend/src/components/audio-player/seekbar/seek-bar.ts
+++ b/frontend/src/components/audio-player/seekbar/seek-bar.ts
@@ -1,14 +1,74 @@
-import { LitElement, html } from 'lit';
-import { customElement } from 'lit/decorators.js';
+import { LitElement, html, css, type PropertyValues } from 'lit';
+import { customElement, property} from 'lit/decorators.js';
+import {SignalWatcher, watch, signal} from '@lit-labs/signals';
+import { ref, createRef } from 'lit/directives/ref.js';
+import { SlRange } from '@node_modules/@shoelace-style/shoelace/dist/shoelace';
-const seekBar = () => html`
-
-`;
+const progress = signal(20);
@customElement('seek-bar')
-export class SeekBar extends LitElement {
+export class SeekBar extends SignalWatcher(LitElement) {
+ @property()
+ trackLengthSeconds: number = 100;
+ @property()
+ isPlaying: boolean = true;
+
+ timerID: number = -1;
+ private rangeRef = createRef();
+
+ constructor(){
+ super();
+ this.startProgress();
+ }
+ static override styles = css`
+ sl-range::part(base) {
+ --track-color-active: yellow;
+ --track-color-inactive: white;
+ --track-height: 6px;
+ --track-width: 50%
+ }
+ `;
override render() {
- return seekBar();
+ return html`
+
+ `;
+ }
+
+ init(trackLength: number){
+ this.trackLengthSeconds = trackLength;
+ }
+
+ getSeekBarUpdateIntervalMillis(){
+ return this.trackLengthSeconds * 10;
+ }
+
+ // update progress update interval timer thing
+ // protected override update(changedProperties: PropertyValues): void {
+ // if (changedProperties.has("trackLengthSeconds")){
+ // this.stopProgress();
+ // this.startProgress();
+ // }
+ // if(changedProperties.has("isPlaying")){
+ // if(this.isPlaying){
+ // this.startProgress();
+ // }
+ // else{
+ // this.stopProgress();
+ // }
+ // }
+ // }
+
+ stopProgress(){
+ clearInterval(this.timerID);
+ }
+
+ startProgress(){
+ this.timerID = setInterval(this.incrementProgressValue, this.getSeekBarUpdateIntervalMillis());
+ }
+
+ async incrementProgressValue(){
+ progress.set(progress.get() + 1);
}
}
+
diff --git a/frontend/wailsjs/go/player/Player.d.ts b/frontend/wailsjs/go/player/Player.d.ts
index 61e1358..5ef53d3 100755
--- a/frontend/wailsjs/go/player/Player.d.ts
+++ b/frontend/wailsjs/go/player/Player.d.ts
@@ -5,6 +5,8 @@ import {player} from '../models';
export function ChangeVolume(arg1:number):Promise;
+export function CurrentPosition():Promise;
+
export function Init(arg1:context.Context):Promise;
export function LoadFile(arg1:string):Promise;
@@ -17,4 +19,8 @@ export function Play():Promise;
export function Resume():Promise;
+export function Seek(arg1:number):Promise;
+
export function SetVolume(arg1:player.UserVolume):Promise;
+
+export function TrackLengthInSeconds():Promise;
diff --git a/frontend/wailsjs/go/player/Player.js b/frontend/wailsjs/go/player/Player.js
index ffc039f..30d250d 100755
--- a/frontend/wailsjs/go/player/Player.js
+++ b/frontend/wailsjs/go/player/Player.js
@@ -6,6 +6,10 @@ export function ChangeVolume(arg1) {
return window['go']['player']['Player']['ChangeVolume'](arg1);
}
+export function CurrentPosition() {
+ return window['go']['player']['Player']['CurrentPosition']();
+}
+
export function Init(arg1) {
return window['go']['player']['Player']['Init'](arg1);
}
@@ -30,6 +34,14 @@ export function Resume() {
return window['go']['player']['Player']['Resume']();
}
+export function Seek(arg1) {
+ return window['go']['player']['Player']['Seek'](arg1);
+}
+
export function SetVolume(arg1) {
return window['go']['player']['Player']['SetVolume'](arg1);
}
+
+export function TrackLengthInSeconds() {
+ return window['go']['player']['Player']['TrackLengthInSeconds']();
+}