update
82
src/components/Dialog.astro
Normal file
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
import { Xmark } from "@iconoir/vue"
|
||||
|
||||
const {
|
||||
Title,
|
||||
Description,
|
||||
Closable,
|
||||
CloseOnclick
|
||||
} = Astro.props
|
||||
---
|
||||
|
||||
<div class="dialog-backdrop"></div>
|
||||
<div id={'dialog-' + Title} class="dialog">
|
||||
<div class="dialog-header">
|
||||
<div class="dialog-header-title">
|
||||
<h2>{Title}</h2>
|
||||
<p>{Description}</p>
|
||||
</div>
|
||||
<div class="dialog-header-action">
|
||||
{Closable ? <button onclick={CloseOnclick}><Xmark/></button> : null}
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<slot/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.dialog-backdrop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 6;
|
||||
backdrop-filter: blur(10px) brightness(0.5) contrast(0.9);
|
||||
}
|
||||
.dialog {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 7;
|
||||
width: 100%;
|
||||
top: 25%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: rgb(24 24 24);
|
||||
border: 2px rgba(255,255,255,0.05) solid;
|
||||
margin: auto;
|
||||
max-width: 600px;
|
||||
border-radius: 10px;
|
||||
flex-direction: column;
|
||||
padding-bottom: 24px;
|
||||
.dialog-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 24px;
|
||||
.dialog-header-title {
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
margin: 0px;
|
||||
}
|
||||
p {
|
||||
font-size: 14px;
|
||||
margin: 0px;
|
||||
color: gray;
|
||||
}
|
||||
}
|
||||
.dialog-header-action button {
|
||||
background: transparent;
|
||||
color: white;
|
||||
border: none;
|
||||
aspect-ratio: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.dialog-content {
|
||||
padding: 0px 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
67
src/components/MusicItem.astro
Normal file
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
// Properties
|
||||
const {
|
||||
ID,
|
||||
Title,
|
||||
Creator,
|
||||
Views,
|
||||
UploadDate,
|
||||
Length
|
||||
} = Astro.props
|
||||
|
||||
// Configuration
|
||||
import {
|
||||
DEFAULT_DATA_PROXY,
|
||||
DEFAULT_IMAGE_PROXY
|
||||
} from '../../config.json'
|
||||
|
||||
// i18n
|
||||
import i18next, { t } from "i18next";
|
||||
|
||||
// Format Published Date
|
||||
const DateFormat = new Date(UploadDate * 1000).toLocaleDateString()
|
||||
|
||||
// Format Video Length
|
||||
// Thanks to "mingjunlu" for helping out with the time format
|
||||
const LengthFormat = new Date(Length * 1000).toISOString().slice(14, 19).split(':').map(Number).join(':')
|
||||
|
||||
// Format Views
|
||||
const ViewsConversion = Intl.NumberFormat('en', { notation: 'compact'})
|
||||
const ViewsFormat = ViewsConversion.format(Views)
|
||||
---
|
||||
|
||||
|
||||
<a href={'/' + i18next.language + '/watch?v=' + ID} class="music-item">
|
||||
<img src={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + ID + '/maxresdefault.jpg'}/>
|
||||
<p id="title">{Title}</p>
|
||||
<p id="artist">{Creator}</p>
|
||||
<p id="date">{DateFormat}</p>
|
||||
<p id="duration">{LengthFormat}</p>
|
||||
</a>
|
||||
|
||||
<style lang="scss">
|
||||
.music-item {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
gap: 12px;
|
||||
grid-template-columns: 60px auto auto 80px 64px;
|
||||
#duration, #date {
|
||||
color: gray;
|
||||
}
|
||||
#artist, #duration, #date {
|
||||
text-align: right;
|
||||
}
|
||||
#title {
|
||||
font-weight: bold;
|
||||
}
|
||||
img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
54
src/components/Search.astro
Normal file
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
import { Search } from '@iconoir/vue'
|
||||
import { t } from 'i18next'
|
||||
---
|
||||
|
||||
<div class="search-bar">
|
||||
<input type="search" placeholder={t("HEADER.SEARCH")} aria-label="Search for a video"/>
|
||||
<button onclick="Search()"><Search/></button>
|
||||
</div>
|
||||
|
||||
<script is:inline>
|
||||
function Search() {
|
||||
var SearchQuery = document.querySelector('input[type="search"]').value
|
||||
location.href = `/search?q=${SearchQuery}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.search-bar {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
input[type="search"] {
|
||||
background: transparent;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 10px 0px 0px 10px;
|
||||
padding: 24px;
|
||||
width: 100%;
|
||||
transition: 0.3s width;
|
||||
&:focus {
|
||||
outline: none;
|
||||
transition: 0.3s width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-bar button {
|
||||
display: none;
|
||||
border-radius: 1rem;
|
||||
aspect-ratio: 1;
|
||||
background: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
margin: 8px 0px 0px -31px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.search-bar button svg {
|
||||
width: 14px;
|
||||
}
|
||||
.search-bar[data-astro-cid-otpdt6jm] {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
82
src/components/VideoItem.astro
Normal file
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
// Properties
|
||||
const {
|
||||
ID,
|
||||
Title,
|
||||
Creator,
|
||||
Views,
|
||||
UploadDate,
|
||||
Length
|
||||
} = Astro.props
|
||||
|
||||
// Configuration
|
||||
import {
|
||||
DEFAULT_DATA_PROXY,
|
||||
DEFAULT_IMAGE_PROXY
|
||||
} from '../../config.json'
|
||||
|
||||
// i18n
|
||||
import i18next, { t } from "i18next";
|
||||
|
||||
// Format Published Date
|
||||
const DateFormat = new Date(UploadDate * 1000).toLocaleDateString()
|
||||
|
||||
// Format Video Length
|
||||
// Thanks to "mingjunlu" for helping out with the time format
|
||||
const LengthFormat = new Date(Length * 1000).toISOString().slice(14, 19).split(':').map(Number).join(':')
|
||||
|
||||
// Format Views
|
||||
const ViewsConversion = Intl.NumberFormat('en', { notation: 'compact'})
|
||||
const ViewsFormat = ViewsConversion.format(Views)
|
||||
---
|
||||
|
||||
<a href={'/' + i18next.language + '/watch?v=' + ID} class="video-item">
|
||||
<div class="video-item-thumbnail">
|
||||
<img src={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + ID + '/maxresdefault.jpg'}/>
|
||||
<p id="vi-length">{LengthFormat}</p>
|
||||
</div>
|
||||
<div class="video-item-details">
|
||||
<p id="vi-title">{Title}</p>
|
||||
<p id="vi-author">{t("WATCH.BY")} {Creator}</p>
|
||||
<p id="vi-viewCount">{ViewsFormat} {t("WATCH.VIEWS")} - {DateFormat}</p>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<style lang="scss">
|
||||
.video-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
.video-item-thumbnail {
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 6px;
|
||||
aspect-ratio: 16/9;
|
||||
object-fit: contain;
|
||||
}
|
||||
p#vi-length {
|
||||
margin: -41px 0px 0px 0px;
|
||||
background: rgba(0,0,0,0.75);
|
||||
padding: 12px 6px 6px 16px;
|
||||
width: max-content;
|
||||
border-radius: 50px 0px 6px 0px;
|
||||
position: relative;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.video-item-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
p {
|
||||
margin: 0px;
|
||||
&#vi-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
&#vi-author {
|
||||
color: darkgrey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
19
src/components/global/Footer.astro
Normal file
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
// Configuration
|
||||
import {
|
||||
DEFAULT_PLAYER
|
||||
} from '../../../config.json'
|
||||
---
|
||||
|
||||
{
|
||||
() => {
|
||||
if (DEFAULT_PLAYER === "Browser") {
|
||||
return (null)
|
||||
}
|
||||
if (DEFAULT_PLAYER === "Zorn") {
|
||||
return (
|
||||
<script is:inline src="/scripts/zorn.js"></script>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
82
src/components/global/Head.astro
Normal file
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
const {
|
||||
Title,
|
||||
Description,
|
||||
EmbedId,
|
||||
EmbedVideo,
|
||||
EmbedImage,
|
||||
EmbedTitle,
|
||||
} = Astro.props
|
||||
|
||||
// Configuration
|
||||
import {
|
||||
STATISTICS,
|
||||
ANALYLICS_TOOL,
|
||||
ANALYLICS_ID,
|
||||
SCRIPT_SRC,
|
||||
DOMAIN,
|
||||
SERVER_DOMAIN
|
||||
} from '../../../config.json'
|
||||
import { Donate, Download, ShareIos, ThumbsUp } from '@iconoir/vue'
|
||||
|
||||
const SWV = Astro.url.href.split("embed/").pop();
|
||||
|
||||
if (Astro.url.href.match('watch')) {
|
||||
var IsVideo = true
|
||||
} else if (Astro.url.href.match('embed')) {
|
||||
var IsVideo = false
|
||||
} else {
|
||||
var IsVideo = false
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
<head>
|
||||
<!-- Metadata -->
|
||||
<title>{Title}</title>
|
||||
<meta name="description" content={Description}>
|
||||
|
||||
<!-- Properties -->
|
||||
<meta charset="UTF-8">
|
||||
<meta name="theme-color" content="#111">
|
||||
<meta name="viewport" content="width=device-1200px, initial-scale=1.0, shrink-to-fit=yes, viewport-fit=cover">
|
||||
<meta http-equiv="content-language" content="en-us">
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<script is:inline src="/service-worker.js"></script>
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="apple-touch-icon" type="image/png" sizes="256x256" href="/images/logo/Favicon.png">
|
||||
<link rel="icon" type="image/png" sizes="256x256" href="/images/logo/Favicon.png">
|
||||
|
||||
<!-- Analytics -->
|
||||
{STATISTICS ?
|
||||
() => {
|
||||
if (ANALYLICS_TOOL === "Plausible") {
|
||||
return (
|
||||
<script defer data-domain={DOMAIN} src={SCRIPT_SRC}></script>
|
||||
)
|
||||
}
|
||||
if (ANALYLICS_TOOL === "Umami") {
|
||||
return (
|
||||
<script async src={SCRIPT_SRC} data-website-id={ANALYLICS_ID}></script>
|
||||
)
|
||||
}
|
||||
}
|
||||
:
|
||||
null
|
||||
}
|
||||
|
||||
<!-- Video Embed -->
|
||||
{IsVideo ?
|
||||
<meta property="og:type" content="video.other">
|
||||
<meta property="og:video:url" content={SERVER_DOMAIN + '/embed/' + EmbedId}>
|
||||
<meta property="og:video:type" content="text/html">
|
||||
<meta property="twitter:player" content={SERVER_DOMAIN + '/embed/' + EmbedId}>
|
||||
<meta property="og:video" content={EmbedVideo} />
|
||||
<meta property="og:title" content={EmbedTitle}>
|
||||
<meta property="og:image" content={EmbedImage}/>
|
||||
<meta property="og:site_name" content={'MinPluto - Privacy YouTube Frontend'}>
|
||||
:
|
||||
null
|
||||
}
|
||||
</head>
|
32
src/components/global/Header.astro
Normal file
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
// Components
|
||||
import Search from '@components/Search.astro'
|
||||
|
||||
// Icons
|
||||
import {
|
||||
Message,
|
||||
Youtube
|
||||
} from '@iconoir/vue'
|
||||
|
||||
// i18n
|
||||
import { t, changeLanguage } from "i18next"
|
||||
import { LanguageSelector } from "astro-i18next/components"
|
||||
---
|
||||
|
||||
<div class="header">
|
||||
<div class="header-start">
|
||||
<img class="mo" style="height: 24px; margin-right: 24px;" src="/images/logo/MinPluto - Logo.png"/>
|
||||
<Search/>
|
||||
</div>
|
||||
<div class="header-end">
|
||||
<LanguageSelector
|
||||
showFlag={false}
|
||||
languageMapping={{
|
||||
en: "English",
|
||||
jp: "Japanese",
|
||||
ru: "Russian"
|
||||
}}
|
||||
/>
|
||||
<a href="https://community.minpluto.org/c/feedback/2" target="_blank"><Message/> {t("HEADER.FEEDBACK")}</a>
|
||||
</div>
|
||||
</div>
|
10
src/components/global/MobileNav.astro
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
import { GraphUp, HomeSimple, InfoCircle, ViewGrid } from "@iconoir/vue";
|
||||
|
||||
---
|
||||
|
||||
<div class="mobile-navigation">
|
||||
<a href="/"><HomeSimple/></a>
|
||||
<a href="/category/trending"><GraphUp/></a>
|
||||
<a href="/m/about"><InfoCircle/></a>
|
||||
</div>
|
170
src/components/global/Sidebar.astro
Normal file
|
@ -0,0 +1,170 @@
|
|||
---
|
||||
// Configuration
|
||||
import {
|
||||
SIDEBAR_DISCOVER,
|
||||
SIDEBAR_CATEGORIES
|
||||
} from '@root/config.json'
|
||||
|
||||
import {
|
||||
version
|
||||
} from '@root/package.json'
|
||||
|
||||
// Icons
|
||||
import {
|
||||
HomeSimple,
|
||||
GraphUp,
|
||||
Movie,
|
||||
MusicDoubleNote,
|
||||
Gamepad,
|
||||
AppleImac2021Side,
|
||||
EmojiTalkingHappy,
|
||||
PizzaSlice,
|
||||
Treadmill,
|
||||
PeaceHand,
|
||||
InfoCircle,
|
||||
HelpCircle,
|
||||
Server
|
||||
} from '@iconoir/vue'
|
||||
|
||||
// i18n
|
||||
import i18next, { t } from "i18next"
|
||||
---
|
||||
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-top">
|
||||
<a href={'/' + i18next.language} class="sidebar-top-start">
|
||||
<img src="/images/logo/MinPluto - Logo.png"/>
|
||||
</a>
|
||||
<div class="sidebar-top-end">
|
||||
<a href={'/' + i18next.language + '/'}><HomeSimple/> {t("SIDEBAR.HOME")}</a>
|
||||
<hr/>
|
||||
{SIDEBAR_CATEGORIES ?
|
||||
<h2>{t("SIDEBAR.CATEGORY")}</h2>
|
||||
<a href={'/' + i18next.language + '/category/trending'}><GraphUp/> {t("SIDEBAR.CATEGORY_LIST.TRENDING")}</a>
|
||||
<a href={'/' + i18next.language + '/category/movies'}><Movie/> {t("SIDEBAR.CATEGORY_LIST.MOVIES")}</a>
|
||||
<a href={'/' + i18next.language + '/category/music'}><MusicDoubleNote/> {t("SIDEBAR.CATEGORY_LIST.MUSIC")}</a>
|
||||
<a href={'/' + i18next.language + '/category/gaming'}><Gamepad/> {t("SIDEBAR.CATEGORY_LIST.GAMES")}</a>
|
||||
:
|
||||
null
|
||||
}
|
||||
{SIDEBAR_DISCOVER ?
|
||||
<hr/>
|
||||
<h2>{t("SIDEBAR.DISCOVER")}</h2>
|
||||
<a href={'/' + i18next.language + '/discover/tech'}><AppleImac2021Side/> {t("SIDEBAR.DISCOVER_LIST.TECH")}</a>
|
||||
<a id="sidebar-disable" href="#"><EmojiTalkingHappy/> {t("SIDEBAR.DISCOVER_LIST.COMEDY")}</a>
|
||||
<a id="sidebar-disable" href="#"><PizzaSlice/> {t("SIDEBAR.DISCOVER_LIST.FOOD")}</a>
|
||||
<a id="sidebar-disable" href="#"><Gamepad/> {t("SIDEBAR.DISCOVER_LIST.GAMES")}</a>
|
||||
<a id="sidebar-disable" href="#"><Treadmill/> {t("SIDEBAR.DISCOVER_LIST.FITNESS")}</a>
|
||||
:
|
||||
null
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-bottom">
|
||||
<div class="sidebar-bottom-start">
|
||||
<a style="pointer-events: none;"><PeaceHand/> {t("SIDEBAR.FOOTER.ALPHA")}</a>
|
||||
<a><HelpCircle/> Help</a>
|
||||
<a><Server/> Instance</a>
|
||||
</div>
|
||||
<div class="sidebar-bottom-center">
|
||||
<p id="version">v{version}</p>
|
||||
</div>
|
||||
<div class="sidebar-bottom-end">
|
||||
<a href="https://space.sudovanilla.com/" target="_blank">{t("SIDEBAR.FOOTER.FORUM")}</a>
|
||||
<a href="https://status.minpluto.org/" target="_blank">{t("SIDEBAR.FOOTER.STATUS")}</a>
|
||||
<a href="https://sudovanilla.com/code/MinPluto/MinPluto" target="_blank">{t("SIDEBAR.FOOTER.SOURCE_CODE")}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 224px;
|
||||
background: linear-gradient(315deg, #0e0e0e, #161616);
|
||||
color: white;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 0px 12px;
|
||||
hr {
|
||||
width: 32%;
|
||||
border: none;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
height: 4px;
|
||||
border-radius: 1rem;
|
||||
}
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
padding-left: 24px;
|
||||
}
|
||||
.sidebar-top {
|
||||
.sidebar-top-start {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
padding: 32px 24px;
|
||||
img {
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
.sidebar-top-end {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
.sidebar-bottom {
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.sidebar-bottom-center {
|
||||
background: #232323;
|
||||
padding: 0px 24px;
|
||||
margin: 0px -24px 12px -24px;
|
||||
text-align: center;
|
||||
}
|
||||
a {
|
||||
margin: 0px 4px;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sidebar-top-end a, .sidebar-bottom-start a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
margin-bottom: 6px;
|
||||
border-radius: 6px;
|
||||
padding: 8px 24px;
|
||||
background: transparent;
|
||||
border: 2px transparent solid;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
font-size: 14px;
|
||||
&:hover {
|
||||
background: rgb(255 255 255 / 05%);
|
||||
border: 2px rgba(255, 255, 255, 0.05) solid;
|
||||
}
|
||||
svg {
|
||||
width: 18px;
|
||||
}
|
||||
&#sidebar-disable {
|
||||
filter: brightness(0.4);
|
||||
cursor: not-allowed;
|
||||
&:hover {
|
||||
background: transparent;
|
||||
border: 2px transparent solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
39
src/data/discover.json
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"Tech": [
|
||||
{
|
||||
"Name": "Linus Tech Tips",
|
||||
"Id": "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||
"Link": "UCXuqSBlHAE6Xw-yeJA0Tunw",
|
||||
"Logo": "/ggpht/Vy6KL7EM_apxPSxF0pPy5w_c87YDTOlBQo3MADDF0Wl51kwxmt9wmRotnt2xQXwlrcyO0Xe56w",
|
||||
"Banner": "/ggpht/oaPQn9KofKbSwSKTW8eGEQTM8KwZ5wZMbo69PPxhgqu3NTNljx7hfJB1XmR4ZTa0VPdpnpIzlQ"
|
||||
},
|
||||
{
|
||||
"Name": "Mac Address",
|
||||
"Id": "UC0KfjyvabuE2J-RBC6ko2Lw",
|
||||
"Link": "UC0KfjyvabuE2J-RBC6ko2Lw",
|
||||
"Logo": "/ggpht/ytc/AIdro_k44TPOZxZNdlBdnnEjlvFs8EP832dq1-bX0ZxG",
|
||||
"Banner": "/ggpht/u5LNefuGhw400tFMOtaFY0JFUM-RUChETq3TRCa1v_vRhnXtULjELNgyTEgB2_PGUMnNdxr4qjY"
|
||||
},
|
||||
{
|
||||
"Name": "MKBHD",
|
||||
"Id": "/UCBJycsmduvYEL83R_U4JriQ",
|
||||
"Link": "/UCBJycsmduvYEL83R_U4JriQ",
|
||||
"Logo": "/ggpht/lkH37D712tiyphnu0Id0D5MwwQ7IRuwgQLVD05iMXlDWO-kDHut3uI4MgIEAQ9StK0qOST7fiA",
|
||||
"Banner": "/ggpht/KhLiJiH9xE8AiPUz9fLD9rOQYNH_EVhVuaKyAu2hp8alAhtkV4IQ9-Dfsoge8E11Im0nxDgjsQ"
|
||||
},
|
||||
{
|
||||
"Name": "The Linux Experiment",
|
||||
"Id": "UC5UAwBUum7CPN5buc-_N1Fw",
|
||||
"Link": "UC5UAwBUum7CPN5buc-_N1Fw",
|
||||
"Logo": "/ggpht/ytc/AIdro_kHP15da41K6sBItk2eRhwK31vp_UO6a4DEzH0EFw",
|
||||
"Banner": "/ggpht/Lc1dH-nj6nvU63AH85SPgoLd2oba4zA41zNbZSWg81PN_zl1mgC_eiL3DbJJPb7b_nS7FarUTYE"
|
||||
},
|
||||
{
|
||||
"Name": "NetworkChuck",
|
||||
"Id": "UC9x0AN7BWHpCDHSm9NiJFJQ",
|
||||
"Link": "UC9x0AN7BWHpCDHSm9NiJFJQ",
|
||||
"Logo": "/ggpht/ytc/AIdro_lUWCdtX-DVvLxWMK-gY-p24JNKmrCtKX_s404uMg",
|
||||
"Banner": "/ggpht/Lc1dH-6TsuYML3OSXSVVFkRGfPfq1qhEiG0tkKj-UV6XPfifmDDAuV8QTF4wna5maptTBMhikcjaAWcg"
|
||||
}
|
||||
]
|
||||
}
|
1
src/env.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/// <reference types="astro/client" />
|
92
src/layouts/Category.astro
Normal file
|
@ -0,0 +1,92 @@
|
|||
---
|
||||
// Properties
|
||||
const {
|
||||
FetchData,
|
||||
CategoryName,
|
||||
CategoryDescription,
|
||||
GradientHero
|
||||
} = Astro.props
|
||||
|
||||
// Use on top of Default Layout
|
||||
import Base from '@layouts/Default.astro'
|
||||
import Video from '@components/VideoItem.astro'
|
||||
|
||||
// Configuration
|
||||
import {
|
||||
DEFAULT_DATA_PROXY,
|
||||
DEFAULT_VIDEO_PROXY
|
||||
} from '../../config.json'
|
||||
|
||||
|
||||
// Fetch
|
||||
const fetchFrom = DEFAULT_DATA_PROXY + '/api/v1/trending' + FetchData
|
||||
const response = await fetch(fetchFrom)
|
||||
const data = await response.json()
|
||||
|
||||
const heroItem = data.slice(0,1)
|
||||
---
|
||||
|
||||
<Base Title={CategoryName + " - MinPluto"} Description={CategoryDescription}>
|
||||
<div style={'background: linear-gradient(180deg, ' + GradientHero + ', transparent);'} class="category-hero">
|
||||
<div class="c-hero-content">
|
||||
<div style="width: 25%;">
|
||||
<h2>{CategoryName}</h2>
|
||||
<p>{CategoryDescription}</p>
|
||||
</div>
|
||||
<div class="c-hero-video">
|
||||
{heroItem.map((data) =>
|
||||
<video autoplay muted src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + data.videoId + '&itag=22&local=true'}></video>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span id="gradient-header"></span>
|
||||
<div class="video-grid">
|
||||
{data.map((data) =>
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style define:vars={{GradientHero}} lang="scss">
|
||||
.category-hero {
|
||||
margin-top: -80px;
|
||||
padding-top: 80px;
|
||||
.c-hero-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
max-width: 1000px;
|
||||
justify-content: space-between;
|
||||
h2 {
|
||||
font-size: 44px;
|
||||
margin: 0px;
|
||||
}
|
||||
.c-hero-video {
|
||||
-webkit-mask-image: radial-gradient(rgb(0 0 0 / 50%), transparent);
|
||||
-webkit-mask-image: linear-gradient(90deg, black, rgba(0, 0, 0, 0));
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
aspect-ratio: 16/9;
|
||||
video {
|
||||
pointer-events: none;
|
||||
object-fit: none;
|
||||
object-position: center;
|
||||
width: 75%;
|
||||
height: 100%;
|
||||
float: right;
|
||||
-webkit-mask-image: linear-gradient(270deg, black, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
24
src/layouts/Default.astro
Normal file
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
// Properties
|
||||
const { Title, Description } = Astro.props
|
||||
|
||||
// Components
|
||||
import Head from '@components/global/Head.astro'
|
||||
import Header from '@components/global/Header.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'
|
||||
---
|
||||
|
||||
<Head Title={Title} Description={Description}/>
|
||||
<MobileNav/>
|
||||
<Sidebar/>
|
||||
<div class="content">
|
||||
<Header/>
|
||||
<slot/>
|
||||
</div>
|
||||
<Footer/>
|
29
src/layouts/Embed.astro
Normal file
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
// Properties
|
||||
const {
|
||||
Title,
|
||||
Description,
|
||||
EmbedId,
|
||||
EmbedVideo,
|
||||
EmbedImage,
|
||||
EmbedTitle
|
||||
} = Astro.props
|
||||
|
||||
// Components
|
||||
import Head from '@components/global/Head.astro'
|
||||
import Footer from '@components/global/Footer.astro'
|
||||
|
||||
// Styles
|
||||
import '@styles/embed.scss'
|
||||
---
|
||||
|
||||
<Head
|
||||
Title={Title}
|
||||
Description={Description}
|
||||
EmbedId={EmbedId}
|
||||
EmbedVideo={EmbedVideo}
|
||||
EmbedImage={EmbedImage}
|
||||
EmbedTitle={EmbedTitle}
|
||||
/>
|
||||
<slot/>
|
||||
<Footer/>
|
35
src/layouts/Markdown.astro
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
// Properties
|
||||
const { Title, Description } = Astro.props
|
||||
|
||||
// Components
|
||||
import Head from '@components/global/Head.astro'
|
||||
import Header from '@components/global/Header.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'
|
||||
---
|
||||
|
||||
<Head Title={Title} Description={Description}/>
|
||||
<MobileNav/>
|
||||
<Sidebar/>
|
||||
<div class="markdown">
|
||||
<slot/>
|
||||
</div>
|
||||
<Footer/>
|
||||
|
||||
<style lang="scss">
|
||||
.markdown {
|
||||
background: transparent;
|
||||
color: white;
|
||||
max-width: 700px;
|
||||
margin: auto;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 32px;
|
||||
padding: 6px 24px;
|
||||
}
|
||||
</style>
|
20
src/pages/404.astro
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<h2>Error 404</h2>
|
||||
<p>Page not found.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
</style>
|
9
src/pages/category/gaming.astro
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Category GradientHero="#269753" FetchData="?type=gaming" CategoryName={t("SIDEBAR.CATEGORY_LIST.GAMES")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.GAMES_DESCRIPTION")}></Category>
|
||||
<style is:inline>a[href="/category/gaming"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
10
src/pages/category/movies.astro
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Category GradientHero="#ff4f4f" FetchData="?type=movies" CategoryName={t("SIDEBAR.CATEGORY_LIST.MOVIES")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.MOVIES_DESCRIPTION")}>
|
||||
</Category>
|
||||
<style is:inline>a[href="/category/movies"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
112
src/pages/category/music.astro
Normal file
|
@ -0,0 +1,112 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Default from "@layouts/Default.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
// Configuration
|
||||
import {
|
||||
DEFAULT_DATA_PROXY,
|
||||
DEFAULT_VIDEO_PROXY
|
||||
} from '../../../config.json'
|
||||
|
||||
// Components
|
||||
import MusicItem from '@components/MusicItem.astro'
|
||||
|
||||
// Fetch
|
||||
const fetchFrom = DEFAULT_DATA_PROXY + '/api/v1/trending?type=music'
|
||||
const response = await fetch(fetchFrom)
|
||||
const data = await response.json()
|
||||
|
||||
const heroItem = data.slice(0,1)
|
||||
---
|
||||
|
||||
<Default FetchData="?type=movies" Title={t("SIDEBAR.CATEGORY_LIST.MUSIC")} Description={t("SIDEBAR.CATEGORY_LIST.MUSIC_DESCRIPTION")}>
|
||||
<div class="category-hero">
|
||||
<div class="c-hero-content">
|
||||
<div style="width: 25%;">
|
||||
<h2>Music</h2>
|
||||
<p>Listen to the latest hits</p>
|
||||
</div>
|
||||
<div class="c-hero-video">
|
||||
{heroItem.map((data) =>
|
||||
<video autoplay muted src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + data.videoId + '&itag=22&local=true'}></video>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span id="gradient-header"></span>
|
||||
<div class="or-mu">
|
||||
<span></span>
|
||||
<p id="title">{t("MUSIC.TITLE")}</p>
|
||||
<p id="artist">{t("MUSIC.ARTIST")}</p>
|
||||
<p id="date">{t("MUSIC.UPLOADED")}</p>
|
||||
<p id="duration">{t("MUSIC.DURATION")}</p>
|
||||
</div>
|
||||
<div class="music-list">
|
||||
{data.map((data) =>
|
||||
<MusicItem
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Default>
|
||||
<style is:inline>a[href="/en /category/music"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
|
||||
<style lang="scss">
|
||||
.category-hero {
|
||||
margin-top: -80px;
|
||||
background: linear-gradient(180deg, #502969, transparent);
|
||||
padding-top: 80px;
|
||||
.c-hero-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
max-width: 1000px;
|
||||
justify-content: space-between;
|
||||
.c-hero-video {
|
||||
-webkit-mask-box-image: radial-gradient(rgb(0 0 0 / 50%), transparent);
|
||||
-webkit-mask-box-image: linear-gradient(90deg, black, rgba(0, 0, 0, 0));
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
video {
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
width: 75%;
|
||||
height: 100%;
|
||||
float: right;
|
||||
-webkit-mask-box-image: linear-gradient(270deg, black, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.or-mu {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
gap: 12px;
|
||||
grid-template-columns: 60px auto auto 80px 64px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
border-bottom: 1px #252525 solid;
|
||||
margin-bottom: 24px;
|
||||
position: sticky;
|
||||
top: 58px;
|
||||
background: black;
|
||||
#artist, #duration, #date {
|
||||
text-align: right;
|
||||
}
|
||||
#title {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
9
src/pages/category/trending.astro
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Category GradientHero="#ff650b" FetchData="" CategoryName={t("SIDEBAR.CATEGORY_LIST.TRENDING")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.TRENDING_DESCRIPTION")}></Category>
|
||||
<style is:inline>a[href="/category/trending"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
139
src/pages/channel/[...slug].astro
Normal file
|
@ -0,0 +1,139 @@
|
|||
---
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
// i18n
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
changeLanguage("en");
|
||||
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../config.json";
|
||||
import { BrightStar, Donate, Download, ShareIos, ThumbsUp } from "@iconoir/vue";
|
||||
|
||||
// Components
|
||||
import Video from '@components/VideoItem.astro'
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("channel/").pop();
|
||||
const channel = await fetch(DEFAULT_DATA_PROXY + "/api/v1/channels/" + SWV).then((response) => response.json());
|
||||
const DescriptionFormat = channel.descriptionHtml.replaceAll("\n", " <br/> ");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="channel-backdrop">
|
||||
<img src={channel.authorBanners[1].url}/>
|
||||
</div>
|
||||
<div class="channel">
|
||||
<div class="channel-header">
|
||||
<div class="channel-banner">
|
||||
<img src={channel.authorBanners[1].url}/>
|
||||
</div>
|
||||
<div class="channel-meta">
|
||||
<div>
|
||||
<img src={channel.authorThumbnails[1].url}/>
|
||||
<h2>{channel.author}</h2>
|
||||
<p>{channel.subCountText}</p>
|
||||
</div>
|
||||
<div>
|
||||
<!-- {channel.isFamilyFriendly ? <p id="family-friendly"><BrightStar/> {t("CHANNEL.FAMILY_FRIENDLY")}</p> : null} -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="channel-content">
|
||||
<!-- <div class="channel-tabs">
|
||||
<a href="#">{t("CHANNEL.HOME")}</a>
|
||||
<a href="#">{t("CHANNEL.VIDEOS")}</a>
|
||||
<a href="#">{t("CHANNEL.COMMUNITY")}</a>
|
||||
</div> -->
|
||||
<div class="channel-tab-content">
|
||||
<h2>{t("CHANNEL.ABOUT")} {channel.author}</h2>
|
||||
<p><Fragment set:html={DescriptionFormat}/></p>
|
||||
<hr/>
|
||||
<h2>{t("CHANNEL.LATEST")}</h2>
|
||||
<div class="video-grid">
|
||||
{channel.latestVideos.map((data) =>
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
<!-- <a>View All Latest Videos</a> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style lang="scss">
|
||||
.channel-backdrop img {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
filter: blur(30px) contrast(0.8);
|
||||
z-index: -1;
|
||||
transform: scale(1.4);
|
||||
opacity: 0.3;
|
||||
display: none;
|
||||
}
|
||||
.channel {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.channel-header {
|
||||
.channel-banner {
|
||||
margin: 12px 0px;
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
.channel-meta {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
#family-friendly {
|
||||
color: white;
|
||||
background: #3b003b;
|
||||
border: 1px #a500a5 solid;
|
||||
border-radius: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
gap: 12px;
|
||||
pointer-events: none;
|
||||
}
|
||||
div:nth-child(1) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 12px;
|
||||
img {
|
||||
border-radius: 3rem;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.channel-content {
|
||||
.channel-tabs {
|
||||
padding-top: 24px;
|
||||
padding-bottom: 12px;
|
||||
cursor: default;
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
padding: 12px 24px;
|
||||
border-radius: 24px;
|
||||
&:hover {
|
||||
background: rgba(41, 41, 41, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
58
src/pages/discover/tech.astro
Normal file
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
|
||||
import Discover from "@layouts/Discover.astro";
|
||||
// Properties
|
||||
const { FetchData, CategoryName, CategoryDescription } = Astro.props;
|
||||
// Use on top of Default Layout
|
||||
import Base from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../config.json";
|
||||
// Discover Data
|
||||
import Discover from "../../data/discover.json";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base>
|
||||
<div class="video-grid">
|
||||
{Discover.Tech.map((channel) =>
|
||||
<a href={'/channel/' + channel.Link} style={"background: url('" + DEFAULT_DATA_PROXY + channel.Banner} class="discovery-channel">
|
||||
<div class="dc-c">
|
||||
<img src={DEFAULT_DATA_PROXY + channel.Logo}/>
|
||||
<p>{channel.Name}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<hr/>
|
||||
<div style="max-width: 1000px; margin: auto; text-align: center;">
|
||||
<p>This is a curated list for all MinPluto users.</p>
|
||||
<p>Is there a channel missing here that you think should be added? You can either <a href="https://sudovanilla.com/code/MinPluto/MinPluto/src/branch/main/src/data/discover.json">edit our list here</a> or you can <a href="https://community.minpluto.org/">submit a request</a>.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/discover/tech"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style lang="scss">
|
||||
.discovery-channel {
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
font-weight: bold;
|
||||
background-position: center !important;
|
||||
background-size: cover !important;
|
||||
.dc-c {
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
backdrop-filter: blur(24px) contrast(0.7) brightness(0.4);
|
||||
img {
|
||||
width: 24%;
|
||||
align-self: center;
|
||||
border-radius: 10rem;
|
||||
padding: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
93
src/pages/embed/[...slug].astro
Normal file
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Embed from "@layouts/Embed.astro";
|
||||
import "@styles/video.scss";
|
||||
// Configuration
|
||||
import { DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../config.json";
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("embed/").pop();
|
||||
const video = await fetch(DEFAULT_DATA_PROXY + "/api/v1/videos/" + SWV).then((response) => response.json());
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Embed
|
||||
Title={video.title}
|
||||
EmbedId={video.videoId}
|
||||
EmbedVideo={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
EmbedImage={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
EmbedTitle={video.title}
|
||||
>
|
||||
<div class="video-container">
|
||||
<video
|
||||
class="zorn-player"
|
||||
autoplay
|
||||
poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
video-title={video.title}
|
||||
src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
>
|
||||
</video>
|
||||
</div>
|
||||
</Embed>
|
||||
|
||||
<script is:inline>
|
||||
function DownloadDialogShow() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function DownloadDialogHide() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
function ShareDialogShow() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function ShareDialogHide() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.video-container {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.zorn-player {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zorn-player-controls {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.dialog-downloads-list {
|
||||
display: grid;
|
||||
grid-gap: 12px;
|
||||
a {
|
||||
background: rgb(51 51 51);
|
||||
border: 2px rgba(255,255,255,0.05) solid;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
padding: 9px 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
20
src/pages/en/404.astro
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<h2>Error 404</h2>
|
||||
<p>Page not found.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
</style>
|
9
src/pages/en/category/gaming.astro
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Category GradientHero="#269753" FetchData="?type=gaming" CategoryName={t("SIDEBAR.CATEGORY_LIST.GAMES")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.GAMES_DESCRIPTION")}></Category>
|
||||
<style is:inline>a[href="/category/gaming"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
10
src/pages/en/category/movies.astro
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Category GradientHero="#ff4f4f" FetchData="?type=movies" CategoryName={t("SIDEBAR.CATEGORY_LIST.MOVIES")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.MOVIES_DESCRIPTION")}>
|
||||
</Category>
|
||||
<style is:inline>a[href="/category/movies"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
106
src/pages/en/category/music.astro
Normal file
|
@ -0,0 +1,106 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Default from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_VIDEO_PROXY } from "../../../../config.json";
|
||||
// Components
|
||||
import MusicItem from "@components/MusicItem.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
// Fetch
|
||||
const fetchFrom = DEFAULT_DATA_PROXY + "/api/v1/trending?type=music";
|
||||
const response = await fetch(fetchFrom);
|
||||
const data = await response.json();
|
||||
const heroItem = data.slice(0, 1);
|
||||
---
|
||||
|
||||
<Default FetchData="?type=movies" Title={t("SIDEBAR.CATEGORY_LIST.MUSIC")} Description={t("SIDEBAR.CATEGORY_LIST.MUSIC_DESCRIPTION")}>
|
||||
<div class="category-hero">
|
||||
<div class="c-hero-content">
|
||||
<div style="width: 25%;">
|
||||
<h2>Music</h2>
|
||||
<p>Listen to the latest hits</p>
|
||||
</div>
|
||||
<div class="c-hero-video">
|
||||
{heroItem.map((data) =>
|
||||
<video autoplay muted src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + data.videoId + '&itag=22&local=true'}></video>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span id="gradient-header"></span>
|
||||
<div class="or-mu">
|
||||
<span></span>
|
||||
<p id="title">{t("MUSIC.TITLE")}</p>
|
||||
<p id="artist">{t("MUSIC.ARTIST")}</p>
|
||||
<p id="date">{t("MUSIC.UPLOADED")}</p>
|
||||
<p id="duration">{t("MUSIC.DURATION")}</p>
|
||||
</div>
|
||||
<div class="music-list">
|
||||
{data.map((data) =>
|
||||
<MusicItem
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Default>
|
||||
<style is:inline>a[href="/en /category/music"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
|
||||
<style lang="scss">
|
||||
.category-hero {
|
||||
margin-top: -80px;
|
||||
background: linear-gradient(180deg, #502969, transparent);
|
||||
padding-top: 80px;
|
||||
.c-hero-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
max-width: 1000px;
|
||||
justify-content: space-between;
|
||||
.c-hero-video {
|
||||
-webkit-mask-box-image: radial-gradient(rgb(0 0 0 / 50%), transparent);
|
||||
-webkit-mask-box-image: linear-gradient(90deg, black, rgba(0, 0, 0, 0));
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
video {
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
width: 75%;
|
||||
height: 100%;
|
||||
float: right;
|
||||
-webkit-mask-box-image: linear-gradient(270deg, black, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.or-mu {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
gap: 12px;
|
||||
grid-template-columns: 60px auto auto 80px 64px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
border-bottom: 1px #252525 solid;
|
||||
margin-bottom: 24px;
|
||||
position: sticky;
|
||||
top: 58px;
|
||||
background: black;
|
||||
#artist, #duration, #date {
|
||||
text-align: right;
|
||||
}
|
||||
#title {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
9
src/pages/en/category/trending.astro
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Category GradientHero="#ff650b" FetchData="" CategoryName={t("SIDEBAR.CATEGORY_LIST.TRENDING")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.TRENDING_DESCRIPTION")}></Category>
|
||||
<style is:inline>a[href="/category/trending"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
137
src/pages/en/channel/[...slug].astro
Normal file
|
@ -0,0 +1,137 @@
|
|||
---
|
||||
import Base from "@layouts/Default.astro";
|
||||
// i18n
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../../config.json";
|
||||
import { BrightStar, Donate, Download, ShareIos, ThumbsUp } from "@iconoir/vue";
|
||||
// Components
|
||||
import Video from "@components/VideoItem.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("channel/").pop();
|
||||
const channel = await fetch(DEFAULT_DATA_PROXY + "/api/v1/channels/" + SWV).then((response) => response.json());
|
||||
const DescriptionFormat = channel.descriptionHtml.replaceAll("\n", " <br/> ");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="channel-backdrop">
|
||||
<img src={channel.authorBanners[1].url}/>
|
||||
</div>
|
||||
<div class="channel">
|
||||
<div class="channel-header">
|
||||
<div class="channel-banner">
|
||||
<img src={channel.authorBanners[1].url}/>
|
||||
</div>
|
||||
<div class="channel-meta">
|
||||
<div>
|
||||
<img src={channel.authorThumbnails[1].url}/>
|
||||
<h2>{channel.author}</h2>
|
||||
<p>{channel.subCountText}</p>
|
||||
</div>
|
||||
<div>
|
||||
<!-- {channel.isFamilyFriendly ? <p id="family-friendly"><BrightStar/> {t("CHANNEL.FAMILY_FRIENDLY")}</p> : null} -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="channel-content">
|
||||
<!-- <div class="channel-tabs">
|
||||
<a href="#">{t("CHANNEL.HOME")}</a>
|
||||
<a href="#">{t("CHANNEL.VIDEOS")}</a>
|
||||
<a href="#">{t("CHANNEL.COMMUNITY")}</a>
|
||||
</div> -->
|
||||
<div class="channel-tab-content">
|
||||
<h2>{t("CHANNEL.ABOUT")} {channel.author}</h2>
|
||||
<p><Fragment set:html={DescriptionFormat}/></p>
|
||||
<hr/>
|
||||
<h2>{t("CHANNEL.LATEST")}</h2>
|
||||
<div class="video-grid">
|
||||
{channel.latestVideos.map((data) =>
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
<!-- <a>View All Latest Videos</a> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style lang="scss">
|
||||
.channel-backdrop img {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
filter: blur(30px) contrast(0.8);
|
||||
z-index: -1;
|
||||
transform: scale(1.4);
|
||||
opacity: 0.3;
|
||||
display: none;
|
||||
}
|
||||
.channel {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.channel-header {
|
||||
.channel-banner {
|
||||
margin: 12px 0px;
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
.channel-meta {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
#family-friendly {
|
||||
color: white;
|
||||
background: #3b003b;
|
||||
border: 1px #a500a5 solid;
|
||||
border-radius: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
gap: 12px;
|
||||
pointer-events: none;
|
||||
}
|
||||
div:nth-child(1) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 12px;
|
||||
img {
|
||||
border-radius: 3rem;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.channel-content {
|
||||
.channel-tabs {
|
||||
padding-top: 24px;
|
||||
padding-bottom: 12px;
|
||||
cursor: default;
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
padding: 12px 24px;
|
||||
border-radius: 24px;
|
||||
&:hover {
|
||||
background: rgba(41, 41, 41, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
57
src/pages/en/discover/tech.astro
Normal file
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Discover from "@layouts/Discover.astro";
|
||||
// Properties
|
||||
const { FetchData, CategoryName, CategoryDescription } = Astro.props;
|
||||
// Use on top of Default Layout
|
||||
import Base from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../../config.json";
|
||||
// Discover Data
|
||||
import Discover from "../../../data/discover.json";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base>
|
||||
<div class="video-grid">
|
||||
{Discover.Tech.map((channel) =>
|
||||
<a href={'/channel/' + channel.Link} style={"background: url('" + DEFAULT_DATA_PROXY + channel.Banner} class="discovery-channel">
|
||||
<div class="dc-c">
|
||||
<img src={DEFAULT_DATA_PROXY + channel.Logo}/>
|
||||
<p>{channel.Name}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<hr/>
|
||||
<div style="max-width: 1000px; margin: auto; text-align: center;">
|
||||
<p>This is a curated list for all MinPluto users.</p>
|
||||
<p>Is there a channel missing here that you think should be added? You can either <a href="https://sudovanilla.com/code/MinPluto/MinPluto/src/branch/main/src/data/discover.json">edit our list here</a> or you can <a href="https://community.minpluto.org/">submit a request</a>.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/discover/tech"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style lang="scss">
|
||||
.discovery-channel {
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
font-weight: bold;
|
||||
background-position: center !important;
|
||||
background-size: cover !important;
|
||||
.dc-c {
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
backdrop-filter: blur(24px) contrast(0.7) brightness(0.4);
|
||||
img {
|
||||
width: 24%;
|
||||
align-self: center;
|
||||
border-radius: 10rem;
|
||||
padding: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
93
src/pages/en/embed/[...slug].astro
Normal file
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Embed from "@layouts/Embed.astro";
|
||||
import "@styles/video.scss";
|
||||
// Configuration
|
||||
import { DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../../config.json";
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("embed/").pop();
|
||||
const video = await fetch(DEFAULT_DATA_PROXY + "/api/v1/videos/" + SWV).then((response) => response.json());
|
||||
---
|
||||
|
||||
<Embed
|
||||
Title={video.title}
|
||||
EmbedId={video.videoId}
|
||||
EmbedVideo={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
EmbedImage={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
EmbedTitle={video.title}
|
||||
>
|
||||
<div class="video-container">
|
||||
<video
|
||||
class="zorn-player"
|
||||
autoplay
|
||||
poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
video-title={video.title}
|
||||
src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
>
|
||||
</video>
|
||||
</div>
|
||||
</Embed>
|
||||
|
||||
<script is:inline>
|
||||
function DownloadDialogShow() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function DownloadDialogHide() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
function ShareDialogShow() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function ShareDialogHide() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.video-container {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.zorn-player {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zorn-player-controls {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.dialog-downloads-list {
|
||||
display: grid;
|
||||
grid-gap: 12px;
|
||||
a {
|
||||
background: rgb(51 51 51);
|
||||
border: 2px rgba(255,255,255,0.05) solid;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
padding: 9px 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
143
src/pages/en/index.astro
Normal file
|
@ -0,0 +1,143 @@
|
|||
---
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import Dialog from "@components/Dialog.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../config.json";
|
||||
import { FireFlame, Frame, Gamepad, GraphUp, Movie, MusicDoubleNote } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
// Fetch
|
||||
const TrendingFetch = DEFAULT_DATA_PROXY + "/api/v1/trending";
|
||||
const TrendingResponse = await fetch(TrendingFetch);
|
||||
const TrendingData = await TrendingResponse.json();
|
||||
const TrendingSplit = TrendingData.slice(0, 1);
|
||||
const MoviesFetch = DEFAULT_DATA_PROXY + "/api/v1/trending?type=movies";
|
||||
const MoviesResponse = await fetch(MoviesFetch);
|
||||
const MoviesData = await MoviesResponse.json();
|
||||
const MoviesSplit = MoviesData.slice(0, 1);
|
||||
const MusicFetch = DEFAULT_DATA_PROXY + "/api/v1/trending?type=music";
|
||||
const MusicResponse = await fetch(MusicFetch);
|
||||
const MusicData = await MusicResponse.json();
|
||||
const MusicSplit = MusicData.slice(0, 1);
|
||||
const GamingFetch = DEFAULT_DATA_PROXY + "/api/v1/trending?type=gaming";
|
||||
const GamingResponse = await fetch(GamingFetch);
|
||||
const GamingData = await GamingResponse.json();
|
||||
const GamingSplit = GamingData.slice(0, 1);
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<hr/>
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</div>
|
||||
<div class="category-select-grid">
|
||||
{TrendingSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/trending'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<GraphUp viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.TRENDING")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{MoviesSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/movies'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<Movie viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.MOVIES")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{MusicSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/music'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<MusicDoubleNote viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.MUSIC")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{GamingSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/gaming'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<Gamepad viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.GAMES")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
.category-select-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) !important;
|
||||
}
|
||||
}
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
|
||||
.goin-card {
|
||||
height: 124px;
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
}
|
||||
|
||||
.goin-card-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0px 12px;
|
||||
height: 100%;
|
||||
place-content: center;
|
||||
border-radius: 10px;
|
||||
backdrop-filter: blur(3px) brightness(0.3) contrast(0.8);
|
||||
}
|
||||
.goin-card-content p {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
margin: 24px;
|
||||
}
|
||||
.goin-card-content svg {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
width: 50px;
|
||||
height: 120px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
opacity: 0.3;
|
||||
}
|
||||
.goin-card img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.category-select-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
grid-gap: 25px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
</style>
|
75
src/pages/en/instance.astro
Normal file
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import Dialog from "@components/Dialog.astro";
|
||||
// Configuration
|
||||
import { SERVER_ADMIN, ANALYLICS_TOOL, DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, DEFAULT_PLAYER, SERVER_LOCATION, MODIFIED, CUSTOM_SOURCE_CODE, STATISTICS } from "../../../config.json";
|
||||
import { FireFlame, Frame, Gamepad, GraphUp, Movie, MusicDoubleNote } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<hr/>
|
||||
<div class="video-grid">
|
||||
<div class="in">
|
||||
<h2>Operated By</h2>
|
||||
<p>{SERVER_ADMIN}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Analytics Software</h2>
|
||||
<p>
|
||||
{
|
||||
STATISTICS
|
||||
?
|
||||
<p>{ANALYLICS_TOOL}</p>
|
||||
:
|
||||
<p>None</p>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Location</h2>
|
||||
<p>{SERVER_LOCATION}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Modified</h2>
|
||||
<p>{MODIFIED ? <p>Yes</p> : <p>No</p>}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Video Proxy</h2>
|
||||
<a href={DEFAULT_VIDEO_PROXY}>{DEFAULT_VIDEO_PROXY}</a>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Image Proxy</h2>
|
||||
<a href={DEFAULT_IMAGE_PROXY}>{DEFAULT_IMAGE_PROXY}</a>
|
||||
</div>
|
||||
</div>
|
||||
{MODIFIED ? <p>Modified Source Code <a href={CUSTOM_SOURCE_CODE}>{CUSTOM_SOURCE_CODE}</a></p> : null}
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
.category-select-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) !important;
|
||||
}
|
||||
}
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
66
src/pages/en/m/about.astro
Normal file
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import { version } from "@root/package.json";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="ms">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<h2>MinPluto</h2>
|
||||
<p>{t("HOME.P1")}</p>
|
||||
<hr/>
|
||||
<p style="font-size: 14px;"><i>{t("HOME.P2")}</i></p>
|
||||
<hr/>
|
||||
<div style="display: flex; justify-content: space-evenly;">
|
||||
<a href="https://community.minpluto.org/" target="_blank">{t("SIDEBAR.FOOTER.STATUS")}</a>
|
||||
<a href="https://status.minpluto.org/" target="_blank">{t("SIDEBAR.FOOTER.FORUM")}</a>
|
||||
<a href="https://sudovanilla.com/code/MinPluto/MinPluto" target="_blank">{t("SIDEBAR.FOOTER.SOURCE_CODE")}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p id="version">v{version}</p>
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.ms {
|
||||
margin-top: 20%;
|
||||
text-align: center;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
hr {
|
||||
width: 100px;
|
||||
border: none;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
height: 4px;
|
||||
border-radius: 1rem;
|
||||
margin: 24px auto;
|
||||
}
|
||||
p#version {
|
||||
position: fixed;
|
||||
bottom: 88px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
background: #232323;
|
||||
color: white;
|
||||
padding: 24px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
40
src/pages/en/m/categories.astro
Normal file
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import { HomeSimple, GraphUp, Movie, MusicDoubleNote, Gamepad, AppleImac2021Side, EmojiTalkingHappy, PizzaSlice, Treadmill, PeaceHand } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div style="padding: 0px 24px;">
|
||||
<h2>Categories</h2>
|
||||
<div id="c" style="display: flex;flex-direction: column;gap: 24px;">
|
||||
<a href="/category/trending"><GraphUp/> {t("CATEGORY_LIST.TRENDING")}</a>
|
||||
<a href="/category/movies"><Movie/> {t("CATEGORY_LIST.MOVIES")}</a>
|
||||
<a href="/category/music"><MusicDoubleNote/> {t("CATEGORY_LIST.MUSIC")}</a>
|
||||
<a href="/category/gaming"><Gamepad/> {t("CATEGORY_LIST.GAMES")}</a>
|
||||
</div>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style lang="scss">
|
||||
#c a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
background: linear-gradient(45deg, #636363, #181818);
|
||||
padding: 48px 24px;
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
border-radius: 10px;
|
||||
svg {
|
||||
position: absolute;
|
||||
right: 60px;
|
||||
width: 100px;
|
||||
height: 70px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
</style>
|
20
src/pages/en/offline.astro
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<h2>No Internet Connection</h2>
|
||||
<p>It appears that you are offline, try connecting your device to the internet, and try again.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
</style>
|
35
src/pages/en/search.astro
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../config.json";
|
||||
import Video from "@components/VideoItem.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
// Fetch
|
||||
const SBO = Astro.url.href.split("search?query=").pop();
|
||||
const response = await fetch(DEFAULT_DATA_PROXY + "/api/v1/search?q=" + SBO)
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
const data = await response.json();
|
||||
---
|
||||
|
||||
<Base Title='MinPluto Search'>
|
||||
<div class="page-title">
|
||||
<h2>Search</h2>
|
||||
</div>
|
||||
<div class="video-grid">
|
||||
{data.map((data) =>
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Base>
|
207
src/pages/en/watch.astro
Normal file
|
@ -0,0 +1,207 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import "@styles/video.scss";
|
||||
// Configuration
|
||||
import { DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../config.json";
|
||||
import { Donate, Download, ShareIos, ThumbsUp, MediaVideo } from "@iconoir/vue";
|
||||
// Components
|
||||
import Dialog from "@components/Dialog.astro";
|
||||
import Video from "@components/VideoItem.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("watch?v=").pop();
|
||||
const video = await fetch(DEFAULT_DATA_PROXY + "/api/v1/videos/" + SWV).then((response) => response.json());
|
||||
const comments = await fetch(DEFAULT_DATA_PROXY + "/api/v1/comments/" + SWV).then((response) => response.json());
|
||||
const Description = video.description;
|
||||
const UploadDate = video.published;
|
||||
const Views = video.viewCount;
|
||||
const VideoSeconds = video.lengthSeconds;
|
||||
let DescriptionFormat = Description.replaceAll("\n", " <br/> ");
|
||||
// Format Published Date
|
||||
const DateFormat = new Date(UploadDate * 1000).toLocaleDateString();
|
||||
// Format Video Length
|
||||
// Thanks to "mingjunlu" for helping out with the time format
|
||||
new Date(VideoSeconds * 1000)
|
||||
.toISOString()
|
||||
.slice(14, 19)
|
||||
.split(":")
|
||||
.map(Number)
|
||||
.join(":");
|
||||
// Format Views
|
||||
const ViewsConversion = Intl.NumberFormat("en", { notation: "compact" });
|
||||
let ViewsFormat = ViewsConversion.format(Views);
|
||||
---
|
||||
|
||||
<Base Title={video.title}>
|
||||
<div class="video-container">
|
||||
<video
|
||||
class="zorn-player"
|
||||
autoplay
|
||||
poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
video-title={video.title}
|
||||
src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
>
|
||||
</video>
|
||||
</div>
|
||||
<div class="video-rea">
|
||||
<div class="rea-details">
|
||||
<p style="font-weight: bold; font-size: 24px;">{video.title}</p>
|
||||
<div class="rea-details-start">
|
||||
<a style="text-decoration: none;" href={video.authorUrl} class="rea-channel">
|
||||
<img src={video.authorThumbnails[1].url} />
|
||||
<div
|
||||
style="display: flex; flex-direction: column; align-items: left;"
|
||||
>
|
||||
<h2 style="margin: 0px; font-weight: bold; font-size: 18px;">{video.author}</h2>
|
||||
<p style="margin: 0px;" id="subs">
|
||||
{video.subCountText} Subscribers
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<div style="display: flex; flex-direction: row; align-items: left;">
|
||||
<button onclick="DownloadDialogShow()"><Download /> Download</button>
|
||||
<button onclick={'location.href = "/embed/' + video.videoId + '/"'}><MediaVideo /> Embed</button>
|
||||
<button onclick="ShareDialogShow()"><ShareIos /> Share</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rea-details-end">
|
||||
<p id="views">{ViewsFormat} Views - {DateFormat}</p>
|
||||
<Fragment set:html={DescriptionFormat} />
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 24px;">
|
||||
<div class="rea-comments">
|
||||
<h2>{t("WATCH.COMMENTS")}</h2>
|
||||
{
|
||||
comments.comments.map((comment) => (
|
||||
<div class="comment">
|
||||
<img
|
||||
src={
|
||||
DEFAULT_IMAGE_PROXY + "/" + comment.authorThumbnails[1].url
|
||||
}
|
||||
/>
|
||||
<div>
|
||||
<p>
|
||||
<a href={comment.authorUrl}>{comment.author}</a> - 2 Months
|
||||
Ago
|
||||
</p>
|
||||
<p>{comment.contentHtml}</p>
|
||||
<p>
|
||||
<ThumbsUp /> {comment.likeCount}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="rea-recommendations">
|
||||
<h2>{t("WATCH.RELATED")}</h2>
|
||||
{
|
||||
video.recommendedVideos.map((data) => (
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Dialog
|
||||
Title="Download"
|
||||
Description="Choose a download method"
|
||||
Closable
|
||||
CloseOnclick="DownloadDialogHide()"
|
||||
>
|
||||
<p>Video</p>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={video.formatStreams[1].url} download={video.title + '.mp4'} target="_blank">Download</a>
|
||||
</div>
|
||||
<p>Audio Only</p>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={video.adaptiveFormats[1].url} download={video.title + '.mp3'} target="_blank">Download</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
<Dialog
|
||||
Title="Share"
|
||||
Description="Choose a share method"
|
||||
Closable
|
||||
CloseOnclick="ShareDialogHide()"
|
||||
>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={'https://mastodonshare.com/?url=' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Mastodon</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Misskey</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Firefish</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Elk</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Lemmy</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Base>
|
||||
|
||||
<script is:inline>
|
||||
function DownloadDialogShow() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function DownloadDialogHide() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
function ShareDialogShow() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function ShareDialogHide() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.video-container {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.zorn-player {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zorn-player-controls {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.dialog-downloads-list {
|
||||
display: grid;
|
||||
grid-gap: 12px;
|
||||
a {
|
||||
background: rgb(51 51 51);
|
||||
border: 2px rgba(255,255,255,0.05) solid;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
padding: 9px 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
156
src/pages/index.astro
Normal file
|
@ -0,0 +1,156 @@
|
|||
---
|
||||
import i18next,{ t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
import Dialog from '@components/Dialog.astro'
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
// Configuration
|
||||
import {
|
||||
DEFAULT_DATA_PROXY,
|
||||
DEFAULT_IMAGE_PROXY
|
||||
} from '../../config.json'
|
||||
import { FireFlame, Frame, Gamepad, GraphUp, Movie, MusicDoubleNote } from "@iconoir/vue";
|
||||
|
||||
// Fetch
|
||||
const TrendingFetch = DEFAULT_DATA_PROXY + '/api/v1/trending'
|
||||
const TrendingResponse = await fetch(TrendingFetch)
|
||||
const TrendingData = await TrendingResponse.json()
|
||||
const TrendingSplit = TrendingData.slice(0, 1)
|
||||
|
||||
const MoviesFetch = DEFAULT_DATA_PROXY + '/api/v1/trending?type=movies'
|
||||
const MoviesResponse = await fetch(MoviesFetch)
|
||||
const MoviesData = await MoviesResponse.json()
|
||||
const MoviesSplit = MoviesData.slice(0, 1)
|
||||
|
||||
|
||||
const MusicFetch = DEFAULT_DATA_PROXY + '/api/v1/trending?type=music'
|
||||
const MusicResponse = await fetch(MusicFetch)
|
||||
const MusicData = await MusicResponse.json()
|
||||
const MusicSplit = MusicData.slice(0, 1)
|
||||
|
||||
|
||||
const GamingFetch = DEFAULT_DATA_PROXY + '/api/v1/trending?type=gaming'
|
||||
const GamingResponse = await fetch(GamingFetch)
|
||||
const GamingData = await GamingResponse.json()
|
||||
const GamingSplit = GamingData.slice(0, 1)
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<hr/>
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</div>
|
||||
<div class="category-select-grid">
|
||||
{TrendingSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/trending'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<GraphUp viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.TRENDING")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{MoviesSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/movies'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<Movie viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.MOVIES")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{MusicSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/music'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<MusicDoubleNote viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.MUSIC")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{GamingSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/gaming'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<Gamepad viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.GAMES")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
.category-select-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) !important;
|
||||
}
|
||||
}
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
|
||||
.goin-card {
|
||||
height: 124px;
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
}
|
||||
|
||||
.goin-card-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0px 12px;
|
||||
height: 100%;
|
||||
place-content: center;
|
||||
border-radius: 10px;
|
||||
backdrop-filter: blur(3px) brightness(0.3) contrast(0.8);
|
||||
}
|
||||
.goin-card-content p {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
margin: 24px;
|
||||
}
|
||||
.goin-card-content svg {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
width: 50px;
|
||||
height: 120px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
opacity: 0.3;
|
||||
}
|
||||
.goin-card img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.category-select-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
grid-gap: 25px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
</style>
|
88
src/pages/instance.astro
Normal file
|
@ -0,0 +1,88 @@
|
|||
---
|
||||
import i18next,{ t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
import Dialog from '@components/Dialog.astro'
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
// Configuration
|
||||
import {
|
||||
SERVER_ADMIN,
|
||||
ANALYLICS_TOOL,
|
||||
DEFAULT_VIDEO_PROXY,
|
||||
DEFAULT_DATA_PROXY,
|
||||
DEFAULT_IMAGE_PROXY,
|
||||
DEFAULT_PLAYER,
|
||||
SERVER_LOCATION,
|
||||
MODIFIED,
|
||||
CUSTOM_SOURCE_CODE,
|
||||
STATISTICS
|
||||
} from '../../config.json'
|
||||
import { FireFlame, Frame, Gamepad, GraphUp, Movie, MusicDoubleNote } from "@iconoir/vue";
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<hr/>
|
||||
<div class="video-grid">
|
||||
<div class="in">
|
||||
<h2>Operated By</h2>
|
||||
<p>{SERVER_ADMIN}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Analytics Software</h2>
|
||||
<p>
|
||||
{
|
||||
STATISTICS
|
||||
?
|
||||
<p>{ANALYLICS_TOOL}</p>
|
||||
:
|
||||
<p>None</p>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Location</h2>
|
||||
<p>{SERVER_LOCATION}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Modified</h2>
|
||||
<p>{MODIFIED ? <p>Yes</p> : <p>No</p>}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Video Proxy</h2>
|
||||
<a href={DEFAULT_VIDEO_PROXY}>{DEFAULT_VIDEO_PROXY}</a>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Image Proxy</h2>
|
||||
<a href={DEFAULT_IMAGE_PROXY}>{DEFAULT_IMAGE_PROXY}</a>
|
||||
</div>
|
||||
</div>
|
||||
{MODIFIED ? <p>Modified Source Code <a href={CUSTOM_SOURCE_CODE}>{CUSTOM_SOURCE_CODE}</a></p> : null}
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
.category-select-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) !important;
|
||||
}
|
||||
}
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
20
src/pages/jp/404.astro
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
changeLanguage("jp");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<h2>Error 404</h2>
|
||||
<p>Page not found.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
</style>
|
9
src/pages/jp/category/gaming.astro
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("jp");
|
||||
---
|
||||
|
||||
<Category GradientHero="#269753" FetchData="?type=gaming" CategoryName={t("SIDEBAR.CATEGORY_LIST.GAMES")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.GAMES_DESCRIPTION")}></Category>
|
||||
<style is:inline>a[href="/category/gaming"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
10
src/pages/jp/category/movies.astro
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("jp");
|
||||
---
|
||||
|
||||
<Category GradientHero="#ff4f4f" FetchData="?type=movies" CategoryName={t("SIDEBAR.CATEGORY_LIST.MOVIES")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.MOVIES_DESCRIPTION")}>
|
||||
</Category>
|
||||
<style is:inline>a[href="/category/movies"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
106
src/pages/jp/category/music.astro
Normal file
|
@ -0,0 +1,106 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Default from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_VIDEO_PROXY } from "../../../../config.json";
|
||||
// Components
|
||||
import MusicItem from "@components/MusicItem.astro";
|
||||
|
||||
changeLanguage("jp");
|
||||
|
||||
// Fetch
|
||||
const fetchFrom = DEFAULT_DATA_PROXY + "/api/v1/trending?type=music";
|
||||
const response = await fetch(fetchFrom);
|
||||
const data = await response.json();
|
||||
const heroItem = data.slice(0, 1);
|
||||
---
|
||||
|
||||
<Default FetchData="?type=movies" Title={t("SIDEBAR.CATEGORY_LIST.MUSIC")} Description={t("SIDEBAR.CATEGORY_LIST.MUSIC_DESCRIPTION")}>
|
||||
<div class="category-hero">
|
||||
<div class="c-hero-content">
|
||||
<div style="width: 25%;">
|
||||
<h2>Music</h2>
|
||||
<p>Listen to the latest hits</p>
|
||||
</div>
|
||||
<div class="c-hero-video">
|
||||
{heroItem.map((data) =>
|
||||
<video autoplay muted src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + data.videoId + '&itag=22&local=true'}></video>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span id="gradient-header"></span>
|
||||
<div class="or-mu">
|
||||
<span></span>
|
||||
<p id="title">{t("MUSIC.TITLE")}</p>
|
||||
<p id="artist">{t("MUSIC.ARTIST")}</p>
|
||||
<p id="date">{t("MUSIC.UPLOADED")}</p>
|
||||
<p id="duration">{t("MUSIC.DURATION")}</p>
|
||||
</div>
|
||||
<div class="music-list">
|
||||
{data.map((data) =>
|
||||
<MusicItem
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Default>
|
||||
<style is:inline>a[href="/en /category/music"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
|
||||
<style lang="scss">
|
||||
.category-hero {
|
||||
margin-top: -80px;
|
||||
background: linear-gradient(180deg, #502969, transparent);
|
||||
padding-top: 80px;
|
||||
.c-hero-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
max-width: 1000px;
|
||||
justify-content: space-between;
|
||||
.c-hero-video {
|
||||
-webkit-mask-box-image: radial-gradient(rgb(0 0 0 / 50%), transparent);
|
||||
-webkit-mask-box-image: linear-gradient(90deg, black, rgba(0, 0, 0, 0));
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
video {
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
width: 75%;
|
||||
height: 100%;
|
||||
float: right;
|
||||
-webkit-mask-box-image: linear-gradient(270deg, black, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.or-mu {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
gap: 12px;
|
||||
grid-template-columns: 60px auto auto 80px 64px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
border-bottom: 1px #252525 solid;
|
||||
margin-bottom: 24px;
|
||||
position: sticky;
|
||||
top: 58px;
|
||||
background: black;
|
||||
#artist, #duration, #date {
|
||||
text-align: right;
|
||||
}
|
||||
#title {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
9
src/pages/jp/category/trending.astro
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("jp");
|
||||
---
|
||||
|
||||
<Category GradientHero="#ff650b" FetchData="" CategoryName={t("SIDEBAR.CATEGORY_LIST.TRENDING")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.TRENDING_DESCRIPTION")}></Category>
|
||||
<style is:inline>a[href="/category/trending"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
137
src/pages/jp/channel/[...slug].astro
Normal file
|
@ -0,0 +1,137 @@
|
|||
---
|
||||
import Base from "@layouts/Default.astro";
|
||||
// i18n
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../../config.json";
|
||||
import { BrightStar, Donate, Download, ShareIos, ThumbsUp } from "@iconoir/vue";
|
||||
// Components
|
||||
import Video from "@components/VideoItem.astro";
|
||||
|
||||
changeLanguage("jp");
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("channel/").pop();
|
||||
const channel = await fetch(DEFAULT_DATA_PROXY + "/api/v1/channels/" + SWV).then((response) => response.json());
|
||||
const DescriptionFormat = channel.descriptionHtml.replaceAll("\n", " <br/> ");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="channel-backdrop">
|
||||
<img src={channel.authorBanners[1].url}/>
|
||||
</div>
|
||||
<div class="channel">
|
||||
<div class="channel-header">
|
||||
<div class="channel-banner">
|
||||
<img src={channel.authorBanners[1].url}/>
|
||||
</div>
|
||||
<div class="channel-meta">
|
||||
<div>
|
||||
<img src={channel.authorThumbnails[1].url}/>
|
||||
<h2>{channel.author}</h2>
|
||||
<p>{channel.subCountText}</p>
|
||||
</div>
|
||||
<div>
|
||||
<!-- {channel.isFamilyFriendly ? <p id="family-friendly"><BrightStar/> {t("CHANNEL.FAMILY_FRIENDLY")}</p> : null} -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="channel-content">
|
||||
<!-- <div class="channel-tabs">
|
||||
<a href="#">{t("CHANNEL.HOME")}</a>
|
||||
<a href="#">{t("CHANNEL.VIDEOS")}</a>
|
||||
<a href="#">{t("CHANNEL.COMMUNITY")}</a>
|
||||
</div> -->
|
||||
<div class="channel-tab-content">
|
||||
<h2>{t("CHANNEL.ABOUT")} {channel.author}</h2>
|
||||
<p><Fragment set:html={DescriptionFormat}/></p>
|
||||
<hr/>
|
||||
<h2>{t("CHANNEL.LATEST")}</h2>
|
||||
<div class="video-grid">
|
||||
{channel.latestVideos.map((data) =>
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
<!-- <a>View All Latest Videos</a> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style lang="scss">
|
||||
.channel-backdrop img {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
filter: blur(30px) contrast(0.8);
|
||||
z-index: -1;
|
||||
transform: scale(1.4);
|
||||
opacity: 0.3;
|
||||
display: none;
|
||||
}
|
||||
.channel {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.channel-header {
|
||||
.channel-banner {
|
||||
margin: 12px 0px;
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
.channel-meta {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
#family-friendly {
|
||||
color: white;
|
||||
background: #3b003b;
|
||||
border: 1px #a500a5 solid;
|
||||
border-radius: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
gap: 12px;
|
||||
pointer-events: none;
|
||||
}
|
||||
div:nth-child(1) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 12px;
|
||||
img {
|
||||
border-radius: 3rem;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.channel-content {
|
||||
.channel-tabs {
|
||||
padding-top: 24px;
|
||||
padding-bottom: 12px;
|
||||
cursor: default;
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
padding: 12px 24px;
|
||||
border-radius: 24px;
|
||||
&:hover {
|
||||
background: rgba(41, 41, 41, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
57
src/pages/jp/discover/tech.astro
Normal file
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Discover from "@layouts/Discover.astro";
|
||||
// Properties
|
||||
const { FetchData, CategoryName, CategoryDescription } = Astro.props;
|
||||
// Use on top of Default Layout
|
||||
import Base from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../../config.json";
|
||||
// Discover Data
|
||||
import Discover from "../../../data/discover.json";
|
||||
|
||||
changeLanguage("jp");
|
||||
---
|
||||
|
||||
<Base>
|
||||
<div class="video-grid">
|
||||
{Discover.Tech.map((channel) =>
|
||||
<a href={'/channel/' + channel.Link} style={"background: url('" + DEFAULT_DATA_PROXY + channel.Banner} class="discovery-channel">
|
||||
<div class="dc-c">
|
||||
<img src={DEFAULT_DATA_PROXY + channel.Logo}/>
|
||||
<p>{channel.Name}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<hr/>
|
||||
<div style="max-width: 1000px; margin: auto; text-align: center;">
|
||||
<p>This is a curated list for all MinPluto users.</p>
|
||||
<p>Is there a channel missing here that you think should be added? You can either <a href="https://sudovanilla.com/code/MinPluto/MinPluto/src/branch/main/src/data/discover.json">edit our list here</a> or you can <a href="https://community.minpluto.org/">submit a request</a>.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/discover/tech"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style lang="scss">
|
||||
.discovery-channel {
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
font-weight: bold;
|
||||
background-position: center !important;
|
||||
background-size: cover !important;
|
||||
.dc-c {
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
backdrop-filter: blur(24px) contrast(0.7) brightness(0.4);
|
||||
img {
|
||||
width: 24%;
|
||||
align-self: center;
|
||||
border-radius: 10rem;
|
||||
padding: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
93
src/pages/jp/embed/[...slug].astro
Normal file
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Embed from "@layouts/Embed.astro";
|
||||
import "@styles/video.scss";
|
||||
// Configuration
|
||||
import { DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../../config.json";
|
||||
|
||||
changeLanguage("jp");
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("embed/").pop();
|
||||
const video = await fetch(DEFAULT_DATA_PROXY + "/api/v1/videos/" + SWV).then((response) => response.json());
|
||||
---
|
||||
|
||||
<Embed
|
||||
Title={video.title}
|
||||
EmbedId={video.videoId}
|
||||
EmbedVideo={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
EmbedImage={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
EmbedTitle={video.title}
|
||||
>
|
||||
<div class="video-container">
|
||||
<video
|
||||
class="zorn-player"
|
||||
autoplay
|
||||
poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
video-title={video.title}
|
||||
src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
>
|
||||
</video>
|
||||
</div>
|
||||
</Embed>
|
||||
|
||||
<script is:inline>
|
||||
function DownloadDialogShow() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function DownloadDialogHide() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
function ShareDialogShow() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function ShareDialogHide() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.video-container {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.zorn-player {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zorn-player-controls {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.dialog-downloads-list {
|
||||
display: grid;
|
||||
grid-gap: 12px;
|
||||
a {
|
||||
background: rgb(51 51 51);
|
||||
border: 2px rgba(255,255,255,0.05) solid;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
padding: 9px 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
143
src/pages/jp/index.astro
Normal file
|
@ -0,0 +1,143 @@
|
|||
---
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import Dialog from "@components/Dialog.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../config.json";
|
||||
import { FireFlame, Frame, Gamepad, GraphUp, Movie, MusicDoubleNote } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("jp");
|
||||
|
||||
// Fetch
|
||||
const TrendingFetch = DEFAULT_DATA_PROXY + "/api/v1/trending";
|
||||
const TrendingResponse = await fetch(TrendingFetch);
|
||||
const TrendingData = await TrendingResponse.json();
|
||||
const TrendingSplit = TrendingData.slice(0, 1);
|
||||
const MoviesFetch = DEFAULT_DATA_PROXY + "/api/v1/trending?type=movies";
|
||||
const MoviesResponse = await fetch(MoviesFetch);
|
||||
const MoviesData = await MoviesResponse.json();
|
||||
const MoviesSplit = MoviesData.slice(0, 1);
|
||||
const MusicFetch = DEFAULT_DATA_PROXY + "/api/v1/trending?type=music";
|
||||
const MusicResponse = await fetch(MusicFetch);
|
||||
const MusicData = await MusicResponse.json();
|
||||
const MusicSplit = MusicData.slice(0, 1);
|
||||
const GamingFetch = DEFAULT_DATA_PROXY + "/api/v1/trending?type=gaming";
|
||||
const GamingResponse = await fetch(GamingFetch);
|
||||
const GamingData = await GamingResponse.json();
|
||||
const GamingSplit = GamingData.slice(0, 1);
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<hr/>
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</div>
|
||||
<div class="category-select-grid">
|
||||
{TrendingSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/trending'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<GraphUp viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.TRENDING")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{MoviesSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/movies'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<Movie viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.MOVIES")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{MusicSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/music'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<MusicDoubleNote viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.MUSIC")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{GamingSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/gaming'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<Gamepad viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.GAMES")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
.category-select-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) !important;
|
||||
}
|
||||
}
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
|
||||
.goin-card {
|
||||
height: 124px;
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
}
|
||||
|
||||
.goin-card-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0px 12px;
|
||||
height: 100%;
|
||||
place-content: center;
|
||||
border-radius: 10px;
|
||||
backdrop-filter: blur(3px) brightness(0.3) contrast(0.8);
|
||||
}
|
||||
.goin-card-content p {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
margin: 24px;
|
||||
}
|
||||
.goin-card-content svg {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
width: 50px;
|
||||
height: 120px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
opacity: 0.3;
|
||||
}
|
||||
.goin-card img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.category-select-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
grid-gap: 25px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
</style>
|
75
src/pages/jp/instance.astro
Normal file
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import Dialog from "@components/Dialog.astro";
|
||||
// Configuration
|
||||
import { SERVER_ADMIN, ANALYLICS_TOOL, DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, DEFAULT_PLAYER, SERVER_LOCATION, MODIFIED, CUSTOM_SOURCE_CODE, STATISTICS } from "../../../config.json";
|
||||
import { FireFlame, Frame, Gamepad, GraphUp, Movie, MusicDoubleNote } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("jp");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<hr/>
|
||||
<div class="video-grid">
|
||||
<div class="in">
|
||||
<h2>Operated By</h2>
|
||||
<p>{SERVER_ADMIN}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Analytics Software</h2>
|
||||
<p>
|
||||
{
|
||||
STATISTICS
|
||||
?
|
||||
<p>{ANALYLICS_TOOL}</p>
|
||||
:
|
||||
<p>None</p>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Location</h2>
|
||||
<p>{SERVER_LOCATION}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Modified</h2>
|
||||
<p>{MODIFIED ? <p>Yes</p> : <p>No</p>}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Video Proxy</h2>
|
||||
<a href={DEFAULT_VIDEO_PROXY}>{DEFAULT_VIDEO_PROXY}</a>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Image Proxy</h2>
|
||||
<a href={DEFAULT_IMAGE_PROXY}>{DEFAULT_IMAGE_PROXY}</a>
|
||||
</div>
|
||||
</div>
|
||||
{MODIFIED ? <p>Modified Source Code <a href={CUSTOM_SOURCE_CODE}>{CUSTOM_SOURCE_CODE}</a></p> : null}
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
.category-select-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) !important;
|
||||
}
|
||||
}
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
66
src/pages/jp/m/about.astro
Normal file
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import { version } from "@root/package.json";
|
||||
|
||||
changeLanguage("jp");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="ms">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<h2>MinPluto</h2>
|
||||
<p>{t("HOME.P1")}</p>
|
||||
<hr/>
|
||||
<p style="font-size: 14px;"><i>{t("HOME.P2")}</i></p>
|
||||
<hr/>
|
||||
<div style="display: flex; justify-content: space-evenly;">
|
||||
<a href="https://community.minpluto.org/" target="_blank">{t("SIDEBAR.FOOTER.STATUS")}</a>
|
||||
<a href="https://status.minpluto.org/" target="_blank">{t("SIDEBAR.FOOTER.FORUM")}</a>
|
||||
<a href="https://sudovanilla.com/code/MinPluto/MinPluto" target="_blank">{t("SIDEBAR.FOOTER.SOURCE_CODE")}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p id="version">v{version}</p>
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.ms {
|
||||
margin-top: 20%;
|
||||
text-align: center;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
hr {
|
||||
width: 100px;
|
||||
border: none;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
height: 4px;
|
||||
border-radius: 1rem;
|
||||
margin: 24px auto;
|
||||
}
|
||||
p#version {
|
||||
position: fixed;
|
||||
bottom: 88px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
background: #232323;
|
||||
color: white;
|
||||
padding: 24px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
40
src/pages/jp/m/categories.astro
Normal file
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import { HomeSimple, GraphUp, Movie, MusicDoubleNote, Gamepad, AppleImac2021Side, EmojiTalkingHappy, PizzaSlice, Treadmill, PeaceHand } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("jp");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div style="padding: 0px 24px;">
|
||||
<h2>Categories</h2>
|
||||
<div id="c" style="display: flex;flex-direction: column;gap: 24px;">
|
||||
<a href="/category/trending"><GraphUp/> {t("CATEGORY_LIST.TRENDING")}</a>
|
||||
<a href="/category/movies"><Movie/> {t("CATEGORY_LIST.MOVIES")}</a>
|
||||
<a href="/category/music"><MusicDoubleNote/> {t("CATEGORY_LIST.MUSIC")}</a>
|
||||
<a href="/category/gaming"><Gamepad/> {t("CATEGORY_LIST.GAMES")}</a>
|
||||
</div>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style lang="scss">
|
||||
#c a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
background: linear-gradient(45deg, #636363, #181818);
|
||||
padding: 48px 24px;
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
border-radius: 10px;
|
||||
svg {
|
||||
position: absolute;
|
||||
right: 60px;
|
||||
width: 100px;
|
||||
height: 70px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
</style>
|
20
src/pages/jp/offline.astro
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
changeLanguage("jp");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<h2>No Internet Connection</h2>
|
||||
<p>It appears that you are offline, try connecting your device to the internet, and try again.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
</style>
|
35
src/pages/jp/search.astro
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../config.json";
|
||||
import Video from "@components/VideoItem.astro";
|
||||
|
||||
changeLanguage("jp");
|
||||
|
||||
// Fetch
|
||||
const SBO = Astro.url.href.split("search?query=").pop();
|
||||
const response = await fetch(DEFAULT_DATA_PROXY + "/api/v1/search?q=" + SBO)
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
const data = await response.json();
|
||||
---
|
||||
|
||||
<Base Title='MinPluto Search'>
|
||||
<div class="page-title">
|
||||
<h2>Search</h2>
|
||||
</div>
|
||||
<div class="video-grid">
|
||||
{data.map((data) =>
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Base>
|
207
src/pages/jp/watch.astro
Normal file
|
@ -0,0 +1,207 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import "@styles/video.scss";
|
||||
// Configuration
|
||||
import { DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../config.json";
|
||||
import { Donate, Download, ShareIos, ThumbsUp, MediaVideo } from "@iconoir/vue";
|
||||
// Components
|
||||
import Dialog from "@components/Dialog.astro";
|
||||
import Video from "@components/VideoItem.astro";
|
||||
|
||||
changeLanguage("jp");
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("watch?v=").pop();
|
||||
const video = await fetch(DEFAULT_DATA_PROXY + "/api/v1/videos/" + SWV).then((response) => response.json());
|
||||
const comments = await fetch(DEFAULT_DATA_PROXY + "/api/v1/comments/" + SWV).then((response) => response.json());
|
||||
const Description = video.description;
|
||||
const UploadDate = video.published;
|
||||
const Views = video.viewCount;
|
||||
const VideoSeconds = video.lengthSeconds;
|
||||
let DescriptionFormat = Description.replaceAll("\n", " <br/> ");
|
||||
// Format Published Date
|
||||
const DateFormat = new Date(UploadDate * 1000).toLocaleDateString();
|
||||
// Format Video Length
|
||||
// Thanks to "mingjunlu" for helping out with the time format
|
||||
new Date(VideoSeconds * 1000)
|
||||
.toISOString()
|
||||
.slice(14, 19)
|
||||
.split(":")
|
||||
.map(Number)
|
||||
.join(":");
|
||||
// Format Views
|
||||
const ViewsConversion = Intl.NumberFormat("en", { notation: "compact" });
|
||||
let ViewsFormat = ViewsConversion.format(Views);
|
||||
---
|
||||
|
||||
<Base Title={video.title}>
|
||||
<div class="video-container">
|
||||
<video
|
||||
class="zorn-player"
|
||||
autoplay
|
||||
poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
video-title={video.title}
|
||||
src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
>
|
||||
</video>
|
||||
</div>
|
||||
<div class="video-rea">
|
||||
<div class="rea-details">
|
||||
<p style="font-weight: bold; font-size: 24px;">{video.title}</p>
|
||||
<div class="rea-details-start">
|
||||
<a style="text-decoration: none;" href={video.authorUrl} class="rea-channel">
|
||||
<img src={video.authorThumbnails[1].url} />
|
||||
<div
|
||||
style="display: flex; flex-direction: column; align-items: left;"
|
||||
>
|
||||
<h2 style="margin: 0px; font-weight: bold; font-size: 18px;">{video.author}</h2>
|
||||
<p style="margin: 0px;" id="subs">
|
||||
{video.subCountText} Subscribers
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<div style="display: flex; flex-direction: row; align-items: left;">
|
||||
<button onclick="DownloadDialogShow()"><Download /> Download</button>
|
||||
<button onclick={'location.href = "/embed/' + video.videoId + '/"'}><MediaVideo /> Embed</button>
|
||||
<button onclick="ShareDialogShow()"><ShareIos /> Share</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rea-details-end">
|
||||
<p id="views">{ViewsFormat} Views - {DateFormat}</p>
|
||||
<Fragment set:html={DescriptionFormat} />
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 24px;">
|
||||
<div class="rea-comments">
|
||||
<h2>{t("WATCH.COMMENTS")}</h2>
|
||||
{
|
||||
comments.comments.map((comment) => (
|
||||
<div class="comment">
|
||||
<img
|
||||
src={
|
||||
DEFAULT_IMAGE_PROXY + "/" + comment.authorThumbnails[1].url
|
||||
}
|
||||
/>
|
||||
<div>
|
||||
<p>
|
||||
<a href={comment.authorUrl}>{comment.author}</a> - 2 Months
|
||||
Ago
|
||||
</p>
|
||||
<p>{comment.contentHtml}</p>
|
||||
<p>
|
||||
<ThumbsUp /> {comment.likeCount}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="rea-recommendations">
|
||||
<h2>{t("WATCH.RELATED")}</h2>
|
||||
{
|
||||
video.recommendedVideos.map((data) => (
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Dialog
|
||||
Title="Download"
|
||||
Description="Choose a download method"
|
||||
Closable
|
||||
CloseOnclick="DownloadDialogHide()"
|
||||
>
|
||||
<p>Video</p>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={video.formatStreams[1].url} download={video.title + '.mp4'} target="_blank">Download</a>
|
||||
</div>
|
||||
<p>Audio Only</p>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={video.adaptiveFormats[1].url} download={video.title + '.mp3'} target="_blank">Download</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
<Dialog
|
||||
Title="Share"
|
||||
Description="Choose a share method"
|
||||
Closable
|
||||
CloseOnclick="ShareDialogHide()"
|
||||
>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={'https://mastodonshare.com/?url=' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Mastodon</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Misskey</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Firefish</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Elk</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Lemmy</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Base>
|
||||
|
||||
<script is:inline>
|
||||
function DownloadDialogShow() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function DownloadDialogHide() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
function ShareDialogShow() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function ShareDialogHide() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.video-container {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.zorn-player {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zorn-player-controls {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.dialog-downloads-list {
|
||||
display: grid;
|
||||
grid-gap: 12px;
|
||||
a {
|
||||
background: rgb(51 51 51);
|
||||
border: 2px rgba(255,255,255,0.05) solid;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
padding: 9px 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
66
src/pages/m/about.astro
Normal file
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import { version } from "@root/package.json";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="ms">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<h2>MinPluto</h2>
|
||||
<p>{t("HOME.P1")}</p>
|
||||
<hr/>
|
||||
<p style="font-size: 14px;"><i>{t("HOME.P2")}</i></p>
|
||||
<hr/>
|
||||
<div style="display: flex; justify-content: space-evenly;">
|
||||
<a href="https://community.minpluto.org/" target="_blank">{t("SIDEBAR.FOOTER.STATUS")}</a>
|
||||
<a href="https://status.minpluto.org/" target="_blank">{t("SIDEBAR.FOOTER.FORUM")}</a>
|
||||
<a href="https://sudovanilla.com/code/MinPluto/MinPluto" target="_blank">{t("SIDEBAR.FOOTER.SOURCE_CODE")}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p id="version">v{version}</p>
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.ms {
|
||||
margin-top: 20%;
|
||||
text-align: center;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
hr {
|
||||
width: 100px;
|
||||
border: none;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
height: 4px;
|
||||
border-radius: 1rem;
|
||||
margin: 24px auto;
|
||||
}
|
||||
p#version {
|
||||
position: fixed;
|
||||
bottom: 88px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
background: #232323;
|
||||
color: white;
|
||||
padding: 24px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
40
src/pages/m/categories.astro
Normal file
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import { HomeSimple, GraphUp, Movie, MusicDoubleNote, Gamepad, AppleImac2021Side, EmojiTalkingHappy, PizzaSlice, Treadmill, PeaceHand } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div style="padding: 0px 24px;">
|
||||
<h2>Categories</h2>
|
||||
<div id="c" style="display: flex;flex-direction: column;gap: 24px;">
|
||||
<a href="/category/trending"><GraphUp/> {t("CATEGORY_LIST.TRENDING")}</a>
|
||||
<a href="/category/movies"><Movie/> {t("CATEGORY_LIST.MOVIES")}</a>
|
||||
<a href="/category/music"><MusicDoubleNote/> {t("CATEGORY_LIST.MUSIC")}</a>
|
||||
<a href="/category/gaming"><Gamepad/> {t("CATEGORY_LIST.GAMES")}</a>
|
||||
</div>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style lang="scss">
|
||||
#c a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
background: linear-gradient(45deg, #636363, #181818);
|
||||
padding: 48px 24px;
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
border-radius: 10px;
|
||||
svg {
|
||||
position: absolute;
|
||||
right: 60px;
|
||||
width: 100px;
|
||||
height: 70px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
</style>
|
20
src/pages/offline.astro
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
changeLanguage("en");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<h2>No Internet Connection</h2>
|
||||
<p>It appears that you are offline, try connecting your device to the internet, and try again.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
</style>
|
56
src/pages/privacy.md
Normal file
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
layout: "@layouts/Markdown.astro"
|
||||
---
|
||||
|
||||
# Privacy Policy
|
||||
|
||||
## 3rd Party Services are Proxied
|
||||
|
||||
Any service in MinPluto that is 3rd party is proxied by this instance or another instance such as images, videos, fonts, scripts, and more. No personal information information is collected and no information is sent to any 3rd party.
|
||||
|
||||
## Information Collection and Use
|
||||
|
||||
This instance of MinPluto uses Plausible for analytics, no personal informatin is collected about you. Data that is collected can not be used to identify you, along with devices or any other factors.
|
||||
|
||||
All data collected with Plausible is anonymous.
|
||||
|
||||
## We Don't Know What You're Watching
|
||||
When you watch a video on a MinPluto instance with analytics enabled, the analytics software doesn't show what video are you watching. The query in the URL, which is the video ID, is not saved to analytics. What we see is only "/watch", not /watch?=dQw4w9WgXcQ".
|
||||
|
||||
## Liability
|
||||
MinPluto and SudoVanilla take no responsibility for the use of our tool, or external instances provided by third parties. It is strongly recommended that you abide by the valid official regulations in your country. Furthermore, we refuse liability for any inappropriate use of MinPluto, such as illegal downloading.
|
||||
|
||||
MinPluto is licenced under AGPL v3, this software is included with a copy.
|
||||
|
||||
<hr/>
|
||||
Copyright (C) 2024 SudoVanilla
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
<hr/>
|
||||
|
||||
## Links to Other Sites
|
||||
|
||||
Channels and videos on MinPluto may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by SudoVanilla, MinPluto, or the MinPluto instance. Therefore, I strongly advise you to review the privacy policy of these websites. I have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.
|
||||
|
||||
## Changes to This Privacy Policy
|
||||
|
||||
The developers of MinPluto, SudoVanilla, may update our privacy policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new privacy policy on this page.
|
||||
|
||||
This also goes for the instance itself.
|
||||
|
||||
This policy is effective as of March 7th, 2024.
|
||||
|
||||
## Contact Us
|
||||
|
||||
If you have any questions or suggestions about MinPluto's privacy policy, do not hesitate to contact me at hello@minpluto.org or to [submit an issue](https://sudovanilla.com/code/MinPluto/MinPluto/issues).
|
20
src/pages/ru/404.astro
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
changeLanguage("ru");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<h2>Error 404</h2>
|
||||
<p>Page not found.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
</style>
|
9
src/pages/ru/category/gaming.astro
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("ru");
|
||||
---
|
||||
|
||||
<Category GradientHero="#269753" FetchData="?type=gaming" CategoryName={t("SIDEBAR.CATEGORY_LIST.GAMES")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.GAMES_DESCRIPTION")}></Category>
|
||||
<style is:inline>a[href="/category/gaming"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
10
src/pages/ru/category/movies.astro
Normal file
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("ru");
|
||||
---
|
||||
|
||||
<Category GradientHero="#ff4f4f" FetchData="?type=movies" CategoryName={t("SIDEBAR.CATEGORY_LIST.MOVIES")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.MOVIES_DESCRIPTION")}>
|
||||
</Category>
|
||||
<style is:inline>a[href="/category/movies"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
106
src/pages/ru/category/music.astro
Normal file
|
@ -0,0 +1,106 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Default from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_VIDEO_PROXY } from "../../../../config.json";
|
||||
// Components
|
||||
import MusicItem from "@components/MusicItem.astro";
|
||||
|
||||
changeLanguage("ru");
|
||||
|
||||
// Fetch
|
||||
const fetchFrom = DEFAULT_DATA_PROXY + "/api/v1/trending?type=music";
|
||||
const response = await fetch(fetchFrom);
|
||||
const data = await response.json();
|
||||
const heroItem = data.slice(0, 1);
|
||||
---
|
||||
|
||||
<Default FetchData="?type=movies" Title={t("SIDEBAR.CATEGORY_LIST.MUSIC")} Description={t("SIDEBAR.CATEGORY_LIST.MUSIC_DESCRIPTION")}>
|
||||
<div class="category-hero">
|
||||
<div class="c-hero-content">
|
||||
<div style="width: 25%;">
|
||||
<h2>Music</h2>
|
||||
<p>Listen to the latest hits</p>
|
||||
</div>
|
||||
<div class="c-hero-video">
|
||||
{heroItem.map((data) =>
|
||||
<video autoplay muted src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + data.videoId + '&itag=22&local=true'}></video>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span id="gradient-header"></span>
|
||||
<div class="or-mu">
|
||||
<span></span>
|
||||
<p id="title">{t("MUSIC.TITLE")}</p>
|
||||
<p id="artist">{t("MUSIC.ARTIST")}</p>
|
||||
<p id="date">{t("MUSIC.UPLOADED")}</p>
|
||||
<p id="duration">{t("MUSIC.DURATION")}</p>
|
||||
</div>
|
||||
<div class="music-list">
|
||||
{data.map((data) =>
|
||||
<MusicItem
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Default>
|
||||
<style is:inline>a[href="/en /category/music"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
|
||||
<style lang="scss">
|
||||
.category-hero {
|
||||
margin-top: -80px;
|
||||
background: linear-gradient(180deg, #502969, transparent);
|
||||
padding-top: 80px;
|
||||
.c-hero-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: auto;
|
||||
max-width: 1000px;
|
||||
justify-content: space-between;
|
||||
.c-hero-video {
|
||||
-webkit-mask-box-image: radial-gradient(rgb(0 0 0 / 50%), transparent);
|
||||
-webkit-mask-box-image: linear-gradient(90deg, black, rgba(0, 0, 0, 0));
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
video {
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
width: 75%;
|
||||
height: 100%;
|
||||
float: right;
|
||||
-webkit-mask-box-image: linear-gradient(270deg, black, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.or-mu {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
gap: 12px;
|
||||
grid-template-columns: 60px auto auto 80px 64px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
border-bottom: 1px #252525 solid;
|
||||
margin-bottom: 24px;
|
||||
position: sticky;
|
||||
top: 58px;
|
||||
background: black;
|
||||
#artist, #duration, #date {
|
||||
text-align: right;
|
||||
}
|
||||
#title {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
9
src/pages/ru/category/trending.astro
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Category from "@layouts/Category.astro";
|
||||
|
||||
changeLanguage("ru");
|
||||
---
|
||||
|
||||
<Category GradientHero="#ff650b" FetchData="" CategoryName={t("SIDEBAR.CATEGORY_LIST.TRENDING")} CategoryDescription={t("SIDEBAR.CATEGORY_LIST.TRENDING_DESCRIPTION")}></Category>
|
||||
<style is:inline>a[href="/category/trending"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
137
src/pages/ru/channel/[...slug].astro
Normal file
|
@ -0,0 +1,137 @@
|
|||
---
|
||||
import Base from "@layouts/Default.astro";
|
||||
// i18n
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../../config.json";
|
||||
import { BrightStar, Donate, Download, ShareIos, ThumbsUp } from "@iconoir/vue";
|
||||
// Components
|
||||
import Video from "@components/VideoItem.astro";
|
||||
|
||||
changeLanguage("ru");
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("channel/").pop();
|
||||
const channel = await fetch(DEFAULT_DATA_PROXY + "/api/v1/channels/" + SWV).then((response) => response.json());
|
||||
const DescriptionFormat = channel.descriptionHtml.replaceAll("\n", " <br/> ");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="channel-backdrop">
|
||||
<img src={channel.authorBanners[1].url}/>
|
||||
</div>
|
||||
<div class="channel">
|
||||
<div class="channel-header">
|
||||
<div class="channel-banner">
|
||||
<img src={channel.authorBanners[1].url}/>
|
||||
</div>
|
||||
<div class="channel-meta">
|
||||
<div>
|
||||
<img src={channel.authorThumbnails[1].url}/>
|
||||
<h2>{channel.author}</h2>
|
||||
<p>{channel.subCountText}</p>
|
||||
</div>
|
||||
<div>
|
||||
<!-- {channel.isFamilyFriendly ? <p id="family-friendly"><BrightStar/> {t("CHANNEL.FAMILY_FRIENDLY")}</p> : null} -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="channel-content">
|
||||
<!-- <div class="channel-tabs">
|
||||
<a href="#">{t("CHANNEL.HOME")}</a>
|
||||
<a href="#">{t("CHANNEL.VIDEOS")}</a>
|
||||
<a href="#">{t("CHANNEL.COMMUNITY")}</a>
|
||||
</div> -->
|
||||
<div class="channel-tab-content">
|
||||
<h2>{t("CHANNEL.ABOUT")} {channel.author}</h2>
|
||||
<p><Fragment set:html={DescriptionFormat}/></p>
|
||||
<hr/>
|
||||
<h2>{t("CHANNEL.LATEST")}</h2>
|
||||
<div class="video-grid">
|
||||
{channel.latestVideos.map((data) =>
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
<!-- <a>View All Latest Videos</a> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style lang="scss">
|
||||
.channel-backdrop img {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: max-content;
|
||||
filter: blur(30px) contrast(0.8);
|
||||
z-index: -1;
|
||||
transform: scale(1.4);
|
||||
opacity: 0.3;
|
||||
display: none;
|
||||
}
|
||||
.channel {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.channel-header {
|
||||
.channel-banner {
|
||||
margin: 12px 0px;
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
.channel-meta {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
#family-friendly {
|
||||
color: white;
|
||||
background: #3b003b;
|
||||
border: 1px #a500a5 solid;
|
||||
border-radius: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
gap: 12px;
|
||||
pointer-events: none;
|
||||
}
|
||||
div:nth-child(1) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 12px;
|
||||
img {
|
||||
border-radius: 3rem;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.channel-content {
|
||||
.channel-tabs {
|
||||
padding-top: 24px;
|
||||
padding-bottom: 12px;
|
||||
cursor: default;
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
padding: 12px 24px;
|
||||
border-radius: 24px;
|
||||
&:hover {
|
||||
background: rgba(41, 41, 41, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
57
src/pages/ru/discover/tech.astro
Normal file
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Discover from "@layouts/Discover.astro";
|
||||
// Properties
|
||||
const { FetchData, CategoryName, CategoryDescription } = Astro.props;
|
||||
// Use on top of Default Layout
|
||||
import Base from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../../config.json";
|
||||
// Discover Data
|
||||
import Discover from "../../../data/discover.json";
|
||||
|
||||
changeLanguage("ru");
|
||||
---
|
||||
|
||||
<Base>
|
||||
<div class="video-grid">
|
||||
{Discover.Tech.map((channel) =>
|
||||
<a href={'/channel/' + channel.Link} style={"background: url('" + DEFAULT_DATA_PROXY + channel.Banner} class="discovery-channel">
|
||||
<div class="dc-c">
|
||||
<img src={DEFAULT_DATA_PROXY + channel.Logo}/>
|
||||
<p>{channel.Name}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<hr/>
|
||||
<div style="max-width: 1000px; margin: auto; text-align: center;">
|
||||
<p>This is a curated list for all MinPluto users.</p>
|
||||
<p>Is there a channel missing here that you think should be added? You can either <a href="https://sudovanilla.com/code/MinPluto/MinPluto/src/branch/main/src/data/discover.json">edit our list here</a> or you can <a href="https://community.minpluto.org/">submit a request</a>.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/discover/tech"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style lang="scss">
|
||||
.discovery-channel {
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
font-weight: bold;
|
||||
background-position: center !important;
|
||||
background-size: cover !important;
|
||||
.dc-c {
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
backdrop-filter: blur(24px) contrast(0.7) brightness(0.4);
|
||||
img {
|
||||
width: 24%;
|
||||
align-self: center;
|
||||
border-radius: 10rem;
|
||||
padding: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
93
src/pages/ru/embed/[...slug].astro
Normal file
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Embed from "@layouts/Embed.astro";
|
||||
import "@styles/video.scss";
|
||||
// Configuration
|
||||
import { DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../../config.json";
|
||||
|
||||
changeLanguage("ru");
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("embed/").pop();
|
||||
const video = await fetch(DEFAULT_DATA_PROXY + "/api/v1/videos/" + SWV).then((response) => response.json());
|
||||
---
|
||||
|
||||
<Embed
|
||||
Title={video.title}
|
||||
EmbedId={video.videoId}
|
||||
EmbedVideo={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
EmbedImage={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
EmbedTitle={video.title}
|
||||
>
|
||||
<div class="video-container">
|
||||
<video
|
||||
class="zorn-player"
|
||||
autoplay
|
||||
poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
video-title={video.title}
|
||||
src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
>
|
||||
</video>
|
||||
</div>
|
||||
</Embed>
|
||||
|
||||
<script is:inline>
|
||||
function DownloadDialogShow() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function DownloadDialogHide() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
function ShareDialogShow() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function ShareDialogHide() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.video-container {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.zorn-player {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zorn-player-controls {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.dialog-downloads-list {
|
||||
display: grid;
|
||||
grid-gap: 12px;
|
||||
a {
|
||||
background: rgb(51 51 51);
|
||||
border: 2px rgba(255,255,255,0.05) solid;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
padding: 9px 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
143
src/pages/ru/index.astro
Normal file
|
@ -0,0 +1,143 @@
|
|||
---
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import Dialog from "@components/Dialog.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../config.json";
|
||||
import { FireFlame, Frame, Gamepad, GraphUp, Movie, MusicDoubleNote } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("ru");
|
||||
|
||||
// Fetch
|
||||
const TrendingFetch = DEFAULT_DATA_PROXY + "/api/v1/trending";
|
||||
const TrendingResponse = await fetch(TrendingFetch);
|
||||
const TrendingData = await TrendingResponse.json();
|
||||
const TrendingSplit = TrendingData.slice(0, 1);
|
||||
const MoviesFetch = DEFAULT_DATA_PROXY + "/api/v1/trending?type=movies";
|
||||
const MoviesResponse = await fetch(MoviesFetch);
|
||||
const MoviesData = await MoviesResponse.json();
|
||||
const MoviesSplit = MoviesData.slice(0, 1);
|
||||
const MusicFetch = DEFAULT_DATA_PROXY + "/api/v1/trending?type=music";
|
||||
const MusicResponse = await fetch(MusicFetch);
|
||||
const MusicData = await MusicResponse.json();
|
||||
const MusicSplit = MusicData.slice(0, 1);
|
||||
const GamingFetch = DEFAULT_DATA_PROXY + "/api/v1/trending?type=gaming";
|
||||
const GamingResponse = await fetch(GamingFetch);
|
||||
const GamingData = await GamingResponse.json();
|
||||
const GamingSplit = GamingData.slice(0, 1);
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<hr/>
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</div>
|
||||
<div class="category-select-grid">
|
||||
{TrendingSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/trending'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<GraphUp viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.TRENDING")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{MoviesSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/movies'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<Movie viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.MOVIES")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{MusicSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/music'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<MusicDoubleNote viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.MUSIC")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
{GamingSplit.map((data) =>
|
||||
<a href={'/' + i18next.language + '/category/gaming'} style={'background: url("' + DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/' + data.videoThumbnails[1].url + '")'} class="goin-card">
|
||||
<div class="goin-card-content">
|
||||
<Gamepad viewBox="0 0 10 24"/>
|
||||
<p>{t("SIDEBAR.CATEGORY_LIST.GAMES")}</p>
|
||||
</div>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
.category-select-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) !important;
|
||||
}
|
||||
}
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
|
||||
.goin-card {
|
||||
height: 124px;
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
}
|
||||
|
||||
.goin-card-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0px 12px;
|
||||
height: 100%;
|
||||
place-content: center;
|
||||
border-radius: 10px;
|
||||
backdrop-filter: blur(3px) brightness(0.3) contrast(0.8);
|
||||
}
|
||||
.goin-card-content p {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
margin: 24px;
|
||||
}
|
||||
.goin-card-content svg {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
width: 50px;
|
||||
height: 120px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
opacity: 0.3;
|
||||
}
|
||||
.goin-card img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.category-select-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
grid-gap: 25px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
</style>
|
75
src/pages/ru/instance.astro
Normal file
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
import i18next, { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import Dialog from "@components/Dialog.astro";
|
||||
// Configuration
|
||||
import { SERVER_ADMIN, ANALYLICS_TOOL, DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, DEFAULT_PLAYER, SERVER_LOCATION, MODIFIED, CUSTOM_SOURCE_CODE, STATISTICS } from "../../../config.json";
|
||||
import { FireFlame, Frame, Gamepad, GraphUp, Movie, MusicDoubleNote } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("ru");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<hr/>
|
||||
<div class="video-grid">
|
||||
<div class="in">
|
||||
<h2>Operated By</h2>
|
||||
<p>{SERVER_ADMIN}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Analytics Software</h2>
|
||||
<p>
|
||||
{
|
||||
STATISTICS
|
||||
?
|
||||
<p>{ANALYLICS_TOOL}</p>
|
||||
:
|
||||
<p>None</p>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Location</h2>
|
||||
<p>{SERVER_LOCATION}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Modified</h2>
|
||||
<p>{MODIFIED ? <p>Yes</p> : <p>No</p>}</p>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Video Proxy</h2>
|
||||
<a href={DEFAULT_VIDEO_PROXY}>{DEFAULT_VIDEO_PROXY}</a>
|
||||
</div>
|
||||
<div class="in">
|
||||
<h2>Image Proxy</h2>
|
||||
<a href={DEFAULT_IMAGE_PROXY}>{DEFAULT_IMAGE_PROXY}</a>
|
||||
</div>
|
||||
</div>
|
||||
{MODIFIED ? <p>Modified Source Code <a href={CUSTOM_SOURCE_CODE}>{CUSTOM_SOURCE_CODE}</a></p> : null}
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style is:inline>a[href="/"] {background: rgb(255 255 255 / 25%) !important;border: 2px rgba(255, 255, 255, 0.25) solid !important;}</style>
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
.category-select-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)) !important;
|
||||
}
|
||||
}
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
66
src/pages/ru/m/about.astro
Normal file
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import { version } from "@root/package.json";
|
||||
|
||||
changeLanguage("ru");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="ms">
|
||||
<img src="/images/logo/MinPluto - Image Logo Full with Shadow.png"/>
|
||||
<h2>MinPluto</h2>
|
||||
<p>{t("HOME.P1")}</p>
|
||||
<hr/>
|
||||
<p style="font-size: 14px;"><i>{t("HOME.P2")}</i></p>
|
||||
<hr/>
|
||||
<div style="display: flex; justify-content: space-evenly;">
|
||||
<a href="https://community.minpluto.org/" target="_blank">{t("SIDEBAR.FOOTER.STATUS")}</a>
|
||||
<a href="https://status.minpluto.org/" target="_blank">{t("SIDEBAR.FOOTER.FORUM")}</a>
|
||||
<a href="https://sudovanilla.com/code/MinPluto/MinPluto" target="_blank">{t("SIDEBAR.FOOTER.SOURCE_CODE")}</a>
|
||||
</div>
|
||||
</div>
|
||||
<p id="version">v{version}</p>
|
||||
<img src="/images/backgrounds/1.webp"/>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
left: 50%;
|
||||
transform: translate(-57%);
|
||||
-webkit-mask-image: linear-gradient(180deg, transparent 5%, rgb(0 0 0) 52%, rgb(0 0 0) 44%, transparent 95%);
|
||||
}
|
||||
@media only screen and (min-width: 875px) {
|
||||
img[src="/images/backgrounds/1.webp"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.ms {
|
||||
margin-top: 20%;
|
||||
text-align: center;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
hr {
|
||||
width: 100px;
|
||||
border: none;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
height: 4px;
|
||||
border-radius: 1rem;
|
||||
margin: 24px auto;
|
||||
}
|
||||
p#version {
|
||||
position: fixed;
|
||||
bottom: 88px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
background: #232323;
|
||||
color: white;
|
||||
padding: 24px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
40
src/pages/ru/m/categories.astro
Normal file
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import { HomeSimple, GraphUp, Movie, MusicDoubleNote, Gamepad, AppleImac2021Side, EmojiTalkingHappy, PizzaSlice, Treadmill, PeaceHand } from "@iconoir/vue";
|
||||
|
||||
changeLanguage("ru");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div style="padding: 0px 24px;">
|
||||
<h2>Categories</h2>
|
||||
<div id="c" style="display: flex;flex-direction: column;gap: 24px;">
|
||||
<a href="/category/trending"><GraphUp/> {t("CATEGORY_LIST.TRENDING")}</a>
|
||||
<a href="/category/movies"><Movie/> {t("CATEGORY_LIST.MOVIES")}</a>
|
||||
<a href="/category/music"><MusicDoubleNote/> {t("CATEGORY_LIST.MUSIC")}</a>
|
||||
<a href="/category/gaming"><Gamepad/> {t("CATEGORY_LIST.GAMES")}</a>
|
||||
</div>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style lang="scss">
|
||||
#c a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
background: linear-gradient(45deg, #636363, #181818);
|
||||
padding: 48px 24px;
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
border-radius: 10px;
|
||||
svg {
|
||||
position: absolute;
|
||||
right: 60px;
|
||||
width: 100px;
|
||||
height: 70px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
</style>
|
20
src/pages/ru/offline.astro
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
import { changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
|
||||
changeLanguage("ru");
|
||||
---
|
||||
|
||||
<Base Title="MinPluto" Description="">
|
||||
<div class="force-center">
|
||||
<h2>No Internet Connection</h2>
|
||||
<p>It appears that you are offline, try connecting your device to the internet, and try again.</p>
|
||||
</div>
|
||||
</Base>
|
||||
|
||||
<style>
|
||||
.force-center {
|
||||
text-align: center;
|
||||
padding-top: 10%;
|
||||
}
|
||||
</style>
|
35
src/pages/ru/search.astro
Normal file
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../../config.json";
|
||||
import Video from "@components/VideoItem.astro";
|
||||
|
||||
changeLanguage("ru");
|
||||
|
||||
// Fetch
|
||||
const SBO = Astro.url.href.split("search?query=").pop();
|
||||
const response = await fetch(DEFAULT_DATA_PROXY + "/api/v1/search?q=" + SBO)
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
const data = await response.json();
|
||||
---
|
||||
|
||||
<Base Title='MinPluto Search'>
|
||||
<div class="page-title">
|
||||
<h2>Search</h2>
|
||||
</div>
|
||||
<div class="video-grid">
|
||||
{data.map((data) =>
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Base>
|
207
src/pages/ru/watch.astro
Normal file
|
@ -0,0 +1,207 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import "@styles/video.scss";
|
||||
// Configuration
|
||||
import { DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../../config.json";
|
||||
import { Donate, Download, ShareIos, ThumbsUp, MediaVideo } from "@iconoir/vue";
|
||||
// Components
|
||||
import Dialog from "@components/Dialog.astro";
|
||||
import Video from "@components/VideoItem.astro";
|
||||
|
||||
changeLanguage("ru");
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("watch?v=").pop();
|
||||
const video = await fetch(DEFAULT_DATA_PROXY + "/api/v1/videos/" + SWV).then((response) => response.json());
|
||||
const comments = await fetch(DEFAULT_DATA_PROXY + "/api/v1/comments/" + SWV).then((response) => response.json());
|
||||
const Description = video.description;
|
||||
const UploadDate = video.published;
|
||||
const Views = video.viewCount;
|
||||
const VideoSeconds = video.lengthSeconds;
|
||||
let DescriptionFormat = Description.replaceAll("\n", " <br/> ");
|
||||
// Format Published Date
|
||||
const DateFormat = new Date(UploadDate * 1000).toLocaleDateString();
|
||||
// Format Video Length
|
||||
// Thanks to "mingjunlu" for helping out with the time format
|
||||
new Date(VideoSeconds * 1000)
|
||||
.toISOString()
|
||||
.slice(14, 19)
|
||||
.split(":")
|
||||
.map(Number)
|
||||
.join(":");
|
||||
// Format Views
|
||||
const ViewsConversion = Intl.NumberFormat("en", { notation: "compact" });
|
||||
let ViewsFormat = ViewsConversion.format(Views);
|
||||
---
|
||||
|
||||
<Base Title={video.title}>
|
||||
<div class="video-container">
|
||||
<video
|
||||
class="zorn-player"
|
||||
autoplay
|
||||
poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
video-title={video.title}
|
||||
src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
>
|
||||
</video>
|
||||
</div>
|
||||
<div class="video-rea">
|
||||
<div class="rea-details">
|
||||
<p style="font-weight: bold; font-size: 24px;">{video.title}</p>
|
||||
<div class="rea-details-start">
|
||||
<a style="text-decoration: none;" href={video.authorUrl} class="rea-channel">
|
||||
<img src={video.authorThumbnails[1].url} />
|
||||
<div
|
||||
style="display: flex; flex-direction: column; align-items: left;"
|
||||
>
|
||||
<h2 style="margin: 0px; font-weight: bold; font-size: 18px;">{video.author}</h2>
|
||||
<p style="margin: 0px;" id="subs">
|
||||
{video.subCountText} Subscribers
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<div style="display: flex; flex-direction: row; align-items: left;">
|
||||
<button onclick="DownloadDialogShow()"><Download /> Download</button>
|
||||
<button onclick={'location.href = "/embed/' + video.videoId + '/"'}><MediaVideo /> Embed</button>
|
||||
<button onclick="ShareDialogShow()"><ShareIos /> Share</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rea-details-end">
|
||||
<p id="views">{ViewsFormat} Views - {DateFormat}</p>
|
||||
<Fragment set:html={DescriptionFormat} />
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 24px;">
|
||||
<div class="rea-comments">
|
||||
<h2>{t("WATCH.COMMENTS")}</h2>
|
||||
{
|
||||
comments.comments.map((comment) => (
|
||||
<div class="comment">
|
||||
<img
|
||||
src={
|
||||
DEFAULT_IMAGE_PROXY + "/" + comment.authorThumbnails[1].url
|
||||
}
|
||||
/>
|
||||
<div>
|
||||
<p>
|
||||
<a href={comment.authorUrl}>{comment.author}</a> - 2 Months
|
||||
Ago
|
||||
</p>
|
||||
<p>{comment.contentHtml}</p>
|
||||
<p>
|
||||
<ThumbsUp /> {comment.likeCount}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="rea-recommendations">
|
||||
<h2>{t("WATCH.RELATED")}</h2>
|
||||
{
|
||||
video.recommendedVideos.map((data) => (
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Dialog
|
||||
Title="Download"
|
||||
Description="Choose a download method"
|
||||
Closable
|
||||
CloseOnclick="DownloadDialogHide()"
|
||||
>
|
||||
<p>Video</p>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={video.formatStreams[1].url} download={video.title + '.mp4'} target="_blank">Download</a>
|
||||
</div>
|
||||
<p>Audio Only</p>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={video.adaptiveFormats[1].url} download={video.title + '.mp3'} target="_blank">Download</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
<Dialog
|
||||
Title="Share"
|
||||
Description="Choose a share method"
|
||||
Closable
|
||||
CloseOnclick="ShareDialogHide()"
|
||||
>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={'https://mastodonshare.com/?url=' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Mastodon</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Misskey</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Firefish</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Elk</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Lemmy</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Base>
|
||||
|
||||
<script is:inline>
|
||||
function DownloadDialogShow() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function DownloadDialogHide() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
function ShareDialogShow() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function ShareDialogHide() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.video-container {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.zorn-player {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zorn-player-controls {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.dialog-downloads-list {
|
||||
display: grid;
|
||||
grid-gap: 12px;
|
||||
a {
|
||||
background: rgb(51 51 51);
|
||||
border: 2px rgba(255,255,255,0.05) solid;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
padding: 9px 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
37
src/pages/search.astro
Normal file
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
// Configuration
|
||||
import { DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY } from "../../config.json";
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
import Video from '@components/VideoItem.astro'
|
||||
|
||||
// Fetch
|
||||
const SBO = Astro.url.href.split("search?query=").pop();
|
||||
const response = await fetch(DEFAULT_DATA_PROXY + "/api/v1/search?q=" + SBO)
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
---
|
||||
|
||||
<Base Title='MinPluto Search'>
|
||||
<div class="page-title">
|
||||
<h2>Search</h2>
|
||||
</div>
|
||||
<div class="video-grid">
|
||||
{data.map((data) =>
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Base>
|
209
src/pages/watch.astro
Normal file
|
@ -0,0 +1,209 @@
|
|||
---
|
||||
import { t, changeLanguage } from "i18next";
|
||||
import Base from "@layouts/Default.astro";
|
||||
import "@styles/video.scss";
|
||||
// Configuration
|
||||
import { DEFAULT_VIDEO_PROXY, DEFAULT_DATA_PROXY, DEFAULT_IMAGE_PROXY, SERVER_DOMAIN } from "../../config.json";
|
||||
import { Donate, Download, ShareIos, ThumbsUp, MediaVideo } from "@iconoir/vue";
|
||||
|
||||
// Components
|
||||
import Dialog from '@components/Dialog.astro'
|
||||
import Video from '@components/VideoItem.astro'
|
||||
|
||||
// Fetch
|
||||
const SWV = Astro.url.href.split("watch?v=").pop();
|
||||
const video = await fetch(DEFAULT_DATA_PROXY + "/api/v1/videos/" + SWV).then((response) => response.json());
|
||||
const comments = await fetch(DEFAULT_DATA_PROXY + "/api/v1/comments/" + SWV).then((response) => response.json());
|
||||
|
||||
changeLanguage("en");
|
||||
|
||||
const Description = video.description;
|
||||
const UploadDate = video.published;
|
||||
const Views = video.viewCount;
|
||||
const VideoSeconds = video.lengthSeconds;
|
||||
let DescriptionFormat = Description.replaceAll("\n", " <br/> ");
|
||||
// Format Published Date
|
||||
const DateFormat = new Date(UploadDate * 1000).toLocaleDateString();
|
||||
// Format Video Length
|
||||
// Thanks to "mingjunlu" for helping out with the time format
|
||||
new Date(VideoSeconds * 1000)
|
||||
.toISOString()
|
||||
.slice(14, 19)
|
||||
.split(":")
|
||||
.map(Number)
|
||||
.join(":");
|
||||
// Format Views
|
||||
const ViewsConversion = Intl.NumberFormat("en", { notation: "compact" });
|
||||
let ViewsFormat = ViewsConversion.format(Views);
|
||||
---
|
||||
|
||||
<Base Title={video.title}>
|
||||
<div class="video-container">
|
||||
<video
|
||||
class="zorn-player"
|
||||
autoplay
|
||||
poster={DEFAULT_IMAGE_PROXY + '/https://i.ytimg.com/vi/' + video.videoId + '/maxresdefault.jpg'}
|
||||
video-title={video.title}
|
||||
src={DEFAULT_VIDEO_PROXY + '/latest_version?id=' + video.videoId + '&itag=22&local=true'}
|
||||
>
|
||||
</video>
|
||||
</div>
|
||||
<div class="video-rea">
|
||||
<div class="rea-details">
|
||||
<p style="font-weight: bold; font-size: 24px;">{video.title}</p>
|
||||
<div class="rea-details-start">
|
||||
<a style="text-decoration: none;" href={video.authorUrl} class="rea-channel">
|
||||
<img src={DEFAULT_IMAGE_PROXY + "/" + video.authorThumbnails[1].url} />
|
||||
<div
|
||||
style="display: flex; flex-direction: column; align-items: left;"
|
||||
>
|
||||
<h2 style="margin: 0px; font-weight: bold; font-size: 18px;">{video.author}</h2>
|
||||
<p style="margin: 0px;" id="subs">
|
||||
{video.subCountText} Subscribers
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<div style="display: flex; flex-direction: row; align-items: left;">
|
||||
<button onclick="DownloadDialogShow()"><Download /> Download</button>
|
||||
<button onclick={'location.href = "/embed/' + video.videoId + '/"'}><MediaVideo /> Embed</button>
|
||||
<button onclick="ShareDialogShow()"><ShareIos /> Share</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rea-details-end">
|
||||
<p id="views">{ViewsFormat} Views - {DateFormat}</p>
|
||||
<Fragment set:html={DescriptionFormat} />
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; gap: 24px;">
|
||||
<div class="rea-comments">
|
||||
<h2>{t("WATCH.COMMENTS")}</h2>
|
||||
{
|
||||
comments.comments.map((comment) => (
|
||||
<div class="comment">
|
||||
<img
|
||||
src={
|
||||
DEFAULT_IMAGE_PROXY + "/" + comment.authorThumbnails[1].url
|
||||
}
|
||||
/>
|
||||
<div>
|
||||
<p>
|
||||
<a href={comment.authorUrl}>{comment.author}</a> - 2 Months
|
||||
Ago
|
||||
</p>
|
||||
<p>{comment.contentHtml}</p>
|
||||
<p>
|
||||
<ThumbsUp /> {comment.likeCount}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div class="rea-recommendations">
|
||||
<h2>{t("WATCH.RELATED")}</h2>
|
||||
{
|
||||
video.recommendedVideos.map((data) => (
|
||||
<Video
|
||||
ID={data.videoId}
|
||||
Title={data.title}
|
||||
Creator={data.author}
|
||||
Views={data.viewCount}
|
||||
UploadDate={data.published}
|
||||
Length={data.lengthSeconds}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Dialog
|
||||
Title="Download"
|
||||
Description="Choose a download method"
|
||||
Closable
|
||||
CloseOnclick="DownloadDialogHide()"
|
||||
>
|
||||
<p>Video</p>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={video.formatStreams[1].url} download={video.title + '.mp4'} target="_blank">Download</a>
|
||||
</div>
|
||||
<p>Audio Only</p>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={video.adaptiveFormats[1].url} download={video.title + '.mp3'} target="_blank">Download</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
<Dialog
|
||||
Title="Share"
|
||||
Description="Choose a share method"
|
||||
Closable
|
||||
CloseOnclick="ShareDialogHide()"
|
||||
>
|
||||
<div class="dialog-downloads-list">
|
||||
<a href={'https://mastodonshare.com/?url=' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Mastodon</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Misskey</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Firefish</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Elk</a>
|
||||
<a href={'https://share.minpluto.org/?url' + SERVER_DOMAIN + '/watch?q=' + video.videoId} target="_blank">Lemmy</a>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Base>
|
||||
|
||||
<script is:inline>
|
||||
function DownloadDialogShow() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function DownloadDialogHide() {
|
||||
var DownloadDialog = document.querySelector('#dialog-Download')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
DownloadDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
function ShareDialogShow() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'flex'
|
||||
BackdropDialog.style.display = 'inherit'
|
||||
}
|
||||
function ShareDialogHide() {
|
||||
var ShareDialog = document.querySelector('#dialog-Share')
|
||||
var BackdropDialog = document.querySelector('.dialog-backdrop')
|
||||
ShareDialog.style.display = 'none'
|
||||
BackdropDialog.style.display = 'none'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.video-container {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
.zorn-player {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zorn-player-controls {
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
}
|
||||
.video-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.dialog-downloads-list {
|
||||
display: grid;
|
||||
grid-gap: 12px;
|
||||
a {
|
||||
background: rgb(51 51 51);
|
||||
border: 2px rgba(255,255,255,0.05) solid;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
border-radius: 4px;
|
||||
padding: 9px 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
BIN
src/public/images/backgrounds/1.webp
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
src/public/images/backgrounds/2.jpg
Normal file
After Width: | Height: | Size: 149 KiB |
BIN
src/public/images/logo/Favicon.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 16 KiB |
BIN
src/public/images/logo/MinPluto - Image Logo Full.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
src/public/images/logo/MinPluto - Logo Full.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
src/public/images/logo/MinPluto - Logo.png
Normal file
After Width: | Height: | Size: 1,019 B |
BIN
src/public/images/logo/MinPluto - PWA Logo.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
src/public/images/pwa/MinPluto - PWA Logo.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
src/public/images/pwa/Mobile.png
Normal file
After Width: | Height: | Size: 154 KiB |
61
src/public/locales/en/translation.json
Normal file
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"GLOBAL": {
|
||||
"MINPLUTO": "MinPluto"
|
||||
},
|
||||
"SIDEBAR": {
|
||||
"HOME": "Home",
|
||||
"CATEGORY": "Category",
|
||||
"CATEGORY_LIST": {
|
||||
"TRENDING": "Trending",
|
||||
"TRENDING_DESCRIPTION": "What is everyone watching",
|
||||
"MOVIES": "Movies",
|
||||
"MOVIES_DESCRIPTION": "Movies and TV Show Trailers",
|
||||
"MUSIC": "Music",
|
||||
"MUSIC_DESCRIPTION": "Popuar Hits",
|
||||
"GAMES": "Games",
|
||||
"GAMES_DESCRIPTION": "Gameplay and more"
|
||||
},
|
||||
"DISCOVER": "Discover",
|
||||
"DISCOVER_LIST": {
|
||||
"TECH": "Tech",
|
||||
"COMEDY": "Comedy",
|
||||
"FOOD": "Food",
|
||||
"GAMES": "Games",
|
||||
"FITNESS": "Fitness"
|
||||
},
|
||||
"FOOTER": {
|
||||
"ALPHA": "You're in Alpha",
|
||||
"STATUS": "Status",
|
||||
"FORUM": "Forum",
|
||||
"SOURCE_CODE": "Source Code"
|
||||
}
|
||||
},
|
||||
"HEADER": {
|
||||
"SEARCH": "Search",
|
||||
"FEEDBACK": "Feedback"
|
||||
},
|
||||
"HOME": {
|
||||
"P1": "Select a category or search something to get started.",
|
||||
"P2": "Currently, MinPluto is in alpha. Features are currently barebones or may not work as expected."
|
||||
},
|
||||
"WATCH": {
|
||||
"BY": "By",
|
||||
"VIEWS": "Views",
|
||||
"RELATED": "Related Videos",
|
||||
"COMMENTS": "Comments"
|
||||
},
|
||||
"CHANNELS": {
|
||||
"FAMILY_FRIENDLY": "Family Friendly",
|
||||
"HOME": "Home",
|
||||
"VIDEOS": "Videos",
|
||||
"COMMUNITY": "Community",
|
||||
"LATEST": "Latest Videos",
|
||||
"ABOUT": "About"
|
||||
},
|
||||
"MUSIC": {
|
||||
"TITLE": "Title",
|
||||
"ARTIST": "Artist",
|
||||
"UPLOADED": "Uploaded",
|
||||
"DURATION": "Duration"
|
||||
}
|
||||
}
|
61
src/public/locales/jp/translation.json
Normal file
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"GLOBAL": {
|
||||
"MINPLUTO": "ミン・プルート"
|
||||
},
|
||||
"SIDEBAR": {
|
||||
"HOME": "ホーム",
|
||||
"CATEGORY": "カテゴリー",
|
||||
"CATEGORY_LIST": {
|
||||
"TRENDING": "トレンド",
|
||||
"TRENDING_DESCRIPTION": "みんなは何を見ているの",
|
||||
"MOVIES": "映画",
|
||||
"MOVIES_DESCRIPTION": "映画とテレビ番組の予告編",
|
||||
"MUSIC": "ミュージック",
|
||||
"MUSIC_DESCRIPTION": "人気の曲",
|
||||
"GAMES": "ゲーム",
|
||||
"GAMES_DESCRIPTION": "ゲームプレイその他"
|
||||
},
|
||||
"DISCOVER": "ディスカバー",
|
||||
"DISCOVER_LIST": {
|
||||
"TECH": "テクノロジー",
|
||||
"COMEDY": "コメディ",
|
||||
"FOOD": "食べ物",
|
||||
"GAMES": "ゲーム",
|
||||
"FITNESS": "フィットネス"
|
||||
},
|
||||
"FOOTER": {
|
||||
"ALPHA": "アルファ版にいます",
|
||||
"STATUS": "ステータス",
|
||||
"FORUM": "フォーラム",
|
||||
"SOURCE_CODE": "ソースコード"
|
||||
}
|
||||
},
|
||||
"HEADER": {
|
||||
"SEARCH": "サーチ",
|
||||
"FEEDBACK": "フィードバック"
|
||||
},
|
||||
"HOME": {
|
||||
"P1": "カテゴリを選択するか、何かを検索して始めてください。",
|
||||
"P2": "現在、ミン・プルート はベータ版です。 現在、機能は最低限のものであるか、期待どおりに動作しない可能性があります。"
|
||||
},
|
||||
"WATCH": {
|
||||
"BY": "による",
|
||||
"VIEWS": "ビュー",
|
||||
"RELATED": "関連ビデオ",
|
||||
"COMMENTS": "コメント"
|
||||
},
|
||||
"CHANNEL": {
|
||||
"FAMILY_FRIENDLY": "ファミリー向け",
|
||||
"HOME": "ホーム",
|
||||
"VIDEOS": "ビデオ",
|
||||
"COMMUNITY": "コミュニティ",
|
||||
"LATEST": "最新のビデオ",
|
||||
"ABOUT": "について"
|
||||
},
|
||||
"MUSIC": {
|
||||
"TITLE": "タイトル",
|
||||
"ARTIST": "アーティスト",
|
||||
"UPLOADED": "アップロード済み",
|
||||
"DURATION": "間隔"
|
||||
}
|
||||
}
|
55
src/public/locales/ru/translation.json
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"GLOBAL": {
|
||||
"MINPLUTO": "MinPluto"
|
||||
},
|
||||
"SIDEBAR": {
|
||||
"HOME": "Главная",
|
||||
"CATEGORY": "Категория",
|
||||
"CATEGORY_LIST": {
|
||||
"TRENDING": "В тренде",
|
||||
"TRENDING_DESCRIPTION": "То, что смотрят все",
|
||||
"MOVIES": "Фильмы",
|
||||
"MOVIES_DESCRIPTION": "Трейлеры фильмов и ТВ шоу",
|
||||
"MUSIC": "Музыка",
|
||||
"MUSIC_DESCRIPTION": "Популярные хиты",
|
||||
"GAMES": "Игры",
|
||||
"GAMES_DESCRIPTION": "Геймплей и прочее"
|
||||
},
|
||||
"DISCOVER": "Рекомендации",
|
||||
"DISCOVER_LIST": {
|
||||
"TECH": "Технологии",
|
||||
"COMEDY": "Комедия",
|
||||
"FOOD": "Еда",
|
||||
"GAMES": "Игры",
|
||||
"FITNESS": "Фитнес"
|
||||
},
|
||||
"FOOTER": {
|
||||
"ALPHA": "Вы в Альфа",
|
||||
"STATUS": "Статус",
|
||||
"FORUM": "Форум",
|
||||
"SOURCE_CODE": "Исходный код"
|
||||
}
|
||||
},
|
||||
"HEADER": {
|
||||
"SEARCH": "Поиск",
|
||||
"FEEDBACK": "Отзывы"
|
||||
},
|
||||
"HOME": {
|
||||
"P1": "Выберите категорию или начните поиск.",
|
||||
"P2": "В настоящий момент, MinPluto в альфе. Некоторые функции сырые или работают непредсказуемо"
|
||||
},
|
||||
"WATCH": {
|
||||
"BY": "От",
|
||||
"VIEWS": "Просмотры",
|
||||
"RELATED": "Похожие видео",
|
||||
"COMMENTS": "Комментарии"
|
||||
},
|
||||
"CHANNELS": {
|
||||
"FAMILY_FRIENDLY": "Для детей",
|
||||
"HOME": "Главная",
|
||||
"VIDEOS": "Видео",
|
||||
"COMMUNITY": "Сообщество",
|
||||
"LATEST": "Новые видео",
|
||||
"ABOUT": "Про"
|
||||
}
|
||||
}
|
33
src/public/manifest.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "MinPluto",
|
||||
"short_name": "MinPluto",
|
||||
"description": "An open source frontend alternative to YouTube.",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#000000",
|
||||
"theme_color": "#000000",
|
||||
"categories": [
|
||||
"entertainment",
|
||||
"music"
|
||||
],
|
||||
"dir": "ltr",
|
||||
"orientation": "any",
|
||||
"display_override": [
|
||||
"window-controls-overlay"
|
||||
],
|
||||
"icons": [
|
||||
{
|
||||
"src": "/images/pwa/MinPluto - PWA Logo.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"screenshots": [
|
||||
{
|
||||
"src": "/images/pwa/Mobile.png",
|
||||
"type": "image/png",
|
||||
"sizes": "527x1004",
|
||||
"form_factor": "narrow"
|
||||
}
|
||||
]
|
||||
}
|
9
src/public/robots.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
User-agent: Applebot
|
||||
User-agent: Googlebot
|
||||
User-agent: bingbot
|
||||
User-agent: Yandex
|
||||
User-agent: Yeti
|
||||
User-agent: Baiduspider
|
||||
User-agent: 360Spider
|
||||
User-agent: *
|
||||
Disallow: /
|
778
src/public/scripts/zorn.js
Normal file
|
@ -0,0 +1,778 @@
|
|||
(() => {
|
||||
// src/assets/icons/play-solid.svg
|
||||
var play_solid_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" stroke-width="1.5"><path d="M6.90588 4.53682C6.50592 4.2998 6 4.58808 6 5.05299V18.947C6 19.4119 6.50592 19.7002 6.90588 19.4632L18.629 12.5162C19.0211 12.2838 19.0211 11.7162 18.629 11.4838L6.90588 4.53682Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
|
||||
|
||||
// src/assets/icons/pause-solid.svg
|
||||
var pause_solid_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" stroke-width="1.5" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M6 18.4V5.6C6 5.26863 6.26863 5 6.6 5H9.4C9.73137 5 10 5.26863 10 5.6V18.4C10 18.7314 9.73137 19 9.4 19H6.6C6.26863 19 6 18.7314 6 18.4Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-fill="" data-darkreader-inline-stroke="" style="--darkreader-inline-fill: #ffffff; --darkreader-inline-stroke: #ffffff;"></path><path d="M14 18.4V5.6C14 5.26863 14.2686 5 14.6 5H17.4C17.7314 5 18 5.26863 18 5.6V18.4C18 18.7314 17.7314 19 17.4 19H14.6C14.2686 19 14 18.7314 14 18.4Z" fill="#ffffff" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-fill="" data-darkreader-inline-stroke="" style="--darkreader-inline-fill: #ffffff; --darkreader-inline-stroke: #ffffff;"></path></svg>';
|
||||
|
||||
// src/assets/icons/maximize.svg
|
||||
var maximize_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="M7 4H4V7" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M17 4H20V7" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 20H4V17" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M17 20H20V17" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
|
||||
|
||||
// src/assets/icons/closed-captions-tag.svg
|
||||
var closed_captions_tag_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M1 15V9C1 5.68629 3.68629 3 7 3H17C20.3137 3 23 5.68629 23 9V15C23 18.3137 20.3137 21 17 21H7C3.68629 21 1 18.3137 1 15Z" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M10.5 10L10.3284 9.82843C9.79799 9.29799 9.07857 9 8.32843 9V9C6.76633 9 5.5 10.2663 5.5 11.8284V12.1716C5.5 13.7337 6.76633 15 8.32843 15V15C9.07857 15 9.79799 14.702 10.3284 14.1716L10.5 14" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M18.5 10L18.3284 9.82843C17.798 9.29799 17.0786 9 16.3284 9V9C14.7663 9 13.5 10.2663 13.5 11.8284V12.1716C13.5 13.7337 14.7663 15 16.3284 15V15C17.0786 15 17.798 14.702 18.3284 14.1716L18.5 14" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>';
|
||||
|
||||
// src/assets/icons/backward15-seconds.svg
|
||||
var backward15_seconds_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" stroke-width="1.5" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff"><path d="M3 13C3 17.9706 7.02944 22 12 22C16.9706 22 21 17.9706 21 13C21 8.02944 16.9706 4 12 4" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M9 9L9 16" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 4L4.5 4M4.5 4L6.5 2M4.5 4L6.5 6" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
|
||||
|
||||
// src/assets/icons/forward15-seconds.svg
|
||||
var forward15_seconds_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" stroke-width="1.5" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff"><path d="M21 13C21 17.9706 16.9706 22 12 22C7.02944 22 3 17.9706 3 13C3 8.02944 7.02944 4 12 4" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 4H19.5M19.5 4L17.5 2M19.5 4L17.5 6" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M9 9L9 16" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 9L13 9C12.4477 9 12 9.44772 12 10L12 11.5C12 12.0523 12.4477 12.5 13 12.5L14 12.5C14.5523 12.5 15 12.9477 15 13.5L15 15C15 15.5523 14.5523 16 14 16L12 16" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
|
||||
|
||||
// src/assets/icons/sound-high.svg
|
||||
var sound_high_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M1 13.8571V10.1429C1 9.03829 1.89543 8.14286 3 8.14286H5.9C6.09569 8.14286 6.28708 8.08544 6.45046 7.97772L12.4495 4.02228C13.1144 3.5839 14 4.06075 14 4.85714V19.1429C14 19.9392 13.1144 20.4161 12.4495 19.9777L6.45046 16.0223C6.28708 15.9146 6.09569 15.8571 5.9 15.8571H3C1.89543 15.8571 1 14.9617 1 13.8571Z" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M17.5 7.5C17.5 7.5 19 9 19 11.5C19 14 17.5 15.5 17.5 15.5" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M20.5 4.5C20.5 4.5 23 7 23 11.5C23 16 20.5 18.5 20.5 18.5" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>';
|
||||
|
||||
// src/assets/icons/sound-min.svg
|
||||
var sound_min_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M3.5 13.8571V10.1429C3.5 9.03829 4.39543 8.14286 5.5 8.14286H8.4C8.59569 8.14286 8.78708 8.08544 8.95046 7.97772L14.9495 4.02228C15.6144 3.5839 16.5 4.06075 16.5 4.85714V19.1429C16.5 19.9392 15.6144 20.4161 14.9495 19.9777L8.95046 16.0223C8.78708 15.9146 8.59569 15.8571 8.4 15.8571H5.5C4.39543 15.8571 3.5 14.9617 3.5 13.8571Z" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M20.5 15L20.5 9" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>';
|
||||
|
||||
// src/assets/icons/sound-off.svg
|
||||
var sound_off_default = '<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#ffffff" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M18 14L20.0005 12M22 10L20.0005 12M20.0005 12L18 10M20.0005 12L22 14" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M2 13.8571V10.1429C2 9.03829 2.89543 8.14286 4 8.14286H6.9C7.09569 8.14286 7.28708 8.08544 7.45046 7.97772L13.4495 4.02228C14.1144 3.5839 15 4.06075 15 4.85714V19.1429C15 19.9392 14.1144 20.4161 13.4495 19.9777L7.45046 16.0223C7.28708 15.9146 7.09569 15.8571 6.9 15.8571H4C2.89543 15.8571 2 14.9617 2 13.8571Z" stroke="#ffffff" stroke-width="1.5" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>';
|
||||
|
||||
// src/assets/icons/refresh-double.svg
|
||||
var refresh_double_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" data-darkreader-inline-color="" style="--darkreader-inline-color: #e8e6e3;"><path d="M21.1679 8C19.6247 4.46819 16.1006 2 11.9999 2C6.81459 2 2.55104 5.94668 2.04932 11" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M17 8H21.4C21.7314 8 22 7.73137 22 7.4V3" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M2.88146 16C4.42458 19.5318 7.94874 22 12.0494 22C17.2347 22 21.4983 18.0533 22 13" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path><path d="M7.04932 16H2.64932C2.31795 16 2.04932 16.2686 2.04932 16.6V21" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: #ffffff;"></path></svg>';
|
||||
|
||||
// src/get.js
|
||||
var ZornVideoPlayer = document.querySelector(".zorn-player");
|
||||
var VideoContainer = document.querySelector(".video-container");
|
||||
var VideoControls = document.querySelector(".zorn-player-controls");
|
||||
var PlayIcon = play_solid_default;
|
||||
var PauseIcon = pause_solid_default;
|
||||
var FullcreenIcon = maximize_default;
|
||||
var CaptionsIcon = closed_captions_tag_default;
|
||||
var Backward15Icon = backward15_seconds_default;
|
||||
var Forward15Icon = forward15_seconds_default;
|
||||
var VolumeHighIcon = sound_high_default;
|
||||
var VolumeMinIcon = sound_min_default;
|
||||
var VolumeOffIcon = sound_off_default;
|
||||
var RefreshIcon = refresh_double_default;
|
||||
|
||||
// src/themes/default.js
|
||||
function Title() {
|
||||
let VideoTitle = ZornVideoPlayer.getAttribute("video-title");
|
||||
document.querySelector(".zorn-title").innerHTML = VideoTitle;
|
||||
if (ZornVideoPlayer.hasAttribute("video-title")) {
|
||||
document.querySelector(".zorn-title").style.display = "inherit";
|
||||
} else {
|
||||
document.querySelector(".zorn-title").style.display = "none";
|
||||
}
|
||||
}
|
||||
var Controls = `
|
||||
<div oncontextmenu="return false" class="zorn-player-controls">
|
||||
<div class="row-2">
|
||||
<div class="video-progress">
|
||||
<progress id="progress-bar" value="0" min="0"></progress>
|
||||
<input class="seek" id="seek" value="0" min="0" type="range" step="1">
|
||||
<div class="seek-tooltip" id="seek-tooltip">00:00</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-1">
|
||||
<div class="row-1-start">
|
||||
<div class="volume-controls">
|
||||
<button data-title="Mute (m)" class="volume-button" id="volume-button">${VolumeHighIcon}</button>
|
||||
<input class="volume" id="volume" value="1" type="range" max="1" min="0" step="0.01"/>
|
||||
</div>
|
||||
<div class="time">
|
||||
<time id="time-elapsed">00:00</time>
|
||||
<span> / </span>
|
||||
<time id="duration">00:00</time>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-1-center">
|
||||
<button id="skip-back">${Backward15Icon}</button>
|
||||
<button id="play-pause">${PlayIcon}</button>
|
||||
<button id="skip-forth">${Forward15Icon}</button>
|
||||
</div>
|
||||
<div class="row-1-end">
|
||||
<button id="subtitles">${CaptionsIcon}</button>
|
||||
<button id="fullscreen">${FullcreenIcon}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
:root {
|
||||
--zorn-progress-bar-bg: rgba(100, 100, 100, 0.5);
|
||||
--zorn-progress-bar: rgba(255, 0, 0, 0.5);
|
||||
--zorn-thumb: red;
|
||||
--zorn-rounded-corners: 4px;
|
||||
}
|
||||
.zorn-context-menu {
|
||||
background: linear-gradient(45deg, #0a141c 0%, rgba(10, 20, 28, 1) 100%);
|
||||
border-radius: 6px;
|
||||
border: 1px rgba(255, 255, 255, 0.08) solid;
|
||||
}
|
||||
.zorn-context-menu ul {
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
.zorn-context-menu ul li {
|
||||
padding: 8px 32px 8px 16px;
|
||||
margin: 4px;
|
||||
border-radius: 4px;
|
||||
font-family: arial;
|
||||
}
|
||||
.zorn-context-menu ul li:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
cursor: pointer;
|
||||
}
|
||||
.zorn-context-menu ul li i {
|
||||
font-size: 14px;
|
||||
margin-right: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
.video-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
color: white;
|
||||
}
|
||||
.video-container .zorn-player-dialogs #buffering {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
padding: 0px 24px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.video-container .zorn-player-dialogs #buffering h2 {
|
||||
font-size: 52px;
|
||||
}
|
||||
.video-container .zorn-player-dialogs #invalid-src {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 24px;
|
||||
transform: translate(0px, -50%);
|
||||
padding: 0px 24px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.video-container .zorn-player-dialogs #invalid-src h2 {
|
||||
font-size: 52px;
|
||||
}
|
||||
.video-container .zorn-player {
|
||||
display: inline-flex;
|
||||
}
|
||||
.video-container .zorn-title {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
background: rgb(0 0 0 / 50%);
|
||||
width: auto;
|
||||
margin: 12px;
|
||||
padding: 12px 24px;
|
||||
border-radius: 10px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.video-container .hide {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.video-container .zorn-player-title {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
background-image: linear-gradient(to top, rgba(12, 12, 12, 0), rgba(12, 12, 12, 0.75));
|
||||
padding: 12px 24px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.video-container .subtitles-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 60px;
|
||||
bottom: 70px;
|
||||
background: #000 9;
|
||||
list-style: none;
|
||||
padding: 6px;
|
||||
border-radius: 6px;
|
||||
background: rgb(0 0 0 / 50%);
|
||||
}
|
||||
.video-container .subtitles-menu button {
|
||||
background-color: transparent;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 6px 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.video-container .subtitles-menu button:hover {
|
||||
background: #fff 29;
|
||||
}
|
||||
.video-container .subtitles-menu .hide {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.video-container .zorn-player-controls {
|
||||
display: inline-flex;
|
||||
right: 0;
|
||||
left: 0;
|
||||
padding: 10px;
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
transition: all 0.2s ease;
|
||||
background-image: linear-gradient(to bottom, rgba(12, 12, 12, 0), rgba(12, 12, 12, 0.75));
|
||||
flex-direction: inherit;
|
||||
}
|
||||
.video-container .zorn-player-controls .row-1 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
.video-container .zorn-player-controls .row-1-start {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.video-container .zorn-player-controls .row-1-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.video-container .zorn-player-controls .row-1-end {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.video-container .zorn-player-controls button {
|
||||
aspect-ratio: 1;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
margin: 0px 6px;
|
||||
}
|
||||
.volume-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.video-container .zorn-player-controls .volume-controls:hover > #volume {
|
||||
opacity: 1;
|
||||
transition: 0.3s opacity, 0.3s width;
|
||||
margin: 0px;
|
||||
width: 72px;
|
||||
}
|
||||
.video-container .zorn-player-controls #volume {
|
||||
opacity: 0;
|
||||
transition: 0.3s opacity, 0.3s width;
|
||||
margin: 0px 12px 0px -6px;
|
||||
width: 0px;
|
||||
}
|
||||
.video-container .zorn-player-controls #volume-button svg {
|
||||
aspect-ratio: 1;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
fill: white;
|
||||
padding: 3px 0px 0px 0px;
|
||||
}
|
||||
.video-container .zorn-player-controls .video-progress {
|
||||
position: relative;
|
||||
height: 6.4px;
|
||||
margin: 24px 0px;
|
||||
width: 100%;
|
||||
}
|
||||
.video-container .zorn-player-controls progress {
|
||||
border-radius: 1rem;
|
||||
width: 100%;
|
||||
height: 8.4px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
.video-container .zorn-player-controls progress::-webkit-progress-bar {
|
||||
border-radius: 1rem;
|
||||
background: var(--zorn-progress-bar-bg);
|
||||
}
|
||||
.video-container .zorn-player-controls progress::-webkit-progress-value {
|
||||
background: var(--zorn-progress-bar);
|
||||
border-radius: 1rem;
|
||||
}
|
||||
.video-container .zorn-player-controls progress::-moz-progress-bar {
|
||||
border-radius: 1rem;
|
||||
background: var(--zorn-progress-bar-bg);
|
||||
}
|
||||
.video-container .zorn-player-controls .seek {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
}
|
||||
.video-container .zorn-player-controls .seek:hover + .seek-tooltip {
|
||||
display: block;
|
||||
}
|
||||
.video-container .zorn-player-controls .seek-tooltip {
|
||||
display: none;
|
||||
position: relative;
|
||||
top: -32px;
|
||||
margin-left: -30px;
|
||||
font-size: 12px;
|
||||
content: attr(data-title);
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
width: fit-content;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range] {
|
||||
height: 8.4px;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range]:focus {
|
||||
outline: none;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range]:focus::-webkit-slider-runnable-track {
|
||||
background: transparent;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range]:focus::-moz-range-track {
|
||||
outline: none;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range]::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
border-radius: 1.3px;
|
||||
-webkit-appearance: none;
|
||||
transition: all 0.4s ease;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range]::-webkit-slider-thumb {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
border-radius: 10px;
|
||||
background: var(--zorn-thumb);
|
||||
cursor: pointer;
|
||||
-webkit-appearance: none;
|
||||
margin-left: -1px;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range]::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 8.4px;
|
||||
cursor: pointer;
|
||||
border: 1px solid transparent;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range].volume {
|
||||
height: 5px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range].volume::-webkit-slider-runnable-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range].volume::-webkit-slider-thumb {
|
||||
margin-left: 0;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
background: #fff;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type=range].volume::-moz-range-thumb {
|
||||
border: 1px solid #fff;
|
||||
background: #fff;
|
||||
}
|
||||
.video-container .zorn-player-controls input[type="range"]::-moz-range-thumb {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
background: var(--zorn-thumb);
|
||||
cursor: pointer;
|
||||
}
|
||||
.video-container .zorn-player-controls .hide {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.video-container .zorn-player-controls #progress-bar {
|
||||
background: var(--zorn-progress-bar-bg);
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
}
|
||||
div#buffering {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 90%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: 1s spin linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg)
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg)
|
||||
}
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
ZornVideoPlayer.insertAdjacentHTML("afterend", Controls);
|
||||
if (ZornVideoPlayer.getAttribute("layout") === "default") {
|
||||
Title();
|
||||
}
|
||||
|
||||
// src/events.js
|
||||
function Events() {
|
||||
ZornVideoPlayer.addEventListener("error", function(event) {
|
||||
document.querySelector("#invalid-src").style.display = "inherit";
|
||||
document.querySelector(".zorn-player-controls").style.display = "none";
|
||||
videoContainer.style.backgroundColor = "#101010";
|
||||
setTimeout(() => {
|
||||
ZornVideoPlayer.style.opacity = "0.10";
|
||||
document.querySelector("#buffering").style.display = "none";
|
||||
}, 168);
|
||||
}, true);
|
||||
ZornVideoPlayer.onwaiting = (event) => {
|
||||
document.querySelector("#buffering").style.display = "inherit";
|
||||
ZornVideoPlayer.style.transition = "5s opacity";
|
||||
ZornVideoPlayer.style.opacity = "0.25";
|
||||
};
|
||||
ZornVideoPlayer.oncanplaythrough = (event) => {
|
||||
document.querySelector("#buffering").style.display = "none";
|
||||
ZornVideoPlayer.style.transition = "0.3s opacity";
|
||||
ZornVideoPlayer.style.opacity = "1";
|
||||
};
|
||||
}
|
||||
|
||||
// src/functions/PlayPause.js
|
||||
function PlayPause() {
|
||||
const Button_PlayPause = document.querySelector(".zorn-player-controls #play-pause");
|
||||
Button_PlayPause.addEventListener("click", Toggle_PlayPause);
|
||||
ZornVideoPlayer.addEventListener("click", Toggle_PlayPause);
|
||||
ZornVideoPlayer.addEventListener("play", Update_PlayPauseButton);
|
||||
ZornVideoPlayer.addEventListener("pause", Update_PlayPauseButton);
|
||||
function Toggle_PlayPause() {
|
||||
if (ZornVideoPlayer.paused || ZornVideoPlayer.ended) {
|
||||
ZornVideoPlayer.play();
|
||||
} else {
|
||||
ZornVideoPlayer.pause();
|
||||
}
|
||||
}
|
||||
function Update_PlayPauseButton() {
|
||||
if (ZornVideoPlayer.paused) {
|
||||
Button_PlayPause.setAttribute("data-title", "Play (K)");
|
||||
Button_PlayPause.innerHTML = `${PlayIcon}`;
|
||||
} else {
|
||||
Button_PlayPause.setAttribute("data-title", "Pause (K)");
|
||||
Button_PlayPause.innerHTML = `${PauseIcon}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// src/functions/SkipAround.js
|
||||
function SkipAround() {
|
||||
const Button_SkipBack = document.querySelector(".zorn-player-controls #skip-back");
|
||||
const Button_SkipForth = document.querySelector(".zorn-player-controls #skip-forth");
|
||||
Button_SkipBack.addEventListener("click", Toggle_SkipBack);
|
||||
Button_SkipForth.addEventListener("click", Toggle_SkipForth);
|
||||
function Toggle_SkipBack() {
|
||||
Skip(-10);
|
||||
}
|
||||
function Toggle_SkipForth() {
|
||||
Skip(10);
|
||||
}
|
||||
function Skip(value) {
|
||||
ZornVideoPlayer.currentTime += value;
|
||||
}
|
||||
}
|
||||
|
||||
// src/functions/Fullscreen.js
|
||||
function Fullscreen() {
|
||||
const Button_Fullscreen = document.getElementById("fullscreen");
|
||||
function Toggle_Fullscreen() {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.webkitFullscreenElement) {
|
||||
document.webkitExitFullscreen();
|
||||
} else if (VideoContainer.webkitRequestFullscreen) {
|
||||
VideoContainer.webkitRequestFullscreen();
|
||||
} else {
|
||||
VideoContainer.requestFullscreen();
|
||||
}
|
||||
}
|
||||
Button_Fullscreen.onclick = Toggle_Fullscreen;
|
||||
function Update_FullscreenButton() {
|
||||
if (document.fullscreenElement) {
|
||||
Button_Fullscreen.setAttribute("data-title", "Exit full screen (f)");
|
||||
} else {
|
||||
Button_Fullscreen.setAttribute("data-title", "Full screen (f)");
|
||||
}
|
||||
}
|
||||
ZornVideoPlayer.addEventListener("dblclick", () => {
|
||||
Toggle_Fullscreen();
|
||||
});
|
||||
}
|
||||
|
||||
// src/functions/Subtitles.js
|
||||
function Subtitles() {
|
||||
var subtitles = document.querySelector('.zorn-player-controls #subtitles')
|
||||
var subtitleMenuButtons = []
|
||||
var createMenuItem = function(id, lang, label) {
|
||||
var listItem = document.createElement('li')
|
||||
var button = listItem.appendChild(document.createElement('button'))
|
||||
button.setAttribute('id', id)
|
||||
button.className = 'subtitles-button'
|
||||
if (lang.length > 0) button.setAttribute('lang', lang)
|
||||
button.value = label
|
||||
button.setAttribute('data-state', 'inactive')
|
||||
button.appendChild(document.createTextNode(label))
|
||||
button.addEventListener('click', function(e) {
|
||||
subtitleMenuButtons.map(function(v, i, a) {
|
||||
subtitleMenuButtons[i].setAttribute('data-state', 'inactive')
|
||||
})
|
||||
var lang = this.getAttribute('lang')
|
||||
for (var i = 0; i < ZornVideoPlayer.textTracks.length; i++) {
|
||||
if (ZornVideoPlayer.textTracks[i].language == lang) {
|
||||
ZornVideoPlayer.textTracks[i].mode = 'showing'
|
||||
this.setAttribute('data-state', 'active')
|
||||
}
|
||||
else {
|
||||
ZornVideoPlayer.textTracks[i].mode = 'hidden'
|
||||
}
|
||||
}
|
||||
subtitlesMenu.style.display = 'none'
|
||||
})
|
||||
subtitleMenuButtons.push(button)
|
||||
return listItem
|
||||
}
|
||||
var subtitlesMenu
|
||||
if (ZornVideoPlayer.textTracks) {
|
||||
var df = document.createDocumentFragment()
|
||||
var subtitlesMenu = df.appendChild(document.createElement('ul'))
|
||||
subtitlesMenu.className = 'subtitles-menu'
|
||||
subtitlesMenu.appendChild(createMenuItem('subtitles-off', '', 'Off'))
|
||||
for (var i = 0; i < ZornVideoPlayer.textTracks.length; i++) {
|
||||
subtitlesMenu.appendChild(createMenuItem('subtitles-' + ZornVideoPlayer.textTracks[i].language, ZornVideoPlayer.textTracks[i].language, ZornVideoPlayer.textTracks[i].label))
|
||||
}
|
||||
VideoContainer.appendChild(subtitlesMenu)
|
||||
}
|
||||
subtitles.addEventListener('click', function(e) {
|
||||
if (subtitlesMenu) {
|
||||
subtitlesMenu.style.display = (subtitlesMenu.style.display == 'block' ? 'none' : 'block')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// src/functions/Volume.js
|
||||
function Volume() {
|
||||
const Button_Volume = document.getElementById("volume-button");
|
||||
const volume2 = document.getElementById("volume");
|
||||
function Update_Volme() {
|
||||
if (ZornVideoPlayer.muted) {
|
||||
ZornVideoPlayer.muted = false;
|
||||
}
|
||||
ZornVideoPlayer.volume = volume2.value;
|
||||
}
|
||||
volume2.addEventListener("input", Update_Volme);
|
||||
function Update_Volume_Icon() {
|
||||
Button_Volume.setAttribute("data-title", "Mute (M)");
|
||||
if (ZornVideoPlayer.muted || ZornVideoPlayer.volume === 0) {
|
||||
Button_Volume.innerHTML = `${VolumeOffIcon}`;
|
||||
Button_Volume.setAttribute("data-title", "Unmute (M)");
|
||||
} else if (ZornVideoPlayer.volume > 0 && ZornVideoPlayer.volume <= 0.5) {
|
||||
Button_Volume.innerHTML = `${VolumeMinIcon}`;
|
||||
} else {
|
||||
Button_Volume.innerHTML = `${VolumeHighIcon}`;
|
||||
}
|
||||
}
|
||||
ZornVideoPlayer.addEventListener("volumechange", Update_Volume_Icon);
|
||||
function Toggle_Mute() {
|
||||
ZornVideoPlayer.muted = !ZornVideoPlayer.muted;
|
||||
if (ZornVideoPlayer.muted) {
|
||||
volume2.setAttribute("data-volume", volume2.value);
|
||||
volume2.value = 0;
|
||||
} else {
|
||||
volume2.value = volume2.dataset.volume;
|
||||
}
|
||||
}
|
||||
Button_Volume.addEventListener("click", Toggle_Mute);
|
||||
}
|
||||
|
||||
// src/functions/Seek.js
|
||||
function Seek() {
|
||||
const timeElapsed = document.getElementById("time-elapsed");
|
||||
const duration = document.getElementById("duration");
|
||||
function formatTime(timeInSeconds) {
|
||||
const result = new Date(timeInSeconds * 1e3).toISOString().substr(11, 8);
|
||||
return {
|
||||
minutes: result.substr(3, 2),
|
||||
seconds: result.substr(6, 2)
|
||||
};
|
||||
}
|
||||
;
|
||||
function initializeVideo() {
|
||||
const videoDuration = Math.round(ZornVideoPlayer.duration);
|
||||
const time = formatTime(videoDuration);
|
||||
duration.innerText = `${time.minutes}:${time.seconds}`;
|
||||
duration.setAttribute("datetime", `${time.minutes}m ${time.seconds}s`);
|
||||
}
|
||||
ZornVideoPlayer.addEventListener("loadedmetadata", initializeVideo);
|
||||
function updateTimeElapsed() {
|
||||
const time = formatTime(Math.round(ZornVideoPlayer.currentTime));
|
||||
timeElapsed.innerText = `${time.minutes}:${time.seconds}`;
|
||||
timeElapsed.setAttribute("datetime", `${time.minutes}m ${time.seconds}s`);
|
||||
}
|
||||
ZornVideoPlayer.addEventListener("timeupdate", updateTimeElapsed);
|
||||
const progressBar = document.getElementById("progress-bar");
|
||||
const seek = document.getElementById("seek");
|
||||
function initializeVideo() {
|
||||
const videoDuration = Math.round(ZornVideoPlayer.duration);
|
||||
seek.setAttribute("max", videoDuration);
|
||||
progressBar.setAttribute("max", videoDuration);
|
||||
const time = formatTime(videoDuration);
|
||||
duration.innerText = `${time.minutes}:${time.seconds}`;
|
||||
duration.setAttribute("datetime", `${time.minutes}m ${time.seconds}s`);
|
||||
}
|
||||
function updateProgress() {
|
||||
seek.value = Math.floor(ZornVideoPlayer.currentTime);
|
||||
progressBar.value = Math.floor(ZornVideoPlayer.currentTime);
|
||||
}
|
||||
ZornVideoPlayer.addEventListener("timeupdate", updateProgress);
|
||||
const seekTooltip = document.getElementById("seek-tooltip");
|
||||
function updateSeekTooltip(event) {
|
||||
const skipTo = Math.round(event.offsetX / event.target.clientWidth * parseInt(event.target.getAttribute("max"), 10));
|
||||
seek.setAttribute("data-seek", skipTo);
|
||||
const t = formatTime(skipTo);
|
||||
seekTooltip.textContent = `${t.minutes}:${t.seconds}`;
|
||||
const rect = ZornVideoPlayer.getBoundingClientRect();
|
||||
seekTooltip.style.left = `${event.pageX - rect.left}px`;
|
||||
}
|
||||
seek.addEventListener("mousemove", updateSeekTooltip);
|
||||
function skipAhead(event) {
|
||||
const skipTo = event.target.dataset.seek ? event.target.dataset.seek : event.target.value;
|
||||
ZornVideoPlayer.currentTime = skipTo;
|
||||
progressBar.value = skipTo;
|
||||
seek.value = skipTo;
|
||||
}
|
||||
seek.addEventListener("input", skipAhead);
|
||||
initializeVideo();
|
||||
}
|
||||
|
||||
// src/dialogs/Buffering.js
|
||||
var BufferDialog = `
|
||||
<div id="buffering" class="zorn-dialog">
|
||||
${RefreshIcon}
|
||||
</div>
|
||||
`;
|
||||
ZornVideoPlayer.insertAdjacentHTML("afterend", BufferDialog);
|
||||
|
||||
// src/functions/AutoToggleControls.js
|
||||
function AutoToggleControls() {
|
||||
function Hide_Controls2() {
|
||||
if (ZornVideoPlayer.paused) {
|
||||
return;
|
||||
} else {
|
||||
document.querySelector(".zorn-player-controls").classList.add("hide");
|
||||
}
|
||||
}
|
||||
function Show_Controls2() {
|
||||
document.querySelector(".zorn-player-controls").classList.remove("hide");
|
||||
}
|
||||
ZornVideoPlayer.addEventListener("mouseenter", Show_Controls2);
|
||||
ZornVideoPlayer.addEventListener("mouseleave", Hide_Controls2);
|
||||
document.querySelector(".zorn-player-controls").addEventListener("mouseenter", Show_Controls2);
|
||||
document.querySelector(".zorn-player-controls").addEventListener("mouseleave", Hide_Controls2);
|
||||
var mouseTimer = null, cursorVisible = true;
|
||||
function Hide_Cursor() {
|
||||
mouseTimer = null;
|
||||
VideoContainer.style.cursor = "none";
|
||||
cursorVisible = false;
|
||||
Hide_Controls2();
|
||||
}
|
||||
document.onmousemove = function() {
|
||||
if (mouseTimer) {
|
||||
window.clearTimeout(mouseTimer);
|
||||
Show_Controls2();
|
||||
}
|
||||
if (!cursorVisible) {
|
||||
VideoContainer.style.cursor = "default";
|
||||
cursorVisible = true;
|
||||
}
|
||||
mouseTimer = window.setTimeout(Hide_Cursor, 3200);
|
||||
};
|
||||
}
|
||||
|
||||
// src/functions/KeyboardShortcuts.js
|
||||
function KeyboardShortcuts(events) {
|
||||
if (ZornVideoPlayer.hasAttribute("keyboard-shortcut-fullscreen")) {
|
||||
var Fullscreen_KeyboardShortcut = ZornVideoPlayer.getAttribute("keyboard-shortcut-fullscreen");
|
||||
} else {
|
||||
var Fullscreen_KeyboardShortcut = "f";
|
||||
}
|
||||
if (ZornVideoPlayer.hasAttribute("keyboard-shortcut-mute")) {
|
||||
var Mute_KeyboardShortcut = ZornVideoPlayer.getAttribute("keyboard-shortcut-mute");
|
||||
} else {
|
||||
var Mute_KeyboardShortcut = "m";
|
||||
}
|
||||
if (ZornVideoPlayer.hasAttribute("keyboard-shortcut-playpause")) {
|
||||
var PlayPause_KeyboardShortcut = ZornVideoPlayer.getAttribute("keyboard-shortcut-playpause");
|
||||
} else {
|
||||
var PlayPause_KeyboardShortcut = "k";
|
||||
}
|
||||
if (ZornVideoPlayer.hasAttribute("keyboard-shortcut-skipback")) {
|
||||
var SkipBack_KeyboardShortcut = ZornVideoPlayer.getAttribute("keyboard-shortcut-skipback");
|
||||
} else {
|
||||
var SkipBack_KeyboardShortcut = "j";
|
||||
}
|
||||
if (ZornVideoPlayer.hasAttribute("keyboard-shortcut-skipforth")) {
|
||||
var SkipForth_KeyboardShortcut = ZornVideoPlayer.getAttribute("keyboard-shortcut-skipforth");
|
||||
} else {
|
||||
var SkipForth_KeyboardShortcut = "l";
|
||||
}
|
||||
function keyboardShortcuts(event) {
|
||||
const { key } = event;
|
||||
if (key === PlayPause_KeyboardShortcut) {
|
||||
if (ZornVideoPlayer.paused || ZornVideoPlayer.ended) {
|
||||
ZornVideoPlayer.play();
|
||||
} else {
|
||||
ZornVideoPlayer.pause();
|
||||
}
|
||||
if (ZornVideoPlayer.paused) {
|
||||
Show_Controls();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
Hide_Controls();
|
||||
}, 1200);
|
||||
}
|
||||
} else if (key === Mute_KeyboardShortcut) {
|
||||
ZornVideoPlayer.muted = !ZornVideoPlayer.muted;
|
||||
if (ZornVideoPlayer.muted) {
|
||||
volume.setAttribute("data-volume", volume.value);
|
||||
volume.value = 0;
|
||||
} else {
|
||||
volume.value = volume.dataset.volume;
|
||||
}
|
||||
} else if (key === Fullscreen_KeyboardShortcut) {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.webkitFullscreenElement) {
|
||||
document.webkitExitFullscreen();
|
||||
} else if (VideoContainer.webkitRequestFullscreen) {
|
||||
VideoContainer.webkitRequestFullscreen();
|
||||
} else {
|
||||
VideoContainer.requestFullscreen();
|
||||
}
|
||||
} else if (key === SkipBack_KeyboardShortcut) {
|
||||
ZornVideoPlayer.currentTime += -10;
|
||||
} else if (key === SkipForth_KeyboardShortcut) {
|
||||
ZornVideoPlayer.currentTime += 10;
|
||||
}
|
||||
}
|
||||
document.addEventListener("keyup", keyboardShortcuts);
|
||||
}
|
||||
|
||||
// src/index.js
|
||||
Events();
|
||||
KeyboardShortcuts();
|
||||
PlayPause();
|
||||
AutoToggleControls();
|
||||
SkipAround();
|
||||
Fullscreen();
|
||||
Subtitles();
|
||||
Volume();
|
||||
Seek();
|
||||
Buffering();
|
||||
})();
|
||||
|
43
src/public/service-worker.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Service Worker is used to cache the offline page
|
||||
// if the end-user were to ever go offline. An offline page
|
||||
// should show up if their network condition is offline.
|
||||
// This is best practice for the Progress Web App and
|
||||
// provides a better user experience.
|
||||
|
||||
// Read more on this topic:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Offline_and_background_operation#offline_operation
|
||||
|
||||
'use strict'
|
||||
|
||||
var cacheVersion = 1
|
||||
var currentCache = {
|
||||
offline: 'offline-cache' + cacheVersion
|
||||
}
|
||||
const offlineUrl = 'offline'
|
||||
|
||||
this.addEventListener('install', event => {
|
||||
event.waitUntil(
|
||||
caches.open(currentCache.offline).then(function (cache) {
|
||||
return cache.addAll([
|
||||
offlineUrl
|
||||
])
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
this.addEventListener('fetch', event => {
|
||||
if (event.request.mode === 'navigate' || (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
|
||||
event.respondWith(
|
||||
fetch(event.request.url).catch(error => {
|
||||
return caches.match(offlineUrl)
|
||||
})
|
||||
)
|
||||
}
|
||||
else {
|
||||
event.respondWith(caches.match(event.request)
|
||||
.then(function (response) {
|
||||
return response || fetch(event.request)
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
10
src/styles/embed.scss
Normal file
|
@ -0,0 +1,10 @@
|
|||
body {background: black}
|
||||
video {border-radius: 0px !important}
|
||||
.video-container {
|
||||
max-width: 100% !important;
|
||||
width: 100% !important;
|
||||
position: fixed !important;
|
||||
top: 0px !important;
|
||||
left: 0px !important;
|
||||
height: 100% !important;
|
||||
}
|
110
src/styles/index.scss
Normal file
|
@ -0,0 +1,110 @@
|
|||
body {
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
margin: auto;
|
||||
width: calc(100% - 248px);
|
||||
}
|
||||
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
hr {
|
||||
width: 100px;
|
||||
border: none;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
height: 4px;
|
||||
border-radius: 1rem;
|
||||
margin: 24px auto;
|
||||
}
|
||||
|
||||
.header {
|
||||
backdrop-filter: blur(10px) brightness(0.4);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
position: sticky;
|
||||
top: 12px;
|
||||
z-index: 5;
|
||||
border-radius: 10px;
|
||||
margin-top: 12px;
|
||||
.header-start {
|
||||
width: 75%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.header-end {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
a, select {
|
||||
background: transparent;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 1rem;
|
||||
padding: 20px;
|
||||
font-size: 14px;
|
||||
border: 1px transparent solid;
|
||||
gap: 6px;
|
||||
svg {
|
||||
width: 20px;
|
||||
}
|
||||
&:hover {
|
||||
color: gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span#gradient-header {
|
||||
background: linear-gradient(180deg, black, transparent);
|
||||
height: 50px;
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1000px;
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.video-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
grid-gap: 25px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
|
||||
.music-list {
|
||||
display: grid;
|
||||
grid-gap: 25px;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: sticky;
|
||||
top: 58px;
|
||||
background: black;
|
||||
z-index: 1;
|
||||
padding: 0px 24px;
|
||||
}
|
||||
|
||||
.rea-recommendations {
|
||||
min-width: 200px;
|
||||
max-width: 360px;
|
||||
}
|
58
src/styles/mobile.scss
Normal file
|
@ -0,0 +1,58 @@
|
|||
.mobile-navigation, .mo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-navigation {
|
||||
position: fixed;
|
||||
bottom: 24px;
|
||||
left: 50%;
|
||||
width: fit-content;
|
||||
background: rgba(10, 10, 10, 0.8);
|
||||
backdrop-filter:blur(4px) contrast(0.5);
|
||||
padding: 12px;
|
||||
gap: 24px;
|
||||
justify-content: space-around;
|
||||
z-index: 50;
|
||||
transform: translate(-50%);
|
||||
border-radius: 10rem;
|
||||
a {
|
||||
background: transparent;
|
||||
border-radius: 3rem;
|
||||
aspect-ratio: 1;
|
||||
color: white;
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
svg {
|
||||
width: 32px;
|
||||
height: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 875px) {
|
||||
body {
|
||||
width: 100%;
|
||||
padding-bottom: 124px;
|
||||
}
|
||||
.sidebar {
|
||||
display: none !important;
|
||||
}
|
||||
.mobile-navigation, .mo {
|
||||
display: flex;
|
||||
}
|
||||
.header, .page-title {
|
||||
background: rgb(0 0 0 / 80%);
|
||||
backdrop-filter: blur(10px) contrast(0.8);
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 800px) {
|
||||
.rea-details-start {
|
||||
flex-direction: column;
|
||||
gap: 32px;
|
||||
align-items: start !important;
|
||||
}
|
||||
body > div.content > div.video-rea > div:nth-child(2) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
0
src/styles/sidebar.scss
Normal file
97
src/styles/video.scss
Normal file
|
@ -0,0 +1,97 @@
|
|||
.video-rea {
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
padding: 0px 24px;
|
||||
.rea-details-start {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24px 0px;
|
||||
button {
|
||||
background: rgb(45 45 45);
|
||||
border: none;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
border-radius: 3rem;
|
||||
padding: 6px 16px;
|
||||
margin-left: 6px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.rea-channel {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
img {
|
||||
border-radius: 3rem;
|
||||
}
|
||||
.rea-channel div {
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
h2, p {
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.comment {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
gap: 12px;
|
||||
margin-bottom: 24px;
|
||||
img {
|
||||
border-radius: 3rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
a {
|
||||
color: white;
|
||||
}
|
||||
p {
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.video-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
.video-item-thumbnail {
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 6px;
|
||||
aspect-ratio: 16/9;
|
||||
object-fit: contain;
|
||||
}
|
||||
p#vi-length {
|
||||
margin: -42px 6px 20px 0px;
|
||||
background: rgb(0 0 0 / 75%);
|
||||
padding: 6px;
|
||||
width: max-content;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
.video-item-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
p {
|
||||
margin: 0px;
|
||||
&#vi-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
&#vi-author {
|
||||
color: darkgrey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|