Compare commits

...

8 commits

Author SHA1 Message Date
Korbs
23bf61f239 update 2024-11-01 21:38:32 -04:00
Korbs
c793d5940f Update README 2024-11-01 21:38:28 -04:00
Korbs
cbc06d83ed Update TODO 2024-11-01 21:38:22 -04:00
Korbs
c930a3bbf1 Don't auto reload during testing 2024-11-01 21:38:16 -04:00
Korbs
eb376151f2 Make all links in the demo white 2024-11-01 21:38:04 -04:00
Korbs
9bcbd72237 Fix fullscreen button updates, add "Play again?" option when video ends 2024-11-01 21:37:51 -04:00
Korbs
ce4007160a Swap out fast forward/backward button icons, "15" was never accurate 2024-11-01 21:37:25 -04:00
Korbs
8c67818689 Adjust video fill, add transitions to controls 2024-11-01 21:36:48 -04:00
11 changed files with 127 additions and 21 deletions

View file

@ -1,8 +1,24 @@
# Zorn <br/>
<h3 align="center">
<img src="https://md.sudovanilla.org/images/Zorn%20Player.png" alt="Logo" height="64"/>
</h3>
<br/>
<div align="center">
Tailored for MinPluto, customizable for you.
<br />
<br />
<br />
</div>
![Zorn using Milieu Mode](https://md.sudovanilla.org/images/Screenshot%20from%202024-08-16%2016-16-48.png) ![Zorn using Milieu Mode](https://md.sudovanilla.org/images/Screenshot%20from%202024-08-16%2016-16-48.png)
A custom video player tailored for MinPluto. <div align="center">
<a href="https://codeberg.org/MinPluto/Zorn/" target="_blank"> <img src="https://img.shields.io/badge/Codeberg-blue"> </a>
<a href="https://npm.sudovanilla.org/-/web/detail/@minpluto/zorn" target="_blank"> <img src="https://img.shields.io/badge/SudoVanilla%20Packages-purple"> </a>
<a href="https://www.npmjs.com/package/@minpluto/zorn" target="_blank"> <img src="https://img.shields.io/badge/NPM-red"> </a>
</div>
## Installation ## Installation
To install Zorn for your Astro project, run the following: To install Zorn for your Astro project, run the following:
@ -79,6 +95,7 @@ Local:
```jsx ```jsx
<Zorn Video="/media/video.webm"/> <Zorn Video="/media/video.webm"/>
``` ```
> [!NOTE]
> Use the `/public/` folder in your Astro project. > Use the `/public/` folder in your Astro project.
Remote: Remote:
@ -94,6 +111,7 @@ Local:
```jsx ```jsx
<Zorn Audio="/media/audio.ogg"/> <Zorn Audio="/media/audio.ogg"/>
``` ```
> [!NOTE]
> Use the `/public/` folder in your Astro project. > Use the `/public/` folder in your Astro project.
Remote: Remote:
@ -127,7 +145,7 @@ Then, as a slot, add your menu like so:
</div> </div>
</Zorn> </Zorn>
``` ```
> [!NOTE]
> Use `OpenZornMenu()` as the open menu function. You can use the scripts provided in `/test/` of this package. > Use `OpenZornMenu()` as the open menu function. You can use the scripts provided in `/test/` of this package.
You can also add sub-menus with additional scripts you'll need to add: You can also add sub-menus with additional scripts you'll need to add:
@ -203,9 +221,10 @@ Just add the `Live` option with an `.m3u8` source.
| **Other Browsers**| | **Other Browsers**|
| FOSS Browser | ✅ | ✅ | ❌ | ✅ | | FOSS Browser | ✅ | ✅ | ❌ | ✅ |
| Ladybird | 🔘 | 🔘 | 🔘 | 🔘 | | Ladybird | 🔘 | 🔘 | 🔘 | 🔘 |
| Pale Moon | 🔘 | 🔘 | 🔘 | 🔘 |
| **WebKit Browsers**| | **WebKit Browsers**|
| Safari | 🔘 | 🔘 | 🔘 | 🔘 | | Safari | 🔘 | 🔘 | 🔘 | 🔘 |
| GNOME Web | ✅ | ✅ | ✅*N| ✅ | | GNOME Web | ✅ | ✅ | ✅ | ✅ |
| DuckDuckGo | 🔘 | 🔘 | 🔘 | 🔘 | | DuckDuckGo | 🔘 | 🔘 | 🔘 | 🔘 |
| **Electron Browsers**| | **Electron Browsers**|
| Min | 🔘 | ✅ | ✅ | ✅ | | Min | 🔘 | ✅ | ✅ | ✅ |
@ -215,9 +234,11 @@ Just add the `Live` option with an `.m3u8` source.
| Google Chrome | ✅ | ✅ | ✅ | ✅ | | Google Chrome | ✅ | ✅ | ✅ | ✅ |
| Microsoft Edge | ✅ | ✅ | ✅ | ✅ | | Microsoft Edge | ✅ | ✅ | ✅ | ✅ |
| Opera | ✅ | ✅ | ✅ | ✅ | | Opera | ✅ | ✅ | ✅ | ✅ |
| Vanadium | 🔘 | 🔘 | 🔘 | 🔘 |
| Vivaldi | ✅ | ✅ | ✅ | ✅ | | Vivaldi | ✅ | ✅ | ✅ | ✅ |
| Yandex | ✅ | ❌ | ✅ | ❌ | | Yandex | ✅ | ✅ | ✅ | ✅ |
| **Firefox Browsers**| | **Firefox Browsers**|
| Basilisk | 🔘 | 🔘 | 🔘 | 🔘 |
| Falkon | ✅ | ✅ | ✅ | ✅ | | Falkon | ✅ | ✅ | ✅ | ✅ |
| Firefox | ✅ | ✅ | ✅ | ✅ | | Firefox | ✅ | ✅ | ✅ | ✅ |
| Floorp | ✅ | ✅ | ✅ | ✅ | | Floorp | ✅ | ✅ | ✅ | ✅ |
@ -227,15 +248,12 @@ Just add the `Live` option with an `.m3u8` source.
| Mullvad | ✅ | ✅ | ✅ | ✅ | | Mullvad | ✅ | ✅ | ✅ | ✅ |
| Tor | 🔘 | 🔘 | 🔘 | 🔘 | | Tor | 🔘 | 🔘 | 🔘 | 🔘 |
| Waterfox | ✅ | ✅ | ✅ | ✅ | | Waterfox | ✅ | ✅ | ✅ | ✅ |
| Zen | ✅ | ✅ | ✅ | ✅ |
| **Outdated Browsers**| | **Outdated Browsers**|
| Internet Explorer | 🔘 | 🔘 | 🔘 | 🔘 | | Internet Explorer | 🔘 | 🔘 | 🔘 | 🔘 |
> All browsers are tested as-is out of box. Some functions with ❌ can probably work if you tweak the settings or interact with a built-in extension. > [!NOTE]
> All browsers are tested as-is out of box. Some functions with ❌ can probably work if you tweak the settings or interact with a built-in extension. 🔘 means it's not been tested yet.
> IC: By default, GNU/IceCat has the LibreJS extension installed, it will block all JS by default if it does not provide a valid license. Examples for settings menu do not provide one nor one is shown in the test version. > [!NOTE]
> IC: By default, GNU/IceCat has the LibreJS extension installed, it will block all JS by default if it does not provide a valid license. Examples for settings menu do not provide one nor one is shown in the test version.
> N: The backdrop blur does not work. This should not affect the function of the video player.
## To Do
- [x] Support HLS (HTTP Live Streaming)
- [ ] Touch gestures for mobile

15
TODO.md Normal file
View file

@ -0,0 +1,15 @@
- [x] Support HLS (HTTP Live Streaming)
- [ ] Subtitles ([`textTracks`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/textTracks))
- [ ] Multi-Video Tracks ([`videoTracks`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/videoTracks))
- [ ] Multi-Audio Tracks ([`audioTracks`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/audioTracks))
- [ ] Playback Rate ([`playbackRate`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/playbackRate))
- [ ] Add Picture-in-Picture button
- [ ] Volume Controller
- [ ] Mobile Gestures
- [ ] Cast Support
- [ ] Allow for multiple players on one page
- [ ] Modes
- [ ] Audio-Only
- [ ] Pop-Up
- [ ] Presentation
- [ ] Inline

BIN
bun.lockb Executable file

Binary file not shown.

View file

@ -1,7 +1,7 @@
{ {
"name": "@minpluto/zorn", "name": "@minpluto/zorn",
"author": "SudoVanilla", "author": "SudoVanilla",
"description": "A video player tailored for MinPluto", "description": "Tailored for MinPluto, customizable for you.",
"repository": { "repository": {
"url": "https://codeberg.org/MinPluto/Zorn" "url": "https://codeberg.org/MinPluto/Zorn"
}, },
@ -14,7 +14,7 @@
"live-streaming" "live-streaming"
], ],
"type": "module", "type": "module",
"version": "0.4.5", "version": "0.4.52",
"exports": { "exports": {
".": "./index.ts" ".": "./index.ts"
}, },
@ -33,4 +33,4 @@
"npm:publish": "npm publish --registry https://npm.sudovanilla.org/", "npm:publish": "npm publish --registry https://npm.sudovanilla.org/",
"test": "cd test/ && bun start" "test": "cd test/ && bun start"
} }
} }

