mirror of
https://github.com/getAlby/hub.git
synced 2026-08-13 12:33:39 +02:00
* feat: integrate Stories widget with backend endpoint
Add stories endpoint plumbing for HTTP and Wails, wire the Home Stories card
to fetch from /api/alby/stories, and keep it first in the right column.
Made-with: Cursor
* feat(home): story modal CTAs and preview fallback
- Add contextual actions in the story dialog (update hub with version,
open Alby Go in-app, install extension) keyed by kind or title
- Use preview stories when the stories API request fails
- Pass hub version from useInfo into the update link
Made-with: Cursor
* feat(stories): polish modal, drop preview fallback
- Widen modal and put video edge-to-edge with overlay close button
- Drop verbose header and 'Watch on YouTube' button
- Remove previewStories fallback so widget hides until upstream API ships
- Tighten title line-height
* feat(stories): render cta from API instead of mapping by kind
Move CTA copy and URLs into the API response. Hub renders story.cta
directly, so adding new story types no longer requires a hub release.
* chore(csp): allow cdn.getalby-assets.com in img-src
* feat(stories): bump avatar size and add ring gap
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(stories): post-review cleanups
- Use react-router Link for in-tab CTA instead of plain <a>.
- Drop redundant www.youtube.com from frame-src (embeds always go through nocookie).
- Tighten stories endpoint status check from >= 300 to >= 400.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(stories): address CodeRabbit feedback
- Switch StoriesWidget to useSWR + swrFetcher (project convention).
- Guard story iframe with isYouTubeUrl so non-YouTube urls never embed.
- Wrap GetStories errors with fmt.Errorf("...: %w", err).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(stories): drop isYouTubeUrl guard
Stories are curated and always YouTube; the runtime check was
redundant. CSP frame-src still constrains the iframe source.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(stories): drop getYouTubeEmbedUrl, embed videoUrl as-is
The Alby API now sends canonical youtube-nocookie embed URLs with
autoplay/rel query strings (getAlby/getalby.com#2568), so the
runtime normalization is no longer needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(stories): use w-16 instead of arbitrary w-[73px]
Match the avatar's size token; no magic numbers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(stories): take videoId from API and assemble embed url locally
Pairs with getAlby/getalby.com#2568. The API now sends just the
YouTube videoId; the hub composes the canonical embed URL so the
domain/query-string format stays in one place.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(stories): treat 3xx as non-success, matching file convention
The other status checks in alby_oauth_service.go all use >= 300;
align GetStories so redirects don't slip through.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(stories): move viewed-storage key to constants, widen story button
Address review feedback:
- Centralize the localStorage key for viewed stories in localStorageKeys
alongside the other keys.
- Widen the story button from w-16 to w-20 so "Alby Extension" fits on
one line and matches the other titles.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(stories): bump story button to w-24 so titles fit one line
w-20 still wrapped "Alby Extension"; w-24 fits all current titles
without truncation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Revert "chore(stories): bump story button to w-24 so titles fit one line"
This reverts commit 0b47438f50.
* chore(stories): split title words onto separate lines
Reserve two lines for every story title so avatars align regardless of
title length.
* chore(stories): align homeStoriesViewed key with sibling pattern
* chore(stories): fit titles on one line
* chore(stories): widen story button to w-21 for one-line titles
---------
Co-authored-by: René Aaron <rene@twentyuno.net>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
105 lines
3.1 KiB
TypeScript
105 lines
3.1 KiB
TypeScript
import tailwindcss from "@tailwindcss/vite";
|
|
import react from "@vitejs/plugin-react-swc";
|
|
import path from "path";
|
|
import { defineConfig, Plugin } from "vite";
|
|
import { VitePWA } from "vite-plugin-pwa";
|
|
import tsconfigPaths from "vite-tsconfig-paths";
|
|
|
|
export default defineConfig(({ command }) => ({
|
|
plugins: [
|
|
react(),
|
|
tailwindcss(),
|
|
tsconfigPaths(),
|
|
VitePWA({
|
|
registerType: "autoUpdate",
|
|
// disable service worker - Alby Hub cannot be used offline (and also breaks oauth callback)
|
|
injectRegister: false,
|
|
includeAssets: [
|
|
"favicon.ico",
|
|
"robots.txt",
|
|
"icon-192.png",
|
|
"icon-512.png",
|
|
],
|
|
useCredentials: true, // because the manifest might sit behind authentication
|
|
manifest: {
|
|
short_name: "Alby Hub",
|
|
name: "Alby Hub",
|
|
icons: [
|
|
{
|
|
src: "icon-192.png",
|
|
sizes: "192x192",
|
|
type: "image/png",
|
|
},
|
|
{
|
|
src: "icon-512.png",
|
|
sizes: "512x512",
|
|
type: "image/png",
|
|
},
|
|
{
|
|
src: "icon-1024.png",
|
|
sizes: "1024x1024",
|
|
type: "image/png",
|
|
},
|
|
],
|
|
start_url: ".",
|
|
display: "standalone",
|
|
theme_color: "#000000",
|
|
background_color: "#ffffff",
|
|
},
|
|
workbox: {
|
|
maximumFileSizeToCacheInBytes: 3000000, // 3MB
|
|
},
|
|
}),
|
|
...(command === "serve" ? [insertDevCSPPlugin] : []),
|
|
],
|
|
server: {
|
|
port: process.env.VITE_PORT ? parseInt(process.env.VITE_PORT) : undefined,
|
|
proxy: {
|
|
"/api": {
|
|
target: process.env.VITE_API_URL || "http://localhost:8080",
|
|
secure: false,
|
|
},
|
|
"/logout": {
|
|
target: process.env.VITE_API_URL || "http://localhost:8080",
|
|
secure: false,
|
|
},
|
|
},
|
|
},
|
|
resolve: {
|
|
alias: {
|
|
src: path.resolve(__dirname, "./src"),
|
|
wailsjs: path.resolve(__dirname, "./wailsjs"),
|
|
// used to refrence public assets when importing images or other
|
|
// assets from the public folder
|
|
// this is necessary to inject the base path during build
|
|
public: "",
|
|
},
|
|
},
|
|
build: {
|
|
assetsInlineLimit: 0,
|
|
},
|
|
html:
|
|
command === "serve"
|
|
? {
|
|
cspNonce: "DEVELOPMENT",
|
|
}
|
|
: undefined,
|
|
base: process.env.BASE_PATH || "/",
|
|
}));
|
|
|
|
const DEVELOPMENT_NONCE = "'nonce-DEVELOPMENT'";
|
|
|
|
const insertDevCSPPlugin: Plugin = {
|
|
name: "dev-csp",
|
|
transformIndexHtml: {
|
|
order: "pre",
|
|
handler: (html) => {
|
|
return html.replace(
|
|
"<head>",
|
|
`<head>
|
|
<!-- DEV-ONLY CSP - when making changes here, also update the CSP header in http_service.go (without the nonce!) -->
|
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self' ${DEVELOPMENT_NONCE}; img-src 'self' https://uploads.getalby-assets.com https://cdn.getalby-assets.com https://getalby.com; connect-src 'self' https://api.getalby.com https://getalby.com https://zapplanner.albylabs.com wss://relay.getalby.com wss://relay2.getalby.com; frame-src https://embed.bitrefill.com https://www.youtube-nocookie.com" />`
|
|
);
|
|
},
|
|
},
|
|
};
|