From f9373bbe1288977bc4438a384cf2f02dfeff4264 Mon Sep 17 00:00:00 2001 From: huzaifaasim017 Date: Fri, 23 Oct 2026 00:48:58 +0500 Subject: [PATCH] Polish site motion, footer, and external links --- scripts/capture-screenshots.sh | 4 ++- web/README.md | 2 +- web/assets/external-link.svg | 5 +++ web/assets/screenshots/empty-v1-coast.png | Bin 17205 -> 0 bytes web/download.html | 11 +++--- web/index.html | 11 +++--- web/motion.js | 39 ++++++++++++++++++++++ web/script.js | 3 +- web/scripts/build.mjs | 1 + web/scripts/check.mjs | 4 ++- web/styles.css | 34 ++++++++++--------- 11 files changed, 84 insertions(+), 30 deletions(-) create mode 100644 web/assets/external-link.svg delete mode 100644 web/assets/screenshots/empty-v1-coast.png create mode 100644 web/motion.js diff --git a/scripts/capture-screenshots.sh b/scripts/capture-screenshots.sh index 5c6d2bd..35512a6 100755 --- a/scripts/capture-screenshots.sh +++ b/scripts/capture-screenshots.sh @@ -20,5 +20,7 @@ linuxplayer --capture-options "$root/docs/screenshots/options-v1-coast.png" "$vi linuxplayer --capture-hidden "$root/docs/screenshots/hidden-v1-coast.png" "$video" linuxplayer --capture-mini "$root/docs/screenshots/mini-player-v1-coast.png" "$video" linuxplayer --capture-ui "$root/docs/screenshots/empty-v1-coast.png" -cp "$root"/docs/screenshots/*-v1-coast.png "$root/web/assets/screenshots/" +for view in playback options hidden mini-player; do + cp "$root/docs/screenshots/$view-v1-coast.png" "$root/web/assets/screenshots/" +done echo 'Captured the current desktop interface for the repository and website.' diff --git a/web/README.md b/web/README.md index faef0ea..6a31a5c 100644 --- a/web/README.md +++ b/web/README.md @@ -27,7 +27,7 @@ The main download uses GitHub's stable latest-release URL for `linuxplayer_amd64 ## Refresh the screenshots -Install the current build, open a graphical desktop session, and run `scripts/capture-screenshots.sh` from the repository root. The script turns the site's generated coastal frame into a short local sample video with FFmpeg, then uses LinuxPlayer's built-in capture commands to write the real playback, options, locked, mini-player, and start-screen views to both `docs/screenshots/` and `web/assets/screenshots/`. Review each capture before publishing. The `*-v1-coast.png` filenames replace the earlier gradient captures and prevent stale browser image caches. +Install the current build, open a graphical desktop session, and run `scripts/capture-screenshots.sh` from the repository root. The script turns the site's generated coastal frame into a short local sample video with FFmpeg, then uses LinuxPlayer's built-in capture commands to write playback, options, locked, and mini-player views to both `docs/screenshots/` and `web/assets/screenshots/`. The start-screen capture stays in `docs/screenshots/` for documentation. Review each capture before publishing. The `*-v1-coast.png` filenames replace the earlier gradient captures and prevent stale browser image caches. ## Content and attribution diff --git a/web/assets/external-link.svg b/web/assets/external-link.svg new file mode 100644 index 0000000..e645f45 --- /dev/null +++ b/web/assets/external-link.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/web/assets/screenshots/empty-v1-coast.png b/web/assets/screenshots/empty-v1-coast.png deleted file mode 100644 index 16f76a0869b07585330443cf4321b012ef70d228..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17205 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 diff --git a/web/download.html b/web/download.html index a4c3f4e..a89927c 100644 --- a/web/download.html +++ b/web/download.html @@ -15,6 +15,7 @@ Download LinuxPlayer — Latest Linux packages + @@ -28,14 +29,14 @@
← Home

Download LinuxPlayer.

- +
-

Install with terminal.

Automatically selects amd64 or ARM64 and checks the download.

Read the installer source ↗
Copy and run
curl -fsSLo /tmp/linuxplayer-install.sh \
+    

Install with terminal.

Automatically selects amd64 or ARM64 and checks the download.

Read the installer source
Copy and run
curl -fsSLo /tmp/linuxplayer-install.sh \
   https://github.com/teamkrope/linuxplayer/releases/latest/download/install.sh
-bash /tmp/linuxplayer-install.sh
Review the script before running it.Release notes ↗
-
+bash /tmp/linuxplayer-install.sh
Review the script before running it.Release notes
+
- + diff --git a/web/index.html b/web/index.html index 991a9a6..1a87322 100644 --- a/web/index.html +++ b/web/index.html @@ -21,6 +21,7 @@ + @@ -32,7 +33,7 @@
-