View file

@ -8,10 +8,11 @@ const {
// Icons // Icons
import { import {
Backward15Seconds, RewindSolid,
Enlarge, Enlarge,
Forward15Seconds, ForwardSolid,
PlaySolid, PlaySolid,
Refresh
} from "@iconoir/vue"; } from "@iconoir/vue";
--- ---
@ -20,13 +21,14 @@ import {
<p>{Title}</p> <p>{Title}</p>
</div> </div>
<div class="vc-bottom"> <div class="vc-bottom">
<button style="display: none" id="vc-playagain"><Refresh /></button>
<div class="vc-start"> <div class="vc-start">
<button id="vc-playpause"><PlaySolid /></button> <button id="vc-playpause"><PlaySolid /></button>
{Live ? {Live ?
null null
: :
<button id="vc-backwards"><Backward15Seconds /></button> <button id="vc-backwards"><RewindSolid /></button>
<button id="vc-forwards"><Forward15Seconds /></button> <button id="vc-forwards"><ForwardSolid /></button>
} }
</div> </div>
<div class="vc-center"> <div class="vc-center">
@ -56,6 +58,10 @@ import {
</div> </div>
</div> </div>
<!-- HLS Script -->
<!-- Required to support live streaming -->
<!-- Script is not loaded if the video player is not set for a stream -->
{Live ? {Live ?
<script is:inline> <script is:inline>
// Original Source: https://hlsjs.video-dev.org/dist/hls.js // Original Source: https://hlsjs.video-dev.org/dist/hls.js

View file

@ -34,6 +34,11 @@ var pause_solid_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24p
var PlayIcon = play_solid_default; var PlayIcon = play_solid_default;
var PauseIcon = pause_solid_default; var PauseIcon = pause_solid_default;
var fullscreen_solid_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff"><path d="M15 9L20 4M20 4V8M20 4H16" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M9 15L4 20M4 20V16M4 20H8" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
var exit_fullscreen_solid_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff"><path d="M4 20L9 15M9 15V19M9 15H5" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20 4L15 9M15 9V5M15 9H19" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'
var FullscreenIcon = fullscreen_solid_default
var ExitFullscreenIcon = exit_fullscreen_solid_default
// Fullscreen // Fullscreen
function Fullscreen() { function Fullscreen() {
const Button_Fullscreen = document.getElementById("vc-fullscreen"); const Button_Fullscreen = document.getElementById("vc-fullscreen");
@ -67,13 +72,16 @@ function Fullscreen() {
document.querySelector('.video-container .video-controls').style.height = '100%' document.querySelector('.video-container .video-controls').style.height = '100%'
VideoContainer.requestFullscreen(); VideoContainer.requestFullscreen();
} }
Update_FullscreenButton()
} }
Button_Fullscreen.onclick = Toggle_Fullscreen; Button_Fullscreen.onclick = Toggle_Fullscreen;
function Update_FullscreenButton() { function Update_FullscreenButton() {
if (document.fullscreenElement) { if (document.fullscreenElement) {
Button_Fullscreen.setAttribute("data-title", "Exit full screen (f)"); Button_Fullscreen.setAttribute("data-title", "Exit full screen (f)");
Button_Fullscreen.innerHTML = `${FullscreenIcon}`;
} else { } else {
Button_Fullscreen.setAttribute("data-title", "Full screen (f)"); Button_Fullscreen.setAttribute("data-title", "Full screen (f)");
Button_Fullscreen.innerHTML = `${ExitFullscreenIcon}`;
} }
} }
Player.addEventListener("dblclick", () => { Player.addEventListener("dblclick", () => {
@ -82,6 +90,17 @@ function Fullscreen() {
}); });
} }
function Update_PlayPauseButton() {
if (Player.paused) {
Button_PlayPause.setAttribute("data-title", "Play (K)");
Button_PlayPause.innerHTML = `${PlayIcon}`;
} else {
Button_PlayPause.setAttribute("data-title", "Pause (K)");
Button_PlayPause.innerHTML = `${PauseIcon}`;
}
}
// Play/Pause // Play/Pause
function PlayPause() { function PlayPause() {
const Button_PlayPause = document.querySelector(".video-controls #vc-playpause"); const Button_PlayPause = document.querySelector(".video-controls #vc-playpause");
@ -227,10 +246,35 @@ function KeyboardShortcuts(events) {
document.addEventListener("keyup", keyboardShortcuts); document.addEventListener("keyup", keyboardShortcuts);
} }
// If Media Ends, fade main controls and show a "Replay" button
function PlayAgain() {
Player.onended = (event) => {
document.querySelector('.vc-start').style.opacity = '0'
document.querySelector('.vc-start').style.pointerEvents = 'none'
document.querySelector('.vc-center').style.opacity = '0'
document.querySelector('.vc-center').style.pointerEvents = 'none'
document.querySelector('#vc-playagain').style.display = 'inherit'
}
document.querySelector('#vc-playagain').onclick = PlayItAgain
}
function PlayItAgain() {
document.querySelector('.vc-start').style.opacity = '1'
document.querySelector('.vc-start').style.pointerEvents = 'all'
document.querySelector('.vc-center').style.opacity = '1'
document.querySelector('.vc-center').style.pointerEvents = 'all'
document.querySelector('#vc-playagain').style.display = 'none'
Player.pause();
Player.currentTime = '0';
Player.play();
}
// Init All Functions // Init All Functions
AutoToggleControls() AutoToggleControls()
Fullscreen() Fullscreen()
KeyboardShortcuts() KeyboardShortcuts()
PlayPause() PlayPause()
SkipAround() SkipAround()
PlayAgain()
</script> </script>

View file

@ -9,6 +9,8 @@
} }
video { video {
width: 100%; width: 100%;
height: 100%;
object-fit: contain;
z-index: 1; z-index: 1;
} }
canvas { canvas {
@ -66,6 +68,10 @@
align-items: center; align-items: center;
gap: 6px; gap: 6px;
} }
.vc-start,
.vc-center {
transition: 0.3s opacity;
}
.vc-center { .vc-center {
width: calc(100% - 220px); width: calc(100% - 220px);
display: flex; display: flex;
@ -192,6 +198,7 @@
gap: 6px; gap: 6px;
padding: 4px; padding: 4px;
backdrop-filter: blur(24px) contrast(0.8) brightness(0.8); backdrop-filter: blur(24px) contrast(0.8) brightness(0.8);
-webkit-backdrop-filter: blur(24px) contrast(0.8) brightness(0.8);
hr { hr {
margin: 0px; margin: 0px;
width: 100%; width: 100%;

View file

@ -1,4 +1,11 @@
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
import vue from '@astrojs/vue'; import vue from '@astrojs/vue';
export default defineConfig({integrations: [vue()]}); export default defineConfig({
vite: {
server: {
hmr: false
}
},
integrations: [vue()]
});

View file

@ -50,6 +50,9 @@ body {
background: #010101; background: #010101;
color: white; color: white;
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
a {
color: white;
}
} }
</style> </style>

View file

@ -13,6 +13,9 @@ body {
background: #010101; background: #010101;
color: white; color: white;
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
a {
color: white;
}
} }
</style> </style>

View file

@ -27,5 +27,8 @@ body {
background: #010101; background: #010101;
color: white; color: white;
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
a {
color: white;
}
} }
</style> </style>