Merge pull request #245 from 404-Program-not-found/main

Fixed issues relating to external URLs and cleaned up how the Watch page is reset
This commit is contained in:
Kenny 2022-04-13 08:56:27 -04:00 committed by GitHub
commit 62cdad816c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 299 additions and 76 deletions

141
.github/workflows/nightly-release.yml vendored Normal file
View File

@ -0,0 +1,141 @@
# This is a basic workflow to help you get started with Actions
name: nightly-release
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
schedule:
# Runs "at minute 55 past every hour" (see https://crontab.guru)
- cron: '0 0 * * *'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
NODE_VERSION: 16
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
name: Build web assets
runs-on: ubuntu-latest
needs: check_date
if: ${{ needs.check_date.outputs.should_run != 'false' }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install dependencies
run: npm i; cd NUXT; npm i
- name: Set App Version
working-directory: NUXT
run: sed -i 's/dev-local/${{ github.sha }}/' nuxt.config.js
- name: Build web assets
working-directory: NUXT
run: npm run generate
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: dist
path: dist
android:
name: Build Android platform
runs-on: ubuntu-latest
needs: [build]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Download artifacts
uses: actions/download-artifact@v2
with:
name: dist
path: dist
- name: Set up Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install dependencies
run: npm i
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Copy web assets to native platform
run: npx cap copy android
- name: Update native platform
run: npx cap update android
- name: Build with Gradle
working-directory: android
run: chmod +x gradlew; ./gradlew clean assembleRelease -x test -Pandroid.injected.signing.store.file=/home/runner/work/VueTube/VueTube/android/key.jks -Pandroid.injected.signing.store.password=${{ secrets.ANDROID_STORE_PASSWORD }} -Pandroid.injected.signing.key.alias=${{ secrets.ANDROID_KEY_ALIAS }} -Pandroid.injected.signing.key.password=${{ secrets.ANDROID_KEY_PASSWORD }}
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: android
path: android/app/build/outputs/apk/release/app-release.apk
ios:
name: Build iOS platform
runs-on: macos-latest
needs: [build]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Download artifacts
uses: actions/download-artifact@v2
with:
name: dist
path: dist
- name: Set up Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install dependencies
run: npm i
- name: Copy web assets to native platform
run: npx cap copy ios
- name: Update native platform
run: npx cap update ios
- name: Add empty `GoogleService-Info.plist`
run: echo "$GOOGLE_SERVICE_INFO_PLIST" > ios/App/App/GoogleService-Info.plist
env:
GOOGLE_SERVICE_INFO_PLIST: ${{secrets.GOOGLE_SERVICE_INFO_PLIST}}
- name: Build and archive with xcodebuild
working-directory: ios
run: xcodebuild
-workspace App/App.xcworkspace
-scheme App
-archivePath App/build/App.xarchive
clean build archive
CODE_SIGN_IDENTITY=""
CODE_SIGNING_REQUIRED=NO
CODE_SIGNING_ALLOWED="NO"
CODE_SIGN_ENTITLEMENTS=""
- name: Make IPA
run: mkdir Payload && mv ~/Library/Developer/Xcode/DerivedData/App-*/Build/Products/Debug-iphoneos/App.app Payload && zip -r Payload.zip Payload && mv Payload.zip VueTube.ipa
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: iOS
path: VueTube.ipa
check_date:
runs-on: ubuntu-latest
name: Check latest commit
outputs:
should_run: ${{ steps.should_run.outputs.should_run }}
steps:
- uses: actions/checkout@v2
- name: print latest_commit
run: echo ${{ github.sha }}
- id: should_run
continue-on-error: true
name: check latest commit is less than a day
if: ${{ github.event_name == 'schedule' }}
run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false"

View File

@ -19,7 +19,7 @@
"
/>
</a>
<v-card-text class="video-info pt-2">
<v-card-text class="video-info pt-2" v-emoji>
<div
v-for="title in video.title.runs"
:key="title.text"

View File

@ -42,7 +42,7 @@
:src="video.channelThumbnail.thumbnails[0].url"
/>
</a>
<v-card-text class="video-info pt-2">
<v-card-text class="video-info pt-2" v-emoji>
<div
v-for="title in video.title.runs"
:key="title.text"

View File

@ -0,0 +1,3 @@
<template>
<div class="swipeableBottomSheet" :open-state="state ? 1 : 0"></div>
</template>

View File

@ -44,7 +44,7 @@
:src="video.channelThumbnail.thumbnails[0].url"
/>
</a>
<v-card-text class="video-info pt-2">
<v-card-text class="video-info pt-2" v-emoji>
<div
v-for="title in video.title.runs"
:key="title.text"

View File

@ -47,7 +47,7 @@
"
/>
</a>
<v-card-text class="video-info pt-2">
<v-card-text class="video-info pt-2" v-emoji>
<div
v-for="title in video.headline.runs"
:key="title.text"

View File

@ -33,12 +33,13 @@
v-for="(item, index) in response"
:key="index"
class="px-0"
v-emoji
>
<v-btn
text
tile
dense
class="searchButton text-left text-capitalize"
class="searchButton text-left"
@click="youtubeSearch(item)"
>
<v-icon class="mr-5">mdi-magnify</v-icon>
@ -106,13 +107,12 @@ export default {
}
});
// --- External URL Handling --- //
CapacitorApp.addListener("appUrlOpen", (event) => {
const slug = new URL(event.url);
// We only push to the route if there is a slug present
if (slug) {
console.log(slug.pathname + slug.search);
this.$router.push(slug.pathname + slug.search);
}
this.$logger("ExternalURL", event.url);
// We only push to the route if there is a url present
linkParser(event.url);
if (result) this.$router.push(result.pathname + result.search);
});
// --- Import Twemoji ---///
@ -134,8 +134,8 @@ export default {
if (isLink) {
this.response = [
{
text: `Watch video from ID: ${isLink}`,
id: isLink,
text: `Watch Video from ID: ${isLink.searchParams.get("v")}`,
id: isLink.searchParams.get("v"),
},
];
return;
@ -215,11 +215,19 @@ div {
.invert {
filter: invert(100%);
}
.emoji {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: -0.1em;
}
</style>
<style scoped>
.searchButton {
width: 100%;
text-transform: none !important;
justify-content: left !important;
}
</style>

View File

@ -1,9 +1,6 @@
<template>
<div class="background" id="watch-body">
<div
class="player-container"
style="position: sticky; top: 0; z-index: 696969"
>
<div class="player-container">
<!-- Stock Player -->
<videoPlayer
:vid-src="vidSrc"
@ -14,7 +11,7 @@
<!-- VueTube Player V1 -->
<vuetubePlayer :sources="sources" v-if="useBetaPlayer === 'true'" />
</div>
<div class="content-container">
<div class="content-container overflow-y-auto">
<v-card v-if="loaded" class="ml-2 mr-2 background" flat>
<v-card-title
class="mt-2"
@ -25,6 +22,7 @@
line-height: 1rem;
"
v-text="video.title"
v-emoji
/>
<v-card-text>
<div style="margin-bottom: 1rem">
@ -102,7 +100,7 @@
<div class="avatar-link mr-3">
<v-img class="avatar-thumbnail" :src="video.channelImg" />
</div>
<div class="channel-byline">
<div class="channel-byline" v-emoji>
<div class="channel-name" v-text="video.channelName" />
<div
class="caption background--text"
@ -134,7 +132,11 @@
</div>
<!-- Comments -->
<div class="comment-container" v-if="loaded && video.commentData">
<div
class="comment-container"
v-if="loaded && video.commentData"
@click="showComments = !showComments"
>
<v-card flat class="background comment-renderer">
<v-text class="comment-count keep-spaces">
<template v-for="text in video.commentData.headerText.runs">
@ -149,6 +151,23 @@
<v-divider />
</div>
<v-dialog
v-model="showComments"
fullscreen
hide-overlay
transition="dialog-bottom-transition"
>
<v-card>
<v-toolbar dark color="background">
<v-btn icon dark @click="showComments = false">
<v-icon>mdi-close</v-icon>
</v-btn>
<v-toolbar-title class="font-weight-bold">Comments</v-toolbar-title>
</v-toolbar>
<v-subheader>Hello World</v-subheader>
</v-card>
</v-dialog>
<!-- Related Videos -->
<div class="loaders" v-if="!loaded">
<v-skeleton-loader
@ -178,66 +197,31 @@ export default {
vuetubePlayer,
ItemSectionRenderer,
},
data() {
return {
interactions: [
{
name: "Likes",
icon: "mdi-thumb-up-outline",
// action: null,
value: this.likes,
disabled: true,
},
{
name: "Dislikes",
icon: "mdi-thumb-down-outline",
// action: this.dislike(),
actionName: "dislike",
value: this.dislikes,
disabled: true,
},
{
name: "Share",
icon: "mdi-share-outline",
// action: this.share(),
actionName: "share",
disabled: false,
},
],
showMore: false,
// share: false,
vidSrc: null,
sources: [],
recommends: null,
loaded: false,
interval: null,
video: null,
useBetaPlayer: false,
};
},
data: function () {
return this.initializeState();
},
watch: {
// Watch for change in the route query string (in this case, ?v=xxxxxxxx to ?v=yyyyyyyy)
$route: {
deep: true,
handler(newRt, oldRt) {
if (newRt.query.v != oldRt.query.v) {
if (newRt.query.v && newRt.query.v != oldRt.query.v) {
// Exit fullscreen if currently in fullscreen
// if (this.$refs.player) this.$refs.player.webkitExitFullscreen();
// Reset player and run getVideo function again
this.vidSrc = "";
this.startTime = Math.floor(Date.now() / 1000);
// this.vidSrc = "";
// this.startTime = Math.floor(Date.now() / 1000);
// this.getVideo();
clearInterval(this.interval);
this.getVideo();
Object.assign(this.$data, this.initializeState());
this.mountedInit();
}
},
},
},
mounted() {
this.startTime = Math.floor(Date.now() / 1000);
this.getVideo();
this.useBetaPlayer = localStorage.getItem("debug.BetaPlayer");
this.mountedInit();
},
destroyed() {
@ -335,6 +319,57 @@ export default {
this.playbackTracking.videostatsPlaybackUrl.baseUrl
);
},
initializeState() {
return {
interactions: [
{
name: "Likes",
icon: "mdi-thumb-up-outline",
// action: null,
value: this.likes,
disabled: true,
},
{
name: "Dislikes",
icon: "mdi-thumb-down-outline",
// action: this.dislike(),
actionName: "dislike",
value: this.dislikes,
disabled: true,
},
{
name: "Share",
icon: "mdi-share-outline",
// action: this.share(),
actionName: "share",
disabled: false,
},
],
showMore: false,
showComments: false,
// share: false,
vidSrc: null,
sources: [],
recommends: null,
loaded: false,
interval: null,
video: null,
useBetaPlayer: false,
};
},
mountedInit() {
this.startTime = Math.floor(Date.now() / 1000);
this.getVideo();
this.useBetaPlayer = localStorage.getItem("debug.BetaPlayer");
// Reset vertical scrolling
const scrollableList = document.querySelectorAll(".overflow-y-auto");
scrollableList.forEach((scrollable) => {
scrollable.scrollTo(0, 0);
});
},
},
};
</script>
@ -348,7 +383,6 @@ export default {
}
.content-container {
overflow-y: auto;
height: 100%;
}

View File

@ -12,7 +12,7 @@ const url = {
const ytApiVal = {
VERSION: "16.25",
CLIENTNAME: "ANDROID",
VERSION_WEB: "2.20220331.06.00",
VERSION_WEB: "2.20220411.09.00",
CLIENT_WEB: 2,
};

View File

@ -17,10 +17,10 @@ function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null;
}
@ -41,11 +41,39 @@ function getMutationByKey(key, mutations) {
if (!key || !mutations) return undefined;
return mutations.find((mutation) => mutation.entityKey === key).payload;
}
function setHttp(link) {
if (link.search(/^http[s]?\:\/\//) == -1) {
link = "http://" + link;
}
return link;
}
// Replace inputted html with tweemoji
function parseEmoji(body) {
if (twemoji)
return twemoji.parse(body, {
folder: "svg",
ext: ".svg",
});
}
function linkParser(url) {
console.log("linkParpar", url)
const regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
const match = url.match(regExp);
return (match && match[7].length == 11) ? match[7] : false;
let result;
if (url) {
try {
const slug = new URL(setHttp(url));
const host = slug.hostname.toLowerCase().replace(/^www\./, "");
if (host == "youtube.com") {
result = slug;
} else if (host == "youtu.be") {
result = new URL("/watch", window.location.origin);
result.searchParams.set("v", slug.pathname.split("/")[1]);
}
} finally {
return result instanceof URL ? result : false;
}
}
}
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
@ -57,4 +85,5 @@ module.exports = {
getMutationByKey,
linkParser,
delay,
parseEmoji,
};

View File

@ -3,8 +3,16 @@ import { Http } from "@capacitor-community/http";
import { StatusBar, Style } from "@capacitor/status-bar";
import { NavigationBar } from "@hugotomazi/capacitor-navigation-bar";
import constants from "./constants";
import { hexToRgb, rgbToHex } from "./utils";
import { hexToRgb, rgbToHex, parseEmoji } from "./utils";
import { Haptics, ImpactStyle } from "@capacitor/haptics";
import Vue from "vue";
Vue.directive("emoji", {
inserted: function (el) {
const twemojiParse = parseEmoji(el.innerHTML);
if (twemojiParse) el.innerHTML = twemojiParse;
},
});
const module = {
//--- Get GitHub Commits ---//