Video playback,
refined for Linux.

+

Video playback,
refined for Linux.

Actual LinuxPlayer 1.0 window playing a local video with controls visible
@@ -56,15 +57,15 @@
Source video16:9 · unchanged
Illustrative widescreen frame showing a person on a coastal overlook and a lighthouse
Canvas preview16:9 · Fit
Same illustrative frame inside the selected canvas
Canvas ratio
Video in canvas
-

Preview only. Your video stays untouched. Feature guide ↗

+

Preview only. Your video stays untouched. Feature guide

-

See the player.

+

See the player.

Install LinuxPlayer.

64-bit x86 .deb package

Terminal install
curl -fsSLo /tmp/linuxplayer-install.sh \
   https://github.com/teamkrope/linuxplayer/releases/latest/download/install.sh
 bash /tmp/linuxplayer-install.sh
-
+

Questions.

How do I see only the video?

Playback hides the controls automatically. Click the lock in the header or press H to keep them hidden. Move the pointer to reveal a temporary unlock button, or press H again.

What video formats work?

LinuxPlayer uses the system's libmpv and FFmpeg libraries. Format support depends on the codecs available on your distribution.

Can I make it my default player?

Yes. Choose "Make default video player" on the opening screen or in More options. The app updates supported file associations for your user account after you click.

Does canvas preview export a new video?

No. Ratios show how a video fits or crops inside a canvas during playback. Your original file stays unchanged.

Where can I get help?

Email contact@teamkrope.com, see the support guide or ask in GitHub Discussions.

