Skip to content
Open
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
22 changes: 22 additions & 0 deletions Extensions/full-screen/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Contributing

```bash
cd Extensions/full-screen
npm install
npm run build-local
```

Bundle: `dist/fullScreen.js`. Use **`build-local`** so output lands in `dist/` (plain `npm run build` may not).

**Try it in Spotify:** Uninstall Marketplace Full Screen (or remove it from `extensions` in `config-xpui.ini` — only one Full Screen should load, otherwise there might be conflicts). Copy the bundle and apply:

```bash
cp dist/fullScreen.js ~/.config/spicetify/Extensions/fullScreenDev.js && spicetify apply
# Windows: %appdata%\spicetify\Extensions\
```

Add `fullScreenDev.js` to `extensions =`, then `spicetify apply`.

**Done testing:** Remove `fullScreenDev.js` from config and from the Extensions folder, reinstall Full Screen from Marketplace, `spicetify apply`.

**Pushing:** Commit changes along with the newly generated `dist/fullScreen.js`
20 changes: 10 additions & 10 deletions Extensions/full-screen/dist/fullScreen.js

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions Extensions/full-screen/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ import "./styles/tvMode.scss";
import "./styles/defaultMode.scss";
import "./styles/settings.scss";

/** Multiplier on 1× (classic) album-art width/max/min; unused for Auto layout. */
const DEFAULT_MODE_CLASSIC_ALBUM_MULT: Partial<
Record<Config["defaultModeAlbumArtSizing"], number>
> = {
scale125: 1.25,
scale15: 1.5,
scale175: 1.75,
scale2: 2,
scale25: 2.5,
};

async function main() {
let INIT_RETRIES = 0;
let entriesNotPresent = Utils.allNotExist();
Expand Down Expand Up @@ -94,6 +105,14 @@ async function main() {
(CFM.get("verticalMonitorSupport") as Settings["verticalMonitorSupport"]) &&
window.innerWidth < window.innerHeight,
);
const albumSizing = CFM.getGlobal("defaultModeAlbumArtSizing") as Config["defaultModeAlbumArtSizing"];
DOM.container.classList.toggle("album-art-auto-scale", albumSizing === "auto");
const classicMult = DEFAULT_MODE_CLASSIC_ALBUM_MULT[albumSizing];
if (classicMult != null) {
DOM.container.style.setProperty("--fsd-album-size-mult", String(classicMult));
} else {
DOM.container.style.removeProperty("--fsd-album-size-mult");
}
document.body.classList.toggle(
"vertical-mode",
(CFM.get("verticalMonitorSupport") as Settings["verticalMonitorSupport"]) &&
Expand Down
1 change: 1 addition & 0 deletions Extensions/full-screen/src/constants/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,5 @@ export const DEFAULTS: Config = {
activationTypes: "both",
buttonActivation: "both",
keyActivation: "both",
defaultModeAlbumArtSizing: "classic",
};
12 changes: 11 additions & 1 deletion Extensions/full-screen/src/resources/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,17 @@
"icons": "Icons",
"songChangeAnimation": "Song Change Animation",
"fullscreen": "Fullscreen",

"albumArtSizing": {
"setting": "Album art size",
"description": "Does not affect TV mode. **1x-2.5x**: fixed layout; higher values make album art larger (may clip or crowd lyrics). **Auto**: responsive cover size (based on window size).",
"classic": "1x",
"scale125": "1.25x",
"scale15": "1.5x",
"scale175": "1.75x",
"scale2": "2x",
"scale25": "2.5x",
"auto": "Auto"
},
"extraHeader": "Extra Functionality",
"backgroundChoice": {
"setting": "⭐ Background Choice",
Expand Down
12 changes: 11 additions & 1 deletion Extensions/full-screen/src/styles/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,16 @@
transition: all var(--transition-duration) var(--transition-function);
}

/* Omnidirectional shadow (0 offset); on wrapper so overflow:hidden on same box does not clip it. */
#fsd-art {
border-radius: 8px;
overflow: hidden;
box-shadow:
0 0 0 1px rgba(255, 255, 255, 0.07),
0 0 22px rgba(0, 0, 0, 0.45),
0 0 52px rgba(0, 0, 0, 0.28);
}

#fsd-art-image {
position: relative;
width: 100%;
Expand All @@ -347,7 +357,7 @@
width: 94%;
height: 94%;
z-index: -1;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.6) !important;
box-shadow: 0 0 18px rgba(0, 0, 0, 0.4) !important;
transform: translateZ(0);
}

Expand Down
69 changes: 66 additions & 3 deletions Extensions/full-screen/src/styles/defaultMode.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#full-screen-display[mode="def"] {
--fsd-album-size-mult: 1;
&,
&.lyrics-unavailable,
&.lyrics-hide-force {
Expand Down Expand Up @@ -160,9 +161,71 @@
text-align: center;
}
#fsd-art {
width: calc(100vh - 300px);
max-width: var(--fsd-art-max-width);
min-width: 300px;
width: calc((100vh - 300px) * var(--fsd-album-size-mult, 1));
max-width: calc(var(--fsd-art-max-width) * var(--fsd-album-size-mult, 1));
min-width: calc(300px * var(--fsd-album-size-mult, 1));
}

