updaet
0
Dockerfile
Normal file → Executable file
0
LICENSE
Normal file → Executable file
2
README.md
Normal file → Executable file
|
@ -36,7 +36,7 @@ ___
|
|||
|
||||
The package manager that you need to use with MinPluto must be [Bun](https://bun.sh/) since it appears to be the most functional option for this project. Attempting to use another package manager like Yarn or PNPM may cause issues, view [Package Managers](#package-managers) in the [Compatibility](#compatibility) section. There seems to be some issues related to both `@astrojs/vue` and `@iconoir/vue`.
|
||||
|
||||
Bun is much faster for installation time and it works standalone, meaning you don't need NodeJS installed for it to work.
|
||||
You'll still need to have [NodeJS](https://nodejs.org/en/download/package-manager) v21 or newer install in order for translations to work properly.
|
||||
|
||||
___
|
||||
|
||||
|
|
0
astro-i18next.config.mjs
Normal file → Executable file
0
astro.config.mjs
Normal file → Executable file
BIN
bun.lockb
0
docker-compose.yml
Normal file → Executable file
0
instances.json
Normal file → Executable file
2
package.json
Normal file → Executable file
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "minpluto",
|
||||
"version": "2024.07.26",
|
||||
"version": "2024.08.02",
|
||||
"description": "An open source frontend alternative to YouTube.",
|
||||
"repository": "https://sudovanilla.org/MinPluto/MinPluto",
|
||||
"author": "Korbs <korbs@sudovanilla.org>",
|
||||
|
|
0
src/components/Chip.astro
Normal file → Executable file
0
src/components/Dialog.astro
Normal file → Executable file
0
src/components/DiscoverChannel.astro
Normal file → Executable file
0
src/components/Dropdown.astro
Normal file → Executable file
0
src/components/MusicItem.astro
Normal file → Executable file
0
src/components/Search.astro
Normal file → Executable file
0
src/components/VideoItem.astro
Normal file → Executable file
0
src/components/buttons/Telemtry.astro
Normal file → Executable file
0
src/components/category/trending.astro
Normal file → Executable file
0
src/components/global/Analytics.astro
Normal file → Executable file
0
src/components/global/Footer.astro
Normal file → Executable file
10
src/components/global/Head.astro
Normal file → Executable file
|
@ -3,8 +3,7 @@
|
|||
import i18next, { t } from "i18next";
|
||||
|
||||
// Cookies
|
||||
/// Language
|
||||
//// If the user is new to the site, set English as default
|
||||
/// Set Default
|
||||
if (Astro.cookies.get("Language") === undefined) {
|
||||
Astro.cookies.set("Language", "EN", {path: "/",sameSite: 'strict'})
|
||||
} else {
|
||||
|
@ -12,6 +11,13 @@ if (Astro.cookies.get("Language") === undefined) {
|
|||
if (UserLanguage === "JP") {i18next.changeLanguage("jp")}
|
||||
else if (UserLanguage === "EN") {i18next.changeLanguage("en")}
|
||||
}
|
||||
if (Astro.cookies.get("Milieu") === undefined) {
|
||||
Astro.cookies.set("Milieu", "Enabled", {path: "/",sameSite: 'strict'})
|
||||
} else {
|
||||
var UserLanguage = Astro.cookies.get("Language").value
|
||||
if (UserLanguage === "JP") {i18next.changeLanguage("jp")}
|
||||
else if (UserLanguage === "EN") {i18next.changeLanguage("en")}
|
||||
}
|
||||
|
||||
/// Telemtry
|
||||
//// Users should be opted-out by default
|
||||
|
|
0
src/components/global/MobileNav.astro
Normal file → Executable file
0
src/components/global/Sidebar.astro
Normal file → Executable file
0
src/components/information/InstanceList.astro
Normal file → Executable file
0
src/components/information/Invidious.astro
Normal file → Executable file
0
src/components/search/Creator.astro
Normal file → Executable file
0
src/components/search/Stream.astro
Normal file → Executable file
0
src/components/text/PrivacyPolicyAnalytics.astro
Normal file → Executable file
0
src/components/text/PrivacyPolicyCloudflare.astro
Normal file → Executable file
117
src/components/video-player/Controls.astro
Normal file → Executable file
|
@ -1,15 +1,27 @@
|
|||
---
|
||||
// Cookies
|
||||
if (Astro.cookies.get("Milieu").value === "Enabled") {
|
||||
var Milieu = true
|
||||
} else {
|
||||
var Milieu = false
|
||||
}
|
||||
|
||||
// Icons
|
||||
import {
|
||||
ArrowUpRight,
|
||||
Backward15Seconds,
|
||||
Enlarge,
|
||||
Forward15Seconds,
|
||||
NavArrowRight,
|
||||
PlaySolid,
|
||||
Settings,
|
||||
SwitchOff,
|
||||
SwitchOn,
|
||||
} from "@iconoir/vue";
|
||||
---
|
||||
<div class="video-controls">
|
||||
<div class="vc-top">
|
||||
<p>DJI: Landscape Footage of Cities</p>
|
||||
<p>The Mark On The Wall</p>
|
||||
</div>
|
||||
<div class="vc-bottom">
|
||||
<div class="vc-start">
|
||||
|
@ -29,9 +41,108 @@ import {
|
|||
</p>
|
||||
</div>
|
||||
<div class="vc-end">
|
||||
<!-- <button id="vc-settings"><Settings /></button> -->
|
||||
<button id="vc-settings" onclick="PlayerMenu_Settings()"><Settings /></button>
|
||||
<!-- <button><SoundHighSolid /></button> Should affect <audio>, not <video> -->
|
||||
<button id="vc-fullscreen"><Enlarge /></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Menus -->
|
||||
<div id="settings" class="vc-menu">
|
||||
<button>Stats for Geeks</button>
|
||||
<hr/>
|
||||
<button>Open Video URL <ArrowUpRight/></button>
|
||||
<button>Download <ArrowUpRight/></button>
|
||||
<button>Embed <ArrowUpRight/></button>
|
||||
<hr/>
|
||||
{Milieu ?
|
||||
<button onclick="location.href = '/api/player/milieu/disable'" id="has-switch">Milieu <SwitchOn/></button>
|
||||
:
|
||||
<button onclick="location.href = '/api/player/milieu/enable'" id="has-switch">Milieu <SwitchOff/></button>
|
||||
}
|
||||
<!-- <button>Close Captions <NavArrowRight/></button> -->
|
||||
<button onclick="PlayerMenu_Quality()">Quality <NavArrowRight/></button>
|
||||
</div>
|
||||
<div id="quality-changer" class="vc-menu">
|
||||
<button onclick="ChangeQualtiy_1080()">1080p</button>
|
||||
<button onclick="ChangeQualtiy_720()">720p</button>
|
||||
<button onclick="ChangeQualtiy_360()">360p</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script is:inline>
|
||||
function PlayerMenu_HideAll() {
|
||||
document.querySelector('.vc-menu#settings').style.display = 'none'
|
||||
document.querySelector('.vc-menu#quality-changer').style.display = 'none'
|
||||
}
|
||||
function PlayerMenu_Settings() {
|
||||
PlayerMenu_HideAll()
|
||||
document.querySelector('.vc-menu#settings').style.display = 'flex'
|
||||
}
|
||||
function PlayerMenu_Quality() {
|
||||
PlayerMenu_HideAll()
|
||||
document.querySelector('.vc-menu#quality-changer').style.display = 'flex'
|
||||
}
|
||||
</script>
|
||||
|
||||
<script is:inline>
|
||||
function ChangeQualtiy_1080() {
|
||||
// Hide Menu
|
||||
PlayerMenu_HideAll()
|
||||
// Get Video
|
||||
var video = document.querySelector('video')
|
||||
var audio = document.querySelector('audio')
|
||||
// Get Source
|
||||
video.setAttribute('src', 'http://catactyl.home.ro:5006/The%20Mark%20On%20The%20Wall/1080.mp4')
|
||||
// Get Current Timestamp
|
||||
var CurrentTimestamp = document.querySelector("#seek").getAttribute('data-seek')
|
||||
// Go To Timestamp
|
||||
setTimeout(() => {
|
||||
video.pause();
|
||||
audio.pause();
|
||||
video.currentTime = CurrentTimestamp;
|
||||
audio.currentTime = CurrentTimestamp;
|
||||
video.play();
|
||||
audio.play();
|
||||
}, 0o100);
|
||||
}
|
||||
function ChangeQualtiy_720() {
|
||||
// Hide Menu
|
||||
PlayerMenu_HideAll()
|
||||
// Get Video
|
||||
var video = document.querySelector('video')
|
||||
var audio = document.querySelector('audio')
|
||||
// Get Source
|
||||
video.setAttribute('src', 'http://catactyl.home.ro:5006/The%20Mark%20On%20The%20Wall/720.mp4')
|
||||
// Get Current Timestamp
|
||||
var CurrentTimestamp = document.querySelector("#seek").getAttribute('data-seek')
|
||||
// Go To Timestamp
|
||||
setTimeout(() => {
|
||||
video.pause();
|
||||
audio.pause();
|
||||
video.currentTime = CurrentTimestamp;
|
||||
audio.currentTime = CurrentTimestamp;
|
||||
video.play();
|
||||
audio.play();
|
||||
}, 0o100);
|
||||
}
|
||||
function ChangeQualtiy_360() {
|
||||
// Hide Menu
|
||||
PlayerMenu_HideAll()
|
||||
// Get Video
|
||||
var video = document.querySelector('video')
|
||||
var audio = document.querySelector('audio')
|
||||
// Get Source
|
||||
video.setAttribute('src', 'http://catactyl.home.ro:5006/The%20Mark%20On%20The%20Wall/360.mp4')
|
||||
// Get Current Timestamp
|
||||
var CurrentTimestamp = document.querySelector("#seek").getAttribute('data-seek')
|
||||
// Go To Timestamp
|
||||
setTimeout(() => {
|
||||
video.pause();
|
||||
audio.pause();
|
||||
video.currentTime = CurrentTimestamp;
|
||||
audio.currentTime = CurrentTimestamp;
|
||||
video.play();
|
||||
audio.play();
|
||||
}, 0o100);
|
||||
}
|
||||
</script>
|
88
src/components/video-player/Player.astro
Normal file → Executable file
|
@ -1,6 +1,13 @@
|
|||
---
|
||||
// Properties
|
||||
const { Poster, Source } = Astro.props
|
||||
const { Poster, Video, Audio } = Astro.props
|
||||
|
||||
// Cookies
|
||||
if (Astro.cookies.get("Milieu").value === "Enabled") {
|
||||
var Milieu = true
|
||||
} else {
|
||||
var Milieu = false
|
||||
}
|
||||
|
||||
// Components
|
||||
import Controls from '@components/video-player/Controls.astro'
|
||||
|
@ -10,12 +17,85 @@ import '@styles/player.scss'
|
|||
---
|
||||
|
||||
<div class="video-container">
|
||||
<video class="main-video" muted autoplay loop src={Source} poster={Poster}></video>
|
||||
<audio class="main-audio" autoplay><source src={Source} type="audio/mp3"/></audio>
|
||||
<canvas id="ambient-canvas-1"/>
|
||||
<canvas id="ambient-canvas-2"/>
|
||||
<video class="main-video" muted src={Video} poster={Poster} preload="auto"></video>
|
||||
<audio class="main-audio"><source src={Audio} type="audio/mp3"/></audio>
|
||||
<Controls/>
|
||||
</div>
|
||||
|
||||
<!-- Player Functions -->
|
||||
<script is:inline src="/player/controller.js"></script>
|
||||
<script is:inline src="/player/seek.js"></script>
|
||||
<script is:inline src="/player/sync.js"></script>
|
||||
<script is:inline src="/player/sync.js"></script>
|
||||
|
||||
{Milieu ?
|
||||
<script is:inline>
|
||||
const AMvideo = document.querySelector("video")
|
||||
const oddCanvas = document.getElementById("ambient-canvas-1")
|
||||
const evenCanvas = document.getElementById("ambient-canvas-2")
|
||||
const oddCtx = oddCanvas.getContext("2d")
|
||||
const evenCtx = evenCanvas.getContext("2d")
|
||||
|
||||
const frameIntervalMs = 2000
|
||||
const canvasOpacity = "0.4"
|
||||
|
||||
let intervalId
|
||||
let oddFrame = true
|
||||
const drawFrame = () => {
|
||||
if (oddFrame) {
|
||||
oddCtx.drawImage(AMvideo, 0, 0, oddCanvas.width, oddCanvas.height)
|
||||
transitionToOddCanvas()
|
||||
} else {
|
||||
evenCtx.drawImage(AMvideo, 0, 0, evenCanvas.width, evenCanvas.height)
|
||||
transitionToEvenCanvas()
|
||||
}
|
||||
oddFrame = !oddFrame
|
||||
};
|
||||
|
||||
const transitionToOddCanvas = () => {
|
||||
oddCanvas.style.opacity = canvasOpacity
|
||||
evenCanvas.style.opacity = "0"
|
||||
}
|
||||
|
||||
const transitionToEvenCanvas = () => {
|
||||
evenCanvas.style.opacity = canvasOpacity
|
||||
oddCanvas.style.opacity = "0"
|
||||
}
|
||||
|
||||
const drawStart = () => {
|
||||
intervalId = window.setInterval(drawFrame, frameIntervalMs)
|
||||
}
|
||||
|
||||
const drawPause = () => {
|
||||
if (intervalId) window.clearInterval(intervalId)
|
||||
}
|
||||
|
||||
const init = () => {
|
||||
|
||||
//fixes a issue where firefox/chromium fails to load the ambinet mode and doesnt load it. - please dont remove this line lmao
|
||||
|
||||
AMvideo.pause();AMvideo.play();
|
||||
|
||||
// DO NOT REMOVE
|
||||
|
||||
AMvideo.addEventListener("play", drawStart, false)
|
||||
AMvideo.addEventListener("pause", drawPause, false)
|
||||
AMvideo.addEventListener("ended", drawPause, false)
|
||||
|
||||
oddCanvas.style.transition = evenCanvas.style.transition = `opacity ${frameIntervalMs}ms`
|
||||
}
|
||||
|
||||
const cleanup = () => {
|
||||
AMvideo.removeEventListener("play", drawStart)
|
||||
AMvideo.removeEventListener("pause", drawPause)
|
||||
AMvideo.removeEventListener("ended", drawPause)
|
||||
drawPause();
|
||||
}
|
||||
|
||||
window.addEventListener("load", init)
|
||||
window.addEventListener("unload", cleanup)
|
||||
</script>
|
||||
:
|
||||
null
|
||||
}
|
0
src/data/discover.json
Normal file → Executable file
0
src/env.d.ts
vendored
Normal file → Executable file
0
src/layouts/API.astro
Normal file → Executable file
24
src/layouts/Default.astro
Normal file → Executable file
|
@ -1,22 +1,22 @@
|
|||
---
|
||||
// Properties
|
||||
const { Title, Description } = Astro.props
|
||||
const { Title, Description } = Astro.props;
|
||||
|
||||
// Components
|
||||
import Head from '@components/global/Head.astro'
|
||||
import MobileNav from '@components/global/MobileNav.astro'
|
||||
import Sidebar from '@components/global/Sidebar.astro'
|
||||
import Footer from '@components/global/Footer.astro'
|
||||
import Head from "@components/global/Head.astro";
|
||||
import MobileNav from "@components/global/MobileNav.astro";
|
||||
import Sidebar from "@components/global/Sidebar.astro";
|
||||
import Footer from "@components/global/Footer.astro";
|
||||
|
||||
// Styles
|
||||
import '@styles/index.scss'
|
||||
import '@styles/mobile.scss'
|
||||
import "@styles/index.scss";
|
||||
import "@styles/mobile.scss";
|
||||
---
|
||||
|
||||
<Head Title={Title} Description={Description}/>
|
||||
<MobileNav/>
|
||||
<Sidebar/>
|
||||
<Head Title={Title} Description={Description} />
|
||||
<MobileNav />
|
||||
<Sidebar />
|
||||
<div class="content">
|
||||
<slot/>
|
||||
<slot />
|
||||
</div>
|
||||
<Footer/>
|
||||
<Footer />
|
||||
|
|
0
src/layouts/Embed.astro
Normal file → Executable file
0
src/layouts/Error.astro
Normal file → Executable file
0
src/layouts/Markdown.astro
Normal file → Executable file
0
src/layouts/Settings.astro
Normal file → Executable file
0
src/library/supabase.ts
Normal file → Executable file
0
src/pages/404.astro
Normal file → Executable file
0
src/pages/500.astro
Normal file → Executable file
0
src/pages/account/confirm-your-email.astro
Normal file → Executable file
0
src/pages/account/index.astro
Normal file → Executable file
0
src/pages/api/auth/confirm.ts
Normal file → Executable file
0
src/pages/api/auth/login.ts
Normal file → Executable file
0
src/pages/api/auth/logout.ts
Normal file → Executable file
0
src/pages/api/auth/register.ts
Normal file → Executable file
0
src/pages/api/language/en.astro
Normal file → Executable file
0
src/pages/api/language/jp.astro
Normal file → Executable file
9
src/pages/api/player/milieu/disable.astro
Executable file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import API from '@layouts/API.astro'
|
||||
Astro.cookies.set("Milieu", "Disabled", {
|
||||
path: "/",
|
||||
sameSite: "strict"
|
||||
});
|
||||
return Astro.redirect("/");
|
||||
---
|
||||
<API Title="MinPluto" Description=""></API>
|
14
src/pages/api/player/milieu/enable.astro
Executable file
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
// Layout
|
||||
import API from '@layouts/API.astro'
|
||||
|
||||
// API Action
|
||||
Astro.cookies.set("Milieu", "Enabled", {
|
||||
path: "/",
|
||||
sameSite: "strict"
|
||||
});
|
||||
|
||||
// Return
|
||||
return Astro.redirect("/telemtry");
|
||||
---
|
||||
<API Title="MinPluto" Description=""></API>
|
0
src/pages/api/telemtry/disable.astro
Normal file → Executable file
0
src/pages/api/telemtry/enable.astro
Normal file → Executable file
0
src/pages/api/update/email.ts
Normal file → Executable file
0
src/pages/api/update/name.ts
Normal file → Executable file
0
src/pages/category/gaming.astro
Normal file → Executable file
0
src/pages/category/movies.astro
Normal file → Executable file
0
src/pages/category/music.astro
Normal file → Executable file
0
src/pages/category/trending.astro
Normal file → Executable file
0
src/pages/channel/[...slug].astro
Normal file → Executable file
0
src/pages/discover.astro
Normal file → Executable file
0
src/pages/embed/[...slug].astro
Normal file → Executable file
0
src/pages/iframe/category/trending.astro
Normal file → Executable file
0
src/pages/index.astro
Normal file → Executable file
0
src/pages/instance.mdx
Normal file → Executable file
0
src/pages/live.astro
Normal file → Executable file
0
src/pages/login.astro
Normal file → Executable file
0
src/pages/m/about.astro
Normal file → Executable file
0
src/pages/m/categories.astro
Normal file → Executable file
0
src/pages/offline.astro
Normal file → Executable file
0
src/pages/playlist.mdx
Normal file → Executable file
0
src/pages/privacy.mdx
Normal file → Executable file
0
src/pages/register.astro
Normal file → Executable file
0
src/pages/search.astro
Normal file → Executable file
0
src/pages/telemtry.mdx
Normal file → Executable file
15
src/pages/vp.astro
Normal file → Executable file
|
@ -4,5 +4,16 @@ import Player from "@components/video-player/Player.astro"
|
|||
---
|
||||
|
||||
<Base>
|
||||
<Player Source="/demo-purposes.mp4"/>
|
||||
</Base>
|
||||
<Player
|
||||
Video="http://catactyl.home.ro:5006/The%20Mark%20On%20The%20Wall/1080.mp4"
|
||||
Audio="http://catactyl.home.ro:5006/The%20Mark%20On%20The%20Wall/audio.mp4"
|
||||
/>
|
||||
</Base>
|
||||
|
||||
<style is:global>
|
||||
.video-container {
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
margin-top: 92px;
|
||||
}
|
||||
</style>
|
36
src/pages/watch.astro
Normal file → Executable file
|
@ -71,12 +71,10 @@ if (EightK === true) { // 571
|
|||
---
|
||||
|
||||
<Base Title={video.title}>
|
||||
<div class="video-container">
|
||||
<Player
|
||||
Poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
Source={DEFAULT_MEDIA_DATA_PROXY + '/latest_version?id=' + video.videoId + '&itag=' + '137' + '&local=true'}
|
||||
/>
|
||||
</div>
|
||||
<Player
|
||||
Poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
Source={DEFAULT_MEDIA_DATA_PROXY + '/latest_version?id=' + video.videoId + '&itag=' + Quality + '&local=true'}
|
||||
/>
|
||||
<div class="video-rea">
|
||||
<div class="rea-details">
|
||||
<p style="font-weight: bold; font-size: 24px;">{video.title}</p>
|
||||
|
@ -227,20 +225,18 @@ function ShareDialogHide() {
|
|||
function SyncTimestamp() {SyncAudio.currentTime = SyncVideo.currentTime}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.video-container {
|
||||
max-width: 90%;
|
||||
margin: auto;
|
||||
.zorn-player {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zorn-player-controls {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
<style is:global lang="scss">
|
||||
.video-container {
|
||||
max-width: 100%;
|
||||
margin: 48px 24px 23px 24px;
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.video-controls, video {
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
|
|
BIN
src/public/demo-media/480.mp4
Executable file
BIN
src/public/demo-purposes.mp4 → src/public/demo-media/720.mp4
Normal file → Executable file
0
src/public/images/backgrounds/1.webp
Normal file → Executable file
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
0
src/public/images/backgrounds/2.jpg
Normal file → Executable file
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 149 KiB |
0
src/public/images/logo/Favicon.png
Normal file → Executable file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
src/public/images/logo/MinPluto - Image Logo Full with Shadow.png
Normal file → Executable file
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
0
src/public/images/logo/MinPluto - Image Logo Full.png
Normal file → Executable file
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
0
src/public/images/logo/MinPluto - Logo Full.png
Normal file → Executable file
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
0
src/public/images/logo/MinPluto - Logo.png
Normal file → Executable file
Before Width: | Height: | Size: 1,019 B After Width: | Height: | Size: 1,019 B |
0
src/public/images/logo/MinPluto - PWA Logo.png
Normal file → Executable file
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
0
src/public/images/pwa/MinPluto - PWA Logo.png
Normal file → Executable file
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
0
src/public/images/pwa/Mobile.png
Normal file → Executable file
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 154 KiB |