- + diff --git a/web/motion.js b/web/motion.js new file mode 100644 index 0000000..4a65dd8 --- /dev/null +++ b/web/motion.js @@ -0,0 +1,39 @@ +(() => { + document.querySelectorAll('a[target="_blank"]').forEach(link => { + if (!link.hasAttribute('aria-label')) { + link.setAttribute('aria-label', `${link.textContent.trim()} (opens in new tab)`); + } + }); + + if (!('IntersectionObserver' in window) || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; + + const targets = document.querySelectorAll([ + 'main .hero-copy', 'main .hero-shot', 'main .section-head', + 'main .feature-shot', 'main .feature-list article', + 'main .pip-copy', 'main .workspace-figure', 'main .ratio-demo', + 'main .gallery', 'main .download-grid > *', 'main .source-grid > *', + 'main .faq-grid > *', 'main .package-card', 'main .download-help-grid > *' + ].join(', ')); + + targets.forEach(target => { + target.classList.add('reveal'); + // The first viewport should be readable even before the observer's first paint. + if (target.getBoundingClientRect().top < window.innerHeight * 0.94) { + target.classList.add('is-visible'); + } + if (target.matches('.feature-list article')) { + const index = [...target.parentElement.children].indexOf(target); + target.style.setProperty('--reveal-delay', `${Math.min(index, 5) * 55}ms`); + } + }); + + document.documentElement.classList.add('motion-ready'); + const observer = new IntersectionObserver(entries => { + entries.forEach(entry => { + if (!entry.isIntersecting) return; + entry.target.classList.add('is-visible'); + observer.unobserve(entry.target); + }); + }, { threshold: 0.08, rootMargin: '0px 0px -6% 0px' }); + targets.forEach(target => observer.observe(target)); +})(); diff --git a/web/script.js b/web/script.js index 2d3fb01..d1856c9 100644 --- a/web/script.js +++ b/web/script.js @@ -20,8 +20,7 @@ playback: { file: 'playback-v1-coast.png', title: 'Playback', alt: 'LinuxPlayer playback interface with lock control' }, options: { file: 'options-v1-coast.png', title: 'Controls', alt: 'LinuxPlayer playback options popup' }, hidden: { file: 'hidden-v1-coast.png', title: 'Video only', alt: 'LinuxPlayer video canvas with controls locked and hidden' }, - mini: { file: 'mini-player-v1-coast.png', title: 'Mini-player', alt: 'LinuxPlayer compact mini-player shown over an illustrative workspace' }, - start: { file: 'empty-v1-coast.png', title: 'Start screen', alt: 'LinuxPlayer start screen with rounded app icon and Open video button' } + mini: { file: 'mini-player-v1-coast.png', title: 'Mini-player', alt: 'LinuxPlayer compact mini-player shown over an illustrative workspace' } }; const tabs = [...document.querySelectorAll('.gallery-tabs [role="tab"]')]; const galleryImage = document.querySelector('#gallery-image'); diff --git a/web/scripts/build.mjs b/web/scripts/build.mjs index 9b15b74..0de8228 100644 --- a/web/scripts/build.mjs +++ b/web/scripts/build.mjs @@ -20,6 +20,7 @@ await mkdir(output, { recursive: true }); await cp(path.join(root, 'assets'), path.join(output, 'assets'), { recursive: true }); await cp(path.join(root, 'styles.css'), path.join(output, 'styles.css')); await cp(path.join(root, 'script.js'), path.join(output, 'script.js')); +await cp(path.join(root, 'motion.js'), path.join(output, 'motion.js')); await cp(path.join(root, 'download.js'), path.join(output, 'download.js')); await cp(path.join(root, 'LICENSE'), path.join(output, 'LICENSE')); diff --git a/web/scripts/check.mjs b/web/scripts/check.mjs index d1c3442..082a677 100644 --- a/web/scripts/check.mjs +++ b/web/scripts/check.mjs @@ -8,13 +8,15 @@ const download = await readFile(path.join(root, 'download.html'), 'utf8'); const script = await readFile(path.join(root, 'script.js'), 'utf8'); if ([html, download].some(page => page.includes('Download for Linux'))) throw new Error('Primary download buttons must say Download'); if (!html.includes('playback-v1-coast.png') || !script.includes('options-v1-coast.png')) throw new Error('Current screenshots are not linked from the site'); +if (html.includes('Start screen') || script.includes('empty-v1-coast.png')) throw new Error('Removed gallery tab is still present'); +if (![html, download].every(page => page.includes('motion.js') && page.includes('footer-line'))) throw new Error('Shared motion or compact footer missing'); for (const text of ['LinuxPlayer', 'id="download"', 'id="features"', 'id="preview"', 'id="open-source"', 'application/ld+json', 'releases/latest/download/install.sh']) { if (!html.includes(text)) throw new Error(`Missing required site content: ${text}`); } for (const asset of ['linuxplayer_amd64.deb', 'linuxplayer_arm64.deb']) { if (!download.includes(`/releases/latest/download/${asset}`)) throw new Error(`Missing latest direct download: ${asset}`); } -for (const file of ['styles.css', 'script.js', 'download.js', 'robots.txt', 'LICENSE', 'assets/linuxplayer-bird.png', 'assets/ratio-source.webp', 'assets/screenshots/playback-v1-coast.png', 'assets/screenshots/options-v1-coast.png', 'assets/screenshots/hidden-v1-coast.png', 'assets/screenshots/mini-player-v1-coast.png', 'assets/screenshots/empty-v1-coast.png']) { +for (const file of ['styles.css', 'motion.js', 'script.js', 'download.js', 'robots.txt', 'LICENSE', 'assets/linuxplayer-bird.png', 'assets/external-link.svg', 'assets/ratio-source.webp', 'assets/screenshots/playback-v1-coast.png', 'assets/screenshots/options-v1-coast.png', 'assets/screenshots/hidden-v1-coast.png', 'assets/screenshots/mini-player-v1-coast.png']) { if (!(await stat(path.join(root, file))).isFile()) throw new Error(`Missing asset: ${file}`); } console.log('Site content and required assets verified.'); diff --git a/web/styles.css b/web/styles.css index 49e23f9..1f7e5b9 100644 --- a/web/styles.css +++ b/web/styles.css @@ -50,6 +50,10 @@ h1 em{font-style:normal;color:var(--accent)} .button-primary:hover{background:#a5eee2;color:#10201b} .button-secondary{border-color:#485250;color:var(--text);background:#172b39} .button-secondary:hover{border-color:#758781;color:var(--text);background:#222a29} +.button-ghost{border-color:#405765;color:var(--accent);background:transparent} +.button-ghost:hover{border-color:var(--accent);color:var(--text);background:#203440} +a[target="_blank"]::after{content:"";display:inline-block;width:14px;height:14px;margin-left:6px;vertical-align:-.16em;flex:none;background:currentColor;mask:url("assets/external-link.svg") center/contain no-repeat} +.button[target="_blank"]::after{margin-left:0} .hero-foot{display:inline-block;margin-top:21px;color:var(--accent);font-size:12px;font-weight:650} .hero-shot{min-width:0} .shot-frame{background:#07131d;border:1px solid #454c4b;border-radius:12px;padding:8px;box-shadow:0 28px 75px rgba(0,0,0,.38)} @@ -125,7 +129,7 @@ h1 em{font-style:normal;color:var(--accent)} .preview-section{background:#0d1b26} .gallery{border:1px solid var(--line);border-radius:10px;overflow:hidden} -.gallery-tabs{display:flex;gap:5px;overflow-x:auto;background:#172b39;padding:13px 16px;border-bottom:1px solid var(--line)} +.gallery-tabs{display:flex;justify-content:center;gap:5px;overflow-x:auto;background:#172b39;padding:13px 16px;border-bottom:1px solid var(--line)} .gallery-tabs button{background:transparent;color:#9eaaa7;border:0;border-radius:6px;padding:8px 15px;font-size:12px;font-weight:650;white-space:nowrap} .gallery-tabs button.active{background:#374740;color:#e9f5ee} .gallery-tabs button:hover:not(.active){color:var(--text);background:#2a3231} @@ -164,7 +168,7 @@ h1 em{font-style:normal;color:var(--accent)} .source-section{background:#101e29} .source-grid{display:grid;grid-template-columns:1fr .8fr;gap:110px;align-items:center} .source-grid p{max-width:560px} -.source-actions{margin-top:28px} +.source-actions{margin-top:28px;align-items:stretch} .text-link{font-size:13px;font-weight:650;color:var(--accent)} .repo-links{border-top:1px solid var(--line)} .repo-links a{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--line);padding:23px 3px;font-weight:550;font-size:15px} @@ -180,15 +184,14 @@ h1 em{font-style:normal;color:var(--accent)} .faq-list p{font-size:14px;line-height:1.65;padding:0 30px 23px 0;max-width:620px} .site-footer{background:#09131d;border-top:1px solid var(--line)} -.footer-main{display:grid;grid-template-columns:1.2fr 1fr;gap:80px;padding:74px 0} -.footer-main>div:first-child p{font-size:13px;margin-top:16px;max-width:280px} -.footer-links{display:grid;grid-template-columns:repeat(3,1fr);gap:30px} -.footer-links>div{display:flex;flex-direction:column;gap:10px} -.footer-links strong{font-size:12px;margin-bottom:6px} -.footer-links a{font-size:12px;color:var(--muted)} -.footer-links a:hover{color:var(--accent)} -.footer-bottom{border-top:1px solid var(--line);padding:19px 0 26px;display:flex;gap:25px;color:var(--quiet);font-size:11px} -.footer-bottom a{margin-left:auto} +.footer-line{min-height:80px;display:flex;align-items:center;justify-content:space-between;gap:28px} +.footer-signature{font-size:12px;color:var(--quiet);white-space:nowrap} +.footer-nav{display:flex;align-items:center;justify-content:flex-end;gap:28px;flex-wrap:wrap} +.footer-nav a{font-size:12px;color:var(--muted);white-space:nowrap} +.footer-nav a:hover{color:var(--accent)} + +.motion-ready .reveal{opacity:0;filter:blur(12px);transform:translate3d(0,18px,0) scale(.985);transition:opacity .75s cubic-bezier(.22,1,.36,1),filter .95s cubic-bezier(.22,1,.36,1),transform .95s cubic-bezier(.22,1,.36,1);transition-delay:var(--reveal-delay,0ms)} +.motion-ready .reveal.is-visible{opacity:1;filter:blur(0);transform:translate3d(0,0,0) scale(1)} .download-page-hero{padding:72px 0 84px;background:radial-gradient(circle at 80% 10%,rgba(29,107,132,.18),transparent 43%),var(--bg)} .back-link{font-size:12px;font-weight:650;color:var(--muted)} @@ -262,7 +265,9 @@ h1 em{font-style:normal;color:var(--accent)} .demo-controls{grid-column:1} .source-frame,.ratio-stage{height:310px} .gallery-image-wrap{min-height:240px;height:57vw;padding:12px} -.footer-main{grid-template-columns:1fr;gap:48px;padding:60px 0} +.gallery-tabs{justify-content:flex-start} +.footer-line{padding:24px 0;flex-wrap:wrap;gap:16px} +.footer-nav{justify-content:flex-start;gap:18px} .faq-grid{gap:20px} } @@ -287,13 +292,12 @@ h1 em{font-style:normal;color:var(--accent)} .gallery-caption{display:block;padding:16px} .gallery-caption a{display:inline-block;margin-top:14px} .install-card pre{padding:20px 16px;font-size:11px} -.footer-links{gap:15px} -.footer-bottom{flex-wrap:wrap} -.footer-bottom a{margin-left:0} +.footer-nav{width:100%;justify-content:space-between} } @media(prefers-reduced-motion:reduce){html{scroll-behavior:auto} *,*:before,*:after{transition:none!important;animation:none!important} +.motion-ready .reveal{opacity:1;filter:none;transform:none} }