minulo は、WKWebView で開いた YouTube の /shorts/ID のページを /watch?v=ID に振り替え、ショートを縦のフィードではなくふつうの再生画面で開いています。設定名は[ショートを普通の再生画面で開く]で、ショートの棚とタブを隠す設定と並んでいます。この記事は、minulo を1人で作っている北林が書いています。
ショートだけ消して、ふつうの動画を残す方法はこちらの頁にまとめています:https://minulo.app/block-youtube-shorts.html?ref=qiita-1104
前提
- minulo は Instagram や YouTube などのウェブ版を WKWebView で開き、CSS と JS を入れてフィードやショートを隠しています。公式アプリの中は変えられません。
- 入れる JS は、ページの中の移動(pushState・replaceState・popstate)のたびに走る「sweep」の中で毎回実行されます。
ルールは宣言だけにする
振り替えのルールは、JS を手で書かずに正規表現と行き先だけを持たせています(src/rules/platforms.ts)。
{
labelKey: 'rule.yt.url',
paths: [/^\/shorts\//, /\/shorts\/?$/],
group: 'grp.yt.shorts',
optional: true,
redirect: { from: /^\/shorts\/([\w-]+)/, to: '/watch?v=$1' },
},
同じ形で、Threads と TikTok のトップ(/)を /following に振り替えるルールや、TikTok の[DM以外のタブ]で / などを /inbox に振り替えるルールも持っています。宣言にそろえておくと、振り替えの仕組みを1か所で直せます。
JS は String.raw で組み立てる
宣言から JS の文字列を作る関数(redirectJs)は、テンプレートリテラルを String.raw で書いています。素のテンプレートリテラルにすると、差し込む正規表現の \$ の \ が消えて /$([1-9])/ になり、$ が行末の意味になって1つも置換されなくなります。正規表現そのものを String(r.from) で埋め込むので、\/ や \w の \ も消えません。
往復の歯止め
振り替え先からサイトが元のページへ戻すことがあります(Threads のログアウト中に /following から / へ戻される、など)。そのままだと、読み込むたびに飛んで回り続けます。そこで次の歯止めを入れています。
- 同じ行き先へは、15秒に2回まで。行き先の文字列(?v= まで含む)ごとに sessionStorage に回数と時刻を残します。パスだけをキーにすると、ショートの3本目が差し替わりませんでした。
- 歯止めに掛かったら、そのタブではもう振り替えません。15秒たって往復を再開すると、ログアウト中の Threads が読み込み直しを繰り返したためです。
- 本人が画面に触れた直後(3秒以内)の移動は往復に数えません。pointerdown の時刻を残しておき、ホームのタブの2度押しなどで歯止めに掛からないようにしています。
- sessionStorage が使えない場面では、歯止め無しで飛びます。
- 移動は
location.replaceで行い、戻るボタンでショートのページに戻らないようにしています。
history を包まない
sweep は画面の中の移動のたびに呼ばれるので、その中で history.pushState を包むと、sweep のたびに包みが1枚ずつ増えます。長く開いているほど呼び出しが積み重なって固まるので、振り替えの JS の中では history に触らず、毎回 location を見て判断するだけにしています。
できないこと
- 公式の YouTube アプリの中のショートは変えられません。振り替えが効くのは minulo の中で開いた YouTube だけです。
- 設定を切ると、その場で振り替えが止まります(切ったルールの JS も入れておき、ページの側の OFF の表で止めています)。