VueTube/NUXT/layouts/default.vue

349 lines
8.4 KiB
Vue
Raw Normal View History

2022-01-24 22:56:57 +00:00
<template>
2022-03-31 04:22:24 +00:00
<v-app style="background: transparent !important">
<topNavigation
2022-03-21 23:47:11 +00:00
:search="search"
:page="page"
2022-05-04 23:09:17 +00:00
style="z-index: 696969"
@search-btn="searchBtn"
@text-changed="textChanged"
2022-05-14 21:20:44 +00:00
@close-search="search = !search"
2022-03-24 04:55:38 +00:00
@scroll-to-top="$refs.pgscroll.scrollTop = 0"
/>
<!-- channel-tabs -->
2022-05-05 23:09:28 +00:00
<v-tabs
v-if="$route.path.includes('/channel') && !search"
2022-05-05 23:09:28 +00:00
mobile-breakpoint="0"
style="
position: fixed;
top: calc(4rem + env(safe-area-inset-top));
z-index: 696969;
"
background-color="background"
:color="$vuetify.theme.dark ? 'white' : 'black'"
>
<v-tab
v-for="tab in channelTabs"
:key="tab.name"
:to="tab.to"
2022-05-14 04:36:56 +00:00
exact
2022-05-05 23:09:28 +00:00
:v-ripple="false"
>
{{ tab.name }}
</v-tab>
</v-tabs>
<div
style="
height: 100%;
padding-bottom: calc(4rem + env(safe-area-inset-bottom));
"
2022-05-05 23:09:28 +00:00
:style="{
paddingTop:
$route.path.includes('/channel') && !search
? 'calc(7rem + env(safe-area-inset-top))'
: 'calc(4rem + env(safe-area-inset-top))',
2022-05-05 23:09:28 +00:00
}"
>
2022-05-04 23:09:17 +00:00
<div v-show="!search">
<!-- class="scrollcontainer" -->
<!-- style="overflow: hidden; height: calc(100vh - 8rem)" -->
<!-- element above removes artifacting from things like v-ripple by -->
2022-03-21 05:13:21 +00:00
<!-- scrollbox below must be a standalone div -->
2022-05-04 23:09:17 +00:00
<div ref="pgscroll" style="height: 100%">
<nuxt />
</div>
</div>
<div
v-show="search"
class="scrollcontainer"
style="overflow: hidden; height: calc(100vh - 4rem)"
>
<div class="scroll-y" style="height: 100%">
2022-03-21 23:47:11 +00:00
<div v-if="search" style="min-width: 180px">
2022-05-14 21:20:44 +00:00
<v-list-item v-for="item in response" :key="item[0]" class="px-0">
2022-03-21 05:13:21 +00:00
<v-btn
2022-05-14 21:20:44 +00:00
v-emoji
2022-03-21 05:13:21 +00:00
text
2022-03-22 01:13:48 +00:00
tile
2022-03-21 05:13:21 +00:00
dense
class="searchButton text-left text-none no-spacing"
2022-05-18 03:19:22 +00:00
@click="youtubeSearch(item)"
2022-03-22 01:13:48 +00:00
>
<v-icon class="mr-5">mdi-magnify</v-icon>
2022-05-14 21:20:44 +00:00
{{ item[0] }}
2022-03-22 01:13:48 +00:00
</v-btn>
2022-03-21 05:13:21 +00:00
</v-list-item>
</div>
2022-03-07 18:53:14 +00:00
</div>
</div>
2022-02-24 19:45:36 +00:00
</div>
2022-01-24 22:56:57 +00:00
2022-03-18 12:21:06 +00:00
<bottomNavigation v-if="!search" />
2022-01-24 22:56:57 +00:00
2022-03-13 20:16:00 +00:00
<updateChecker />
2022-01-24 22:56:57 +00:00
</v-app>
</template>
<script>
2022-03-21 05:13:21 +00:00
import { App as CapacitorApp } from "@capacitor/app";
import { mapState } from "vuex";
import constants from "~/plugins/constants";
2022-04-11 05:06:40 +00:00
import { linkParser } from "~/plugins/utils";
2022-05-03 11:07:40 +00:00
import backType from "~/plugins/classes/backType";
2022-03-07 18:53:14 +00:00
export default {
data: () => ({
search: false,
response: [],
2022-05-05 23:09:28 +00:00
channelTabs: [
{ name: "Home", to: "/channel" },
{ name: "Videos", to: "/channel/videos" },
{ name: "Playlists", to: "/channel/playlists" },
{ name: "Community", to: "/channel/community" },
{ name: "Channels", to: "/channel/channels" },
{ name: "About", to: "/channel/about" },
],
2022-03-07 18:53:14 +00:00
}),
computed: {
...mapState({
roundTweak: (state) => state.tweaks.roundTweak,
}),
page: function () {
const splitPath = this.$route.path.split("/");
let pageName = splitPath[splitPath.length - 1];
pageName = pageName.charAt(0).toUpperCase() + pageName.slice(1);
return pageName || "Home";
},
},
watch: {
// Watch for any changes in the route string
// When change is detected, scroll main div back to the top
$route() {
this.$refs.pgscroll.scrollTop = 0; // scroll back to top when moving to new route
// Exit fullscreen if currently in fullscreen
this.$vuetube.statusBar.show();
this.$vuetube.navigationBar.show();
2022-03-25 12:07:35 +00:00
},
},
2022-03-07 18:53:14 +00:00
mounted() {
2022-05-05 04:28:51 +00:00
if (!process.browser) this.$vuetube.resetBackActions();
// --- External URL Handling --- //
CapacitorApp.addListener("appUrlOpen", (event) => {
2022-04-12 05:26:33 +00:00
this.$logger("ExternalURL", event.url);
// We only push to the route if there is a url present
2022-06-19 07:13:49 +00:00
const result = linkParser(event.url);
2022-04-13 01:43:32 +00:00
if (result) this.$router.push(result.pathname + result.search);
});
// --- Import Twemoji ---///
const plugin = document.createElement("script");
plugin.setAttribute("src", "//twemoji.maxcdn.com/v/latest/twemoji.min.js");
plugin.setAttribute("crossorigin", "anonymous");
document.head.appendChild(plugin);
2022-03-07 18:53:14 +00:00
},
beforeDestroy() {
if (this.backHandler) this.backHandler.remove();
},
2022-03-07 18:53:14 +00:00
methods: {
textChanged(text) {
2022-04-11 05:06:40 +00:00
if (text.length <= 0) {
this.response = [];
return;
} // No text found, no point in calling API
const isLink = linkParser(text);
2022-06-02 01:42:43 +00:00
if (!isLink) {
//--- Auto Suggest ---//
this.$youtube.autoComplete(text, (res) => {
const data = res.replace(/^.*?\(/, "").replace(/\)$/, ""); //Format Response
this.response = JSON.parse(data)[1];
console.log(this.response);
});
} else {
//--- User Pastes Link, Direct Them To Video ---//
2022-04-11 05:06:40 +00:00
this.response = [
2022-06-02 01:42:43 +00:00
[
`Watch Video from ID: ${isLink.searchParams.get("v")}`,
{ id: isLink.searchParams.get("v") },
],
2022-04-11 05:06:40 +00:00
];
2022-06-02 01:42:43 +00:00
console.log("this.response: ", this.response);
return;
2022-06-02 01:42:43 +00:00
//--- End User Pastes Link, Direct Them To Video ---//
}
2022-03-07 18:53:14 +00:00
},
youtubeSearch(item) {
2022-05-18 03:19:22 +00:00
const link = item[1].id
? `/watch?v=${item[1].id}` // link pasted
: `/search?q=${item[0]}`; // regular suggestion
this.$router.push(link);
2022-03-16 00:37:33 +00:00
this.search = false;
2022-03-17 22:25:13 +00:00
},
searchBtn(text) {
const query = text;
2022-03-17 22:25:13 +00:00
2022-03-22 08:23:23 +00:00
this.$logger(
constants.LOGGER_NAMES.search,
"Query: " + query + " this.search: " + this.search
);
2022-03-17 22:25:13 +00:00
if (this.search === true) {
2022-03-21 05:13:21 +00:00
if (query) {
2022-03-19 19:39:07 +00:00
this.$router.push(`/search?q=${query}`);
this.search = false;
}
2022-03-17 22:25:13 +00:00
} else {
this.search = true;
2022-05-03 11:07:40 +00:00
// Adds to the back stack
const closeSearch = new backType(
() => {
this.search = false;
},
() => {
return this.search;
}
);
this.$vuetube.addBackAction(closeSearch);
2022-03-17 22:25:13 +00:00
}
2022-03-21 05:13:21 +00:00
},
},
};
2022-01-24 22:56:57 +00:00
</script>
<style>
* {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
2022-03-25 12:07:35 +00:00
*:focus::before {
opacity: 0 !important;
}
2022-05-05 23:09:28 +00:00
.v-slide-group__prev {
display: none !important;
}
.v-slide-group__next {
display: none !important;
}
.v-input--selection-controls__input {
margin-right: 0 !important;
}
2022-05-18 03:53:03 +00:00
.v-input__slot {
margin: 0 !important;
}
2022-05-21 02:01:39 +00:00
.v-slider {
margin: 0 !important;
}
2022-03-25 12:07:35 +00:00
2022-07-06 04:07:12 +00:00
.container-max-height {
min-height: calc(
100vh - 8rem - env(safe-area-inset-top) - env(safe-area-inset-bottom)
) !important;
}
.background-opaque {
background: linear-gradient(var(--v-background-base) -1000%, #00000000 1000%);
}
.border-primary {
border: 2px solid var(--v-primary-base) !important;
}
2022-05-04 23:09:17 +00:00
.glassy {
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}
2022-05-29 18:13:09 +00:00
.transparent-lighten-1 {
background: #ffffff22;
}
.transparent-darken-1 {
background: #00000022;
}
2022-05-21 02:01:39 +00:00
.debug {
outline: 1px solid red;
}
2022-05-04 23:09:17 +00:00
2022-05-07 04:54:08 +00:00
.v-card--reveal {
bottom: 0;
opacity: 1 !important;
position: absolute !important;
width: 100%;
}
.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 {
2022-04-15 03:14:52 +00:00
overflow-y: scroll !important;
/* has to be scroll, not auto */
2022-03-31 04:22:24 +00:00
overflow-x: hidden !important;
-webkit-overflow-scrolling: touch !important;
}
html,
body {
2022-03-31 04:22:24 +00:00
background: var(--v-background-base);
2022-05-18 21:51:33 +00:00
-webkit-overflow-scrolling: touch !important;
overflow-y: scroll !important;
overflow-x: hidden !important;
}
p,
span,
div {
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+/Edge */
user-select: none; /* Standard */
}
.invert {
filter: invert(100%);
}
2022-04-13 03:55:29 +00:00
.emoji {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: -0.1em;
margin: 0 2px;
2022-04-13 03:55:29 +00:00
}
2022-04-25 03:24:46 +00:00
.min-height-0 {
min-height: 0 !important;
}
.fill-width {
width: 100% !important;
}
2022-06-15 00:08:45 +00:00
.container {
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.no-spacing {
letter-spacing: 0px !important;
}
</style>
<style scoped>
.searchButton {
width: 100%;
justify-content: left !important;
}
</style>