mirror of
https://github.com/ld3z/new-manga.git
synced 2026-11-09 20:43:45 -07:00
add annoucement banner and bump version
This commit is contained in:
parent
17ceea25d9
commit
71c775f70e
6 changed files with 423 additions and 1942 deletions
2181
package-lock.json
generated
2181
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@ldez/manga",
|
"name": "@ldez/manga",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.0.1",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
|
|
|
||||||
111
src/components/AnnouncementBanner.astro
Normal file
111
src/components/AnnouncementBanner.astro
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
---
|
||||||
|
import type { Announcement } from '../lib/types';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
announcement: Announcement;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { announcement } = Astro.props;
|
||||||
|
|
||||||
|
const bgColorClass = {
|
||||||
|
info: 'bg-[rgb(var(--accent))] text-[rgb(var(--accent-text))]',
|
||||||
|
warning: 'bg-yellow-500 text-white',
|
||||||
|
success: 'bg-emerald-500 text-white'
|
||||||
|
}[announcement.type];
|
||||||
|
|
||||||
|
// Create a simple hash of the announcement content
|
||||||
|
const announcementHash = btoa(JSON.stringify({
|
||||||
|
message: announcement.message,
|
||||||
|
type: announcement.type,
|
||||||
|
link: announcement.link
|
||||||
|
}));
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class={`announcement-banner hidden w-full ${bgColorClass} px-6 py-4 shadow-lg`}>
|
||||||
|
<div class="container mx-auto flex items-center justify-between">
|
||||||
|
<div class="flex items-center gap-3 text-lg">
|
||||||
|
{announcement.type === 'info' && (
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
{announcement.type === 'warning' && (
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
{announcement.type === 'success' && (
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<span class="font-medium">{announcement.message}</span>
|
||||||
|
|
||||||
|
{announcement.link && (
|
||||||
|
<a
|
||||||
|
href={announcement.link.url}
|
||||||
|
class="underline hover:opacity-80 transition-opacity font-semibold ml-2"
|
||||||
|
>
|
||||||
|
{announcement.link.text} →
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{announcement.dismissible && (
|
||||||
|
<button
|
||||||
|
class="dismiss-announcement p-2 hover:bg-black/10 rounded-full transition-colors"
|
||||||
|
aria-label="Dismiss announcement"
|
||||||
|
>
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script define:vars={{ dismissible: announcement.dismissible, announcementHash }}>
|
||||||
|
const banner = document.querySelector('.announcement-banner');
|
||||||
|
const dismissBtn = document.querySelector('.dismiss-announcement');
|
||||||
|
const storageKey = `announcement-dismissed-${announcementHash}`;
|
||||||
|
|
||||||
|
// Check if announcement should be shown
|
||||||
|
function checkVisibility() {
|
||||||
|
// Only check localStorage if the banner is dismissible
|
||||||
|
const isDismissed = dismissible ?
|
||||||
|
localStorage.getItem(storageKey) === 'true' :
|
||||||
|
false;
|
||||||
|
|
||||||
|
if (!isDismissed && banner) {
|
||||||
|
banner.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run after DOM is loaded
|
||||||
|
document.addEventListener('DOMContentLoaded', checkVisibility);
|
||||||
|
|
||||||
|
dismissBtn?.addEventListener('click', () => {
|
||||||
|
if (dismissible) {
|
||||||
|
banner?.classList.add('hidden');
|
||||||
|
localStorage.setItem(storageKey, 'true');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.announcement-banner {
|
||||||
|
animation: slideDown 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideDown {
|
||||||
|
from {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import ThemeToggle from '../components/ThemeToggle.astro';
|
import ThemeToggle from '../components/ThemeToggle.astro';
|
||||||
import Analytics from '@vercel/analytics/astro';
|
import Analytics from '@vercel/analytics/astro';
|
||||||
import { getRandomBackground } from '../config/backgrounds';
|
import { getRandomBackground } from '../config/backgrounds';
|
||||||
|
import AnnouncementBanner from '../components/AnnouncementBanner.astro';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -16,6 +17,17 @@ const {
|
||||||
const background = getRandomBackground();
|
const background = getRandomBackground();
|
||||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site ?? 'https://comick-rss.vercel.app').toString();
|
const canonicalURL = new URL(Astro.url.pathname, Astro.site ?? 'https://comick-rss.vercel.app').toString();
|
||||||
const isCreditsPage = Astro.url.pathname === '/credits';
|
const isCreditsPage = Astro.url.pathname === '/credits';
|
||||||
|
|
||||||
|
// Add the announcement configuration
|
||||||
|
const announcement = {
|
||||||
|
message: "You can add your own custom feeds!",
|
||||||
|
type: "info" as const,
|
||||||
|
dismissible: true,
|
||||||
|
link: {
|
||||||
|
text: "Try it now",
|
||||||
|
url: "/custom"
|
||||||
|
}
|
||||||
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
|
|
@ -50,6 +62,9 @@ const isCreditsPage = Astro.url.pathname === '/credits';
|
||||||
id="body-element"
|
id="body-element"
|
||||||
style={`--bg-url: url('${background.url}')`}
|
style={`--bg-url: url('${background.url}')`}
|
||||||
>
|
>
|
||||||
|
<!-- Add the banner right after body opening tag -->
|
||||||
|
<AnnouncementBanner announcement={announcement} />
|
||||||
|
|
||||||
{!isCreditsPage && (
|
{!isCreditsPage && (
|
||||||
<div class="fixed bottom-4 sm:bottom-6 right-4 sm:right-6 z-50">
|
<div class="fixed bottom-4 sm:bottom-6 right-4 sm:right-6 z-50">
|
||||||
<div class="relative" id="settings-dropdown">
|
<div class="relative" id="settings-dropdown">
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,13 @@ export interface ComicCover {
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Announcement {
|
||||||
|
message: string;
|
||||||
|
type: 'info' | 'warning' | 'success';
|
||||||
|
dismissible?: boolean;
|
||||||
|
link?: {
|
||||||
|
text: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -7,16 +7,38 @@ const description = "Create a custom RSS feed for your favorite comics";
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title={title} description={description}>
|
<Layout title={title} description={description}>
|
||||||
<main class="mx-auto px-3 sm:px-4 lg:px-8 max-w-[800px] py-4 sm:py-8">
|
<div class="container mx-auto px-4 py-8">
|
||||||
<h1 class="text-2xl sm:text-3xl lg:text-4xl font-bold text-center mb-4 sm:mb-8">Custom RSS Feed</h1>
|
<!-- Add back button -->
|
||||||
|
<a
|
||||||
|
href="/en/sfw/all"
|
||||||
|
class="inline-flex items-center gap-2 mb-6 px-4 py-2 bg-secondary hover:bg-hover rounded-md transition-colors font-medium"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-5 h-5"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M19 12H5M12 19l-7-7 7-7"/>
|
||||||
|
</svg>
|
||||||
|
Back to Comics
|
||||||
|
</a>
|
||||||
|
|
||||||
<div class="bg-secondary/50 p-3 sm:p-6 rounded-lg shadow-lg">
|
<main class="mx-auto px-3 sm:px-4 lg:px-8 max-w-[800px] py-4 sm:py-8">
|
||||||
<SlugInput />
|
<h1 class="text-2xl sm:text-3xl lg:text-4xl font-bold text-center mb-4 sm:mb-8">Custom RSS Feed</h1>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-4 sm:mt-8 text-center text-primary/60 text-sm sm:text-base">
|
<div class="bg-secondary/50 p-3 sm:p-6 rounded-lg shadow-lg">
|
||||||
<p>Search for your favorite comics using the search box above, or add their slugs manually.</p>
|
<SlugInput />
|
||||||
<p class="mt-2">Manual example: For <a href="https://comick.io/comic/01-one-piece" class="text-accent hover:underline">https://comick.io/comic/01-one-piece</a>, the slug is "01-one-piece"</p>
|
</div>
|
||||||
</div>
|
|
||||||
</main>
|
<div class="mt-4 sm:mt-8 text-center text-primary/60 text-sm sm:text-base">
|
||||||
|
<p>Search for your favorite comics using the search box above, or add their slugs manually.</p>
|
||||||
|
<p class="mt-2">Manual example: For <a href="https://comick.io/comic/01-one-piece" class="text-accent hover:underline">https://comick.io/comic/01-one-piece</a>, the slug is "01-one-piece"</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue