Skip to content

Commit

Permalink
Icons for years
Browse files Browse the repository at this point in the history
  • Loading branch information
simojenki committed Feb 7, 2025
1 parent d8d532e commit 71717e6
Show file tree
Hide file tree
Showing 11 changed files with 238 additions and 64 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"clean": "rm -Rf build node_modules",
"build": "tsc",
"dev": "BNB_SUBSONIC_CUSTOM_CLIENTS1=audio/flac,audio/mpeg,audio/mp4\\>audio/flac BNB_LOG_LEVEL=debug BNB_DEBUG=true BNB_SCROBBLE_TRACKS=false BNB_REPORT_NOW_PLAYING=false BNB_SONOS_SEED_HOST=$BNB_DEV_SONOS_DEVICE_IP BNB_SONOS_SERVICE_NAME=z_bonobDev BNB_URL=\"http://${BNB_DEV_HOST_IP}:4534\" BNB_SUBSONIC_URL=\"${BNB_DEV_SUBSONIC_URL}\" nodemon -V ./src/app.ts",
"devr": "BNB_LOG_LEVEL=debug BNB_DEBUG=true BNB_SCROBBLE_TRACKS=false BNB_REPORT_NOW_PLAYING=false BNB_SONOS_SEED_HOST=$BNB_DEV_SONOS_DEVICE_IP BNB_SONOS_SERVICE_NAME=z_bonobDev BNB_SONOS_DEVICE_DISCOVERY=true BNB_SONOS_AUTO_REGISTER=true BNB_URL=\"http://${BNB_DEV_HOST_IP}:4534\" BNB_SUBSONIC_URL=\"${BNB_DEV_SUBSONIC_URL}\" nodemon -V ./src/app.ts",
"devr": "BNB_LOG_LEVEL=debug BNB_DEBUG=true BNB_ICON_FOREGROUND_COLOR=deeppink BNB_ICON_BACKGROUND_COLOR=darkslategray BNB_SCROBBLE_TRACKS=false BNB_REPORT_NOW_PLAYING=false BNB_SONOS_SEED_HOST=$BNB_DEV_SONOS_DEVICE_IP BNB_SONOS_SERVICE_NAME=z_bonobDev BNB_SONOS_DEVICE_DISCOVERY=true BNB_SONOS_AUTO_REGISTER=true BNB_URL=\"http://${BNB_DEV_HOST_IP}:4534\" BNB_SUBSONIC_URL=\"${BNB_DEV_SUBSONIC_URL}\" nodemon -V ./src/app.ts",
"register-dev": "ts-node ./src/register.ts http://${BNB_DEV_HOST_IP}:4534",
"test": "jest",
"testw": "jest --watch",
Expand Down
49 changes: 31 additions & 18 deletions src/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,16 @@ export type IconFeatures = {
viewPortIncreasePercent: number | undefined;
backgroundColor: string | undefined;
foregroundColor: string | undefined;
text: string | undefined;
};

export const NO_FEATURES: IconFeatures = {
viewPortIncreasePercent: undefined,
backgroundColor: undefined,
foregroundColor: undefined,
text: undefined
}

