v3: fixed authorization bug with stale tokens, fixed private dump access bug, various small fixes across the app
Some checks failed
Build and Publish Docker Image / build-and-push (push) Failing after 20s
Some checks failed
Build and Publish Docker Image / build-and-push (push) Failing after 20s
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { Link, useNavigate } from "react-router";
|
||||
import { Plural, Trans } from "@lingui/react/macro";
|
||||
import type { Dump } from "../model.ts";
|
||||
import { API_URL } from "../config/api.ts";
|
||||
import { relativeTime } from "../utils/relativeTime.ts";
|
||||
import { dumpUrl } from "../utils/urls.ts";
|
||||
import { dumpThumbnailUrl, dumpUrl } from "../utils/urls.ts";
|
||||
import { useAuth } from "../hooks/useAuth.ts";
|
||||
import { isDumpVisited, isRecent, markDumpVisited } from "../utils/visited.ts";
|
||||
import FilePreview from "./FilePreview.tsx";
|
||||
import RichContentCard from "./RichContentCard.tsx";
|
||||
@@ -27,6 +27,7 @@ export function DumpCard(
|
||||
DumpCardProps,
|
||||
) {
|
||||
const navigate = useNavigate();
|
||||
const { token } = useAuth();
|
||||
const unread = !isOwner && isRecent(dump.createdAt) &&
|
||||
!isDumpVisited(dump.id);
|
||||
|
||||
@@ -54,7 +55,7 @@ export function DumpCard(
|
||||
richContent={dump.richContent}
|
||||
compact
|
||||
thumbnailOverrideUrl={dump.thumbnailMime
|
||||
? `${API_URL}/api/thumbnails/${dump.id}`
|
||||
? dumpThumbnailUrl(dump, token)
|
||||
: undefined}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { API_URL } from "../config/api.ts";
|
||||
import type { Dump } from "../model.ts";
|
||||
import { formatBytes } from "../utils/format.ts";
|
||||
import { dumpFileUrl, dumpThumbnailUrl } from "../utils/urls.ts";
|
||||
import { useAuth } from "../hooks/useAuth.ts";
|
||||
import { IconPause, IconPlay, MediaPlayer } from "./MediaPlayer.tsx";
|
||||
import { PlayerContext } from "../contexts/PlayerContext.ts";
|
||||
import {
|
||||
@@ -145,11 +146,12 @@ export default function FilePreview(
|
||||
{ dump, compact = false, global: useGlobal = false }: FilePreviewProps,
|
||||
) {
|
||||
const { current, playing, play, togglePlay } = useContext(PlayerContext);
|
||||
const fileUrl = `${API_URL}/api/files/${dump.id}?v=${dump.fileSize ?? 0}`;
|
||||
const { token } = useAuth();
|
||||
const fileUrl = dumpFileUrl(dump, token);
|
||||
const mime = dump.fileMime ?? "";
|
||||
const isPlaying = current?.kind === "file" && current.fileUrl === fileUrl;
|
||||
const thumbOverride = dump.thumbnailMime
|
||||
? `${API_URL}/api/thumbnails/${dump.id}`
|
||||
? dumpThumbnailUrl(dump, token)
|
||||
: null;
|
||||
|
||||
if (compact) {
|
||||
@@ -166,7 +168,7 @@ export default function FilePreview(
|
||||
);
|
||||
}
|
||||
if (mime.startsWith("video/")) {
|
||||
const thumbUrl = `${API_URL}/api/thumbnails/${dump.id}`;
|
||||
const thumbUrl = dumpThumbnailUrl(dump, token);
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -4,7 +4,8 @@ import { Plural, Trans } from "@lingui/react/macro";
|
||||
import type { Dump } from "../model.ts";
|
||||
import { API_URL } from "../config/api.ts";
|
||||
import { relativeTime } from "../utils/relativeTime.ts";
|
||||
import { dumpUrl } from "../utils/urls.ts";
|
||||
import { dumpFileUrl, dumpUrl } from "../utils/urls.ts";
|
||||
import { useAuth } from "../hooks/useAuth.ts";
|
||||
import { isDumpVisited, isRecent, markDumpVisited } from "../utils/visited.ts";
|
||||
import { VoteButton } from "./VoteButton.tsx";
|
||||
import { Markdown } from "./Markdown.tsx";
|
||||
@@ -29,6 +30,7 @@ export function JournalCard(
|
||||
JournalCardProps,
|
||||
) {
|
||||
const navigate = useNavigate();
|
||||
const { token } = useAuth();
|
||||
const { play } = useContext(PlayerContext);
|
||||
const unread = !isOwner && isRecent(dump.createdAt) &&
|
||||
!isDumpVisited(dump.id);
|
||||
@@ -40,7 +42,7 @@ export function JournalCard(
|
||||
|
||||
const rawThumbnail =
|
||||
dump.kind === "file" && dump.fileMime?.startsWith("image/")
|
||||
? `${API_URL}/api/files/${dump.id}?v=${dump.fileSize ?? 0}`
|
||||
? dumpFileUrl(dump, token)
|
||||
: (dump.richContent?.thumbnailUrl ?? null);
|
||||
|
||||
// Route external HTTP thumbnails through the server proxy to avoid
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useId } from "react";
|
||||
import { type ReactNode, useId } from "react";
|
||||
import {
|
||||
type FieldValues,
|
||||
type Path,
|
||||
@@ -12,6 +12,8 @@ import { charCountClass } from "../../utils/charCount.ts";
|
||||
interface TextFieldProps<T extends FieldValues> {
|
||||
name: Path<T>;
|
||||
label?: string;
|
||||
/** Optional control rendered to the right of the label (e.g. a reset button). */
|
||||
labelAction?: ReactNode;
|
||||
type?: "text" | "email" | "password" | "url" | "search";
|
||||
placeholder?: string;
|
||||
autoComplete?: string;
|
||||
@@ -45,6 +47,7 @@ function CharCounter<T extends FieldValues>(
|
||||
export function TextField<T extends FieldValues>({
|
||||
name,
|
||||
label,
|
||||
labelAction,
|
||||
type = "text",
|
||||
placeholder,
|
||||
autoComplete,
|
||||
@@ -61,10 +64,17 @@ export function TextField<T extends FieldValues>({
|
||||
|
||||
return (
|
||||
<div className="form-field">
|
||||
{label && (
|
||||
<label className="form-label" htmlFor={id}>
|
||||
{label}
|
||||
</label>
|
||||
{(label || labelAction) && (
|
||||
<div className="form-label-row">
|
||||
{label
|
||||
? (
|
||||
<label className="form-label" htmlFor={id}>
|
||||
{label}
|
||||
</label>
|
||||
)
|
||||
: <span />}
|
||||
{labelAction}
|
||||
</div>
|
||||
)}
|
||||
<div className={counted ? "input-with-count" : undefined}>
|
||||
<input
|
||||
|
||||
Reference in New Issue
Block a user