use repeat.svg icon; clean up generate_manifests.py
Hunter
Thursday, March 26th, 2026 at 4:41 PM
8 import re
9 from pathlib import Path
10
-def get_configuration(localhost=False):
- """Prompt user for configuration values
-
- Args:
- localhost: If True, assumes root path and only asks for app name.
- This enables PWA installation on localhost (iOS 18+).
- """
11 +def get_configuration():
12 + """Prompt user for configuration values"""
13 print("=" * 60)
14 print("PWA Configuration")
15 print("=" * 60)
16 print()
17
18 # Get app name
- if localhost:
- app_name = input("Enter a name for your mixapp (or press Return/Enter for 'my mixapp'): ").strip()
- if not app_name:
- app_name = "my mixapp"
- print(f"Using default: {app_name}")
- else:
- app_name = input("Enter a name for your mixapp: ").strip()
- if not app_name:
- print("Error: App name is required")
- exit(1)
-
- # For localhost mode, use root path
- if localhost:
- base_path = "/"
- print()
- print("Localhost mode: Using root path for PWA installation")
19 + app_name = input("Enter a name for your mixapp: ").strip()
20 + if not app_name:
21 + print("Error: App name is required")
22 + exit(1)
23 +
24 + # Get base path with smart default
25 + default_path = app_name.lower().replace(" ", "_")
26 + print()
27 + print(f"Enter the deployment path (or press Return/Enter for default)")
28 + print(f"Default: /{default_path}/")
29 + base_path_input = input("Path: ").strip()
30 +
31 + if base_path_input:
32 + # User provided a path - ensure it has leading/trailing slashes
33 + base_path = base_path_input
34 + if not base_path.startswith("/"):
35 + base_path = "/" + base_path
36 + if not base_path.endswith("/"):
37 + base_path = base_path + "/"
38 else:
- # Get base path with smart default
- default_path = app_name.lower().replace(" ", "_")
- print()
- print(f"Enter the deployment path (or press Return/Enter for default)")
- print(f"Default: /{default_path}/")
- base_path_input = input("Path: ").strip()
-
- if base_path_input:
- # User provided a path - ensure it has leading/trailing slashes
- base_path = base_path_input
- if not base_path.startswith("/"):
- base_path = "/" + base_path
- if not base_path.endswith("/"):
- base_path = base_path + "/"
- else:
- # Use default
- base_path = f"/{default_path}/"
- print(f"Using default path: {base_path}")
39 + # Use default
40 + base_path = f"/{default_path}/"
41 + print(f"Using default path: {base_path}")
42
43 print()
44 print(f"Configuration:")
172 "resources/pause.png",
173 "resources/prev.png",
174 "resources/next.png",
175 + "resources/repeat.svg",
176 ]
177
178 # Conditionally include optional files if they exist
1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
3 +
4 +<svg
5 + width="65.407951mm"
6 + height="56.782715mm"
7 + viewBox="0 0 65.407951 56.782715"
8 + version="1.1"
9 + id="svg5"
10 + xml:space="preserve"
11 + xmlns="http://www.w3.org/2000/svg"
12 + xmlns:svg="http://www.w3.org/2000/svg"><defs
13 + id="defs2" /><g
14 + id="layer1"
15 + transform="translate(-468.51962,-125.48088)"><g
16 + id="g9251"><path
17 + id="path2689-9"
18 + style="fill:currentColor;fill-opacity:1;stroke-width:5.39981;stroke-linecap:round;stroke-linejoin:round"
19 + d="m 558.39505,447.02975 a 2.7001749,2.7001749 0 0 0 -0.9715,0.25878 2.7001749,2.7001749 0 0 0 -1.53172,2.43391 v 19.6921 h -68.73634 c -48.82418,-10e-6 -78.6236,51.9014 -57.88312,93.24693 l 2.36317,4.71165 25.58799,-20.65363 c -9.52258,-21.20085 3.26483,-45.131 29.93196,-45.13099 h 68.73634 v 19.69211 a 2.7001749,2.7001749 0 0 0 4.39509,2.1015 l 44.4911,-35.91071 a 2.7001749,2.7001749 0 0 0 -0.009,-4.20747 l -44.48888,-35.64969 a 2.7001749,2.7001749 0 0 0 -1.8852,-0.58449 z"
20 + transform="matrix(0.23245107,0,0,0.23163997,379.32931,30.229918)" /><path
21 + id="path2689-7-7"
22 + style="fill:currentColor;fill-opacity:1;stroke-width:5.39981;stroke-linecap:round;stroke-linejoin:round"
23 + d="m 558.39505,447.02975 a 2.7001749,2.7001749 0 0 0 -0.9715,0.25878 2.7001749,2.7001749 0 0 0 -1.53172,2.43391 v 19.6921 h -68.73634 c -48.82418,-10e-6 -78.6236,51.9014 -57.88312,93.24693 l 2.36317,4.71165 25.58799,-20.65363 c -9.52258,-21.20085 3.26483,-45.131 29.93196,-45.13099 h 68.73634 v 19.69211 a 2.7001749,2.7001749 0 0 0 4.39509,2.1015 l 44.4911,-35.91071 a 2.7001749,2.7001749 0 0 0 -0.009,-4.20747 l -44.48888,-35.64969 a 2.7001749,2.7001749 0 0 0 -1.8852,-0.58449 z"
24 + transform="matrix(-0.23245107,0,0,-0.23163997,623.1179,277.51456)" /></g></g></svg>
226 contentDiv.appendChild(artistDiv);
227
228 const loopIcon = document.createElement('span');
- loopIcon.textContent = '🔁';
- loopIcon.style.display = (song.looping || false) ? 'inline' : 'none';
229 + loopIcon.style.width = '1.18em';
230 + loopIcon.style.height = '1.18em';
231 + loopIcon.style.display = (song.looping || false) ? 'inline-block' : 'none';
232 + loopIcon.style.color = 'var(--text)';
233 + fetch('resources/repeat.svg')
234 + .then(r => r.text())
235 + .then(svgText => {
236 + loopIcon.innerHTML = svgText;
237 + const svg = loopIcon.querySelector('svg');
238 + if (svg) {
239 + svg.style.width = '1.18em';
240 + svg.style.height = '1.18em';
241 + }
242 + });
243
244 item.appendChild(contentDiv);
245 item.appendChild(loopIcon);