Flixy heißt ab hier Halo
Reine Umbenennung, kein Verhalten geändert — bewusst als eigener Commit, damit „umbenannt" und „umgebaut" im Nachhinein auseinanderzuhalten sind. 712 mal `Flixy`, 778 mal `flixy`, 7 mal `FLIXY` in 169 Dateien, dazu 25 Pfade. Ziele: `Halo`, `HaloTV`, `HaloTopShelf`, `HaloUITests`, `HaloKit` mit `HaloDesign`, `HaloDownloads`, `HaloPlayback` und `HaloProbe`. `MediaKit`, `JellyfinKit` und `DownloadWidget` tragen den Namen nicht und bleiben. `docs/superpowers/specs/` ist ausgenommen. Datierte Entwurfsdokumente sind ein Protokoll getroffener Entscheidungen; sie nachträglich umzuschreiben hiesse, die Vergangenheit zu glätten. **Die Bundle-ID wandert mit** — ausdrücklich so gewollt, mit bekanntem Preis: `com.scarriffleservices.halo` ist für iOS eine *andere* App. Die installierte Fassung bleibt daneben stehen, mit Downloads und Anmeldung in ihrem Container; Halo startet leer. Einmal neu anmelden, heruntergeladene Folgen einmal neu laden. Dasselbe gilt für die App-Gruppe, die sich TV-App und Top Shelf teilen. **Eine Folge davon, die beim Entscheiden noch nicht auf dem Tisch lag:** der Aufräumschritt aus dem vorigen Commit kommt an die alten Plex-Token nicht mehr heran. Der Schlüsselbund grenzt nach Team und Bundle-Kennung ab — was unter `…flixy` liegt, ist für `…halo` unerreichbar. Erledigt wird es trotzdem, nur anders: **die alte App löschen.** iOS räumt deren Schlüsselbund-Einträge beim Deinstallieren mit ab. Der Code bleibt stehen, weil er für jeden Stand vor dieser Umbenennung richtig ist und im Jahr einen Startvergleich kostet. Die Projektdatei ist aus `project.yml` neu erzeugt, der alte Ordner gelöscht statt umbenannt — sie steht ohnehin nicht im Repo. Das Verzeichnis des Repos selbst heißt weiter `Flixy`; das umzubenennen ist ein Handgriff ausserhalb des Projekts. 368 Tests grün. iOS und tvOS bauen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2fcf6821c8
commit
4b9a1e7b67
@@ -0,0 +1,334 @@
|
||||
/* ============================================================================
|
||||
Halo für Jellyfin Web
|
||||
----------------------------------------------------------------------------
|
||||
Bringt Jellyfins Weboberfläche auf die Farben, Schrift und Formen der
|
||||
Halo-App. Es ist ein Kleid, kein Umbau: die Oberfläche bleibt Jellyfins,
|
||||
sie sieht nur anders aus.
|
||||
|
||||
EINBAUEN
|
||||
Jellyfin-Dashboard → Allgemein → „Benutzerdefiniertes CSS“ — alles hier
|
||||
hineinkopieren, speichern, Seite neu laden. Gilt serverweit für alle
|
||||
Browser, also auch auf Windows. Wieder loswerden: Feld leeren.
|
||||
|
||||
AUFGEBAUT AUF MESSUNG, NICHT AUF VERMUTUNG
|
||||
Die Variablennamen und Klassen stammen aus einer laufenden Jellyfin-
|
||||
Instanz (Stand 09/2026), nicht aus dem Gedächtnis. Der größte Teil der
|
||||
Wirkung entsteht dadurch, dass Jellyfins **eigene** Farbvariablen
|
||||
umgebogen werden — das hält das Ganze kurz und überlebt Updates besser
|
||||
als eine Sammlung einzeln überschriebener Regeln.
|
||||
========================================================================= */
|
||||
|
||||
:root {
|
||||
/* ---- Die Akzentfarbe -----------------------------------------------
|
||||
Zum Wechseln nur diese eine Zeile ändern. Die Palette der App:
|
||||
Ember #E5484D · Tangerine #F76B15 · Amber #FFB224 · Lime #99D52A
|
||||
Mint #3DD68C · Teal #12A594 · Sky #52A9FF · Indigo #7C77E8
|
||||
Orchid #C04AC9 · Rose #F76190
|
||||
Voreingestellt ist Orchid — die Farbe, die auf dem iPad eingestellt
|
||||
ist. Die App selbst kommt ab Werk mit Mint. */
|
||||
--halo-accent: #C04AC9;
|
||||
|
||||
/* ---- Die Flächen der App, von hinten nach vorn ---------------------- */
|
||||
--halo-canvas: #0B0B0D; /* Seitenhintergrund */
|
||||
--halo-surface: #141417; /* Karten, Kopfbereiche */
|
||||
--halo-elevated: #1D1D21; /* Blätter, Menüs */
|
||||
--halo-placeholder: #26262B; /* Platzhalter, gedrückte Zustände */
|
||||
|
||||
--halo-text: #F5F5F7;
|
||||
--halo-text-secondary: #A0A0A8;
|
||||
--halo-text-muted: #6E6E76;
|
||||
--halo-destructive: #E5484D;
|
||||
--halo-separator: rgba(255, 255, 255, 0.10);
|
||||
|
||||
/* ---- Formen --------------------------------------------------------- */
|
||||
--halo-radius-card: 8px;
|
||||
--halo-radius-control: 10px;
|
||||
--halo-radius-sheet: 16px;
|
||||
--halo-radius-panel: 22px; /* die schwebende Leiste */
|
||||
|
||||
/* ---- Schrift --------------------------------------------------------
|
||||
Der größte einzelne Hebel. Jellyfin liefert Noto Sans aus; die
|
||||
Systemschrift macht aus derselben Seite sofort eine, die auf den
|
||||
Rechner gehört — SF auf Mac und iPhone, Segoe UI Variable auf
|
||||
Windows 11. */
|
||||
--halo-font: -apple-system, BlinkMacSystemFont, "SF Pro Text",
|
||||
"Segoe UI Variable Text", "Segoe UI", system-ui,
|
||||
Roboto, "Helvetica Neue", sans-serif;
|
||||
|
||||
/* ---- Jellyfins eigene Variablen umbiegen ---------------------------
|
||||
Hier entsteht der Großteil der Wirkung: Jellyfin baut auf einer
|
||||
MUI-Palette auf, und wer die verstellt, verstellt alles, was darauf
|
||||
aufsetzt — inklusive Bauteilen, die dieses CSS gar nicht kennt. */
|
||||
--jf-palette-background-default: var(--halo-canvas);
|
||||
--jf-palette-background-defaultChannel: 11 11 13;
|
||||
--jf-palette-background-paper: var(--halo-surface);
|
||||
--jf-palette-background-paperChannel: 20 20 23;
|
||||
|
||||
--jf-palette-primary-main: var(--halo-accent);
|
||||
--jf-palette-primary-dark: var(--halo-accent);
|
||||
--jf-palette-primary-light: var(--halo-accent);
|
||||
--jf-palette-secondary-main: var(--halo-accent);
|
||||
--jf-palette-secondary-dark: var(--halo-accent);
|
||||
--jf-palette-secondary-light: var(--halo-accent);
|
||||
/* Schrift auf dem Akzent: hell, weil die Palette der App durchweg
|
||||
kräftige Farben hat. Bei einem hellen Akzent (Amber, Lime) hier auf
|
||||
#101013 stellen, sonst verschwindet die Beschriftung. */
|
||||
--jf-palette-primary-contrastText: #FFFFFF;
|
||||
--jf-palette-secondary-contrastText: #FFFFFF;
|
||||
|
||||
--jf-palette-text-primary: var(--halo-text);
|
||||
--jf-palette-text-secondary: var(--halo-text-secondary);
|
||||
--jf-palette-text-disabled: var(--halo-text-muted);
|
||||
--jf-palette-text-icon: var(--halo-text-secondary);
|
||||
--jf-palette-divider: var(--halo-separator);
|
||||
|
||||
--jf-palette-error-main: var(--halo-destructive);
|
||||
--jf-palette-error-dark: #B4373B;
|
||||
--jf-palette-error-light: #EC6E72;
|
||||
|
||||
--jf-palette-action-hover: rgba(255, 255, 255, 0.06);
|
||||
--jf-palette-action-selected: rgba(255, 255, 255, 0.12);
|
||||
--jf-palette-action-disabled: var(--halo-text-muted);
|
||||
|
||||
/* Die Kopfleiste trägt die Insel — sie selbst bleibt durchsichtig. */
|
||||
--jf-palette-AppBar-defaultBg: transparent;
|
||||
--jf-palette-AppBar-darkBg: transparent;
|
||||
|
||||
--jf-card-borderRadius: var(--halo-radius-card);
|
||||
--jf-shape-borderRadius: var(--halo-radius-control);
|
||||
}
|
||||
|
||||
/* ---- Grundfläche und Schrift --------------------------------------------
|
||||
`html` bekommt seinen Hintergrund bei Jellyfin unmittelbar gesetzt und
|
||||
nicht über die Palette — deshalb steht er hier noch einmal ausdrücklich. */
|
||||
html {
|
||||
background-color: var(--halo-canvas) !important;
|
||||
font-family: var(--halo-font) !important;
|
||||
color: var(--halo-text);
|
||||
}
|
||||
|
||||
body,
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
.emby-button,
|
||||
.emby-input,
|
||||
.emby-select,
|
||||
.cardText,
|
||||
.sectionTitle {
|
||||
font-family: var(--halo-font) !important;
|
||||
}
|
||||
|
||||
.backgroundContainer,
|
||||
.mainAnimatedPage {
|
||||
background-color: var(--halo-canvas) !important;
|
||||
}
|
||||
|
||||
/* ---- Die Kopfleiste als schwebende Insel --------------------------------
|
||||
Das Merkmal der App: die Navigation ist eine Fläche mit Abstand ringsum,
|
||||
nicht ein Balken, der am Rand klebt. Der Inhalt läuft dahinter durch.
|
||||
|
||||
`backdrop-filter` ist der Kern — und der Grund, warum es auf Safari und
|
||||
Chrome überzeugender aussieht als auf älteren Firefox-Fassungen. Wo er
|
||||
fehlt, bleibt eine schlicht gefüllte Fläche; unschön ist das nicht. */
|
||||
.skinHeader {
|
||||
background: rgba(20, 20, 23, 0.72) !important;
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
border: 1px solid var(--halo-separator);
|
||||
border-radius: var(--halo-radius-panel);
|
||||
margin: 10px 12px 0;
|
||||
width: calc(100% - 24px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.skinHeader-withBackground {
|
||||
background: rgba(20, 20, 23, 0.72) !important;
|
||||
}
|
||||
|
||||
/* ---- Die Seitenleiste ---------------------------------------------------- */
|
||||
.mainDrawer {
|
||||
background-color: var(--halo-surface) !important;
|
||||
border-right: 1px solid var(--halo-separator);
|
||||
}
|
||||
|
||||
.navMenuOption {
|
||||
border-radius: var(--halo-radius-control);
|
||||
margin: 2px 8px;
|
||||
}
|
||||
|
||||
.navMenuOption-selected {
|
||||
background: var(--halo-elevated) !important;
|
||||
color: var(--halo-accent) !important;
|
||||
}
|
||||
|
||||
/* ---- Karten -------------------------------------------------------------
|
||||
Die Poster sind das, was man auf einer Startseite hauptsächlich sieht;
|
||||
ihre Rundung bestimmt den Eindruck stärker als jede Farbe. Acht Punkt,
|
||||
wie in der App. */
|
||||
.cardImageContainer,
|
||||
.cardContent,
|
||||
.cardScalable,
|
||||
.cardOverlayContainer {
|
||||
border-radius: var(--halo-radius-card) !important;
|
||||
}
|
||||
|
||||
.cardBox {
|
||||
margin: 0.5em !important;
|
||||
}
|
||||
|
||||
.cardText {
|
||||
color: var(--halo-text);
|
||||
}
|
||||
|
||||
.cardText-secondary {
|
||||
color: var(--halo-text-secondary);
|
||||
}
|
||||
|
||||
.defaultCardBackground,
|
||||
.defaultCardBackground1,
|
||||
.defaultCardBackground2,
|
||||
.defaultCardBackground3,
|
||||
.defaultCardBackground4,
|
||||
.defaultCardBackground5 {
|
||||
background-color: var(--halo-placeholder) !important;
|
||||
}
|
||||
|
||||
/* Der Fortschrittsbalken auf angefangenen Titeln — in der App trägt er den
|
||||
Akzent, und er ist dünner als Jellyfins Voreinstellung. */
|
||||
.itemProgressBarForeground {
|
||||
background-color: var(--halo-accent) !important;
|
||||
}
|
||||
|
||||
.itemProgressBar {
|
||||
height: 3px !important;
|
||||
border-radius: 2px;
|
||||
background-color: rgba(255, 255, 255, 0.18) !important;
|
||||
}
|
||||
|
||||
/* ---- Knöpfe -------------------------------------------------------------- */
|
||||
.emby-button,
|
||||
.button-flat,
|
||||
.detailButton {
|
||||
border-radius: var(--halo-radius-control) !important;
|
||||
font-family: var(--halo-font) !important;
|
||||
}
|
||||
|
||||
.emby-button.raised {
|
||||
background: var(--halo-elevated);
|
||||
color: var(--halo-text);
|
||||
}
|
||||
|
||||
.emby-button.raised.button-submit,
|
||||
.button-submit {
|
||||
background: var(--halo-accent) !important;
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
/* Die Kapselform der App für die Hauptknöpfe einer Detailseite. */
|
||||
.detailPagePrimaryContainer .emby-button,
|
||||
.mainDetailButtons .emby-button {
|
||||
border-radius: 999px !important;
|
||||
}
|
||||
|
||||
/* ---- Eingabefelder ------------------------------------------------------- */
|
||||
.emby-input,
|
||||
.emby-select,
|
||||
.emby-textarea {
|
||||
background-color: var(--halo-elevated) !important;
|
||||
border: 1px solid var(--halo-separator) !important;
|
||||
border-radius: var(--halo-radius-control) !important;
|
||||
color: var(--halo-text) !important;
|
||||
}
|
||||
|
||||
.emby-input:focus,
|
||||
.emby-select:focus {
|
||||
border-color: var(--halo-accent) !important;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.inputLabel,
|
||||
.selectLabel,
|
||||
.fieldDescription {
|
||||
color: var(--halo-text-secondary) !important;
|
||||
}
|
||||
|
||||
/* ---- Blätter, Menüs, Dialoge --------------------------------------------- */
|
||||
.dialog,
|
||||
.formDialog,
|
||||
.actionSheet,
|
||||
.paper-icon-button-light + .actionSheet {
|
||||
background-color: var(--halo-elevated) !important;
|
||||
border-radius: var(--halo-radius-sheet) !important;
|
||||
border: 1px solid var(--halo-separator);
|
||||
}
|
||||
|
||||
.actionSheetMenuItem:hover,
|
||||
.listItem:hover {
|
||||
background-color: var(--jf-palette-action-hover) !important;
|
||||
}
|
||||
|
||||
/* ---- Detailseite --------------------------------------------------------- */
|
||||
.detailPagePrimaryContainer,
|
||||
.detailPageSecondaryContainer,
|
||||
.detailRibbon {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.detailSectionContent,
|
||||
.detailTableBodyCell {
|
||||
color: var(--halo-text-secondary);
|
||||
}
|
||||
|
||||
/* Das Hintergrundbild soll nach unten in die Seitenfarbe auslaufen, statt an
|
||||
einer Kante aufzuhören — dieselbe Verlaufsidee wie im Aufmacher der App. */
|
||||
.itemBackdrop {
|
||||
-webkit-mask-image: linear-gradient(to bottom,
|
||||
rgba(0, 0, 0, 1) 0%,
|
||||
rgba(0, 0, 0, 0.85) 45%,
|
||||
rgba(0, 0, 0, 0) 100%);
|
||||
mask-image: linear-gradient(to bottom,
|
||||
rgba(0, 0, 0, 1) 0%,
|
||||
rgba(0, 0, 0, 0.85) 45%,
|
||||
rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
|
||||
/* ---- Überschriften ------------------------------------------------------- */
|
||||
.sectionTitle {
|
||||
color: var(--halo-text) !important;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
/* ---- Trennlinien und Kleinkram ------------------------------------------- */
|
||||
.listItem-border,
|
||||
.detailTableBodyCell,
|
||||
hr {
|
||||
border-color: var(--halo-separator) !important;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--halo-accent);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* Die Bildlaufleisten dunkel halten — eine helle Leiste am Rand ist das
|
||||
Erste, was eine sonst dunkle Seite verrät. */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.14);
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255, 255, 255, 0.22);
|
||||
}
|
||||
Reference in New Issue
Block a user