This commit is contained in:
Alex 2022-04-01 14:03:31 +13:00
commit 58d61be3a3
43 changed files with 685 additions and 319 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -29,7 +29,11 @@
{{ title.text }}
</div>
<div class="grey--text caption" v-text="parseBottom(video)" />
<div
class="caption background--text"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
v-text="parseBottom(video)"
/>
</v-card-text>
</div>
</v-card>

View File

@ -1,6 +1,6 @@
<template>
<v-card
class="entry gridVideoRenderer accent"
class="entry gridVideoRenderer background"
:to="`/watch?v=${video.videoId}`"
flat
>
@ -52,7 +52,11 @@
{{ title.text }}
</div>
<div class="grey--text caption" v-text="parseBottom(video)" />
<div
class="background--text caption"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
v-text="parseBottom(video)"
/>
</v-card-text>
</div>
</v-card>

View File

@ -1,15 +1,17 @@
<template>
<div>
<div class="content">
<v-btn class="pausePlay" text @click="playing = !playing">
<v-icon size="5em" color="white">mdi-{{ playing ? "pause" : "play" }}</v-icon>
</v-btn>
<div @click="toggleControls()" class="content" :style="showControls ? 'background: rgba(0, 0, 0, 0.5);' : '' ">
<scrubber class="scrubber" :duration="duration" :endDuration="endDuration" />
<div v-show="showControls">
<v-btn class="pausePlay" text @click="playing = !playing">
<v-icon size="5em" color="white">mdi-{{ playing ? "pause" : "play" }}</v-icon>
</v-btn>
<scrubber class="scrubber" :duration="duration" :endDuration="endDuration" />
</div>
<video
ref="player"
autoplay
:src="vidSrc"
width="100%"
style="max-height: 50vh"
@ -43,7 +45,8 @@ export default {
vidSrc: null,
//--- Player State Information ---//
playing: true,
showControls: false,
playing: false,
duration: 0,
endDuration: 0,
};
@ -79,6 +82,11 @@ export default {
this.duration = player.currentTime;
this.endDuration = player.duration;
},
toggleControls() {
this.showControls = !this.showControls;
}
},
};
</script>
@ -97,7 +105,6 @@ export default {
.content:before {
content: "";
position: absolute;
background: rgba(0, 0, 0, 0.5);
top: 0;
right: 0;
bottom: 0;

View File

@ -16,7 +16,8 @@
v-if="
render.separatorDetails && render.separatorDetails.hasBottomSeparator
"
class="separator-bottom grey"
class="separator-bottom background"
:class="$vuetify.theme.dark ? 'lighten-4' : 'darken-4'"
:style="{ height: render.separatorDetails.height + 'px' }"
></div>
</div>

View File

@ -13,7 +13,8 @@
></component>
<div
v-if="render.separator && render.separator.hasBottomSeparator"
class="separator-bottom grey"
class="separator-bottom background"
:class="$vuetify.theme.dark ? 'lighten-4' : 'darken-4'"
:style="{ height: render.separator.height + 'px' }"
></div>
</div>

View File

@ -2,7 +2,7 @@
<v-bottom-navigation
v-model="tabSelection"
shift
class="bottomNav py-4 accent"
class="bottomNav py-4 transparent"
>
<v-btn
v-for="(item, i) in tabs"
@ -14,8 +14,20 @@
>
<span v-text="item.name" />
<v-icon
:color="tabSelection == i ? 'primary' : 'grey'"
:class="tabSelection == i ? 'tab primary lighten-2' : ''"
:color="
tabSelection == i
? 'primary'
: $vuetify.theme.dark
? 'background lighten-4'
: 'background darken-4'
"
:class="
tabSelection == i
? $vuetify.theme.dark
? 'tab primary darken-4'
: 'tab primary lighten-4'
: ''
"
v-text="item.icon"
/>
<!--
@ -56,12 +68,12 @@ export default {
<style scoped>
.bottomNav {
/* ios gesture nav */
bottom: env(safe-area-inset-bottom) !important;
box-shadow: none !important;
height: 4rem !important;
position: fixed;
bottom: 0;
padding: 0 !important;
z-index: 99999;
position: fixed;
}
.navButton {
width: 25vw !important;

View File

@ -1,11 +1,12 @@
<template>
<v-card
class="entry gridVideoRenderer accent"
class="entry gridVideoRenderer background"
:to="`/watch?v=${video.videoId}`"
flat
>
<div style="position: relative" class="thumbnail-container">
<v-img
v-if="video.thumbnail"
:aspect-ratio="16 / 9"
:src="
$youtube.getThumbnail(
@ -16,6 +17,7 @@
"
/>
<div
v-if="video.thumbnailOverlays"
class="videoRuntimeFloat"
:class="
'style-' +
@ -31,7 +33,7 @@
<div id="details">
<a
:href="
this.$rendererUtils.getNavigationEndpoints(
$rendererUtils.getNavigationEndpoints(
video.shortBylineText.runs[0].navigationEndpoint
)
"
@ -52,7 +54,11 @@
{{ title.text }}
</div>
<div class="grey--text caption" v-text="parseBottom(video)" />
<div
class="background--text text--lighten-5 caption"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
v-text="parseBottom(video)"
/>
</v-card-text>
</div>
</v-card>

View File

@ -1,8 +1,7 @@
<template>
<v-card
style="height: 4rem !important; display: flex; box-shadow: none !important"
color="accent"
class="topNav rounded-0 pa-3"
class="rounded-0 pa-3 topNav transparent"
>
<h3 v-show="!search" class="my-auto ml-4" v-text="page" />
@ -22,7 +21,10 @@
dense
flat
label="Search"
class="searchBar"
style="margin-top: 1px"
:background-color="
$vuetify.theme.dark ? 'background lighten-1' : 'background darken-1'
"
@input="$emit('text-changed', text)"
@keyup.enter="$emit('search-btn', text)"
/>
@ -30,6 +32,7 @@
<v-spacer v-if="!search" />
<v-btn
v-if="!search"
v-show="page == 'Home'"
icon
tile
@ -100,18 +103,13 @@ export default {
<style scoped>
.topNav {
/* ios notch */
top: env(safe-area-inset-top) !important;
position: fixed;
width: 100%;
top: 0;
z-index: 999;
/*border-radius: 0 0 1em 1em !important;*/
}
.topNavSearch {
margin-bottom: -10em;
margin-left: 2em;
/*transform: translateY(-2.5%);*/
}
.searchBar {
margin: 0;
}
</style>

View File

@ -1,10 +1,12 @@
// this is an loading animation for videos
<template>
<div>
<v-skeleton-loader
v-for="i in 10"
:key="i"
type="image, list-item-avatar-two-line"
/>
<v-sheet color="background" v-for="i in 10" :key="i">
<v-skeleton-loader type="image, list-item-avatar-two-line" />
</v-sheet>
</div>
</template>
<script>
export default {};
</script>

View File

@ -1,5 +1,5 @@
<template>
<v-app v-show="stateLoaded" style="background: black !important">
<v-app style="background: transparent !important">
<topNavigation
:search="search"
:page="page"
@ -9,16 +9,11 @@
@scroll-to-top="$refs.pgscroll.scrollTop = 0"
/>
<div class="accent" style="height: 100%; margin-top: 4rem">
<div style="height: 100%; margin-top: 4rem">
<div
v-show="!search"
class="background"
style="
overflow: hidden;
height: calc(100vh - 8rem);
transition-duration: 0.3s;
transition-property: border-radius;
"
class="scrollcontainer"
style="overflow: hidden; height: calc(100vh - 8rem)"
:style="{
borderRadius: `${roundTweak / 2}rem`,
}"
@ -26,20 +21,14 @@
<!-- element above removes artifacting from things like v-ripple by -->
<!-- scrollbox below must be a standalone div -->
<div ref="pgscroll" class="scroll-y" style="height: 100%">
<nuxt v-show="!search" />
<nuxt />
</div>
</div>
<div
v-show="search"
class="accent"
style="
padding: 0;
overflow: hidden;
height: calc(100vh - 4rem);
transition-duration: 0.3s;
transition-property: border-radius;
"
class="scrollcontainer"
style="overflow: hidden; height: calc(100vh - 4rem)"
>
<div class="scroll-y" style="height: 100%">
<div v-if="search" style="min-width: 180px">
@ -52,7 +41,7 @@
text
tile
dense
class="info--text searchButton text-left text-capitalize"
class="searchButton text-left text-capitalize"
@click="youtubeSearch(item)"
>
<v-icon class="mr-5">mdi-magnify</v-icon>
@ -78,7 +67,6 @@ export default {
data: () => ({
search: false,
response: [],
stateLoaded: false,
}),
computed: {
@ -104,13 +92,7 @@ export default {
},
},
beforeCreate() {
// initializes UI tweaks to the saved state
this.$store.commit("tweaks/initTweaks");
},
mounted() {
this.stateLoaded = true;
//--- Back Button Listener ---//
CapacitorApp.addListener("backButton", ({ canGoBack }) => {
//--- Back Closes Search ---//
@ -179,13 +161,21 @@ export default {
opacity: 0 !important;
}
.scrollcontainer {
overflow: hidden;
/* ios notch & gesture nav */
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left) !important;
}
.scroll-y {
overflow-y: scroll !important; /* has to be scroll, not auto */
overflow-x: hidden !important;
-webkit-overflow-scrolling: touch !important;
}
html,
body {
background: black;
background: var(--v-background-base);
overflow: hidden;
}

View File

@ -1,5 +1,5 @@
<template>
<v-app>
<v-app style="background: transparent !important">
<nuxt />
</v-app>
</template>

View File

@ -2,7 +2,12 @@
<v-app>
<center>
<v-icon size="100">mdi-alert-circle</v-icon>
<h1 class="grey--text">An error occured!</h1>
<h1
class="background--text"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
>
An error occured!
</h1>
<v-btn to="/">Reload Application</v-btn>
<v-btn to="/logs">Show Logs</v-btn>

View File

@ -1,4 +1,3 @@
import colors from "vuetify/es5/util/colors";
/**** Front's Notes / Don't Remove ****
* Data Storage:
* localStorage.setItem("key", data)
@ -36,7 +35,11 @@ export default {
},
meta: [
{ charset: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{
name: "viewport",
content:
"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover",
},
{ name: "format-detection", content: "telephone=no" },
],
},
@ -51,26 +54,18 @@ export default {
customVariables: ["~/assets/variables.scss"],
treeShake: true,
theme: {
dark: false,
options: { customProperties: true },
dark: true,
options: {
customProperties: true,
},
themes: {
light: {
primary: {
base: colors.red.lighten2,
lighten2: colors.red.lighten4,
},
background: "#fff",
accent: "#fff",
info: "#000",
primary: "#E57373",
background: "#ffffff",
},
dark: {
primary: {
base: colors.red.darken2,
lighten2: "#533",
},
background: "#333",
accent: "#222",
info: "#fff",
primary: "#B71C1C",
background: "#000000",
},
},
},

View File

@ -2,11 +2,14 @@
<center class="container">
<v-img
src="/icon.svg"
width="10em"
style="margin-bottom: 1em"
width="10rem"
height="10rem"
class="intro"
:class="$vuetify.theme.dark ? '' : 'invert'"
/>
<v-progress-circular size="50" indeterminate color="primary" />
<div style="height: 5rem" />
<v-progress-linear rounded height="8" indeterminate color="primary" />
<div class="pt-2">{{ progressMsg }}...</div>
</center>
</template>
@ -14,46 +17,38 @@
export default {
layout: "empty",
//--- Hide Splash Screen ---//
async beforeCreate() {
const { SplashScreen } = await require("@capacitor/splash-screen"); // This has to be imported here, otherwise NUXT won't import the package because its so early in the lifecycle -Front
await SplashScreen.hide();
},
//--- End Hide Splash Screen ---//
data: () => ({
progressMsg: "Fetching the API",
}),
async mounted() {
//--- Theme Loader Moved From '~/layouts/default.vue' (because this only needs to be run once) -Front ---//
setTimeout(() => {
//Set timeout is required to make it load properly... dont ask me why -Front
const darkTheme = localStorage.getItem("darkTheme");
if (darkTheme == "true") {
this.$vuetify.theme.dark = darkTheme;
//this.$vuetube.statusBar.setDark(); //Not needed unless setLight() is used below -Front
this.$vuetube.statusBar.setBackground(
this.$vuetify.theme.themes.dark.accent
this.$store.commit("tweaks/initTweaks");
const theming = new Promise((resolve) =>
// Set timeout is required for $vuetify.theme... dont ask me why -Front
setTimeout(() => {
this.$vuetify.theme.dark = JSON.parse(localStorage.getItem("darkTheme")) === true;
if (localStorage.getItem("primaryDark") != null)
this.$vuetify.theme.themes.dark.primary = localStorage.getItem("primaryDark");
if (localStorage.getItem("primaryLight") != null)
this.$vuetify.theme.themes.light.primary = localStorage.getItem("primaryLight");
if (localStorage.getItem("backgroundDark") != null)
this.$vuetify.theme.themes.dark.background = localStorage.getItem("backgroundDark");
if (localStorage.getItem("backgroundLight") != null)
this.$vuetify.theme.themes.light.background = localStorage.getItem("backgroundLight");
this.$vuetube.navigationBar.setTheme(
this.$vuetify.theme.currentTheme.background,
!this.$vuetify.theme.dark
);
const isOled = localStorage.getItem("isOled");
if (isOled == "true") {
(this.$vuetify.theme.themes.dark.accent = "#000"),
(this.$vuetify.theme.themes.dark.accent = "#000"),
(this.$vuetify.theme.themes.dark.background = "#000");
} else {
(this.$vuetify.theme.themes.dark.accent = "#222"),
(this.$vuetify.theme.themes.dark.accent = "#222"),
(this.$vuetify.theme.themes.dark.background = "#333");
}
} else {
//this.$vuetube.statusBar.setLight() //Looks weird -Front
this.$vuetube.statusBar.setBackground(
this.$vuetify.theme.themes.light.accent
this.$vuetube.statusBar.setTheme(
this.$vuetify.theme.currentTheme.background,
this.$vuetify.theme.dark
);
}
}, 0);
//-----------------------------------------------------------------------------------------------------------//
resolve();
}, 0)
);
await theming;
await this.$youtube.getAPI();
this.progressMsg = "Navigating Home";
this.$router.push(`/${localStorage.getItem("startPage") || "home"}`);
},
};
@ -61,12 +56,46 @@ export default {
<style scoped>
.container {
padding-top: 3em;
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -80%);
transform: translate(-50%, -50%);
}
.intro {
opacity: 0;
transform: scale(0.5);
transition-property: opacity, transform;
animation: bounce 0.66s ease infinite alternate;
}
/* triangles aren't very good at spinning :c */
@keyframes bounce {
0% {
opacity: 0;
transform: scale(0.5);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@keyframes fadein {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* reduced-motion animations */
@media (prefers-reduced-motion) {
.intro {
opacity: 0;
transform: scale(1);
transition-property: opacity, transform;
animation: fadein 0.5s ease 1 forwards;
}
}
</style>

View File

@ -1,11 +1,25 @@
<template>
<center>
<center class="px-4">
<v-img
contain
style="margin-top: 5em; max-width: 80%; max-height: 15em"
src="/dev.svg"
/>
<h1 class="grey--text">Page Under Construction</h1>
<p class="grey--text">Please read the VueTube FAQ for more information.</p>
<h2
class="background--text mt-4"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
>
Page Under Construction
</h2>
<p
class="background--text"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
>
Please read the VueTube FAQ for more information.
</p>
</center>
</template>
<script>
export default {};
</script>

View File

@ -0,0 +1,104 @@
<template>
<div>
<!-- Top Notice -->
<center style="margin: 2em;">
<h1>VueTube Registry</h1>
<v-alert text outlined type="warning">
ONLY TOUCH THIS IF YOU KNOW WHAT YOU ARE DOING!<br>
MESSING WITH SETTINGS MAY CAUSE YOUR APP TO BREAK!
</v-alert>
</center>
<!-- Registry List Loader -->
<v-list-item v-for="(item, index) in keys" :key="index">
<v-card class="card rounded-lg" :class="$vuetify.theme.dark ? 'background lighten-1' : 'background darken-1'">
<v-card-title v-text="item.key" />
<v-card-text v-text="item.value" />
<v-card-actions>
<v-spacer />
<v-btn text class="actionButton" disabled><v-icon color="primary">mdi-pencil</v-icon></v-btn>
<v-btn text class="actionButton" @click="confirmDelete(item)"><v-icon color="error">mdi-delete</v-icon></v-btn>
</v-card-actions>
</v-card>
</v-list-item>
<!-- Delete Entry Dialog -->
<v-dialog v-model="deleteDialog" width="500">
<v-card :class="$vuetify.theme.dark ? 'background lighten-1' : 'background darken-1'">
<v-card-title class="text-h5">Confirm Delete</v-card-title>
<v-card-text>Are you sure that you want to delete <span class="highlight" v-text="selectedKey" />?</v-card-text>
<v-alert text outlined type="warning" style="margin: 0 2em 2em; 2em;">Deleting random keys may cause the app to break!</v-alert>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" text @click="deleteDialog = false">No</v-btn>
<v-btn color="primary" text @click="deleteKey()">Yes</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
export default {
data() {
return {
keys: [],
selectedKey: null,
deleteDialog: false
};
},
mounted() {
this.syncRegistry();
},
methods: {
syncRegistry() {
this.keys = [];
const localStorageKeys = Object.keys(localStorage)
for (const i in localStorageKeys) {
const key = localStorageKeys[i];
const keyValue = localStorage.getItem(key);
this.keys.push({key: key, value: keyValue});
}
},
confirmDelete(item) {
this.selectedKey = item.key;
this.deleteDialog = true;
},
deleteKey() {
this.deleteDialog = false;
localStorage.removeItem(this.selectedKey);
this.syncRegistry();
}
}
};
</script>
<style scoped>
.card {
margin: 1em;
width: 100%;
}
.actionButton {
min-width: 1em !important;
}
.highlight {
background: #999;
border-radius: 5px;
padding: 0.25em;
}
</style>

View File

@ -1,20 +1,28 @@
<template>
<div>
<v-list-item v-for="(item, index) in logs" :key="index">
<v-card class="card">
<v-card
class="card background"
:class="$vuetify.theme.dark ? 'lighten-1' : 'darken-1'"
flat
>
<v-card-title>
<v-chip v-if="item.error" outlined class="errorChip" color="error"
>Error</v-chip
>
{{ item.name }}
<span
class="date"
class="date background--text"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
v-text="`• ${new Date(item.time).toLocaleString()}`"
/>
</v-card-title>
<v-expansion-panels>
<v-expansion-panel>
<v-expansion-panel
class="background"
:class="$vuetify.theme.dark ? 'lighten-1' : 'darken-1'"
>
<v-expansion-panel-header>More</v-expansion-panel-header>
<v-expansion-panel-content class="logContent" v-text="item.data" />
</v-expansion-panel>
@ -33,7 +41,6 @@
margin: 0.4em;
font-size: 0.75em;
transform: translateY(5%);
color: #999;
}
.errorChip {
margin-right: 0.5em;

View File

@ -1,10 +1,15 @@
<template>
<div class="mainContainer pt-1">
<v-card class="pb-5">
<v-card
flat
class="pb-5 background"
:class="$vuetify.theme.dark ? 'lighten-1' : 'darken-1'"
>
<v-card-title>Default Page</v-card-title>
<v-card-text>
<v-select
v-model="page"
background-color="background"
:items="pages"
label="Default Page"
solo

View File

@ -1,122 +1,224 @@
<template>
<div class="py-1">
<v-card class="pb-5">
<v-card-title>Global Base Color</v-card-title>
<v-row class="ml-3 mr-6">
<section class="row">
<v-switch
v-model="$vuetify.theme.dark"
label="Dark Theme"
hint="Bravo Six, Going Dark."
persistent-hint
inset
@click="saveTheme($vuetify.theme.dark)"
/>
</section>
<v-btn
v-if="$vuetify.theme.dark"
text
tile
class="white--text black"
@click="amoled"
<client-only>
<div class="d-flex flex-column justify-end" style="min-height: 100%">
<!-- ----------------------------------------------Background Colors------------------------ -->
<v-radio-group v-model="$vuetify.theme.currentTheme.background">
<div
class="d-flex flex-row px-6 no-wrap"
style="max-width: 100%; overflow-x: auto"
>
{{
$vuetify.theme.themes.dark.background === "#000" ? "LCD" : "OLED"
}}
<v-icon
:size="
$vuetify.theme.themes.dark.background === '#000'
? '.5rem'
: '.9rem'
"
class="ml-2"
>mdi-brightness-2</v-icon
<div
v-for="background in $vuetify.theme.dark
? backgroundsDark
: backgroundsLight"
:key="background.color"
class="text-center"
>
</v-btn>
</v-row>
</v-card>
<v-card class="pb-5">
<v-card-title>Accent Color</v-card-title>
<v-card-text>
<v-alert color="primary" dense outlined type="warning"
>NOTE: This doesn't save after closing the app (yet)</v-alert
<v-radio
color="primary"
active-class="px-6 border-primary"
style="transition-duration: 0.3s"
:style="{
background: background.color,
border: '2px solid ' + background.color,
}"
class="py-4 px-4 ma-2 rounded-lg"
:value="background.color"
/>
{{ background.name }}
</div>
<div class="text-center">
<v-radio
color="primary"
active-class="px-6 border-primary primary"
style="transition-duration: 0.3s"
:style="{
background: $vuetify.theme.dark
? 'var(--v-primary-darken4) !important'
: 'var(--v-primary-lighten4) !important',
border: $vuetify.theme.dark
? '2px solid var(--v-primary-darken4)'
: '2px solid var(--v-primary-lighten4)',
}"
class="py-4 px-4 ma-2 rounded-lg"
:value="
$vuetify.theme.dark ? experimentalDark : experimentalLight
"
/>
Adaptive
</div>
</div>
</v-radio-group>
<!-- ----------------------------------------------Primary Colors------------------------ -->
<v-radio-group v-model="$vuetify.theme.currentTheme.primary" class="mx-2">
<div
class="d-flex flex-row px-6 py-2 no-wrap align-center"
style="max-width: 100%; overflow-x: auto; margin-top: -1.5rem"
>
<v-color-picker
v-model="accentColor"
dot-size="5"
hide-mode-switch
mode="hexa"
<v-radio
v-for="color in $vuetify.theme.dark ? primaryDark : primaryLight"
:key="color"
color="background"
on-icon="mdi-check"
:light="$vuetify.theme.dark"
:dark="!$vuetify.theme.dark"
active-class="border-primary"
style="transition-duration: 0.3s"
:style="{
background: color,
border: '2px solid ' + color,
}"
class="mr-2 my-auto rounded-xl"
:value="color"
/>
<v-dialog
v-model="dialog"
width="300"
content-class="background rounded-lg"
>
<template #activator="{ on, attrs }">
<v-btn
icon
class="background"
style="height: 1.75rem; width: 1.75rem"
:class="$vuetify.theme.dark ? 'lighten-2' : 'darken-2'"
v-bind="attrs"
v-on="on"
>
<v-icon>mdi-plus</v-icon>
</v-btn>
</template>
<v-color-picker
v-model="$vuetify.theme.currentTheme.primary"
style="min-width: 100%"
class="background"
hide-mode-switch
dot-size="50"
mode="hexa"
flat
/>
</v-dialog>
</div>
</v-radio-group>
<!-- ----------------------------------------------Mode Switch------------------------ -->
<v-card
flat
class="d-flex flex-row justify-between mx-8 mb-4 px-4 background rounded-lg"
:class="$vuetify.theme.dark ? 'lighten-1' : 'darken-1'"
@click="
($vuetify.theme.dark = !$vuetify.theme.dark),
$vuetube.haptics.hapticsImpactLight(1)
"
>
<div class="my-auto">
<div>Dark Mode</div>
<div
class="background--text"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
style="font-size: 0.75rem; margin-top: -0.25rem !important"
>
Bravo Six, Going Dark.
</div>
</div>
<v-spacer />
<v-switch
v-model="$vuetify.theme.dark"
style="pointer-events: none"
persistent-hint
inset
/>
</v-card-text>
</v-card>
</div>
</v-card>
</div>
</client-only>
</template>
<script>
export default {
data() {
return {
accentColor: "#ffffff",
primaryLight: ["#E57373", "#8b5f37", "#016a49", "#34495E"],
primaryDark: [
"#B71C1C",
"#FFBBFF",
"#AAAFFF",
"#AAFFFF",
"#7CD6AF",
"#FEC89B",
],
backgroundsDark: [
{ name: "Dark", color: "#181818" },
{ name: "Black", color: "#000000" },
],
backgroundsLight: [{ name: "Normal", color: "#ffffff" }],
experimentalLight: "",
experimentalDark: "",
dialog: false,
};
},
watch: {
accentColor: function (val) {
this.$vuetify.theme.currentTheme.primary.base = val;
let primaryAlt = this.$vuetube.hexToRgb(val);
let rgbEdit = 130; //Light Mode
if (localStorage.getItem("darkTheme") === "true") rgbEdit = -80; //Dark Mode
for (const i in primaryAlt) {
primaryAlt[i] = primaryAlt[i] + rgbEdit; //Amount To Lighten By
if (primaryAlt[i] > 255) primaryAlt[i] = 255;
if (primaryAlt[i] < 0) primaryAlt[i] = 0;
// also triggers background and primary watcher, unless primary colors match
"$vuetify.theme.dark"(value) {
localStorage.setItem("darkTheme", value);
},
"$vuetify.theme.currentTheme.background"(value) {
this.$vuetify.theme.dark
? localStorage.setItem("backgroundDark", value)
: localStorage.setItem("backgroundLight", value);
this.$vuetube.statusBar.setTheme(value, this.$vuetify.theme.dark);
this.$vuetube.navigationBar.setTheme(value, !this.$vuetify.theme.dark);
},
"$vuetify.theme.currentTheme.primary"(value) {
if (value != undefined) {
this.$vuetify.theme.dark
? localStorage.setItem("primaryDark", value)
: localStorage.setItem("primaryLight", value);
let tempD = this.experimentalDark;
let tempL = this.experimentalLight;
this.adapt();
if (this.$vuetify.theme.currentTheme.background === tempD)
this.$vuetify.theme.currentTheme.background = this.experimentalDark;
if (this.$vuetify.theme.currentTheme.background === tempL)
this.$vuetify.theme.currentTheme.background = this.experimentalLight;
}
primaryAlt = this.$vuetube.rgbToHex(
primaryAlt.r,
primaryAlt.g,
primaryAlt.b
);
this.$vuetify.theme.currentTheme.primary.lighten2 = primaryAlt;
},
},
mounted() {
this.accentColor = this.$vuetify.theme.themes.dark.primary.base;
beforeMount() {
this.adapt();
},
methods: {
amoled() {
this.$vuetify.theme.themes.dark.background === "#000"
? ((this.$vuetify.theme.themes.dark.accent = "#222"),
(this.$vuetify.theme.themes.dark.accent = "#222"),
(this.$vuetify.theme.themes.dark.background = "#333"),
localStorage.setItem("isOled", false))
: ((this.$vuetify.theme.themes.dark.accent = "#000"),
(this.$vuetify.theme.themes.dark.accent = "#000"),
(this.$vuetify.theme.themes.dark.background = "#000"),
localStorage.setItem("isOled", true));
},
saveTheme(isDark) {
this.$vuetube.statusBar.setBackground(
this.$vuetify.theme.currentTheme.accent
adapt() {
let hexD = getComputedStyle(document.documentElement).getPropertyValue(
"--v-primary-darken4"
);
localStorage.setItem("darkTheme", isDark);
let hexL = getComputedStyle(document.documentElement).getPropertyValue(
"--v-primary-lighten4"
);
// the menace above returns a hex string with A SPACE " " in front of it, that's why substring(1)
// the SPACE " " is stored as part of the CSS variable itself to be used for chaining
this.experimentalDark = hexD.substring(1).toUpperCase();
this.experimentalLight = hexL.substring(1).toUpperCase();
setTimeout(() => {
if (
this.$vuetify.theme.currentTheme.background ==
hexD.substring(1).toUpperCase()
)
this.$vuetify.theme.currentTheme.background = this.experimentalDark;
if (
this.$vuetify.theme.currentTheme.background ==
hexL.substring(1).toUpperCase()
)
this.$vuetify.theme.currentTheme.background = this.experimentalLight;
}, 0);
},
},
};
</script>
<style scoped>
.v-card {
margin: 1em;
<style>
.border-primary {
border: 2px solid var(--v-primary-base) !important;
}
section {
padding: 0 1em 1em 1em;
.v-input--selection-controls__input {
margin-right: 0 !important;
}
</style>

View File

@ -1,33 +1,37 @@
<template>
<div class="py-1">
<v-card class="px-8 py-6 ma-4">
<h3>Layout</h3>
<v-switch class="mt-6" disabled label="Dense Navbars" />
<v-switch disabled label="Disable Top Bar" />
<!-- <v-switch class="mt-6" disabled label="Reverse (disabled)" /> -->
</v-card>
<v-card class="px-8 pt-6 ma-4">
<h3>Rounded Corners</h3>
<v-switch class="mt-6" disabled label="Reverse (disabled)" />
<v-slider
disabled
class="mr-2"
label="Outer (disabled)"
:max="4"
step="1"
thumb-size="64"
></v-slider>
<div class="d-flex flex-column justify-end" style="min-height: 100%">
<v-card
flat
class="px-6 ma-4 mt-2 background"
style="transition-duration: 0.3s; transition-property: border-radius"
:class="$vuetify.theme.dark ? 'lighten-1' : 'darken-1'"
:style="{
borderRadius: `${roundTweak / 2}rem`,
}"
>
<h3 class="mt-5">Rounded Corners</h3>
<div
class="background--text"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
>
applies to only a few elements for now
</div>
<!-- TODO: outer radius -->
<!-- TODO: Dense Navbar -->
<!-- TODO: Disable Top Bar -->
<!-- TODO: Top and Bottom bar color selection -->
<v-slider
v-model="roundTweak"
class="mr-2"
class="mr-2 mt-5"
label="Inner"
:max="4"
step="1"
thumb-size="64"
@input="$vuetube.haptics.hapticsImpactLight(0)"
>
<template #thumb-label="{ value }">
<div
class="pa-4 white text-red red-text red--text"
class="pa-4 background text-red red-text red--text"
:style="{ borderRadius: value * 3 + 'px !important' }"
></div>
</template>

View File

@ -1,26 +1,51 @@
<template>
<div class="py-2">
<v-list-item v-for="(item, index) in commits" :key="index" class="my-1">
<v-card class="card my-2">
<v-card
flat
class="card my-2 background"
:class="$vuetify.theme.dark ? 'lighten-1' : 'darken-1'"
>
<v-card-title style="padding: 0 0.25em 0 0.75em">
{{ item.author ? item.author.login : item.commit.author.name }}
<span class="subtitle" v-text="` ${item.sha.substring(0, 7)}`" />
<span
class="subtitle background--text"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
v-text="`• ${item.sha.substring(0, 7)}`"
/>
<v-spacer />
<v-chip v-if="index == 0" outlined class="tags" color="orange"
>Latest</v-chip
<v-chip
v-if="index == 0"
class="tags"
color="orange"
style="
border-radius: 0.5rem;
border: 2px var(--v-oragnge-base);
margin-top: -1.5rem;
margin-right: -0.5rem;
"
>
Latest
</v-chip>
<v-chip
v-if="item.sha == installedVersion"
outlined
class="tags"
color="green"
style="
border-radius: 0.5rem;
border: 2px var(--v-green-base);
margin-top: -1.5rem;
margin-right: -0.5rem;
"
>
>Installed</v-chip
>
</v-card-title>
<div style="margin-left: 1em">
<div
class="date"
class="date background--text"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
v-text="new Date(item.commit.committer.date).toLocaleString()"
/>
{{ item.commit.message }}
@ -28,12 +53,12 @@
<v-card-actions>
<v-spacer />
<v-btn @click="openExternal(item)"
><v-icon class="btn-icon">mdi-github</v-icon>View</v-btn
>
<v-btn disabled @click="install(item)"
><v-icon class="btn-icon">mdi-download</v-icon>Install</v-btn
>
<v-btn @click="openExternal(item)" class="background">
<v-icon class="btn-icon">mdi-github</v-icon>View
</v-btn>
<v-btn disabled @click="install(item)">
<v-icon class="btn-icon">mdi-download</v-icon>Install
</v-btn>
</v-card-actions>
</v-card>
</v-list-item>
@ -48,10 +73,8 @@
margin: 0.4em;
font-size: 0.75em;
transform: translateY(5%);
color: #999;
}
.date {
color: #999;
transform: translateY(-40%);
}
.btn-icon {

View File

@ -1,5 +1,5 @@
<template>
<div class="accent">
<div class="background">
<!-- Video Loading Animation -->
<vid-load-renderer v-if="renderer.length <= 0" />
<sectionListRenderer :render="renderer" />

View File

@ -53,6 +53,8 @@ export default {
},
{ name: "Logs", icon: "mdi-text-box-outline", to: "/mods/logs" },
{ name: "About", icon: "mdi-information-outline", to: "/mods/about" },
/* Developer Settings, Don't Remove // Included in all releases for users to mess with if they feel comfortable enough */ { name: "", icon: "", to: "/mods/developer" },
],
};
},

View File

@ -1,11 +1,25 @@
<template>
<center>
<center class="px-4">
<v-img
contain
style="margin-top: 5em; max-width: 80%; max-height: 15em"
src="/dev.svg"
/>
<h1 class="grey--text">Page Under Construction</h1>
<p class="grey--text">Please read the VueTube FAQ for more information.</p>
<h2
class="background--text mt-4"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
>
Page Under Construction
</h2>
<p
class="background--text"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
>
Please read the VueTube FAQ for more information.
</p>
</center>
</template>
<script>
export default {};
</script>

View File

@ -1,15 +1,15 @@
<template>
<div class="accent">
<div class="background">
<!-- Stock Player -->
<videoPlayer :vid-src="vidSrc" />
<videoPlayer
style="position: sticky; top: 0; z-index: 696969"
:vid-src="vidSrc"
/>
<!-- VueTube Player V1 -->
<!-- <VTPlayerV1 :sources="sources" v-if="sources.length > 0" />-->
<v-card v-if="loaded" class="ml-2 mr-2 accent" flat>
<v-card v-if="loaded" class="ml-2 mr-2 background" flat>
<v-card-title
class="mt-2"
style="
@ -65,7 +65,7 @@
<!-- <v-bottom-sheet
v-model="showMore"
color="accent"
color="background"
style="z-index: 9999999"
>
<v-sheet style="padding: 1em">
@ -78,7 +78,7 @@
</div>
</v-sheet>
</v-bottom-sheet> -->
<!-- <v-bottom-sheet v-model="share" color="accent" style="z-index: 9999999">
<!-- <v-bottom-sheet v-model="share" color="background" style="z-index: 9999999">
<v-sheet style="padding: 1em">
<div class="scroll-y">
{{ description }}
@ -95,7 +95,7 @@
import { Share } from "@capacitor/share";
import ShelfRenderer from "~/components/SectionRenderers/shelfRenderer.vue";
import VidLoadRenderer from "~/components/vidLoadRenderer.vue";
import SlimVideoDescriptionRenderer from '~/components/UtilRenderers/slimVideoDescriptionRenderer.vue';
import SlimVideoDescriptionRenderer from "~/components/UtilRenderers/slimVideoDescriptionRenderer.vue";
export default {
components: { ShelfRenderer, VidLoadRenderer, SlimVideoDescriptionRenderer },

View File

@ -4,6 +4,7 @@ import { StatusBar, Style } from "@capacitor/status-bar";
import { NavigationBar } from "@hugotomazi/capacitor-navigation-bar";
import constants from "./constants";
import { hexToRgb, rgbToHex } from "./utils";
import { Haptics, ImpactStyle } from "@capacitor/haptics";
const module = {
//--- Get GitHub Commits ---//
@ -37,6 +38,21 @@ const module = {
});
},
haptics: {
async hapticsImpactHeavy(x) {
await Haptics.impact({ style: ImpactStyle.Heavy, duration: x });
},
async hapticsImpactMedium(x) {
await Haptics.impact({ style: ImpactStyle.Medium, duration: x });
},
async hapticsImpactLight(x) {
await Haptics.impact({ style: ImpactStyle.Light, duration: x });
},
async hapticsVibrate(x) {
await Haptics.vibrate(x);
},
},
statusBar: {
async hide() {
return await StatusBar.hide();
@ -54,7 +70,13 @@ const module = {
return StatusBar.setOverlaysWebView({ overlay: true });
},
async setBackground(color) {
return await StatusBar.setBackgroundColor({ color: color });
return await StatusBar.setBackgroundColor({ color });
},
async setTheme(color, dark) {
dark
? StatusBar.setStyle({ style: Style.Dark })
: StatusBar.setStyle({ style: Style.Light });
StatusBar.setBackgroundColor({ color });
},
},
@ -65,6 +87,12 @@ const module = {
async show() {
return await NavigationBar.show();
},
async setTheme(color, darkButtons) {
return await NavigationBar.setColor({ color, darkButtons });
},
async setTransparent() {
return NavigationBar.setTransparency({ isTransparent: true });
},
},
hexToRgb(hex) {

View File

@ -7,11 +7,11 @@
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_5_API_31.avd" />
<value value="$USER_HOME$/.android/avd/Pixel_3a_API_31_arm64-v8a.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2022-03-23T18:18:11.698053Z" />
<timeTargetWasSelectedWithDropDown value="2022-03-31T22:44:20.197073Z" />
</component>
</project>

View File

@ -13,6 +13,7 @@ dependencies {
implementation project(':capacitor-app')
implementation project(':capacitor-browser')
implementation project(':capacitor-device')
implementation project(':capacitor-haptics')
implementation project(':capacitor-share')
implementation project(':capacitor-splash-screen')
implementation project(':capacitor-status-bar')

View File

@ -7,19 +7,20 @@
"hostname": "youtube.com",
"androidScheme": "https"
},
"android": {
"backgroundColor": "#000000"
},
"ios": {
"backgroundColor": "#000000"
},
"plugins": {
"SplashScreen": {
"launchShowDuration": 0,
"launchAutoHide": true,
"backgroundColor": "#111111",
"androidSplashResourceName": "splash",
"androidScaleType": "CENTER_CROP",
"androidSpinnerStyle": "large",
"iosSpinnerStyle": "small",
"spinnerColor": "#999999",
"showSpinner": false,
"backgroundColor": "#000000",
"splashFullScreen": false,
"splashImmersive": false
"splashImmersive": false,
"launchAutoHide": true,
"showSpinner": false
}
}
}

View File

@ -15,6 +15,10 @@
"pkg": "@capacitor/device",
"classpath": "com.capacitorjs.plugins.device.DevicePlugin"
},
{
"pkg": "@capacitor/haptics",
"classpath": "com.capacitorjs.plugins.haptics.HapticsPlugin"
},
{
"pkg": "@capacitor/share",
"classpath": "com.capacitorjs.plugins.share.SharePlugin"

View File

@ -14,6 +14,9 @@ project(':capacitor-browser').projectDir = new File('../node_modules/@capacitor/
include ':capacitor-device'
project(':capacitor-device').projectDir = new File('../node_modules/@capacitor/device/android')
include ':capacitor-haptics'
project(':capacitor-haptics').projectDir = new File('../node_modules/@capacitor/haptics/android')
include ':capacitor-share'
project(':capacitor-share').projectDir = new File('../node_modules/@capacitor/share/android')

View File

@ -9,20 +9,21 @@
"androidScheme": "https"
},
"android": {
"backgroundColor": "#000000"
},
"ios": {
"backgroundColor": "#000000"
},
"plugins": {
"SplashScreen": {
"launchShowDuration": 0,
"launchAutoHide": true,
"backgroundColor": "#111111",
"androidSplashResourceName": "splash",
"androidScaleType": "CENTER_CROP",
"androidSpinnerStyle": "large",
"iosSpinnerStyle": "small",
"spinnerColor": "#999999",
"showSpinner": false,
"backgroundColor": "#000000",
"splashFullScreen": false,
"splashImmersive": false
"splashImmersive": false,
"launchAutoHide": true,
"showSpinner": false
}
}
}

View File

@ -7,19 +7,20 @@
"hostname": "youtube.com",
"androidScheme": "https"
},
"android": {
"backgroundColor": "#000000"
},
"ios": {
"backgroundColor": "#000000"
},
"plugins": {
"SplashScreen": {
"launchShowDuration": 0,
"launchAutoHide": true,
"backgroundColor": "#111111",
"androidSplashResourceName": "splash",
"androidScaleType": "CENTER_CROP",
"androidSpinnerStyle": "large",
"iosSpinnerStyle": "small",
"spinnerColor": "#999999",
"showSpinner": false,
"backgroundColor": "#000000",
"splashFullScreen": false,
"splashImmersive": false
"splashImmersive": false,
"launchAutoHide": true,
"showSpinner": false
}
}
}

View File

@ -9,14 +9,15 @@ install! 'cocoapods', :disable_input_output_paths => true
def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCommunityHttp', :path => '..\..\node_modules\@capacitor-community\http'
pod 'CapacitorApp', :path => '..\..\node_modules\@capacitor\app'
pod 'CapacitorBrowser', :path => '..\..\node_modules\@capacitor\browser'
pod 'CapacitorDevice', :path => '..\..\node_modules\@capacitor\device'
pod 'CapacitorShare', :path => '..\..\node_modules\@capacitor\share'
pod 'CapacitorSplashScreen', :path => '..\..\node_modules\@capacitor\splash-screen'
pod 'CapacitorStatusBar', :path => '..\..\node_modules\@capacitor\status-bar'
pod 'HugotomaziCapacitorNavigationBar', :path => '..\..\node_modules\@hugotomazi\capacitor-navigation-bar'
pod 'CapacitorCommunityHttp', :path => '../../node_modules/@capacitor-community/http'
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
pod 'CapacitorBrowser', :path => '../../node_modules/@capacitor/browser'
pod 'CapacitorDevice', :path => '../../node_modules/@capacitor/device'
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'
pod 'CapacitorShare', :path => '../../node_modules/@capacitor/share'
pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen'
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
pod 'HugotomaziCapacitorNavigationBar', :path => '../../node_modules/@hugotomazi/capacitor-navigation-bar'
end
target 'App' do

View File

@ -7,6 +7,7 @@
"@capacitor/cli": "^3.4.0",
"@capacitor/core": "^3.4.0",
"@capacitor/device": "^1.1.2",
"@capacitor/haptics": "^1.1.4",
"@capacitor/share": "^1.1.2",
"@capacitor/splash-screen": "^1.2.2",
"@capacitor/status-bar": "^1.0.8",

View File

@ -38,11 +38,7 @@ Well this has been thrown around on the Return Youtube Dislike discord server fo
Also, YouTube Vanced just shut down
## Screenshots
<img src="https://github.com/Frontesque/VueTube/raw/main/Icons/screenshots/home.PNG" alt="VueTube Home" width="400"/>
<img src="https://github.com/Frontesque/VueTube/raw/main/Icons/screenshots/search.PNG" alt="VueTube Search" width="400"/>
<img src="https://github.com/Frontesque/VueTube/raw/main/Icons/screenshots/watch.PNG" alt="VueTube Watch" width="400"/>
[View on our website: https://vuetube.app/info/screenshots](https://vuetube.app/info/screenshots)
## Want to contribute?
Please read our website on how to do so: https://vuetube.app/contributing

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 131 KiB

View File

@ -9,7 +9,7 @@ function hot {
while true; do
b=`ls -lahR $* | grep -v 'node_modules'`
# to avoid confusing myself with nested-if - it is a "short form" of doing a=$b; eval $script if $a != $b.
[[ $a != $b ]] && a=$b && eval $script;
[[ $a != $b ]] && a=$b && eval time $script;
sleep .5;
done
fi