/* Auto scale: viewport-based size with margins (.album-art-auto-scale on #full-screen-display).
Inner floors use 300px so the smallest cover matches classic 1× `min-width: calc(300px * mult)`. */
&.album-art-auto-scale {
#fsd-art {
width: min(
max(300px, calc(100vh - 452px)),
max(300px, calc(50vw - 128px)),
max(300px, 65vmin)
);
max-width: none;
min-width: 300px;
}

&.lyrics-active:not(.lyrics-unavailable):not(.lyrics-hide-force) #fsd-art {
width: min(
max(300px, calc(100vh - 492px)),
max(300px, calc(50vw - 104px)),
max(300px, 63vmin)
);
max-width: none;
min-width: 300px;
}

&.vertical-mode.lyrics-active #fsd-foreground #fsd-art {
width: min(
max(300px, calc(50vh - 192px)),
max(300px, calc(100vw - 104px)),
max(300px, 62vmin)
);
max-width: none;
min-width: 300px;
}

&.vertical-mode.lyrics-active.lyrics-unavailable #fsd-foreground #fsd-art,
&.vertical-mode.lyrics-active.lyrics-hide-force #fsd-foreground #fsd-art {
width: min(
max(300px, calc(100vh - 492px)),
max(300px, calc(100vw - 104px)),
max(300px, 63vmin)
);
max-width: none;
min-width: 300px;
}

@media (max-width: 768px) {
#fsd-art {
width: min(
max(300px, calc(100vh - 392px)),
max(300px, calc(50vw - 84px)),
max(300px, 63vmin)
);
}
&.lyrics-active:not(.lyrics-unavailable):not(.lyrics-hide-force) #fsd-art {
width: min(
max(300px, calc(100vh - 412px)),
max(300px, calc(50vw - 80px)),
max(300px, 62vmin)
);
}
}
}

#fsd-title {
Expand Down
9 changes: 9 additions & 0 deletions Extensions/full-screen/src/types/fullscreen.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ export type Config = {
activationTypes: "both" | "btns" | "keys";
buttonActivation: "both" | "tv" | "def";
keyActivation: "both" | "tv" | "def";
/** Default full screen only (not TV). `classic` = 1× base layout; `scale*` = same rules × 1.25…2.5. */
defaultModeAlbumArtSizing:
| "classic"
| "auto"
| "scale125"
| "scale15"
| "scale175"
| "scale2"
| "scale25";
};

export type Settings = {
Expand Down
25 changes: 23 additions & 2 deletions Extensions/full-screen/src/ui/components/Config/Config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ export class ConfigManager {
const settingCard = getSettingCard(
`<select>
${Object.keys(options)
.map((item) => `<option value="${item}" dir="auto">${options[item]}</option>`)
.join("\n")}
.map((item) => `<option value="${item}" dir="auto">${options[item]}</option>`)
.join("\n")}
</select>`,
title,
key,
Expand Down Expand Up @@ -332,6 +332,27 @@ export class ConfigManager {
document.fullscreenEnabled
? this.createToggle(translations[LOCALE].settings.fullscreen, "enableFullscreen")
: "",
this.createOptions(
translations[LOCALE].settings.albumArtSizing.setting,
{
classic: translations[LOCALE].settings.albumArtSizing.classic,
scale125: translations[LOCALE].settings.albumArtSizing.scale125,
scale15: translations[LOCALE].settings.albumArtSizing.scale15,
scale175: translations[LOCALE].settings.albumArtSizing.scale175,
scale2: translations[LOCALE].settings.albumArtSizing.scale2,
scale25: translations[LOCALE].settings.albumArtSizing.scale25,
auto: translations[LOCALE].settings.albumArtSizing.auto,
},
CFM.getGlobal("defaultModeAlbumArtSizing") as Config["defaultModeAlbumArtSizing"],
"defaultModeAlbumArtSizing",
(value: string) => {
this.saveGlobalOption(
"defaultModeAlbumArtSizing",
value as Config["defaultModeAlbumArtSizing"],
);
},
translations[LOCALE].settings.albumArtSizing.description,
),
headerText(translations[LOCALE].settings.extraHeader),
this.createOptions(
translations[LOCALE].settings.extraControls,
Expand Down
19 changes: 19 additions & 0 deletions Extensions/full-screen/src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,25 @@ function getConfig(DEFAULTS: Config): Config {
const parsed = JSON.parse(localStorage.getItem("full-screen-config") ?? "{}");
if (Boolean(parsed) && typeof parsed === "object") {
defaultsDeep(parsed, DEFAULTS);
const def = parsed.def as Record<string, unknown> | undefined;
const legacyAlbum = def?.albumArtSizing;
if (
def &&
typeof legacyAlbum === "string" &&
[
"classic",
"auto",
"scale125",
"scale15",
"scale175",
"scale2",
"scale25",
].includes(legacyAlbum)
) {
(parsed as unknown as Config).defaultModeAlbumArtSizing =
legacyAlbum as Config["defaultModeAlbumArtSizing"];
delete def.albumArtSizing;
}
localStorage.setItem("full-screen-config", JSON.stringify(parsed));
return parsed;
}
Expand Down