diff --git a/.all-contributorsrc b/.all-contributorsrc index 182e3657e..b79ce3ba5 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,7 +1,5 @@ { - "files": [ - "README.md" - ], + "files": ["README.md"], "imageSize": 100, "commit": false, "contributors": [ @@ -10,73 +8,56 @@ "name": "cyacedev", "avatar_url": "https://avatars0.githubusercontent.com/u/46712905?v=4", "profile": "https://github.com/cyacedev", - "contributions": [ - "code", - "doc" - ] + "contributions": ["code", "doc"] }, { "login": "ckVendrix", "name": "Vendrix", "avatar_url": "https://avatars2.githubusercontent.com/u/51775140?v=4", "profile": "https://github.com/ckVendrix", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "Mennaruuk", "name": "Mennaruuk", "avatar_url": "https://avatars.githubusercontent.com/u/52135169?v=4", "profile": "https://github.com/Mennaruuk", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "mizzunet", "name": "Missu", "avatar_url": "https://avatars.githubusercontent.com/u/10193999?v=4", "profile": "https://github.com/mizzunet", - "contributions": [ - "doc" - ] + "contributions": ["doc"] }, { "login": "beardeddude", "name": "beardeddude", "avatar_url": "https://avatars.githubusercontent.com/u/36680638?v=4", "profile": "https://github.com/beardeddude", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "mattfbacon", "name": "Matt Fellenz", "avatar_url": "https://avatars.githubusercontent.com/u/58113890?v=4", "profile": "http://matt.felle.nz", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "themisir", "name": "Misir", "avatar_url": "https://avatars.githubusercontent.com/u/29130291?v=4", "profile": "http://themisir.com", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "alvanrahimli", "name": "Alvan Rahimli", "avatar_url": "https://avatars.githubusercontent.com/u/41202771?v=4", "profile": "https://www.rahim.li", - "contributions": [ - "code" - ] + "contributions": ["code"] }, { "login": "chonsser", diff --git a/.dockerignore b/.dockerignore index a7da65b36..d11ba8cc4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -30,3 +30,5 @@ client/.output client/.nuxt server/node_modules server/dist +shared/node_modules +shared/dist \ No newline at end of file diff --git a/.github/workflows/build-workflow.yml b/.github/workflows/build-workflow.yml index be6a92e80..db4cc2755 100644 --- a/.github/workflows/build-workflow.yml +++ b/.github/workflows/build-workflow.yml @@ -38,7 +38,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v2 with: - version: 8 + version: 9 run_install: false - name: Generate build metadata diff --git a/.github/workflows/pr-workflow.yml b/.github/workflows/pr-workflow.yml index af79f1c22..80077e41a 100644 --- a/.github/workflows/pr-workflow.yml +++ b/.github/workflows/pr-workflow.yml @@ -8,7 +8,7 @@ jobs: pr-job: strategy: matrix: - command: ['build', 'test', 'lint:client', 'lint:server'] + command: ['build', 'lint'] name: ${{ matrix.command }} timeout-minutes: 60 @@ -26,7 +26,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v2 with: - version: 8 + version: 9 run_install: false - name: Get pnpm store directory @@ -45,6 +45,9 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Prepare .nuxt directory + run: pnpm run nuxt:prepare + - name: Generate build metadata run: | pnpm build:metadata @@ -68,7 +71,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v2 with: - version: 8 + version: 9 run_install: false - name: Install e2e test dependencies diff --git a/.github/workflows/test-workflow.yml b/.github/workflows/test-workflow.yml index f9f8bc66d..f7ca4b458 100644 --- a/.github/workflows/test-workflow.yml +++ b/.github/workflows/test-workflow.yml @@ -23,7 +23,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@v2 with: - version: 8 + version: 9 run_install: false - name: Install e2e test dependencies diff --git a/.gitignore b/.gitignore index f52324aae..d131d2dbf 100644 --- a/.gitignore +++ b/.gitignore @@ -33,7 +33,7 @@ sw.* out/ out/* -data/* +data !/server/data output/* .vs/* @@ -44,6 +44,7 @@ dump.rdb tests/cypress/screenshots tests/cypress/videos tests/cypress/downloads +tests/cypress/environment/data Dockerfile.nodejs-mongodb .vscode/.ropeproject/ @@ -55,3 +56,4 @@ client/buildMetadata.json **/cache generated.txt original.txt +screenshots diff --git a/.npmrc b/.npmrc deleted file mode 100644 index c483022c0..000000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -shamefully-hoist=true \ No newline at end of file diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs deleted file mode 100644 index ec7e9f136..000000000 --- a/.pnpmfile.cjs +++ /dev/null @@ -1,13 +0,0 @@ -function readPackage(pkg, context) { - if (process.env.CI === 'true') { - delete pkg?.scripts?.prepare; - } - - return pkg; -} - -module.exports = { - hooks: { - readPackage - } -}; diff --git a/.prettierignore b/.prettierignore index fdca7354a..12256171e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -12,9 +12,13 @@ client/assets/fonts server/data server/node_modules server/dist +server/src/metadata.ts # Shared shared/node_modules +shared/src/api.schema.ts # Tests tests/node_modules + +.all-contributorsrc diff --git a/.prettierrc.json b/.prettierrc.json index 7565478df..38070c202 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -9,5 +9,6 @@ "endOfLine": "lf", "printWidth": 100, "vueIndentScriptAndStyle": false, - "quoteProps": "as-needed" + "quoteProps": "as-needed", + "plugins": ["prettier-plugin-organize-imports"] } diff --git a/.vscode/settings.json b/.vscode/settings.json index c6e2e98f6..b1bb3af5c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "prettier.prettierPath": "node_modules/prettier/index.cjs", "typescript.tsdk": "node_modules/typescript/lib", - "githubPullRequests.ignoredPullRequestBranches": ["development"] + "githubPullRequests.ignoredPullRequestBranches": ["development"], + "eslint.experimental.useFlatConfig": true } diff --git a/CHANGELOG.md b/CHANGELOG.md index b9db35ab3..75e8fd522 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ This file is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.16.0] + +### Added + +- Brand new video player (Checkout the wiki: https://viewtube.wiki/features/videoplayer) [#2388] + ## [0.15.4] ### Fixed @@ -86,7 +92,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking ⚠️ - Disable clustering by default [#2377](https://github.com/ViewTube/viewtube/pull/2377) - - Clustering is now disabled by default. If you want to use clustering, you have to set the `VIEWTUBE_CLUSTERED` environment variable to `true`. + - Clustering is controlled by the `VIEWTUBE_CLUSTERED` environment variable [viewtube.wiki > advanced configuration](https://viewtube.wiki/installation/configuration#advanced-configuration). + If you have disabled clustering previously, you don't need to change anything. + If you want to keep clustering enabled, you need to set the `VIEWTUBE_CLUSTERED` environment variable to `true`. ### Added @@ -104,6 +112,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix "window is not defined" when logged in and "Rewrite YouTube URLs" is enabled [#2469](https://github.com/ViewTube/viewtube/pull/2469) - Fix certain search terms not working [#2493](https://github.com/ViewTube/viewtube/pull/2493) +## Removed + +- Remove unused VIEWTUBE_YOUTUBE_IDENTIFIER environment variable [#2388](https://github.com/ViewTube/viewtube/pull/2388) + ## [0.13.1] ### Fixed @@ -427,7 +439,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial release -[unreleased]: https://github.com/viewtube/viewtube/compare/v0.15.4...development +[unreleased]: https://github.com/viewtube/viewtube/compare/v0.16.0...development +[0.16.0]: https://github.com/viewtube/viewtube/compare/v0.15.4...v0.16.0 [0.15.4]: https://github.com/viewtube/viewtube/compare/v0.15.3...v0.15.4 [0.15.3]: https://github.com/viewtube/viewtube/compare/v0.15.2...v0.15.3 [0.15.2]: https://github.com/viewtube/viewtube/compare/v0.15.1...v0.15.2 diff --git a/Dockerfile b/Dockerfile index 26d6d6bf4..03b91f3db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,17 @@ FROM node:20-bookworm as build WORKDIR /home/build -ENV NUXT_BUILD=true - -COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./ +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ COPY server/package.json ./server/ -COPY client/package.json ./client/ COPY shared/package.json ./shared/ +COPY client/package.json ./client/ +COPY client/scripts ./client/scripts COPY patches ./patches -RUN npm install -g pnpm@8.15.7 +RUN npm install -g pnpm@9.1.3 -RUN pnpm --filter=./server --filter=./client install --frozen-lockfile +RUN pnpm install --frozen-lockfile COPY . . @@ -30,12 +29,15 @@ ENV NODE_ENV=production COPY --from=build /home/build/package.json ./ COPY --from=build /home/build/client/package.json ./client/ COPY --from=build /home/build/server/package.json ./server/ +COPY --from=build /home/build/shared/package.json ./shared/ COPY --from=build /home/build/node_modules ./node_modules COPY --from=build /home/build/server/node_modules ./server/node_modules COPY --from=build /home/build/server/dist ./server/dist/ +COPY --from=build /home/build/shared/dist ./shared/dist/ + COPY --from=build /home/build/client/.output ./client/.output/ RUN \ @@ -48,4 +50,4 @@ ENV VIEWTUBE_BASE_DIR=/home/app HEALTHCHECK --interval=30s --timeout=20s --start-period=60s CMD wget --no-verbose --tries=3 --spider http://localhost:8066/ || exit 1 EXPOSE 8066 -CMD ["node", "/home/app/server/dist/main.cjs"] +CMD ["node", "/home/app/server/dist/main.js"] diff --git a/README.md b/README.md index 18719edbd..f09936b69 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ ViewTube is an alternative YouTube frontend that lets you watch, search and disc It's built using [Nuxt](https://nuxt.com/) and [Nest](https://nestjs.com/). > [!NOTE] -> You can find the documentation at [viewtube.wiki](https://viewtube.wiki) -Check [uptime.m-o.dev/status](https://uptime.m-o.dev/status) for updates and downtime status. +> You can find the documentation at [viewtube.wiki](https://viewtube.wiki). +> Check [uptime.m-o.dev/status](https://uptime.m-o.dev/status) for updates and downtime status.
{{ communityPost.publishedText }} • {{ communityPost.author }}
{{ channelInfo?.author }} diff --git a/client/components/channel/BannerStats.vue b/client/components/channel/BannerStats.vue index 4d1e7f497..53626ca78 100644 --- a/client/components/channel/BannerStats.vue +++ b/client/components/channel/BannerStats.vue @@ -1,4 +1,6 @@ @@ -20,10 +31,14 @@ const { data: channelStats, pending: pendingStats } = useGetChannelStats(channel class="channel-home" >
-
-
+
+
diff --git a/client/components/community-post/Image.vue b/client/components/community-post/Image.vue
index fe0907ab1..396f2929d 100644
--- a/client/components/community-post/Image.vue
+++ b/client/components/community-post/Image.vue
@@ -72,7 +72,9 @@ const postImageHeightPx = ref('0px');
position: relative;
top: 50%;
transform: translateY(-50%);
- transition: top 300ms $intro-easing, transform 300ms $intro-easing;
+ transition:
+ top 300ms $intro-easing,
+ transform 300ms $intro-easing;
display: block;
}
diff --git a/client/components/community-post/MultiImage.vue b/client/components/community-post/MultiImage.vue
index 74cfd4656..377fa11b4 100644
--- a/client/components/community-post/MultiImage.vue
+++ b/client/components/community-post/MultiImage.vue
@@ -19,7 +19,7 @@ const modules = [Navigation];
-
+
diff --git a/client/components/filter/Dropdown.vue b/client/components/filter/Dropdown.vue
index 390ee77a1..206c2eaca 100644
--- a/client/components/filter/Dropdown.vue
+++ b/client/components/filter/Dropdown.vue
@@ -209,7 +209,10 @@ visible.value = true;
transform: scale(0) translateY(-50%) !important;
clip-path: none !important;
transform-origin: center top !important;
- transition: opacity 300ms 0ms $intro-easing, transform 600ms $outro-easing, box-shadow 300ms,
+ transition:
+ opacity 300ms 0ms $intro-easing,
+ transform 600ms $outro-easing,
+ box-shadow 300ms,
pointer-events 0ms !important;
opacity: 0;
pointer-events: none !important;
@@ -217,8 +220,10 @@ visible.value = true;
&.open {
clip-path: none !important;
transform: scale(1) translateY(-50%) !important;
- transition: opacity 200ms 100ms $intro-easing,
- transform 300ms cubic-bezier(0, 0.98, 0.21, 0.98), box-shadow 300ms !important;
+ transition:
+ opacity 200ms 100ms $intro-easing,
+ transform 300ms cubic-bezier(0, 0.98, 0.21, 0.98),
+ box-shadow 300ms !important;
opacity: 1;
pointer-events: auto !important;
}
diff --git a/client/components/flip/CaptionsRenderer.vue b/client/components/flip/CaptionsRenderer.vue
new file mode 100644
index 000000000..6fbe0a115
--- /dev/null
+++ b/client/components/flip/CaptionsRenderer.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/CaptionsSelector.vue b/client/components/flip/CaptionsSelector.vue
new file mode 100644
index 000000000..45350ec39
--- /dev/null
+++ b/client/components/flip/CaptionsSelector.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+ Off
+
+
+ {{ track.name }}
+
+
+
+
+
+
+
diff --git a/client/components/flip/Chapters.vue b/client/components/flip/Chapters.vue
new file mode 100644
index 000000000..a135b2f78
--- /dev/null
+++ b/client/components/flip/Chapters.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/ControlButtons.vue b/client/components/flip/ControlButtons.vue
new file mode 100644
index 000000000..30a7cce67
--- /dev/null
+++ b/client/components/flip/ControlButtons.vue
@@ -0,0 +1,143 @@
+
+
+
+
+ {{ timestampText }}
+
+
+
+
+
+
+
+
+
+
+ {{ videoLengthText }}
+
+
+
+
diff --git a/client/components/flip/Controls.vue b/client/components/flip/Controls.vue
new file mode 100644
index 000000000..3b0fff52c
--- /dev/null
+++ b/client/components/flip/Controls.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/Effect.vue b/client/components/flip/Effect.vue
new file mode 100644
index 000000000..5afb0d946
--- /dev/null
+++ b/client/components/flip/Effect.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/EffectsOverlay.vue b/client/components/flip/EffectsOverlay.vue
new file mode 100644
index 000000000..3c6ea1b1e
--- /dev/null
+++ b/client/components/flip/EffectsOverlay.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/Loading.vue b/client/components/flip/Loading.vue
new file mode 100644
index 000000000..bfd53d0e7
--- /dev/null
+++ b/client/components/flip/Loading.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/PlaybackSettings.vue b/client/components/flip/PlaybackSettings.vue
new file mode 100644
index 000000000..7233d15d9
--- /dev/null
+++ b/client/components/flip/PlaybackSettings.vue
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+ Video speed
+
+
+ (asList = val)"
+ />
+
+ setVideoSpeed(e.target.value)"
+ />
+ setVideoSpeed(val.value)"
+ />
+
+
+ videoState.setLoop(val)"
+ />
+
+
+
+
+
+
diff --git a/client/components/flip/Player.vue b/client/components/flip/Player.vue
new file mode 100644
index 000000000..8a65ff5d7
--- /dev/null
+++ b/client/components/flip/Player.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/PlayerUI.vue b/client/components/flip/PlayerUI.vue
new file mode 100644
index 000000000..ee94e41e4
--- /dev/null
+++ b/client/components/flip/PlayerUI.vue
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/Poster.vue b/client/components/flip/Poster.vue
new file mode 100644
index 000000000..2d816e372
--- /dev/null
+++ b/client/components/flip/Poster.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/QualitySelector.vue b/client/components/flip/QualitySelector.vue
new file mode 100644
index 000000000..54741664b
--- /dev/null
+++ b/client/components/flip/QualitySelector.vue
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+
+ Auto
+ · {{ currentVideoRepresentation?.label }}
+
+
+
+
+
+
+ {{ representation.label }}
+
+
+
+ HDR
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ representation.label }}
+
+
+
+
+
+
+
diff --git a/client/components/flip/Seekbar.vue b/client/components/flip/Seekbar.vue
new file mode 100644
index 000000000..5319a0acc
--- /dev/null
+++ b/client/components/flip/Seekbar.vue
@@ -0,0 +1,226 @@
+
+
+
+ {}"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/SeekbarPreview.vue b/client/components/flip/SeekbarPreview.vue
new file mode 100644
index 000000000..2e18aded1
--- /dev/null
+++ b/client/components/flip/SeekbarPreview.vue
@@ -0,0 +1,253 @@
+
+
+
+
+
+
+
+
+
+
+ {{ hoveredTimestamp }}
+
+
+ {{ currentChapter?.title ?? '' }}
+
+
+
+ {{ currentSponsorBlockSegmentCategory?.text ?? '' }}
+
+
+
+
+
+
diff --git a/client/components/flip/Settings.vue b/client/components/flip/Settings.vue
new file mode 100644
index 000000000..35245d91e
--- /dev/null
+++ b/client/components/flip/Settings.vue
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ language.label }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/components/flip/SkipButton.vue b/client/components/flip/SkipButton.vue
new file mode 100644
index 000000000..beb24058a
--- /dev/null
+++ b/client/components/flip/SkipButton.vue
@@ -0,0 +1,123 @@
+
+
+
+
+ Skip {{ currentSponsorBlockSegment?.text }}
+ Press enter to skip
+
+
+
+
diff --git a/client/components/flip/SkipSegment.vue b/client/components/flip/SkipSegment.vue
new file mode 100644
index 000000000..f14fc42c8
--- /dev/null
+++ b/client/components/flip/SkipSegment.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
diff --git a/client/components/flip/TopBar.vue b/client/components/flip/TopBar.vue
new file mode 100644
index 000000000..930c79373
--- /dev/null
+++ b/client/components/flip/TopBar.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+ {{ video.title }}
+ {{ video.author.name }}
+
+
+
+
+
diff --git a/client/components/flip/Volume.vue b/client/components/flip/Volume.vue
new file mode 100644
index 000000000..61b964aec
--- /dev/null
+++ b/client/components/flip/Volume.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
diff --git a/client/components/form/CheckBox.vue b/client/components/form/CheckBox.vue
index 5d72e66dc..0239ebaec 100644
--- a/client/components/form/CheckBox.vue
+++ b/client/components/form/CheckBox.vue
@@ -91,7 +91,9 @@ const onChange = (e: any) => {
clip-path: polygon(0 0, 0 0, 20px 0, 20px 20px, 0 20px, 0 0);
background-color: var(--bgcolor-alt);
display: block;
- transition: background-color 300ms $intro-easing, clip-path 300ms $intro-easing;
+ transition:
+ background-color 300ms $intro-easing,
+ clip-path 300ms $intro-easing;
.checkbox-background {
width: 20px;
diff --git a/client/components/form/FileButton.vue b/client/components/form/FileButton.vue
index a59f61b6d..23b2c167d 100644
--- a/client/components/form/FileButton.vue
+++ b/client/components/form/FileButton.vue
@@ -2,7 +2,13 @@
@@ -13,7 +19,7 @@ export default defineComponent({
label: String,
accept: String
},
- emits: {'change': null}
+ emits: { change: null }
});
diff --git a/client/components/form/IconSwitcher.vue b/client/components/form/IconSwitcher.vue
index 7f588ad19..5e7f5db72 100644
--- a/client/components/form/IconSwitcher.vue
+++ b/client/components/form/IconSwitcher.vue
@@ -31,7 +31,7 @@ const selectIcon = (newIcon: string) => {
.icon-switcher {
display: flex;
margin: 0 auto;
- gap: 5px;
+ gap: 5px;
.switch-icon {
width: 45px;
diff --git a/client/components/form/LoginForm.vue b/client/components/form/LoginForm.vue
index 2e05eb0e8..fcfdafa36 100644
--- a/client/components/form/LoginForm.vue
+++ b/client/components/form/LoginForm.vue
@@ -5,7 +5,13 @@
Usernames are case sensitive
diff --git a/client/components/form/RegisterForm.vue b/client/components/form/RegisterForm.vue
index 8cf50dd6e..200cfb7d5 100644
--- a/client/components/form/RegisterForm.vue
+++ b/client/components/form/RegisterForm.vue
@@ -8,7 +8,7 @@ import { useUserStore } from '@/store/user';
import { useCaptchaStore } from '@/store/captcha';
const props = defineProps<{
- complete?: Function;
+ complete?: () => void;
}>();
const route = useRoute();
@@ -90,7 +90,13 @@ captchaStore.getCaptcha();
Usernames are case sensitive
{{ videoState.bufferMessage.value }}...
+Codec
+Player settings
+