@krx3d/tizentube2 1.15.810 → 1.15.830
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Build the release body for a TizenTube Standalone release.
|
|
3
|
+
#
|
|
4
|
+
# Usage: build-release-notes.sh <release_sha> <release_version> <app_id> <app_name> <out_file>
|
|
5
|
+
#
|
|
6
|
+
# The changelog is derived from the merge/squash commits between the previous
|
|
7
|
+
# published release and this build, grouped by conventional-commit prefix.
|
|
8
|
+
# Version-bump commits made by CI carry no PR number and drop out on their own.
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
RELEASE_SHA="$1"
|
|
12
|
+
RELEASE_VERSION="$2"
|
|
13
|
+
APP_ID="$3"
|
|
14
|
+
APP_NAME="$4"
|
|
15
|
+
OUT="$5"
|
|
16
|
+
|
|
17
|
+
REPO="${GITHUB_REPOSITORY:-}"
|
|
18
|
+
|
|
19
|
+
# Previous release = the newest published release that isn't the one being cut.
|
|
20
|
+
# Falls back to the newest version tag, then to "no previous release".
|
|
21
|
+
PREV_TAG=""
|
|
22
|
+
if [ -n "$REPO" ] && command -v gh >/dev/null 2>&1; then
|
|
23
|
+
PREV_TAG=$(gh api "repos/${REPO}/releases" --jq \
|
|
24
|
+
"[.[] | select(.draft == false) | .tag_name] | map(select(. != \"${RELEASE_VERSION}\")) | .[0] // empty" \
|
|
25
|
+
2>/dev/null || true)
|
|
26
|
+
fi
|
|
27
|
+
# Reject anything that isn't an ancestor of this build: version-string order is
|
|
28
|
+
# not history order (a v2.x standalone tag can sort above the current v1.15.x
|
|
29
|
+
# line and would drag in every commit since the fork point).
|
|
30
|
+
if [ -n "$PREV_TAG" ] && ! git merge-base --is-ancestor "${PREV_TAG}^{commit}" "$RELEASE_SHA" 2>/dev/null; then
|
|
31
|
+
echo "Ignoring ${PREV_TAG}: not an ancestor of ${RELEASE_SHA}" >&2
|
|
32
|
+
PREV_TAG=""
|
|
33
|
+
fi
|
|
34
|
+
if [ -z "$PREV_TAG" ]; then
|
|
35
|
+
PREV_TAG=$(git describe --tags --abbrev=0 "${RELEASE_SHA}^" 2>/dev/null || true)
|
|
36
|
+
[ "$PREV_TAG" = "$RELEASE_VERSION" ] && PREV_TAG=""
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
if [ -n "$PREV_TAG" ] && git rev-parse -q --verify "${PREV_TAG}^{commit}" >/dev/null; then
|
|
40
|
+
RANGE="${PREV_TAG}..${RELEASE_SHA}"
|
|
41
|
+
else
|
|
42
|
+
# First release, or the previous tag isn't in this clone — describe the last
|
|
43
|
+
# stretch of history rather than the entire project.
|
|
44
|
+
RANGE="${RELEASE_SHA}~50..${RELEASE_SHA}"
|
|
45
|
+
git rev-parse -q --verify "${RELEASE_SHA}~50" >/dev/null || RANGE="$RELEASE_SHA"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# --- collect (pr_number, title) pairs -----------------------------------------
|
|
49
|
+
# GitHub merge commits: "Merge pull request #N from owner/branch" + body=title
|
|
50
|
+
# GitHub squash commits: "title (#N)"
|
|
51
|
+
declare -a FEATURES=() FIXES=() PORTS=() OTHER=()
|
|
52
|
+
|
|
53
|
+
while IFS=$'\x1f' read -r -d $'\x1e' subject body; do
|
|
54
|
+
subject="${subject#$'\n'}"
|
|
55
|
+
pr=""
|
|
56
|
+
title=""
|
|
57
|
+
if [[ "$subject" =~ ^Merge\ pull\ request\ \#([0-9]+) ]]; then
|
|
58
|
+
pr="${BASH_REMATCH[1]}"
|
|
59
|
+
title=$(printf '%s' "$body" | sed '/^[[:space:]]*$/d' | head -n1)
|
|
60
|
+
elif [[ "$subject" =~ ^(.*)\ \(\#([0-9]+)\)$ ]]; then
|
|
61
|
+
title="${BASH_REMATCH[1]}"
|
|
62
|
+
pr="${BASH_REMATCH[2]}"
|
|
63
|
+
fi
|
|
64
|
+
[ -z "$pr" ] && continue
|
|
65
|
+
[ -z "$title" ] && title="$subject"
|
|
66
|
+
|
|
67
|
+
entry="- ${title} (#${pr})"
|
|
68
|
+
shopt -s nocasematch
|
|
69
|
+
if [[ "$title" == Port\ upstream* ]]; then
|
|
70
|
+
PORTS+=("$entry")
|
|
71
|
+
elif [[ "$title" =~ ^feat(\(.*\))?: ]]; then
|
|
72
|
+
FEATURES+=("$entry")
|
|
73
|
+
elif [[ "$title" =~ ^fix(\(.*\))?: ]]; then
|
|
74
|
+
FIXES+=("$entry")
|
|
75
|
+
else
|
|
76
|
+
OTHER+=("$entry")
|
|
77
|
+
fi
|
|
78
|
+
shopt -u nocasematch
|
|
79
|
+
done < <(git log --first-parent --pretty=format:'%s%x1f%b%x1e' "$RANGE")
|
|
80
|
+
|
|
81
|
+
# --- write the body -----------------------------------------------------------
|
|
82
|
+
{
|
|
83
|
+
echo "TizenTube Standalone build from commit \`${RELEASE_SHA}\`, version-synced with the userscript."
|
|
84
|
+
echo "TBI_METADATA: {\"appId\":\"${APP_ID}\",\"appName\":\"${APP_NAME}\"}"
|
|
85
|
+
echo
|
|
86
|
+
|
|
87
|
+
section() {
|
|
88
|
+
local heading="$1"; shift
|
|
89
|
+
[ "$#" -eq 0 ] && return 0
|
|
90
|
+
echo "### ${heading}"
|
|
91
|
+
printf '%s\n' "$@"
|
|
92
|
+
echo
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if [ ${#FEATURES[@]} -eq 0 ] && [ ${#FIXES[@]} -eq 0 ] && [ ${#PORTS[@]} -eq 0 ] && [ ${#OTHER[@]} -eq 0 ]; then
|
|
96
|
+
echo "No pull requests were merged since \`${PREV_TAG:-the previous build}\`."
|
|
97
|
+
else
|
|
98
|
+
echo "## What's Changed"
|
|
99
|
+
echo
|
|
100
|
+
section "Features" ${FEATURES[@]+"${FEATURES[@]}"}
|
|
101
|
+
section "Fixes" ${FIXES[@]+"${FIXES[@]}"}
|
|
102
|
+
section "Ported from upstream" ${PORTS[@]+"${PORTS[@]}"}
|
|
103
|
+
section "Other" ${OTHER[@]+"${OTHER[@]}"}
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
if [ -n "$PREV_TAG" ] && [ -n "$REPO" ]; then
|
|
107
|
+
echo "**Full changelog:** https://github.com/${REPO}/compare/${PREV_TAG}...${RELEASE_VERSION}"
|
|
108
|
+
fi
|
|
109
|
+
} > "$OUT"
|
|
110
|
+
|
|
111
|
+
echo "Wrote release notes to $OUT:"
|
|
112
|
+
echo "---"
|
|
113
|
+
cat "$OUT"
|
|
@@ -286,13 +286,20 @@ jobs:
|
|
|
286
286
|
name: TizenTube-Standalone-${{ env.RELEASE_SHA }}.wgt
|
|
287
287
|
path: standalone/release/TizenTube.wgt
|
|
288
288
|
|
|
289
|
+
# Changelog is built from the PRs merged since the previous published
|
|
290
|
+
# release; the build/TBI_METADATA header stays first so the TizenBrew
|
|
291
|
+
# Installer still finds it.
|
|
292
|
+
- name: Build release notes
|
|
293
|
+
env:
|
|
294
|
+
GH_TOKEN: ${{ github.token }}
|
|
295
|
+
run: |
|
|
296
|
+
bash .github/scripts/build-release-notes.sh "${{ env.RELEASE_SHA }}" "${{ env.RELEASE_VERSION }}" "${{ env.APP_ID }}" "${{ env.APP_NAME }}" "$RUNNER_TEMP/release-notes.md"
|
|
297
|
+
|
|
289
298
|
- name: Release TizenTube Standalone
|
|
290
299
|
uses: softprops/action-gh-release@v1
|
|
291
300
|
with:
|
|
292
301
|
tag_name: ${{ env.RELEASE_VERSION }}
|
|
293
302
|
target_commitish: ${{ env.RELEASE_SHA }}
|
|
294
|
-
|
|
295
|
-
TizenTube Standalone build from commit `${{ env.RELEASE_SHA }}`, version-synced with the userscript.
|
|
296
|
-
TBI_METADATA: {"appId":"${{ env.APP_ID }}","appName":"${{ env.APP_NAME }}"}
|
|
303
|
+
body_path: ${{ runner.temp }}/release-notes.md
|
|
297
304
|
files: |
|
|
298
305
|
standalone/release/*
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Watch reisxd/TizenTube for new commits and open a PR that carries them.
|
|
2
|
+
#
|
|
3
|
+
# This fork has rewritten large parts of mods/ (adblock.js, hideWatched.js,
|
|
4
|
+
# settings.js in particular), so most upstream commits touching those files
|
|
5
|
+
# WILL conflict. The workflow does not pretend otherwise: it always produces a
|
|
6
|
+
# branch that merges cleanly into main, and when a file conflicted it keeps the
|
|
7
|
+
# fork's version and says so in the PR body, so the upstream change can be
|
|
8
|
+
# hand-ported afterwards.
|
|
9
|
+
name: Upstream sync
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
schedule:
|
|
13
|
+
# 04:20 UTC daily — outside the usual release window.
|
|
14
|
+
- cron: '20 4 * * *'
|
|
15
|
+
workflow_dispatch:
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: upstream-sync
|
|
19
|
+
cancel-in-progress: false
|
|
20
|
+
|
|
21
|
+
env:
|
|
22
|
+
UPSTREAM_REPO: https://github.com/reisxd/TizenTube.git
|
|
23
|
+
UPSTREAM_BRANCH: main
|
|
24
|
+
UPSTREAM_BRANCH_REF: upstream/main
|
|
25
|
+
SYNC_BRANCH: sync/upstream
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
sync:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
permissions:
|
|
31
|
+
contents: write
|
|
32
|
+
pull-requests: write
|
|
33
|
+
steps:
|
|
34
|
+
- name: Clone repo with full history
|
|
35
|
+
uses: actions/checkout@v5
|
|
36
|
+
with:
|
|
37
|
+
fetch-depth: 0
|
|
38
|
+
|
|
39
|
+
- name: Configure git identity
|
|
40
|
+
run: |
|
|
41
|
+
git config user.name 'github-actions[bot]'
|
|
42
|
+
git config user.email 'github-actions[bot]@users.noreply.github.com'
|
|
43
|
+
|
|
44
|
+
- name: Fetch upstream
|
|
45
|
+
run: |
|
|
46
|
+
set -euo pipefail
|
|
47
|
+
git remote add upstream "$UPSTREAM_REPO" 2>/dev/null || git remote set-url upstream "$UPSTREAM_REPO"
|
|
48
|
+
git fetch upstream "$UPSTREAM_BRANCH" --no-tags
|
|
49
|
+
|
|
50
|
+
- name: Check for new upstream commits
|
|
51
|
+
id: check
|
|
52
|
+
run: |
|
|
53
|
+
set -euo pipefail
|
|
54
|
+
COUNT=$(git rev-list --count "origin/main..upstream/${UPSTREAM_BRANCH}")
|
|
55
|
+
echo "count=$COUNT" >> "$GITHUB_OUTPUT"
|
|
56
|
+
echo "Upstream commits not in main: $COUNT"
|
|
57
|
+
|
|
58
|
+
- name: Merge upstream, keeping the fork's side of any conflict
|
|
59
|
+
id: merge
|
|
60
|
+
if: steps.check.outputs.count != '0'
|
|
61
|
+
run: |
|
|
62
|
+
set -euo pipefail
|
|
63
|
+
BASE_SHA=$(git rev-parse origin/main)
|
|
64
|
+
git checkout -B "$SYNC_BRANCH" origin/main
|
|
65
|
+
|
|
66
|
+
# --no-commit so the CI-exclusion below lands in the same commit
|
|
67
|
+
# whether or not the merge conflicted, rather than needing a second.
|
|
68
|
+
CONFLICTS=""
|
|
69
|
+
git merge --no-commit --no-ff "$UPSTREAM_BRANCH_REF" || true
|
|
70
|
+
|
|
71
|
+
CONFLICTS=$(git diff --name-only --diff-filter=U || true)
|
|
72
|
+
if [ -n "$CONFLICTS" ]; then
|
|
73
|
+
# Keep this fork's version of every conflicted file. The point of
|
|
74
|
+
# the PR is to surface the change for review, not to guess at a
|
|
75
|
+
# resolution — committing conflict markers would only produce a
|
|
76
|
+
# branch that cannot build.
|
|
77
|
+
echo "Conflicted files kept at fork version:"
|
|
78
|
+
echo "$CONFLICTS"
|
|
79
|
+
while IFS= read -r f; do
|
|
80
|
+
[ -z "$f" ] && continue
|
|
81
|
+
git checkout --ours -- "$f" 2>/dev/null || git rm -q -- "$f"
|
|
82
|
+
git add -- "$f" 2>/dev/null || true
|
|
83
|
+
done <<< "$CONFLICTS"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# CI is never synced from upstream, for two reasons. This fork runs
|
|
87
|
+
# its own workflows (npm publish, standalone .wgt build, this sync)
|
|
88
|
+
# which have no upstream counterpart, so importing theirs would be
|
|
89
|
+
# actively wrong. And GITHUB_TOKEN *cannot* push changes under
|
|
90
|
+
# .github/workflows at all — there is no "workflows" permission in
|
|
91
|
+
# the permissions: block, that scope exists only for PATs and GitHub
|
|
92
|
+
# Apps, so a push carrying one is rejected outright:
|
|
93
|
+
# refusing to allow a GitHub App to create or update workflow
|
|
94
|
+
# `.github/workflows/...` without `workflows` permission
|
|
95
|
+
# Restoring the directory to exactly origin/main covers both the
|
|
96
|
+
# modified and the newly-added case.
|
|
97
|
+
if git rev-parse --verify -q "${BASE_SHA}:.github/workflows" >/dev/null; then
|
|
98
|
+
git rm -rf --quiet --ignore-unmatch .github/workflows >/dev/null 2>&1 || true
|
|
99
|
+
git checkout "$BASE_SHA" -- .github/workflows
|
|
100
|
+
git add -A .github/workflows
|
|
101
|
+
echo "Restored .github/workflows to the fork's version"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# A clean merge leaves everything staged but uncommitted because of
|
|
105
|
+
# --no-commit; a conflicted one is staged by the loop above.
|
|
106
|
+
git commit --no-edit || echo "Nothing to commit"
|
|
107
|
+
|
|
108
|
+
{
|
|
109
|
+
echo 'conflicts<<TT_EOF'
|
|
110
|
+
echo "$CONFLICTS"
|
|
111
|
+
echo 'TT_EOF'
|
|
112
|
+
} >> "$GITHUB_OUTPUT"
|
|
113
|
+
|
|
114
|
+
if git diff --quiet origin/main -- .; then
|
|
115
|
+
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
116
|
+
else
|
|
117
|
+
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
118
|
+
git push --force-with-lease origin "$SYNC_BRANCH"
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
- name: Open or update the sync PR
|
|
122
|
+
if: steps.check.outputs.count != '0' && steps.merge.outputs.changed == 'true'
|
|
123
|
+
env:
|
|
124
|
+
GH_TOKEN: ${{ github.token }}
|
|
125
|
+
CONFLICTS: ${{ steps.merge.outputs.conflicts }}
|
|
126
|
+
NEW_COMMITS: ${{ steps.check.outputs.count }}
|
|
127
|
+
run: |
|
|
128
|
+
set -euo pipefail
|
|
129
|
+
|
|
130
|
+
{
|
|
131
|
+
echo "Automated sync with [reisxd/TizenTube](https://github.com/reisxd/TizenTube) — **${NEW_COMMITS}** new upstream commit(s)."
|
|
132
|
+
echo
|
|
133
|
+
|
|
134
|
+
if [ -n "${CONFLICTS//[[:space:]]/}" ]; then
|
|
135
|
+
echo "## :warning: Needs hand-porting"
|
|
136
|
+
echo
|
|
137
|
+
echo "These files conflicted and were **kept at this fork's version**, so the upstream changes to them are *not* in this PR. Merging as-is is safe but incomplete — port them by hand before or after merging:"
|
|
138
|
+
echo
|
|
139
|
+
while IFS= read -r f; do
|
|
140
|
+
[ -z "$f" ] && continue
|
|
141
|
+
echo "- \`$f\`"
|
|
142
|
+
done <<< "$CONFLICTS"
|
|
143
|
+
echo
|
|
144
|
+
else
|
|
145
|
+
echo "Merged cleanly — no conflicts."
|
|
146
|
+
echo
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
echo "## Upstream commits"
|
|
150
|
+
echo
|
|
151
|
+
git log --reverse --no-merges --pretty=format:'- [`%h`](https://github.com/reisxd/TizenTube/commit/%H) %s' "origin/main..upstream/${UPSTREAM_BRANCH}"
|
|
152
|
+
echo
|
|
153
|
+
echo
|
|
154
|
+
echo "_Opened automatically by \`.github/workflows/upstream-sync.yml\`._"
|
|
155
|
+
} > /tmp/pr-body.md
|
|
156
|
+
|
|
157
|
+
EXISTING=$(gh pr list --head "$SYNC_BRANCH" --state open --json number --jq '.[0].number // empty')
|
|
158
|
+
TITLE="Sync with upstream (${NEW_COMMITS} new commit(s))"
|
|
159
|
+
|
|
160
|
+
if [ -n "$EXISTING" ]; then
|
|
161
|
+
gh pr edit "$EXISTING" --title "$TITLE" --body-file /tmp/pr-body.md
|
|
162
|
+
echo "Updated PR #$EXISTING"
|
|
163
|
+
else
|
|
164
|
+
gh pr create --base main --head "$SYNC_BRANCH" --title "$TITLE" --body-file /tmp/pr-body.md
|
|
165
|
+
fi
|
package/AGENTS.md
CHANGED
|
@@ -788,6 +788,72 @@ install-blocked mode), and the user's hardware is an unconfirmed fit (has
|
|
|
788
788
|
a Samsung soundbar, not confirmed Q-Symphony-compatible). Ask before
|
|
789
789
|
implementing if this comes back up.
|
|
790
790
|
|
|
791
|
+
## Hard-won lessons (read before touching `mods/features/adblock.js`)
|
|
792
|
+
|
|
793
|
+
These cost real debugging time and are not obvious from the code. They are
|
|
794
|
+
recorded here rather than in any one contributor's notes so a fork inherits
|
|
795
|
+
them.
|
|
796
|
+
|
|
797
|
+
### There are two response-handling paths, and they are not shared code
|
|
798
|
+
|
|
799
|
+
YouTube delivers responses in two shapes, and `adblock.js` has a separate
|
|
800
|
+
handler for each:
|
|
801
|
+
|
|
802
|
+
- **array-root** → `processResponsePayload(payload, detectedPage)`
|
|
803
|
+
- **object-root** → the branch inside the patched `JSON.parse`
|
|
804
|
+
|
|
805
|
+
A filter added to one path and not the other works on some surfaces and
|
|
806
|
+
silently does nothing on others. This has bitten repeatedly: the array-root
|
|
807
|
+
grid handler was missing `filterShortsFromItems` and
|
|
808
|
+
`filterMembersOnlyFromItems`; `noteContinuationBatch` had to be hooked at
|
|
809
|
+
*both* continuation sites; `hideRelatedVideos` is called from both watch-next
|
|
810
|
+
sites.
|
|
811
|
+
|
|
812
|
+
When adding anything per-item or per-shelf, put the logic in its own module and
|
|
813
|
+
call it from both sites — `mods/features/sidebarChannelButton.js` is the shape
|
|
814
|
+
to copy — rather than duplicating the body. Grep for the sibling call site
|
|
815
|
+
before assuming one hook is enough.
|
|
816
|
+
|
|
817
|
+
### `JSON.parse` is wrapped by several modules, and order matters
|
|
818
|
+
|
|
819
|
+
`playlistContinue.js`, `playlistBatchCollect.js`, `adblock.js` and
|
|
820
|
+
`customGuideAction.js` each wrap `JSON.parse`, in that order (set by the import
|
|
821
|
+
order in `userScript.js`). Every wrapper calls through to whatever it captured
|
|
822
|
+
as the original, so they compose — but an early `return` added to any of them
|
|
823
|
+
silently swallows every wrapper installed before it.
|
|
824
|
+
|
|
825
|
+
`captionStylePersistence.js` independently wraps `resolveCommand` alongside
|
|
826
|
+
`resolveCommand.js`'s own patch. Same rule applies.
|
|
827
|
+
|
|
828
|
+
### A playlist continuation response must contain at least one item
|
|
829
|
+
|
|
830
|
+
YouTube's refill loop stops dead if a continuation comes back empty — loading
|
|
831
|
+
never resumes, even on scroll. `hideVideo` therefore deliberately keeps one
|
|
832
|
+
"helper" tile per continuation batch (`__ttKeepOneForContinuation`).
|
|
833
|
+
|
|
834
|
+
This was learned the hard way: PR #678 capped helpers at one per visit and
|
|
835
|
+
returned `[]` for the rest, and playlist loading stalled after two batches on
|
|
836
|
+
device. It was reverted in #679. If you change the helper logic, test a long,
|
|
837
|
+
mostly-watched playlist and confirm it still loads past batch 2.
|
|
838
|
+
|
|
839
|
+
### Tizen 5.0 has no usable Polymer element APIs
|
|
840
|
+
|
|
841
|
+
`yt-virtual-list` positions its rows by transform from its own data model, and
|
|
842
|
+
the Polymer APIs you would reach for to force a re-render are `undefined` on
|
|
843
|
+
Tizen 5.0. Every DOM-level attempt to collapse the blank slot left behind by a
|
|
844
|
+
removed helper tile failed for this reason — rows are recycled and carry their
|
|
845
|
+
previous inline styles, and helper tiles carry no video-id attribute to target
|
|
846
|
+
(the id exists only inside a thumbnail's `background-image` URL).
|
|
847
|
+
|
|
848
|
+
Blank helper slots are an accepted limitation. Don't re-litigate it at the DOM
|
|
849
|
+
layer without new evidence.
|
|
850
|
+
|
|
851
|
+
### Verifying that a change actually reached the bundle
|
|
852
|
+
|
|
853
|
+
`dist/userScript.js` is minified and Babel-transpiled: identifier names are
|
|
854
|
+
mangled, string literals survive. Grep for a distinctive **string literal**,
|
|
855
|
+
never a function name, and use `grep -a` — the bundle is detected as binary.
|
|
856
|
+
|
|
791
857
|
## Conventions this repo has established (follow these)
|
|
792
858
|
|
|
793
859
|
- New app identities (Tizen `package`/app id) must be unique, not reused
|
|
@@ -818,3 +884,15 @@ implementing if this comes back up.
|
|
|
818
884
|
mistake). If you need a per-dependency try/catch wrapper for
|
|
819
885
|
diagnostics, wrap each literal `require('x')` call individually rather
|
|
820
886
|
than passing the module name through a shared helper function.
|
|
887
|
+
- Never run the build by hand and commit the generated output (`dist/*`,
|
|
888
|
+
`standalone/service/dist/*`) alongside a source change. CI rebuilds and
|
|
889
|
+
commits it on version bump; doing it manually produces merge conflicts on
|
|
890
|
+
generated files for everyone branching off `main`. Build locally to check a
|
|
891
|
+
change compiles, then `git checkout -- dist/` before committing.
|
|
892
|
+
- Work on a branch and open a PR; don't push to `main`. Don't push further
|
|
893
|
+
commits onto a branch whose PR is already merged — the commits end up
|
|
894
|
+
orphaned. Check merge state before pushing to an existing branch.
|
|
895
|
+
- When porting an upstream commit, read it rather than applying it: upstream
|
|
896
|
+
code has shipped with operator-precedence bugs, dead branches behind early
|
|
897
|
+
returns, and renames that would reset this fork's stored settings. Fix them
|
|
898
|
+
in the port and say so in the PR.
|
package/README.md
CHANGED
|
@@ -54,12 +54,98 @@ If a run failed because of a bug in the workflow file itself and that's since be
|
|
|
54
54
|
|
|
55
55
|
# Features
|
|
56
56
|
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
-
|
|
57
|
+
Everything below is toggleable from the in-app settings menu (**green button** on
|
|
58
|
+
the remote, or `G` / `F2` / `2` when testing in Chrome). This fork carries a
|
|
59
|
+
number of features that upstream TizenTube does not — those are marked
|
|
60
|
+
**(fork)**.
|
|
61
|
+
|
|
62
|
+
Each row is one settings-menu entry; where an entry has its own sub-menu, its
|
|
63
|
+
options are described in the row rather than listed separately.
|
|
64
|
+
|
|
65
|
+
## Blocking and filtering
|
|
66
|
+
|
|
67
|
+
| Feature | What it does |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| Ad Block | Removes video ads, ad slots, and the masthead/banner ad on Home |
|
|
70
|
+
| [SponsorBlock](https://sponsor.ajay.app/) | Skips sponsor, intro, outro, self-promo, interaction, filler, preview and non-music segments. Each category can be set to auto-skip, skip manually, or ignore, with optional toasts. Highlights (jump to the video's main point) can be enabled separately |
|
|
71
|
+
| Hide End Screen Cards | Removes the suggested-video cards overlaid at the end of a video |
|
|
72
|
+
| "Includes paid promotion" overlay | Toggle the paid-promotion banner |
|
|
73
|
+
| Hide Members-Only Videos **(fork)** | Filters videos you can't watch without a channel membership out of shelves and grids |
|
|
74
|
+
| Hide Channel Shelves **(fork)** | Removes whole channel-recommendation shelves from feeds |
|
|
75
|
+
| Hide Feedback Surveys **(fork)** | Removes YouTube's in-feed "help us improve" survey cards |
|
|
76
|
+
| Hide Special Playlists **(fork)** | Hides Liked Videos and/or Watch Later from the Library and Playlists pages |
|
|
77
|
+
| Enable Shorts | Off by default — Shorts shelves and Shorts tiles are stripped from every surface |
|
|
78
|
+
|
|
79
|
+
## Watched-video handling
|
|
80
|
+
|
|
81
|
+
| Feature | What it does |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| Hide Watched Videos | Hides videos you've already watched. Configurable watched-percentage threshold, and per-page control over where it applies (Home, Search, Subscriptions, Channel pages, Library, individual playlists, History, Music, Gaming, More, Watch) |
|
|
84
|
+
| Playlist Batch Load **(fork)** | Loads a playlist's later batches up front instead of only as you scroll, so hide-watched can act on the whole playlist rather than the first ~30 items. The number of batches fetched is capped by a configurable limit |
|
|
85
|
+
|
|
86
|
+
## Video player
|
|
87
|
+
|
|
88
|
+
| Feature | What it does |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| Preferred Video Quality | Locks playback to a chosen quality (or the next best available) instead of letting YouTube pick |
|
|
91
|
+
| Preferred Video Codec | Prefer VP9, AV1 or AVC1 when the video offers a choice |
|
|
92
|
+
| Auto Frame Rate | Matches the TV's output frame rate to the video, with a configurable pause duration while it switches (Tizen only) |
|
|
93
|
+
| Spoof Viewport Resolution **(fork)** | Reports a different screen resolution to YouTube. Useful when the TV reports a lower resolution to the browser than it can actually decode. Requires an app restart |
|
|
94
|
+
| Speed Settings Increments | Sets the step size used by the playback-speed control |
|
|
95
|
+
| Picture-in-Picture / Mini Player | Both available from the player options popup; the two buttons can be swapped |
|
|
96
|
+
| Screen Off | Blanks the screen while audio keeps playing — for using the TV as a music player |
|
|
97
|
+
| Hide Related Videos in Player | Removes the related/suggested-videos rail that slides in over the player, so a nudge on the D-pad during playback doesn't cover the video with recommendations |
|
|
98
|
+
| Number Keys Jump to Percentage | Pressing `1`–`9` jumps to that percentage of the video, `0` jumps to the start |
|
|
99
|
+
| Reload Player After TV Wakes **(fork)** | Rebuilds the player after standby, fixing the frozen first frame |
|
|
100
|
+
| Player UI patching | Optional Previous/Next, Super Thanks, Ask, and Speed Controls buttons |
|
|
101
|
+
|
|
102
|
+
## Thumbnails and titles
|
|
103
|
+
|
|
104
|
+
| Feature | What it does |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| [DeArrow](https://dearrow.ajay.app/) | Community-sourced, non-clickbait titles, with optional DeArrow thumbnails |
|
|
107
|
+
| High Quality Thumbnails | Upgrades tile thumbnails to `hqdefault`/`sddefault` |
|
|
108
|
+
| Video Previews | Hover/focus previews on tiles |
|
|
109
|
+
| Disable Enlarged Thumbnails | Stops the focused tile from scaling up |
|
|
110
|
+
| Enable Shrinked Thumbnails | Shrinks unfocused tiles instead |
|
|
111
|
+
|
|
112
|
+
## Interface
|
|
113
|
+
|
|
114
|
+
| Feature | What it does |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| Customizable Themes | Custom focus-container and route colouring (**red button**) |
|
|
117
|
+
| Clock | On-screen clock, 12/24-hour, optional seconds, and an option to hide it while a video is playing |
|
|
118
|
+
| Screen Dimming | Dims the screen after a configurable idle timeout, at a configurable opacity |
|
|
119
|
+
| Disable Sidebar Contents | Choose which sidebar entries to hide |
|
|
120
|
+
| Disable Channels on Sidebar | Removes subscribed-channel entries from the sidebar |
|
|
121
|
+
| Launch To on Startup | Choose which page the app opens to |
|
|
122
|
+
| Reload Home on Startup | Forces a fresh Home feed on launch |
|
|
123
|
+
| Library Tabs Buttons to Hide **(fork)** | Hides individual Library tabs (Music, Movies & Shows, Podcasts, My Videos, History, Watch Later, Playlists) |
|
|
124
|
+
| Sort Subscriptions Alphabetically | Alphabetical instead of YouTube's own ordering |
|
|
125
|
+
| Long Press Actions | Long-press a tile for Play, Watch Later, Save to Playlist and Add to Queue |
|
|
126
|
+
| Who's Watching Menu | Control whether the profile picker appears, including on app exit, and whether it stays permanently enabled |
|
|
127
|
+
| "Are you still watching?" prompt | Toggle YouTube's idle-playback interruption |
|
|
128
|
+
| Show Guest Sign In Reminder | Toggle the prompt asking a signed-out viewer to sign in |
|
|
129
|
+
| Show TT Welcome Message | Toggle the TizenTube toast shown on launch |
|
|
130
|
+
| Fix UI | Layout corrections for TVs that render the YouTube TV UI incorrectly |
|
|
131
|
+
|
|
132
|
+
## Subtitles
|
|
133
|
+
|
|
134
|
+
| Feature | What it does |
|
|
135
|
+
| --- | --- |
|
|
136
|
+
| Show Local Subtitle | Surfaces subtitles in your own language |
|
|
137
|
+
| Show Hidden Subtitles | Exposes tracks YouTube hides from the picker |
|
|
138
|
+
| Remember Caption Style **(fork)** | Persists caption font/size/colour settings across sessions and restarts |
|
|
139
|
+
|
|
140
|
+
## Maintenance and diagnostics
|
|
141
|
+
|
|
142
|
+
| Feature | What it does |
|
|
143
|
+
| --- | --- |
|
|
144
|
+
| Updater | Checks for TizenTube updates, optionally on startup |
|
|
145
|
+
| Debug Console **(fork)** | On-screen log console (**yellow button**), with configurable corner position and height |
|
|
146
|
+
| Remote Log Server **(fork)** | Streams logs to a PC receiver for on-device debugging, with a built-in connection test |
|
|
147
|
+
|
|
148
|
+
Missing something? [Request it](https://github.com/reisxd/TizenTube/issues/new).
|
|
63
149
|
|
|
64
150
|
# Tampermonkey local debugging helpers (Windows + Chrome)
|
|
65
151
|
|