mirror of https://github.com/VueTubeApp/VueTube
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:
commit
62cdad816c
|
@ -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"
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<div class="swipeableBottomSheet" :open-state="state ? 1 : 0"></div>
|
||||
</template>
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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%;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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 ---//
|
||||
|
|
Loading…
Reference in New Issue