v3: various minor visual fixes
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 39s
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 39s
This commit is contained in:
11
src/App.css
11
src/App.css
@@ -1022,6 +1022,13 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
a.global-player-title {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a.global-player-title:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
.global-player-body {
|
.global-player-body {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 1fr;
|
grid-template-rows: 1fr;
|
||||||
@@ -4972,8 +4979,10 @@ body.has-fab .page-content {
|
|||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
font-size: 0.9rem;
|
font-size: 0.8rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background 0.12s;
|
transition: background 0.12s;
|
||||||
|
|||||||
@@ -176,11 +176,11 @@ function App() {
|
|||||||
<CategoriesProvider>
|
<CategoriesProvider>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<AppRoutes />
|
<AppRoutes />
|
||||||
|
<GlobalPlayer />
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</CategoriesProvider>
|
</CategoriesProvider>
|
||||||
</FollowProvider>
|
</FollowProvider>
|
||||||
</WSProvider>
|
</WSProvider>
|
||||||
<GlobalPlayer />
|
|
||||||
</PlayerProvider>
|
</PlayerProvider>
|
||||||
</AuthProvider>
|
</AuthProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export function DumpCard(
|
|||||||
<RichContentCard
|
<RichContentCard
|
||||||
richContent={dump.richContent}
|
richContent={dump.richContent}
|
||||||
compact
|
compact
|
||||||
|
dumpHref={dumpUrl(dump)}
|
||||||
thumbnailOverrideUrl={dump.thumbnailMime
|
thumbnailOverrideUrl={dump.thumbnailMime
|
||||||
? dumpThumbnailUrl(dump, token)
|
? dumpThumbnailUrl(dump, token)
|
||||||
: undefined}
|
: undefined}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, useState } from "react";
|
||||||
import type { Dump } from "../model.ts";
|
import type { Dump } from "../model.ts";
|
||||||
import { formatBytes } from "../utils/format.ts";
|
import { formatBytes } from "../utils/format.ts";
|
||||||
import { dumpFileUrl, dumpThumbnailUrl } from "../utils/urls.ts";
|
import { dumpFileUrl, dumpThumbnailUrl, dumpUrl } from "../utils/urls.ts";
|
||||||
import { useAuth } from "../hooks/useAuth.ts";
|
import { useAuth } from "../hooks/useAuth.ts";
|
||||||
import { IconPause, IconPlay, MediaPlayer } from "./MediaPlayer.tsx";
|
import { IconPause, IconPlay, MediaPlayer } from "./MediaPlayer.tsx";
|
||||||
import { PlayerContext } from "../contexts/PlayerContext.ts";
|
import { PlayerContext } from "../contexts/PlayerContext.ts";
|
||||||
@@ -45,7 +45,7 @@ function AudioFilePreview(
|
|||||||
|
|
||||||
const handlePlayBtn = () => {
|
const handlePlayBtn = () => {
|
||||||
if (isActive) togglePlay();
|
if (isActive) togglePlay();
|
||||||
else play({ kind: "file", fileUrl, mimeType: mime, title: dump.title });
|
else play({ kind: "file", fileUrl, mimeType: mime, title: dump.title, dumpHref: dumpUrl(dump) });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleWaveformClick = (e: React.MouseEvent<Element>) => {
|
const handleWaveformClick = (e: React.MouseEvent<Element>) => {
|
||||||
@@ -59,7 +59,7 @@ function AudioFilePreview(
|
|||||||
} else {
|
} else {
|
||||||
// Start playing and seek once it loads — seekTo after play() is a no-op
|
// Start playing and seek once it loads — seekTo after play() is a no-op
|
||||||
// until MediaPlayer mounts; the fraction is best-effort on first click
|
// until MediaPlayer mounts; the fraction is best-effort on first click
|
||||||
play({ kind: "file", fileUrl, mimeType: mime, title: dump.title });
|
play({ kind: "file", fileUrl, mimeType: mime, title: dump.title, dumpHref: dumpUrl(dump) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ export default function FilePreview(
|
|||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
play({ kind: "file", fileUrl, mimeType: mime, title: dump.title });
|
play({ kind: "file", fileUrl, mimeType: mime, title: dump.title, dumpHref: dumpUrl(dump) });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<VideoThumb src={thumbUrl} fallback={mimeIcon(mime)} />
|
<VideoThumb src={thumbUrl} fallback={mimeIcon(mime)} />
|
||||||
@@ -196,7 +196,7 @@ export default function FilePreview(
|
|||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
play({ kind: "file", fileUrl, mimeType: mime, title: dump.title });
|
play({ kind: "file", fileUrl, mimeType: mime, title: dump.title, dumpHref: dumpUrl(dump) });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{thumbOverride
|
{thumbOverride
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useContext, useEffect, useRef, useState } from "react";
|
import { useContext, useEffect, useRef, useState } from "react";
|
||||||
|
import { Link } from "react-router";
|
||||||
import { PlayerContext } from "../contexts/PlayerContext.ts";
|
import { PlayerContext } from "../contexts/PlayerContext.ts";
|
||||||
import { MediaPlayer } from "./MediaPlayer.tsx";
|
import { MediaPlayer } from "./MediaPlayer.tsx";
|
||||||
|
|
||||||
@@ -75,7 +76,13 @@ export function GlobalPlayer() {
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
<div className="global-player-header">
|
<div className="global-player-header">
|
||||||
<span className="global-player-title">{title}</span>
|
{current.dumpHref
|
||||||
|
? (
|
||||||
|
<Link to={current.dumpHref} className="global-player-title">
|
||||||
|
{title}
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
: <span className="global-player-title">{title}</span>}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn--ghost"
|
className="btn btn--ghost"
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ export function JournalCard(
|
|||||||
embedUrl,
|
embedUrl,
|
||||||
title: dump.richContent?.title,
|
title: dump.richContent?.title,
|
||||||
type: dump.richContent?.type ?? "unknown",
|
type: dump.richContent?.type ?? "unknown",
|
||||||
|
dumpHref: dumpUrl(dump),
|
||||||
})
|
})
|
||||||
: handleNavigate}
|
: handleNavigate}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -22,10 +22,13 @@ interface RichContentCardProps {
|
|||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
/** Overrides richContent.thumbnailUrl with a custom dump thumbnail, if set. */
|
/** Overrides richContent.thumbnailUrl with a custom dump thumbnail, if set. */
|
||||||
thumbnailOverrideUrl?: string;
|
thumbnailOverrideUrl?: string;
|
||||||
|
/** Link back to the owning dump, surfaced as the global player's title. */
|
||||||
|
dumpHref?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RichContentCard(
|
export default function RichContentCard(
|
||||||
{ richContent, compact = false, thumbnailOverrideUrl }: RichContentCardProps,
|
{ richContent, compact = false, thumbnailOverrideUrl, dumpHref }:
|
||||||
|
RichContentCardProps,
|
||||||
) {
|
) {
|
||||||
const { play, current, playing } = useContext(PlayerContext);
|
const { play, current, playing } = useContext(PlayerContext);
|
||||||
const thumbnailSrc = thumbnailOverrideUrl ??
|
const thumbnailSrc = thumbnailOverrideUrl ??
|
||||||
@@ -52,6 +55,7 @@ export default function RichContentCard(
|
|||||||
embedUrl: richContent.embedUrl!,
|
embedUrl: richContent.embedUrl!,
|
||||||
title: richContent.title,
|
title: richContent.title,
|
||||||
type: richContent.type,
|
type: richContent.type,
|
||||||
|
dumpHref,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
aria-label={isPlaying ? "Pause" : "Play"}
|
aria-label={isPlaying ? "Pause" : "Play"}
|
||||||
@@ -113,6 +117,7 @@ export default function RichContentCard(
|
|||||||
embedUrl: richContent.embedUrl!,
|
embedUrl: richContent.embedUrl!,
|
||||||
title: richContent.title,
|
title: richContent.title,
|
||||||
type: richContent.type,
|
type: richContent.type,
|
||||||
|
dumpHref,
|
||||||
})}
|
})}
|
||||||
aria-label="Play"
|
aria-label="Play"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { createContext } from "react";
|
import { createContext } from "react";
|
||||||
|
|
||||||
export type PlayerItem =
|
export type PlayerItem =
|
||||||
| { kind: "embed"; embedUrl: string; title?: string; type: string }
|
| { kind: "embed"; embedUrl: string; title?: string; type: string; dumpHref?: string }
|
||||||
| { kind: "file"; fileUrl: string; mimeType: string; title?: string };
|
| { kind: "file"; fileUrl: string; mimeType: string; title?: string; dumpHref?: string };
|
||||||
|
|
||||||
export interface PlayerContextValue {
|
export interface PlayerContextValue {
|
||||||
// Playback state — readable by any consumer
|
// Playback state — readable by any consumer
|
||||||
|
|||||||
@@ -462,6 +462,7 @@ export function Dump() {
|
|||||||
? (
|
? (
|
||||||
<RichContentCard
|
<RichContentCard
|
||||||
richContent={dump.richContent}
|
richContent={dump.richContent}
|
||||||
|
dumpHref={dumpUrl(dump)}
|
||||||
thumbnailOverrideUrl={dump.thumbnailMime
|
thumbnailOverrideUrl={dump.thumbnailMime
|
||||||
? dumpThumbnailUrl(dump, token)
|
? dumpThumbnailUrl(dump, token)
|
||||||
: undefined}
|
: undefined}
|
||||||
|
|||||||
@@ -309,7 +309,9 @@
|
|||||||
/* ── Category management chips / inline editor ───────────────────── */
|
/* ── Category management chips / inline editor ───────────────────── */
|
||||||
[data-style="brutalist"] .category-chip,
|
[data-style="brutalist"] .category-chip,
|
||||||
[data-style="brutalist"] .category-editor,
|
[data-style="brutalist"] .category-editor,
|
||||||
[data-style="brutalist"] .category-editor-btn {
|
[data-style="brutalist"] .category-editor-btn,
|
||||||
|
[data-style="brutalist"] .dump-card-category-chip,
|
||||||
|
[data-style="brutalist"] .profile-role-chip {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -492,7 +492,9 @@
|
|||||||
[data-style="geocities"] .feed-tab,
|
[data-style="geocities"] .feed-tab,
|
||||||
[data-style="geocities"] .category-chip,
|
[data-style="geocities"] .category-chip,
|
||||||
[data-style="geocities"] .category-editor,
|
[data-style="geocities"] .category-editor,
|
||||||
[data-style="geocities"] .category-editor-btn {
|
[data-style="geocities"] .category-editor-btn,
|
||||||
|
[data-style="geocities"] .dump-card-category-chip,
|
||||||
|
[data-style="geocities"] .profile-role-chip {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -245,6 +245,7 @@
|
|||||||
[data-style="nyt"] .related-section-title,
|
[data-style="nyt"] .related-section-title,
|
||||||
[data-style="nyt"] .form-page-eyebrow,
|
[data-style="nyt"] .form-page-eyebrow,
|
||||||
[data-style="nyt"] .feed-sort-btn,
|
[data-style="nyt"] .feed-sort-btn,
|
||||||
|
[data-style="nyt"] .category-switcher-option,
|
||||||
[data-style="nyt"] .follow-btn,
|
[data-style="nyt"] .follow-btn,
|
||||||
[data-style="nyt"] .playlist-badge,
|
[data-style="nyt"] .playlist-badge,
|
||||||
[data-style="nyt"] .dump-card-private-badge,
|
[data-style="nyt"] .dump-card-private-badge,
|
||||||
@@ -529,7 +530,8 @@
|
|||||||
[data-style="nyt"] .vote-btn,
|
[data-style="nyt"] .vote-btn,
|
||||||
[data-style="nyt"] .follow-btn,
|
[data-style="nyt"] .follow-btn,
|
||||||
[data-style="nyt"] .btn-add-playlist,
|
[data-style="nyt"] .btn-add-playlist,
|
||||||
[data-style="nyt"] .invite-btn {
|
[data-style="nyt"] .invite-btn,
|
||||||
|
[data-style="nyt"] .profile-role-chip {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
@@ -537,7 +539,8 @@
|
|||||||
/* Category management chips / inline editor: squared, no accent glow. */
|
/* Category management chips / inline editor: squared, no accent glow. */
|
||||||
[data-style="nyt"] .category-chip,
|
[data-style="nyt"] .category-chip,
|
||||||
[data-style="nyt"] .category-editor,
|
[data-style="nyt"] .category-editor,
|
||||||
[data-style="nyt"] .category-editor-btn {
|
[data-style="nyt"] .category-editor-btn,
|
||||||
|
[data-style="nyt"] .dump-card-category-chip {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user