export type IconSpec = {
svg: string | undefined;
features: Partial<IconFeatures> | undefined;
Expand Down Expand Up @@ -93,17 +101,11 @@ export class SvgIcon implements Icon {

constructor(
svg: string,
features: Partial<IconFeatures> = {
viewPortIncreasePercent: undefined,
backgroundColor: undefined,
foregroundColor: undefined,
}
features: Partial<IconFeatures> = {}
) {
this.svg = svg;
this.features = {
viewPortIncreasePercent: undefined,
backgroundColor: undefined,
foregroundColor: undefined,
...NO_FEATURES,
...features,
};
}
Expand Down Expand Up @@ -131,6 +133,17 @@ export class SvgIcon implements Icon {
viewBox = viewBox.increasePercent(this.features.viewPortIncreasePercent);
element("//svg:svg").setAttribute("viewBox", viewBox.toString());
}
if(this.features.text) {
elements("//svg:text").forEach((text) => {
text.textContent = this.features.text!
});
}
if (this.features.foregroundColor) {
elements("//svg:path|//svg:text").forEach((path) => {
if (path.getAttribute("fill")) path.setAttribute("stroke", this.features.foregroundColor!);
else path.setAttribute("fill", this.features.foregroundColor!);
});
}
if (this.features.backgroundColor) {
const rect = doc.createElementNS(SVG_NS, "rect");
rect.setAttribute("x", `${viewBox.minX}`);
Expand All @@ -142,12 +155,6 @@ export class SvgIcon implements Icon {
const svg = element("//svg:svg")
svg.insertBefore(rect, svg.childNodes[0]!);
}
if (this.features.foregroundColor) {
elements("//svg:path").forEach((path) => {
if (path.getAttribute("fill")) path.setAttribute("stroke", this.features.foregroundColor!);
else path.setAttribute("fill", this.features.foregroundColor!);
});
}

return xmlTidy(doc as unknown as Node);
};
Expand Down Expand Up @@ -230,20 +237,24 @@ export type ICON =
| "yoda"
| "heart"
| "star"
| "solidStar";
| "solidStar"
| "yy"
| "yyyy";

const iconFrom = (name: string) =>
const svgFrom = (name: string) =>
new SvgIcon(
fs
.readFileSync(path.resolve(__dirname, "..", "web", "icons", name))
.toString()
);

const iconFrom = (name: string) => svgFrom(name).with({ features: { viewPortIncreasePercent: 80 } });

export const ICONS: Record<ICON, SvgIcon> = {
artists: iconFrom("navidrome-artists.svg"),
albums: iconFrom("navidrome-all.svg"),
radio: iconFrom("navidrome-radio.svg"),
blank: iconFrom("blank.svg"),
blank: svgFrom("blank.svg"),
playlists: iconFrom("navidrome-playlists.svg"),
genres: iconFrom("Theatre-Mask-111172.svg"),
random: iconFrom("navidrome-random.svg"),
Expand Down Expand Up @@ -308,7 +319,9 @@ export const ICONS: Record<ICON, SvgIcon> = {
yoda: iconFrom("Yoda-68107.svg"),
heart: iconFrom("Heart-85038.svg"),
star: iconFrom("Star-16101.svg"),
solidStar: iconFrom("Star-43879.svg")
solidStar: iconFrom("Star-43879.svg"),
yy: svgFrom("yy.svg"),
yyyy: svgFrom("yyyy.svg"),
};

export const STAR_WARS = [ICONS.c3po, ICONS.chewy, ICONS.darth, ICONS.skywalker, ICONS.leia, ICONS.r2d2, ICONS.yoda];
Expand Down
16 changes: 9 additions & 7 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,16 +498,18 @@ function server(
}
});

app.get("/icon/:type/size/:size", (req, res) => {
const type = req.params["type"]!;
app.get("/icon/:type_text/size/:size", (req, res) => {
const match = (req.params["type_text"] || "")!.match("^([A-Za-z0-9]+)(?:\:([A-Za-z0-9]+))?$")
if (!match)
return res.status(400).send();

const type = match[1]!
const text = match[2]
const size = req.params["size"]!;

if (!Object.keys(ICONS).includes(type)) {
return res.status(404).send();
} else if (
size != "legacy" &&
!SONOS_RECOMMENDED_IMAGE_SIZES.includes(size)
) {
} else if (size != "legacy" && !SONOS_RECOMMENDED_IMAGE_SIZES.includes(size)) {
return res.status(400).send();
} else {
let icon = (ICONS as any)[type]! as Icon;
Expand All @@ -528,8 +530,8 @@ function server(
icon
.apply(
features({
viewPortIncreasePercent: 80,
...serverOpts.iconColors,
text: text
})
)
.apply(festivals(clock))
Expand Down
11 changes: 6 additions & 5 deletions src/smapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,11 +251,12 @@ const genre = (bonobUrl: URLBuilder, genre: Genre) => ({
albumArtURI: iconArtURI(bonobUrl, iconForGenre(genre.name)).href(),
});

const year = (bonobUrl: URLBuilder, year: Year) => ({
const yyyy = (bonobUrl: URLBuilder, year: Year) => ({
itemType: "albumList",
id: `year:${year.year}`,
title: year.year,
albumArtURI: iconArtURI(bonobUrl, "music").href(),
// todo: maybe year.year should be nullable?
albumArtURI: year.year !== "?" ? iconArtURI(bonobUrl, "yyyy", year.year).href() : iconArtURI(bonobUrl, "music").href(),
});

const playlist = (bonobUrl: URLBuilder, playlist: Playlist) => ({
Expand Down Expand Up @@ -286,9 +287,9 @@ export const coverArtURI = (
O.getOrElseW(() => iconArtURI(bonobUrl, "vinyl"))
);

export const iconArtURI = (bonobUrl: URLBuilder, icon: ICON) =>
export const iconArtURI = (bonobUrl: URLBuilder, icon: ICON, text: string | undefined = undefined) =>
bonobUrl.append({
pathname: `/icon/${icon}/size/legacy`,
pathname: `/icon/${text == undefined ? icon : `${icon}:${text}`}/size/legacy`,
});

export const sonosifyMimeType = (mimeType: string) =>
Expand Down Expand Up @@ -888,7 +889,7 @@ function bindSmapiSoapServiceToExpress(
.then(([page, total]) =>
getMetadataResult({
mediaCollection: page.map((it) =>
year(bonobUrl, it)
yyyy(bonobUrl, it)
),
index: paging._index,
total,
Expand Down
2 changes: 1 addition & 1 deletion src/subsonic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ export class SubsonicMusicLibrary implements MusicLibrary {
years = async () => {
const q: AlbumQuery = {
_index: 0,
_count: 100000, // FIXME: better than this ?
_count: 100000, // FIXME: better than this, probably doesnt work anyway as max _count is 500 or something
type: "alphabeticalByArtist",
};
const years = this.subsonic.getAlbumList2(this.credentials, q)
Expand Down
8 changes: 1 addition & 7 deletions tests/builders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
Playlist,
SimilarArtist,
AlbumSummary,
RadioStation,
RadioStation
} from "../src/music_service";

import { b64Encode } from "../src/b64";
Expand Down Expand Up @@ -166,12 +166,6 @@ export const SAMPLE_GENRES = [
];
export const randomGenre = () => SAMPLE_GENRES[randomInt(SAMPLE_GENRES.length)];

export const aYear = (year: string) => ({ id: year, year });

export const Y2024 = aYear("2024");
export const Y2023 = aYear("2023");
export const Y1969 = aYear("1969");

export function aTrack(fields: Partial<Track> = {}): Track {
const id = uuid();
const artist = anArtist();
Expand Down
Loading

0 comments on commit 71717e6

Please sign in to comment.