diff --git a/Dockerfile b/Dockerfile index 98d4af4e..ee3410cf 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,4 @@ + # サードパーティーライブラリのダウンロードを行うステージ # 念のため最終イメージに合わせて ubuntu20.04 にしておく # 中間イメージなので、サイズは(ビルドするマシンのディスク容量以外は)気にしなくて良い @@ -28,7 +29,7 @@ RUN ln -s /usr/lib/x86_64-linux-gnu/libamfrt64.so /usr/lib/x86_64-linux-gnu/liba # サードパーティーライブラリをダウンロード WORKDIR /thirdparty -RUN aria2c -x10 https://github.com/tsukumijima/KonomiTV/releases/download/v0.4.0/thirdparty.7z +RUN aria2c -x10 https://github.com/tsukumijima/KonomiTV/releases/download/v0.5.0/thirdparty.7z RUN 7z x -y thirdparty.7z # サードパーティーライブラリに実行権限を付与 @@ -103,7 +104,7 @@ COPY ./server /code/server # ダウンロードしておいたサードパーティライブラリをコピー COPY --from=thirdparty-downloader /thirdparty/thirdparty /code/server/thirdparty -# client の成果物をコピー(dist だけで良い) +# client の成果物をコピー (dist だけで良い) COPY --from=client-builder /code/client/dist /code/client/dist # データベースを必要な場合にアップグレードし、起動 diff --git a/Readme.md b/Readme.md index 646cbfa0..c8b59a8b 100644 --- a/Readme.md +++ b/Readme.md @@ -30,34 +30,10 @@ 当然ながら表に泥臭い処理を見せないようにしている分、裏側の実装がそれなりに大変です。細かいところまで調整しているとかなりの手間がかかります。 それでも私が頑張れば私を含めたユーザーの視聴体験が向上するわけで、必要な犠牲かなと思っています。 -
- -## 備考・注意事項 - -- 現在 β 版で、まだ実験的なプロダクトです。当初よりかなり安定してきましたが、まだ保証ができる状態ではありません。 - - まだ安定しているとは言えませんが、それでも構わない方のみ導入してください。 - - 使い方などの説明も用意できていないため、自力でトラブルに対処できるエンジニアの方以外には現状おすすめできません。 - - 今後インストーラーを開発予定ですが、後述の通り現時点ではインストール方法がかなり煩雑になっています。他の環境でちゃんと動作するのかさえも微妙です。 - - 完成予想はおろか、TVRemotePlus で実装していた機能に関してもまだ完全にカバーできていないため、現時点で TVRemotePlus を代替できるレベルには達していません。 -- TVRemotePlus の後継という位置づけのソフトですが、それはあくまで「精神的な」ものであり、実際の技術スタックや UI/UX は完全に新規で設計されています。 - - 確かに TVRemotePlus の開発で得られた知見を数多く活用していますし開発者も同じではありますが、ユーザービリティや操作感は大きく異なると思います。 - - TVRemotePlus の技術スタックでは解決不可能なボトルネックを根本的に解消した上で、「同じものを作り直す」のではなく、ゼロから新しいテレビ視聴・録画視聴のユーザー体験を作り上げ、追求したいという想いから開発しています。 - - どちらかというと録画視聴機能の方がメインの予定でいますが、前述のとおり、現時点ではテレビのライブ視聴機能のみの実装です。構想は壮大ですが、全て実装し終えるには年単位で時間がかかるでしょう。 -- 今のところ、スマホ・タブレットは横画面表示のみ対応しています。将来的には縦画面でも崩れずに表示できるようにする予定です。 - - タブレットは Fire HD 10 (2021), iPad mini 4, iPad mini 6 で動作することを確認済みです。 - - スマホ(横画面)は実験的なもので、今後 UI が大幅に変更される可能性があります。 - - iPhone は Media Source Extensions API に対応していないため、現時点では動作しません。 - - 今後 LL-HLS 再生モードを実装する予定ですが、私が iPhone を常用していない事もあり、実装時期は未定です。 - - また、iPad でホーム画面に追加したアイコンから単独アプリのように起動した場合も (PWA)、同様に動作しません。 -- 今後、開発の過程で設定や構成が互換性なく大幅に変更される可能性があります。 -- ユーザービリティなどのフィードバック・不具合報告・Pull Requests (PR) などは歓迎します。 - - 技術スタックはサーバー側が Python + [FastAPI](https://github.com/tiangolo/fastapi) + [Tortoise ORM](https://github.com/tortoise/tortoise-orm) + [Uvicorn](https://github.com/encode/uvicorn) 、クライアント側が Vue.js + [Vuetify](https://github.com/vuetifyjs/vuetify) の SPA です。 - - Vuetify は補助的に利用しているだけで、大部分は独自で書いた SCSS スタイルを適用しています。 - - コメントを多めに書いたりそれなりにきれいにコーディングしているつもりなので、少なくとも TVRemotePlus なんかよりかは読みやすいコードになっている…はず。 - - 他人が見るために書いたものではないのであれですが、一応自分用の [開発資料](https://mango-garlic-eff.notion.site/KonomiTV-90f4b25555c14b9ba0cf5498e6feb1c3) と [DB設計](https://mango-garlic-eff.notion.site/KonomiTV-544e02334c89420fa24804ec70f46b6d) 的なメモを公開しておきます。もし PR される場合などの参考になれば。 - ## 動作環境 +
+ ### サーバー - **Windows PC または Linux PC** @@ -89,11 +65,35 @@ - PWA モードでは Safari 側のバグにより、テレビのライブストリーミングに失敗します。 - 前述のとおり、iOS Safari への対応は当面の間行いません。 -
+## 備考・注意事項 + +- 現在 β 版で、まだ実験的なプロダクトです。当初よりかなり安定してきましたが、まだ保証ができる状態ではありません。 + - まだ安定しているとは言えませんが、それでも構わない方のみ導入してください。 + - 使い方などの説明も用意できていないため、自力でトラブルに対処できるエンジニアの方以外には現状おすすめできません。 + - 今後インストーラーを開発予定ですが、後述の通り現時点ではインストール方法がかなり煩雑になっています。他の環境でちゃんと動作するのかさえも微妙です。 + - 完成予想はおろか、TVRemotePlus で実装していた機能に関してもまだ完全にカバーできていないため、現時点で TVRemotePlus を代替できるレベルには達していません。 +- TVRemotePlus の後継という位置づけのソフトですが、それはあくまで精神的なものであり、実際の技術スタックや UI/UX はゼロから設計されています。 + - 確かに TVRemotePlus の開発で得られた知見を数多く活用していますし開発者も同じではありますが、ユーザービリティや操作感は大きく異なると思います。 + - TVRemotePlus の技術スタックでは解決不可能なボトルネックを根本的に解消した上で、「同じものを作り直す」のではなく、ゼロから新しいテレビ視聴・録画視聴のユーザー体験を作り上げ、追求したいという想いから開発しています。 + - どちらかというと録画視聴機能の方がメインの予定でいますが、前述のとおり、現時点ではテレビのライブ視聴機能のみの実装です。構想は壮大ですが、全て実装し終えるには年単位で時間がかかるでしょう。 +- 今のところ、スマホ・タブレットは横画面表示のみ対応しています。将来的には縦画面でも崩れずに表示できるようにする予定です。 + - タブレットは Fire HD 10 (2021), iPad mini 4, iPad mini 6 で動作することを確認済みです。 + - スマホ(横画面)は実験的なもので、今後 UI が大幅に変更される可能性があります。 + - iPhone は Media Source Extensions API に対応していないため、現時点では動作しません。 + - 今後 LL-HLS 再生モードを実装する予定ですが、私が iPhone を常用していない事もあり、実装時期は未定です。 + - また、iPad でホーム画面に追加したアイコンから単独アプリのように起動した場合も (PWA)、同様に動作しません。 +- 今後、開発の過程で設定や構成が互換性なく大幅に変更される可能性があります。 +- ユーザービリティなどのフィードバック・不具合報告・Pull Requests (PR) などは歓迎します。 + - 技術スタックはサーバー側が Python + [FastAPI](https://github.com/tiangolo/fastapi) + [Tortoise ORM](https://github.com/tortoise/tortoise-orm) + [Uvicorn](https://github.com/encode/uvicorn) 、クライアント側が Vue.js + [Vuetify](https://github.com/vuetifyjs/vuetify) の SPA です。 + - Vuetify は補助的に利用しているだけで、大部分は独自で書いた SCSS スタイルを適用しています。 + - コメントを多めに書いたりそれなりにきれいにコーディングしているつもりなので、少なくとも TVRemotePlus なんかよりかは読みやすいコードになっている…はず。 + - 他人が見るために書いたものではないのであれですが、一応自分用の [開発資料](https://mango-garlic-eff.notion.site/KonomiTV-90f4b25555c14b9ba0cf5498e6feb1c3) と [DB設計](https://mango-garlic-eff.notion.site/KonomiTV-544e02334c89420fa24804ec70f46b6d) 的なメモを公開しておきます。もし PR される場合などの参考になれば。 ## 事前準備 -### ドライバ +
+ +### チューナーのドライバ変更 必須ではありませんが、Windows で PLEX 製チューナーを利用している場合は、事前にドライバを [px4_drv for WinUSB](https://github.com/tsukumijima/px4_drv) に変更しておくことを推奨します。 px4_drv では公式ドライバと比べてチューナーの起動時間が大幅に短縮されています。その分 KonomiTV での視聴までにかかる待機時間も速くなるため(5秒以上速くなる)、より快適に使えます。 @@ -154,10 +154,10 @@ Mirakurun または EDCB から局ロゴを取得できなかった場合は、 > 同梱されているロゴは `server/data/logo/` に `NID(ネットワークID)-SID(サービスID).png` として、256×256 のフォーマットで保存されています。 > チャンネルのネットワーク ID とサービス ID がわかっていれば、自分で局ロゴ画像を作ることも可能です。 -
- ## インストール方法(暫定) +
+ 以下は暫定的なインストール方法です。将来的にはインストーラーでインストールできるようにする予定ですが、現時点では煩雑な手順になっています。 すべての環境でこの通りに進めて動くとは限りません。保証もできないので、すべて自己責任のもとでお願いします。 @@ -184,7 +184,7 @@ VCEEncC に関しても対応済みのつもりですが、手元に環境がな 事前に、後述の設定ファイルの編集を行ってください。最低でも config.yaml が存在する状態にしておく必要があります。 -あとは他のソフトウェアと同様に、`docker-compose up` を実行するだけで、KonomiTV のサーバーが起動します。他のインストール手順は実行不要です。 +あとは他のソフトウェアと同様に、`docker-compose up` を実行するだけで、KonomiTV のサーバーが起動します。これでインストールは完了です。 バックグラウンドで常時起動させたいときは、`docker-compose up -d` と実行してください。 ### 1. pipenv のインストール @@ -314,10 +314,10 @@ rm ./data/database.sqlite pipenv run aerich upgrade ``` -
- ### 6. 設定ファイルの編集 +
+ ここまで手順通りにやっていれば Readme.md のあるフォルダに config.example.yaml があるはずなので、**同じ階層に config.yaml としてコピーします。** 設定ファイルは YAML ですが、JSON のようなスタイルで書いています。括弧がないとわかりにくいと思うので… @@ -385,10 +385,10 @@ API ドキュメント (Swagger) は http://localhost:7000/api/docs にありま とはいえ最低限視聴できる状態にはなっているはずです。まずは使ってみて、もしよければ感想をお聞かせください。 -
- ## 開発者向け情報 +
+ ### サーバー Uvicorn は ASGI サーバーで、FastAPI で書かれた KonomiTV のアプリケーションサーバーを実行します。 @@ -413,6 +413,14 @@ API サーバーは別のポート (7000) でリッスンされているので クライアントの静的ファイルは、`client/dist/` に配置されているビルド済みのものをサーバー側で配信するように設定されています。 そのため、`yarn build` でクライアントのビルドを更新したのなら、サーバー側で配信されるファイルも同時に更新されることになります。 +## Special Thanks + +- [xtne6f](https://github.com/xtne6f) さん: KonomiTV と EDCB を連携するための実装や、[tsreadex](https://github.com/xtne6f/tsreadex) の実装の依頼・開発などで多大なご協力をいただきました。 +- [rigaya](https://github.com/rigaya) さん: QSVEncC・NVEncC・VCEEncC での動作オプションや不具合の対応、エンコードパラメーターのアドバイスなどを支援していただきました。 +- [xqq](https://github.com/xqq/mpegts.js) さん: [mpegts.js](https://github.com/xqq/mpegts.js) で MPEG-TS をダイレクトストリーミングできるようになり、わずか最短 1.5 秒の低遅延でテレビを視聴することができるようになりました。mpegts.js のヘルプやプレイヤーへの導入のサポートなども支援していただきました。 + +KonomiTV の開発にあたり、ほかにも多くの方からサポートやフィードバックをいただきました。この場をお借りして厚く感謝申し上げます。 + ## License [MIT License](License.txt) diff --git a/client/dist/assets/css/app.7b2ec17c.css b/client/dist/assets/css/app.7b2ec17c.css new file mode 100644 index 00000000..f62b0d3e --- /dev/null +++ b/client/dist/assets/css/app.7b2ec17c.css @@ -0,0 +1 @@ +html{overflow-y:auto!important}body .v-application{min-height:100vh;font-family:YakuHanJPs,Open Sans,Hiragino Sans,Noto Sans JP,sans-serif;font-weight:500;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@supports(-webkit-touch-callout:none){body .v-application{min-height:-webkit-fill-available}}body .v-application .v-application--wrap{min-height:100%!important}body main{display:flex;width:100%;min-height:100%}body header+main{padding-top:65px!important}@media screen and (max-height:450px){body header+main{padding-top:48px!important}}body .route-container{height:100%;background:var(--v-background-base)}.v-popper--theme-tooltip .v-popper__inner{display:inline-block;padding:4px 10px;border-radius:4px;background:rgba(47,34,31,.7529411764705882);color:var(--v-text-base);font-size:12px;font-family:YakuHanJPs,Open Sans,Hiragino Sans,Noto Sans JP,sans-serif;font-weight:500;opacity:.9;line-height:22px}.v-popper--theme-tooltip .v-popper__arrow-container{display:none}@media(hover:none){:hover:before{background-color:transparent!important}}::-moz-selection{background-color:rgba(230,79,151,.5019607843137255)}::selection{background-color:rgba(230,79,151,.5019607843137255)}.decorate-symbol{display:inline-flex;justify-content:center;align-items:center;position:relative;padding:0 3px;margin-left:2.5px;margin-right:2.5px;border-radius:4px;color:var(--v-text-base);background:var(--v-primary-base);font-size:.94em}*{scrollbar-color:var(--v-gray-base) var(--v-background-base);scrollbar-width:thin}::-webkit-scrollbar{width:7px;height:7px}::-webkit-scrollbar-track{background:var(--v-background-base)}::-webkit-scrollbar-thumb{background:var(--v-background-lighten2)}::-webkit-scrollbar-thumb:hover{background:var(--v-gray-base)}.v-menu__content::-webkit-scrollbar{width:12px;height:12px}.v-menu__content::-webkit-scrollbar-thumb{border:solid 3.5px var(--v-background-base)}.v-enter-active,.v-leave-active{transition:opacity .3s}.v-enter,.v-leave-to{opacity:0}.v-enter-active.route-container{position:fixed;top:0;left:0;right:0}.w-25{width:25%}.w-50{width:50%}.w-75{width:75%}.w-100{width:100%}.h-25{height:25%}.h-50{height:50%}.h-75{height:75%}.h-100{height:100%}body .v-toolbar.header{position:fixed;height:65px!important;z-index:10}body .v-toolbar.header .v-toolbar__content{height:65px!important}@media screen and (max-height:450px){body .v-toolbar.header,body .v-toolbar.header .v-toolbar__content{height:48px!important}}body .v-toolbar.header .logo{padding:12px 8px;border-radius:8px}body .v-toolbar.header .logo__image{display:block}@media screen and (max-height:450px){body .v-toolbar.header .logo__image{height:19.5px}}.navigation-container[data-v-4fdece88]{flex-shrink:0;width:220px;background:var(--v-background-lighten1)}@media screen and (max-height:450px){.navigation-container[data-v-4fdece88]{width:210px}}.navigation-container .navigation[data-v-4fdece88]{position:fixed;width:220px;top:65px;left:0;bottom:-100px;padding-bottom:100px;background:var(--v-background-lighten1);z-index:1}@media screen and (max-height:450px){.navigation-container .navigation[data-v-4fdece88]{top:48px;width:210px}}.navigation-container .navigation .navigation-scroll[data-v-4fdece88]{display:flex;flex-direction:column;height:100%;padding:22px 12px;overflow-y:auto}@media screen and (max-height:450px){.navigation-container .navigation .navigation-scroll[data-v-4fdece88]{padding:20px 12px}}.navigation-container .navigation .navigation-scroll[data-v-4fdece88]::-webkit-scrollbar-track{background:var(--v-background-lighten1)}.navigation-container .navigation .navigation-scroll .navigation__link[data-v-4fdece88]{display:flex;align-items:center;flex-shrink:0;height:52px;padding-left:16px;padding-right:16px;margin-top:4px;border-radius:11px;font-size:16px;color:var(--v-text-base);transition:background-color .15s;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.navigation-container .navigation .navigation-scroll .navigation__link[data-v-4fdece88]{height:44px;padding-left:12px;padding-right:12px;font-size:15px}}.navigation-container .navigation .navigation-scroll .navigation__link[data-v-4fdece88]:hover{background:var(--v-background-lighten2)}.navigation-container .navigation .navigation-scroll .navigation__link[data-v-4fdece88]:first-of-type{margin-top:0}.navigation-container .navigation .navigation-scroll .navigation__link--active[data-v-4fdece88]{color:var(--v-primary-base);background:#5b2d3c}.navigation-container .navigation .navigation-scroll .navigation__link--active[data-v-4fdece88]:hover{background:#5b2d3c}.navigation-container .navigation .navigation-scroll .navigation__link .navigation__link-icon[data-v-4fdece88]{margin-right:14px}@media screen and (max-height:450px){.navigation-container .navigation .navigation-scroll .navigation__link .navigation__link-icon[data-v-4fdece88]{margin-right:10px}}.channels-container.channels-container--home .v-tabs-bar{height:54px;background:linear-gradient(180deg,var(--v-background-base) calc(100% - 3px),var(--v-background-lighten1) 3px)}@media screen and (max-height:450px){.channels-container.channels-container--home .v-tabs-bar{height:46px}}.channels-container.channels-container--home .v-tabs-slider-wrapper{height:3px!important;transition:left .3s cubic-bezier(.25,.8,.5,1)}.channels-container.channels-container--home .v-window__container{min-height:calc(100vh - 180px)}@media(hover:none){.channels-container.channels-container--home .v-window__container{min-height:auto}}:root .channels-container.channels-container--home .v-window__container,_::-webkit-full-page-media,_:future{height:inherit!important;-webkit-transition:none!important;transition:none!important}:root .channels-container.channels-container--home .v-window__container--is-active,_::-webkit-full-page-media,_:future{display:none!important}:root .channels-container.channels-container--home .v-window__container .v-window-item,_::-webkit-full-page-media,_:future{display:none!important;position:static!important;transform:none!important;-webkit-transition:none!important;transition:none!important}:root .channels-container.channels-container--home .v-window__container .v-window-item--active,_::-webkit-full-page-media,_:future{display:block!important}.channels-container[data-v-6a407b07]{display:flex;flex-direction:column;width:100%;margin-left:21px;margin-right:21px;opacity:1;transition:opacity .4s}.channels-container--loading[data-v-6a407b07]{opacity:0}.channels-container .channels-tab[data-v-6a407b07]{position:sticky;flex:none;top:65px;padding-top:10px;padding-bottom:20px;background:var(--v-background-base);z-index:1}@media screen and (max-height:450px){.channels-container .channels-tab[data-v-6a407b07]{top:47.9px;padding-top:2px;padding-bottom:12px}}.channels-container .channels-tab .channels-tab__item[data-v-6a407b07]{width:98px;padding:0;color:var(--v-text-base)!important;font-size:16px;text-transform:none}@media screen and (max-height:450px){.channels-container .channels-tab .channels-tab__item[data-v-6a407b07]{font-size:15px}}.channels-container .channels-list[data-v-6a407b07]{padding-bottom:32px;background:transparent!important;overflow:inherit}@media screen and (max-height:450px){.channels-container .channels-list[data-v-6a407b07]{padding-bottom:22px}}.channels-container .channels-list .channels[data-v-6a407b07]{display:grid;grid-template-columns:repeat(auto-fit,minmax(365px,1fr));grid-row-gap:16px;grid-column-gap:16px;justify-content:center;background:var(--v-background-base);will-change:transform}@media screen and (min-width:1630px){.channels-container .channels-list .channels[data-v-6a407b07]{grid-template-columns:repeat(auto-fit,445px)}}.channels-container .channels-list .channels.channels--length-0.channels--tab-ピン留め[data-v-6a407b07]{display:flex;min-height:calc(100vh - 180px)}@media screen and (min-width:1008px){.channels-container .channels-list .channels.channels--length-1[data-v-6a407b07]{margin-right:calc(50% + 8px)}}@media screen and (min-width:1389px){.channels-container .channels-list .channels.channels--length-1[data-v-6a407b07]{margin-right:calc(66.66667% + 10.66667px)}}@media screen and (min-width:1630px){.channels-container .channels-list .channels.channels--length-1[data-v-6a407b07]{margin-right:922px}}@media screen and (min-width:2090px){.channels-container .channels-list .channels.channels--length-1[data-v-6a407b07]{margin-right:1383px}}@media screen and (min-width:1389px){.channels-container .channels-list .channels.channels--length-2[data-v-6a407b07]{margin-right:calc(33.33333% + 5.33333px)}}@media screen and (min-width:1630px){.channels-container .channels-list .channels.channels--length-2[data-v-6a407b07]{margin-right:461px}}@media screen and (min-width:2090px){.channels-container .channels-list .channels.channels--length-2[data-v-6a407b07]{margin-right:922px}}@media screen and (min-width:2090px){.channels-container .channels-list .channels.channels--length-3[data-v-6a407b07]{margin-right:461px}}.channels-container .channels-list .channels .channel[data-v-6a407b07]{display:flex;flex-direction:column;position:relative;height:275px;padding:19px 22px;border-radius:16px;color:var(--v-text-base);background:var(--v-background-lighten1);transition:background-color .15s;overflow:hidden;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}@media screen and (max-width:1007.9px){.channels-container .channels-list .channels .channel[data-v-6a407b07]{height:auto}}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel[data-v-6a407b07]{padding:15px 18px;height:auto;border-radius:15px}}.channels-container .channels-list .channels .channel[data-v-6a407b07]:hover{background:var(--v-background-lighten2)}@media(hover:none){.channels-container .channels-list .channels .channel[data-v-6a407b07]:hover{background:var(--v-background-lighten1)}}.channels-container .channels-list .channels .channel .channel__broadcaster[data-v-6a407b07]{display:flex;height:44px}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__broadcaster[data-v-6a407b07]{height:38px}}.channels-container .channels-list .channels .channel .channel__broadcaster-icon[data-v-6a407b07]{display:inline-block;flex-shrink:0;width:80px;height:44px;border-radius:5px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__broadcaster-icon[data-v-6a407b07]{width:64px;height:38px}}.channels-container .channels-list .channels .channel .channel__broadcaster-content[data-v-6a407b07]{display:flex;flex-direction:column;margin-left:16px;width:100%;min-width:0}.channels-container .channels-list .channels .channel .channel__broadcaster-name[data-v-6a407b07]{flex-shrink:0;font-size:18px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__broadcaster-name[data-v-6a407b07]{font-size:15px}}.channels-container .channels-list .channels .channel .channel__broadcaster-status[data-v-6a407b07]{display:flex;align-items:center;margin-top:2px;font-size:12px;color:var(--v-text-darken1)}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__broadcaster-status[data-v-6a407b07]{font-size:10px;margin-top:3px}}.channels-container .channels-list .channels .channel .channel__broadcaster-status-force[data-v-6a407b07],.channels-container .channels-list .channels .channel .channel__broadcaster-status-viewers[data-v-6a407b07]{display:flex;align-items:center}.channels-container .channels-list .channels .channel .channel__broadcaster-status-force--festival[data-v-6a407b07]{color:#e7556e}.channels-container .channels-list .channels .channel .channel__broadcaster-status-force--so-many[data-v-6a407b07]{color:#e76b55}.channels-container .channels-list .channels .channel .channel__broadcaster-status-force--many[data-v-6a407b07]{color:#e7a355}.channels-container .channels-list .channels .channel .channel__broadcaster-pin[data-v-6a407b07]{display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;top:-5px;right:-5px;width:34px;height:34px;padding:4px;color:var(--v-text-darken1);border-radius:50%;transition:color .15s ease,background-color .15s ease;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.channels-container .channels-list .channels .channel .channel__broadcaster-pin[data-v-6a407b07]:before{background-color:currentColor;border-radius:inherit;bottom:0;color:inherit;content:"";left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:0;transition:opacity .2s cubic-bezier(.4,0,.6,1)}.channels-container .channels-list .channels .channel .channel__broadcaster-pin[data-v-6a407b07]:hover{color:var(--v-text-base)}.channels-container .channels-list .channels .channel .channel__broadcaster-pin[data-v-6a407b07]:hover:before{opacity:.15}.channels-container .channels-list .channels .channel .channel__broadcaster-pin--pinned[data-v-6a407b07]{color:var(--v-primary-base)}.channels-container .channels-list .channels .channel .channel__broadcaster-pin--pinned[data-v-6a407b07]:hover{color:var(--v-primary-lighten1)}.channels-container .channels-list .channels .channel .channel__program-present[data-v-6a407b07]{display:flex;flex-direction:column}.channels-container .channels-list .channels .channel .channel__program-present-title[data-v-6a407b07]{display:-webkit-box;margin-top:14px;font-size:16px;font-weight:700;font-feature-settings:"palt" 1;letter-spacing:.07em;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-present-title[data-v-6a407b07]{margin-top:10px;font-size:14.5px;-webkit-line-clamp:1}}.channels-container .channels-list .channels .channel .channel__program-present-time[data-v-6a407b07]{margin-top:4px;color:var(--v-text-darken1);font-size:13.5px}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-present-time[data-v-6a407b07]{font-size:12px}}.channels-container .channels-list .channels .channel .channel__program-present-description[data-v-6a407b07]{display:-webkit-box;margin-top:8px;color:var(--v-text-darken1);font-size:10.5px;line-height:175%;overflow-wrap:break-word;font-feature-settings:"palt" 1;letter-spacing:.07em;overflow:hidden;-webkit-line-clamp:3;-webkit-box-orient:vertical}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-present-description[data-v-6a407b07]{margin-top:8px;font-size:10px;-webkit-line-clamp:2}}.channels-container .channels-list .channels .channel .channel__program-following[data-v-6a407b07]{display:flex;flex-direction:column;color:var(--v-text-base);font-size:12.5px}@media screen and (max-width:1007.9px){.channels-container .channels-list .channels .channel .channel__program-following[data-v-6a407b07]{margin-top:6px}}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-following[data-v-6a407b07]{margin-top:6px;font-size:12px}}.channels-container .channels-list .channels .channel .channel__program-following-title[data-v-6a407b07]{display:flex;align-items:center}.channels-container .channels-list .channels .channel .channel__program-following-title-decorate[data-v-6a407b07]{flex-shrink:0;font-weight:700}.channels-container .channels-list .channels .channel .channel__program-following-title-icon[data-v-6a407b07]{flex-shrink:0;margin-left:3px}.channels-container .channels-list .channels .channel .channel__program-following-title-text[data-v-6a407b07]{margin-left:2px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.channels-container .channels-list .channels .channel .channel__program-following-time[data-v-6a407b07]{color:var(--v-text-darken1)}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-following-time[data-v-6a407b07]{font-size:11.5px}}.channels-container .channels-list .channels .channel .channel__progressbar[data-v-6a407b07]{position:absolute;left:0;right:0;bottom:0;height:4px;background:var(--v-gray-base)}.channels-container .channels-list .channels .channel .channel__progressbar-progress[data-v-6a407b07]{height:4px;background:var(--v-primary-base);transition:width .3s}.channels-container.channels-container--watch .v-tabs-bar{position:relative;top:-9px;height:48px;background:linear-gradient(180deg,var(--v-background-base) calc(100% - 3px),var(--v-background-lighten1) 3px)}@media screen and (max-height:450px){.channels-container.channels-container--watch .v-tabs-bar{top:-7px;height:40px}}.channels-container.channels-container--watch .v-tabs-bar .v-slide-group__next,.channels-container.channels-container--watch .v-tabs-bar .v-slide-group__prev{flex:auto!important;min-width:28px!important}.channels-container.channels-container--watch .v-tabs-slider-wrapper{height:3px!important;transition:left .3s cubic-bezier(.25,.8,.5,1)}:root .channels-container.channels-container--watch .v-window__container,_::-webkit-full-page-media,_:future{height:inherit!important;-webkit-transition:none!important;transition:none!important}:root .channels-container.channels-container--watch .v-window__container--is-active,_::-webkit-full-page-media,_:future{display:none!important}:root .channels-container.channels-container--watch .v-window__container .v-window-item,_::-webkit-full-page-media,_:future{display:none!important;position:static!important;transform:none!important;-webkit-transition:none!important;transition:none!important}:root .channels-container.channels-container--watch .v-window__container .v-window-item--active,_::-webkit-full-page-media,_:future{display:block!important}.channels-container[data-v-691b389f]{display:flex;flex-direction:column}.channels-container .channels-tab[data-v-691b389f]{position:sticky;flex:none;top:0;padding-left:16px;padding-right:16px;padding-bottom:9px;background:var(--v-background-base);z-index:1}@media screen and (max-height:450px){.channels-container .channels-tab[data-v-691b389f]{padding-bottom:7px;margin-top:12px}}.channels-container .channels-tab .channels-tab__item[data-v-691b389f]{width:88px;padding:0;color:var(--v-text-base)!important;font-size:15px;text-transform:none}@media screen and (max-height:450px){.channels-container .channels-tab .channels-tab__item[data-v-691b389f]{font-size:14.5px}}.channels-container .channels-list-container[data-v-691b389f]{overflow-y:auto}.channels-container .channels-list-container .channels-list[data-v-691b389f]{padding-left:16px;padding-right:10px;padding-bottom:16px;background:transparent!important;overflow:visible!important}.channels-container .channels-list-container .channels-list .channels[data-v-691b389f]{display:flex;justify-content:center;flex-direction:column;will-change:transform}@media screen and (min-width:1630px){.channels-container .channels-list-container .channels-list .channels[data-v-691b389f]{grid-template-columns:repeat(auto-fit,445px)}}.channels-container .channels-list-container .channels-list .channels .channel[data-v-691b389f]{display:flex;flex-direction:column;position:relative;margin-top:12px;padding:10px 12px 14px 12px;border-radius:11px;color:var(--v-text-base);background:var(--v-background-lighten1);transition:background-color .15s;overflow:hidden;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}.channels-container .channels-list-container .channels-list .channels .channel[data-v-691b389f]:first-of-type{margin-top:0}.channels-container .channels-list-container .channels-list .channels .channel[data-v-691b389f]:hover{background:var(--v-background-lighten2)}@media(hover:none){.channels-container .channels-list-container .channels-list .channels .channel[data-v-691b389f]:hover{background:var(--v-background-lighten1)}}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster[data-v-691b389f]{display:flex;height:28px}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-icon[data-v-691b389f]{display:inline-block;flex-shrink:0;width:48px;height:100%;border-radius:4px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-content[data-v-691b389f]{display:flex;align-items:center;margin-left:12px;width:100%;min-width:0}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-name[data-v-691b389f]{font-size:14.5px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-force[data-v-691b389f]{display:flex;align-items:center;flex-shrink:0;margin-top:2px;margin-left:auto;padding-left:6px;font-size:12px;color:var(--v-text-darken1)}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-force--festival[data-v-691b389f]{color:#e7556e}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-force--so-many[data-v-691b389f]{color:#e76b55}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-force--many[data-v-691b389f]{color:#e7a355}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-present[data-v-691b389f]{display:flex;flex-direction:column}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-present-title[data-v-691b389f]{display:-webkit-box;margin-top:8px;font-size:13.5px;font-weight:700;font-feature-settings:"palt" 1;letter-spacing:.07em;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-present-time[data-v-691b389f]{margin-top:4px;color:var(--v-text-darken1);font-size:11.5px}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following[data-v-691b389f]{display:flex;flex-direction:column;margin-top:4px;color:var(--v-text-darken1);font-size:11.5px}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-title[data-v-691b389f]{display:flex;align-items:center}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-title-decorate[data-v-691b389f]{flex-shrink:0}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-title-icon[data-v-691b389f]{flex-shrink:0;margin-left:3px}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-title-text[data-v-691b389f]{margin-left:2px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-time[data-v-691b389f]{margin-top:1px}.channels-container .channels-list-container .channels-list .channels .channel .channel__progressbar[data-v-691b389f]{position:absolute;left:0;right:0;bottom:0;height:4px;background:var(--v-gray-base)}.channels-container .channels-list-container .channels-list .channels .channel .channel__progressbar-progress[data-v-691b389f]{height:4px;background:var(--v-primary-base);transition:width .3s}.comment-container[data-v-7575b645]{display:flex;flex-direction:column}.comment-container .comment-header[data-v-7575b645]{display:flex;align-items:center;flex-shrink:0;width:100%;height:26px;padding-left:16px;padding-right:16px}@media screen and (max-height:450px){.comment-container .comment-header[data-v-7575b645]{margin-top:12px}}.comment-container .comment-header__title[data-v-7575b645]{display:flex;align-items:center;font-size:18.5px;font-weight:700;line-height:145%}@media screen and (max-height:450px){.comment-container .comment-header__title[data-v-7575b645]{font-size:16.5px}}.comment-container .comment-header__title-icon[data-v-7575b645]{margin-bottom:-3px}@media screen and (max-height:450px){.comment-container .comment-header__title-icon[data-v-7575b645]{height:17.5px}}.comment-container .comment-header__title-text[data-v-7575b645]{margin-left:12px}.comment-container .comment-header__button[data-v-7575b645]{display:flex;align-items:center;height:26px;padding:0 9px;border-radius:4px;background:var(--v-background-lighten3);font-size:11px;line-height:1.8;letter-spacing:0}.comment-container .comment-list[data-v-7575b645]{width:100%;height:100%;margin-top:16px;padding-left:16px;padding-right:10px;padding-bottom:12px;overflow-y:scroll!important}@media screen and (max-height:450px){.comment-container .comment-list[data-v-7575b645]{margin-top:12px}}.comment-container .comment-list .comment[data-v-7575b645]{display:flex;align-items:center;min-height:28px;padding-top:6px;word-break:break-all}.comment-container .comment-list .comment__text[data-v-7575b645]{font-size:13px}.comment-container .comment-list .comment__time[data-v-7575b645]{flex-shrink:0;margin-left:auto;padding-left:8px;color:var(--v-text-darken1);font-size:13px}.comment-container .comment-scroll-button[data-v-7575b645]{display:flex;align-items:center;justify-content:center;position:absolute;left:0;right:0;bottom:22px;width:42px;height:42px;margin:0 auto;border-radius:50%;background:var(--v-primary-base);transition:background-color .15s,opacity .3s,visibility .3s;visibility:hidden;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}.comment-container .comment-scroll-button--display[data-v-7575b645]{opacity:1;visibility:visible}.program-container[data-v-00e07beb]{padding-left:16px;padding-right:16px;overflow-y:auto}.program-container .program-broadcaster[data-v-00e07beb]{display:none;align-items:center;min-width:0}@media screen and (max-height:450px){.program-container .program-broadcaster[data-v-00e07beb]{display:flex;margin-top:16px}}.program-container .program-broadcaster__icon[data-v-00e07beb]{display:inline-block;flex-shrink:0;width:43px;height:24px;border-radius:3px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.program-container .program-broadcaster__icon[data-v-00e07beb]{width:42px;height:23.5px}}.program-container .program-broadcaster__number[data-v-00e07beb]{flex-shrink:0;margin-left:12px;font-size:16.5px}.program-container .program-broadcaster__name[data-v-00e07beb]{margin-left:5px;font-size:16.5px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.program-container .program-info .program-info__title[data-v-00e07beb]{font-size:22px;font-weight:700;line-height:145%;font-feature-settings:"palt" 1;letter-spacing:.05em}@media screen and (max-height:450px){.program-container .program-info .program-info__title[data-v-00e07beb]{margin-top:10px;font-size:18px}}.program-container .program-info .program-info__time[data-v-00e07beb]{margin-top:8px;color:var(--v-text-darken1);font-size:14px}@media screen and (max-height:450px){.program-container .program-info .program-info__time[data-v-00e07beb]{font-size:13px}}.program-container .program-info .program-info__description[data-v-00e07beb]{margin-top:12px;color:var(--v-text-darken1);font-size:12px;line-height:168%;overflow-wrap:break-word;font-feature-settings:"palt" 1;letter-spacing:.08em}@media screen and (max-height:450px){.program-container .program-info .program-info__description[data-v-00e07beb]{margin-top:8px;font-size:11px}}.program-container .program-info .program-info__genre-container[data-v-00e07beb]{display:flex;flex-wrap:wrap;margin-top:10px}.program-container .program-info .program-info__genre-container .program-info__genre[data-v-00e07beb]{display:inline-block;font-size:10.5px;padding:3px;margin-top:4px;margin-right:4px;border-radius:4px;background:var(--v-background-lighten2)}@media screen and (max-height:450px){.program-container .program-info .program-info__genre-container .program-info__genre[data-v-00e07beb]{font-size:9px}}.program-container .program-info .program-info__next[data-v-00e07beb]{display:flex;align-items:center;margin-top:18px;color:var(--v-text-base);font-size:14px;font-weight:700}@media screen and (max-height:450px){.program-container .program-info .program-info__next[data-v-00e07beb]{margin-top:14px;font-size:13px}}.program-container .program-info .program-info__next-decorate[data-v-00e07beb]{flex-shrink:0}.program-container .program-info .program-info__next-icon[data-v-00e07beb]{flex-shrink:0;margin-left:3px;font-size:15px}.program-container .program-info .program-info__next-title[data-v-00e07beb]{display:-webkit-box;margin-top:2px;color:var(--v-text-base);font-size:14px;font-weight:700;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media screen and (max-height:450px){.program-container .program-info .program-info__next-title[data-v-00e07beb]{font-size:13px}}.program-container .program-info .program-info__next-time[data-v-00e07beb]{margin-top:3px;color:var(--v-text-darken1);font-size:13.5px}.program-container .program-info .program-info__status[data-v-00e07beb]{display:flex;align-items:center;margin-top:16px;font-size:14px;color:var(--v-text-darken1)}@media screen and (max-height:450px){.program-container .program-info .program-info__status[data-v-00e07beb]{margin-top:10px;font-size:12px}}.program-container .program-info .program-info__status-force[data-v-00e07beb],.program-container .program-info .program-info__status-viewers[data-v-00e07beb]{display:flex;align-items:center}.program-container .program-info .program-info__status-force--festival[data-v-00e07beb]{color:#e7556e}.program-container .program-info .program-info__status-force--so-many[data-v-00e07beb]{color:#e76b55}.program-container .program-info .program-info__status-force--many[data-v-00e07beb]{color:#e7a355}.program-container .program-detail-container[data-v-00e07beb]{margin-top:24px;margin-bottom:24px}@media screen and (max-height:450px){.program-container .program-detail-container[data-v-00e07beb]{margin-top:20px}}.program-container .program-detail-container .program-detail[data-v-00e07beb]{margin-top:16px}.program-container .program-detail-container .program-detail .program-detail__heading[data-v-00e07beb]{font-size:18px}@media screen and (max-height:450px){.program-container .program-detail-container .program-detail .program-detail__heading[data-v-00e07beb]{font-size:16px}}.program-container .program-detail-container .program-detail .program-detail__text[data-v-00e07beb]{margin-top:8px;color:var(--v-text-darken1);font-size:12px;line-height:168%;overflow-wrap:break-word;white-space:pre-wrap;font-feature-settings:"palt" 1;letter-spacing:.08em}@media screen and (max-height:450px){.program-container .program-detail-container .program-detail .program-detail__text[data-v-00e07beb]{font-size:11px}}.watch-player__dplayer svg circle,.watch-player__dplayer svg path{fill:var(--v-text-base)!important}.watch-player__dplayer .dplayer-video-wrap{background:transparent!important}.watch-player__dplayer .dplayer-video-wrap .dplayer-video-wrap-aspect{transition:opacity .4s cubic-bezier(.4,.38,.49,.94);opacity:1}.watch-player__dplayer .dplayer-video-wrap .dplayer-danmaku{top:50%;left:50%;right:auto;bottom:auto;transform:translate(-50%,-50%);width:100%;max-width:100%;max-height:calc(100% - var(--comment-area-vertical-margin, 0px));aspect-ratio:var(--comment-area-aspect-ratio,16/9);transition:max-height .5s cubic-bezier(.42,.19,.53,.87),aspect-ratio .5s cubic-bezier(.42,.19,.53,.87);will-change:aspect-ratio;overflow:hidden}.watch-player__dplayer .dplayer-video-wrap .dplayer-danloading{display:none!important}.watch-player__dplayer .dplayer-controller-mask{height:82px!important;background:linear-gradient(180deg,transparent,var(--v-background-base))!important;opacity:0!important;visibility:hidden}@media screen and (max-height:450px){.watch-player__dplayer .dplayer-controller-mask{height:66px!important}}.watch-player__dplayer .dplayer-controller{padding-left:86px!important;padding-bottom:6px!important;transition:opacity .3s ease,visibility .3s ease;opacity:0!important;visibility:hidden}.watch-player__dplayer .dplayer-controller .dplayer-live-badge,.watch-player__dplayer .dplayer-controller .dplayer-time{color:var(--v-text-base)!important}.watch-player__dplayer .dplayer-controller .dplayer-volume-bar{background:var(--v-text-base)!important}.watch-player__dplayer .dplayer-controller .dplayer-icons{bottom:auto!important}.watch-player__dplayer .dplayer-controller .dplayer-icons.dplayer-icons-right{right:22px!important}@media screen and (max-height:450px){.watch-player__dplayer .dplayer-controller .dplayer-icons.dplayer-icons-right{right:11px!important}}.watch-player__dplayer .dplayer-controller .dplayer-icons .dplayer-icon.dplayer-full-in-icon{display:none!important}.watch-player__dplayer .dplayer-controller .dplayer-comment-box{transition:opacity .3s ease,visibility .3s ease}.watch-player__dplayer .dplayer-notice{padding:16px 22px!important;margin-right:30px;border-radius:4px!important;font-size:15px!important;line-height:1.6}@media(max-width:960px){.watch-player__dplayer .dplayer-notice{padding:12px 16px!important;margin-right:16px;font-size:13.5px!important}}.watch-player__dplayer .dplayer-info-panel{transition:top .3s,left .3s}.watch-player__dplayer .dplayer-setting-box .dplayer-setting-audio-panel .dplayer-setting-audio-item.dplayer-setting-audio-item--disabled{pointer-events:none}.watch-player__dplayer .dplayer-setting-box .dplayer-setting-audio-panel .dplayer-setting-audio-item.dplayer-setting-audio-item--disabled .dplayer-label{color:#aaa}.watch-player__dplayer .dplayer-comment-setting-box .dplayer-comment-setting-title{color:var(--v-text-base)}.watch-player__dplayer .dplayer-comment-setting-box .dplayer-comment-setting-type span{border:1px solid --v-text-base}.watch-player__dplayer .dplayer-comment-setting-box .dplayer-comment-setting-type input:checked+span{background:var(--v-text-base)}.watch-player__dplayer.dplayer-mobile .dplayer-controller{padding-left:98px!important}@media screen and (max-height:450px){.watch-player__dplayer.dplayer-mobile .dplayer-controller{padding-left:74px!important}}.watch-player__dplayer.dplayer-mobile.dplayer-hide-controller .dplayer-controller{transform:none!important}.watch-player--loading .dplayer-video-wrap-aspect{opacity:0!important}:root .dplayer-icon:hover .dplayer-icon-content,_::-webkit-full-page-media,_:future{opacity:.8!important}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller,.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller-mask{opacity:1!important;visibility:visible!important}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller-mask .dplayer-comment-box,.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller .dplayer-comment-box{left:88px}@media(max-width:960px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller-mask .dplayer-comment-box,.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller .dplayer-comment-box{left:84px}}@media screen and (max-height:450px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller-mask .dplayer-comment-box,.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller .dplayer-comment-box{left:72px}}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:98px;bottom:62px}@media(max-width:960px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:84px}}@media screen and (max-height:450px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:72px}}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-info-panel{top:82px;left:98px}@media(max-width:960px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-info-panel{left:84px}}@media screen and (max-height:450px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-info-panel{left:72px}}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-comment-setting-box{left:88px}@media(max-width:960px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-comment-setting-box{left:84px}}@media screen and (max-height:450px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-comment-setting-box{left:72px}}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-mobile .dplayer-mobile-icon-wrap{opacity:.7!important;visibility:visible!important}.watch-container:not(.watch-container--control-display) .watch-player__dplayer .dplayer-danmaku{max-height:100%!important;aspect-ratio:16/9!important}.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-controller{padding-left:20px!important}.watch-container.watch-container--fullscreen .watch-player__dplayer.dplayer-mobile .dplayer-controller{padding-left:30px!important}@media screen and (max-height:450px){.watch-container.watch-container--fullscreen .watch-player__dplayer.dplayer-mobile .dplayer-controller{padding-left:16px!important}}.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-box,.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-setting-box{left:20px!important}@media(max-width:960px){.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-box,.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-setting-box{left:16px!important}}@media screen and (max-height:450px){.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-box,.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-setting-box{left:16px!important}}.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-info-panel,.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:30px!important}@media(max-width:960px){.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-info-panel,.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:16px!important}}@media screen and (max-height:450px){.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-info-panel,.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:16px!important}}.shortcut-key[data-v-8b237ea4]{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;min-width:32px;height:28px;padding:0 8px;border-radius:5px;background-color:var(--v-background-lighten2);font-size:14.5px}.shortcut-key-plus[data-v-8b237ea4]{display:inline-block;margin:0 5px;flex-shrink:0}.route-container[data-v-8b237ea4]{height:100vh!important;background:var(--v-black-base)!important;overflow:hidden}@supports(-webkit-touch-callout:none){.route-container[data-v-8b237ea4]{height:-webkit-fill-available!important}}.watch-container[data-v-8b237ea4]{display:flex;width:calc(100% + 352px);height:100%;transition:width .4s cubic-bezier(.26,.68,.55,.99)}@media screen and (max-height:450px){.watch-container[data-v-8b237ea4]{width:calc(100% + 310px)}}.watch-container.watch-container--control-display .watch-content[data-v-8b237ea4]{cursor:auto!important}.watch-container.watch-container--control-display .watch-header[data-v-8b237ea4],.watch-container.watch-container--control-display .watch-navigation[data-v-8b237ea4],.watch-container.watch-container--control-display .watch-player__button[data-v-8b237ea4]{opacity:1!important;visibility:visible!important}.watch-container.watch-container--panel-display[data-v-8b237ea4]{width:100%}.watch-container.watch-container--panel-display .switch-button-panel .switch-button-icon[data-v-8b237ea4]{color:var(--v-primary-base)}.watch-container.watch-container--fullscreen .watch-navigation[data-v-8b237ea4]{display:none}.watch-container.watch-container--fullscreen .watch-content .watch-header[data-v-8b237ea4]{padding-left:30px}@media(max-width:960px){.watch-container.watch-container--fullscreen .watch-content .watch-header[data-v-8b237ea4]{padding-left:16px}}@media screen and (max-height:450px){.watch-container.watch-container--fullscreen .watch-content .watch-header[data-v-8b237ea4]{padding-left:16px}}.watch-container .watch-navigation[data-v-8b237ea4]{display:flex;flex-direction:column;position:fixed;width:68px;top:0;left:0;bottom:-100px;padding:18px 8px 122px;background:rgba(47,34,31,.5019607843137255);transition:opacity .3s,visibility .3s;opacity:0;visibility:hidden;z-index:2}@media screen and (max-height:450px){.watch-container .watch-navigation[data-v-8b237ea4]{width:56px;padding:18px 6px 122px}}.watch-container .watch-navigation .watch-navigation__icon[data-v-8b237ea4]{display:flex;justify-content:center;align-items:center;height:52px;margin-bottom:17px;border-radius:11px;font-size:16px;color:var(--v-text-base);transition:background-color .15s;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.watch-container .watch-navigation .watch-navigation__icon[data-v-8b237ea4]{height:32px;border-radius:10px}}@media screen and (max-height:450px){.watch-container .watch-navigation div.spacer[data-v-8b237ea4]{display:none}}.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]{display:flex;justify-content:center;align-items:center;height:52px;border-radius:11px;font-size:16px;color:var(--v-text-base);transition:background-color .15s;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]{height:44px;border-radius:10px}.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]:last-child,.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]:nth-last-child(2){display:none}}.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]:hover{background:rgba(67,53,50,.6274509803921569)}@media screen and (max-height:450px){.watch-container .watch-navigation .watch-navigation__link-icon[data-v-8b237ea4]{width:26px;height:26px}}.watch-container .watch-navigation .watch-navigation__link--active[data-v-8b237ea4]{color:var(--v-primary-base);background:rgba(67,53,50,.6274509803921569)}.watch-container .watch-navigation .watch-navigation__link+.watch-navigation__link[data-v-8b237ea4]{margin-top:4px}@media screen and (max-height:450px){.watch-container .watch-navigation .watch-navigation__link+.watch-navigation__link[data-v-8b237ea4]{margin-top:auto}}.watch-container .watch-content[data-v-8b237ea4]{display:flex;position:relative;width:100%;cursor:none}.watch-container .watch-content .watch-header[data-v-8b237ea4]{display:flex;align-items:center;position:absolute;top:0;left:0;width:100%;height:82px;padding-left:98px;padding-right:30px;background:linear-gradient(180deg,var(--v-background-base),transparent);transition:opacity .3s,visibility .3s;opacity:0;visibility:hidden;z-index:1}@media(max-width:960px){.watch-container .watch-content .watch-header[data-v-8b237ea4]{padding-left:84px;padding-right:16px}}@media screen and (max-height:450px){.watch-container .watch-content .watch-header[data-v-8b237ea4]{height:66px;padding-left:72px}}.watch-container .watch-content .watch-header .watch-header__broadcaster[data-v-8b237ea4]{display:inline-block;flex-shrink:0;width:64px;height:36px;border-radius:5px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media(max-width:960px){.watch-container .watch-content .watch-header .watch-header__broadcaster[data-v-8b237ea4]{width:48px;height:28px;border-radius:4px}}.watch-container .watch-content .watch-header .watch-header__program-title[data-v-8b237ea4]{margin-left:18px;font-size:18px;font-weight:700;font-feature-settings:"palt" 1;letter-spacing:.05em;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media(max-width:960px){.watch-container .watch-content .watch-header .watch-header__program-title[data-v-8b237ea4]{margin-left:12px}}@media screen and (max-height:450px){.watch-container .watch-content .watch-header .watch-header__program-title[data-v-8b237ea4]{font-size:16px}}.watch-container .watch-content .watch-header .watch-header__program-time[data-v-8b237ea4]{flex-shrink:0;margin-left:16px;font-size:15px}@media(max-width:960px){.watch-container .watch-content .watch-header .watch-header__program-time[data-v-8b237ea4]{margin-left:8px}}@media screen and (max-height:450px){.watch-container .watch-content .watch-header .watch-header__program-time[data-v-8b237ea4]{font-size:14px}}.watch-container .watch-content .watch-header .watch-header__now[data-v-8b237ea4]{flex-shrink:0;margin-left:16px;font-size:13px}@media(max-width:960px){.watch-container .watch-content .watch-header .watch-header__now[data-v-8b237ea4]{display:none}}.watch-container .watch-content .watch-player[data-v-8b237ea4]{display:flex;position:relative;width:100%;height:100%;background-size:contain;background-position:50%}.watch-container .watch-content .watch-player .watch-player__background[data-v-8b237ea4]{position:absolute;top:50%;left:50%;width:100%;max-width:100%;max-height:100%;padding-top:min(56.25%,100vh);aspect-ratio:16/9;background-blend-mode:overlay;background-color:rgba(14,14,18,.35);background-size:cover;background-image:none;transform:translate(-50%,-50%);opacity:0;visibility:hidden;will-change:opacity;transition:opacity .4s cubic-bezier(.4,.38,.49,.94),visibility .4s cubic-bezier(.4,.38,.49,.94)}.watch-container .watch-content .watch-player .watch-player__background--display[data-v-8b237ea4]{opacity:1;visibility:visible}.watch-container .watch-content .watch-player .watch-player__background .watch-player__background-logo[data-v-8b237ea4]{display:inline-block;position:absolute;height:34px;right:56px;bottom:44px;filter:drop-shadow(0 0 5px var(--v-black-base))}@media(max-width:1264px){.watch-container .watch-content .watch-player .watch-player__background .watch-player__background-logo[data-v-8b237ea4]{height:30px;right:34px;bottom:30px}}@media(max-width:960px){.watch-container .watch-content .watch-player .watch-player__background .watch-player__background-logo[data-v-8b237ea4]{height:25px;right:30px;bottom:24px}}.watch-container .watch-content .watch-player .watch-player__dplayer[data-v-8b237ea4]{width:100%}.watch-container .watch-content .watch-player .watch-player__button[data-v-8b237ea4]{display:flex;justify-content:space-around;flex-direction:column;position:absolute;top:50%;right:28px;height:190px;transform:translateY(-50%);opacity:0;visibility:hidden;transition:opacity .3s,visibility .3s}@media screen and (max-height:450px){.watch-container .watch-content .watch-player .watch-player__button[data-v-8b237ea4]{right:15px;height:155px}}.watch-container .watch-content .watch-player .watch-player__button .switch-button[data-v-8b237ea4]{display:flex;justify-content:center;align-items:center;width:48px;height:48px;color:var(--v-text-base);background:rgba(47,34,31,.7529411764705882);border-radius:7px;transition:background-color .15s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}@media screen and (max-height:450px){.watch-container .watch-content .watch-player .watch-player__button .switch-button[data-v-8b237ea4]{width:38px;height:38px;border-radius:5px}}.watch-container .watch-content .watch-player .watch-player__button .switch-button[data-v-8b237ea4]:hover{background:rgba(47,34,31,.9411764705882353)}@media(hover:none){.watch-container .watch-content .watch-player .watch-player__button .switch-button[data-v-8b237ea4]:hover{background:rgba(47,34,31,.7529411764705882)}}@media screen and (max-height:450px){.watch-container .watch-content .watch-player .watch-player__button .switch-button svg[data-v-8b237ea4]{height:27px}}.watch-container .watch-content .watch-player .watch-player__button .switch-button .switch-button-icon[data-v-8b237ea4]{position:relative}.watch-container .watch-content .watch-player .watch-player__button .switch-button-up>.switch-button-icon[data-v-8b237ea4]{top:6px}.watch-container .watch-content .watch-player .watch-player__button .switch-button-panel>.switch-button-icon[data-v-8b237ea4]{top:1.5px;transition:color .4s cubic-bezier(.26,.68,.55,.99)}.watch-container .watch-content .watch-player .watch-player__button .switch-button-down>.switch-button-icon[data-v-8b237ea4]{bottom:4px}.watch-container .watch-panel[data-v-8b237ea4]{display:flex;flex-direction:column;flex-shrink:0;width:352px;height:100%;background:var(--v-background-base)}@media screen and (max-height:450px){.watch-container .watch-panel[data-v-8b237ea4]{width:310px}}.watch-container .watch-panel .watch-panel__header[data-v-8b237ea4]{display:flex;align-items:center;flex-shrink:0;width:100%;height:70px;padding-left:16px;padding-right:16px}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header[data-v-8b237ea4]{display:none}}.watch-container .watch-panel .watch-panel__header .panel-close-button[data-v-8b237ea4]{display:flex;position:relative;align-items:center;flex-shrink:0;left:-4px;height:35px;padding:0 4px;border-radius:5px;font-size:16px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-close-button[data-v-8b237ea4]{font-size:14px}}.watch-container .watch-panel .watch-panel__header .panel-close-button__icon[data-v-8b237ea4]{position:relative;left:-4px}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-close-button__icon[data-v-8b237ea4]{height:22px}}.watch-container .watch-panel .watch-panel__header .panel-close-button__text[data-v-8b237ea4]{font-weight:700}.watch-container .watch-panel .watch-panel__header .panel-broadcaster[data-v-8b237ea4]{display:flex;align-items:center;min-width:0;margin-left:16px}.watch-container .watch-panel .watch-panel__header .panel-broadcaster__icon[data-v-8b237ea4]{display:inline-block;flex-shrink:0;width:43px;height:24px;border-radius:3px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-broadcaster__icon[data-v-8b237ea4]{width:38px;height:22px}}.watch-container .watch-panel .watch-panel__header .panel-broadcaster__number[data-v-8b237ea4]{flex-shrink:0;margin-left:8px;font-size:16px}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-broadcaster__number[data-v-8b237ea4]{font-size:14px}}.watch-container .watch-panel .watch-panel__header .panel-broadcaster__name[data-v-8b237ea4]{margin-left:5px;font-size:16px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-broadcaster__name[data-v-8b237ea4]{font-size:14px}}.watch-container .watch-panel .watch-panel__content-container[data-v-8b237ea4]{position:relative;height:100%}.watch-container .watch-panel .watch-panel__content-container .watch-panel__content[data-v-8b237ea4]{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--v-background-base);transition:opacity .3s,visibility .3s;opacity:0;visibility:hidden}.watch-container .watch-panel .watch-panel__content-container .watch-panel__content--active[data-v-8b237ea4]{opacity:1;visibility:visible}.watch-container .watch-panel .watch-panel__navigation[data-v-8b237ea4]{display:flex;align-items:center;justify-content:space-evenly;flex-shrink:0;height:77px;background:var(--v-background-lighten1)}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__navigation[data-v-8b237ea4]{height:56px}}.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button[data-v-8b237ea4]{display:flex;justify-content:center;align-items:center;flex-direction:column;width:66px;height:56px;padding:6px 5.5px;border-radius:5px;color:var(--v-text-base);box-sizing:content-box;transition:color .3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button[data-v-8b237ea4]{height:42px;padding:6px 5.5px 4px}}.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button--active[data-v-8b237ea4]{color:var(--v-primary-base)}.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button__icon[data-v-8b237ea4]{height:30px}.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button__text[data-v-8b237ea4]{margin-top:5px;font-size:13px}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button__text[data-v-8b237ea4]{margin-top:2px;font-size:12px}}.settings-container[data-v-18637a38]{width:100%}.settings-container .settings-navigation[data-v-18637a38]{position:sticky;top:85px!important}.settings-container .settings-navigation .v-list-item--link[data-v-18637a38]:before{border-radius:11px!important}.settings-container .settings[data-v-18637a38]{width:100%;border-radius:11px!important}.settings-container .settings[data-v-18637a38] .settings__heading{display:flex;align-items:center;font-size:22px}.settings-container .settings[data-v-18637a38] .settings__content{margin-top:24px}.settings-container .settings[data-v-18637a38] .settings__content .settings__item{display:flex;flex-direction:column;margin-top:24px}.settings-container .settings[data-v-18637a38] .settings__content .settings__item-heading{color:var(--v-text-base);font-size:16.5px}.settings-container .settings[data-v-18637a38] .settings__content .settings__item-label{margin-top:6px;color:var(--v-text-darken1);font-size:13.5px;line-height:1.6}.settings-container .settings[data-v-18637a38] .settings__content .settings__item-form{margin-top:12px} \ No newline at end of file diff --git a/client/dist/assets/css/app.7dbdd8c6.css b/client/dist/assets/css/app.7dbdd8c6.css deleted file mode 100644 index b9431921..00000000 --- a/client/dist/assets/css/app.7dbdd8c6.css +++ /dev/null @@ -1 +0,0 @@ -html{overflow-y:auto!important}body .v-application{min-height:100vh;font-family:YakuHanJPs,Open Sans,Hiragino Sans,Noto Sans JP,sans-serif;font-weight:500;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@supports(-webkit-touch-callout:none){body .v-application{min-height:-webkit-fill-available}}body .v-application .v-application--wrap{min-height:100%!important}body main{display:flex;width:100%;min-height:100%}body header+main{padding-top:65px!important}@media screen and (max-height:450px){body header+main{padding-top:48px!important}}body .route-container{height:100%;background:var(--v-background-base)}.v-popper--theme-tooltip .v-popper__inner{display:inline-block;padding:4px 10px;border-radius:4px;background:rgba(47,34,31,.7529411764705882);color:var(--v-text-base);font-size:12px;font-family:YakuHanJPs,Open Sans,Hiragino Sans,Noto Sans JP,sans-serif;font-weight:500;opacity:.9;line-height:22px}.v-popper--theme-tooltip .v-popper__arrow-container{display:none}@media(hover:none){:hover:before{background-color:transparent!important}}::-moz-selection{background-color:rgba(230,79,151,.5019607843137255)}::selection{background-color:rgba(230,79,151,.5019607843137255)}.decorate-symbol{display:inline-flex;justify-content:center;align-items:center;position:relative;padding:0 3px;margin-left:2.5px;margin-right:2.5px;border-radius:4px;color:var(--v-text-base);background:var(--v-primary-base);font-size:.94em}*{scrollbar-color:var(--v-gray-base) var(--v-background-base);scrollbar-width:thin}::-webkit-scrollbar{width:7px;height:7px}::-webkit-scrollbar-track{background:var(--v-background-base)}::-webkit-scrollbar-thumb{background:var(--v-background-lighten2)}::-webkit-scrollbar-thumb:hover{background:var(--v-gray-base)}.v-menu__content{overflow:hidden}.v-menu__content::-webkit-scrollbar{width:12px;height:12px}.v-menu__content::-webkit-scrollbar-thumb{border:solid 3.5px var(--v-background-base)}.v-enter-active,.v-leave-active{transition:opacity .3s}.v-enter,.v-leave-to{opacity:0}.v-enter-active.route-container{position:fixed;top:0;left:0;right:0}.w-25{width:25%}.w-50{width:50%}.w-75{width:75%}.w-100{width:100%}.h-25{height:25%}.h-50{height:50%}.h-75{height:75%}.h-100{height:100%}body .v-toolbar.header{position:fixed;height:65px!important;z-index:10}body .v-toolbar.header .v-toolbar__content{height:65px!important}@media screen and (max-height:450px){body .v-toolbar.header,body .v-toolbar.header .v-toolbar__content{height:48px!important}}body .v-toolbar.header .logo{padding:12px 8px;border-radius:8px}body .v-toolbar.header .logo__image{display:block}@media screen and (max-height:450px){body .v-toolbar.header .logo__image{height:19.5px}}.navigation-container[data-v-4fdece88]{flex-shrink:0;width:220px;background:var(--v-background-lighten1)}@media screen and (max-height:450px){.navigation-container[data-v-4fdece88]{width:210px}}.navigation-container .navigation[data-v-4fdece88]{position:fixed;width:220px;top:65px;left:0;bottom:-100px;padding-bottom:100px;background:var(--v-background-lighten1);z-index:1}@media screen and (max-height:450px){.navigation-container .navigation[data-v-4fdece88]{top:48px;width:210px}}.navigation-container .navigation .navigation-scroll[data-v-4fdece88]{display:flex;flex-direction:column;height:100%;padding:22px 12px;overflow-y:auto}@media screen and (max-height:450px){.navigation-container .navigation .navigation-scroll[data-v-4fdece88]{padding:20px 12px}}.navigation-container .navigation .navigation-scroll[data-v-4fdece88]::-webkit-scrollbar-track{background:var(--v-background-lighten1)}.navigation-container .navigation .navigation-scroll .navigation__link[data-v-4fdece88]{display:flex;align-items:center;flex-shrink:0;height:52px;padding-left:16px;padding-right:16px;margin-top:4px;border-radius:11px;font-size:16px;color:var(--v-text-base);transition:background-color .15s;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.navigation-container .navigation .navigation-scroll .navigation__link[data-v-4fdece88]{height:44px;padding-left:12px;padding-right:12px;font-size:15px}}.navigation-container .navigation .navigation-scroll .navigation__link[data-v-4fdece88]:hover{background:var(--v-background-lighten2)}.navigation-container .navigation .navigation-scroll .navigation__link[data-v-4fdece88]:first-of-type{margin-top:0}.navigation-container .navigation .navigation-scroll .navigation__link--active[data-v-4fdece88]{color:var(--v-primary-base);background:#5b2d3c}.navigation-container .navigation .navigation-scroll .navigation__link--active[data-v-4fdece88]:hover{background:#5b2d3c}.navigation-container .navigation .navigation-scroll .navigation__link .navigation__link-icon[data-v-4fdece88]{margin-right:14px}@media screen and (max-height:450px){.navigation-container .navigation .navigation-scroll .navigation__link .navigation__link-icon[data-v-4fdece88]{margin-right:10px}}.channels-container.channels-container--home .v-tabs-bar{height:54px;background:linear-gradient(180deg,var(--v-background-base) calc(100% - 3px),var(--v-background-lighten1) 3px)}@media screen and (max-height:450px){.channels-container.channels-container--home .v-tabs-bar{height:46px}}.channels-container.channels-container--home .v-tabs-slider-wrapper{height:3px!important;transition:left .3s cubic-bezier(.25,.8,.5,1)}.channels-container.channels-container--home .v-window__container{min-height:calc(100vh - 180px)}@media(hover:none){.channels-container.channels-container--home .v-window__container{min-height:auto}}:root .channels-container.channels-container--home .v-window__container,_::-webkit-full-page-media,_:future{height:inherit!important;-webkit-transition:none!important;transition:none!important}:root .channels-container.channels-container--home .v-window__container--is-active,_::-webkit-full-page-media,_:future{display:none!important}:root .channels-container.channels-container--home .v-window__container .v-window-item,_::-webkit-full-page-media,_:future{display:none!important;position:static!important;transform:none!important;-webkit-transition:none!important;transition:none!important}:root .channels-container.channels-container--home .v-window__container .v-window-item--active,_::-webkit-full-page-media,_:future{display:block!important}.channels-container[data-v-6a407b07]{display:flex;flex-direction:column;width:100%;margin-left:21px;margin-right:21px;opacity:1;transition:opacity .4s}.channels-container--loading[data-v-6a407b07]{opacity:0}.channels-container .channels-tab[data-v-6a407b07]{position:sticky;flex:none;top:65px;padding-top:10px;padding-bottom:20px;background:var(--v-background-base);z-index:1}@media screen and (max-height:450px){.channels-container .channels-tab[data-v-6a407b07]{top:47.9px;padding-top:2px;padding-bottom:12px}}.channels-container .channels-tab .channels-tab__item[data-v-6a407b07]{width:98px;padding:0;color:var(--v-text-base)!important;font-size:16px;text-transform:none}@media screen and (max-height:450px){.channels-container .channels-tab .channels-tab__item[data-v-6a407b07]{font-size:15px}}.channels-container .channels-list[data-v-6a407b07]{padding-bottom:32px;background:transparent!important;overflow:inherit}@media screen and (max-height:450px){.channels-container .channels-list[data-v-6a407b07]{padding-bottom:22px}}.channels-container .channels-list .channels[data-v-6a407b07]{display:grid;grid-template-columns:repeat(auto-fit,minmax(365px,1fr));grid-row-gap:16px;grid-column-gap:16px;justify-content:center;background:var(--v-background-base);will-change:transform}@media screen and (min-width:1630px){.channels-container .channels-list .channels[data-v-6a407b07]{grid-template-columns:repeat(auto-fit,445px)}}.channels-container .channels-list .channels.channels--length-0.channels--tab-ピン留め[data-v-6a407b07]{display:flex;min-height:calc(100vh - 180px)}@media screen and (min-width:1008px){.channels-container .channels-list .channels.channels--length-1[data-v-6a407b07]{margin-right:calc(50% + 8px)}}@media screen and (min-width:1389px){.channels-container .channels-list .channels.channels--length-1[data-v-6a407b07]{margin-right:calc(66.66667% + 10.66667px)}}@media screen and (min-width:1630px){.channels-container .channels-list .channels.channels--length-1[data-v-6a407b07]{margin-right:922px}}@media screen and (min-width:2090px){.channels-container .channels-list .channels.channels--length-1[data-v-6a407b07]{margin-right:1383px}}@media screen and (min-width:1389px){.channels-container .channels-list .channels.channels--length-2[data-v-6a407b07]{margin-right:calc(33.33333% + 5.33333px)}}@media screen and (min-width:1630px){.channels-container .channels-list .channels.channels--length-2[data-v-6a407b07]{margin-right:461px}}@media screen and (min-width:2090px){.channels-container .channels-list .channels.channels--length-2[data-v-6a407b07]{margin-right:922px}}@media screen and (min-width:2090px){.channels-container .channels-list .channels.channels--length-3[data-v-6a407b07]{margin-right:461px}}.channels-container .channels-list .channels .channel[data-v-6a407b07]{display:flex;flex-direction:column;position:relative;height:275px;padding:19px 22px;border-radius:16px;color:var(--v-text-base);background:var(--v-background-lighten1);transition:background-color .15s;overflow:hidden;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}@media screen and (max-width:1007.9px){.channels-container .channels-list .channels .channel[data-v-6a407b07]{height:auto}}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel[data-v-6a407b07]{padding:15px 18px;height:auto;border-radius:15px}}.channels-container .channels-list .channels .channel[data-v-6a407b07]:hover{background:var(--v-background-lighten2)}@media(hover:none){.channels-container .channels-list .channels .channel[data-v-6a407b07]:hover{background:var(--v-background-lighten1)}}.channels-container .channels-list .channels .channel .channel__broadcaster[data-v-6a407b07]{display:flex;height:44px}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__broadcaster[data-v-6a407b07]{height:38px}}.channels-container .channels-list .channels .channel .channel__broadcaster-icon[data-v-6a407b07]{display:inline-block;flex-shrink:0;width:80px;height:44px;border-radius:5px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__broadcaster-icon[data-v-6a407b07]{width:64px;height:38px}}.channels-container .channels-list .channels .channel .channel__broadcaster-content[data-v-6a407b07]{display:flex;flex-direction:column;margin-left:16px;width:100%;min-width:0}.channels-container .channels-list .channels .channel .channel__broadcaster-name[data-v-6a407b07]{flex-shrink:0;font-size:18px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__broadcaster-name[data-v-6a407b07]{font-size:15px}}.channels-container .channels-list .channels .channel .channel__broadcaster-status[data-v-6a407b07]{display:flex;align-items:center;margin-top:2px;font-size:12px;color:var(--v-text-darken1)}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__broadcaster-status[data-v-6a407b07]{font-size:10px;margin-top:3px}}.channels-container .channels-list .channels .channel .channel__broadcaster-status-force[data-v-6a407b07],.channels-container .channels-list .channels .channel .channel__broadcaster-status-viewers[data-v-6a407b07]{display:flex;align-items:center}.channels-container .channels-list .channels .channel .channel__broadcaster-status-force--festival[data-v-6a407b07]{color:#e7556e}.channels-container .channels-list .channels .channel .channel__broadcaster-status-force--so-many[data-v-6a407b07]{color:#e76b55}.channels-container .channels-list .channels .channel .channel__broadcaster-status-force--many[data-v-6a407b07]{color:#e7a355}.channels-container .channels-list .channels .channel .channel__broadcaster-pin[data-v-6a407b07]{display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;top:-5px;right:-5px;width:34px;height:34px;padding:4px;color:var(--v-text-darken1);border-radius:50%;transition:color .15s ease,background-color .15s ease;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.channels-container .channels-list .channels .channel .channel__broadcaster-pin[data-v-6a407b07]:before{background-color:currentColor;border-radius:inherit;bottom:0;color:inherit;content:"";left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:0;transition:opacity .2s cubic-bezier(.4,0,.6,1)}.channels-container .channels-list .channels .channel .channel__broadcaster-pin[data-v-6a407b07]:hover{color:var(--v-text-base)}.channels-container .channels-list .channels .channel .channel__broadcaster-pin[data-v-6a407b07]:hover:before{opacity:.15}.channels-container .channels-list .channels .channel .channel__broadcaster-pin--pinned[data-v-6a407b07]{color:var(--v-primary-base)}.channels-container .channels-list .channels .channel .channel__broadcaster-pin--pinned[data-v-6a407b07]:hover{color:var(--v-primary-lighten1)}.channels-container .channels-list .channels .channel .channel__program-present[data-v-6a407b07]{display:flex;flex-direction:column}.channels-container .channels-list .channels .channel .channel__program-present-title[data-v-6a407b07]{display:-webkit-box;margin-top:14px;font-size:16px;font-weight:700;font-feature-settings:"palt" 1;letter-spacing:.07em;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-present-title[data-v-6a407b07]{margin-top:10px;font-size:14.5px;-webkit-line-clamp:1}}.channels-container .channels-list .channels .channel .channel__program-present-time[data-v-6a407b07]{margin-top:4px;color:var(--v-text-darken1);font-size:13.5px}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-present-time[data-v-6a407b07]{font-size:12px}}.channels-container .channels-list .channels .channel .channel__program-present-description[data-v-6a407b07]{display:-webkit-box;margin-top:8px;color:var(--v-text-darken1);font-size:10.5px;line-height:175%;overflow-wrap:break-word;font-feature-settings:"palt" 1;letter-spacing:.07em;overflow:hidden;-webkit-line-clamp:3;-webkit-box-orient:vertical}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-present-description[data-v-6a407b07]{margin-top:8px;font-size:10px;-webkit-line-clamp:2}}.channels-container .channels-list .channels .channel .channel__program-following[data-v-6a407b07]{display:flex;flex-direction:column;color:var(--v-text-base);font-size:12.5px}@media screen and (max-width:1007.9px){.channels-container .channels-list .channels .channel .channel__program-following[data-v-6a407b07]{margin-top:6px}}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-following[data-v-6a407b07]{margin-top:6px;font-size:12px}}.channels-container .channels-list .channels .channel .channel__program-following-title[data-v-6a407b07]{display:flex;align-items:center}.channels-container .channels-list .channels .channel .channel__program-following-title-decorate[data-v-6a407b07]{flex-shrink:0;font-weight:700}.channels-container .channels-list .channels .channel .channel__program-following-title-icon[data-v-6a407b07]{flex-shrink:0;margin-left:3px}.channels-container .channels-list .channels .channel .channel__program-following-title-text[data-v-6a407b07]{margin-left:2px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.channels-container .channels-list .channels .channel .channel__program-following-time[data-v-6a407b07]{color:var(--v-text-darken1)}@media screen and (max-height:450px){.channels-container .channels-list .channels .channel .channel__program-following-time[data-v-6a407b07]{font-size:11.5px}}.channels-container .channels-list .channels .channel .channel__progressbar[data-v-6a407b07]{position:absolute;left:0;right:0;bottom:0;height:4px;background:var(--v-gray-base)}.channels-container .channels-list .channels .channel .channel__progressbar-progress[data-v-6a407b07]{height:4px;background:var(--v-primary-base);transition:width .3s}.channels-container.channels-container--watch .v-tabs-bar{position:relative;top:-9px;height:48px;background:linear-gradient(180deg,var(--v-background-base) calc(100% - 3px),var(--v-background-lighten1) 3px)}@media screen and (max-height:450px){.channels-container.channels-container--watch .v-tabs-bar{top:-7px;height:40px}}.channels-container.channels-container--watch .v-tabs-bar .v-slide-group__next,.channels-container.channels-container--watch .v-tabs-bar .v-slide-group__prev{flex:auto!important;min-width:28px!important}.channels-container.channels-container--watch .v-tabs-slider-wrapper{height:3px!important;transition:left .3s cubic-bezier(.25,.8,.5,1)}:root .channels-container.channels-container--watch .v-window__container,_::-webkit-full-page-media,_:future{height:inherit!important;-webkit-transition:none!important;transition:none!important}:root .channels-container.channels-container--watch .v-window__container--is-active,_::-webkit-full-page-media,_:future{display:none!important}:root .channels-container.channels-container--watch .v-window__container .v-window-item,_::-webkit-full-page-media,_:future{display:none!important;position:static!important;transform:none!important;-webkit-transition:none!important;transition:none!important}:root .channels-container.channels-container--watch .v-window__container .v-window-item--active,_::-webkit-full-page-media,_:future{display:block!important}.channels-container[data-v-691b389f]{display:flex;flex-direction:column}.channels-container .channels-tab[data-v-691b389f]{position:sticky;flex:none;top:0;padding-left:16px;padding-right:16px;padding-bottom:9px;background:var(--v-background-base);z-index:1}@media screen and (max-height:450px){.channels-container .channels-tab[data-v-691b389f]{padding-bottom:7px;margin-top:12px}}.channels-container .channels-tab .channels-tab__item[data-v-691b389f]{width:88px;padding:0;color:var(--v-text-base)!important;font-size:15px;text-transform:none}@media screen and (max-height:450px){.channels-container .channels-tab .channels-tab__item[data-v-691b389f]{font-size:14.5px}}.channels-container .channels-list-container[data-v-691b389f]{overflow-y:auto}.channels-container .channels-list-container .channels-list[data-v-691b389f]{padding-left:16px;padding-right:10px;padding-bottom:16px;background:transparent!important;overflow:visible!important}.channels-container .channels-list-container .channels-list .channels[data-v-691b389f]{display:flex;justify-content:center;flex-direction:column;will-change:transform}@media screen and (min-width:1630px){.channels-container .channels-list-container .channels-list .channels[data-v-691b389f]{grid-template-columns:repeat(auto-fit,445px)}}.channels-container .channels-list-container .channels-list .channels .channel[data-v-691b389f]{display:flex;flex-direction:column;position:relative;margin-top:12px;padding:10px 12px 14px 12px;border-radius:11px;color:var(--v-text-base);background:var(--v-background-lighten1);transition:background-color .15s;overflow:hidden;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}.channels-container .channels-list-container .channels-list .channels .channel[data-v-691b389f]:first-of-type{margin-top:0}.channels-container .channels-list-container .channels-list .channels .channel[data-v-691b389f]:hover{background:var(--v-background-lighten2)}@media(hover:none){.channels-container .channels-list-container .channels-list .channels .channel[data-v-691b389f]:hover{background:var(--v-background-lighten1)}}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster[data-v-691b389f]{display:flex;height:28px}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-icon[data-v-691b389f]{display:inline-block;flex-shrink:0;width:48px;height:100%;border-radius:4px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-content[data-v-691b389f]{display:flex;align-items:center;margin-left:12px;width:100%;min-width:0}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-name[data-v-691b389f]{font-size:14.5px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-force[data-v-691b389f]{display:flex;align-items:center;flex-shrink:0;margin-top:2px;margin-left:auto;padding-left:6px;font-size:12px;color:var(--v-text-darken1)}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-force--festival[data-v-691b389f]{color:#e7556e}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-force--so-many[data-v-691b389f]{color:#e76b55}.channels-container .channels-list-container .channels-list .channels .channel .channel__broadcaster-force--many[data-v-691b389f]{color:#e7a355}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-present[data-v-691b389f]{display:flex;flex-direction:column}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-present-title[data-v-691b389f]{display:-webkit-box;margin-top:8px;font-size:13.5px;font-weight:700;font-feature-settings:"palt" 1;letter-spacing:.07em;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-present-time[data-v-691b389f]{margin-top:4px;color:var(--v-text-darken1);font-size:11.5px}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following[data-v-691b389f]{display:flex;flex-direction:column;margin-top:4px;color:var(--v-text-darken1);font-size:11.5px}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-title[data-v-691b389f]{display:flex;align-items:center}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-title-decorate[data-v-691b389f]{flex-shrink:0}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-title-icon[data-v-691b389f]{flex-shrink:0;margin-left:3px}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-title-text[data-v-691b389f]{margin-left:2px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.channels-container .channels-list-container .channels-list .channels .channel .channel__program-following-time[data-v-691b389f]{margin-top:1px}.channels-container .channels-list-container .channels-list .channels .channel .channel__progressbar[data-v-691b389f]{position:absolute;left:0;right:0;bottom:0;height:4px;background:var(--v-gray-base)}.channels-container .channels-list-container .channels-list .channels .channel .channel__progressbar-progress[data-v-691b389f]{height:4px;background:var(--v-primary-base);transition:width .3s}.comment-container[data-v-7575b645]{display:flex;flex-direction:column}.comment-container .comment-header[data-v-7575b645]{display:flex;align-items:center;flex-shrink:0;width:100%;height:26px;padding-left:16px;padding-right:16px}@media screen and (max-height:450px){.comment-container .comment-header[data-v-7575b645]{margin-top:12px}}.comment-container .comment-header__title[data-v-7575b645]{display:flex;align-items:center;font-size:18.5px;font-weight:700;line-height:145%}@media screen and (max-height:450px){.comment-container .comment-header__title[data-v-7575b645]{font-size:16.5px}}.comment-container .comment-header__title-icon[data-v-7575b645]{margin-bottom:-3px}@media screen and (max-height:450px){.comment-container .comment-header__title-icon[data-v-7575b645]{height:17.5px}}.comment-container .comment-header__title-text[data-v-7575b645]{margin-left:12px}.comment-container .comment-header__button[data-v-7575b645]{display:flex;align-items:center;height:26px;padding:0 9px;border-radius:4px;background:var(--v-background-lighten3);font-size:11px;line-height:1.8;letter-spacing:0}.comment-container .comment-list[data-v-7575b645]{width:100%;height:100%;margin-top:16px;padding-left:16px;padding-right:10px;padding-bottom:12px;overflow-y:scroll!important}@media screen and (max-height:450px){.comment-container .comment-list[data-v-7575b645]{margin-top:12px}}.comment-container .comment-list .comment[data-v-7575b645]{display:flex;align-items:center;min-height:28px;padding-top:6px;word-break:break-all}.comment-container .comment-list .comment__text[data-v-7575b645]{font-size:13px}.comment-container .comment-list .comment__time[data-v-7575b645]{flex-shrink:0;margin-left:auto;padding-left:8px;color:var(--v-text-darken1);font-size:13px}.comment-container .comment-scroll-button[data-v-7575b645]{display:flex;align-items:center;justify-content:center;position:absolute;left:0;right:0;bottom:22px;width:42px;height:42px;margin:0 auto;border-radius:50%;background:var(--v-primary-base);transition:background-color .15s,opacity .3s,visibility .3s;visibility:hidden;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}.comment-container .comment-scroll-button--display[data-v-7575b645]{opacity:1;visibility:visible}.program-container[data-v-00e07beb]{padding-left:16px;padding-right:16px;overflow-y:auto}.program-container .program-broadcaster[data-v-00e07beb]{display:none;align-items:center;min-width:0}@media screen and (max-height:450px){.program-container .program-broadcaster[data-v-00e07beb]{display:flex;margin-top:16px}}.program-container .program-broadcaster__icon[data-v-00e07beb]{display:inline-block;flex-shrink:0;width:43px;height:24px;border-radius:3px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.program-container .program-broadcaster__icon[data-v-00e07beb]{width:42px;height:23.5px}}.program-container .program-broadcaster__number[data-v-00e07beb]{flex-shrink:0;margin-left:12px;font-size:16.5px}.program-container .program-broadcaster__name[data-v-00e07beb]{margin-left:5px;font-size:16.5px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.program-container .program-info .program-info__title[data-v-00e07beb]{font-size:22px;font-weight:700;line-height:145%;font-feature-settings:"palt" 1;letter-spacing:.05em}@media screen and (max-height:450px){.program-container .program-info .program-info__title[data-v-00e07beb]{margin-top:10px;font-size:18px}}.program-container .program-info .program-info__time[data-v-00e07beb]{margin-top:8px;color:var(--v-text-darken1);font-size:14px}@media screen and (max-height:450px){.program-container .program-info .program-info__time[data-v-00e07beb]{font-size:13px}}.program-container .program-info .program-info__description[data-v-00e07beb]{margin-top:12px;color:var(--v-text-darken1);font-size:12px;line-height:168%;overflow-wrap:break-word;font-feature-settings:"palt" 1;letter-spacing:.08em}@media screen and (max-height:450px){.program-container .program-info .program-info__description[data-v-00e07beb]{margin-top:8px;font-size:11px}}.program-container .program-info .program-info__genre-container[data-v-00e07beb]{display:flex;flex-wrap:wrap;margin-top:10px}.program-container .program-info .program-info__genre-container .program-info__genre[data-v-00e07beb]{display:inline-block;font-size:10.5px;padding:3px;margin-top:4px;margin-right:4px;border-radius:4px;background:var(--v-background-lighten2)}@media screen and (max-height:450px){.program-container .program-info .program-info__genre-container .program-info__genre[data-v-00e07beb]{font-size:9px}}.program-container .program-info .program-info__next[data-v-00e07beb]{display:flex;align-items:center;margin-top:18px;color:var(--v-text-base);font-size:14px;font-weight:700}@media screen and (max-height:450px){.program-container .program-info .program-info__next[data-v-00e07beb]{margin-top:14px;font-size:13px}}.program-container .program-info .program-info__next-decorate[data-v-00e07beb]{flex-shrink:0}.program-container .program-info .program-info__next-icon[data-v-00e07beb]{flex-shrink:0;margin-left:3px;font-size:15px}.program-container .program-info .program-info__next-title[data-v-00e07beb]{display:-webkit-box;margin-top:2px;color:var(--v-text-base);font-size:14px;font-weight:700;overflow:hidden;-webkit-line-clamp:2;-webkit-box-orient:vertical}@media screen and (max-height:450px){.program-container .program-info .program-info__next-title[data-v-00e07beb]{font-size:13px}}.program-container .program-info .program-info__next-time[data-v-00e07beb]{margin-top:3px;color:var(--v-text-darken1);font-size:13.5px}.program-container .program-info .program-info__status[data-v-00e07beb]{display:flex;align-items:center;margin-top:16px;font-size:14px;color:var(--v-text-darken1)}@media screen and (max-height:450px){.program-container .program-info .program-info__status[data-v-00e07beb]{margin-top:10px;font-size:12px}}.program-container .program-info .program-info__status-force[data-v-00e07beb],.program-container .program-info .program-info__status-viewers[data-v-00e07beb]{display:flex;align-items:center}.program-container .program-info .program-info__status-force--festival[data-v-00e07beb]{color:#e7556e}.program-container .program-info .program-info__status-force--so-many[data-v-00e07beb]{color:#e76b55}.program-container .program-info .program-info__status-force--many[data-v-00e07beb]{color:#e7a355}.program-container .program-detail-container[data-v-00e07beb]{margin-top:24px;margin-bottom:24px}@media screen and (max-height:450px){.program-container .program-detail-container[data-v-00e07beb]{margin-top:20px}}.program-container .program-detail-container .program-detail[data-v-00e07beb]{margin-top:16px}.program-container .program-detail-container .program-detail .program-detail__heading[data-v-00e07beb]{font-size:18px}@media screen and (max-height:450px){.program-container .program-detail-container .program-detail .program-detail__heading[data-v-00e07beb]{font-size:16px}}.program-container .program-detail-container .program-detail .program-detail__text[data-v-00e07beb]{margin-top:8px;color:var(--v-text-darken1);font-size:12px;line-height:168%;overflow-wrap:break-word;white-space:pre-wrap;font-feature-settings:"palt" 1;letter-spacing:.08em}@media screen and (max-height:450px){.program-container .program-detail-container .program-detail .program-detail__text[data-v-00e07beb]{font-size:11px}}.watch-player__dplayer svg circle,.watch-player__dplayer svg path{fill:var(--v-text-base)!important}.watch-player__dplayer .dplayer-video-wrap{background:transparent!important}.watch-player__dplayer .dplayer-video-wrap .dplayer-video-wrap-aspect{transition:opacity .4s cubic-bezier(.4,.38,.49,.94);opacity:1}.watch-player__dplayer .dplayer-video-wrap .dplayer-danmaku{top:50%;left:50%;right:auto;bottom:auto;transform:translate(-50%,-50%);width:100%;max-width:100%;max-height:calc(100% - var(--comment-area-vertical-margin, 0px));aspect-ratio:var(--comment-area-aspect-ratio,16/9);transition:max-height .5s cubic-bezier(.42,.19,.53,.87),aspect-ratio .5s cubic-bezier(.42,.19,.53,.87);will-change:aspect-ratio;overflow:hidden}.watch-player__dplayer .dplayer-video-wrap .dplayer-danloading{display:none!important}.watch-player__dplayer .dplayer-controller-mask{height:82px!important;background:linear-gradient(180deg,transparent,var(--v-background-base))!important;opacity:0!important;visibility:hidden}@media screen and (max-height:450px){.watch-player__dplayer .dplayer-controller-mask{height:66px!important}}.watch-player__dplayer .dplayer-controller{padding-left:86px!important;padding-bottom:6px!important;transition:opacity .3s ease,visibility .3s ease;opacity:0!important;visibility:hidden}.watch-player__dplayer .dplayer-controller .dplayer-live-badge,.watch-player__dplayer .dplayer-controller .dplayer-time{color:var(--v-text-base)!important}.watch-player__dplayer .dplayer-controller .dplayer-volume-bar{background:var(--v-text-base)!important}.watch-player__dplayer .dplayer-controller .dplayer-icons{bottom:auto!important}.watch-player__dplayer .dplayer-controller .dplayer-icons.dplayer-icons-right{right:22px!important}@media screen and (max-height:450px){.watch-player__dplayer .dplayer-controller .dplayer-icons.dplayer-icons-right{right:11px!important}}.watch-player__dplayer .dplayer-controller .dplayer-icons .dplayer-icon.dplayer-full-in-icon{display:none!important}.watch-player__dplayer .dplayer-controller .dplayer-comment-box{transition:opacity .3s ease,visibility .3s ease}.watch-player__dplayer .dplayer-notice{padding:16px 22px!important;margin-right:30px;border-radius:4px!important;font-size:15px!important;line-height:1.6}@media(max-width:960px){.watch-player__dplayer .dplayer-notice{padding:12px 16px!important;margin-right:16px;font-size:13.5px!important}}.watch-player__dplayer .dplayer-info-panel{transition:top .3s,left .3s}.watch-player__dplayer .dplayer-setting-box .dplayer-setting-audio-panel .dplayer-setting-audio-item.dplayer-setting-audio-item--disabled{pointer-events:none}.watch-player__dplayer .dplayer-setting-box .dplayer-setting-audio-panel .dplayer-setting-audio-item.dplayer-setting-audio-item--disabled .dplayer-label{color:#aaa}.watch-player__dplayer .dplayer-comment-setting-box .dplayer-comment-setting-title{color:var(--v-text-base)}.watch-player__dplayer .dplayer-comment-setting-box .dplayer-comment-setting-type span{border:1px solid --v-text-base}.watch-player__dplayer .dplayer-comment-setting-box .dplayer-comment-setting-type input:checked+span{background:var(--v-text-base)}.watch-player__dplayer.dplayer-mobile .dplayer-controller{padding-left:98px!important}@media screen and (max-height:450px){.watch-player__dplayer.dplayer-mobile .dplayer-controller{padding-left:74px!important}}.watch-player__dplayer.dplayer-mobile.dplayer-hide-controller .dplayer-controller{transform:none!important}.watch-player--loading .dplayer-video-wrap-aspect{opacity:0!important}:root .dplayer-icon:hover .dplayer-icon-content,_::-webkit-full-page-media,_:future{opacity:.8!important}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller,.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller-mask{opacity:1!important;visibility:visible!important}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller-mask .dplayer-comment-box,.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller .dplayer-comment-box{left:88px}@media(max-width:960px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller-mask .dplayer-comment-box,.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller .dplayer-comment-box{left:84px}}@media screen and (max-height:450px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller-mask .dplayer-comment-box,.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-controller .dplayer-comment-box{left:72px}}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:98px;bottom:62px}@media(max-width:960px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:84px}}@media screen and (max-height:450px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:72px}}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-info-panel{top:82px;left:98px}@media(max-width:960px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-info-panel{left:84px}}@media screen and (max-height:450px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-info-panel{left:72px}}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-comment-setting-box{left:88px}@media(max-width:960px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-comment-setting-box{left:84px}}@media screen and (max-height:450px){.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-comment-setting-box{left:72px}}.watch-container.watch-container--control-display .watch-player__dplayer .dplayer-mobile .dplayer-mobile-icon-wrap{opacity:.7!important;visibility:visible!important}.watch-container:not(.watch-container--control-display) .watch-player__dplayer .dplayer-danmaku{max-height:100%!important;aspect-ratio:16/9!important}.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-controller{padding-left:20px!important}.watch-container.watch-container--fullscreen .watch-player__dplayer.dplayer-mobile .dplayer-controller{padding-left:30px!important}@media screen and (max-height:450px){.watch-container.watch-container--fullscreen .watch-player__dplayer.dplayer-mobile .dplayer-controller{padding-left:16px!important}}.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-box,.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-setting-box{left:20px!important}@media(max-width:960px){.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-box,.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-setting-box{left:16px!important}}@media screen and (max-height:450px){.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-box,.watch-container.watch-container--fullscreen .watch-player__dplayer .dplayer-comment-setting-box{left:16px!important}}.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-info-panel,.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:30px!important}@media(max-width:960px){.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-info-panel,.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:16px!important}}@media screen and (max-height:450px){.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-info-panel,.watch-container.watch-container--fullscreen.watch-container--control-display .watch-player__dplayer .dplayer-notice{left:16px!important}}.shortcut-key[data-v-8b237ea4]{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;min-width:32px;height:28px;padding:0 8px;border-radius:5px;background-color:var(--v-background-lighten2);font-size:14.5px}.shortcut-key-plus[data-v-8b237ea4]{display:inline-block;margin:0 5px;flex-shrink:0}.route-container[data-v-8b237ea4]{height:100vh!important;background:var(--v-black-base)!important;overflow:hidden}@supports(-webkit-touch-callout:none){.route-container[data-v-8b237ea4]{height:-webkit-fill-available!important}}.watch-container[data-v-8b237ea4]{display:flex;width:calc(100% + 352px);height:100%;transition:width .4s cubic-bezier(.26,.68,.55,.99)}@media screen and (max-height:450px){.watch-container[data-v-8b237ea4]{width:calc(100% + 310px)}}.watch-container.watch-container--control-display .watch-content[data-v-8b237ea4]{cursor:auto!important}.watch-container.watch-container--control-display .watch-header[data-v-8b237ea4],.watch-container.watch-container--control-display .watch-navigation[data-v-8b237ea4],.watch-container.watch-container--control-display .watch-player__button[data-v-8b237ea4]{opacity:1!important;visibility:visible!important}.watch-container.watch-container--panel-display[data-v-8b237ea4]{width:100%}.watch-container.watch-container--panel-display .switch-button-panel .switch-button-icon[data-v-8b237ea4]{color:var(--v-primary-base)}.watch-container.watch-container--fullscreen .watch-navigation[data-v-8b237ea4]{display:none}.watch-container.watch-container--fullscreen .watch-content .watch-header[data-v-8b237ea4]{padding-left:30px}@media(max-width:960px){.watch-container.watch-container--fullscreen .watch-content .watch-header[data-v-8b237ea4]{padding-left:16px}}@media screen and (max-height:450px){.watch-container.watch-container--fullscreen .watch-content .watch-header[data-v-8b237ea4]{padding-left:16px}}.watch-container .watch-navigation[data-v-8b237ea4]{display:flex;flex-direction:column;position:fixed;width:68px;top:0;left:0;bottom:-100px;padding:18px 8px 122px;background:rgba(47,34,31,.5019607843137255);transition:opacity .3s,visibility .3s;opacity:0;visibility:hidden;z-index:2}@media screen and (max-height:450px){.watch-container .watch-navigation[data-v-8b237ea4]{width:56px;padding:18px 6px 122px}}.watch-container .watch-navigation .watch-navigation__icon[data-v-8b237ea4]{display:flex;justify-content:center;align-items:center;height:52px;margin-bottom:17px;border-radius:11px;font-size:16px;color:var(--v-text-base);transition:background-color .15s;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.watch-container .watch-navigation .watch-navigation__icon[data-v-8b237ea4]{height:32px;border-radius:10px}}@media screen and (max-height:450px){.watch-container .watch-navigation div.spacer[data-v-8b237ea4]{display:none}}.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]{display:flex;justify-content:center;align-items:center;height:52px;border-radius:11px;font-size:16px;color:var(--v-text-base);transition:background-color .15s;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]{height:44px;border-radius:10px}.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]:last-child,.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]:nth-last-child(2){display:none}}.watch-container .watch-navigation .watch-navigation__link[data-v-8b237ea4]:hover{background:rgba(67,53,50,.6274509803921569)}@media screen and (max-height:450px){.watch-container .watch-navigation .watch-navigation__link-icon[data-v-8b237ea4]{width:26px;height:26px}}.watch-container .watch-navigation .watch-navigation__link--active[data-v-8b237ea4]{color:var(--v-primary-base);background:rgba(67,53,50,.6274509803921569)}.watch-container .watch-navigation .watch-navigation__link+.watch-navigation__link[data-v-8b237ea4]{margin-top:4px}@media screen and (max-height:450px){.watch-container .watch-navigation .watch-navigation__link+.watch-navigation__link[data-v-8b237ea4]{margin-top:auto}}.watch-container .watch-content[data-v-8b237ea4]{display:flex;position:relative;width:100%;cursor:none}.watch-container .watch-content .watch-header[data-v-8b237ea4]{display:flex;align-items:center;position:absolute;top:0;left:0;width:100%;height:82px;padding-left:98px;padding-right:30px;background:linear-gradient(180deg,var(--v-background-base),transparent);transition:opacity .3s,visibility .3s;opacity:0;visibility:hidden;z-index:1}@media(max-width:960px){.watch-container .watch-content .watch-header[data-v-8b237ea4]{padding-left:84px;padding-right:16px}}@media screen and (max-height:450px){.watch-container .watch-content .watch-header[data-v-8b237ea4]{height:66px;padding-left:72px}}.watch-container .watch-content .watch-header .watch-header__broadcaster[data-v-8b237ea4]{display:inline-block;flex-shrink:0;width:64px;height:36px;border-radius:5px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media(max-width:960px){.watch-container .watch-content .watch-header .watch-header__broadcaster[data-v-8b237ea4]{width:48px;height:28px;border-radius:4px}}.watch-container .watch-content .watch-header .watch-header__program-title[data-v-8b237ea4]{margin-left:18px;font-size:18px;font-weight:700;font-feature-settings:"palt" 1;letter-spacing:.05em;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media(max-width:960px){.watch-container .watch-content .watch-header .watch-header__program-title[data-v-8b237ea4]{margin-left:12px}}@media screen and (max-height:450px){.watch-container .watch-content .watch-header .watch-header__program-title[data-v-8b237ea4]{font-size:16px}}.watch-container .watch-content .watch-header .watch-header__program-time[data-v-8b237ea4]{flex-shrink:0;margin-left:16px;font-size:15px}@media(max-width:960px){.watch-container .watch-content .watch-header .watch-header__program-time[data-v-8b237ea4]{margin-left:8px}}@media screen and (max-height:450px){.watch-container .watch-content .watch-header .watch-header__program-time[data-v-8b237ea4]{font-size:14px}}.watch-container .watch-content .watch-header .watch-header__now[data-v-8b237ea4]{flex-shrink:0;margin-left:16px;font-size:13px}@media(max-width:960px){.watch-container .watch-content .watch-header .watch-header__now[data-v-8b237ea4]{display:none}}.watch-container .watch-content .watch-player[data-v-8b237ea4]{display:flex;position:relative;width:100%;height:100%;background-size:contain;background-position:50%}.watch-container .watch-content .watch-player .watch-player__background[data-v-8b237ea4]{position:absolute;top:50%;left:50%;width:100%;max-width:100%;max-height:100%;padding-top:min(56.25%,100vh);aspect-ratio:16/9;background-blend-mode:overlay;background-color:rgba(14,14,18,.35);background-size:cover;background-image:none;transform:translate(-50%,-50%);opacity:0;visibility:hidden;will-change:opacity;transition:opacity .4s cubic-bezier(.4,.38,.49,.94),visibility .4s cubic-bezier(.4,.38,.49,.94)}.watch-container .watch-content .watch-player .watch-player__background--display[data-v-8b237ea4]{opacity:1;visibility:visible}.watch-container .watch-content .watch-player .watch-player__background .watch-player__background-logo[data-v-8b237ea4]{display:inline-block;position:absolute;height:34px;right:56px;bottom:44px;filter:drop-shadow(0 0 5px var(--v-black-base))}@media(max-width:1264px){.watch-container .watch-content .watch-player .watch-player__background .watch-player__background-logo[data-v-8b237ea4]{height:30px;right:34px;bottom:30px}}@media(max-width:960px){.watch-container .watch-content .watch-player .watch-player__background .watch-player__background-logo[data-v-8b237ea4]{height:25px;right:30px;bottom:24px}}.watch-container .watch-content .watch-player .watch-player__dplayer[data-v-8b237ea4]{width:100%}.watch-container .watch-content .watch-player .watch-player__button[data-v-8b237ea4]{display:flex;justify-content:space-around;flex-direction:column;position:absolute;top:50%;right:28px;height:190px;transform:translateY(-50%);opacity:0;visibility:hidden;transition:opacity .3s,visibility .3s}@media screen and (max-height:450px){.watch-container .watch-content .watch-player .watch-player__button[data-v-8b237ea4]{right:15px;height:155px}}.watch-container .watch-content .watch-player .watch-player__button .switch-button[data-v-8b237ea4]{display:flex;justify-content:center;align-items:center;width:48px;height:48px;color:var(--v-text-base);background:rgba(47,34,31,.7529411764705882);border-radius:7px;transition:background-color .15s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}@media screen and (max-height:450px){.watch-container .watch-content .watch-player .watch-player__button .switch-button[data-v-8b237ea4]{width:38px;height:38px;border-radius:5px}}.watch-container .watch-content .watch-player .watch-player__button .switch-button[data-v-8b237ea4]:hover{background:rgba(47,34,31,.9411764705882353)}@media(hover:none){.watch-container .watch-content .watch-player .watch-player__button .switch-button[data-v-8b237ea4]:hover{background:rgba(47,34,31,.7529411764705882)}}@media screen and (max-height:450px){.watch-container .watch-content .watch-player .watch-player__button .switch-button svg[data-v-8b237ea4]{height:27px}}.watch-container .watch-content .watch-player .watch-player__button .switch-button .switch-button-icon[data-v-8b237ea4]{position:relative}.watch-container .watch-content .watch-player .watch-player__button .switch-button-up>.switch-button-icon[data-v-8b237ea4]{top:6px}.watch-container .watch-content .watch-player .watch-player__button .switch-button-panel>.switch-button-icon[data-v-8b237ea4]{top:1.5px;transition:color .4s cubic-bezier(.26,.68,.55,.99)}.watch-container .watch-content .watch-player .watch-player__button .switch-button-down>.switch-button-icon[data-v-8b237ea4]{bottom:4px}.watch-container .watch-panel[data-v-8b237ea4]{display:flex;flex-direction:column;flex-shrink:0;width:352px;height:100%;background:var(--v-background-base)}@media screen and (max-height:450px){.watch-container .watch-panel[data-v-8b237ea4]{width:310px}}.watch-container .watch-panel .watch-panel__header[data-v-8b237ea4]{display:flex;align-items:center;flex-shrink:0;width:100%;height:70px;padding-left:16px;padding-right:16px}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header[data-v-8b237ea4]{display:none}}.watch-container .watch-panel .watch-panel__header .panel-close-button[data-v-8b237ea4]{display:flex;position:relative;align-items:center;flex-shrink:0;left:-4px;height:35px;padding:0 4px;border-radius:5px;font-size:16px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-close-button[data-v-8b237ea4]{font-size:14px}}.watch-container .watch-panel .watch-panel__header .panel-close-button__icon[data-v-8b237ea4]{position:relative;left:-4px}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-close-button__icon[data-v-8b237ea4]{height:22px}}.watch-container .watch-panel .watch-panel__header .panel-close-button__text[data-v-8b237ea4]{font-weight:700}.watch-container .watch-panel .watch-panel__header .panel-broadcaster[data-v-8b237ea4]{display:flex;align-items:center;min-width:0;margin-left:16px}.watch-container .watch-panel .watch-panel__header .panel-broadcaster__icon[data-v-8b237ea4]{display:inline-block;flex-shrink:0;width:43px;height:24px;border-radius:3px;background:linear-gradient(150deg,var(--v-gray-base),var(--v-background-lighten2));-o-object-fit:cover;object-fit:cover;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-broadcaster__icon[data-v-8b237ea4]{width:38px;height:22px}}.watch-container .watch-panel .watch-panel__header .panel-broadcaster__number[data-v-8b237ea4]{flex-shrink:0;margin-left:8px;font-size:16px}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-broadcaster__number[data-v-8b237ea4]{font-size:14px}}.watch-container .watch-panel .watch-panel__header .panel-broadcaster__name[data-v-8b237ea4]{margin-left:5px;font-size:16px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__header .panel-broadcaster__name[data-v-8b237ea4]{font-size:14px}}.watch-container .watch-panel .watch-panel__content-container[data-v-8b237ea4]{position:relative;height:100%}.watch-container .watch-panel .watch-panel__content-container .watch-panel__content[data-v-8b237ea4]{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--v-background-base);transition:opacity .3s,visibility .3s;opacity:0;visibility:hidden}.watch-container .watch-panel .watch-panel__content-container .watch-panel__content--active[data-v-8b237ea4]{opacity:1;visibility:visible}.watch-container .watch-panel .watch-panel__navigation[data-v-8b237ea4]{display:flex;align-items:center;justify-content:space-evenly;flex-shrink:0;height:77px;background:var(--v-background-lighten1)}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__navigation[data-v-8b237ea4]{height:56px}}.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button[data-v-8b237ea4]{display:flex;justify-content:center;align-items:center;flex-direction:column;width:66px;height:56px;padding:6px 5.5px;border-radius:5px;color:var(--v-text-base);box-sizing:content-box;transition:color .3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button[data-v-8b237ea4]{height:42px;padding:6px 5.5px 4px}}.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button--active[data-v-8b237ea4]{color:var(--v-primary-base)}.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button__icon[data-v-8b237ea4]{height:30px}.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button__text[data-v-8b237ea4]{margin-top:5px;font-size:13px}@media screen and (max-height:450px){.watch-container .watch-panel .watch-panel__navigation .panel-navigation-button__text[data-v-8b237ea4]{margin-top:2px;font-size:12px}}.settings-container[data-v-18637a38]{width:100%}.settings-container .settings-navigation[data-v-18637a38]{position:sticky;top:85px!important}.settings-container .settings-navigation .v-list-item--link[data-v-18637a38]:before{border-radius:11px!important}.settings-container .settings[data-v-18637a38]{width:100%;border-radius:11px!important}.settings-container .settings[data-v-18637a38] .settings__heading{display:flex;align-items:center;font-size:22px}.settings-container .settings[data-v-18637a38] .settings__content{margin-top:24px}.settings-container .settings[data-v-18637a38] .settings__content .settings__item{display:flex;flex-direction:column;margin-top:24px}.settings-container .settings[data-v-18637a38] .settings__content .settings__item-heading{color:var(--v-text-base);font-size:16.5px}.settings-container .settings[data-v-18637a38] .settings__content .settings__item-label{margin-top:6px;color:var(--v-text-darken1);font-size:13.5px;line-height:1.6}.settings-container .settings[data-v-18637a38] .settings__content .settings__item-form{margin-top:12px} \ No newline at end of file diff --git a/client/dist/assets/js/app.d1a5668b.js b/client/dist/assets/js/app.bf991577.js similarity index 99% rename from client/dist/assets/js/app.d1a5668b.js rename to client/dist/assets/js/app.bf991577.js index b15fa8fd..72e69049 100644 --- a/client/dist/assets/js/app.d1a5668b.js +++ b/client/dist/assets/js/app.bf991577.js @@ -1,2 +1,2 @@ -(function(t){function e(e){for(var a,r,l=e[0],o=e[1],c=e[2],p=0,d=[];p$1');return s=s.replace(i,'$1'),s}return"title"==e?"放送休止":"この時間は放送を休止しています。"}},{key:"getAttribute",value:function(t,e,n){return null!==t&&void 0!==t[e]&&null!==t[e]?t[e]:n}},{key:"getChannelType",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.match("(?[a-z]+)[0-9]+").groups.channel_type.toUpperCase();return"GR"===n&&e?"地デジ":n}},{key:"getChannelForceType",value:function(t){return null===t?"normal":t>=1e3?"festival":t>=200?"so-many":t>=100?"many":"normal"}},{key:"getChannelFromRemoconID",value:function(t,e,n){e=e.replace("GR","地デジ");for(var a=t.get(e),i=0;i1&&void 0!==arguments[1]&&arguments[1];if(null!==t&&"2000-01-01T00:00:00+09:00"!==t.start_time){tt.a.locale("ja");var n=tt()(t.start_time),a=tt()(t.end_time),i=t.duration/60;return!0===e?"".concat(n.format("HH:mm")," ~ ").concat(a.format("HH:mm")):"".concat(n.format("YYYY/MM/DD (dd) HH:mm")," ~ ").concat(a.format("HH:mm")," (").concat(i,"分)")}return!0===e?"--:-- ~ --:--":"----/--/-- (-) --:-- ~ --:-- (--分)"}},{key:"getProgramProgress",value:function(t){if(null!==t){var e=tt()(tt()()).diff(t.start_time,"second");return e/t.duration*100}return 0}}]),t}()),nt=Q,at=r["a"].extend({name:"Navigation",data:function(){return{Utils:nt}}}),it=at,st=(n("d2ee"),Object(d["a"])(it,Y,W,!1,null,"4fdece88",null)),rt=st.exports;m()(st,{VSpacer:L["a"]}),$()(st,{Ripple:K["a"]});var lt=r["a"].extend({name:"Home",components:{Header:z,Navigation:rt},data:function(){return{Utils:nt,TVUtils:et,tab:null,is_loading:!0,interval_ids:[],channels_list:new Map,pinned_channel_ids:[]}},created:function(){var t=this;this.update();var e=60-Math.floor((new Date).getTime()/1e3)%60;this.interval_ids.push(window.setTimeout((function(){t.update(),t.interval_ids.push(window.setInterval((function(){t.update()}),3e4))}),1e3*e))},beforeDestroy:function(){var t,e=Object(D["a"])(this.interval_ids);try{for(e.s();!(t=e.n()).done;){var n=t.value;window.clearInterval(n)}}catch(a){e.e(a)}finally{e.f()}},methods:{update:function(){var t=this;return Object(A["a"])(regeneratorRuntime.mark((function e(){var n,a;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,r["a"].axios.get("".concat(nt.api_base_url,"/channels"));case 3:n=e.sent,e.next=10;break;case 6:return e.prev=6,e.t0=e["catch"](0),console.error(e.t0),e.abrupt("return");case 10:a=function(t){return t.is_display},t.channels_list=new Map,n.data.GR.length>0&&t.channels_list.set("地デジ",n.data.GR.filter(a)),n.data.BS.length>0&&t.channels_list.set("BS",n.data.BS.filter(a)),n.data.CS.length>0&&t.channels_list.set("CS",n.data.CS.filter(a)),n.data.CATV.length>0&&t.channels_list.set("CATV",n.data.CATV.filter(a)),n.data.SKY.length>0&&t.channels_list.set("SKY",n.data.SKY.filter(a)),n.data.STARDIGIO.length>0&&t.channels_list.set("StarDigio",n.data.STARDIGIO.filter(a)),t.updatePinnedChannelList(!!t.is_loading),t.is_loading=!1;case 20:case"end":return e.stop()}}),e,null,[[0,6]])})))()},addPinnedChannel:function(t){this.pinned_channel_ids=nt.getSettingsItem("pinned_channel_ids"),this.pinned_channel_ids.push(t),nt.setSettingsItem("pinned_channel_ids",this.pinned_channel_ids),this.updatePinnedChannelList()},removePinnedChannel:function(t){this.pinned_channel_ids=nt.getSettingsItem("pinned_channel_ids"),this.pinned_channel_ids.splice(this.pinned_channel_ids.indexOf(t),1),nt.setSettingsItem("pinned_channel_ids",this.pinned_channel_ids),this.updatePinnedChannelList()},updatePinnedChannelList:function(){var t=this,e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.pinned_channel_ids=nt.getSettingsItem("pinned_channel_ids");var n,a=[],i=Object(D["a"])(this.pinned_channel_ids);try{var s=function(){var e=n.value,i=et.getChannelType(e,!0);a.push(t.channels_list.get(i).find((function(t){return t.channel_id===e})))};for(i.s();!(n=i.n()).done;)s()}catch(r){i.e(r)}finally{i.f()}this.channels_list.has("ピン留め")?this.channels_list.set("ピン留め",a):this.channels_list=new Map([["ピン留め",a]].concat(Object(V["a"])(this.channels_list))),0===a.length&&!0===e&&(this.tab=1)},isPinnedChannel:function(t){return this.pinned_channel_ids.includes(t)}}}),ot=lt,ct=(n("92b8"),n("ee0e"),n("71a3")),ut=Object(d["a"])(ot,R,E,!1,null,"6a407b07",null),pt=ut.exports;m()(ut,{VSpacer:L["a"],VTab:ct["a"]}),$()(ut,{Ripple:K["a"]});var dt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"route-container"},[n("main",{staticClass:"watch-container",class:{"watch-container--control-display":t.is_control_display,"watch-container--panel-display":t.is_panel_display,"watch-container--fullscreen":t.is_fullscreen}},[n("nav",{staticClass:"watch-navigation",on:{mousemove:function(e){return t.controlDisplayTimer(e)},touchmove:function(e){return t.controlDisplayTimer(e)},click:function(e){return t.controlDisplayTimer(e)}}},[n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"watch-navigation__icon",attrs:{to:"/tv/"}},[n("img",{staticClass:"watch-navigation__icon-image",attrs:{src:"/assets/img/icon.svg",width:"23px"}})]),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"テレビをみる",expression:"'テレビをみる'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/tv/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:tv-20-regular",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"ビデオをみる",expression:"'ビデオをみる'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/videos/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:movies-and-tv-20-regular",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"番組表",expression:"'番組表'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/schedules/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:calendar-ltr-20-regular",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"キャプチャ",expression:"'キャプチャ'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/captures/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:image-multiple-24-regular",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"ウォッチリスト",expression:"'ウォッチリスト'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/watchlists/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"ic:round-playlist-play",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"視聴履歴",expression:"'視聴履歴'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/histories/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:history-16-regular",width:"26px"}})],1),n("v-spacer"),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"設定",expression:"'設定'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/settings/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:settings-20-regular",width:"26px"}})],1),n("a",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"version "+t.Utils.version,expression:"`version ${Utils.version}`",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",href:"https://github.com/tsukumijima/KonomiTV"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:info-16-regular",width:"26px"}})],1)],1),n("div",{staticClass:"watch-content",on:{mousemove:function(e){return t.controlDisplayTimer(e,!0)},touchmove:function(e){return t.controlDisplayTimer(e,!0)},click:function(e){return t.controlDisplayTimer(e,!0)}}},[n("header",{staticClass:"watch-header"},[n("img",{staticClass:"watch-header__broadcaster",attrs:{src:t.Utils.api_base_url+"/channels/"+t.$route.params.channel_id+"/logo"}}),n("span",{staticClass:"watch-header__program-title",domProps:{innerHTML:t._s(t.TVUtils.decorateProgramInfo(t.channel.program_present,"title"))}}),n("span",{staticClass:"watch-header__program-time"},[t._v(t._s(t.TVUtils.getProgramTime(t.channel.program_present,!0)))]),n("v-spacer"),n("span",{staticClass:"watch-header__now"},[t._v(t._s(t.time))])],1),n("div",{staticClass:"watch-player",class:{"watch-player--loading":t.is_loading}},[n("div",{staticClass:"watch-player__background",class:{"watch-player__background--display":t.is_background_display},style:{backgroundImage:"url("+t.background_url+")"}},[n("img",{staticClass:"watch-player__background-logo",attrs:{src:"/assets/img/logo.svg"}})]),n("div",{staticClass:"watch-player__dplayer"}),n("div",{staticClass:"watch-player__button",on:{mousemove:function(e){return t.controlDisplayTimer(e)},touchmove:function(e){return t.controlDisplayTimer(e)},click:function(e){return t.controlDisplayTimer(e)}}},[n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.top",value:"前のチャンネル",expression:"'前のチャンネル'",modifiers:{top:!0}}],staticClass:"switch-button switch-button-up",attrs:{to:"/tv/watch/"+t.channel_previous.channel_id}},[n("Icon",{staticClass:"switch-button-icon",attrs:{icon:"fluent:ios-arrow-left-24-filled",width:"32px",rotate:"1"}})],1),n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"switch-button switch-button-panel switch-button-panel--open",on:{click:function(e){t.is_panel_display=!t.is_panel_display}}},[n("Icon",{staticClass:"switch-button-icon",attrs:{icon:"fluent:navigation-16-filled",width:"32px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.bottom",value:"次のチャンネル",expression:"'次のチャンネル'",modifiers:{bottom:!0}}],staticClass:"switch-button switch-button-down",attrs:{to:"/tv/watch/"+t.channel_next.channel_id}},[n("Icon",{staticClass:"switch-button-icon",attrs:{icon:"fluent:ios-arrow-right-24-filled",width:"33px",rotate:"1"}})],1)],1)])]),n("div",{staticClass:"watch-panel",on:{mousemove:function(e){return t.controlDisplayTimer(e)},touchmove:function(e){return t.controlDisplayTimer(e)},click:function(e){return t.controlDisplayTimer(e)}}},[n("div",{staticClass:"watch-panel__header"},[n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-close-button",on:{click:function(e){t.is_panel_display=!1}}},[n("Icon",{staticClass:"panel-close-button__icon",attrs:{icon:"akar-icons:chevron-right",width:"25px"}}),n("span",{staticClass:"panel-close-button__text"},[t._v("閉じる")])],1),n("v-spacer"),n("div",{staticClass:"panel-broadcaster"},[n("img",{staticClass:"panel-broadcaster__icon",attrs:{src:t.Utils.api_base_url+"/channels/"+t.$route.params.channel_id+"/logo"}}),n("div",{staticClass:"panel-broadcaster__number"},[t._v(t._s(t.channel.channel_number))]),n("div",{staticClass:"panel-broadcaster__name"},[t._v(t._s(t.channel.channel_name))])])],1),n("div",{staticClass:"watch-panel__content-container"},[n("Program",{staticClass:"watch-panel__content",class:{"watch-panel__content--active":"Program"===t.panel_active_tab},attrs:{channel:t.channel}}),n("Channel",{staticClass:"watch-panel__content",class:{"watch-panel__content--active":"Channel"===t.panel_active_tab},attrs:{channels_list:t.channels_list}}),n("Comment",{staticClass:"watch-panel__content",class:{"watch-panel__content--active":"Comment"===t.panel_active_tab},attrs:{channel:t.channel,player:t.player}})],1),n("div",{staticClass:"watch-panel__navigation"},[n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-navigation-button",class:{"panel-navigation-button--active":"Program"===t.panel_active_tab},on:{click:function(e){t.panel_active_tab="Program"}}},[n("Icon",{staticClass:"panel-navigation-button__icon",attrs:{icon:"fa-solid:info-circle",width:"33px"}}),n("span",{staticClass:"panel-navigation-button__text"},[t._v("番組情報")])],1),n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-navigation-button",class:{"panel-navigation-button--active":"Channel"===t.panel_active_tab},on:{click:function(e){t.panel_active_tab="Channel"}}},[n("Icon",{staticClass:"panel-navigation-button__icon",attrs:{icon:"fa-solid:broadcast-tower",width:"34px"}}),n("span",{staticClass:"panel-navigation-button__text"},[t._v("チャンネル")])],1),n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-navigation-button",class:{"panel-navigation-button--active":"Comment"===t.panel_active_tab},on:{click:function(e){t.panel_active_tab="Comment"}}},[n("Icon",{staticClass:"panel-navigation-button__icon",attrs:{icon:"bi:chat-left-text-fill",width:"29px"}}),n("span",{staticClass:"panel-navigation-button__text"},[t._v("コメント")])],1),n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-navigation-button",class:{"panel-navigation-button--active":"Twitter"===t.panel_active_tab},on:{click:function(e){t.panel_active_tab="Twitter"}}},[n("Icon",{staticClass:"panel-navigation-button__icon",attrs:{icon:"fa-brands:twitter",width:"34px"}}),n("span",{staticClass:"panel-navigation-button__text"},[t._v("Twitter")])],1)])])]),n("v-dialog",{attrs:{"max-width":"980",transition:"slide-y-transition"},model:{value:t.shortcut_key_modal,callback:function(e){t.shortcut_key_modal=e},expression:"shortcut_key_modal"}},[n("v-card",[n("v-card-title",{staticClass:"px-5 pt-4 pb-3 d-flex align-center font-weight-bold"},[n("Icon",{attrs:{icon:"fluent:keyboard-20-filled",height:"28px"}}),n("span",{staticClass:"ml-3"},[t._v("キーボードショートカット")])],1),n("div",{staticClass:"px-5 pb-4"},[n("v-row",t._l(t.shortcut_key_list,(function(e,a){return n("v-col",{key:a,attrs:{cols:"6"}},t._l(e,(function(e){return n("div",{key:e.name,staticClass:"mt-3"},[n("div",{staticClass:"text-subtitle-1 d-flex align-center font-weight-bold"},[n("Icon",{attrs:{icon:e.icon,height:e.icon_height}}),n("span",{staticClass:"ml-2"},[t._v(t._s(e.name))])],1),t._l(e.shortcuts,(function(e){return n("div",{key:e.name,staticClass:"mt-3"},[n("div",{staticClass:"text-subtitle-2 mt-2 d-flex align-center font-weight-medium"},[n("span",{staticClass:"mr-2",domProps:{innerHTML:t._s(e.name)}}),n("div",{staticClass:"ml-auto d-flex align-center flex-shrink-0"},t._l(e.keys,(function(a,i){return n("div",{key:a.name,staticClass:"ml-auto d-flex align-center"},[!0===a.icon?n("Icon",{staticClass:"shortcut-key",attrs:{icon:a.name,height:"18px"}}):t._e(),!1===a.icon?n("span",{staticClass:"shortcut-key"},[t._v(t._s(a.name))]):t._e(),in.comment_list_element.clientWidth&&(i=!0)},n.comment_list_element.onmouseup=function(t){var e=t.clientX-n.comment_list_element.getBoundingClientRect().left;e>n.comment_list_element.clientWidth&&(i=!1)},s=function(){i=!0,window.setTimeout((function(){return i=!1}),100)},r=!1,n.comment_list_element.ontouchstart=function(){return r=!0},n.comment_list_element.ontouchend=function(){return r=!1},n.comment_list_element.ontouchmove=function(){return!0===r?s():""},n.comment_list_element.onwheel=s,n.comment_list_element.onscroll=Object(A["a"])(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(!1!==n.is_auto_scrolling||!0!==i){t.next=5;break}return n.is_manual_scroll=!0,t.next=4,new Promise((function(t){return setTimeout(t,100)}));case 4:n.comment_list_element.scrollTop+n.comment_list_element.offsetHeight>n.comment_list_element.scrollHeight-10&&(n.is_manual_scroll=!1);case 5:case"end":return t.stop()}}),t)}))),a.next=20,n.initWatchSession();case 20:return l=a.sent,a.next=23,n.initCommentSession(l);case 23:return a.next=25,n.initReserveObserver();case 25:case"end":return a.stop()}}),a)})))()}},methods:{initWatchSession:function(){var t=this;return Object(A["a"])(regeneratorRuntime.mark((function e(){var n;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,r["a"].axios.get("".concat(nt.api_base_url,"/channels/").concat(t.channel.channel_id,"/jikkyo"));case 3:n=e.sent,e.next=9;break;case 6:throw e.prev=6,e.t0=e["catch"](0),new Error(e.t0);case 9:if(!1!==n.data.is_success){e.next=11;break}throw new Error(n.data.detail);case 11:return e.abrupt("return",new Promise((function(e){t.watch_session=new WebSocket(n.data.audience_token),t.watch_session.addEventListener("open",(function(){t.watch_session.send(JSON.stringify({type:"startWatching",data:{reconnect:!1}}))})),t.watch_session.addEventListener("message",function(){var n=Object(A["a"])(regeneratorRuntime.mark((function n(a){var i,s,r,l,o;return regeneratorRuntime.wrap((function(n){while(1)switch(n.prev=n.next){case 0:i=JSON.parse(a.data),n.t0=i.type,n.next="room"===n.t0?4:"seat"===n.t0?5:"ping"===n.t0?7:"error"===n.t0?9:"reconnect"===n.t0?33:"disconnect"===n.t0?43:79;break;case 4:return n.abrupt("return",e({thread_id:i.data.threadId,your_post_key:i.data.yourPostKey?i.data.yourPostKey:null,message_server:i.data.messageServer.uri}));case 5:return t.keep_seat_interval_id=window.setInterval((function(){1===t.watch_session.readyState?t.watch_session.send(JSON.stringify({type:"keepSeat"})):window.clearInterval(t.keep_seat_interval_id)}),1e3*i.data.keepIntervalSec),n.abrupt("break",79);case 7:return t.watch_session.send(JSON.stringify({type:"pong"})),n.abrupt("break",79);case 9:n.t1=i.data.code,n.next="CONNECT_ERROR"===n.t1?12:"CONTENT_NOT_READY"===n.t1?14:"NO_THREAD_AVAILABLE"===n.t1?16:"NO_ROOM_AVAILABLE"===n.t1?18:"NO_PERMISSION"===n.t1?20:"NOT_ON_AIR"===n.t1?22:"BROADCAST_NOT_FOUND"===n.t1?24:"INTERNAL_SERVERERROR"===n.t1?26:28;break;case 12:return s="コメントサーバーに接続できません。",n.abrupt("break",30);case 14:return s="ニコニコ実況が配信できない状態です。",n.abrupt("break",30);case 16:return s="コメントスレッドを取得できません。",n.abrupt("break",30);case 18:return s="コメント部屋を取得できません。",n.abrupt("break",30);case 20:return s="API にアクセスする権限がありません。",n.abrupt("break",30);case 22:return s="ニコニコ実況が放送中ではありません。",n.abrupt("break",30);case 24:return s="ニコニコ実況の配信情報を取得できません。",n.abrupt("break",30);case 26:return s="ニコニコ実況でサーバーエラーが発生しています。",n.abrupt("break",30);case 28:return s="ニコニコ実況でエラーが発生しています。(".concat(i.data.code,")"),n.abrupt("break",30);case 30:return console.log("error occurred. code: ".concat(i.data.code)),t.player.danmaku.showing&&t.player.notice(s),n.abrupt("break",79);case 33:return t.destroy(),n.next=36,new Promise((function(t){return setTimeout(t,1e3*i.data.waitTimeSec)}));case 36:return t.player.danmaku.showing&&t.player.notice("ニコニコ実況に再接続しています…"),n.next=39,t.initWatchSession();case 39:return r=n.sent,n.next=42,t.initCommentSession(r);case 42:return n.abrupt("break",79);case 43:t.watch_session&&(t.watch_session.onclose=null),n.t2=i.data.reason,n.next="TAKEOVER"===n.t2?47:"NO_PERMISSION"===n.t2?49:"END_PROGRAM"===n.t2?51:"PING_TIMEOUT"===n.t2?53:"TOO_MANY_CONNECTIONS"===n.t2?55:"TOO_MANY_WATCHINGS"===n.t2?57:"CROWDED"===n.t2?59:"MAINTENANCE_IN"===n.t2?61:"SERVICE_TEMPORARILY_UNAVAILABLE"===n.t2?63:65;break;case 47:return l="ニコニコ実況の番組から追い出されました。",n.abrupt("break",67);case 49:return l="ニコニコ実況の番組の座席を取得できませんでした。",n.abrupt("break",67);case 51:return l="ニコニコ実況がリセットされたか、コミュニティの番組が終了しました。",n.abrupt("break",67);case 53:return l="コメントサーバーとの接続生存確認に失敗しました。",n.abrupt("break",67);case 55:return l="ニコニコ実況の同一ユーザからの接続数上限を越えています。",n.abrupt("break",67);case 57:return l="ニコニコ実況の同一ユーザからの視聴番組数上限を越えています。",n.abrupt("break",67);case 59:return l="ニコニコ実況の番組が満席です。",n.abrupt("break",67);case 61:return l="ニコニコ実況はメンテナンス中です。",n.abrupt("break",67);case 63:return l="ニコニコ実況で一時的にサーバーエラーが発生しています。",n.abrupt("break",67);case 65:return l="ニコニコ実況との接続が切断されました。(".concat(i.data.reason,")"),n.abrupt("break",67);case 67:return console.log("disconnected. reason: ".concat(i.data.reason)),t.player.danmaku.showing&&t.player.notice(l),t.destroy(),n.next=72,new Promise((function(t){return setTimeout(t,5e3)}));case 72:return t.player.danmaku.showing&&t.player.notice("ニコニコ実況に再接続しています…"),n.next=75,t.initWatchSession();case 75:return o=n.sent,n.next=78,t.initCommentSession(o);case 78:return n.abrupt("break",79);case 79:case"end":return n.stop()}}),n)})));return function(t){return n.apply(this,arguments)}}()),t.watch_session.onclose=function(){var e=Object(A["a"])(regeneratorRuntime.mark((function e(n){var a;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return console.log("disconnected. code: ".concat(n.code)),t.player.danmaku.showing&&t.player.notice("ニコニコ実況との接続が切断されました。(code: ".concat(n.code,")")),t.destroy(),e.next=5,new Promise((function(t){return setTimeout(t,1e4)}));case 5:return t.player.danmaku.showing&&t.player.notice("ニコニコ実況に再接続しています…"),e.next=8,t.initWatchSession();case 8:return a=e.sent,e.next=11,t.initCommentSession(a);case 11:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()})));case 12:case"end":return e.stop()}}),e,null,[[0,6]])})))()},initCommentSession:function(t){var e=this;return Object(A["a"])(regeneratorRuntime.mark((function n(){var a,i;return regeneratorRuntime.wrap((function(n){while(1)switch(n.prev=n.next){case 0:a=[],i=!1,e.comment_session=new WebSocket(t.message_server),e.comment_session.addEventListener("open",(function(){e.comment_session.send(JSON.stringify([{ping:{content:"rs:0"}},{ping:{content:"ps:0"}},{thread:{version:"20061206",thread:t.thread_id,threadkey:t.your_post_key,user_id:"",res_from:-50}},{ping:{content:"pf:0"}},{ping:{content:"rf:0"}}]))})),e.comment_session.addEventListener("message",function(){var t=Object(A["a"])(regeneratorRuntime.mark((function t(n){var s,r,l,o,c,u,p,d,_,m,h;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(s=JSON.parse(n.data),void 0!==s.thread&&(0===s.thread.resultcode||(r="コメントサーバーに接続できませんでした。",console.error("Error: "+r))),void 0!==s.ping&&"rf:0"===s.ping.content&&(i=!0,e.scrollCommentList()),l=s.chat,void 0!==l&&void 0!==l.content&&!l.content.match(/\/[a-z]+ /)){t.next=6;break}return t.abrupt("return");case 6:if(!l.yourpost||1!==l.yourpost){t.next=8;break}return t.abrupt("return");case 8:if(o="#FFEAEA",c="right",void 0!==l.mail&&null!==l.mail){u=l.mail.replace("184","").split(" "),p=Object(D["a"])(u);try{for(p.s();!(d=p.n()).done;)_=d.value,null!==e.getCommentColor(_)&&(o=e.getCommentColor(_)),null!==e.getCommentPosition(_)&&(c=e.getCommentPosition(_))}catch(v){p.e(v)}finally{p.f()}}if(!i){t.next=15;break}return m=nt.getSettingsItem("comment_delay_time"),t.next=15,new Promise((function(t){return setTimeout(t,1e3*m)}));case 15:if(e.comment_list.length>500&&e.comment_list.shift(),h={id:l.no,text:l.content,time:tt()(1e3*l.date).format("HH:mm:ss")},"hidden"!==document.visibilityState){t.next=20;break}return a.push(h),t.abrupt("return");case 20:e.comment_list.push(h),i&&e.scrollCommentList(),i&&(e.player.video.paused||e.player.danmaku.draw({text:l.content,color:o,type:c}));case 23:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),document.onvisibilitychange=function(){var t;"visible"===document.visibilityState&&((t=e.comment_list).push.apply(t,Object(V["a"])(a)),a=[],e.scrollCommentList())};case 6:case"end":return n.stop()}}),n)})))()},initReserveObserver:function(){var t=this;return Object(A["a"])(regeneratorRuntime.mark((function e(){var n,a;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:t.resize_observer_element=document.querySelector(".watch-player"),n=null,a=function(){var e=document.querySelector(".dplayer-video-wrap-aspect"),a=document.querySelector(".dplayer-danmaku");if(null!==t.resize_observer_element&&null!==t.resize_observer_element.clientHeight&&null!==e&&null!==e.clientHeight){var i=(t.resize_observer_element.clientHeight-e.clientHeight)/2,s=window.matchMedia("(max-height: 450px)").matches?50:66;if(i0&&void 0!==t[0]&&t[0],!0!==e.is_manual_scroll){n.next=3;break}return n.abrupt("return");case 3:e.is_auto_scrolling=!0,i=0;case 5:if(!(i<3)){n.next=12;break}return n.next=8,new Promise((function(t){return setTimeout(t,10)}));case 8:!0===a?e.comment_list_element.scrollTo({top:e.comment_list_element.scrollHeight,left:0,behavior:"smooth"}):e.comment_list_element.scrollTo(0,e.comment_list_element.scrollHeight);case 9:i++,n.next=5;break;case 12:return n.next=14,new Promise((function(t){return setTimeout(t,100)}));case 14:e.is_auto_scrolling=!1;case 15:case"end":return n.stop()}}),n)})))()},getCommentColor:function(t){var e={red:"#E54256",pink:"#FF8080",orange:"#FFC000",yellow:"#FFE133",green:"#64DD17",cyan:"#39CCFF",blue:"#0000FF",purple:"#D500F9",black:"#1E1310",white:"#FFEAEA",white2:"#CCCC99",niconicowhite:"#CCCC99",red2:"#CC0033",truered:"#CC0033",pink2:"#FF33CC",orange2:"#FF6600",passionorange:"#FF6600",yellow2:"#999900",madyellow:"#999900",green2:"#00CC66",elementalgreen:"#00CC66",cyan2:"#00CCCC",blue2:"#3399FF",marineblue:"#3399FF",purple2:"#6633CC",nobleviolet:"#6633CC",black2:"#666666"};return void 0!==e[t]?e[t]:null},getCommentPosition:function(t){switch(t){case"ue":return"top";case"naka":return"right";case"shita":return"bottom";default:return null}},destroy:function(){this.comment_list=[],document.onvisibilitychange=null,null!==this.watch_session&&(this.watch_session.onclose=null,this.watch_session.close(),this.watch_session=null),null!==this.comment_session&&(this.comment_session.onclose=null,this.comment_session.close(),this.comment_session=null),window.clearInterval(this.keep_seat_interval_id)}}})),Nt=Ot,Rt=(n("1548"),Object(d["a"])(Nt,It,Pt,!1,null,"7575b645",null)),Et=Rt.exports;$()(Rt,{Ripple:K["a"]});var Vt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"program-container"},[n("section",{staticClass:"program-broadcaster"},[n("img",{staticClass:"program-broadcaster__icon",attrs:{src:t.Utils.api_base_url+"/channels/"+t.$route.params.channel_id+"/logo"}}),n("div",{staticClass:"program-broadcaster__number"},[t._v("Ch: "+t._s(t.channel.channel_number))]),n("div",{staticClass:"program-broadcaster__name"},[t._v(t._s(t.channel.channel_name))])]),n("section",{staticClass:"program-info"},[n("h1",{staticClass:"program-info__title",domProps:{innerHTML:t._s(t.TVUtils.decorateProgramInfo(t.channel.program_present,"title"))}}),n("div",{staticClass:"program-info__time"},[t._v(t._s(t.TVUtils.getProgramTime(t.channel.program_present)))]),n("div",{staticClass:"program-info__description",domProps:{innerHTML:t._s(t.TVUtils.decorateProgramInfo(t.channel.program_present,"description"))}}),n("div",{staticClass:"program-info__genre-container"},t._l(t.TVUtils.getAttribute(t.channel.program_present,"genre",[]),(function(e,a){return n("div",{key:a,staticClass:"program-info__genre"},[t._v(" "+t._s(e.major)+" / "+t._s(e.middle)+" ")])})),0),n("div",{staticClass:"program-info__next"},[n("span",{staticClass:"program-info__next-decorate"},[t._v("NEXT")]),n("Icon",{staticClass:"program-info__next-icon",attrs:{icon:"fluent:fast-forward-20-filled",width:"16px"}})],1),n("span",{staticClass:"program-info__next-title",domProps:{innerHTML:t._s(t.TVUtils.decorateProgramInfo(t.channel.program_following,"title"))}}),n("div",{staticClass:"program-info__next-time"},[t._v(t._s(t.TVUtils.getProgramTime(t.channel.program_following)))]),n("div",{staticClass:"program-info__status"},[n("div",{staticClass:"program-info__status-force",class:"program-info__status-force--"+t.TVUtils.getChannelForceType(t.channel.channel_force)},[n("Icon",{attrs:{icon:"fa-solid:fire-alt",height:"14px"}}),n("span",{staticClass:"ml-2"},[t._v("勢い:")]),n("span",{staticClass:"ml-2"},[t._v(t._s(t.TVUtils.getAttribute(t.channel,"channel_force","--"))+" コメ/分")])],1),n("div",{staticClass:"program-info__status-viewers ml-5"},[n("Icon",{attrs:{icon:"fa-solid:eye",height:"14px"}}),n("span",{staticClass:"ml-2"},[t._v("視聴数:")]),n("span",{staticClass:"ml-1"},[t._v(t._s(t.channel.viewers))])],1)])]),n("section",{staticClass:"program-detail-container"},t._l(t.TVUtils.getAttribute(t.channel.program_present,"detail",{}),(function(e,a){return n("div",{key:a,staticClass:"program-detail"},[n("h2",{staticClass:"program-detail__heading"},[t._v(t._s(a))]),n("div",{staticClass:"program-detail__text"},[t._v(t._s(e))])])})),0)])},At=[],Dt=r["a"].extend({name:"Program",props:{channel:{type:Object,required:!0}},data:function(){return{Utils:nt,TVUtils:et}}}),jt=Dt,Mt=(n("9652"),Object(d["a"])(jt,Vt,At,!1,null,"00e07beb",null)),Ht=Mt.exports,Ft=r["a"].extend({name:"Watch",components:{Channel:Tt,Comment:Et,Program:Ht},data:function(){return{Utils:nt,TVUtils:et,time:tt()().format("YYYY/MM/DD HH:mm:ss"),panel_active_tab:nt.getSettingsItem("panel_active_tab"),background_url:"",is_loading:!0,is_background_display:!1,is_control_display:!0,is_panel_display:function(){switch(nt.getSettingsItem("panel_display_state")){case"AlwaysDisplay":return!0;case"AlwaysFold":return!1;case"RestorePreviousState":return nt.getSettingsItem("is_latest_panel_display")}}(),is_fullscreen:!1,interval_ids:[],control_interval_id:0,channel_id:this.$route.params.channel_id,channel:bt,channel_previous:bt,channel_next:bt,channels_list:new Map,player:null,eventsource:null,fullscreen_handler:null,shortcut_key_handler:null,shortcut_key_pressed_at:Date.now(),shortcut_key_modal:!1,shortcut_key_list:{left_column:[{name:"全般",icon:"fluent:home-20-filled",icon_height:"22px",shortcuts:[{name:"数字キー・テンキーに対応するリモコン番号 (1~12) のチャンネルに切り替える
(同時に Shift キーを押すと、地デジならBS、BSなら地デジのチャンネルを選局する)",keys:[{name:"1~9, 0, -(=), ^(~)",icon:!1}]},{name:"前のチャンネルに切り替える",keys:[{name:"fluent:arrow-up-12-filled",icon:!0}]},{name:"次のチャンネルに切り替える",keys:[{name:"fluent:arrow-down-12-filled",icon:!0}]},{name:"キーボードショートカットの一覧を表示する",keys:[{name:"/(?)",icon:!1}]}]},{name:"パネル",icon:"fluent:panel-right-20-filled",icon_height:"24px",shortcuts:[{name:"パネルの表示切り替え",keys:[{name:"P",icon:!1}]},{name:"番組情報タブを表示する",keys:[{name:"K",icon:!1}]},{name:"チャンネルタブを表示する",keys:[{name:"L",icon:!1}]},{name:"コメントタブを表示する",keys:[{name:";(+)",icon:!1}]},{name:"Twitter タブを表示する",keys:[{name:":(*)",icon:!1}]}]}],right_column:[{name:"プレイヤー",icon:"fluent:play-20-filled",icon_height:"20px",shortcuts:[{name:"再生 / 一時停止の切り替え",keys:[{name:"Space",icon:!1}]},{name:"停止して0.25秒早戻し",keys:[{name:"fluent:arrow-left-12-filled",icon:!0}]},{name:"停止して0.25秒早送り",keys:[{name:"fluent:arrow-right-12-filled",icon:!0}]},{name:"フルスクリーンの切り替え",keys:[{name:"F",icon:!1}]},{name:"ライブストリームの同期",keys:[{name:"W",icon:!1}]},{name:"Picture-in-Picture の表示切り替え",keys:[{name:"E",icon:!1}]},{name:"字幕の表示切り替え",keys:[{name:"S",icon:!1}]},{name:"コメントの表示切り替え",keys:[{name:"D",icon:!1}]},{name:"コメント入力フォームにフォーカスする",keys:[{name:"M",icon:!1}]}]}]}}},created:function(){this.init()},beforeDestroy:function(){this.destroy(!0),null!==this.shortcut_key_handler&&(document.removeEventListener("keydown",this.shortcut_key_handler),this.shortcut_key_handler=null)},beforeRouteUpdate:function(t,e,n){var a=this;this.destroy(),this.channel_id=t.params.channel_id;var i=et.getPreviousAndCurrentAndNextChannel(this.channels_list,this.channel_id),s=Object(mt["a"])(i,3);this.channel_previous=s[0],this.channel=s[1],this.channel_next=s[2],this.interval_ids.push(window.setTimeout((function(){a.init()}),500)),n()},watch:{is_panel_display:function(){nt.setSettingsItem("is_latest_panel_display",this.is_panel_display)}},methods:{init:function(){var t=this;this.background_url=nt.generatePlayerBackgroundURL(),this.controlDisplayTimer(),this.update(),this.interval_ids.push(window.setInterval((function(){t.time=tt()().format("YYYY/MM/DD HH:mm:ss")}),1e3));var e=60-Math.floor((new Date).getTime()/1e3)%60;this.interval_ids.push(window.setTimeout((function(){t.update(),t.interval_ids.push(window.setInterval((function(){t.update()}),3e4))}),1e3*e))},update:function(){var t=this;return Object(A["a"])(regeneratorRuntime.mark((function e(){var n,a,i,s,l,o,c,u,p,d,_;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:if(void 0!==t.$route.params.channel_id){e.next=2;break}return e.abrupt("return");case 2:return e.prev=2,e.next=5,r["a"].axios.get("".concat(nt.api_base_url,"/channels/").concat(t.channel_id));case 5:n=e.sent,e.next=15;break;case 8:if(e.prev=8,e.t0=e["catch"](2),console.error(e.t0),!e.t0.response||422!==e.t0.response.status||"Specified channel_id was not found"!==e.t0.response.data.detail){e.next=14;break}return e.next=14,t.$router.replace({path:"/not-found/"});case 14:return e.abrupt("return");case 15:return t.channel=n.data,null!==t.player&&!0!==t.player.KonomiTVCanDestroy||(t.initPlayer(),t.initEventHandler(),t.initShortcutKeyHandler()),null===t.channel.program_present||"1/0+1/0モード(デュアルモノ)"!==t.channel.program_present.primary_audio_type&&null===t.channel.program_present.secondary_audio_type?(t.player.template.audioItem[1].classList.add("dplayer-setting-audio-item--disabled"),t.player.plugins.mpegts&&window.setTimeout((function(){t.player.template.audioItem[0].classList.add("dplayer-setting-audio-current"),t.player.template.audioItem[1].classList.remove("dplayer-setting-audio-current"),t.player.template.audioValue.textContent=t.player.tran("Primary audio");try{t.player.plugins.mpegts.switchPrimaryAudio()}catch(e){}}),300)):t.player.template.audioItem[1].classList.remove("dplayer-setting-audio-item--disabled"),e.prev=18,e.next=21,r["a"].axios.get("".concat(nt.api_base_url,"/channels"));case 21:a=e.sent,e.next=28;break;case 24:return e.prev=24,e.t1=e["catch"](18),console.error(e.t1),e.abrupt("return");case 28:i=function(e){return e.is_display||t.channel_id===e.channel_id},t.channels_list=new Map,t.channels_list.set("ピン留め",[]),a.data.GR.length>0&&t.channels_list.set("地デジ",a.data.GR.filter(i)),a.data.BS.length>0&&t.channels_list.set("BS",a.data.BS.filter(i)),a.data.CS.length>0&&t.channels_list.set("CS",a.data.CS.filter(i)),a.data.CATV.length>0&&t.channels_list.set("CATV",a.data.CATV.filter(i)),a.data.SKY.length>0&&t.channels_list.set("SKY",a.data.SKY.filter(i)),a.data.STARDIGIO.length>0&&t.channels_list.set("StarDigio",a.data.STARDIGIO.filter(i)),s=nt.getSettingsItem("pinned_channel_ids"),l=[],o=Object(D["a"])(s);try{for(u=function(){var e=c.value,n=et.getChannelType(e,!0);l.push(t.channels_list.get(n).find((function(t){return t.channel_id===e})))},o.s();!(c=o.n()).done;)u()}catch(m){o.e(m)}finally{o.f()}l.length>0?t.channels_list.set("ピン留め",l):t.channels_list.delete("ピン留め"),p=et.getPreviousAndCurrentAndNextChannel(t.channels_list,t.channel_id),d=Object(mt["a"])(p,3),t.channel_previous=d[0],t.channel_next=d[2],"mediaSession"in navigator&&(_=[{src:"/assets/img/icons/icon-maskable-192px.png",sizes:"192x192",type:"image/png"},{src:"/assets/img/icons/icon-maskable-512px.png",sizes:"512x512",type:"image/png"}],navigator.mediaSession.metadata=new MediaMetadata({title:t.channel.program_present?t.channel.program_present.title:"放送休止",artist:t.channel.channel_name,artwork:_}),"setPositionState"in navigator.mediaSession&&navigator.mediaSession.setPositionState({duration:0,playbackRate:1}),navigator.mediaSession.setActionHandler("play",(function(){t.player.play()})),navigator.mediaSession.setActionHandler("pause",(function(){t.player.pause()})),navigator.mediaSession.setActionHandler("previoustrack",Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return navigator.mediaSession.metadata=new MediaMetadata({title:t.channel_previous.program_present?t.channel_previous.program_present.title:"放送休止",artist:t.channel_previous.channel_name,artwork:_}),e.next=3,t.$router.replace({path:"/tv/watch/".concat(t.channel_previous.channel_id)});case 3:case"end":return e.stop()}}),e)})))),navigator.mediaSession.setActionHandler("nexttrack",Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return navigator.mediaSession.metadata=new MediaMetadata({title:t.channel_next.program_present?t.channel_next.program_present.title:"放送休止",artist:t.channel_next.channel_name,artwork:_}),e.next=3,t.$router.replace({path:"/tv/watch/".concat(t.channel_next.channel_id)});case 3:case"end":return e.stop()}}),e)})))));case 47:case"end":return e.stop()}}),e,null,[[2,8],[18,24]])})))()},controlDisplayTimer:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=/iPhone|iPad|iPod|Macintosh|Android|Mobile/i.test(navigator.userAgent)&&"ontouchend"in document;if((1!=a||null===e||"mousemove"!==e.type)&&(0!=a||null===e||"touchmove"!==e.type&&"click"!==e.type)){window.clearTimeout(this.control_interval_id);var i=function e(){document.activeElement!==t.player.template.commentInput?(t.is_control_display=!1,null!==t.player&&(t.player.controller.hide(),t.player.setting.hide())):t.control_interval_id=window.setTimeout(e,3e3)};!0===a&&!0===n?this.player.controller.isShow()?(this.is_control_display=!0,this.player.controller.show(),this.control_interval_id=window.setTimeout(i,3e3)):(this.is_control_display=!1,this.player.controller.hide(),this.player.setting.hide()):(this.is_control_display=!0,null!==this.player&&this.player.controller.show(),this.control_interval_id=window.setTimeout(i,3e3))}},initPlayer:function(){var t=this;if(window.mpegts=ft.a,null!==this.player&&!0===this.player.KonomiTVCanDestroy){try{this.player.destroy()}catch(s){void 0!==this.player.plugins.mpegts&&this.player.plugins.mpegts.destroy()}this.player=null}this.player=new vt.a({container:this.$el.querySelector(".watch-player__dplayer"),theme:"#E64F97",lang:"ja-jp",live:!0,loop:!1,airplay:!1,autoplay:!0,hotkey:!1,screenshot:!0,volume:1,video:{defaultQuality:this.channel.is_radiochannel?"48kHz/192kbps":nt.getSettingsItem("tv_streaming_quality"),quality:function(){var e=[];if(t.channel.is_radiochannel)e.push({name:"48kHz/192kbps",type:"mpegts",url:"".concat(nt.api_base_url,"/streams/live/").concat(t.channel_id,"/1080p/mpegts")});else for(var n=0,a=["1080p","810p","720p","540p","480p","360p","240p"];n\n キーボードショートカット\n
\n \n \n \n
\n ');var n=this.player.template.settingOriginPanel.scrollHeight;this.player.template.settingBox.style.clipPath="inset(calc(100% - ".concat(n,"px) 0 0 round 7px)"),this.$el.querySelector(".dplayer-setting-keyboard-shortcut").addEventListener("click",(function(){t.player.setting.hide(),t.shortcut_key_modal=!0}))}var a=function(){t.player.setting.hide(),t.controlDisplayTimer()};this.player.on("play",a),this.player.on("pause",a),this.player.on("quality_start",(function(){t.background_url=nt.generatePlayerBackgroundURL(),null!==t.eventsource&&(t.eventsource.close(),t.eventsource=null),t.initEventHandler()})),this.player.plugins.aribb24Superimpose.show(),this.player.on("subtitle_hide",(function(){t.player.plugins.aribb24Superimpose.show()})),this.interval_ids.push(window.setInterval((function(){t.player.video.paused&&t.player.video.buffered.end(0)-t.player.video.currentTime>30&&t.player.sync()}),6e4));var i=this.$el;this.fullscreen_handler=function(){return t.is_fullscreen=t.player.fullScreen.isFullScreen()},void 0!==i.onfullscreenchange?i.addEventListener("fullscreenchange",this.fullscreen_handler):i.addEventListener("webkitfullscreenchange",this.fullscreen_handler),this.player.fullScreen.isFullScreen=function(t){return!(!document.fullscreenElement&&!document.webkitFullscreenElement)},this.player.fullScreen.request=function(e){t.player.fullScreen.isFullScreen()?t.player.fullScreen.cancel():(i.requestFullscreen=i.requestFullscreen||i.webkitRequestFullscreen,i.requestFullscreen&&i.requestFullscreen(),screen.orientation&&screen.orientation.lock("landscape").catch((function(){})))},this.player.fullScreen.cancel=function(t){document.exitFullscreen=document.exitFullscreen||document.webkitExitFullscreen,document.exitFullscreen&&document.exitFullscreen(),screen.orientation&&screen.orientation.unlock()}},initEventHandler:function(){var t=this;this.is_loading=!0;var e=function(){window.setTimeout((function(){t.is_loading=!1,t.channel.is_radiochannel?t.is_background_display=!0:t.is_background_display=!1}),100),t.player.video.oncanplay=null,t.player.video.oncanplaythrough=null};this.player.video.oncanplay=e,this.player.video.oncanplaythrough=e;var n=this.channel.is_radiochannel?"1080p":this.player.quality.name;this.eventsource=new EventSource("".concat(nt.api_base_url,"/streams/live/").concat(this.channel_id,"/").concat(n,"/events")),this.eventsource.addEventListener("initial_update",(function(e){var n=JSON.parse(e.data);"Standby"===n.status&&(t.is_background_display=!0)})),this.eventsource.addEventListener("status_update",(function(e){var n=JSON.parse(e.data);switch(console.log("Status: ".concat(n.status," Detail:").concat(n.detail)),t.channel.viewers=n.clients_count,n.status){case"Standby":t.player.template.notice.textContent.includes("画質を")||t.player.notice(n.detail,-1),t.is_background_display=!0;break;case"ONAir":t.player.template.notice.textContent.includes("画質を")||t.player.notice(t.player.template.notice.textContent,1e-6),document.pictureInPictureElement&&(document.exitPictureInPicture(),t.player.video.requestPictureInPicture());break;case"Restart":t.player.notice(n.detail,-1),t.player.switchVideo({url:t.player.quality.url,type:t.player.quality.type}),t.player.play(),t.is_background_display=!0;break;case"Offline":t.player.notice(n.detail,-1),t.player.video.onerror=function(){t.player.notice(n.detail,-1),t.player.video.onerror=null},t.player.danmaku.clear(),t.player.video.pause(),t.eventsource.close(),t.is_background_display=!0;break}})),this.eventsource.addEventListener("detail_update",(function(e){var n=JSON.parse(e.data);console.log("Status: ".concat(n.status," Detail:").concat(n.detail)),t.channel.viewers=n.clients_count,"Standby"===n.status&&(t.player.notice(n.detail,-1),t.is_background_display||(t.is_background_display=!0))})),this.eventsource.addEventListener("clients_update",(function(e){var n=JSON.parse(e.data);t.channel.viewers=n.clients_count}))},initShortcutKeyHandler:function(){var t=this;this.shortcut_key_handler=function(e){var n=!1;e.repeat&&(n=!0);var a=Date.now();if(!(a-t.shortcut_key_pressed_at<100)){t.shortcut_key_pressed_at=a;var i=document.activeElement.tagName.toUpperCase(),s=document.activeElement.getAttribute("contenteditable");if("INPUT"!==i&&"TEXTAREA"!==i&&""!==s&&"true"!==s){if(!1===n){var r=t.channel.channel_type;e.shiftKey&&"GR"==t.channel.channel_type&&(r="BS"),e.shiftKey&&"BS"==t.channel.channel_type&&(r="GR");var l=null;if("Digit1"!==e.code&&"Digit2"!==e.code&&"Digit3"!==e.code&&"Digit4"!==e.code&&"Digit5"!==e.code&&"Digit6"!==e.code&&"Digit7"!==e.code&&"Digit8"!==e.code&&"Digit9"!==e.code||(l=Number(e.code.replace("Digit",""))),"Digit0"===e.code&&(l=10),"Minus"===e.code&&(l=11),"Equal"===e.code&&(l=12),"Numpad1"!==e.code&&"Numpad2"!==e.code&&"Numpad3"!==e.code&&"Numpad4"!==e.code&&"Numpad5"!==e.code&&"Numpad6"!==e.code&&"Numpad7"!==e.code&&"Numpad8"!==e.code&&"Numpad9"!==e.code||(l=Number(e.code.replace("Numpad",""))),"Numpad0"===e.code&&(l=10),null!==l){var o=et.getChannelFromRemoconID(t.channels_list,r,l);if(null!==o&&o.channel_id!==t.channel_id)return void Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,t.$router.replace({path:"/tv/watch/".concat(o.channel_id)});case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}}),e)})))()}}if("ArrowUp"===e.code&&!1===n)return e.preventDefault(),void Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,t.$router.replace({path:"/tv/watch/".concat(t.channel_previous.channel_id)});case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}}),e)})))();if("ArrowDown"===e.code&&!1===n)return e.preventDefault(),void Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,t.$router.replace({path:"/tv/watch/".concat(t.channel_next.channel_id)});case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}}),e)})))();if("Slash"===e.code&&!1===n)return void(t.shortcut_key_modal=!t.shortcut_key_modal);if(!1===n){if("KeyP"===e.code)return void(t.is_panel_display=!t.is_panel_display);if("KeyK"===e.code)return void(t.panel_active_tab="Program");if("KeyL"===e.code)return void(t.panel_active_tab="Channel");if("Semicolon"===e.code)return void(t.panel_active_tab="Comment");if("Quote"===e.code)return void(t.panel_active_tab="Twitter")}if(null!==t.player&&!e.ctrlKey&&!e.metaKey){if("ArrowLeft"===e.code)return e.preventDefault(),!1===t.player.video.paused&&t.player.video.pause(),void(t.player.video.currentTime=t.player.video.currentTime-.25);if("ArrowRight"===e.code)return e.preventDefault(),!1===t.player.video.paused&&t.player.video.pause(),void(t.player.video.currentTime=t.player.video.currentTime+.25);if(!1===n){if("Space"===e.code)return void t.player.toggle();if("KeyF"===e.code)return void t.player.fullScreen.toggle();if("KeyW"===e.code)return void t.player.sync();if("KeyE"===e.code)return void(document.pictureInPictureEnabled&&t.player.template.pipButton.click());if("KeyS"===e.code)return t.player.subtitle.toggle(),void(t.player.subtitle.container.classList.contains("dplayer-subtitle-hide")?t.player.notice("".concat(t.player.tran("Hide subtitle"))):t.player.notice("".concat(t.player.tran("Show subtitle"))));if("KeyD"===e.code)return t.player.template.showDanmaku.click(),void(t.player.template.showDanmakuToggle.checked?t.player.notice("".concat(t.player.tran("Show comment"))):t.player.notice("".concat(t.player.tran("Hide comment"))));if("KeyM"===e.code)return e.preventDefault(),t.player.controller.show(),t.player.comment.show(),t.controlDisplayTimer(),void window.setTimeout((function(){return t.player.template.commentInput.focus()}),100)}}}}},document.addEventListener("keydown",this.shortcut_key_handler)},destroy:function(){var t,e=this,n=arguments.length>0&&void 0!==arguments[0]&&arguments[0],a=Object(D["a"])(this.interval_ids);try{for(a.s();!(t=a.n()).done;){var i=t.value;window.clearInterval(i)}}catch(s){a.e(s)}finally{a.f()}window.clearTimeout(this.control_interval_id),this.interval_ids=[],this.is_loading=!0,this.is_background_display=!1,this.player.KonomiTVCanDestroy=!0,null!==this.eventsource&&(this.eventsource.close(),this.eventsource=null),this.interval_ids.push(window.setTimeout((function(){if(e.player.video.pause(),!0===n&&null!==e.player){try{e.player.destroy()}catch(t){void 0!==e.player.plugins.mpegts&&e.player.plugins.mpegts.destroy()}e.player=null}}),400))}}}),Lt=Ft,Ut=(n("598f"),n("e8a1"),n("b0af")),Bt=n("99d9"),$t=n("62ad"),Kt=n("169a"),qt=n("ce7e"),Gt=n("0fd9"),zt=Object(d["a"])(Lt,dt,_t,!1,null,"8b237ea4",null),Yt=zt.exports;m()(zt,{VBtn:H["a"],VCard:Ut["a"],VCardActions:Bt["a"],VCardTitle:Bt["b"],VCol:$t["a"],VDialog:Kt["a"],VDivider:qt["a"],VRow:Gt["a"],VSpacer:L["a"]}),$()(zt,{Ripple:K["a"]});var Wt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("Base",[n("h2",{staticClass:"settings__heading"},[n("Icon",{attrs:{icon:"fa-solid:sliders-h",width:"18px"}}),n("span",{staticClass:"ml-3"},[t._v("全般")])],1),n("div",{staticClass:"settings__content"},[n("div",{staticClass:"settings__item"},[n("div",{staticClass:"settings__item-heading"},[t._v("テレビのストリーミング画質")]),n("div",{staticClass:"settings__item-label"},[t._v(" テレビをライブストリーミングする際の既定の画質を設定します。"),n("br"),t._v(" ストリーミング画質はプレイヤーの設定からいつでも切り替えられます。"),n("br")]),n("v-select",{staticClass:"settings__item-form",attrs:{outlined:"","hide-details":"",items:t.tv_streaming_quality},model:{value:t.settings.tv_streaming_quality,callback:function(e){t.$set(t.settings,"tv_streaming_quality",e)},expression:"settings.tv_streaming_quality"}})],1),n("div",{staticClass:"settings__item"},[n("div",{staticClass:"settings__item-heading"},[t._v("既定のパネルの表示状態")]),n("div",{staticClass:"settings__item-label"},[t._v(" 視聴画面を開いたときに、右側のパネルをどう表示するかを設定します。"),n("br")]),n("v-select",{staticClass:"settings__item-form",attrs:{outlined:"","hide-details":"",items:t.panel_display_state},model:{value:t.settings.panel_display_state,callback:function(e){t.$set(t.settings,"panel_display_state",e)},expression:"settings.panel_display_state"}})],1),n("div",{staticClass:"settings__item"},[n("div",{staticClass:"settings__item-heading"},[t._v("既定で表示されるパネルのタブ")]),n("div",{staticClass:"settings__item-label"},[t._v(" 視聴画面を開いたときに、右側のパネルで最初に表示されるタブを設定します。"),n("br")]),n("v-select",{staticClass:"settings__item-form",attrs:{outlined:"","hide-details":"",items:t.panel_active_tab},model:{value:t.settings.panel_active_tab,callback:function(e){t.$set(t.settings,"panel_active_tab",e)},expression:"settings.panel_active_tab"}})],1)])])},Jt=[],Xt=(n("4fad"),function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"route-container"},[n("Header"),n("main",[n("Navigation"),n("v-card",{staticClass:"settings-container d-flex px-5 py-5 mx-auto background",attrs:{elevation:"0",width:"100%","max-width":"1000"}},[n("div",[n("v-navigation-drawer",{staticClass:"settings-navigation flex-shrink-0 background",attrs:{permanent:"",width:"195",height:"auto"}},[n("v-list-item",{staticClass:"px-4"},[n("v-list-item-content",[n("h1",[t._v("設定")])])],1),n("v-list",{staticClass:"mt-2 px-0",attrs:{nav:""}},[n("v-list-item",{staticClass:"px-4",attrs:{link:"",color:"primary",to:"/settings/general"}},[n("v-list-item-icon",{staticClass:"mr-4"},[n("Icon",{staticStyle:{padding:"0 3px"},attrs:{icon:"fa-solid:sliders-h",width:"26px"}})],1),n("v-list-item-content",[n("v-list-item-title",[t._v("全般")])],1)],1),n("v-list-item",{staticClass:"px-4",attrs:{link:"",color:"primary",to:"/settings/account"}},[n("v-list-item-icon",{staticClass:"mr-4"},[n("Icon",{attrs:{icon:"fluent:person-20-filled",width:"26px"}})],1),n("v-list-item-content",[n("v-list-item-title",[t._v("アカウント")])],1)],1),n("v-list-item",{staticClass:"px-4",attrs:{link:"",color:"primary",to:"/settings/jikkyo"}},[n("v-list-item-icon",{staticClass:"mr-4"},[n("Icon",{staticStyle:{padding:"0 2px"},attrs:{icon:"bi:chat-left-text-fill",width:"26px"}})],1),n("v-list-item-content",[n("v-list-item-title",[t._v("ニコニコ実況")])],1)],1),n("v-list-item",{staticClass:"px-4",attrs:{link:"",color:"primary",to:"/settings/twitter"}},[n("v-list-item-icon",{staticClass:"mr-4"},[n("Icon",{staticStyle:{padding:"0 1px"},attrs:{icon:"fa-brands:twitter",width:"26px"}})],1),n("v-list-item-content",[n("v-list-item-title",[t._v("Twitter")])],1)],1)],1)],1)],1),n("v-card",{staticClass:"settings ml-5 px-7 py-7 background lighten-1",attrs:{width:"100%"}},[t._t("default")],2)],1)],1)],1)}),Qt=[],Zt=r["a"].extend({name:"SettingsBase",components:{Header:z,Navigation:rt}}),te=Zt,ee=(n("5e6f"),n("8860")),ne=n("da13"),ae=n("5d23"),ie=n("34c3"),se=n("f774"),re=Object(d["a"])(te,Xt,Qt,!1,null,"18637a38",null),le=re.exports;m()(re,{VCard:Ut["a"],VList:ee["a"],VListItem:ne["a"],VListItemContent:ae["a"],VListItemIcon:ie["a"],VListItemTitle:ae["b"],VNavigationDrawer:se["a"]});var oe=r["a"].extend({name:"SettingsGeneral",components:{Base:le},data:function(){return{tv_streaming_quality:[{text:"1080p (1時間あたり約2.31GB / 5.1Mbps)",value:"1080p"},{text:"810p (1時間あたり約1.92GB / 4.2Mbps)",value:"810p"},{text:"720p (1時間あたり約1.33GB / 3.0Mbps)",value:"720p"},{text:"540p (1時間あたり約1.00GB / 2.2Mbps)",value:"540p"},{text:"480p (1時間あたり約0.74GB / 1.6Mbps)",value:"480p"},{text:"360p (1時間あたり約0.40GB / 0.9Mbps)",value:"360p"},{text:"240p (1時間あたり約0.23GB / 0.5Mbps)",value:"240p"}],panel_display_state:[{text:"前回の状態を復元する",value:"RestorePreviousState"},{text:"常に表示する",value:"AlwaysDisplay"},{text:"常に折りたたむ",value:"AlwaysFold"}],panel_active_tab:[{text:"番組情報タブ",value:"Program"},{text:"チャンネルタブ",value:"Channel"},{text:"コメントタブ",value:"Comment"},{text:"Twitter タブ",value:"Twitter"}],settings:function(){for(var t={},e=0,n=["tv_streaming_quality","panel_display_state","panel_active_tab"];e$1');return s=s.replace(i,'$1'),s}return"title"==e?"放送休止":"この時間は放送を休止しています。"}},{key:"getAttribute",value:function(t,e,n){return null!==t&&void 0!==t[e]&&null!==t[e]?t[e]:n}},{key:"getChannelType",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.match("(?[a-z]+)[0-9]+").groups.channel_type.toUpperCase();return"GR"===n&&e?"地デジ":n}},{key:"getChannelForceType",value:function(t){return null===t?"normal":t>=1e3?"festival":t>=200?"so-many":t>=100?"many":"normal"}},{key:"getChannelFromRemoconID",value:function(t,e,n){e=e.replace("GR","地デジ");for(var a=t.get(e),i=0;i1&&void 0!==arguments[1]&&arguments[1];if(null!==t&&"2000-01-01T00:00:00+09:00"!==t.start_time){tt.a.locale("ja");var n=tt()(t.start_time),a=tt()(t.end_time),i=t.duration/60;return!0===e?"".concat(n.format("HH:mm")," ~ ").concat(a.format("HH:mm")):"".concat(n.format("YYYY/MM/DD (dd) HH:mm")," ~ ").concat(a.format("HH:mm")," (").concat(i,"分)")}return!0===e?"--:-- ~ --:--":"----/--/-- (-) --:-- ~ --:-- (--分)"}},{key:"getProgramProgress",value:function(t){if(null!==t){var e=tt()(tt()()).diff(t.start_time,"second");return e/t.duration*100}return 0}}]),t}()),nt=Q,at=r["a"].extend({name:"Navigation",data:function(){return{Utils:nt}}}),it=at,st=(n("d2ee"),Object(d["a"])(it,Y,W,!1,null,"4fdece88",null)),rt=st.exports;m()(st,{VSpacer:L["a"]}),$()(st,{Ripple:K["a"]});var lt=r["a"].extend({name:"Home",components:{Header:z,Navigation:rt},data:function(){return{Utils:nt,TVUtils:et,tab:null,is_loading:!0,interval_ids:[],channels_list:new Map,pinned_channel_ids:[]}},created:function(){var t=this;this.update();var e=60-Math.floor((new Date).getTime()/1e3)%60;this.interval_ids.push(window.setTimeout((function(){t.update(),t.interval_ids.push(window.setInterval((function(){t.update()}),3e4))}),1e3*e))},beforeDestroy:function(){var t,e=Object(D["a"])(this.interval_ids);try{for(e.s();!(t=e.n()).done;){var n=t.value;window.clearInterval(n)}}catch(a){e.e(a)}finally{e.f()}},methods:{update:function(){var t=this;return Object(A["a"])(regeneratorRuntime.mark((function e(){var n,a;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,r["a"].axios.get("".concat(nt.api_base_url,"/channels"));case 3:n=e.sent,e.next=10;break;case 6:return e.prev=6,e.t0=e["catch"](0),console.error(e.t0),e.abrupt("return");case 10:a=function(t){return t.is_display},t.channels_list=new Map,n.data.GR.length>0&&t.channels_list.set("地デジ",n.data.GR.filter(a)),n.data.BS.length>0&&t.channels_list.set("BS",n.data.BS.filter(a)),n.data.CS.length>0&&t.channels_list.set("CS",n.data.CS.filter(a)),n.data.CATV.length>0&&t.channels_list.set("CATV",n.data.CATV.filter(a)),n.data.SKY.length>0&&t.channels_list.set("SKY",n.data.SKY.filter(a)),n.data.STARDIGIO.length>0&&t.channels_list.set("StarDigio",n.data.STARDIGIO.filter(a)),t.updatePinnedChannelList(!!t.is_loading),t.is_loading=!1;case 20:case"end":return e.stop()}}),e,null,[[0,6]])})))()},addPinnedChannel:function(t){this.pinned_channel_ids=nt.getSettingsItem("pinned_channel_ids"),this.pinned_channel_ids.push(t),nt.setSettingsItem("pinned_channel_ids",this.pinned_channel_ids),this.updatePinnedChannelList()},removePinnedChannel:function(t){this.pinned_channel_ids=nt.getSettingsItem("pinned_channel_ids"),this.pinned_channel_ids.splice(this.pinned_channel_ids.indexOf(t),1),nt.setSettingsItem("pinned_channel_ids",this.pinned_channel_ids),this.updatePinnedChannelList()},updatePinnedChannelList:function(){var t=this,e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.pinned_channel_ids=nt.getSettingsItem("pinned_channel_ids");var n,a=[],i=Object(D["a"])(this.pinned_channel_ids);try{var s=function(){var e=n.value,i=et.getChannelType(e,!0);a.push(t.channels_list.get(i).find((function(t){return t.channel_id===e})))};for(i.s();!(n=i.n()).done;)s()}catch(r){i.e(r)}finally{i.f()}this.channels_list.has("ピン留め")?this.channels_list.set("ピン留め",a):this.channels_list=new Map([["ピン留め",a]].concat(Object(V["a"])(this.channels_list))),0===a.length&&!0===e&&(this.tab=1)},isPinnedChannel:function(t){return this.pinned_channel_ids.includes(t)}}}),ot=lt,ct=(n("92b8"),n("ee0e"),n("71a3")),ut=Object(d["a"])(ot,R,E,!1,null,"6a407b07",null),pt=ut.exports;m()(ut,{VSpacer:L["a"],VTab:ct["a"]}),$()(ut,{Ripple:K["a"]});var dt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"route-container"},[n("main",{staticClass:"watch-container",class:{"watch-container--control-display":t.is_control_display,"watch-container--panel-display":t.is_panel_display,"watch-container--fullscreen":t.is_fullscreen}},[n("nav",{staticClass:"watch-navigation",on:{mousemove:function(e){return t.controlDisplayTimer(e)},touchmove:function(e){return t.controlDisplayTimer(e)},click:function(e){return t.controlDisplayTimer(e)}}},[n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"watch-navigation__icon",attrs:{to:"/tv/"}},[n("img",{staticClass:"watch-navigation__icon-image",attrs:{src:"/assets/img/icon.svg",width:"23px"}})]),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"テレビをみる",expression:"'テレビをみる'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/tv/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:tv-20-regular",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"ビデオをみる",expression:"'ビデオをみる'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/videos/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:movies-and-tv-20-regular",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"番組表",expression:"'番組表'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/schedules/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:calendar-ltr-20-regular",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"キャプチャ",expression:"'キャプチャ'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/captures/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:image-multiple-24-regular",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"ウォッチリスト",expression:"'ウォッチリスト'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/watchlists/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"ic:round-playlist-play",width:"26px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"視聴履歴",expression:"'視聴履歴'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/histories/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:history-16-regular",width:"26px"}})],1),n("v-spacer"),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"設定",expression:"'設定'",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",to:"/settings/"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:settings-20-regular",width:"26px"}})],1),n("a",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.right",value:"version "+t.Utils.version,expression:"`version ${Utils.version}`",modifiers:{right:!0}}],staticClass:"watch-navigation__link",attrs:{"active-class":"watch-navigation__link--active",href:"https://github.com/tsukumijima/KonomiTV"}},[n("Icon",{staticClass:"watch-navigation__link-icon",attrs:{icon:"fluent:info-16-regular",width:"26px"}})],1)],1),n("div",{staticClass:"watch-content",on:{mousemove:function(e){return t.controlDisplayTimer(e,!0)},touchmove:function(e){return t.controlDisplayTimer(e,!0)},click:function(e){return t.controlDisplayTimer(e,!0)}}},[n("header",{staticClass:"watch-header"},[n("img",{staticClass:"watch-header__broadcaster",attrs:{src:t.Utils.api_base_url+"/channels/"+t.$route.params.channel_id+"/logo"}}),n("span",{staticClass:"watch-header__program-title",domProps:{innerHTML:t._s(t.TVUtils.decorateProgramInfo(t.channel.program_present,"title"))}}),n("span",{staticClass:"watch-header__program-time"},[t._v(t._s(t.TVUtils.getProgramTime(t.channel.program_present,!0)))]),n("v-spacer"),n("span",{staticClass:"watch-header__now"},[t._v(t._s(t.time))])],1),n("div",{staticClass:"watch-player",class:{"watch-player--loading":t.is_loading}},[n("div",{staticClass:"watch-player__background",class:{"watch-player__background--display":t.is_background_display},style:{backgroundImage:"url("+t.background_url+")"}},[n("img",{staticClass:"watch-player__background-logo",attrs:{src:"/assets/img/logo.svg"}})]),n("div",{staticClass:"watch-player__dplayer"}),n("div",{staticClass:"watch-player__button",on:{mousemove:function(e){return t.controlDisplayTimer(e)},touchmove:function(e){return t.controlDisplayTimer(e)},click:function(e){return t.controlDisplayTimer(e)}}},[n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.top",value:"前のチャンネル",expression:"'前のチャンネル'",modifiers:{top:!0}}],staticClass:"switch-button switch-button-up",attrs:{to:"/tv/watch/"+t.channel_previous.channel_id}},[n("Icon",{staticClass:"switch-button-icon",attrs:{icon:"fluent:ios-arrow-left-24-filled",width:"32px",rotate:"1"}})],1),n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"switch-button switch-button-panel switch-button-panel--open",on:{click:function(e){t.is_panel_display=!t.is_panel_display}}},[n("Icon",{staticClass:"switch-button-icon",attrs:{icon:"fluent:navigation-16-filled",width:"32px"}})],1),n("router-link",{directives:[{name:"ripple",rawName:"v-ripple"},{name:"tooltip",rawName:"v-tooltip.bottom",value:"次のチャンネル",expression:"'次のチャンネル'",modifiers:{bottom:!0}}],staticClass:"switch-button switch-button-down",attrs:{to:"/tv/watch/"+t.channel_next.channel_id}},[n("Icon",{staticClass:"switch-button-icon",attrs:{icon:"fluent:ios-arrow-right-24-filled",width:"33px",rotate:"1"}})],1)],1)])]),n("div",{staticClass:"watch-panel",on:{mousemove:function(e){return t.controlDisplayTimer(e)},touchmove:function(e){return t.controlDisplayTimer(e)},click:function(e){return t.controlDisplayTimer(e)}}},[n("div",{staticClass:"watch-panel__header"},[n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-close-button",on:{click:function(e){t.is_panel_display=!1}}},[n("Icon",{staticClass:"panel-close-button__icon",attrs:{icon:"akar-icons:chevron-right",width:"25px"}}),n("span",{staticClass:"panel-close-button__text"},[t._v("閉じる")])],1),n("v-spacer"),n("div",{staticClass:"panel-broadcaster"},[n("img",{staticClass:"panel-broadcaster__icon",attrs:{src:t.Utils.api_base_url+"/channels/"+t.$route.params.channel_id+"/logo"}}),n("div",{staticClass:"panel-broadcaster__number"},[t._v(t._s(t.channel.channel_number))]),n("div",{staticClass:"panel-broadcaster__name"},[t._v(t._s(t.channel.channel_name))])])],1),n("div",{staticClass:"watch-panel__content-container"},[n("Program",{staticClass:"watch-panel__content",class:{"watch-panel__content--active":"Program"===t.panel_active_tab},attrs:{channel:t.channel}}),n("Channel",{staticClass:"watch-panel__content",class:{"watch-panel__content--active":"Channel"===t.panel_active_tab},attrs:{channels_list:t.channels_list}}),n("Comment",{staticClass:"watch-panel__content",class:{"watch-panel__content--active":"Comment"===t.panel_active_tab},attrs:{channel:t.channel,player:t.player}})],1),n("div",{staticClass:"watch-panel__navigation"},[n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-navigation-button",class:{"panel-navigation-button--active":"Program"===t.panel_active_tab},on:{click:function(e){t.panel_active_tab="Program"}}},[n("Icon",{staticClass:"panel-navigation-button__icon",attrs:{icon:"fa-solid:info-circle",width:"33px"}}),n("span",{staticClass:"panel-navigation-button__text"},[t._v("番組情報")])],1),n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-navigation-button",class:{"panel-navigation-button--active":"Channel"===t.panel_active_tab},on:{click:function(e){t.panel_active_tab="Channel"}}},[n("Icon",{staticClass:"panel-navigation-button__icon",attrs:{icon:"fa-solid:broadcast-tower",width:"34px"}}),n("span",{staticClass:"panel-navigation-button__text"},[t._v("チャンネル")])],1),n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-navigation-button",class:{"panel-navigation-button--active":"Comment"===t.panel_active_tab},on:{click:function(e){t.panel_active_tab="Comment"}}},[n("Icon",{staticClass:"panel-navigation-button__icon",attrs:{icon:"bi:chat-left-text-fill",width:"29px"}}),n("span",{staticClass:"panel-navigation-button__text"},[t._v("コメント")])],1),n("div",{directives:[{name:"ripple",rawName:"v-ripple"}],staticClass:"panel-navigation-button",class:{"panel-navigation-button--active":"Twitter"===t.panel_active_tab},on:{click:function(e){t.panel_active_tab="Twitter"}}},[n("Icon",{staticClass:"panel-navigation-button__icon",attrs:{icon:"fa-brands:twitter",width:"34px"}}),n("span",{staticClass:"panel-navigation-button__text"},[t._v("Twitter")])],1)])])]),n("v-dialog",{attrs:{"max-width":"980",transition:"slide-y-transition"},model:{value:t.shortcut_key_modal,callback:function(e){t.shortcut_key_modal=e},expression:"shortcut_key_modal"}},[n("v-card",[n("v-card-title",{staticClass:"px-5 pt-4 pb-3 d-flex align-center font-weight-bold"},[n("Icon",{attrs:{icon:"fluent:keyboard-20-filled",height:"28px"}}),n("span",{staticClass:"ml-3"},[t._v("キーボードショートカット")])],1),n("div",{staticClass:"px-5 pb-4"},[n("v-row",t._l(t.shortcut_key_list,(function(e,a){return n("v-col",{key:a,attrs:{cols:"6"}},t._l(e,(function(e){return n("div",{key:e.name,staticClass:"mt-3"},[n("div",{staticClass:"text-subtitle-1 d-flex align-center font-weight-bold"},[n("Icon",{attrs:{icon:e.icon,height:e.icon_height}}),n("span",{staticClass:"ml-2"},[t._v(t._s(e.name))])],1),t._l(e.shortcuts,(function(e){return n("div",{key:e.name,staticClass:"mt-3"},[n("div",{staticClass:"text-subtitle-2 mt-2 d-flex align-center font-weight-medium"},[n("span",{staticClass:"mr-2",domProps:{innerHTML:t._s(e.name)}}),n("div",{staticClass:"ml-auto d-flex align-center flex-shrink-0"},t._l(e.keys,(function(a,i){return n("div",{key:a.name,staticClass:"ml-auto d-flex align-center"},[!0===a.icon?n("Icon",{staticClass:"shortcut-key",attrs:{icon:a.name,height:"18px"}}):t._e(),!1===a.icon?n("span",{staticClass:"shortcut-key"},[t._v(t._s(a.name))]):t._e(),in.comment_list_element.clientWidth&&(i=!0)},n.comment_list_element.onmouseup=function(t){var e=t.clientX-n.comment_list_element.getBoundingClientRect().left;e>n.comment_list_element.clientWidth&&(i=!1)},s=function(){i=!0,window.setTimeout((function(){return i=!1}),100)},r=!1,n.comment_list_element.ontouchstart=function(){return r=!0},n.comment_list_element.ontouchend=function(){return r=!1},n.comment_list_element.ontouchmove=function(){return!0===r?s():""},n.comment_list_element.onwheel=s,n.comment_list_element.onscroll=Object(A["a"])(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(!1!==n.is_auto_scrolling||!0!==i){t.next=5;break}return n.is_manual_scroll=!0,t.next=4,new Promise((function(t){return setTimeout(t,100)}));case 4:n.comment_list_element.scrollTop+n.comment_list_element.offsetHeight>n.comment_list_element.scrollHeight-10&&(n.is_manual_scroll=!1);case 5:case"end":return t.stop()}}),t)}))),a.next=20,n.initWatchSession();case 20:return l=a.sent,a.next=23,n.initCommentSession(l);case 23:return a.next=25,n.initReserveObserver();case 25:case"end":return a.stop()}}),a)})))()}},methods:{initWatchSession:function(){var t=this;return Object(A["a"])(regeneratorRuntime.mark((function e(){var n;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,r["a"].axios.get("".concat(nt.api_base_url,"/channels/").concat(t.channel.channel_id,"/jikkyo"));case 3:n=e.sent,e.next=9;break;case 6:throw e.prev=6,e.t0=e["catch"](0),new Error(e.t0);case 9:if(!1!==n.data.is_success){e.next=11;break}throw new Error(n.data.detail);case 11:return e.abrupt("return",new Promise((function(e){t.watch_session=new WebSocket(n.data.audience_token),t.watch_session.addEventListener("open",(function(){t.watch_session.send(JSON.stringify({type:"startWatching",data:{reconnect:!1}}))})),t.watch_session.addEventListener("message",function(){var n=Object(A["a"])(regeneratorRuntime.mark((function n(a){var i,s,r,l,o;return regeneratorRuntime.wrap((function(n){while(1)switch(n.prev=n.next){case 0:i=JSON.parse(a.data),n.t0=i.type,n.next="room"===n.t0?4:"seat"===n.t0?5:"ping"===n.t0?7:"error"===n.t0?9:"reconnect"===n.t0?33:"disconnect"===n.t0?43:79;break;case 4:return n.abrupt("return",e({thread_id:i.data.threadId,your_post_key:i.data.yourPostKey?i.data.yourPostKey:null,message_server:i.data.messageServer.uri}));case 5:return t.keep_seat_interval_id=window.setInterval((function(){1===t.watch_session.readyState?t.watch_session.send(JSON.stringify({type:"keepSeat"})):window.clearInterval(t.keep_seat_interval_id)}),1e3*i.data.keepIntervalSec),n.abrupt("break",79);case 7:return t.watch_session.send(JSON.stringify({type:"pong"})),n.abrupt("break",79);case 9:n.t1=i.data.code,n.next="CONNECT_ERROR"===n.t1?12:"CONTENT_NOT_READY"===n.t1?14:"NO_THREAD_AVAILABLE"===n.t1?16:"NO_ROOM_AVAILABLE"===n.t1?18:"NO_PERMISSION"===n.t1?20:"NOT_ON_AIR"===n.t1?22:"BROADCAST_NOT_FOUND"===n.t1?24:"INTERNAL_SERVERERROR"===n.t1?26:28;break;case 12:return s="コメントサーバーに接続できません。",n.abrupt("break",30);case 14:return s="ニコニコ実況が配信できない状態です。",n.abrupt("break",30);case 16:return s="コメントスレッドを取得できません。",n.abrupt("break",30);case 18:return s="コメント部屋を取得できません。",n.abrupt("break",30);case 20:return s="API にアクセスする権限がありません。",n.abrupt("break",30);case 22:return s="ニコニコ実況が放送中ではありません。",n.abrupt("break",30);case 24:return s="ニコニコ実況の配信情報を取得できません。",n.abrupt("break",30);case 26:return s="ニコニコ実況でサーバーエラーが発生しています。",n.abrupt("break",30);case 28:return s="ニコニコ実況でエラーが発生しています。(".concat(i.data.code,")"),n.abrupt("break",30);case 30:return console.log("error occurred. code: ".concat(i.data.code)),t.player.danmaku.showing&&t.player.notice(s),n.abrupt("break",79);case 33:return t.destroy(),n.next=36,new Promise((function(t){return setTimeout(t,1e3*i.data.waitTimeSec)}));case 36:return t.player.danmaku.showing&&t.player.notice("ニコニコ実況に再接続しています…"),n.next=39,t.initWatchSession();case 39:return r=n.sent,n.next=42,t.initCommentSession(r);case 42:return n.abrupt("break",79);case 43:t.watch_session&&(t.watch_session.onclose=null),n.t2=i.data.reason,n.next="TAKEOVER"===n.t2?47:"NO_PERMISSION"===n.t2?49:"END_PROGRAM"===n.t2?51:"PING_TIMEOUT"===n.t2?53:"TOO_MANY_CONNECTIONS"===n.t2?55:"TOO_MANY_WATCHINGS"===n.t2?57:"CROWDED"===n.t2?59:"MAINTENANCE_IN"===n.t2?61:"SERVICE_TEMPORARILY_UNAVAILABLE"===n.t2?63:65;break;case 47:return l="ニコニコ実況の番組から追い出されました。",n.abrupt("break",67);case 49:return l="ニコニコ実況の番組の座席を取得できませんでした。",n.abrupt("break",67);case 51:return l="ニコニコ実況がリセットされたか、コミュニティの番組が終了しました。",n.abrupt("break",67);case 53:return l="コメントサーバーとの接続生存確認に失敗しました。",n.abrupt("break",67);case 55:return l="ニコニコ実況の同一ユーザからの接続数上限を越えています。",n.abrupt("break",67);case 57:return l="ニコニコ実況の同一ユーザからの視聴番組数上限を越えています。",n.abrupt("break",67);case 59:return l="ニコニコ実況の番組が満席です。",n.abrupt("break",67);case 61:return l="ニコニコ実況はメンテナンス中です。",n.abrupt("break",67);case 63:return l="ニコニコ実況で一時的にサーバーエラーが発生しています。",n.abrupt("break",67);case 65:return l="ニコニコ実況との接続が切断されました。(".concat(i.data.reason,")"),n.abrupt("break",67);case 67:return console.log("disconnected. reason: ".concat(i.data.reason)),t.player.danmaku.showing&&t.player.notice(l),t.destroy(),n.next=72,new Promise((function(t){return setTimeout(t,5e3)}));case 72:return t.player.danmaku.showing&&t.player.notice("ニコニコ実況に再接続しています…"),n.next=75,t.initWatchSession();case 75:return o=n.sent,n.next=78,t.initCommentSession(o);case 78:return n.abrupt("break",79);case 79:case"end":return n.stop()}}),n)})));return function(t){return n.apply(this,arguments)}}()),t.watch_session.onclose=function(){var e=Object(A["a"])(regeneratorRuntime.mark((function e(n){var a;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return console.log("disconnected. code: ".concat(n.code)),t.player.danmaku.showing&&t.player.notice("ニコニコ実況との接続が切断されました。(code: ".concat(n.code,")")),t.destroy(),e.next=5,new Promise((function(t){return setTimeout(t,1e4)}));case 5:return t.player.danmaku.showing&&t.player.notice("ニコニコ実況に再接続しています…"),e.next=8,t.initWatchSession();case 8:return a=e.sent,e.next=11,t.initCommentSession(a);case 11:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()})));case 12:case"end":return e.stop()}}),e,null,[[0,6]])})))()},initCommentSession:function(t){var e=this;return Object(A["a"])(regeneratorRuntime.mark((function n(){var a,i;return regeneratorRuntime.wrap((function(n){while(1)switch(n.prev=n.next){case 0:a=[],i=!1,e.comment_session=new WebSocket(t.message_server),e.comment_session.addEventListener("open",(function(){e.comment_session.send(JSON.stringify([{ping:{content:"rs:0"}},{ping:{content:"ps:0"}},{thread:{version:"20061206",thread:t.thread_id,threadkey:t.your_post_key,user_id:"",res_from:-50}},{ping:{content:"pf:0"}},{ping:{content:"rf:0"}}]))})),e.comment_session.addEventListener("message",function(){var t=Object(A["a"])(regeneratorRuntime.mark((function t(n){var s,r,l,o,c,u,p,d,_,m,h;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:if(s=JSON.parse(n.data),void 0!==s.thread&&(0===s.thread.resultcode||(r="コメントサーバーに接続できませんでした。",console.error("Error: "+r))),void 0!==s.ping&&"rf:0"===s.ping.content&&(i=!0,e.scrollCommentList()),l=s.chat,void 0!==l&&void 0!==l.content&&!l.content.match(/\/[a-z]+ /)){t.next=6;break}return t.abrupt("return");case 6:if(!l.yourpost||1!==l.yourpost){t.next=8;break}return t.abrupt("return");case 8:if(o="#FFEAEA",c="right",void 0!==l.mail&&null!==l.mail){u=l.mail.replace("184","").split(" "),p=Object(D["a"])(u);try{for(p.s();!(d=p.n()).done;)_=d.value,null!==e.getCommentColor(_)&&(o=e.getCommentColor(_)),null!==e.getCommentPosition(_)&&(c=e.getCommentPosition(_))}catch(v){p.e(v)}finally{p.f()}}if(!i){t.next=15;break}return m=nt.getSettingsItem("comment_delay_time"),t.next=15,new Promise((function(t){return setTimeout(t,1e3*m)}));case 15:if(e.comment_list.length>500&&e.comment_list.shift(),h={id:l.no,text:l.content,time:tt()(1e3*l.date).format("HH:mm:ss")},"hidden"!==document.visibilityState){t.next=20;break}return a.push(h),t.abrupt("return");case 20:e.comment_list.push(h),i&&e.scrollCommentList(),i&&(e.player.video.paused||e.player.danmaku.draw({text:l.content,color:o,type:c}));case 23:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),document.onvisibilitychange=function(){var t;"visible"===document.visibilityState&&((t=e.comment_list).push.apply(t,Object(V["a"])(a)),a=[],e.scrollCommentList())};case 6:case"end":return n.stop()}}),n)})))()},initReserveObserver:function(){var t=this;return Object(A["a"])(regeneratorRuntime.mark((function e(){var n,a;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:t.resize_observer_element=document.querySelector(".watch-player"),n=null,a=function(){var e=document.querySelector(".dplayer-video-wrap-aspect"),a=document.querySelector(".dplayer-danmaku");if(null!==t.resize_observer_element&&null!==t.resize_observer_element.clientHeight&&null!==e&&null!==e.clientHeight){var i=(t.resize_observer_element.clientHeight-e.clientHeight)/2,s=window.matchMedia("(max-height: 450px)").matches?50:66;if(i0&&void 0!==t[0]&&t[0],!0!==e.is_manual_scroll){n.next=3;break}return n.abrupt("return");case 3:e.is_auto_scrolling=!0,i=0;case 5:if(!(i<3)){n.next=12;break}return n.next=8,new Promise((function(t){return setTimeout(t,10)}));case 8:!0===a?e.comment_list_element.scrollTo({top:e.comment_list_element.scrollHeight,left:0,behavior:"smooth"}):e.comment_list_element.scrollTo(0,e.comment_list_element.scrollHeight);case 9:i++,n.next=5;break;case 12:return n.next=14,new Promise((function(t){return setTimeout(t,100)}));case 14:e.is_auto_scrolling=!1;case 15:case"end":return n.stop()}}),n)})))()},getCommentColor:function(t){var e={red:"#E54256",pink:"#FF8080",orange:"#FFC000",yellow:"#FFE133",green:"#64DD17",cyan:"#39CCFF",blue:"#0000FF",purple:"#D500F9",black:"#1E1310",white:"#FFEAEA",white2:"#CCCC99",niconicowhite:"#CCCC99",red2:"#CC0033",truered:"#CC0033",pink2:"#FF33CC",orange2:"#FF6600",passionorange:"#FF6600",yellow2:"#999900",madyellow:"#999900",green2:"#00CC66",elementalgreen:"#00CC66",cyan2:"#00CCCC",blue2:"#3399FF",marineblue:"#3399FF",purple2:"#6633CC",nobleviolet:"#6633CC",black2:"#666666"};return void 0!==e[t]?e[t]:null},getCommentPosition:function(t){switch(t){case"ue":return"top";case"naka":return"right";case"shita":return"bottom";default:return null}},destroy:function(){this.comment_list=[],document.onvisibilitychange=null,null!==this.watch_session&&(this.watch_session.onclose=null,this.watch_session.close(),this.watch_session=null),null!==this.comment_session&&(this.comment_session.onclose=null,this.comment_session.close(),this.comment_session=null),window.clearInterval(this.keep_seat_interval_id)}}})),Nt=Ot,Rt=(n("1548"),Object(d["a"])(Nt,It,Pt,!1,null,"7575b645",null)),Et=Rt.exports;$()(Rt,{Ripple:K["a"]});var Vt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"program-container"},[n("section",{staticClass:"program-broadcaster"},[n("img",{staticClass:"program-broadcaster__icon",attrs:{src:t.Utils.api_base_url+"/channels/"+t.$route.params.channel_id+"/logo"}}),n("div",{staticClass:"program-broadcaster__number"},[t._v("Ch: "+t._s(t.channel.channel_number))]),n("div",{staticClass:"program-broadcaster__name"},[t._v(t._s(t.channel.channel_name))])]),n("section",{staticClass:"program-info"},[n("h1",{staticClass:"program-info__title",domProps:{innerHTML:t._s(t.TVUtils.decorateProgramInfo(t.channel.program_present,"title"))}}),n("div",{staticClass:"program-info__time"},[t._v(t._s(t.TVUtils.getProgramTime(t.channel.program_present)))]),n("div",{staticClass:"program-info__description",domProps:{innerHTML:t._s(t.TVUtils.decorateProgramInfo(t.channel.program_present,"description"))}}),n("div",{staticClass:"program-info__genre-container"},t._l(t.TVUtils.getAttribute(t.channel.program_present,"genre",[]),(function(e,a){return n("div",{key:a,staticClass:"program-info__genre"},[t._v(" "+t._s(e.major)+" / "+t._s(e.middle)+" ")])})),0),n("div",{staticClass:"program-info__next"},[n("span",{staticClass:"program-info__next-decorate"},[t._v("NEXT")]),n("Icon",{staticClass:"program-info__next-icon",attrs:{icon:"fluent:fast-forward-20-filled",width:"16px"}})],1),n("span",{staticClass:"program-info__next-title",domProps:{innerHTML:t._s(t.TVUtils.decorateProgramInfo(t.channel.program_following,"title"))}}),n("div",{staticClass:"program-info__next-time"},[t._v(t._s(t.TVUtils.getProgramTime(t.channel.program_following)))]),n("div",{staticClass:"program-info__status"},[n("div",{staticClass:"program-info__status-force",class:"program-info__status-force--"+t.TVUtils.getChannelForceType(t.channel.channel_force)},[n("Icon",{attrs:{icon:"fa-solid:fire-alt",height:"14px"}}),n("span",{staticClass:"ml-2"},[t._v("勢い:")]),n("span",{staticClass:"ml-2"},[t._v(t._s(t.TVUtils.getAttribute(t.channel,"channel_force","--"))+" コメ/分")])],1),n("div",{staticClass:"program-info__status-viewers ml-5"},[n("Icon",{attrs:{icon:"fa-solid:eye",height:"14px"}}),n("span",{staticClass:"ml-2"},[t._v("視聴数:")]),n("span",{staticClass:"ml-1"},[t._v(t._s(t.channel.viewers))])],1)])]),n("section",{staticClass:"program-detail-container"},t._l(t.TVUtils.getAttribute(t.channel.program_present,"detail",{}),(function(e,a){return n("div",{key:a,staticClass:"program-detail"},[n("h2",{staticClass:"program-detail__heading"},[t._v(t._s(a))]),n("div",{staticClass:"program-detail__text"},[t._v(t._s(e))])])})),0)])},At=[],Dt=r["a"].extend({name:"Program",props:{channel:{type:Object,required:!0}},data:function(){return{Utils:nt,TVUtils:et}}}),jt=Dt,Mt=(n("9652"),Object(d["a"])(jt,Vt,At,!1,null,"00e07beb",null)),Ht=Mt.exports,Ft=r["a"].extend({name:"Watch",components:{Channel:Tt,Comment:Et,Program:Ht},data:function(){return{Utils:nt,TVUtils:et,time:tt()().format("YYYY/MM/DD HH:mm:ss"),panel_active_tab:nt.getSettingsItem("panel_active_tab"),background_url:"",is_loading:!0,is_background_display:!1,is_control_display:!0,is_panel_display:function(){switch(nt.getSettingsItem("panel_display_state")){case"AlwaysDisplay":return!0;case"AlwaysFold":return!1;case"RestorePreviousState":return nt.getSettingsItem("is_latest_panel_display")}}(),is_fullscreen:!1,interval_ids:[],control_interval_id:0,channel_id:this.$route.params.channel_id,channel:bt,channel_previous:bt,channel_next:bt,channels_list:new Map,player:null,eventsource:null,fullscreen_handler:null,shortcut_key_handler:null,shortcut_key_pressed_at:Date.now(),shortcut_key_modal:!1,shortcut_key_list:{left_column:[{name:"全般",icon:"fluent:home-20-filled",icon_height:"22px",shortcuts:[{name:"数字キー・テンキーに対応するリモコン番号 (1~12) のチャンネルに切り替える
(同時に Shift キーを押すと、地デジならBS、BSなら地デジのチャンネルを選局する)",keys:[{name:"1~9, 0, -(=), ^(~)",icon:!1}]},{name:"前のチャンネルに切り替える",keys:[{name:"fluent:arrow-up-12-filled",icon:!0}]},{name:"次のチャンネルに切り替える",keys:[{name:"fluent:arrow-down-12-filled",icon:!0}]},{name:"キーボードショートカットの一覧を表示する",keys:[{name:"/(?)",icon:!1}]}]},{name:"パネル",icon:"fluent:panel-right-20-filled",icon_height:"24px",shortcuts:[{name:"パネルの表示切り替え",keys:[{name:"P",icon:!1}]},{name:"番組情報タブを表示する",keys:[{name:"K",icon:!1}]},{name:"チャンネルタブを表示する",keys:[{name:"L",icon:!1}]},{name:"コメントタブを表示する",keys:[{name:";(+)",icon:!1}]},{name:"Twitter タブを表示する",keys:[{name:":(*)",icon:!1}]}]}],right_column:[{name:"プレイヤー",icon:"fluent:play-20-filled",icon_height:"20px",shortcuts:[{name:"再生 / 一時停止の切り替え",keys:[{name:"Space",icon:!1}]},{name:"停止して0.25秒早戻し",keys:[{name:"fluent:arrow-left-12-filled",icon:!0}]},{name:"停止して0.25秒早送り",keys:[{name:"fluent:arrow-right-12-filled",icon:!0}]},{name:"フルスクリーンの切り替え",keys:[{name:"F",icon:!1}]},{name:"ライブストリームの同期",keys:[{name:"W",icon:!1}]},{name:"Picture-in-Picture の表示切り替え",keys:[{name:"E",icon:!1}]},{name:"字幕の表示切り替え",keys:[{name:"S",icon:!1}]},{name:"コメントの表示切り替え",keys:[{name:"D",icon:!1}]},{name:"コメント入力フォームにフォーカスする",keys:[{name:"M",icon:!1}]}]}]}}},created:function(){this.init()},beforeDestroy:function(){this.destroy(!0),null!==this.shortcut_key_handler&&(document.removeEventListener("keydown",this.shortcut_key_handler),this.shortcut_key_handler=null)},beforeRouteUpdate:function(t,e,n){var a=this;this.destroy(),this.channel_id=t.params.channel_id;var i=et.getPreviousAndCurrentAndNextChannel(this.channels_list,this.channel_id),s=Object(mt["a"])(i,3);this.channel_previous=s[0],this.channel=s[1],this.channel_next=s[2],this.interval_ids.push(window.setTimeout((function(){a.init()}),500)),n()},watch:{is_panel_display:function(){nt.setSettingsItem("is_latest_panel_display",this.is_panel_display)}},methods:{init:function(){var t=this;this.background_url=nt.generatePlayerBackgroundURL(),this.controlDisplayTimer(),this.update(),this.interval_ids.push(window.setInterval((function(){t.time=tt()().format("YYYY/MM/DD HH:mm:ss")}),1e3));var e=60-Math.floor((new Date).getTime()/1e3)%60;this.interval_ids.push(window.setTimeout((function(){t.update(),t.interval_ids.push(window.setInterval((function(){t.update()}),3e4))}),1e3*e))},update:function(){var t=this;return Object(A["a"])(regeneratorRuntime.mark((function e(){var n,a,i,s,l,o,c,u,p,d,_;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:if(void 0!==t.$route.params.channel_id){e.next=2;break}return e.abrupt("return");case 2:return e.prev=2,e.next=5,r["a"].axios.get("".concat(nt.api_base_url,"/channels/").concat(t.channel_id));case 5:n=e.sent,e.next=15;break;case 8:if(e.prev=8,e.t0=e["catch"](2),console.error(e.t0),!e.t0.response||422!==e.t0.response.status||"Specified channel_id was not found"!==e.t0.response.data.detail){e.next=14;break}return e.next=14,t.$router.replace({path:"/not-found/"});case 14:return e.abrupt("return");case 15:return t.channel=n.data,null!==t.player&&!0!==t.player.KonomiTVCanDestroy||(t.initPlayer(),t.initEventHandler(),t.initShortcutKeyHandler()),null===t.channel.program_present||"1/0+1/0モード(デュアルモノ)"!==t.channel.program_present.primary_audio_type&&null===t.channel.program_present.secondary_audio_type?(t.player.template.audioItem[1].classList.add("dplayer-setting-audio-item--disabled"),t.player.plugins.mpegts&&window.setTimeout((function(){t.player.template.audioItem[0].classList.add("dplayer-setting-audio-current"),t.player.template.audioItem[1].classList.remove("dplayer-setting-audio-current"),t.player.template.audioValue.textContent=t.player.tran("Primary audio");try{t.player.plugins.mpegts.switchPrimaryAudio()}catch(e){}}),300)):t.player.template.audioItem[1].classList.remove("dplayer-setting-audio-item--disabled"),e.prev=18,e.next=21,r["a"].axios.get("".concat(nt.api_base_url,"/channels"));case 21:a=e.sent,e.next=28;break;case 24:return e.prev=24,e.t1=e["catch"](18),console.error(e.t1),e.abrupt("return");case 28:i=function(e){return e.is_display||t.channel_id===e.channel_id},t.channels_list=new Map,t.channels_list.set("ピン留め",[]),a.data.GR.length>0&&t.channels_list.set("地デジ",a.data.GR.filter(i)),a.data.BS.length>0&&t.channels_list.set("BS",a.data.BS.filter(i)),a.data.CS.length>0&&t.channels_list.set("CS",a.data.CS.filter(i)),a.data.CATV.length>0&&t.channels_list.set("CATV",a.data.CATV.filter(i)),a.data.SKY.length>0&&t.channels_list.set("SKY",a.data.SKY.filter(i)),a.data.STARDIGIO.length>0&&t.channels_list.set("StarDigio",a.data.STARDIGIO.filter(i)),s=nt.getSettingsItem("pinned_channel_ids"),l=[],o=Object(D["a"])(s);try{for(u=function(){var e=c.value,n=et.getChannelType(e,!0);l.push(t.channels_list.get(n).find((function(t){return t.channel_id===e})))},o.s();!(c=o.n()).done;)u()}catch(m){o.e(m)}finally{o.f()}l.length>0?t.channels_list.set("ピン留め",l):t.channels_list.delete("ピン留め"),p=et.getPreviousAndCurrentAndNextChannel(t.channels_list,t.channel_id),d=Object(mt["a"])(p,3),t.channel_previous=d[0],t.channel_next=d[2],"mediaSession"in navigator&&(_=[{src:"/assets/img/icons/icon-maskable-192px.png",sizes:"192x192",type:"image/png"},{src:"/assets/img/icons/icon-maskable-512px.png",sizes:"512x512",type:"image/png"}],navigator.mediaSession.metadata=new MediaMetadata({title:t.channel.program_present?t.channel.program_present.title:"放送休止",artist:t.channel.channel_name,artwork:_}),"setPositionState"in navigator.mediaSession&&navigator.mediaSession.setPositionState({duration:0,playbackRate:1}),navigator.mediaSession.setActionHandler("play",(function(){t.player.play()})),navigator.mediaSession.setActionHandler("pause",(function(){t.player.pause()})),navigator.mediaSession.setActionHandler("previoustrack",Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return navigator.mediaSession.metadata=new MediaMetadata({title:t.channel_previous.program_present?t.channel_previous.program_present.title:"放送休止",artist:t.channel_previous.channel_name,artwork:_}),e.next=3,t.$router.replace({path:"/tv/watch/".concat(t.channel_previous.channel_id)});case 3:case"end":return e.stop()}}),e)})))),navigator.mediaSession.setActionHandler("nexttrack",Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return navigator.mediaSession.metadata=new MediaMetadata({title:t.channel_next.program_present?t.channel_next.program_present.title:"放送休止",artist:t.channel_next.channel_name,artwork:_}),e.next=3,t.$router.replace({path:"/tv/watch/".concat(t.channel_next.channel_id)});case 3:case"end":return e.stop()}}),e)})))));case 47:case"end":return e.stop()}}),e,null,[[2,8],[18,24]])})))()},controlDisplayTimer:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=/iPhone|iPad|iPod|Macintosh|Android|Mobile/i.test(navigator.userAgent)&&"ontouchend"in document;if((1!=a||null===e||"mousemove"!==e.type)&&(0!=a||null===e||"touchmove"!==e.type&&"click"!==e.type)){window.clearTimeout(this.control_interval_id);var i=function e(){document.activeElement!==t.player.template.commentInput?(t.is_control_display=!1,null!==t.player&&(t.player.controller.hide(),t.player.setting.hide())):t.control_interval_id=window.setTimeout(e,3e3)};!0===a&&!0===n?this.player.controller.isShow()?(this.is_control_display=!0,this.player.controller.show(),this.control_interval_id=window.setTimeout(i,3e3)):(this.is_control_display=!1,this.player.controller.hide(),this.player.setting.hide()):(this.is_control_display=!0,null!==this.player&&this.player.controller.show(),this.control_interval_id=window.setTimeout(i,3e3))}},initPlayer:function(){var t=this;if(window.mpegts=ft.a,null!==this.player&&!0===this.player.KonomiTVCanDestroy){try{this.player.destroy()}catch(s){void 0!==this.player.plugins.mpegts&&this.player.plugins.mpegts.destroy()}this.player=null}this.player=new vt.a({container:this.$el.querySelector(".watch-player__dplayer"),theme:"#E64F97",lang:"ja-jp",live:!0,loop:!1,airplay:!1,autoplay:!0,hotkey:!1,screenshot:!0,volume:1,video:{defaultQuality:this.channel.is_radiochannel?"48kHz/192kbps":nt.getSettingsItem("tv_streaming_quality"),quality:function(){var e=[];if(t.channel.is_radiochannel)e.push({name:"48kHz/192kbps",type:"mpegts",url:"".concat(nt.api_base_url,"/streams/live/").concat(t.channel_id,"/1080p/mpegts")});else for(var n=0,a=["1080p","810p","720p","540p","480p","360p","240p"];n\n キーボードショートカット\n
\n \n \n \n
\n ');var n=this.player.template.settingOriginPanel.scrollHeight;this.player.template.settingBox.style.clipPath="inset(calc(100% - ".concat(n,"px) 0 0 round 7px)"),this.$el.querySelector(".dplayer-setting-keyboard-shortcut").addEventListener("click",(function(){t.player.setting.hide(),t.shortcut_key_modal=!0}))}var a=function(){t.player.setting.hide(),t.controlDisplayTimer()};this.player.on("play",a),this.player.on("pause",a),this.player.on("quality_start",(function(){t.background_url=nt.generatePlayerBackgroundURL(),null!==t.eventsource&&(t.eventsource.close(),t.eventsource=null),t.initEventHandler()})),this.player.plugins.aribb24Superimpose.show(),this.player.on("subtitle_hide",(function(){t.player.plugins.aribb24Superimpose.show()})),this.interval_ids.push(window.setInterval((function(){t.player.video.paused&&t.player.video.buffered.end(0)-t.player.video.currentTime>30&&t.player.sync()}),6e4));var i=this.$el;this.fullscreen_handler=function(){return t.is_fullscreen=t.player.fullScreen.isFullScreen()},void 0!==i.onfullscreenchange?i.addEventListener("fullscreenchange",this.fullscreen_handler):i.addEventListener("webkitfullscreenchange",this.fullscreen_handler),this.player.fullScreen.isFullScreen=function(t){return!(!document.fullscreenElement&&!document.webkitFullscreenElement)},this.player.fullScreen.request=function(e){t.player.fullScreen.isFullScreen()?t.player.fullScreen.cancel():(i.requestFullscreen=i.requestFullscreen||i.webkitRequestFullscreen,i.requestFullscreen&&i.requestFullscreen(),screen.orientation&&screen.orientation.lock("landscape").catch((function(){})))},this.player.fullScreen.cancel=function(t){document.exitFullscreen=document.exitFullscreen||document.webkitExitFullscreen,document.exitFullscreen&&document.exitFullscreen(),screen.orientation&&screen.orientation.unlock()}},initEventHandler:function(){var t=this;this.is_loading=!0;var e=function(){window.setTimeout((function(){t.is_loading=!1,t.channel.is_radiochannel?t.is_background_display=!0:t.is_background_display=!1}),100),t.player.video.oncanplay=null,t.player.video.oncanplaythrough=null};this.player.video.oncanplay=e,this.player.video.oncanplaythrough=e;var n=this.channel.is_radiochannel?"1080p":this.player.quality.name;this.eventsource=new EventSource("".concat(nt.api_base_url,"/streams/live/").concat(this.channel_id,"/").concat(n,"/events")),this.eventsource.addEventListener("initial_update",(function(e){var n=JSON.parse(e.data);"Standby"===n.status&&(t.is_background_display=!0)})),this.eventsource.addEventListener("status_update",(function(e){var n=JSON.parse(e.data);switch(console.log("Status: ".concat(n.status," Detail:").concat(n.detail)),t.channel.viewers=n.clients_count,n.status){case"Standby":t.player.template.notice.textContent.includes("画質を")||t.player.notice(n.detail,-1),t.is_background_display=!0;break;case"ONAir":t.player.template.notice.textContent.includes("画質を")||t.player.notice(t.player.template.notice.textContent,1e-6),document.pictureInPictureElement&&(document.exitPictureInPicture(),t.player.video.requestPictureInPicture());break;case"Restart":t.player.notice(n.detail,-1),t.player.switchVideo({url:t.player.quality.url,type:t.player.quality.type}),t.player.play(),t.is_background_display=!0;break;case"Offline":t.player.notice(n.detail,-1),t.player.video.onerror=function(){t.player.notice(n.detail,-1),t.player.video.onerror=null},t.player.danmaku.clear(),t.player.video.pause(),t.eventsource.close(),t.is_background_display=!0;break}})),this.eventsource.addEventListener("detail_update",(function(e){var n=JSON.parse(e.data);console.log("Status: ".concat(n.status," Detail:").concat(n.detail)),t.channel.viewers=n.clients_count,"Standby"===n.status&&(t.player.notice(n.detail,-1),t.is_background_display||(t.is_background_display=!0))})),this.eventsource.addEventListener("clients_update",(function(e){var n=JSON.parse(e.data);t.channel.viewers=n.clients_count}))},initShortcutKeyHandler:function(){var t=this;this.shortcut_key_handler=function(e){var n=!1;e.repeat&&(n=!0);var a=Date.now();if(!(a-t.shortcut_key_pressed_at<100)){t.shortcut_key_pressed_at=a;var i=document.activeElement.tagName.toUpperCase(),s=document.activeElement.getAttribute("contenteditable");if("INPUT"!==i&&"TEXTAREA"!==i&&""!==s&&"true"!==s){if(!1===n){var r=t.channel.channel_type;e.shiftKey&&"GR"==t.channel.channel_type&&(r="BS"),e.shiftKey&&"BS"==t.channel.channel_type&&(r="GR");var l=null;if("Digit1"!==e.code&&"Digit2"!==e.code&&"Digit3"!==e.code&&"Digit4"!==e.code&&"Digit5"!==e.code&&"Digit6"!==e.code&&"Digit7"!==e.code&&"Digit8"!==e.code&&"Digit9"!==e.code||(l=Number(e.code.replace("Digit",""))),"Digit0"===e.code&&(l=10),"Minus"===e.code&&(l=11),"Equal"===e.code&&(l=12),"Numpad1"!==e.code&&"Numpad2"!==e.code&&"Numpad3"!==e.code&&"Numpad4"!==e.code&&"Numpad5"!==e.code&&"Numpad6"!==e.code&&"Numpad7"!==e.code&&"Numpad8"!==e.code&&"Numpad9"!==e.code||(l=Number(e.code.replace("Numpad",""))),"Numpad0"===e.code&&(l=10),null!==l){var o=et.getChannelFromRemoconID(t.channels_list,r,l);if(null!==o&&o.channel_id!==t.channel_id)return void Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,t.$router.replace({path:"/tv/watch/".concat(o.channel_id)});case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}}),e)})))()}}if("ArrowUp"===e.code&&!1===n)return e.preventDefault(),void Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,t.$router.replace({path:"/tv/watch/".concat(t.channel_previous.channel_id)});case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}}),e)})))();if("ArrowDown"===e.code&&!1===n)return e.preventDefault(),void Object(A["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,t.$router.replace({path:"/tv/watch/".concat(t.channel_next.channel_id)});case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}}),e)})))();if("Slash"===e.code&&!1===n)return void(t.shortcut_key_modal=!t.shortcut_key_modal);if(!1===n){if("KeyP"===e.code)return void(t.is_panel_display=!t.is_panel_display);if("KeyK"===e.code)return void(t.panel_active_tab="Program");if("KeyL"===e.code)return void(t.panel_active_tab="Channel");if("Semicolon"===e.code)return void(t.panel_active_tab="Comment");if("Quote"===e.code)return void(t.panel_active_tab="Twitter")}if(null!==t.player&&!e.ctrlKey&&!e.metaKey){if("ArrowLeft"===e.code)return e.preventDefault(),!1===t.player.video.paused&&t.player.video.pause(),void(t.player.video.currentTime=t.player.video.currentTime-.25);if("ArrowRight"===e.code)return e.preventDefault(),!1===t.player.video.paused&&t.player.video.pause(),void(t.player.video.currentTime=t.player.video.currentTime+.25);if(!1===n){if("Space"===e.code)return void t.player.toggle();if("KeyF"===e.code)return void t.player.fullScreen.toggle();if("KeyW"===e.code)return void t.player.sync();if("KeyE"===e.code)return void(document.pictureInPictureEnabled&&t.player.template.pipButton.click());if("KeyS"===e.code)return t.player.subtitle.toggle(),void(t.player.subtitle.container.classList.contains("dplayer-subtitle-hide")?t.player.notice("".concat(t.player.tran("Hide subtitle"))):t.player.notice("".concat(t.player.tran("Show subtitle"))));if("KeyD"===e.code)return t.player.template.showDanmaku.click(),void(t.player.template.showDanmakuToggle.checked?t.player.notice("".concat(t.player.tran("Show comment"))):t.player.notice("".concat(t.player.tran("Hide comment"))));if("KeyM"===e.code)return e.preventDefault(),t.player.controller.show(),t.player.comment.show(),t.controlDisplayTimer(),void window.setTimeout((function(){return t.player.template.commentInput.focus()}),100)}}}}},document.addEventListener("keydown",this.shortcut_key_handler)},destroy:function(){var t,e=this,n=arguments.length>0&&void 0!==arguments[0]&&arguments[0],a=Object(D["a"])(this.interval_ids);try{for(a.s();!(t=a.n()).done;){var i=t.value;window.clearInterval(i)}}catch(s){a.e(s)}finally{a.f()}window.clearTimeout(this.control_interval_id),this.interval_ids=[],this.is_loading=!0,this.is_background_display=!1,this.player.KonomiTVCanDestroy=!0,null!==this.eventsource&&(this.eventsource.close(),this.eventsource=null),this.interval_ids.push(window.setTimeout((function(){if(e.player.video.pause(),!0===n&&null!==e.player){try{e.player.destroy()}catch(t){void 0!==e.player.plugins.mpegts&&e.player.plugins.mpegts.destroy()}e.player=null}}),400))}}}),Lt=Ft,Ut=(n("598f"),n("e8a1"),n("b0af")),Bt=n("99d9"),$t=n("62ad"),Kt=n("169a"),qt=n("ce7e"),Gt=n("0fd9"),zt=Object(d["a"])(Lt,dt,_t,!1,null,"8b237ea4",null),Yt=zt.exports;m()(zt,{VBtn:H["a"],VCard:Ut["a"],VCardActions:Bt["a"],VCardTitle:Bt["b"],VCol:$t["a"],VDialog:Kt["a"],VDivider:qt["a"],VRow:Gt["a"],VSpacer:L["a"]}),$()(zt,{Ripple:K["a"]});var Wt=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("Base",[n("h2",{staticClass:"settings__heading"},[n("Icon",{attrs:{icon:"fa-solid:sliders-h",width:"18px"}}),n("span",{staticClass:"ml-3"},[t._v("全般")])],1),n("div",{staticClass:"settings__content"},[n("div",{staticClass:"settings__item"},[n("div",{staticClass:"settings__item-heading"},[t._v("テレビのストリーミング画質")]),n("div",{staticClass:"settings__item-label"},[t._v(" テレビをライブストリーミングする際の既定の画質を設定します。"),n("br"),t._v(" ストリーミング画質はプレイヤーの設定からいつでも切り替えられます。"),n("br")]),n("v-select",{staticClass:"settings__item-form",attrs:{outlined:"","hide-details":"",items:t.tv_streaming_quality},model:{value:t.settings.tv_streaming_quality,callback:function(e){t.$set(t.settings,"tv_streaming_quality",e)},expression:"settings.tv_streaming_quality"}})],1),n("div",{staticClass:"settings__item"},[n("div",{staticClass:"settings__item-heading"},[t._v("既定のパネルの表示状態")]),n("div",{staticClass:"settings__item-label"},[t._v(" 視聴画面を開いたときに、右側のパネルをどう表示するかを設定します。"),n("br")]),n("v-select",{staticClass:"settings__item-form",attrs:{outlined:"","hide-details":"",items:t.panel_display_state},model:{value:t.settings.panel_display_state,callback:function(e){t.$set(t.settings,"panel_display_state",e)},expression:"settings.panel_display_state"}})],1),n("div",{staticClass:"settings__item"},[n("div",{staticClass:"settings__item-heading"},[t._v("既定で表示されるパネルのタブ")]),n("div",{staticClass:"settings__item-label"},[t._v(" 視聴画面を開いたときに、右側のパネルで最初に表示されるタブを設定します。"),n("br")]),n("v-select",{staticClass:"settings__item-form",attrs:{outlined:"","hide-details":"",items:t.panel_active_tab},model:{value:t.settings.panel_active_tab,callback:function(e){t.$set(t.settings,"panel_active_tab",e)},expression:"settings.panel_active_tab"}})],1)])])},Jt=[],Xt=(n("4fad"),function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"route-container"},[n("Header"),n("main",[n("Navigation"),n("v-card",{staticClass:"settings-container d-flex px-5 py-5 mx-auto background",attrs:{elevation:"0",width:"100%","max-width":"1000"}},[n("div",[n("v-navigation-drawer",{staticClass:"settings-navigation flex-shrink-0 background",attrs:{permanent:"",width:"195",height:"auto"}},[n("v-list-item",{staticClass:"px-4"},[n("v-list-item-content",[n("h1",[t._v("設定")])])],1),n("v-list",{staticClass:"mt-2 px-0",attrs:{nav:""}},[n("v-list-item",{staticClass:"px-4",attrs:{link:"",color:"primary",to:"/settings/general"}},[n("v-list-item-icon",{staticClass:"mr-4"},[n("Icon",{staticStyle:{padding:"0 3px"},attrs:{icon:"fa-solid:sliders-h",width:"26px"}})],1),n("v-list-item-content",[n("v-list-item-title",[t._v("全般")])],1)],1),n("v-list-item",{staticClass:"px-4",attrs:{link:"",color:"primary",to:"/settings/account"}},[n("v-list-item-icon",{staticClass:"mr-4"},[n("Icon",{attrs:{icon:"fluent:person-20-filled",width:"26px"}})],1),n("v-list-item-content",[n("v-list-item-title",[t._v("アカウント")])],1)],1),n("v-list-item",{staticClass:"px-4",attrs:{link:"",color:"primary",to:"/settings/jikkyo"}},[n("v-list-item-icon",{staticClass:"mr-4"},[n("Icon",{staticStyle:{padding:"0 2px"},attrs:{icon:"bi:chat-left-text-fill",width:"26px"}})],1),n("v-list-item-content",[n("v-list-item-title",[t._v("ニコニコ実況")])],1)],1),n("v-list-item",{staticClass:"px-4",attrs:{link:"",color:"primary",to:"/settings/twitter"}},[n("v-list-item-icon",{staticClass:"mr-4"},[n("Icon",{staticStyle:{padding:"0 1px"},attrs:{icon:"fa-brands:twitter",width:"26px"}})],1),n("v-list-item-content",[n("v-list-item-title",[t._v("Twitter")])],1)],1)],1)],1)],1),n("v-card",{staticClass:"settings ml-5 px-7 py-7 background lighten-1",attrs:{width:"100%"}},[t._t("default")],2)],1)],1)],1)}),Qt=[],Zt=r["a"].extend({name:"SettingsBase",components:{Header:z,Navigation:rt}}),te=Zt,ee=(n("5e6f"),n("8860")),ne=n("da13"),ae=n("5d23"),ie=n("34c3"),se=n("f774"),re=Object(d["a"])(te,Xt,Qt,!1,null,"18637a38",null),le=re.exports;m()(re,{VCard:Ut["a"],VList:ee["a"],VListItem:ne["a"],VListItemContent:ae["a"],VListItemIcon:ie["a"],VListItemTitle:ae["b"],VNavigationDrawer:se["a"]});var oe=r["a"].extend({name:"SettingsGeneral",components:{Base:le},data:function(){return{tv_streaming_quality:[{text:"1080p (1時間あたり約2.31GB / 5.1Mbps)",value:"1080p"},{text:"810p (1時間あたり約1.92GB / 4.2Mbps)",value:"810p"},{text:"720p (1時間あたり約1.33GB / 3.0Mbps)",value:"720p"},{text:"540p (1時間あたり約1.00GB / 2.2Mbps)",value:"540p"},{text:"480p (1時間あたり約0.74GB / 1.6Mbps)",value:"480p"},{text:"360p (1時間あたり約0.40GB / 0.9Mbps)",value:"360p"},{text:"240p (1時間あたり約0.23GB / 0.5Mbps)",value:"240p"}],panel_display_state:[{text:"前回の状態を復元する",value:"RestorePreviousState"},{text:"常に表示する",value:"AlwaysDisplay"},{text:"常に折りたたむ",value:"AlwaysFold"}],panel_active_tab:[{text:"番組情報タブ",value:"Program"},{text:"チャンネルタブ",value:"Channel"},{text:"コメントタブ",value:"Comment"},{text:"Twitter タブ",value:"Twitter"}],settings:function(){for(var t={},e=0,n=["tv_streaming_quality","panel_display_state","panel_active_tab"];e {\n\n // VueComponent の key が一致する this.$slots.default 内の VNode を探す\n const index_a = this.$slots.default.findIndex((element) => {\n return a.$vnode.key === element.key;\n });\n const index_b = this.$slots.default.findIndex((element) => {\n return b.$vnode.key === element.key;\n });\n\n // index 順で並び替え\n return index_a - index_b;\n });\n\n item.$on('change', () => (this as any).onClick(item));\n if ((this as any).mandatory && !(this as any).selectedValues.length) {\n (this as any).updateMandatory();\n }\n\n // 追加された要素のソート後のインデックスを取得して更新する\n (this as any).updateItem(item, this.items.indexOf(item));\n\n // ソート後の現在アクティブなタブのインデックスを取得し直し、設定する\n // 配列の末尾以外に追加された場合はインデックスが1つずつずれてしまうため、インデックスを設定し直す必要がある\n if (activeItem !== undefined) {\n (this as any).updateInternalValue(this.items.indexOf(activeItem));\n }\n },\n\n unregister(item: GroupableInstance) {\n\n // 現在アクティブなタブの VueComponent を取得\n const activeItem = this.items[(this as any).internalIndex];\n\n // 継承元の unregister() の処理を呼び出す(いわゆる super() )\n // ref: https://github.com/vuejs/vue/issues/2977\n (this.constructor as any).super.options.methods.unregister.call(this, item);\n\n // 配列の末尾以外から削除された場合はインデックスが1つずつずれてしまうため、インデックスを設定し直す必要がある\n if (activeItem !== undefined) {\n (this as any).updateInternalValue(this.items.indexOf(activeItem));\n }\n }\n }\n});\n","\nimport { VueConstructor, VNode } from 'vue';\n\nimport { convertToUnit } from 'vuetify/lib/util/helpers'\nimport VTabs from 'vuetify/lib/components/VTabs/VTabs';\nimport VTabsBar from '@/components/VTabsBar';\n\nexport default (VTabs as VueConstructor).extend({\n methods: {\n\n // VTabsBar は VTabs から暗黙的に生成されるコンポーネントのため、直接上書きすることができない\n // そこで VTabs 自体も上書きし、VTabs で $createElement() される時の VTabsBar を自前でオーバーライドしたものに差し替える\n // ビルド済みのファイルには型定義が入っていないので any を多用せざるを得ない…\n genBar(items: VNode[], slider: VNode | null) {\n const data = {\n style: {\n height: convertToUnit((this as any).height),\n },\n props: {\n activeClass: (this as any).activeClass,\n centerActive: (this as any).centerActive,\n dark: (this as any).dark,\n light: (this as any).light,\n mandatory: !(this as any).optional,\n mobileBreakpoint: (this as any).mobileBreakpoint,\n nextIcon: (this as any).nextIcon,\n prevIcon: (this as any).prevIcon,\n showArrows: (this as any).showArrows,\n value: (this as any).internalValue,\n },\n on: {\n 'call:slider': (this as any).callSlider,\n change: (val: any) => {\n (this as any).internalValue = val;\n },\n },\n ref: 'items',\n };\n\n (this as any).setTextColor((this as any).computedColor, data);\n (this as any).setBackgroundColor((this as any).backgroundColor, data);\n\n // ここでオーバーライドした VTabsBar を使うのが最重要\n // これをやるためだけにわざわざ VTabs に関してもオーバーライドする羽目になってる…\n return (this as any).$createElement(VTabsBar, data, [\n (this as any).genSlider(slider),\n items,\n ]);\n }\n }\n});\n","\nimport { VueConstructor } from 'vue';\n\nimport { GroupableInstance } from 'vuetify/lib/components/VItemGroup/VItemGroup';\nimport VTabsItems from 'vuetify/lib/components/VTabs/VTabsItems';\n\n// VTabsItems は VItemGroup と VWindow を extend() して実装されている\nexport default (VTabsItems as VueConstructor).extend({\n data() {\n return {\n // 一応型定義をしておく\n items: [] as GroupableInstance[],\n }\n },\n methods: {\n\n // タブのデータ配列の先頭に新しい要素が追加されるとそのタブのアニメーションの向きが逆になるバグがあるので、VItemGroup 側の挙動をオーバーライドする\n // DOM 上も VNode 上も正しい順序で並んでいるが、this.items に関しては追加された順になっていてしまっていて齟齬が発生するのが原因\n // ref: https://github.com/vuetifyjs/vuetify/issues/13862\n register(item: GroupableInstance) {\n\n // 現在アクティブなタブの VueComponent を取得\n const activeItem = this.items[(this as any).internalIndex];\n\n // 要素を items に追加\n this.items.push(item);\n\n // this.$slots.default に VNode が、items には単に VueComponent が入っているので、事前に VNode の順番に合わせて並べ替える\n // こうすることで、追加された順ではなく元のデータ配列通りの順番になる\n this.items.sort((a, b) => {\n\n // VueComponent の key が一致する this.$slots.default 内の VNode を探す\n const index_a = this.$slots.default.findIndex((element) => {\n return a.$vnode.key === element.key;\n });\n const index_b = this.$slots.default.findIndex((element) => {\n return b.$vnode.key === element.key;\n });\n\n // index 順で並び替え\n return index_a - index_b;\n });\n\n item.$on('change', () => (this as any).onClick(item));\n if ((this as any).mandatory && !(this as any).selectedValues.length) {\n (this as any).updateMandatory();\n }\n\n // 追加された要素のソート後のインデックスを取得して更新する\n (this as any).updateItem(item, this.items.indexOf(item));\n\n // ソート後の現在アクティブなタブのインデックスを取得し直し、設定する\n // 配列の末尾以外に追加された場合はインデックスが1つずつずれてしまうため、インデックスを設定し直す必要がある\n if (activeItem !== undefined) {\n // 値が異なるときだけ更新する\n // こうしないと、Safari で変なアニメーションがついてしまう\n if (this.items.indexOf(activeItem) !== (this as any).internalValue) {\n (this as any).updateInternalValue(this.items.indexOf(activeItem));\n }\n }\n },\n\n unregister(item: GroupableInstance) {\n\n // 現在アクティブなタブの VueComponent を取得\n const activeItem = this.items[(this as any).internalIndex];\n\n // 継承元の unregister() の処理を呼び出す(いわゆる super() )\n // ref: https://github.com/vuejs/vue/issues/2977\n (this.constructor as any).super.options.methods.unregister.call(this, item);\n\n // 配列の末尾以外から削除された場合はインデックスが1つずつずれてしまうため、インデックスを設定し直す必要がある\n if (activeItem !== undefined) {\n (this as any).updateInternalValue(this.items.indexOf(activeItem));\n }\n },\n\n // 最初のタブから最後のタブに遷移するとアニメーションの向きが逆になるバグがあるので、VWindow 側の挙動をオーバーライドする\n // 本来は VCarousel 用の動作だが、VTabsItems も VWindow を継承しているので、それが適用されてしまっているらしい\n // ref: https://github.com/yuwu9145/vuetify/blob/master/packages/vuetify/src/components/VWindow/VWindow.ts#L239-L252\n updateReverse(val: number, oldVal: number) {\n\n const itemsLength = this.items.length;\n const lastIndex = itemsLength - 1;\n\n if (itemsLength <= 2) return val < oldVal;\n\n // continuous が false の時、常に val < oldVal の結果を返す\n if (!(this as any).continuous) return val < oldVal;\n\n if (val === lastIndex && oldVal === 0) {\n return true;\n } else if (val === 0 && oldVal === lastIndex) {\n return false;\n } else {\n return val < oldVal;\n }\n }\n }\n});\n","\nimport Vue from 'vue';\nimport Vuetify from 'vuetify/lib/framework';\n\nVue.use(Vuetify);\n\nexport default new Vuetify({\n theme: {\n dark: true,\n themes: {\n dark: {\n primary: '#E64F97',\n secondary: '#E64F97',\n twitter: '#4F82E6',\n gray: '#66514C',\n black: '#110A09',\n background: {\n base: '#1E1310',\n lighten1: '#2F221F',\n lighten2: '#433532',\n lighten3: '#4c3c38',\n },\n text: {\n base: '#FFEAEA',\n darken1: '#D9C7C7',\n darken2: '#8E7F7E',\n darken3: '#786968',\n }\n }\n },\n options: {\n customProperties: true,\n },\n },\n});\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"route-container\"},[_c('Header'),_c('main',[_c('Navigation'),_c('div',{staticClass:\"channels-container channels-container--home\",class:{'channels-container--loading': _vm.is_loading}},[_c('v-tabs-fix',{staticClass:\"channels-tab\",attrs:{\"centered\":\"\"},model:{value:(_vm.tab),callback:function ($$v) {_vm.tab=$$v},expression:\"tab\"}},_vm._l((Array.from(_vm.channels_list)),function(ref){\nvar channels_type = ref[0];\nreturn _c('v-tab',{key:channels_type,staticClass:\"channels-tab__item\"},[_vm._v(_vm._s(channels_type))])}),1),_c('v-tabs-items-fix',{staticClass:\"channels-list\",model:{value:(_vm.tab),callback:function ($$v) {_vm.tab=$$v},expression:\"tab\"}},_vm._l((Array.from(_vm.channels_list)),function(ref){\nvar channels_type = ref[0];\nvar channels = ref[1];\nreturn _c('v-tab-item-fix',{key:channels_type,staticClass:\"channels-tabitem\"},[_c('div',{staticClass:\"channels\",class:(\"channels--tab-\" + channels_type + \" channels--length-\" + (channels.length))},[_vm._l((channels),function(channel){return _c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],key:channel.id,staticClass:\"channel\",attrs:{\"to\":(\"/tv/watch/\" + (channel.channel_id))}},[_c('div',{staticClass:\"channel__broadcaster\"},[_c('img',{staticClass:\"channel__broadcaster-icon\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + (channel.channel_id) + \"/logo\")}}),_c('div',{staticClass:\"channel__broadcaster-content\"},[_c('span',{staticClass:\"channel__broadcaster-name\"},[_vm._v(\"Ch: \"+_vm._s(channel.channel_number)+\" \"+_vm._s(channel.channel_name))]),_c('div',{staticClass:\"channel__broadcaster-status\"},[_c('div',{staticClass:\"channel__broadcaster-status-force\",class:(\"channel__broadcaster-status-force--\" + (_vm.TVUtils.getChannelForceType(channel.channel_force)))},[_c('Icon',{attrs:{\"icon\":\"fa-solid:fire-alt\",\"height\":\"12px\"}}),_c('span',{staticClass:\"ml-1\"},[_vm._v(\"勢い:\")]),_c('span',{staticClass:\"ml-1\"},[_vm._v(_vm._s(_vm.TVUtils.getAttribute(channel, 'channel_force', '--'))+\" コメ/分\")])],1),_c('div',{staticClass:\"channel__broadcaster-status-viewers ml-4\"},[_c('Icon',{attrs:{\"icon\":\"fa-solid:eye\",\"height\":\"14px\"}}),_c('span',{staticClass:\"ml-1\"},[_vm._v(\"視聴数:\")]),_c('span',{staticClass:\"ml-1\"},[_vm._v(_vm._s(channel.viewers))])],1)])]),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip\",value:(_vm.isPinnedChannel(channel.channel_id) ? 'ピン留めを外す' : 'ピン留めする'),expression:\"isPinnedChannel(channel.channel_id) ? 'ピン留めを外す' : 'ピン留めする'\"}],staticClass:\"channel__broadcaster-pin\",class:{'channel__broadcaster-pin--pinned': _vm.isPinnedChannel(channel.channel_id)},on:{\"click\":function($event){$event.preventDefault();$event.stopPropagation();_vm.isPinnedChannel(channel.channel_id) ? _vm.removePinnedChannel(channel.channel_id) : _vm.addPinnedChannel(channel.channel_id)},\"mousedown\":function($event){$event.preventDefault();$event.stopPropagation();/* 親要素の波紋が広がらないように */}}},[_c('Icon',{attrs:{\"icon\":\"fluent:pin-20-filled\",\"width\":\"24px\"}})],1)]),_c('div',{staticClass:\"channel__program-present\"},[_c('span',{staticClass:\"channel__program-present-title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_present, 'title'))}}),_c('span',{staticClass:\"channel__program-present-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(channel.program_present)))]),_c('span',{staticClass:\"channel__program-present-description\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_present, 'description'))}})]),_c('v-spacer'),_c('div',{staticClass:\"channel__program-following\"},[_c('div',{staticClass:\"channel__program-following-title\"},[_c('span',{staticClass:\"channel__program-following-title-decorate\"},[_vm._v(\"NEXT\")]),_c('Icon',{staticClass:\"channel__program-following-title-icon\",attrs:{\"icon\":\"fluent:fast-forward-20-filled\",\"width\":\"16px\"}}),_c('span',{staticClass:\"channel__program-following-title-text\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_following, 'title'))}})],1),_c('span',{staticClass:\"channel__program-following-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(channel.program_following)))])]),_c('div',{staticClass:\"channel__progressbar\"},[_c('div',{staticClass:\"channel__progressbar-progress\",style:((\"width:\" + (_vm.TVUtils.getProgramProgress(channel.program_present)) + \"%;\"))})])],1)}),(channels_type === 'ピン留め' && channels.length === 0)?_c('div',{staticClass:\"d-flex justify-center align-center w-100\"},[_c('div',{staticClass:\"d-flex justify-center align-center flex-column\"},[_c('h2',[_vm._v(\"ピン留めされているチャンネルがありません。\")]),_c('div',{staticClass:\"mt-4 text--text text--darken-1\"},[_vm._v(\"各チャンネルの \"),_c('Icon',{staticStyle:{\"position\":\"relative\",\"bottom\":\"-5px\"},attrs:{\"icon\":\"fluent:pin-20-filled\",\"width\":\"22px\"}}),_vm._v(\" アイコンから、よくみるチャンネルをこのタブにピン留めできます。\")],1),_c('div',{staticClass:\"mt-2 text--text text--darken-1\"},[_vm._v(\"チャンネルをピン留めすると、このタブが最初に表示されます。\")])])]):_vm._e()],2)])}),1)],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('v-toolbar',{staticClass:\"header\",attrs:{\"absolute\":\"\",\"color\":\"background\",\"elevation\":\"8\",\"width\":\"100%\"}},[_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"logo ml-3 ml-md-6\",attrs:{\"to\":\"/tv/\"}},[_c('img',{staticClass:\"logo__image\",attrs:{\"src\":\"/assets/img/logo.svg\",\"height\":\"21\"}})]),_c('v-spacer'),_c('v-btn',{staticClass:\"mr-3 mr-md-6\",attrs:{\"icon\":\"\"}},[_c('v-icon',[_vm._v(\"mdi-dots-vertical\")])],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./Header.vue?vue&type=template&id=04bd7f60&\"\nvar script = {}\nimport style0 from \"./Header.vue?vue&type=style&index=0&lang=scss&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VBtn } from 'vuetify/lib/components/VBtn';\nimport { VIcon } from 'vuetify/lib/components/VIcon';\nimport { VSpacer } from 'vuetify/lib/components/VGrid';\nimport { VToolbar } from 'vuetify/lib/components/VToolbar';\ninstallComponents(component, {VBtn,VIcon,VSpacer,VToolbar})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"navigation-container elevation-8\"},[_c('nav',{staticClass:\"navigation\"},[_c('div',{staticClass:\"navigation-scroll\"},[_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/tv/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:tv-20-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"テレビをみる\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/videos/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:movies-and-tv-20-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"ビデオをみる\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/schedules/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:calendar-ltr-20-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"番組表\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/captures/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:image-multiple-24-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"キャプチャ\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/watchlists/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"ic:round-playlist-play\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"ウォッチリスト\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/histories/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:history-16-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"視聴履歴\")])],1),_c('v-spacer'),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/settings/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:settings-20-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"設定\")])],1),_c('a',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"href\":\"https://github.com/tsukumijima/KonomiTV\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:info-16-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"version \"+_vm._s(_vm.Utils.version))])],1)],1)])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n/**\n * 共通ユーティリティ\n */\nexport default class Utils {\n\n // バージョン情報\n // ビルド時の環境変数 (vue.config.js に記載) から取得\n static readonly version:string = process.env.VUE_APP_VERSION;\n\n // バックエンドの API のベース URL\n static readonly api_base_url = (() => {\n if (process.env.NODE_ENV === 'development') {\n // デバッグ時はポートを 7000 に強制する\n return `${window.location.protocol}//${window.location.hostname}:7000/api`;\n } else {\n // ビルド後は同じポートを使う\n return `${window.location.protocol}//${window.location.host}/api`;\n }\n })();\n\n // デフォルトの設定値\n static readonly default_settings = {\n\n // ピン留めしているチャンネルの ID (ex: gr011) が入るリスト\n pinned_channel_ids: [] as string[],\n\n // テレビのストリーミング画質(1080p)\n tv_streaming_quality: '1080p' as ('1080p' | '810p' | '720p' | '540p' | '480p' | '360p' | '240p'),\n\n // 前回視聴画面を開いた際にパネルが表示されていたかどうか\n is_latest_panel_display: true as boolean,\n\n // 既定のパネルの表示状態(前回の状態を復元する)\n panel_display_state: 'RestorePreviousState' as ('RestorePreviousState' | 'AlwaysDisplay' | 'AlwaysFold'),\n\n // 既定で表示されるパネルのタブ(番組情報タブ)\n panel_active_tab: 'Program' as ('Program' | 'Channel' | 'Comment' | 'Twitter'),\n\n // コメントの速さ (1倍)\n comment_speed_rate: 1 as number,\n\n // コメントのフォントサイズ (34px)\n comment_font_size: 34 as number,\n\n // コメントの遅延時間 (1秒)\n comment_delay_time: 1 as number,\n };\n\n\n /**\n * プレイヤーの背景画像をランダムで取得し、その URL を返す\n * @returns ランダムで設定されたプレイヤーの背景画像の URL\n */\n static generatePlayerBackgroundURL(): string {\n const background_count = 12; // 12種類から選択\n const random = (Math.floor(Math.random() * background_count) + 1);\n return `/assets/img/player-backgrounds/${random.toString().padStart(2, '0')}.jpg`;\n }\n\n\n /**\n * 設定を LocalStorage から取得する\n * @param key 設定のキー名\n * @returns 設定されている値\n */\n static getSettingsItem(key: string): any | null {\n\n // LocalStorage から KonomiTV-Settings を取得\n // データは JSON で管理し、LocalStorage 上の一つのキーにまとめる\n // キーが存在しない場合はデフォルトの設定値を使う\n const settings:object = JSON.parse(localStorage.getItem('KonomiTV-Settings')) || Utils.default_settings;\n\n // そのキーが保存されているときだけ、設定値を返す\n if (key in settings) {\n return settings[key];\n } else {\n // デフォルトの設定値にあればそれを使う\n if (key in this.default_settings) {\n return this.default_settings[key];\n } else {\n return null;\n }\n }\n }\n\n\n /**\n * 設定を LocalStorage に保存する\n * @param key 設定のキー名\n * @param value 設定する値\n */\n static setSettingsItem(key: string, value: any): void {\n\n // LocalStorage から KonomiTV-Settings を取得\n const settings:object = JSON.parse(localStorage.getItem('KonomiTV-Settings')) || Utils.default_settings;\n\n // そのキーがデフォルトの設定値に定義されているときだけ\n // バージョン違いなどで settings には登録されていないキーだが default_settings には登録されているケースが発生し得るため\n if (key in this.default_settings) {\n\n // 設定値を新しい値で置き換え\n settings[key] = value;\n\n // LocalStorage に保存\n localStorage.setItem('KonomiTV-Settings', JSON.stringify(settings));\n }\n }\n}\n","\nimport dayjs from 'dayjs';\nimport 'dayjs/locale/ja';\n\nimport { IChannel, IProgram } from '@/interface';\n\n/**\n * TV 機能のユーティリティ\n */\nexport class TVUtils {\n\n /**\n * 番組情報中の[字]や[解]などの記号をいい感じに装飾する\n * @param program 番組情報のオブジェクト\n * @param key 番組情報のオブジェクトから取り出すプロパティのキー\n * @returns 装飾した文字列\n */\n static decorateProgramInfo(program: IProgram, key: string): string {\n\n // program が空でないかつ、program[key] が存在する\n if (program !== null && program[key] !== null) {\n\n // 本来 ARIB 外字である記号の一覧\n // ref: https://ja.wikipedia.org/wiki/%E7%95%AA%E7%B5%84%E8%A1%A8\n // ref: https://github.com/xtne6f/EDCB/blob/work-plus-s/EpgDataCap3/EpgDataCap3/ARIB8CharDecode.cpp#L1319\n const mark = '新|終|再|交|映|手|声|多|副|字|文|CC|OP|二|S|B|SS|無|無料' +\n 'C|S1|S2|S3|MV|双|デ|D|N|W|P|H|HV|SD|天|解|料|前|後初|生|販|吹|PPV|' +\n '演|移|他|収|・|英|韓|中|字/日|字/日英|3D|2K|4K|8K|5.1|7.1|22.2|60P|120P|d|HC|HDR|SHV|UHD|VOD|配|初';\n\n // 正規表現を作成\n const pattern1 = new RegExp(`\\\\((二|字|再)\\\\)`, 'g'); // 通常の括弧で囲まれている記号\n const pattern2 = new RegExp(`\\\\[(${mark})\\\\]`, 'g');\n\n // 正規表現で置換した結果を返す\n let replaced = program[key].replace(pattern1, '$1');\n replaced = replaced.replace(pattern2, '$1');\n return replaced;\n\n // 放送休止中\n } else {\n return key == 'title' ? '放送休止': 'この時間は放送を休止しています。';\n }\n }\n\n\n /**\n * オブジェクトからプロパティを取得し、もしプロパティが存在しなければ代替値を返す\n * @param items 対象のオブジェクト\n * @param key オブジェクトから取り出すプロパティのキー\n * @param default_value 取得できなかった際の代替値\n * @returns オブジェクト取得した値 or 代替値\n */\n static getAttribute(items: {[key: string]: any}, key: string, default_value: any): any {\n\n // items が空でないかつ、items[key] が存在する\n if (items !== null && items[key] !== undefined && items[key] !== null) {\n\n // items[key] の内容を返す\n return items[key];\n\n // 指定された代替値を返す\n } else {\n return default_value;\n }\n }\n\n\n /**\n * チャンネル ID からチャンネルタイプを取得する\n * @param channel_id チャンネル ID\n * @param is_chideji GR を「地デジ」と表記するかどうか\n * @returns チャンネルタイプ\n */\n static getChannelType(channel_id: string, is_chideji: boolean = false): string {\n const result = channel_id.match('(?[a-z]+)[0-9]+').groups.channel_type.toUpperCase();\n if (result === 'GR' && is_chideji) {\n return '地デジ';\n } else {\n return result;\n }\n }\n\n\n /**\n * チャンネルの実況勢いから「多」「激多」「祭」を取得する\n * ref: https://ja.wikipedia.org/wiki/%E3%83%8B%E3%82%B3%E3%83%8B%E3%82%B3%E5%AE%9F%E6%B3%81\n * @param channel_force チャンネルの実況勢い\n * @returns normal(普通)or many(多)or so-many(激多)or festival(祭)\n */\n static getChannelForceType(channel_force: number | null): 'normal' | 'many' | 'so-many' | 'festival' {\n\n // 実況勢いが null(=対応する実況チャンネルがない)\n if (channel_force === null) return 'normal';\n\n // 実況勢いが 1000 コメント以上(祭)\n if (channel_force >= 1000) return 'festival';\n // 実況勢いが 200 コメント以上(激多)\n if (channel_force >= 200) return 'so-many';\n // 実況勢いが 100 コメント以上(多)\n if (channel_force >= 100) return 'many';\n\n // それ以外\n return 'normal';\n }\n\n\n /**\n * チャンネルタイプとリモコン番号からチャンネル情報を取得する\n * @param channels_list チャンネルリスト\n * @param channel_type チャンネルタイプ\n * @param remocon_id リモコン番号\n * @returns チャンネル情報\n */\n static getChannelFromRemoconID(channels_list: Map, channel_type: string, remocon_id: number): IChannel | null {\n\n // 指定されたチャンネルタイプのチャンネルを取得\n channel_type = channel_type.replace('GR', '地デジ'); //「GR」は「地デジ」に置換しておく\n const channels = channels_list.get(channel_type);\n\n // リモコン番号が一致するチャンネルを見つけ、一番最初に見つかったものを返す\n for (let index = 0; index < channels.length; index++) {\n const channel = channels[index];\n if (channel.remocon_id === remocon_id) {\n return channel;\n }\n }\n\n // リモコン番号が一致するチャンネルを見つけられなかった\n return null;\n }\n\n\n /**\n * 前・現在・次のチャンネル情報を取得する\n * @param channels_list チャンネルリスト\n * @param channel_id 起点にする現在のチャンネル ID\n * @returns 前・現在・次のチャンネル情報\n */\n static getPreviousAndCurrentAndNextChannel(channels_list: Map, channel_id: string): IChannel[] {\n\n // 前後のチャンネルを取得\n const channels = channels_list.get(this.getChannelType(channel_id, true));\n for (let index = 0; index < channels.length; index++) {\n const element = channels[index];\n\n // チャンネル ID が一致したときだけ\n if (element.channel_id === channel_id) {\n\n // インデックスが最初か最後の時はそれぞれ最後と最初にインデックスを一周させる\n let previous_index = index - 1;\n if (previous_index === -1) previous_index = channels.length - 1;\n let next_index = index + 1;\n if (next_index === channels.length) next_index = 0;\n\n // 前・現在・次のチャンネル情報を返す\n return [channels[previous_index], channels[index], channels[next_index]];\n }\n }\n }\n\n\n /**\n * 番組の放送時刻を取得する\n * @param program 番組情報\n * @param is_short 時刻のみ返すかどうか\n * @returns 番組の放送時刻\n */\n static getProgramTime(program: IProgram, is_short: boolean = false): string {\n\n // program が空でなく、かつ番組時刻が初期値でない\n if (program !== null && program.start_time !== '2000-01-01T00:00:00+09:00') {\n\n // dayjs で日付を扱いやすく\n dayjs.locale('ja'); // ロケールを日本に設定\n const start_time = dayjs(program.start_time);\n const end_time = dayjs(program.end_time);\n const duration = program.duration / 60; // 分換算\n\n // 時刻のみ返す\n if (is_short === true) { // 時刻のみ\n return `${start_time.format('HH:mm')} ~ ${end_time.format('HH:mm')}`;\n // 通常\n } else {\n return `${start_time.format('YYYY/MM/DD (dd) HH:mm')} ~ ${end_time.format('HH:mm')} (${duration}分)`;\n }\n\n // 放送休止中\n } else {\n\n // 時刻のみ返す\n if (is_short === true) {\n return '--:-- ~ --:--';\n // 通常\n } else {\n return '----/--/-- (-) --:-- ~ --:-- (--分)';\n }\n }\n }\n\n\n /**\n * 番組の進捗状況を取得する\n * @param program 番組情報\n * @returns 番組の進捗状況(%単位)\n */\n static getProgramProgress(program: IProgram): number {\n\n // program が空でない\n if (program !== null) {\n\n // 番組開始時刻から何秒進んだか\n const progress = dayjs(dayjs()).diff(program.start_time, 'second');\n\n // %単位の割合を算出して返す\n return progress / program.duration * 100;\n\n // 放送休止中\n } else {\n return 0;\n }\n }\n}\n","\n// 共通ユーティリティをデフォルトとしてインポート\nimport Utils from '@/utils/Utils';\nexport default Utils;\n\n// Utils フォルダ配下のユーティリティを一括でインポートできるように\nexport * from '@/utils/TVUtils';\n","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'Navigation',\n data() {\n return {\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n }\n }\n});\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--15-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Navigation.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--15-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Navigation.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Navigation.vue?vue&type=template&id=4fdece88&scoped=true&\"\nimport script from \"./Navigation.vue?vue&type=script&lang=ts&\"\nexport * from \"./Navigation.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Navigation.vue?vue&type=style&index=0&id=4fdece88&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"4fdece88\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VSpacer } from 'vuetify/lib/components/VGrid';\ninstallComponents(component, {VSpacer})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport { IChannel } from '@/interface';\nimport Header from '@/components/Header.vue';\nimport Navigation from '@/components/Navigation.vue';\nimport Utils, { TVUtils } from '@/utils';\n\nexport default Vue.extend({\n name: 'Home',\n components: {\n Header,\n Navigation,\n },\n data() {\n return {\n\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n TVUtils: TVUtils,\n\n // タブの状態管理\n tab: null as number | null,\n\n // ローディング中かどうか\n is_loading: true,\n\n // インターバル ID\n // ページ遷移時に setInterval(), setTimeout() の実行を止めるのに使う\n // setInterval(), setTimeout() の返り値を登録する\n interval_ids: [] as number[],\n\n // チャンネル情報リスト\n channels_list: new Map() as Map,\n\n // ピン留めしているチャンネルの ID (ex: gr011) が入るリスト\n pinned_channel_ids: [] as string[],\n }\n },\n // 開始時に実行\n created() {\n\n // チャンネル情報を取得\n this.update();\n\n // 00秒までの残り秒数\n // 現在 16:01:34 なら 26 (秒) になる\n const residue_second = 60 - (Math.floor(new Date().getTime() / 1000) % 60);\n\n // 00秒になるまで待ってから\n // 番組は基本1分単位で組まれているため、20秒や45秒など中途半端な秒数で更新してしまうと反映が遅れてしまう\n this.interval_ids.push(window.setTimeout(() => {\n\n // チャンネル情報を更新\n this.update();\n\n // チャンネル情報を定期的に更新\n this.interval_ids.push(window.setInterval(() => {\n this.update();\n }, 30 * 1000)); // 30秒おき\n\n }, residue_second * 1000));\n },\n // 終了前に実行\n beforeDestroy() {\n\n // clearInterval() ですべての setInterval(), setTimeout() の実行を止める\n // clearInterval() と clearTimeout() は中身共通なので問題ない\n for (const interval_id of this.interval_ids) {\n window.clearInterval(interval_id);\n }\n },\n methods: {\n\n // チャンネル情報一覧を取得し、画面を更新する\n async update() {\n\n // チャンネル情報一覧 API にアクセス\n let channels_response;\n try {\n channels_response = await Vue.axios.get(`${Utils.api_base_url}/channels`);\n } catch (error) {\n console.error(error); // エラー内容を表示\n return;\n }\n\n // is_display が true のチャンネルのみに絞り込むフィルタ関数\n // 放送していないサブチャンネルを表示から除外する\n const filter = (channel: IChannel) => {\n return channel.is_display;\n }\n\n // チャンネルリストを再構築\n // 1つでもチャンネルが存在するチャンネルタイプのみ表示するように\n // たとえば SKY (スカパー!プレミアムサービス) のタブは SKY に属すチャンネルが1つもない(=受信できない)なら表示されない\n this.channels_list = new Map();\n if (channels_response.data.GR.length > 0) this.channels_list.set('地デジ', channels_response.data.GR.filter(filter));\n if (channels_response.data.BS.length > 0) this.channels_list.set('BS', channels_response.data.BS.filter(filter));\n if (channels_response.data.CS.length > 0) this.channels_list.set('CS', channels_response.data.CS.filter(filter));\n if (channels_response.data.CATV.length > 0) this.channels_list.set('CATV', channels_response.data.CATV.filter(filter));\n if (channels_response.data.SKY.length > 0) this.channels_list.set('SKY', channels_response.data.SKY.filter(filter));\n if (channels_response.data.STARDIGIO.length > 0) this.channels_list.set('StarDigio', channels_response.data.STARDIGIO.filter(filter));\n\n // ピン留めされているチャンネルのリストを更新\n this.updatePinnedChannelList(this.is_loading ? true : false);\n\n // ローディング状態を解除\n this.is_loading = false;\n },\n\n // チャンネルをピン留めする\n addPinnedChannel(channel_id: string) {\n\n // 現在ピン留めされているチャンネルを取得\n this.pinned_channel_ids = Utils.getSettingsItem('pinned_channel_ids');\n\n // ピン留めするチャンネルの ID を追加\n this.pinned_channel_ids.push(channel_id);\n\n // 設定を保存\n Utils.setSettingsItem('pinned_channel_ids', this.pinned_channel_ids);\n\n // ピン留めされているチャンネルのリストを更新\n this.updatePinnedChannelList();\n },\n\n // チャンネルをピン留めから外す\n removePinnedChannel(channel_id: string) {\n\n // 現在ピン留めされているチャンネルを取得\n this.pinned_channel_ids = Utils.getSettingsItem('pinned_channel_ids');\n\n // ピン留めを外すチャンネルの ID を削除\n this.pinned_channel_ids.splice(this.pinned_channel_ids.indexOf(channel_id), 1);\n\n // 設定を保存\n Utils.setSettingsItem('pinned_channel_ids', this.pinned_channel_ids);\n\n // ピン留めされているチャンネルのリストを更新\n this.updatePinnedChannelList();\n },\n\n // ピン留めされているチャンネルのリストを更新する\n updatePinnedChannelList(is_update_tab: boolean = true) {\n\n // ピン留めされているチャンネルの ID を取得\n this.pinned_channel_ids = Utils.getSettingsItem('pinned_channel_ids');\n\n // ピン留めされているチャンネル情報のリスト\n const pinned_channels = [] as IChannel[];\n\n // チャンネル ID が一致したチャンネルの情報を保存する\n for (const pinned_channel_id of this.pinned_channel_ids) {\n const pinned_channel_type = TVUtils.getChannelType(pinned_channel_id, true);\n pinned_channels.push(this.channels_list.get(pinned_channel_type).find((channel) => {\n return channel.channel_id === pinned_channel_id; // チャンネル ID がピン留めされているチャンネルのものと同じ\n }));\n }\n\n if (!this.channels_list.has('ピン留め')) {\n // タブの一番左にピン留めタブを表示する\n this.channels_list = new Map([['ピン留め', pinned_channels], ...this.channels_list]);\n } else {\n // 既に存在するピン留めタブにチャンネル情報を設定する\n this.channels_list.set('ピン留め', pinned_channels);\n }\n\n // pinned_channels が空の場合は、タブを地デジタブに変更\n // ピン留めができる事を示唆するためにピン留めタブ自体は残す\n if (pinned_channels.length === 0 && is_update_tab === true) {\n this.tab = 1;\n }\n },\n\n // チャンネルがピン留めされているか\n isPinnedChannel(channel_id: string): boolean {\n\n // 引数のチャンネルがピン留めリストに存在するかを返す\n return this.pinned_channel_ids.includes(channel_id);\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Home.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Home.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Home.vue?vue&type=template&id=6a407b07&scoped=true&\"\nimport script from \"./Home.vue?vue&type=script&lang=ts&\"\nexport * from \"./Home.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Home.vue?vue&type=style&index=0&lang=scss&\"\nimport style1 from \"./Home.vue?vue&type=style&index=1&id=6a407b07&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"6a407b07\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VSpacer } from 'vuetify/lib/components/VGrid';\nimport { VTab } from 'vuetify/lib/components/VTabs';\ninstallComponents(component, {VSpacer,VTab})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"route-container\"},[_c('main',{staticClass:\"watch-container\",class:{\n 'watch-container--control-display': _vm.is_control_display,\n 'watch-container--panel-display': _vm.is_panel_display,\n 'watch-container--fullscreen': _vm.is_fullscreen,\n }},[_c('nav',{staticClass:\"watch-navigation\",on:{\"mousemove\":function($event){return _vm.controlDisplayTimer($event)},\"touchmove\":function($event){return _vm.controlDisplayTimer($event)},\"click\":function($event){return _vm.controlDisplayTimer($event)}}},[_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"watch-navigation__icon\",attrs:{\"to\":\"/tv/\"}},[_c('img',{staticClass:\"watch-navigation__icon-image\",attrs:{\"src\":\"/assets/img/icon.svg\",\"width\":\"23px\"}})]),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('テレビをみる'),expression:\"'テレビをみる'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/tv/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:tv-20-regular\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('ビデオをみる'),expression:\"'ビデオをみる'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/videos/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:movies-and-tv-20-regular\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('番組表'),expression:\"'番組表'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/schedules/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:calendar-ltr-20-regular\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('キャプチャ'),expression:\"'キャプチャ'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/captures/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:image-multiple-24-regular\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('ウォッチリスト'),expression:\"'ウォッチリスト'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/watchlists/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"ic:round-playlist-play\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('視聴履歴'),expression:\"'視聴履歴'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/histories/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:history-16-regular\",\"width\":\"26px\"}})],1),_c('v-spacer'),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('設定'),expression:\"'設定'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/settings/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:settings-20-regular\",\"width\":\"26px\"}})],1),_c('a',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:((\"version \" + (_vm.Utils.version))),expression:\"`version ${Utils.version}`\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"href\":\"https://github.com/tsukumijima/KonomiTV\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:info-16-regular\",\"width\":\"26px\"}})],1)],1),_c('div',{staticClass:\"watch-content\",on:{\"mousemove\":function($event){return _vm.controlDisplayTimer($event, true)},\"touchmove\":function($event){return _vm.controlDisplayTimer($event, true)},\"click\":function($event){return _vm.controlDisplayTimer($event, true)}}},[_c('header',{staticClass:\"watch-header\"},[_c('img',{staticClass:\"watch-header__broadcaster\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + ((_vm.$route.params.channel_id)) + \"/logo\")}}),_c('span',{staticClass:\"watch-header__program-title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(_vm.channel.program_present, 'title'))}}),_c('span',{staticClass:\"watch-header__program-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(_vm.channel.program_present, true)))]),_c('v-spacer'),_c('span',{staticClass:\"watch-header__now\"},[_vm._v(_vm._s(_vm.time))])],1),_c('div',{staticClass:\"watch-player\",class:{'watch-player--loading': _vm.is_loading}},[_c('div',{staticClass:\"watch-player__background\",class:{'watch-player__background--display': _vm.is_background_display},style:({backgroundImage: (\"url(\" + _vm.background_url + \")\")})},[_c('img',{staticClass:\"watch-player__background-logo\",attrs:{\"src\":\"/assets/img/logo.svg\"}})]),_c('div',{staticClass:\"watch-player__dplayer\"}),_c('div',{staticClass:\"watch-player__button\",on:{\"mousemove\":function($event){return _vm.controlDisplayTimer($event)},\"touchmove\":function($event){return _vm.controlDisplayTimer($event)},\"click\":function($event){return _vm.controlDisplayTimer($event)}}},[_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.top\",value:('前のチャンネル'),expression:\"'前のチャンネル'\",modifiers:{\"top\":true}}],staticClass:\"switch-button switch-button-up\",attrs:{\"to\":(\"/tv/watch/\" + (_vm.channel_previous.channel_id))}},[_c('Icon',{staticClass:\"switch-button-icon\",attrs:{\"icon\":\"fluent:ios-arrow-left-24-filled\",\"width\":\"32px\",\"rotate\":\"1\"}})],1),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"switch-button switch-button-panel switch-button-panel--open\",on:{\"click\":function($event){_vm.is_panel_display = !_vm.is_panel_display}}},[_c('Icon',{staticClass:\"switch-button-icon\",attrs:{\"icon\":\"fluent:navigation-16-filled\",\"width\":\"32px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.bottom\",value:('次のチャンネル'),expression:\"'次のチャンネル'\",modifiers:{\"bottom\":true}}],staticClass:\"switch-button switch-button-down\",attrs:{\"to\":(\"/tv/watch/\" + (_vm.channel_next.channel_id))}},[_c('Icon',{staticClass:\"switch-button-icon\",attrs:{\"icon\":\"fluent:ios-arrow-right-24-filled\",\"width\":\"33px\",\"rotate\":\"1\"}})],1)],1)])]),_c('div',{staticClass:\"watch-panel\",on:{\"mousemove\":function($event){return _vm.controlDisplayTimer($event)},\"touchmove\":function($event){return _vm.controlDisplayTimer($event)},\"click\":function($event){return _vm.controlDisplayTimer($event)}}},[_c('div',{staticClass:\"watch-panel__header\"},[_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-close-button\",on:{\"click\":function($event){_vm.is_panel_display = false}}},[_c('Icon',{staticClass:\"panel-close-button__icon\",attrs:{\"icon\":\"akar-icons:chevron-right\",\"width\":\"25px\"}}),_c('span',{staticClass:\"panel-close-button__text\"},[_vm._v(\"閉じる\")])],1),_c('v-spacer'),_c('div',{staticClass:\"panel-broadcaster\"},[_c('img',{staticClass:\"panel-broadcaster__icon\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + ((_vm.$route.params.channel_id)) + \"/logo\")}}),_c('div',{staticClass:\"panel-broadcaster__number\"},[_vm._v(_vm._s(_vm.channel.channel_number))]),_c('div',{staticClass:\"panel-broadcaster__name\"},[_vm._v(_vm._s(_vm.channel.channel_name))])])],1),_c('div',{staticClass:\"watch-panel__content-container\"},[_c('Program',{staticClass:\"watch-panel__content\",class:{'watch-panel__content--active': _vm.panel_active_tab === 'Program'},attrs:{\"channel\":_vm.channel}}),_c('Channel',{staticClass:\"watch-panel__content\",class:{'watch-panel__content--active': _vm.panel_active_tab === 'Channel'},attrs:{\"channels_list\":_vm.channels_list}}),_c('Comment',{staticClass:\"watch-panel__content\",class:{'watch-panel__content--active': _vm.panel_active_tab === 'Comment'},attrs:{\"channel\":_vm.channel,\"player\":_vm.player}})],1),_c('div',{staticClass:\"watch-panel__navigation\"},[_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-navigation-button\",class:{'panel-navigation-button--active': _vm.panel_active_tab === 'Program'},on:{\"click\":function($event){_vm.panel_active_tab = 'Program'}}},[_c('Icon',{staticClass:\"panel-navigation-button__icon\",attrs:{\"icon\":\"fa-solid:info-circle\",\"width\":\"33px\"}}),_c('span',{staticClass:\"panel-navigation-button__text\"},[_vm._v(\"番組情報\")])],1),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-navigation-button\",class:{'panel-navigation-button--active': _vm.panel_active_tab === 'Channel'},on:{\"click\":function($event){_vm.panel_active_tab = 'Channel'}}},[_c('Icon',{staticClass:\"panel-navigation-button__icon\",attrs:{\"icon\":\"fa-solid:broadcast-tower\",\"width\":\"34px\"}}),_c('span',{staticClass:\"panel-navigation-button__text\"},[_vm._v(\"チャンネル\")])],1),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-navigation-button\",class:{'panel-navigation-button--active': _vm.panel_active_tab === 'Comment'},on:{\"click\":function($event){_vm.panel_active_tab = 'Comment'}}},[_c('Icon',{staticClass:\"panel-navigation-button__icon\",attrs:{\"icon\":\"bi:chat-left-text-fill\",\"width\":\"29px\"}}),_c('span',{staticClass:\"panel-navigation-button__text\"},[_vm._v(\"コメント\")])],1),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-navigation-button\",class:{'panel-navigation-button--active': _vm.panel_active_tab === 'Twitter'},on:{\"click\":function($event){_vm.panel_active_tab = 'Twitter'}}},[_c('Icon',{staticClass:\"panel-navigation-button__icon\",attrs:{\"icon\":\"fa-brands:twitter\",\"width\":\"34px\"}}),_c('span',{staticClass:\"panel-navigation-button__text\"},[_vm._v(\"Twitter\")])],1)])])]),_c('v-dialog',{attrs:{\"max-width\":\"980\",\"transition\":\"slide-y-transition\"},model:{value:(_vm.shortcut_key_modal),callback:function ($$v) {_vm.shortcut_key_modal=$$v},expression:\"shortcut_key_modal\"}},[_c('v-card',[_c('v-card-title',{staticClass:\"px-5 pt-4 pb-3 d-flex align-center font-weight-bold\"},[_c('Icon',{attrs:{\"icon\":\"fluent:keyboard-20-filled\",\"height\":\"28px\"}}),_c('span',{staticClass:\"ml-3\"},[_vm._v(\"キーボードショートカット\")])],1),_c('div',{staticClass:\"px-5 pb-4\"},[_c('v-row',_vm._l((_vm.shortcut_key_list),function(shortcut_key_column,shortcut_key_column_name){return _c('v-col',{key:shortcut_key_column_name,attrs:{\"cols\":\"6\"}},_vm._l((shortcut_key_column),function(shortcut_keys){return _c('div',{key:shortcut_keys.name,staticClass:\"mt-3\"},[_c('div',{staticClass:\"text-subtitle-1 d-flex align-center font-weight-bold\"},[_c('Icon',{attrs:{\"icon\":shortcut_keys.icon,\"height\":shortcut_keys.icon_height}}),_c('span',{staticClass:\"ml-2\"},[_vm._v(_vm._s(shortcut_keys.name))])],1),_vm._l((shortcut_keys.shortcuts),function(shortcut){return _c('div',{key:shortcut.name,staticClass:\"mt-3\"},[_c('div',{staticClass:\"text-subtitle-2 mt-2 d-flex align-center font-weight-medium\"},[_c('span',{staticClass:\"mr-2\",domProps:{\"innerHTML\":_vm._s(shortcut.name)}}),_c('div',{staticClass:\"ml-auto d-flex align-center flex-shrink-0\"},_vm._l((shortcut.keys),function(key,index){return _c('div',{key:key.name,staticClass:\"ml-auto d-flex align-center\"},[(key.icon === true)?_c('Icon',{staticClass:\"shortcut-key\",attrs:{\"icon\":key.name,\"height\":\"18px\"}}):_vm._e(),(key.icon === false)?_c('span',{staticClass:\"shortcut-key\"},[_vm._v(_vm._s(key.name))]):_vm._e(),(index < (shortcut.keys.length - 1))?_c('span',{staticClass:\"shortcut-key-plus\"},[_vm._v(\"+\")]):_vm._e()],1)}),0)])])})],2)}),0)}),1)],1),_c('v-divider'),_c('v-card-actions',{staticClass:\"px-5 py-3\"},[_c('v-spacer'),_c('v-btn',{attrs:{\"color\":\"background lighten-2 px-3\",\"elevation\":\"0\"},on:{\"click\":function($event){_vm.shortcut_key_modal = false}}},[_vm._v(\"閉じる\")])],1)],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n// 番組情報を表すインターフェイス\nexport interface IProgram {\n id: string;\n network_id: number;\n service_id: number;\n event_id: number;\n channel_id: string;\n title: string;\n description: string;\n detail: {[key: string]: string};\n start_time: string;\n end_time: string;\n duration: number;\n is_free: boolean;\n genre: {major: string; middle: string}[];\n video_type: string;\n video_codec: string;\n video_resolution: string;\n primary_audio_type: string;\n primary_audio_language: string;\n primary_audio_sampling_rate: string;\n secondary_audio_type: string | null;\n secondary_audio_language: string | null;\n secondary_audio_sampling_rate: string | null;\n}\n\n// 番組情報を表すインターフェイスのデフォルト値\nexport const IProgramDefault: IProgram = {\n id: 'NID0-SID0',\n service_id: 0,\n network_id: 0,\n event_id: 0,\n channel_id: 'gr000',\n title: '取得中…',\n description: '取得中…',\n detail: {},\n start_time: '2000-01-01T00:00:00+09:00',\n end_time: '2000-01-01T00:00:00+09:00',\n duration: 0,\n is_free: true,\n genre: [],\n video_type: '映像1080i(1125i)、アスペクト比16:9 パンベクトルなし',\n video_codec: 'mpeg2',\n video_resolution: '1080i',\n primary_audio_type: '2/0モード(ステレオ)',\n primary_audio_language: '日本語',\n primary_audio_sampling_rate: '48kHz',\n secondary_audio_type: null,\n secondary_audio_language: null,\n secondary_audio_sampling_rate: null,\n}\n\n// チャンネル情報を表すインターフェイス\nexport interface IChannel {\n id: string;\n network_id: number;\n service_id: number;\n transport_stream_id: number | null;\n remocon_id: number | null;\n channel_id: string;\n channel_number: string;\n channel_name: string;\n channel_type: string;\n channel_force: number | null;\n channel_comment: number | null;\n is_subchannel: boolean;\n is_radiochannel: boolean;\n is_display: boolean;\n viewers: number;\n program_present: IProgram;\n program_following: IProgram;\n}\n\n// チャンネル情報を表すインターフェイスのデフォルト値\nexport const IChannelDefault: IChannel = {\n id: 'NID0-SID0',\n service_id: 0,\n network_id: 0,\n transport_stream_id: null,\n remocon_id: null,\n channel_id: 'gr000',\n channel_number: '---',\n channel_name: '取得中…',\n channel_type: 'GR',\n channel_force: null,\n channel_comment: null,\n is_subchannel: false,\n is_radiochannel: false,\n is_display: true,\n viewers: 0,\n program_present: IProgramDefault,\n program_following: IProgramDefault,\n}\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"channels-container channels-container--watch\"},[_c('v-tabs-fix',{staticClass:\"channels-tab\",attrs:{\"centered\":\"\",\"show-arrows\":\"\"},model:{value:(_vm.tab),callback:function ($$v) {_vm.tab=$$v},expression:\"tab\"}},_vm._l((Array.from(_vm.channels_list)),function(ref){\nvar channels_type = ref[0];\nreturn _c('v-tab',{key:channels_type,staticClass:\"channels-tab__item\"},[_vm._v(\" \"+_vm._s(channels_type)+\" \")])}),1),_c('div',{staticClass:\"channels-list-container\"},[_c('v-tabs-items-fix',{staticClass:\"channels-list\",model:{value:(_vm.tab),callback:function ($$v) {_vm.tab=$$v},expression:\"tab\"}},_vm._l((Array.from(_vm.channels_list)),function(ref){\nvar channels_type = ref[0];\nvar channels = ref[1];\nreturn _c('v-tab-item-fix',{key:channels_type,staticClass:\"channels\"},_vm._l((channels),function(channel){return _c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],key:channel.id,staticClass:\"channel\",attrs:{\"to\":(\"/tv/watch/\" + (channel.channel_id))}},[_c('div',{staticClass:\"channel__broadcaster\"},[_c('img',{staticClass:\"channel__broadcaster-icon\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + (channel.channel_id) + \"/logo\")}}),_c('div',{staticClass:\"channel__broadcaster-content\"},[_c('span',{staticClass:\"channel__broadcaster-name\"},[_vm._v(\"Ch: \"+_vm._s(channel.channel_number)+\" \"+_vm._s(channel.channel_name))]),_c('div',{staticClass:\"channel__broadcaster-force\",class:(\"channel__broadcaster-force--\" + (_vm.TVUtils.getChannelForceType(channel.channel_force)))},[_c('Icon',{attrs:{\"icon\":\"fa-solid:fire-alt\",\"height\":\"11px\"}}),_c('span',{staticClass:\"ml-1\"},[_vm._v(_vm._s(_vm.TVUtils.getAttribute(channel, 'channel_force', '-')))])],1)])]),_c('div',{staticClass:\"channel__program-present\"},[_c('span',{staticClass:\"channel__program-present-title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_present, 'title'))}}),_c('span',{staticClass:\"channel__program-present-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(channel.program_present)))])]),_c('div',{staticClass:\"channel__program-following\"},[_c('div',{staticClass:\"channel__program-following-title\"},[_c('span',{staticClass:\"channel__program-following-title-decorate\"},[_vm._v(\"NEXT\")]),_c('Icon',{staticClass:\"channel__program-following-title-icon\",attrs:{\"icon\":\"fluent:fast-forward-20-filled\",\"width\":\"16px\"}}),_c('span',{staticClass:\"channel__program-following-title-text\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_following, 'title'))}})],1),_c('span',{staticClass:\"channel__program-following-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(channel.program_following)))])]),_c('div',{staticClass:\"channel__progressbar\"},[_c('div',{staticClass:\"channel__progressbar-progress\",style:((\"width:\" + (_vm.TVUtils.getProgramProgress(channel.program_present)) + \"%;\"))})])])}),1)}),1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue, { PropType } from 'vue';\n\nimport { IChannel } from '@/interface';\nimport Utils, { TVUtils } from '@/utils';\n\nexport default Vue.extend({\n name: 'Channel',\n props: {\n // チャンネル情報リスト\n channels_list: {\n type: Map as PropType>,\n required: true,\n }\n },\n data() {\n return {\n\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n TVUtils: TVUtils,\n\n // タブの状態管理\n tab: null,\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Channel.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Channel.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Channel.vue?vue&type=template&id=691b389f&scoped=true&\"\nimport script from \"./Channel.vue?vue&type=script&lang=ts&\"\nexport * from \"./Channel.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Channel.vue?vue&type=style&index=0&lang=scss&\"\nimport style1 from \"./Channel.vue?vue&type=style&index=1&id=691b389f&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"691b389f\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VTab } from 'vuetify/lib/components/VTabs';\ninstallComponents(component, {VTab})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"comment-container\"},[_c('section',{staticClass:\"comment-header\"},[_c('h2',{staticClass:\"comment-header__title\"},[_c('Icon',{staticClass:\"comment-header__title-icon\",attrs:{\"icon\":\"bi:chat-left-text-fill\",\"height\":\"18.5px\"}}),_c('span',{staticClass:\"comment-header__title-text\"},[_vm._v(\"コメント\")])],1),_c('button',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"comment-header__button ml-auto\"},[_c('Icon',{attrs:{\"icon\":\"heroicons-solid:filter\",\"height\":\"11px\"}}),_c('span',{staticClass:\"ml-1\"},[_vm._v(\"コメントフィルター\")])],1)]),_c('DynamicScroller',{staticClass:\"comment-list\",attrs:{\"direction\":'vertical',\"items\":_vm.comment_list,\"min-item-size\":34},scopedSlots:_vm._u([{key:\"default\",fn:function(ref){\nvar item = ref.item;\nvar active = ref.active;\nreturn [_c('DynamicScrollerItem',{attrs:{\"item\":item,\"active\":active,\"size-dependencies\":[item.text]}},[_c('div',{staticClass:\"comment\"},[_c('span',{staticClass:\"comment__text\"},[_vm._v(_vm._s(item.text))]),_c('span',{staticClass:\"comment__time\"},[_vm._v(_vm._s(item.time))])])])]}}])}),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"comment-scroll-button elevation-5\",class:{'comment-scroll-button--display': _vm.is_manual_scroll},on:{\"click\":function($event){_vm.is_manual_scroll = false; _vm.scrollCommentList(true);}}},[_c('Icon',{attrs:{\"icon\":\"fluent:arrow-down-12-filled\",\"height\":\"29px\"}})],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { AxiosResponse } from 'axios';\nimport dayjs from 'dayjs';\nimport Vue, { PropType } from 'vue';\n\nimport { IChannel } from '@/interface';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'Comment',\n props: {\n // チャンネル情報\n channel: {\n type: Object as PropType,\n required: true,\n },\n // プレイヤーのインスタンス\n player: {\n type: null as PropType, // 代入当初は null になるため苦肉の策\n required: true,\n }\n },\n data() {\n return {\n\n // 手動スクロール状態かどうか\n is_manual_scroll: false,\n\n // 自動スクロール中かどうか\n // 自動スクロール中の場合、scroll イベントが発火しても無視する\n is_auto_scrolling: false,\n\n // コメントリストの配列\n comment_list: [] as {[key: string]: number | string}[],\n\n // コメントリストの要素\n comment_list_element: null as HTMLElement | null,\n\n // 視聴セッションの WebSocket のインスタンス\n watch_session: null as WebSocket | null,\n\n // コメントセッションの WebSocket のインスタンス\n comment_session: null as WebSocket | null,\n\n // 座席維持用のタイマーのインターバル ID\n keep_seat_interval_id: 0,\n\n // ResizeObserver のインスタンス\n resize_observer: null as ResizeObserver | null,\n\n // ResizeObserver の監視対象の要素\n resize_observer_element: null as HTMLElement | null,\n }\n },\n // 終了前に実行\n beforeDestroy() {\n\n // destroy() を実行\n this.destroy();\n\n // ResizeObserver を終了\n if (this.resize_observer !== null) {\n this.resize_observer.unobserve(this.resize_observer_element);\n }\n },\n watch: {\n\n // チャンネル情報が変更されたとき\n // created() だとチャンネル情報の取得前に実行してしまう\n // this が変わってしまうのでアロー関数は使えない\n async channel(new_channel: IChannel, old_channel: IChannel) {\n\n // 前のチャンネル情報と次のチャンネル情報で channel_id が変わってたら\n if (new_channel.channel_id !== old_channel.channel_id) {\n\n // 0.5秒だけ待ってから\n // 連続してチャンネルを切り替えた時などに毎回コメントサーバーに接続しないように猶予を設ける\n // ただし、最初 (channel_id が gr000 の初期値になっている) だけは待たずに実行する\n if (old_channel.channel_id !== 'gr000') {\n await new Promise(resolve => setTimeout(resolve, 0.5 * 1000));\n // 0.5 秒待った結果、channel_id が既に変更されているので終了\n if (this.channel.channel_id !== new_channel.channel_id) {\n return;\n }\n }\n\n // 前の視聴セッション・コメントセッションを破棄\n this.destroy();\n\n // コメントリストの要素を取得\n if (this.comment_list_element === null) {\n this.comment_list_element = this.$el.querySelector('.comment-list');\n }\n\n // 現在コメントリストがユーザーイベントでスクロールされているかどうか\n let is_user_scrolling = false;\n\n // mousedown → mouseup 中: スクロールバーをマウスでドラッグ\n // 残念ながらスクロールバーのドラッグ中は mousemove のイベントが発火しないため、直接 is_user_scrolling を設定する\n this.comment_list_element.onmousedown = (event: MouseEvent) => {\n // コメントリストの要素の左上を起点としたカーソルのX座標を求める\n const x = event.clientX - this.comment_list_element.getBoundingClientRect().left;\n // 座標が clientWidth 以上であれば、スクロールバー上で mousedown されたものとする\n if (x > this.comment_list_element.clientWidth) is_user_scrolling = true;\n }\n this.comment_list_element.onmouseup = (event: MouseEvent) => {\n // コメントリストの要素の左上を起点としたカーソルのX座標を求める\n const x = event.clientX - this.comment_list_element.getBoundingClientRect().left;\n // 座標が clientWidth 以上であれば、スクロールバー上で mouseup されたものとする\n if (x > this.comment_list_element.clientWidth) is_user_scrolling = false;\n }\n\n // ユーザーによるスクロールイベントで is_user_scrolling を true にする\n // 0.1 秒後に false にする(継続してイベントが発火すれば再び true になる)\n const on_user_scrolling = () => {\n is_user_scrolling = true;\n window.setTimeout(() => is_user_scrolling = false, 100);\n }\n\n // 現在コメントリストがドラッグされているかどうか\n let is_dragging = false;\n // touchstart → touchend 中: スクロールバーをタップでドラッグ\n this.comment_list_element.ontouchstart = () => is_dragging = true;\n this.comment_list_element.ontouchend = () => is_dragging = false;\n // touchmove + is_dragging 中: コメントリストをタップでドラッグしてスクロール\n this.comment_list_element.ontouchmove = () => is_dragging === true ? on_user_scrolling(): '';\n\n // wheel 中: マウスホイールの回転\n this.comment_list_element.onwheel = on_user_scrolling;\n\n // コメントリストがスクロールされた際、自動スクロール中でない&ユーザーイベントで操作されていれば、手動スクロールモードに設定\n // 手動スクロールモードでは自動スクロールを行わず、ユーザーがコメントリストをスクロールできるようにする\n this.comment_list_element.onscroll = async () => {\n\n // scroll イベントは自動スクロールでも発火してしまうので、ユーザーイベントによるスクロールかを確認しないといけない\n // 自動スクロール中かどうかは is_auto_scrolling が true のときで判定できるはずだが、\n // コメントが多くなると is_auto_scrolling が false なのに scroll イベントが遅れて発火してしまうことがある\n if (this.is_auto_scrolling === false && is_user_scrolling === true) {\n\n // 手動スクロールを有効化\n this.is_manual_scroll = true;\n\n // イベント発火時点では scrollTop の値が完全に下にスクロールされていない場合があるため、0.1秒だけ待つ\n await new Promise(resolve => setTimeout(resolve, 100));\n\n // 一番下までスクロールしていたら自動スクロールに戻す\n if ((this.comment_list_element.scrollTop + this.comment_list_element.offsetHeight) >\n (this.comment_list_element.scrollHeight - 10)) { // 一番下から 10px 以内\n this.is_manual_scroll = false; // 手動スクロールを無効化\n }\n }\n }\n\n // 視聴セッションを初期化\n const comment_session_info = await this.initWatchSession();\n\n // コメントセッションを初期化\n await this.initCommentSession(comment_session_info);\n\n // リサイズ時のイベントを初期化\n await this.initReserveObserver();\n }\n }\n },\n methods: {\n\n // 視聴セッションを初期化\n async initWatchSession(): Promise<{[key: string]: string | null}> {\n\n // セッション情報を取得\n let watch_session_info: AxiosResponse;\n try {\n watch_session_info = await Vue.axios.get(`${Utils.api_base_url}/channels/${this.channel.channel_id}/jikkyo`);\n } catch (error) {\n throw new Error(error); // エラー内容を表示\n }\n\n // セッション情報を取得できなかった\n if (watch_session_info.data.is_success === false) {\n throw new Error(watch_session_info.data.detail); // エラー内容を表示\n }\n\n // イベント内で値を返すため、Promise で包む\n return new Promise((resolve) => {\n\n // 視聴セッション WebSocket を開く\n this.watch_session = new WebSocket(watch_session_info.data.audience_token);\n\n // 視聴セッション WebSocket を開いたとき\n this.watch_session.addEventListener('open', () => {\n\n // 視聴セッションをリクエスト\n // 某所で限定公開されている公式ドキュメントいわく、stream フィールドは Optional らしい\n // サーバー負荷軽減のため、映像が不要な場合は必ず省略してくださいとのこと\n this.watch_session.send(JSON.stringify({\n 'type': 'startWatching',\n 'data': {\n 'reconnect': false,\n },\n }));\n });\n\n // 視聴セッション WebSocket からメッセージを受信したとき\n this.watch_session.addEventListener('message', async (event) => {\n\n // 受信したメッセージ\n const message = JSON.parse(event.data);\n\n switch (message.type) {\n\n // 部屋情報(実際には統合されていて、全てアリーナ扱いになっている)\n case 'room': {\n\n // コメントサーバーへの接続情報の入ったオブジェクトを返す\n // デバッグ用で実際には使わないものもある\n return resolve({\n // コメントサーバーへの接続情報\n 'thread_id': message.data.threadId,\n 'your_post_key': (message.data.yourPostKey ? message.data.yourPostKey : null),\n 'message_server': message.data.messageServer.uri,\n });\n }\n\n // 座席情報\n case 'seat': {\n\n // keepIntervalSec の秒数ごとに keepSeat を送信して座席を維持する\n this.keep_seat_interval_id = window.setInterval(() => {\n // セッションがまだ開いていれば\n if (this.watch_session.readyState === 1) {\n // 座席を維持\n this.watch_session.send(JSON.stringify({\n 'type': 'keepSeat',\n }));\n // setInterval を解除\n } else {\n window.clearInterval(this.keep_seat_interval_id);\n }\n }, message.data.keepIntervalSec * 1000);\n break;\n }\n\n // ping-pong\n case 'ping': {\n\n // pong を返してセッションを維持する\n // 送り返さなかった場合勝手にセッションが閉じられてしまう\n this.watch_session.send(JSON.stringify({\n 'type': 'pong',\n }));\n break;\n }\n\n // エラー情報\n case 'error': {\n\n // エラー情報\n let error:string;\n switch (message.data.code) {\n\n case 'CONNECT_ERROR':\n error = 'コメントサーバーに接続できません。';\n break;\n case 'CONTENT_NOT_READY':\n error = 'ニコニコ実況が配信できない状態です。';\n break;\n case 'NO_THREAD_AVAILABLE':\n error = 'コメントスレッドを取得できません。';\n break;\n case 'NO_ROOM_AVAILABLE':\n error = 'コメント部屋を取得できません。';\n break;\n case 'NO_PERMISSION':\n error = 'API にアクセスする権限がありません。';\n break;\n case 'NOT_ON_AIR':\n error = 'ニコニコ実況が放送中ではありません。';\n break;\n case 'BROADCAST_NOT_FOUND':\n error = 'ニコニコ実況の配信情報を取得できません。';\n break;\n case 'INTERNAL_SERVERERROR':\n error = 'ニコニコ実況でサーバーエラーが発生しています。';\n break;\n default:\n error = `ニコニコ実況でエラーが発生しています。(${message.data.code})`;\n break;\n }\n\n // エラー情報を表示\n console.log(`error occurred. code: ${message.data.code}`);\n if (this.player.danmaku.showing) {\n this.player.notice(error);\n }\n\n break;\n }\n\n // 再接続を求められた\n case 'reconnect': {\n\n // 前の視聴セッション・コメントセッションを破棄\n this.destroy();\n\n // waitTimeSec に記載の秒数だけ待ってから再接続する\n await new Promise(resolve => setTimeout(resolve, message.data.waitTimeSec * 1000));\n if (this.player.danmaku.showing) {\n this.player.notice('ニコニコ実況に再接続しています…');\n }\n\n // 視聴セッションを再初期化\n // ドキュメントには reconnect で送られてくる audienceToken で再接続しろと書いてあるんだけど、\n // 確実性的な面で実装が面倒なので当面このままにしておく\n const comment_session_info = await this.initWatchSession();\n\n // コメントセッションを再初期化\n await this.initCommentSession(comment_session_info);\n\n break;\n }\n\n // 視聴セッションが閉じられた(4時のリセットなど)\n case 'disconnect': {\n\n // 実際に接続が閉じられる前に disconnect イベントが送られてきたので、onclose イベントを削除する\n // onclose イベントが発火するのは不意に切断されたときなど最終手段\n if (this.watch_session) this.watch_session.onclose = null;\n\n // 接続切断の理由\n let disconnect_reason;\n switch (message.data.reason) {\n\n case 'TAKEOVER':\n disconnect_reason = 'ニコニコ実況の番組から追い出されました。';\n break;\n case 'NO_PERMISSION':\n disconnect_reason = 'ニコニコ実況の番組の座席を取得できませんでした。';\n break;\n case 'END_PROGRAM':\n disconnect_reason = 'ニコニコ実況がリセットされたか、コミュニティの番組が終了しました。';\n break;\n case 'PING_TIMEOUT':\n disconnect_reason = 'コメントサーバーとの接続生存確認に失敗しました。';\n break;\n case 'TOO_MANY_CONNECTIONS':\n disconnect_reason = 'ニコニコ実況の同一ユーザからの接続数上限を越えています。';\n break;\n case 'TOO_MANY_WATCHINGS':\n disconnect_reason = 'ニコニコ実況の同一ユーザからの視聴番組数上限を越えています。';\n break;\n case 'CROWDED':\n disconnect_reason = 'ニコニコ実況の番組が満席です。';\n break;\n case 'MAINTENANCE_IN':\n disconnect_reason = 'ニコニコ実況はメンテナンス中です。';\n break;\n case 'SERVICE_TEMPORARILY_UNAVAILABLE':\n disconnect_reason = 'ニコニコ実況で一時的にサーバーエラーが発生しています。';\n break;\n default:\n disconnect_reason = `ニコニコ実況との接続が切断されました。(${message.data.reason})`;\n break;\n }\n\n // 接続切断の理由を表示\n console.log(`disconnected. reason: ${message.data.reason}`);\n if (this.player.danmaku.showing) {\n this.player.notice(disconnect_reason);\n }\n\n // 前の視聴セッション・コメントセッションを破棄\n this.destroy();\n\n // 5 秒ほど待ってから再接続する\n await new Promise(resolve => setTimeout(resolve, 5 * 1000));\n if (this.player.danmaku.showing) {\n this.player.notice('ニコニコ実況に再接続しています…');\n }\n\n // 視聴セッションを再初期化\n const comment_session_info = await this.initWatchSession();\n\n // コメントセッションを再初期化\n await this.initCommentSession(comment_session_info);\n\n break;\n }\n }\n });\n\n\n // 視聴セッションの接続が閉じられたとき(ネットワークが切断された場合など)\n // イベントを無効化しやすいように敢えて onclose で実装する\n this.watch_session.onclose = async (event) => {\n\n // 接続切断の理由を表示\n console.log(`disconnected. code: ${event.code}`);\n if (this.player.danmaku.showing) {\n this.player.notice(`ニコニコ実況との接続が切断されました。(code: ${event.code})`);\n }\n\n // 前の視聴セッション・コメントセッションを破棄\n this.destroy();\n\n // 10 秒ほど待ってから再接続する\n // ニコ生側から切断された場合と異なりネットワークが切断された可能性が高いので、間を多めに取る\n await new Promise(resolve => setTimeout(resolve, 10 * 1000));\n if (this.player.danmaku.showing) {\n this.player.notice('ニコニコ実況に再接続しています…');\n }\n\n // 視聴セッションを再初期化\n const comment_session_info = await this.initWatchSession();\n\n // コメントセッションを再初期化\n await this.initCommentSession(comment_session_info);\n };\n });\n },\n\n // コメントセッションを初期化\n async initCommentSession(comment_session_info: {[key: string]: string | null}) {\n\n // タブが非表示状態のときにコメントを格納する配列\n // タブが表示状態になったらコメントリストにのみ表示する(遅れているのでプレイヤーには表示しない)\n let comment_list_buffer = [];\n\n // 最初に送信されてくるコメントを受信し終えたかどうかのフラグ\n let is_received_initial_comment = false;\n\n // コメントセッション WebSocket を開く\n this.comment_session = new WebSocket(comment_session_info.message_server);\n\n // コメントセッション WebSocket を開いたとき\n this.comment_session.addEventListener('open', () => {\n\n // コメント送信をリクエスト\n // このコマンドを送らないとコメントが送信されてこない\n this.comment_session.send(JSON.stringify([\n { 'ping': {'content': 'rs:0'} },\n { 'ping': {'content': 'ps:0'} },\n {\n 'thread': {\n 'version': '20061206', // 設定必須\n 'thread': comment_session_info.thread_id, // スレッド ID\n 'threadkey': comment_session_info.your_post_key, // スレッドキー\n 'user_id': '', // ユーザー ID\n 'res_from': -50, // 最初にコメントを 50 個送信する\n }\n },\n { 'ping': {'content': 'pf:0'} },\n { 'ping': {'content': 'rf:0'} },\n ]));\n });\n\n // 視聴セッション WebSocket からメッセージを受信したとき\n this.comment_session.addEventListener('message', async (event_raw) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n\n // thread メッセージのみ\n if (event.thread !== undefined) {\n\n // 接続成功のコールバックを DPlayer に通知\n if (event.thread.resultcode === 0) {\n\n // 接続失敗のコールバックを DPlayer に通知\n } else {\n const message = 'コメントサーバーに接続できませんでした。';\n console.error('Error: ' + message);\n }\n }\n\n // ping メッセージのみ\n // rf:0 が送られてきたら初回コメントの受信は完了\n if (event.ping !== undefined && event.ping.content === 'rf:0') {\n\n // フラグを立てる\n is_received_initial_comment = true;\n\n // コメントリストを一番下にスクロール\n // 初回コメントは量が多いので、一括でスクロールする\n this.scrollCommentList();\n }\n\n // コメントを取得\n const comment = event.chat;\n\n // コメントがない or 広告用など特殊な場合は弾く\n if (comment === undefined ||\n comment.content === undefined ||\n comment.content.match(/\\/[a-z]+ /)) {\n return;\n }\n\n // 自分のコメントも表示しない\n if (comment.yourpost && comment.yourpost === 1) {\n return;\n }\n\n // 色・位置\n let color = '#FFEAEA'; // 色のデフォルト\n let position = 'right'; // 位置のデフォルト\n if (comment.mail !== undefined && comment.mail !== null) {\n // コマンドをスペースで区切って配列にしたもの\n const command = comment.mail.replace('184', '').split(' ');\n for (const item of command) { // コマンドごとに\n if (this.getCommentColor(item) !== null) {\n color = this.getCommentColor(item);\n }\n if (this.getCommentPosition(item) !== null) {\n position = this.getCommentPosition(item);\n }\n }\n }\n\n // 配信に発生する遅延分待ってから\n // 現状だいたい1秒くらいなので暫定で決め打ち\n // 最初に受信したコメントはリアルタイムなコメントではないため、遅らせないように\n if (is_received_initial_comment) {\n const comment_delay_time = Utils.getSettingsItem('comment_delay_time');\n await new Promise(resolve => setTimeout(resolve, comment_delay_time * 1000));\n }\n\n // コメントリストのコメントが 500 件を超えたら古いものから順に削除する\n // 仮想スクロールとはいえ、さすがに 500 件を超えると重くなりそう\n if (this.comment_list.length > 500) {\n this.comment_list.shift();\n }\n\n // コメントリストへ追加するオブジェクト\n // コメント投稿時刻はフォーマットしてから\n const comment_dict = {\n id: comment.no,\n text: comment.content,\n time: dayjs(comment.date * 1000).format('HH:mm:ss'),\n };\n\n // タブが非表示状態のときは、バッファにコメントを追加するだけで終了する\n // ここで追加すると、タブが表示状態になったときに一斉に描画されて大変なことになる\n if (document.visibilityState === 'hidden') {\n comment_list_buffer.push(comment_dict);\n return;\n }\n\n // コメントリストに追加\n this.comment_list.push(comment_dict);\n\n // // コメントリストを一番下にスクロール\n // 最初に受信したコメントは上の処理で一括でスクロールさせる\n if (is_received_initial_comment) {\n this.scrollCommentList();\n }\n\n // コメント描画 (再生時のみ)\n // 最初に受信したコメントはリアルタイムなコメントではないため、描画しないように\n if (is_received_initial_comment) {\n if (!this.player.video.paused){\n this.player.danmaku.draw({\n text: comment.content,\n color: color,\n type: position,\n });\n }\n }\n });\n\n // タブの表示/非表示の状態が切り替わったときのイベント\n // 表示状態になったときにバッファにあるコメントをコメントリストに表示する\n document.onvisibilitychange = () => {\n if (document.visibilityState === 'visible') {\n this.comment_list.push(...comment_list_buffer); // コメントリストに一括で追加\n comment_list_buffer = []; // バッファをクリア\n this.scrollCommentList(); // コメントリストをスクロール\n }\n };\n },\n\n // リサイズ時のイベントを初期化\n async initReserveObserver() {\n\n // 監視対象の要素\n this.resize_observer_element = document.querySelector('.watch-player');\n\n // タイムアウト ID\n // 一時的に無効にした transition を有効化する際に利用する\n let animation_timeout_id = null;\n\n // プレイヤーの要素がリサイズされた際に発火するイベント\n const on_resize = () => {\n\n // 映像の要素\n const video_element = document.querySelector('.dplayer-video-wrap-aspect');\n\n // コメント描画領域の要素\n const comment_area_element = (document.querySelector('.dplayer-danmaku') as HTMLElement);\n\n // プレイヤー全体と映像の高さの差(レターボックス)から、コメント描画領域の高さを狭める必要があるかを判定する\n // 2で割っているのは単体の差を測るため\n if (this.resize_observer_element === null || this.resize_observer_element.clientHeight === null) return;\n if (video_element === null || video_element.clientHeight === null) return;\n const letter_box_height = (this.resize_observer_element.clientHeight - video_element.clientHeight) / 2;\n\n // 70px or 54px (高さが 450px 以下) 以下ならヘッダー(番組名などの表示)と被るので対応する\n const threshold = window.matchMedia('(max-height: 450px)').matches ? 50 : 66;\n if (letter_box_height < threshold) {\n\n // コメント描画領域に必要な上下マージン\n const comment_area_vertical_margin = (threshold - letter_box_height) * 2;\n\n // 狭めるコメント描画領域の幅\n // 映像の要素の幅をそのまま利用する\n const comment_area_width = video_element.clientWidth;\n\n // 狭めるコメント描画領域の高さ\n const comment_area_height = video_element.clientHeight - comment_area_vertical_margin;\n\n // 狭めるコメント描画領域のアスペクト比を求める\n // https://tech.arc-one.jp/asepct-ratio/\n const gcd = (x: number, y: number) => { // 最大公約数を求める関数\n if(y === 0) return x;\n return gcd(y, x % y);\n }\n // 幅と高さの最大公約数を求める\n const gcd_result = gcd(comment_area_width, comment_area_height);\n // 幅と高さをそれぞれ最大公約数で割ってアスペクト比を算出\n const comment_area_height_aspect = `${comment_area_width / gcd_result} / ${comment_area_height / gcd_result}`;\n\n // 一時的に transition を無効化する\n // アスペクト比の設定は連続して行われるが、その際に transition が適用されるとワンテンポ遅れたアニメーションになってしまう\n comment_area_element.style.transition = 'none';\n\n // コメント描画領域に算出したアスペクト比を設定する\n comment_area_element.style.setProperty('--comment-area-aspect-ratio', comment_area_height_aspect);\n\n // コメント描画領域に必要な上下マージンを設定する\n comment_area_element.style.setProperty('--comment-area-vertical-margin', `${comment_area_vertical_margin}px`);\n\n // 以前セットされた setTimeout() を止める\n window.clearTimeout(animation_timeout_id);\n\n // 0.2秒後に実行する\n // 0.2秒より前にもう一度リサイズイベントが来た場合はタイマーがクリアされるため実行されない\n window.setTimeout(() => {\n\n // 再び transition を有効化する\n comment_area_element.style.transition = '';\n\n }, 0.2 * 1000);\n\n } else {\n\n // コメント描画領域に設定したアスペクト比・上下マージンを削除する\n comment_area_element.style.removeProperty('--comment-area-aspect-ratio');\n comment_area_element.style.removeProperty('--comment-area-vertical-margin');\n }\n }\n\n // 要素の監視を開始\n this.resize_observer = new ResizeObserver(on_resize);\n this.resize_observer.observe(this.resize_observer_element);\n },\n\n // コメントリストを一番下までスクロールする\n async scrollCommentList(smooth: boolean = false) {\n\n // 手動スクロールモードの時は実行しない\n if (this.is_manual_scroll === true) return;\n\n // 自動スクロール中のフラグを立てる\n this.is_auto_scrolling = true;\n\n // 0.01 秒待って実行し、念押しで2回実行しないと完全に最下部までスクロールされない…(ブラウザの描画バグ?)\n // this.$nextTick() は効かなかった\n for (let index = 0; index < 3; index++) {\n await new Promise(resolve => setTimeout(resolve, 0.01 * 1000));\n if (smooth === true) { // スムーズスクロール\n this.comment_list_element.scrollTo({top: this.comment_list_element.scrollHeight, left: 0, behavior: 'smooth'});\n } else {\n this.comment_list_element.scrollTo(0, this.comment_list_element.scrollHeight);\n }\n }\n\n // 0.1 秒待つ(重要)\n await new Promise(resolve => setTimeout(resolve, 0.1 * 1000));\n\n // 自動スクロール中のフラグを降ろす\n this.is_auto_scrolling = false;\n },\n\n /**\n * ニコニコの色指定を 16 進数カラーコードに置換する\n * @param {string} color ニコニコの色指定\n * @return {string} 16 進数カラーコード\n */\n getCommentColor(color: string): string {\n const color_table = {\n 'red': '#E54256',\n 'pink': '#FF8080',\n 'orange': '#FFC000',\n 'yellow': '#FFE133',\n 'green': '#64DD17',\n 'cyan': '#39CCFF',\n 'blue': '#0000FF',\n 'purple': '#D500F9',\n 'black': '#1E1310',\n 'white': '#FFEAEA',\n 'white2': '#CCCC99',\n 'niconicowhite': '#CCCC99',\n 'red2': '#CC0033',\n 'truered': '#CC0033',\n 'pink2': '#FF33CC',\n 'orange2': '#FF6600',\n 'passionorange': '#FF6600',\n 'yellow2': '#999900',\n 'madyellow': '#999900',\n 'green2': '#00CC66',\n 'elementalgreen': '#00CC66',\n 'cyan2': '#00CCCC',\n 'blue2': '#3399FF',\n 'marineblue': '#3399FF',\n 'purple2': '#6633CC',\n 'nobleviolet': '#6633CC',\n 'black2': '#666666',\n };\n if (color_table[color] !== undefined) {\n return color_table[color];\n } else {\n return null;\n }\n },\n\n /**\n * ニコニコの位置指定を DPlayer の位置指定に置換する\n * @param {string} position ニコニコの位置指定\n * @return {string} DPlayer の位置指定\n */\n getCommentPosition(position: string): string {\n switch (position) {\n case 'ue':\n return 'top';\n case 'naka':\n return 'right';\n case 'shita':\n return 'bottom';\n default:\n return null;\n }\n },\n\n // 破棄する\n destroy() {\n\n // コメントリストをクリア\n this.comment_list = [];\n\n // タブの表示/非表示の状態が切り替わったときのイベントを削除\n document.onvisibilitychange = null;\n\n // 視聴セッションを閉じる\n if (this.watch_session !== null) {\n this.watch_session.onclose = null; // WebSocket が閉じられた際のイベントを削除\n this.watch_session.close(); // WebSocket を閉じる\n this.watch_session = null; // null に戻す\n }\n\n // コメントセッションを閉じる\n if (this.comment_session !== null) {\n this.comment_session.onclose = null; // WebSocket が閉じられた際のイベントを削除\n this.comment_session.close(); // WebSocket を閉じる\n this.comment_session = null; // null に戻す\n }\n\n // 座席保持用のタイマーをクリア\n window.clearInterval(this.keep_seat_interval_id);\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Comment.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Comment.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Comment.vue?vue&type=template&id=7575b645&scoped=true&\"\nimport script from \"./Comment.vue?vue&type=script&lang=ts&\"\nexport * from \"./Comment.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Comment.vue?vue&type=style&index=0&id=7575b645&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"7575b645\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installDirectives from \"!../../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"program-container\"},[_c('section',{staticClass:\"program-broadcaster\"},[_c('img',{staticClass:\"program-broadcaster__icon\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + ((_vm.$route.params.channel_id)) + \"/logo\")}}),_c('div',{staticClass:\"program-broadcaster__number\"},[_vm._v(\"Ch: \"+_vm._s(_vm.channel.channel_number))]),_c('div',{staticClass:\"program-broadcaster__name\"},[_vm._v(_vm._s(_vm.channel.channel_name))])]),_c('section',{staticClass:\"program-info\"},[_c('h1',{staticClass:\"program-info__title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(_vm.channel.program_present, 'title'))}}),_c('div',{staticClass:\"program-info__time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(_vm.channel.program_present)))]),_c('div',{staticClass:\"program-info__description\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(_vm.channel.program_present, 'description'))}}),_c('div',{staticClass:\"program-info__genre-container\"},_vm._l((_vm.TVUtils.getAttribute(_vm.channel.program_present, 'genre', [])),function(genre,genre_index){return _c('div',{key:genre_index,staticClass:\"program-info__genre\"},[_vm._v(\" \"+_vm._s(genre.major)+\" / \"+_vm._s(genre.middle)+\" \")])}),0),_c('div',{staticClass:\"program-info__next\"},[_c('span',{staticClass:\"program-info__next-decorate\"},[_vm._v(\"NEXT\")]),_c('Icon',{staticClass:\"program-info__next-icon\",attrs:{\"icon\":\"fluent:fast-forward-20-filled\",\"width\":\"16px\"}})],1),_c('span',{staticClass:\"program-info__next-title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(_vm.channel.program_following, 'title'))}}),_c('div',{staticClass:\"program-info__next-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(_vm.channel.program_following)))]),_c('div',{staticClass:\"program-info__status\"},[_c('div',{staticClass:\"program-info__status-force\",class:(\"program-info__status-force--\" + (_vm.TVUtils.getChannelForceType(_vm.channel.channel_force)))},[_c('Icon',{attrs:{\"icon\":\"fa-solid:fire-alt\",\"height\":\"14px\"}}),_c('span',{staticClass:\"ml-2\"},[_vm._v(\"勢い:\")]),_c('span',{staticClass:\"ml-2\"},[_vm._v(_vm._s(_vm.TVUtils.getAttribute(_vm.channel, 'channel_force', '--'))+\" コメ/分\")])],1),_c('div',{staticClass:\"program-info__status-viewers ml-5\"},[_c('Icon',{attrs:{\"icon\":\"fa-solid:eye\",\"height\":\"14px\"}}),_c('span',{staticClass:\"ml-2\"},[_vm._v(\"視聴数:\")]),_c('span',{staticClass:\"ml-1\"},[_vm._v(_vm._s(_vm.channel.viewers))])],1)])]),_c('section',{staticClass:\"program-detail-container\"},_vm._l((_vm.TVUtils.getAttribute(_vm.channel.program_present, 'detail', {})),function(detail_text,detail_heading){return _c('div',{key:detail_heading,staticClass:\"program-detail\"},[_c('h2',{staticClass:\"program-detail__heading\"},[_vm._v(_vm._s(detail_heading))]),_c('div',{staticClass:\"program-detail__text\"},[_vm._v(_vm._s(detail_text))])])}),0)])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue, { PropType } from 'vue';\n\nimport { IChannel } from '@/interface';\nimport Utils, { TVUtils } from '@/utils';\n\nexport default Vue.extend({\n name: 'Program',\n props: {\n // チャンネル情報\n channel: {\n type: Object as PropType,\n required: true,\n }\n },\n data() {\n return {\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n TVUtils: TVUtils,\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Program.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Program.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Program.vue?vue&type=template&id=00e07beb&scoped=true&\"\nimport script from \"./Program.vue?vue&type=script&lang=ts&\"\nexport * from \"./Program.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Program.vue?vue&type=style&index=0&id=00e07beb&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"00e07beb\",\n null\n \n)\n\nexport default component.exports","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { AxiosResponse } from 'axios';\nimport dayjs from 'dayjs';\n// @ts-ignore JavaScript で書かれているので型定義がなく、作ろうとするとややこしくなるので黙殺\nimport DPlayer from 'dplayer';\nimport mpegts from 'mpegts.js';\nimport Vue from 'vue';\n\nimport { IChannel, IChannelDefault } from '@/interface';\nimport Channel from '@/components/TV/Channel.vue';\nimport Comment from '@/components/TV/Comment.vue';\nimport Program from '@/components/TV/Program.vue';\nimport Utils, { TVUtils } from '@/utils';\n\nexport default Vue.extend({\n name: 'Watch',\n components: {\n Channel,\n Comment,\n Program,\n },\n data() {\n return {\n\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n TVUtils: TVUtils,\n\n // 現在時刻\n time: dayjs().format('YYYY/MM/DD HH:mm:ss'),\n\n // 表示されるパネルのタブ\n panel_active_tab: Utils.getSettingsItem('panel_active_tab'),\n\n // 背景の URL\n background_url: '',\n\n // プレイヤーのローディング状態\n // 既定でローディングとする\n is_loading: true,\n\n // プレイヤーの背景を表示するか\n // 既定で表示しない\n is_background_display: false,\n\n // コントロールを表示するか\n // 既定で表示する\n is_control_display: true,\n\n // パネルを表示するか\n // panel_display_state が 'AlwaysDisplay' なら常に表示し、'AlwaysFold' なら常に折りたたむ\n // 'RestorePreviousState' なら is_latest_panel_display の値を使い、前回の状態を復元する\n is_panel_display: (() => {\n switch (Utils.getSettingsItem('panel_display_state')) {\n case 'AlwaysDisplay':\n return true;\n case 'AlwaysFold':\n return false;\n case 'RestorePreviousState':\n return Utils.getSettingsItem('is_latest_panel_display');\n }\n })() as boolean,\n\n // フルスクリーン状態かどうか\n is_fullscreen: false,\n\n // インターバル ID\n // ページ遷移時に setInterval(), setTimeout() の実行を止めるのに使う\n // setInterval(), setTimeout() の返り値を登録する\n interval_ids: [] as number[],\n\n // コントロール表示切り替え用のインターバル ID\n // 混ぜるとダメなので独立させる\n control_interval_id: 0,\n\n // チャンネル ID\n channel_id: this.$route.params.channel_id,\n\n // チャンネル情報\n // IChannelDefault に情報取得が完了するまでの間表示される初期値が定義されている\n channel: IChannelDefault,\n\n // 前のチャンネルのチャンネル情報\n channel_previous: IChannelDefault,\n\n // 次のチャンネルのチャンネル情報\n channel_next: IChannelDefault,\n\n // チャンネル情報リスト\n channels_list: new Map() as Map,\n\n // プレイヤー (DPlayer) のインスタンス\n player: null,\n\n // イベントソースのインスタンス\n eventsource: null as EventSource | null,\n\n // フルスクリーン状態が切り替わったときのハンドラー\n fullscreen_handler: null as () => void | null,\n\n // ショートカットキーのハンドラー\n shortcut_key_handler: null as (event: KeyboardEvent) => void | null,\n\n // ショートカットキーの最終押下時刻のタイムスタンプ\n shortcut_key_pressed_at: Date.now(),\n\n // キーボードショートカットの一覧のモーダルを表示するか\n shortcut_key_modal: false,\n\n // キーボードショートカットの一覧に表示するショートカットキーのリスト\n shortcut_key_list: {\n left_column: [\n {\n name: '全般',\n icon: 'fluent:home-20-filled',\n icon_height: '22px',\n shortcuts: [\n { name: '数字キー・テンキーに対応するリモコン番号 (1~12) のチャンネルに切り替える
(同時に Shift キーを押すと、地デジならBS、BSなら地デジのチャンネルを選局する)', keys: [{name: '1~9, 0, -(=), ^(~)', icon: false}] },\n { name: '前のチャンネルに切り替える', keys: [{name: 'fluent:arrow-up-12-filled', icon: true}] },\n { name: '次のチャンネルに切り替える', keys: [{name: 'fluent:arrow-down-12-filled', icon: true}] },\n { name: 'キーボードショートカットの一覧を表示する', keys: [{name: '/(?)', icon: false}] },\n ]\n },\n {\n name: 'パネル',\n icon: 'fluent:panel-right-20-filled',\n icon_height: '24px',\n shortcuts: [\n { name: 'パネルの表示切り替え', keys: [{name: 'P', icon: false}] },\n { name: '番組情報タブを表示する', keys: [{name: 'K', icon: false}] },\n { name: 'チャンネルタブを表示する', keys: [{name: 'L', icon: false}] },\n { name: 'コメントタブを表示する', keys: [{name: ';(+)', icon: false}] },\n { name: 'Twitter タブを表示する', keys: [{name: ':(*)', icon: false}] },\n ]\n }\n ],\n right_column: [\n {\n name: 'プレイヤー',\n icon: 'fluent:play-20-filled',\n icon_height: '20px',\n shortcuts: [\n { name: '再生 / 一時停止の切り替え', keys: [{name: 'Space', icon: false}] },\n { name: '停止して0.25秒早戻し', keys: [{name: 'fluent:arrow-left-12-filled', icon: true}] },\n { name: '停止して0.25秒早送り', keys: [{name: 'fluent:arrow-right-12-filled', icon: true}] },\n { name: 'フルスクリーンの切り替え', keys: [{name: 'F', icon: false}] },\n { name: 'ライブストリームの同期', keys: [{name: 'W', icon: false}] },\n { name: 'Picture-in-Picture の表示切り替え', keys: [{name: 'E', icon: false}] },\n { name: '字幕の表示切り替え', keys: [{name: 'S', icon: false}] },\n { name: 'コメントの表示切り替え', keys: [{name: 'D', icon: false}] },\n { name: 'コメント入力フォームにフォーカスする', keys: [{name: 'M', icon: false}] },\n ]\n }\n ]\n }\n }\n },\n // 開始時に実行\n created() {\n\n // init() を実行\n this.init();\n },\n // 終了前に実行\n beforeDestroy() {\n\n // destroy() を実行\n // 別のページへ遷移するため、DPlayer のインスタンスを確実に破棄する\n // さもなければ、ブラウザがリロードされるまでバックグラウンドで永遠に再生されてしまう\n this.destroy(true);\n\n // ページ上でキーが押されたときのイベントを削除\n if (this.shortcut_key_handler !== null) {\n document.removeEventListener('keydown', this.shortcut_key_handler);\n this.shortcut_key_handler = null;\n }\n },\n // チャンネル切り替え時に実行\n // コンポーネント(インスタンス)は再利用される\n // ref: https://router.vuejs.org/ja/guide/advanced/navigation-guards.html#%E3%83%AB%E3%83%BC%E3%83%88%E5%8D%98%E4%BD%8D%E3%82%AB%E3%82%99%E3%83%BC%E3%83%88%E3%82%99\n beforeRouteUpdate(to, from, next) {\n\n // 前のインスタンスを破棄して終了する\n this.destroy();\n\n // チャンネル ID を次のチャンネルのものに切り替える\n this.channel_id = to.params.channel_id;\n\n // 既に取得済みのチャンネル情報で、前・現在・次のチャンネル情報を更新する\n [this.channel_previous, this.channel, this.channel_next]\n = TVUtils.getPreviousAndCurrentAndNextChannel(this.channels_list, this.channel_id);\n\n // 0.5秒だけ待ってから\n // 連続して押した時などにライブストリームを初期化しないように猶予を設ける\n this.interval_ids.push(window.setTimeout(() => {\n\n // 現在のインスタンスを初期化する\n this.init();\n\n }, 500));\n\n next();\n },\n watch: {\n // 前回視聴画面を開いた際にパネルが表示されていたかどうかを保存\n is_panel_display() {\n Utils.setSettingsItem('is_latest_panel_display', this.is_panel_display);\n }\n },\n methods: {\n\n // 初期化する\n init() {\n\n // ローディング中の背景画像をランダムで設定\n this.background_url = Utils.generatePlayerBackgroundURL();\n\n // コントロール表示タイマーを実行\n this.controlDisplayTimer();\n\n // チャンネル情報を取得\n this.update();\n\n // 現在時刻を1秒おきに更新\n this.interval_ids.push(window.setInterval(() => {\n this.time = dayjs().format('YYYY/MM/DD HH:mm:ss');\n }, 1 * 1000));\n\n // 00秒までの残り秒数\n // 現在 16:01:34 なら 26 (秒) になる\n const residue_second = 60 - (Math.floor(new Date().getTime() / 1000) % 60);\n\n // 00秒になるまで待ってから\n // 番組は基本1分単位で組まれているため、20秒や45秒など中途半端な秒数で更新してしまうと反映が遅れてしまう\n this.interval_ids.push(window.setTimeout(() => {\n\n // チャンネル情報を更新\n this.update();\n\n // チャンネル情報を定期的に更新\n this.interval_ids.push(window.setInterval(() => {\n this.update();\n }, 30 * 1000)); // 30秒おき\n\n }, residue_second * 1000));\n },\n\n // チャンネル情報一覧を取得し、画面を更新する\n async update() {\n\n // チャンネル ID が未定義なら実行しない(フェイルセーフ)\n if (this.$route.params.channel_id === undefined) {\n return;\n }\n\n // チャンネル情報 API にアクセス\n let channel_response: AxiosResponse;\n try {\n channel_response = await Vue.axios.get(`${Utils.api_base_url}/channels/${this.channel_id}`);\n } catch (error) {\n\n // エラー内容を表示\n console.error(error);\n\n // ステータスコードが 422(チャンネルが存在しない)なら 404 ページにリダイレクト\n // 正確には 404 ページ自体がルートとして存在するわけじゃないけど、そもそも存在しないページなら 404 になるので\n if (error.response && error.response.status === 422 && error.response.data.detail === 'Specified channel_id was not found') {\n await this.$router.replace({path: '/not-found/'});\n }\n\n // 処理を中断\n return;\n }\n\n // チャンネル情報を代入\n this.channel = channel_response.data;\n\n // プレイヤーがまだ初期化されていない or 他のチャンネルからの切り替えですでにプレイヤーが初期化されているけど破棄が可能\n // update() 自体は初期化時以外にも1分ごとに定期実行されるため、その際に毎回プレイヤーを再初期化しないようにする\n if (this.player === null || this.player.KonomiTVCanDestroy === true) {\n\n // プレイヤーを初期化\n this.initPlayer();\n\n // イベントハンドラーを初期化\n this.initEventHandler();\n\n // ショートカットキーを初期化\n this.initShortcutKeyHandler();\n }\n\n // 副音声がない番組でプレイヤー上で副音声に切り替えられないように\n // 音声多重放送でもデュアルモノでもない番組のみ\n if ((this.channel.program_present === null) ||\n ((this.channel.program_present.primary_audio_type !== '1/0+1/0モード(デュアルモノ)') &&\n (this.channel.program_present.secondary_audio_type === null))) {\n\n // クラスを付与\n this.player.template.audioItem[1].classList.add('dplayer-setting-audio-item--disabled');\n\n // 現在副音声が選択されている可能性を考慮し、明示的に主音声に切り替える\n if (this.player.plugins.mpegts) {\n window.setTimeout(() => { // プレイヤーの初期化が完了するまで少し待つ\n this.player.template.audioItem[0].classList.add('dplayer-setting-audio-current');\n this.player.template.audioItem[1].classList.remove('dplayer-setting-audio-current');\n this.player.template.audioValue.textContent = this.player.tran('Primary audio');\n try {\n this.player.plugins.mpegts.switchPrimaryAudio();\n } catch (error) {\n // pass\n }\n }, 300);\n }\n\n // 音声多重放送かデュアルモノなので、副音声への切り替えを有効化\n } else {\n\n // クラスを削除\n this.player.template.audioItem[1].classList.remove('dplayer-setting-audio-item--disabled');\n }\n\n // チャンネル情報一覧 API にアクセス\n // チャンネル情報 API と同時にアクセスするとむしろレスポンスが遅くなるので、返ってくるのを待ってから実行\n let channels_response: AxiosResponse;\n try {\n channels_response = await Vue.axios.get(`${Utils.api_base_url}/channels`);\n } catch (error) {\n console.error(error); // エラー内容を表示\n return;\n }\n\n // is_display が true または現在表示中のチャンネルのみに絞り込むフィルタ関数\n // 放送していないサブチャンネルを表示から除外する\n const filter = (channel: IChannel) => {\n return channel.is_display || this.channel_id === channel.channel_id;\n }\n\n // チャンネルリストを再構築\n // 1つでもチャンネルが存在するチャンネルタイプのみ表示するように\n // たとえば SKY (スカパー!プレミアムサービス) のタブは SKY に属すチャンネルが1つもない(=受信できない)なら表示されない\n this.channels_list = new Map();\n this.channels_list.set('ピン留め', []); // ピン留めタブの準備\n if (channels_response.data.GR.length > 0) this.channels_list.set('地デジ', channels_response.data.GR.filter(filter));\n if (channels_response.data.BS.length > 0) this.channels_list.set('BS', channels_response.data.BS.filter(filter));\n if (channels_response.data.CS.length > 0) this.channels_list.set('CS', channels_response.data.CS.filter(filter));\n if (channels_response.data.CATV.length > 0) this.channels_list.set('CATV', channels_response.data.CATV.filter(filter));\n if (channels_response.data.SKY.length > 0) this.channels_list.set('SKY', channels_response.data.SKY.filter(filter));\n if (channels_response.data.STARDIGIO.length > 0) this.channels_list.set('StarDigio', channels_response.data.STARDIGIO.filter(filter));\n\n // ピン留めされているチャンネルの ID を取得\n const pinned_channel_ids = Utils.getSettingsItem('pinned_channel_ids');\n\n // ピン留めされているチャンネル情報のリスト\n const pinned_channels = [] as IChannel[];\n\n // チャンネル ID が一致したチャンネルの情報を保存する\n for (const pinned_channel_id of pinned_channel_ids) {\n const pinned_channel_type = TVUtils.getChannelType(pinned_channel_id, true);\n pinned_channels.push(this.channels_list.get(pinned_channel_type).find((channel) => {\n return channel.channel_id === pinned_channel_id; // チャンネル ID がピン留めされているチャンネルのものと同じ\n }));\n }\n\n // pinned_channels に何か入っていたらピン留めタブを表示するし、そうでなければ表示しない\n if (pinned_channels.length > 0) {\n this.channels_list.set('ピン留め', pinned_channels);\n } else {\n this.channels_list.delete('ピン留め');\n }\n\n // 前と次のチャンネル ID を取得する\n [this.channel_previous, , this.channel_next] = TVUtils.getPreviousAndCurrentAndNextChannel(this.channels_list, this.channel_id);\n\n // MediaSession API を使い、メディア通知の表示をカスタマイズ\n if ('mediaSession' in navigator) {\n\n // アートワークとして表示するアイコン\n const artwork = [\n {src: '/assets/img/icons/icon-maskable-192px.png', sizes: '192x192', type: 'image/png'},\n {src: '/assets/img/icons/icon-maskable-512px.png', sizes: '512x512', type: 'image/png'},\n ];\n\n // メディア通知の表示をカスタマイズ\n navigator.mediaSession.metadata = new MediaMetadata({\n title: this.channel.program_present ? this.channel.program_present.title : '放送休止',\n artist: this.channel.channel_name,\n artwork: artwork,\n });\n\n // 再生状況のステータスを設定\n if ('setPositionState' in navigator.mediaSession) {\n navigator.mediaSession.setPositionState({\n duration: 0, // ライブなので0(長さなしを表すらしい)に設定\n playbackRate: 1, // ライブなので再生速度は常に1になる\n });\n }\n\n // メディア通知上のボタンが押されたときのイベント\n navigator.mediaSession.setActionHandler('play', () => { this.player.play() }); // 再生\n navigator.mediaSession.setActionHandler('pause', () => { this.player.pause() }); // 停止\n navigator.mediaSession.setActionHandler('previoustrack', async () => { // 前のチャンネルに切り替え\n navigator.mediaSession.metadata = new MediaMetadata({\n title: this.channel_previous.program_present ? this.channel_previous.program_present.title : '放送休止',\n artist: this.channel_previous.channel_name,\n artwork: artwork,\n });\n // ルーティングを前のチャンネルに置き換える\n await this.$router.replace({path: `/tv/watch/${this.channel_previous.channel_id}`});\n });\n navigator.mediaSession.setActionHandler('nexttrack', async () => { // 次のチャンネルに切り替え\n navigator.mediaSession.metadata = new MediaMetadata({\n title: this.channel_next.program_present ? this.channel_next.program_present.title : '放送休止',\n artist: this.channel_next.channel_name,\n artwork: artwork,\n });\n // ルーティングを次のチャンネルに置き換える\n await this.$router.replace({path: `/tv/watch/${this.channel_next.channel_id}`});\n });\n }\n },\n\n // マウスが動いたりタップされた時のイベント\n // 3秒間何も操作がなければコントロールを非表示にする\n controlDisplayTimer(event: Event | null = null, is_player_event: boolean = false) {\n\n // タッチデバイスかどうか\n // DPlayer の UA 判定コードと同一\n const is_touch_device = /iPhone|iPad|iPod|Macintosh|Android|Mobile/i.test(navigator.userAgent) && 'ontouchend' in document;\n\n // タッチデバイスで mousemove 、あるいはタッチデバイス以外で touchmove か click が発火した時は実行じない\n if (is_touch_device == true && event !== null && event.type === 'mousemove') return;\n if (is_touch_device == false && event !== null && (event.type === 'touchmove' || event.type === 'click')) return;\n\n // 以前セットされたタイマーを止める\n window.clearTimeout(this.control_interval_id);\n\n // setTimeout に渡すタイマー関数\n const timeout = () => {\n\n // コメント入力フォームにフォーカスされているときは実行しない\n // タイマーを掛け直してから抜ける\n if (document.activeElement === this.player.template.commentInput) {\n this.control_interval_id = window.setTimeout(timeout, 3 * 1000);\n return;\n }\n\n // コントロールを非表示にする\n this.is_control_display = false;\n\n // プレイヤーのコントロールと設定パネルを非表示にする\n if (this.player !== null) {\n this.player.controller.hide();\n this.player.setting.hide();\n }\n }\n\n // タッチデバイスでプレイヤー画面がクリックされたとき\n if (is_touch_device === true && is_player_event === true) {\n\n // プレイヤーのコントロールの表示状態に合わせる\n if (this.player.controller.isShow()) {\n\n // コントロールを表示する\n this.is_control_display = true;\n\n // プレイヤーのコントロールを表示する\n this.player.controller.show();\n\n // 3秒間何も操作がなければコントロールを非表示にする\n // 3秒間の間一度でもマウスが動けばタイマーが解除されてやり直しになる\n this.control_interval_id = window.setTimeout(timeout, 3 * 1000);\n\n } else {\n\n // コントロールを非表示にする\n this.is_control_display = false;\n\n // プレイヤーのコントロールと設定パネルを非表示にする\n this.player.controller.hide();\n this.player.setting.hide();\n }\n\n // それ以外の画面がクリックされたとき\n } else {\n\n // コントロールを表示する\n this.is_control_display = true;\n\n // プレイヤーのコントロールを表示する\n if (this.player !== null) {\n this.player.controller.show();\n }\n\n // 3秒間何も操作がなければコントロールを非表示にする\n // 3秒間の間一度でもマウスが動けばタイマーが解除されてやり直しになる\n this.control_interval_id = window.setTimeout(timeout, 3 * 1000);\n }\n },\n\n // プレイヤーを初期化する\n initPlayer() {\n\n // mpegts.js を window 直下に入れる\n // こうしないと DPlayer が mpegts.js を認識できない\n (window as any).mpegts = mpegts;\n\n // すでに DPlayer が初期化されている場合は破棄する\n // チャンネル切り替え時などが該当する\n if (this.player !== null && this.player.KonomiTVCanDestroy === true) {\n try {\n this.player.destroy();\n } catch (error) {\n // mpegts.js をうまく破棄できない場合\n if (this.player.plugins.mpegts !== undefined) {\n this.player.plugins.mpegts.destroy();\n }\n }\n this.player = null;\n }\n\n // DPlayer を初期化\n this.player = new DPlayer({\n container: this.$el.querySelector('.watch-player__dplayer'),\n theme: '#E64F97', // テーマカラー\n lang: 'ja-jp', // 言語\n live: true, // ライブモード\n loop: false, // ループ再生 (ライブのため無効化)\n airplay: false, // AirPlay 機能 (うまく動かないため無効化)\n autoplay: true, // 自動再生\n hotkey: false, // ショートカットキー(こちらで制御するため無効化)\n screenshot: true, // スクリーンショット\n // screenshotOfEventTriggerOnly: true, // スクリーンショットボタンが押された際、イベントと Blob URL のみ受け取る\n volume: 1.0, // 音量の初期値\n // 映像\n video: {\n // デフォルトの品質\n // ラジオチャンネルでは常に 48KHz/192kbps に固定する\n defaultQuality: (this.channel.is_radiochannel) ? '48kHz/192kbps' : Utils.getSettingsItem('tv_streaming_quality'),\n // 品質リスト\n quality: (() => {\n const qualities = [];\n // ラジオチャンネル\n // API が受け付ける品質の値は通常のチャンネルと同じだが (手抜き…)、実際の品質は 48KHz/192kbps で固定される\n // ラジオチャンネルの場合は、1080p と渡しても 48kHz/192kbps 固定の音声だけの MPEG-TS が配信される\n if (this.channel.is_radiochannel) {\n qualities.push({\n name: '48kHz/192kbps',\n type: 'mpegts',\n url: `${Utils.api_base_url}/streams/live/${this.channel_id}/1080p/mpegts`,\n });\n // 通常のチャンネル\n } else {\n for (const quality of ['1080p', '810p', '720p', '540p', '480p', '360p', '240p']) {\n qualities.push({\n name: quality,\n type: 'mpegts',\n url: `${Utils.api_base_url}/streams/live/${this.channel_id}/${quality}/mpegts`,\n });\n }\n }\n return qualities;\n })(),\n },\n // コメント\n danmaku: {\n speedRate: Utils.getSettingsItem('comment_speed_rate'), // コメントの流れる速度\n fontSize: Utils.getSettingsItem('comment_font_size'), // コメントのフォントサイズ\n },\n // コメント API バックエンド\n apiBackend: {\n // コメント受信時\n read: (options) => {\n // 成功したことにして通知を抑制\n options.success([{}]);\n },\n // コメント送信時\n send: (options) => {\n // TODO: コメント送信は未実装\n options.error('現在、コメントの送信には対応していません。');\n },\n },\n // プラグイン\n pluginOptions: {\n // mpegts.js\n mpegts: {\n config: {\n enableWorker: true, // Web Worker を有効にする\n liveBufferLatencyChasing: true, // HTMLMediaElement の内部バッファによるライブストリームの待機時間を追跡する\n liveBufferLatencyMaxLatency: 3.0, // HTMLMediaElement で許容するバッファの最大値 (秒単位)\n liveBufferLatencyMinRemain: 0.5, // HTMLMediaElement に保持されるバッファの待機時間の最小値 (秒単位)\n }\n },\n // aribb24.js\n aribb24: {\n normalFont: '\"Windows TV MaruGothic\", \"Hiragino Maru Gothic Pro\", \"Yu Gothic Medium\", sans-serif',\n gaijiFont: '\"Windows TV MaruGothic\", \"Hiragino Maru Gothic Pro\", \"Yu Gothic Medium\", sans-serif',\n forceStrokeColor: 'black', // 縁取りする色\n drcsReplacement: true, // DRCS 文字を対応する Unicode 文字に置換\n enableRawCanvas: true, // 高解像度の字幕 Canvas を取得できるように\n useStrokeText: true, // 縁取りに strokeText API を利用\n }\n },\n // 字幕\n subtitle: {\n type: 'aribb24', // aribb24.js を有効化\n }\n });\n\n // デバッグ用にプレイヤーインスタンスも window 直下に入れる\n (window as any).player = this.player;\n\n // プレイヤー側のコントロール非表示タイマーを無効化(上書き)\n // 無効化しておかないと、controlDisplayTimer() と競合してしまう\n // 上書き元のコードは https://github.com/tsukumijima/DPlayer/blob/master/src/js/controller.js#L387-L395 にある\n this.player.controller.setAutoHide = (time: number) => {};\n\n // 設定パネルにショートカット一覧を表示するリンクを動的に追加する\n // タッチデバイスでは実行しない\n const is_touch_device = /iPhone|iPad|iPod|Macintosh|Android|Mobile/i.test(navigator.userAgent) && 'ontouchend' in document;\n if (is_touch_device === false) {\n this.player.template.settingOriginPanel.insertAdjacentHTML('beforeend', `\n
\n キーボードショートカット\n
\n \n \n \n
\n
`)\n\n // 設定パネルの高さを再設定\n const settingOriginPanelHeight = this.player.template.settingOriginPanel.scrollHeight;\n this.player.template.settingBox.style.clipPath = `inset(calc(100% - ${settingOriginPanelHeight}px) 0 0 round 7px)`;\n\n // 設定パネルのショートカット一覧を表示するリンクがクリックされたときのイベント\n // リアクティブではないので、手動でやらないといけない…\n this.$el.querySelector('.dplayer-setting-keyboard-shortcut').addEventListener('click', () => {\n this.player.setting.hide(); // 設定パネルを閉じる\n this.shortcut_key_modal = true;\n });\n }\n\n // 再生/停止されたとき\n // 通知バーからの制御など、画面から以外の外的要因で再生/停止が行われる事もある\n const on_play_or_pause = () => {\n\n // まだ設定パネルが表示されていたら非表示にする\n this.player.setting.hide();\n\n // コントロールを表示する\n this.controlDisplayTimer();\n }\n this.player.on('play', on_play_or_pause);\n this.player.on('pause', on_play_or_pause);\n\n // 画質の切り替えが開始されたとき\n this.player.on('quality_start', () => {\n\n // ローディング中の背景画像をランダムで設定\n this.background_url = Utils.generatePlayerBackgroundURL();\n\n // イベントソースを閉じる\n if (this.eventsource !== null) {\n this.eventsource.close();\n this.eventsource = null;\n }\n\n // 新しい EventSource を作成\n // 画質ごとにイベント API は異なるため、一度破棄してから作り直す\n this.initEventHandler();\n });\n\n // 字幕が非表示の場合でも、文字スーパーは表示する\n this.player.plugins.aribb24Superimpose.show();\n this.player.on('subtitle_hide', () => {\n this.player.plugins.aribb24Superimpose.show();\n });\n\n // 停止状態でかつ再生時間からバッファが 30 秒以上離れていないかを1分おきに監視し、そうなっていたら強制的にシークする\n // mpegts.js の仕様上、MSE に未再生のバッファがたまり過ぎると SourceBuffer が追加できなくなるため、強制的に接続が切断されてしまう\n this.interval_ids.push(window.setInterval(() => {\n if (this.player.video.paused && this.player.video.buffered.end(0) - this.player.video.currentTime > 30) {\n this.player.sync();\n }\n }, 60 * 1000));\n\n // フルスクリーンにするコンテナ要素(コンポーネント全体)\n const fullscreen_container = this.$el;\n this.fullscreen_handler = () => this.is_fullscreen = this.player.fullScreen.isFullScreen();\n if (fullscreen_container.onfullscreenchange !== undefined) {\n fullscreen_container.addEventListener('fullscreenchange', this.fullscreen_handler);\n } else {\n fullscreen_container.addEventListener('webkitfullscreenchange', this.fullscreen_handler);\n }\n\n // DPlayer のフルスクリーン関係のメソッドを無理やり上書きし、KonomiTV の UI と統合する\n // 上書き元のコードは https://github.com/tsukumijima/DPlayer/blob/master/src/js/fullscreen.js にある\n // フルスクリーンかどうか\n this.player.fullScreen.isFullScreen = (type: string) => {\n return !!(document.fullscreenElement || document.webkitFullscreenElement);\n }\n // フルスクリーンをリクエスト\n this.player.fullScreen.request = (type: string) => {\n\n // すでにフルスクリーンだったらキャンセルする\n if (this.player.fullScreen.isFullScreen()) {\n this.player.fullScreen.cancel();\n return;\n }\n\n // フルスクリーンをリクエスト\n // Safari は webkit のベンダープレフィックスが必要\n fullscreen_container.requestFullscreen = fullscreen_container.requestFullscreen || fullscreen_container.webkitRequestFullscreen;\n if (fullscreen_container.requestFullscreen) {\n fullscreen_container.requestFullscreen();\n }\n\n // 画面の向きを横に固定 (Screen Orientation API がサポートされている場合)\n if (screen.orientation) {\n screen.orientation.lock('landscape').catch(() => {});\n }\n }\n // フルスクリーンをキャンセル\n this.player.fullScreen.cancel = (type: string) => {\n\n // フルスクリーンを終了\n // Safari は webkit のベンダープレフィックスが必要\n document.exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen;\n if (document.exitFullscreen) {\n document.exitFullscreen();\n }\n\n // 画面の向きの固定を解除\n if (screen.orientation) {\n screen.orientation.unlock();\n }\n }\n },\n\n // イベントハンドラーを初期化する\n initEventHandler() {\n\n // 必ず最初はローディング状態とする\n this.is_loading = true;\n\n // プレイヤーの背景を非表示にするイベントを登録\n // 実際に再生可能になるのを待ってから実行する\n const on_canplay = () => {\n // 念のためさらに少しだけ待ってから\n window.setTimeout(() => {\n this.is_loading = false;\n // ラジオチャンネルでは映像の代わりに背景画像を表示し続ける\n if (this.channel.is_radiochannel) {\n this.is_background_display = true;\n } else {\n this.is_background_display = false;\n }\n }, 100);\n this.player.video.oncanplay = null;\n this.player.video.oncanplaythrough = null;\n }\n this.player.video.oncanplay = on_canplay;\n this.player.video.oncanplaythrough = on_canplay;\n\n // EventSource を作成\n // ラジオチャンネルの場合は見かけ上の品質と API に渡す品質が異なるので、それに合わせる\n const quality_name = (this.channel.is_radiochannel) ? '1080p' : this.player.quality.name;\n this.eventsource = new EventSource(`${Utils.api_base_url}/streams/live/${this.channel_id}/${quality_name}/events`);\n\n // 初回接続時のイベント\n this.eventsource.addEventListener('initial_update', (event_raw: MessageEvent) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n\n // ステータスが Standby であれば、プレイヤーの背景を表示する\n if (event.status === 'Standby') {\n this.is_background_display = true;\n }\n });\n\n // ステータスが更新されたときのイベント\n this.eventsource.addEventListener('status_update', (event_raw: MessageEvent) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n console.log(`Status: ${event.status} Detail:${event.detail}`);\n\n // 視聴者数を更新\n this.channel.viewers = event.clients_count;\n\n // ステータスごとに処理を振り分け\n switch (event.status) {\n\n // Status: Standby\n case 'Standby': {\n\n // ステータス詳細をプレイヤーに表示\n if (!this.player.template.notice.textContent.includes('画質を')) { // 画質切り替えの表示を上書きしない\n this.player.notice(event.detail, -1);\n }\n\n // プレイヤーの背景を表示する\n this.is_background_display = true;\n\n break;\n }\n\n // Status: ONAir\n case 'ONAir': {\n\n // ステータス詳細をプレイヤーから削除\n if (!this.player.template.notice.textContent.includes('画質を')) { // 画質切り替えの表示を上書きしない\n this.player.notice(this.player.template.notice.textContent, 0.000001);\n }\n\n // 前のプレイヤーインスタンスの Picture-in-Picture ウインドウが残っている場合、終了させてからもう一度切り替える\n // チャンネル切り替えが完了しても前の Picture-in-Picture ウインドウは再利用されないため、一旦終了させるしかない\n if (document.pictureInPictureElement) {\n document.exitPictureInPicture();\n this.player.video.requestPictureInPicture();\n }\n\n break;\n }\n\n // Status: Restart\n case 'Restart': {\n\n // ステータス詳細をプレイヤーに表示\n this.player.notice(event.detail, -1);\n\n // プレイヤーを再起動する\n this.player.switchVideo({\n url: this.player.quality.url,\n type: this.player.quality.type,\n });\n\n // 再起動しただけでは自動再生されないので、明示的に\n this.player.play();\n\n // プレイヤーの背景を表示する\n this.is_background_display = true;\n\n break;\n }\n\n // Status: Offline\n case 'Offline': {\n\n // ステータス詳細をプレイヤーに表示\n // 動画の読み込みエラーが送出された時にメッセージを上書きする\n this.player.notice(event.detail, -1);\n this.player.video.onerror = () => {\n this.player.notice(event.detail, -1);\n this.player.video.onerror = null;\n }\n\n // 描画されたコメントをクリア\n this.player.danmaku.clear()\n\n // 動画を停止する\n this.player.video.pause();\n\n // イベントソースを閉じる(復帰の見込みがないため)\n this.eventsource.close();\n\n // プレイヤーの背景を表示する\n this.is_background_display = true;\n\n break;\n }\n }\n });\n\n // ステータス詳細が更新されたときのイベント\n this.eventsource.addEventListener('detail_update', (event_raw: MessageEvent) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n console.log(`Status: ${event.status} Detail:${event.detail}`);\n\n // 視聴者数を更新\n this.channel.viewers = event.clients_count;\n\n // Standby のときだけプレイヤーに表示\n if (event.status === 'Standby') {\n this.player.notice(event.detail, -1);\n\n // プレイヤーの背景を表示する\n if (!this.is_background_display) {\n this.is_background_display = true;\n }\n }\n });\n\n // クライアント数(だけ)が更新されたときのイベント\n this.eventsource.addEventListener('clients_update', (event_raw: MessageEvent) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n\n // 視聴者数を更新\n this.channel.viewers = event.clients_count;\n });\n },\n\n // ショートカットキーを初期化する\n initShortcutKeyHandler() {\n\n // ショートカットキーハンドラー\n this.shortcut_key_handler = (event: KeyboardEvent) => {\n\n // キーリピート(押しっぱなし)状態の場合は基本実行しない\n // 押し続けると何度も同じ動作が実行されて大変な事になる…\n // ただ、キーリピートを使いたい場合もあるので、リピート状態をフラグとして保存する\n let is_repeat = false;\n if (event.repeat) is_repeat = true;\n\n // キーリピート状態は event.repeat を見る事でだいたい検知できるが、最初の何回かは検知できないこともある\n // そこで、0.1 秒以内に連続して発火したキーイベントは間引きも兼ねて実行しない\n const now = Date.now();\n if (now - this.shortcut_key_pressed_at < (0.1 * 1000)) return;\n this.shortcut_key_pressed_at = now; // 最終押下時刻を更新\n\n // input・textarea・contenteditable 状態の要素でなければ\n // 文字入力中にショートカットキーが作動してしまわないように\n const tag = document.activeElement.tagName.toUpperCase();\n const editable = document.activeElement.getAttribute('contenteditable');\n if (tag !== 'INPUT' && tag !== 'TEXTAREA' && editable !== '' && editable !== 'true') {\n\n // ***** 数字キーでチャンネルを切り替える *****\n\n if (is_repeat === false) {\n\n // チャンネルタイプを選択\n // Shift キーが押されていたらチャンネルタイプを地デジならBSに、BSなら地デジにする\n let switch_channel_type = this.channel.channel_type;\n if (event.shiftKey && this.channel.channel_type == 'GR') switch_channel_type = 'BS';\n if (event.shiftKey && this.channel.channel_type == 'BS') switch_channel_type = 'GR';\n\n // 1~9キー\n let switch_remocon_id = null;\n if (event.code === 'Digit1' || event.code === 'Digit2' || event.code === 'Digit3' ||\n event.code === 'Digit4' || event.code === 'Digit5' || event.code === 'Digit6' ||\n event.code === 'Digit7' || event.code === 'Digit8' || event.code === 'Digit9') {\n switch_remocon_id = Number(event.code.replace('Digit', ''));\n }\n // 0キー: 10に割り当て\n if (event.code === 'Digit0') switch_remocon_id = 10;\n // -キー: 11に割り当て\n if (event.code === 'Minus') switch_remocon_id = 11;\n // ^キー: 12に割り当て\n if (event.code === 'Equal') switch_remocon_id = 12;\n // 1~9キー (テンキー)\n if (event.code === 'Numpad1' || event.code === 'Numpad2' || event.code === 'Numpad3' ||\n event.code === 'Numpad4' || event.code === 'Numpad5' || event.code === 'Numpad6' ||\n event.code === 'Numpad7' || event.code === 'Numpad8' || event.code === 'Numpad9') {\n switch_remocon_id = Number(event.code.replace('Numpad', ''));\n }\n // 0キー (テンキー): 10に割り当て\n if (event.code === 'Numpad0') switch_remocon_id = 10;\n\n // この時点でリモコン番号が取得できていたら実行\n if (switch_remocon_id !== null) {\n\n // 切り替え先のチャンネルを取得する\n const switch_channel = TVUtils.getChannelFromRemoconID(this.channels_list, switch_channel_type, switch_remocon_id);\n\n // チャンネルが取得できていれば、ルーティングをそのチャンネルに置き換える\n // 押されたキーに対応するリモコン番号のチャンネルがない場合や、現在と同じチャンネル ID の場合は何も起こらない\n if (switch_channel !== null && switch_channel.channel_id !== this.channel_id) {\n (async () => await this.$router.replace({path: `/tv/watch/${switch_channel.channel_id}`}))();\n return;\n }\n }\n }\n\n // ***** 上下キーでチャンネルを切り替える *****\n\n // ↑キー: 前のチャンネルに切り替え\n if (event.code === 'ArrowUp' && is_repeat === false) {\n event.preventDefault(); // デフォルトのイベントを無効化\n (async () => await this.$router.replace({path: `/tv/watch/${this.channel_previous.channel_id}`}))();\n return;\n }\n // ↓キー: 次のチャンネルに切り替え\n if (event.code === 'ArrowDown' && is_repeat === false) {\n event.preventDefault(); // デフォルトのイベントを無効化\n (async () => await this.$router.replace({path: `/tv/watch/${this.channel_next.channel_id}`}))();\n return;\n }\n\n // ***** キーボードショートカットの一覧を表示する *****\n\n // /(?)キー: キーボードショートカットの一覧を表示する\n if (event.code === 'Slash' && is_repeat === false) {\n this.shortcut_key_modal = !this.shortcut_key_modal;\n return;\n }\n\n // ***** パネルのタブを切り替える *****\n\n if (is_repeat === false) {\n // Pキー: パネルの表示切り替え\n if (event.code === 'KeyP') {\n this.is_panel_display = !this.is_panel_display;\n return;\n }\n // Kキー: 番組情報タブ\n if (event.code === 'KeyK') {\n this.panel_active_tab = 'Program';\n return;\n }\n // Lキー: チャンネルタブ\n if (event.code === 'KeyL') {\n this.panel_active_tab = 'Channel';\n return;\n }\n // ;(+)キー: コメントタブ\n if (event.code === 'Semicolon') {\n this.panel_active_tab = 'Comment';\n return;\n }\n // :(*)キー: Twitterタブ\n if (event.code === 'Quote') {\n this.panel_active_tab = 'Twitter';\n return;\n }\n }\n\n // ***** プレイヤーのショートカットキー *****\n\n // プレイヤーが初期化されていない際や Ctrl or Cmd キーが一緒に押された際に作動しないように\n if (this.player !== null && !event.ctrlKey && !event.metaKey) {\n // ←キー: 停止して0.25秒巻き戻し\n // ここだけキーリピートを許可する\n if (event.code === 'ArrowLeft') {\n event.preventDefault(); // デフォルトのイベントを無効化\n if (this.player.video.paused === false) this.player.video.pause();\n this.player.video.currentTime = this.player.video.currentTime - 0.25;\n return;\n }\n // →キー: 停止して0.25秒早送り\n // ここだけキーリピートを許可する\n if (event.code === 'ArrowRight') {\n event.preventDefault(); // デフォルトのイベントを無効化\n if (this.player.video.paused === false) this.player.video.pause();\n this.player.video.currentTime = this.player.video.currentTime + 0.25;\n return;\n }\n if (is_repeat === false) {\n // Spaceキー: 再生/停止\n if (event.code === 'Space') {\n this.player.toggle();\n return;\n }\n // Fキー: フルスクリーンの切り替え\n if (event.code === 'KeyF') {\n this.player.fullScreen.toggle();\n return;\n }\n // Wキー: ライブストリームの同期\n if (event.code === 'KeyW') {\n this.player.sync();\n return;\n }\n // Eキー: Picture-in-Picture の表示切り替え\n if (event.code === 'KeyE') {\n if (document.pictureInPictureEnabled) {\n this.player.template.pipButton.click();\n }\n return;\n }\n // Sキー: 字幕の表示切り替え\n if (event.code === 'KeyS') {\n this.player.subtitle.toggle();\n if (!this.player.subtitle.container.classList.contains('dplayer-subtitle-hide')) {\n this.player.notice(`${this.player.tran('Show subtitle')}`);\n } else {\n this.player.notice(`${this.player.tran('Hide subtitle')}`);\n }\n return;\n }\n // Dキー: コメントの表示切り替え\n if (event.code === 'KeyD') {\n this.player.template.showDanmaku.click();\n if (this.player.template.showDanmakuToggle.checked) {\n this.player.notice(`${this.player.tran('Show comment')}`);\n } else {\n this.player.notice(`${this.player.tran('Hide comment')}`);\n }\n return;\n }\n // Mキー: コメント入力フォームにフォーカス\n if (event.code === 'KeyM') {\n event.preventDefault(); // デフォルトのイベントを無効化\n this.player.controller.show();\n this.player.comment.show();\n this.controlDisplayTimer();\n window.setTimeout(() => this.player.template.commentInput.focus(), 100);\n return;\n }\n }\n }\n }\n };\n\n // ページ上でキーが押されたときのイベントを登録\n document.addEventListener('keydown', this.shortcut_key_handler);\n },\n\n // 破棄する\n destroy(is_destroy_player = false) {\n\n // clearInterval() ですべての setInterval(), setTimeout() の実行を止める\n // clearInterval() と clearTimeout() は中身共通なので問題ない\n for (const interval_id of this.interval_ids) {\n window.clearInterval(interval_id);\n }\n\n // コントロール表示制御用タイマーを止める\n window.clearTimeout(this.control_interval_id);\n\n // interval_ids をクリア\n this.interval_ids = [];\n\n // 再びローディング状態にする\n this.is_loading = true;\n\n // プレイヤーの背景を隠す\n this.is_background_display = false;\n\n // プレイヤーに破棄が可能なフラグをつける\n this.player.KonomiTVCanDestroy = true;\n\n // イベントソースを閉じる\n if (this.eventsource !== null) {\n this.eventsource.close();\n this.eventsource = null;\n }\n\n // アニメーション分待ってから実行\n this.interval_ids.push(window.setTimeout(() => {\n\n // プレイヤーを停止する\n this.player.video.pause();\n\n // is_destroy_player が true の時は、ここで DPlayer 自体を破棄する\n // false の時は次の initPlayer() が実行されるまで破棄されない\n if (is_destroy_player === true && this.player !== null) {\n try {\n this.player.destroy();\n } catch (error) {\n // mpegts.js をうまく破棄できない場合\n if (this.player.plugins.mpegts !== undefined) {\n this.player.plugins.mpegts.destroy();\n }\n }\n this.player = null;\n }\n\n }, 400)); // 0.4 秒\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Watch.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Watch.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Watch.vue?vue&type=template&id=8b237ea4&scoped=true&\"\nimport script from \"./Watch.vue?vue&type=script&lang=ts&\"\nexport * from \"./Watch.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Watch.vue?vue&type=style&index=0&lang=scss&\"\nimport style1 from \"./Watch.vue?vue&type=style&index=1&id=8b237ea4&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"8b237ea4\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VBtn } from 'vuetify/lib/components/VBtn';\nimport { VCard } from 'vuetify/lib/components/VCard';\nimport { VCardActions } from 'vuetify/lib/components/VCard';\nimport { VCardTitle } from 'vuetify/lib/components/VCard';\nimport { VCol } from 'vuetify/lib/components/VGrid';\nimport { VDialog } from 'vuetify/lib/components/VDialog';\nimport { VDivider } from 'vuetify/lib/components/VDivider';\nimport { VRow } from 'vuetify/lib/components/VGrid';\nimport { VSpacer } from 'vuetify/lib/components/VGrid';\ninstallComponents(component, {VBtn,VCard,VCardActions,VCardTitle,VCol,VDialog,VDivider,VRow,VSpacer})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Base',[_c('h2',{staticClass:\"settings__heading\"},[_c('Icon',{attrs:{\"icon\":\"fa-solid:sliders-h\",\"width\":\"18px\"}}),_c('span',{staticClass:\"ml-3\"},[_vm._v(\"全般\")])],1),_c('div',{staticClass:\"settings__content\"},[_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"テレビのストリーミング画質\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" テレビをライブストリーミングする際の既定の画質を設定します。\"),_c('br'),_vm._v(\" ストリーミング画質はプレイヤーの設定からいつでも切り替えられます。\"),_c('br')]),_c('v-select',{staticClass:\"settings__item-form\",attrs:{\"outlined\":\"\",\"hide-details\":\"\",\"items\":_vm.tv_streaming_quality},model:{value:(_vm.settings.tv_streaming_quality),callback:function ($$v) {_vm.$set(_vm.settings, \"tv_streaming_quality\", $$v)},expression:\"settings.tv_streaming_quality\"}})],1),_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"既定のパネルの表示状態\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" 視聴画面を開いたときに、右側のパネルをどう表示するかを設定します。\"),_c('br')]),_c('v-select',{staticClass:\"settings__item-form\",attrs:{\"outlined\":\"\",\"hide-details\":\"\",\"items\":_vm.panel_display_state},model:{value:(_vm.settings.panel_display_state),callback:function ($$v) {_vm.$set(_vm.settings, \"panel_display_state\", $$v)},expression:\"settings.panel_display_state\"}})],1),_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"既定で表示されるパネルのタブ\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" 視聴画面を開いたときに、右側のパネルで最初に表示されるタブを設定します。\"),_c('br')]),_c('v-select',{staticClass:\"settings__item-form\",attrs:{\"outlined\":\"\",\"hide-details\":\"\",\"items\":_vm.panel_active_tab},model:{value:(_vm.settings.panel_active_tab),callback:function ($$v) {_vm.$set(_vm.settings, \"panel_active_tab\", $$v)},expression:\"settings.panel_active_tab\"}})],1)])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"route-container\"},[_c('Header'),_c('main',[_c('Navigation'),_c('v-card',{staticClass:\"settings-container d-flex px-5 py-5 mx-auto background\",attrs:{\"elevation\":\"0\",\"width\":\"100%\",\"max-width\":\"1000\"}},[_c('div',[_c('v-navigation-drawer',{staticClass:\"settings-navigation flex-shrink-0 background\",attrs:{\"permanent\":\"\",\"width\":\"195\",\"height\":\"auto\"}},[_c('v-list-item',{staticClass:\"px-4\"},[_c('v-list-item-content',[_c('h1',[_vm._v(\"設定\")])])],1),_c('v-list',{staticClass:\"mt-2 px-0\",attrs:{\"nav\":\"\"}},[_c('v-list-item',{staticClass:\"px-4\",attrs:{\"link\":\"\",\"color\":\"primary\",\"to\":\"/settings/general\"}},[_c('v-list-item-icon',{staticClass:\"mr-4\"},[_c('Icon',{staticStyle:{\"padding\":\"0 3px\"},attrs:{\"icon\":\"fa-solid:sliders-h\",\"width\":\"26px\"}})],1),_c('v-list-item-content',[_c('v-list-item-title',[_vm._v(\"全般\")])],1)],1),_c('v-list-item',{staticClass:\"px-4\",attrs:{\"link\":\"\",\"color\":\"primary\",\"to\":\"/settings/account\"}},[_c('v-list-item-icon',{staticClass:\"mr-4\"},[_c('Icon',{attrs:{\"icon\":\"fluent:person-20-filled\",\"width\":\"26px\"}})],1),_c('v-list-item-content',[_c('v-list-item-title',[_vm._v(\"アカウント\")])],1)],1),_c('v-list-item',{staticClass:\"px-4\",attrs:{\"link\":\"\",\"color\":\"primary\",\"to\":\"/settings/jikkyo\"}},[_c('v-list-item-icon',{staticClass:\"mr-4\"},[_c('Icon',{staticStyle:{\"padding\":\"0 2px\"},attrs:{\"icon\":\"bi:chat-left-text-fill\",\"width\":\"26px\"}})],1),_c('v-list-item-content',[_c('v-list-item-title',[_vm._v(\"ニコニコ実況\")])],1)],1),_c('v-list-item',{staticClass:\"px-4\",attrs:{\"link\":\"\",\"color\":\"primary\",\"to\":\"/settings/twitter\"}},[_c('v-list-item-icon',{staticClass:\"mr-4\"},[_c('Icon',{staticStyle:{\"padding\":\"0 1px\"},attrs:{\"icon\":\"fa-brands:twitter\",\"width\":\"26px\"}})],1),_c('v-list-item-content',[_c('v-list-item-title',[_vm._v(\"Twitter\")])],1)],1)],1)],1)],1),_c('v-card',{staticClass:\"settings ml-5 px-7 py-7 background lighten-1\",attrs:{\"width\":\"100%\"}},[_vm._t(\"default\")],2)],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Header from '@/components/Header.vue';\nimport Navigation from '@/components/Navigation.vue';\n\n// 設定のベース画面なので、ロジックは基本置かない\nexport default Vue.extend({\n name: 'SettingsBase',\n components: {\n Header,\n Navigation,\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Base.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Base.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Base.vue?vue&type=template&id=18637a38&scoped=true&\"\nimport script from \"./Base.vue?vue&type=script&lang=ts&\"\nexport * from \"./Base.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Base.vue?vue&type=style&index=0&id=18637a38&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"18637a38\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VCard } from 'vuetify/lib/components/VCard';\nimport { VList } from 'vuetify/lib/components/VList';\nimport { VListItem } from 'vuetify/lib/components/VList';\nimport { VListItemContent } from 'vuetify/lib/components/VList';\nimport { VListItemIcon } from 'vuetify/lib/components/VList';\nimport { VListItemTitle } from 'vuetify/lib/components/VList';\nimport { VNavigationDrawer } from 'vuetify/lib/components/VNavigationDrawer';\ninstallComponents(component, {VCard,VList,VListItem,VListItemContent,VListItemIcon,VListItemTitle,VNavigationDrawer})\n","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Base from '@/views/Settings/Base.vue';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'SettingsGeneral',\n components: {\n Base,\n },\n data() {\n return {\n\n // テレビのストリーミング画質の選択肢\n tv_streaming_quality: [\n {'text': '1080p (1時間あたり約2.31GB / 5.1Mbps)', 'value': '1080p'},\n {'text': '810p (1時間あたり約1.92GB / 4.2Mbps)', 'value': '810p'},\n {'text': '720p (1時間あたり約1.33GB / 3.0Mbps)', 'value': '720p'},\n {'text': '540p (1時間あたり約1.00GB / 2.2Mbps)', 'value': '540p'},\n {'text': '480p (1時間あたり約0.74GB / 1.6Mbps)', 'value': '480p'},\n {'text': '360p (1時間あたり約0.40GB / 0.9Mbps)', 'value': '360p'},\n {'text': '240p (1時間あたり約0.23GB / 0.5Mbps)', 'value': '240p'},\n ],\n\n // 既定のパネルの表示状態の選択肢\n panel_display_state: [\n {'text': '前回の状態を復元する', 'value': 'RestorePreviousState'},\n {'text': '常に表示する', 'value': 'AlwaysDisplay'},\n {'text': '常に折りたたむ', 'value': 'AlwaysFold'},\n ],\n\n // 既定で表示されるパネルのタブの選択肢\n panel_active_tab: [\n {'text': '番組情報タブ', 'value': 'Program'},\n {'text': 'チャンネルタブ', 'value': 'Channel'},\n {'text': 'コメントタブ', 'value': 'Comment'},\n {'text': 'Twitter タブ', 'value': 'Twitter'},\n ],\n\n // 設定値が保存されるオブジェクト\n // ここの値とフォームを v-model で binding する\n settings: (() => {\n // 設定の既定値を取得する\n const settings = {}\n for (const setting of ['tv_streaming_quality', 'panel_display_state', 'panel_active_tab']) {\n settings[setting] = Utils.getSettingsItem(setting);\n }\n return settings;\n })(),\n }\n },\n watch: {\n // settings 内の値の変更を監視する\n settings: {\n deep: true,\n handler() {\n // settings 内の値を順に LocalStorage に保存する\n for (const [setting_key, setting_value] of Object.entries(this.settings)) {\n Utils.setSettingsItem(setting_key, setting_value);\n }\n }\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./General.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./General.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./General.vue?vue&type=template&id=7c670856&\"\nimport script from \"./General.vue?vue&type=script&lang=ts&\"\nexport * from \"./General.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VSelect } from 'vuetify/lib/components/VSelect';\ninstallComponents(component, {VSelect})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Base',[_c('h2',{staticClass:\"settings__heading\"},[_c('Icon',{attrs:{\"icon\":\"fluent:person-20-filled\",\"width\":\"24px\"}}),_c('span',{staticClass:\"ml-2\"},[_vm._v(\"アカウント\")])],1),_c('div',{staticClass:\"settings__content\"},[_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"鋭意開発中…\")])])])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Base from '@/views/Settings/Base.vue';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'SettingsAccount',\n components: {\n Base,\n },\n data() {\n return {\n\n // 設定値が保存されるオブジェクト\n // ここの値とフォームを v-model で binding する\n settings: (() => {\n // 設定の既定値を取得する\n const settings = {}\n for (const setting of []) {\n settings[setting] = Utils.getSettingsItem(setting);\n }\n return settings;\n })(),\n }\n },\n watch: {\n // settings 内の値の変更を監視する\n settings: {\n deep: true,\n handler() {\n // settings 内の値を順に LocalStorage に保存する\n for (const [setting_key, setting_value] of Object.entries(this.settings)) {\n Utils.setSettingsItem(setting_key, setting_value);\n }\n }\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Account.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Account.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Account.vue?vue&type=template&id=19541e55&\"\nimport script from \"./Account.vue?vue&type=script&lang=ts&\"\nexport * from \"./Account.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Base',[_c('h2',{staticClass:\"settings__heading\"},[_c('Icon',{attrs:{\"icon\":\"bi:chat-left-text-fill\",\"width\":\"18px\"}}),_c('span',{staticClass:\"ml-3\"},[_vm._v(\"ニコニコ実況\")])],1),_c('div',{staticClass:\"settings__content\"},[_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"コメントの速さ\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" プレイヤーに流れるコメントの速さを設定します。\"),_c('br'),_vm._v(\" たとえば 1.2 に設定すると、コメントが 1.2 倍速く流れます。\"),_c('br')]),_c('v-slider',{staticClass:\"settings__item-form\",attrs:{\"ticks\":\"always\",\"thumb-label\":\"\",\"hide-details\":\"\",\"step\":0.1,\"min\":0.5,\"max\":2},model:{value:(_vm.settings.comment_speed_rate),callback:function ($$v) {_vm.$set(_vm.settings, \"comment_speed_rate\", $$v)},expression:\"settings.comment_speed_rate\"}})],1),_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"コメントの文字サイズ\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" プレイヤーに流れるコメントの文字サイズの基準値を設定します。\"),_c('br'),_vm._v(\" 実際の文字サイズは画面の大きさに合わせて調整されます。既定の文字サイズは 34px です。\"),_c('br')]),_c('v-slider',{staticClass:\"settings__item-form\",attrs:{\"ticks\":\"always\",\"thumb-label\":\"\",\"hide-details\":\"\",\"min\":20,\"max\":60},model:{value:(_vm.settings.comment_font_size),callback:function ($$v) {_vm.$set(_vm.settings, \"comment_font_size\", $$v)},expression:\"settings.comment_font_size\"}})],1),_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"コメントの遅延時間\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" プレイヤーやコメントリストに表示されるコメントを何秒遅らせて反映するかを設定します。\"),_c('br'),_vm._v(\" 通常は 1 秒程度で大丈夫です。ネットワークが遅いなどでタイムラグが大きいときだけ、映像の遅延に合わせて調整してください。\"),_c('br')]),_c('v-slider',{staticClass:\"settings__item-form\",attrs:{\"ticks\":\"always\",\"thumb-label\":\"\",\"hide-details\":\"\",\"step\":0.5,\"min\":0,\"max\":5},model:{value:(_vm.settings.comment_delay_time),callback:function ($$v) {_vm.$set(_vm.settings, \"comment_delay_time\", $$v)},expression:\"settings.comment_delay_time\"}})],1)])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Base from '@/views/Settings/Base.vue';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'SettingsJikkyo',\n components: {\n Base,\n },\n data() {\n return {\n\n // 設定値が保存されるオブジェクト\n // ここの値とフォームを v-model で binding する\n settings: (() => {\n // 設定の既定値を取得する\n const settings = {}\n for (const setting of ['comment_speed_rate', 'comment_font_size', 'comment_delay_time']) {\n settings[setting] = Utils.getSettingsItem(setting);\n }\n return settings;\n })(),\n }\n },\n watch: {\n // settings 内の値の変更を監視する\n settings: {\n deep: true,\n handler() {\n // settings 内の値を順に LocalStorage に保存する\n for (const [setting_key, setting_value] of Object.entries(this.settings)) {\n Utils.setSettingsItem(setting_key, setting_value);\n }\n }\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Jikkyo.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Jikkyo.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Jikkyo.vue?vue&type=template&id=cc7a4024&\"\nimport script from \"./Jikkyo.vue?vue&type=script&lang=ts&\"\nexport * from \"./Jikkyo.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VSlider } from 'vuetify/lib/components/VSlider';\ninstallComponents(component, {VSlider})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Base',[_c('h2',{staticClass:\"settings__heading\"},[_c('Icon',{attrs:{\"icon\":\"fa-brands:twitter\",\"width\":\"21px\"}}),_c('span',{staticClass:\"ml-3\"},[_vm._v(\"Twitter\")])],1),_c('div',{staticClass:\"settings__content\"},[_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"鋭意開発中…\")])])])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Base from '@/views/Settings/Base.vue';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'SettingsAccount',\n components: {\n Base,\n },\n data() {\n return {\n\n // 設定値が保存されるオブジェクト\n // ここの値とフォームを v-model で binding する\n settings: (() => {\n // 設定の既定値を取得する\n const settings = {}\n for (const setting of []) {\n settings[setting] = Utils.getSettingsItem(setting);\n }\n return settings;\n })(),\n }\n },\n watch: {\n // settings 内の値の変更を監視する\n settings: {\n deep: true,\n handler() {\n // settings 内の値を順に LocalStorage に保存する\n for (const [setting_key, setting_value] of Object.entries(this.settings)) {\n Utils.setSettingsItem(setting_key, setting_value);\n }\n }\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Twitter.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Twitter.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Twitter.vue?vue&type=template&id=07e6e1f8&\"\nimport script from \"./Twitter.vue?vue&type=script&lang=ts&\"\nexport * from \"./Twitter.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"route-container\"},[_c('Header'),_c('main',[_c('Navigation'),_vm._m(0)],1)],1)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"d-flex justify-center align-center w-100\"},[_c('div',{staticClass:\"d-flex justify-center align-center flex-column\"},[_c('h1',[_vm._v(\"Not Found, or Under Development...\")]),_c('span',{staticClass:\"mt-4 text--text text--darken-1\"},[_vm._v(\"お探しのページは存在しないか、鋭意開発中です。\")])])])}]\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Header from '@/components/Header.vue';\nimport Navigation from '@/components/Navigation.vue';\n\nexport default Vue.extend({\n name: 'Home',\n components: {\n Header,\n Navigation,\n },\n});\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--15-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./NotFound.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--15-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./NotFound.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./NotFound.vue?vue&type=template&id=161dd190&\"\nimport script from \"./NotFound.vue?vue&type=script&lang=ts&\"\nexport * from \"./NotFound.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","\nimport Vue from 'vue';\nimport VueRouter from 'vue-router';\n\nimport TVHome from '@/views/TV/Home.vue';\nimport TVWatch from '@/views/TV/Watch.vue';\nimport SettingsGeneral from '@/views/Settings/General.vue';\nimport SettingsAccount from '@/views/Settings/Account.vue';\nimport SettingsJikkyo from '@/views/Settings/Jikkyo.vue';\nimport SettingsTwitter from '@/views/Settings/Twitter.vue';\nimport NotFound from '@/views/NotFound.vue';\n\nVue.use(VueRouter);\n\nconst routes = [\n {\n path: '/',\n redirect: '/tv/',\n },\n {\n path: '/tv/',\n name: 'TV Home',\n component: TVHome,\n },\n {\n path: '/tv/watch/:channel_id',\n name: 'TV Watch',\n component: TVWatch,\n },\n {\n path: '/settings/',\n redirect: '/settings/general',\n },\n {\n path: '/settings/general',\n name: 'Settings General',\n component: SettingsGeneral,\n },\n {\n path: '/settings/account',\n name: 'Settings Account',\n component: SettingsAccount,\n },\n {\n path: '/settings/jikkyo',\n name: 'Settings Jikkyo',\n component: SettingsJikkyo,\n },\n {\n path: '/settings/twitter',\n name: 'Settings Twitter',\n component: SettingsTwitter,\n },\n {\n path: '*',\n name: 'NotFound',\n component: NotFound,\n },\n];\n\nconst router = new VueRouter({\n mode: 'history',\n base: process.env.BASE_URL,\n routes,\n});\n\nexport default router;\n","/* eslint-disable no-console */\n\nimport { register } from 'register-service-worker';\n\nif (process.env.NODE_ENV === 'production') {\n register(`${process.env.BASE_URL}service-worker.js`, {\n ready () {\n console.log(\n 'App is being served from cache by a service worker.\\n' +\n 'For more details, visit https://goo.gl/AFskqB'\n )\n },\n registered () {\n console.log('Service worker has been registered.')\n },\n cached () {\n console.log('Content has been cached for offline use.')\n },\n updatefound () {\n console.log('New content is downloading.')\n },\n updated () {\n console.log('New content is available; please refresh.')\n },\n offline () {\n console.log('No internet connection found. App is running in offline mode.')\n },\n error (error) {\n console.error('Error during service worker registration:', error)\n }\n });\n}\n","\nimport axios from 'axios';\nimport { Icon } from '@iconify/vue2';\nimport Vue from 'vue';\nimport VueAxios from 'vue-axios';\nimport VueVirtualScroller from 'vue-virtual-scroller'\nimport 'vue-virtual-scroller/dist/vue-virtual-scroller.css'\nimport VTooltip from 'v-tooltip';\nimport 'v-tooltip/dist/v-tooltip.css'\n\nimport App from '@/App.vue';\nimport VTabItem from '@/components/VTabItem';\nimport VTabs from '@/components/VTabs';\nimport VTabsItems from '@/components/VTabsItems';\nimport vuetify from '@/plugins/vuetify';\nimport router from '@/router';\nimport '@/service-worker';\n\n// Production Tip を非表示に\nVue.config.productionTip = false;\n\n// Axios を使う\nVue.use(VueAxios, axios);\n\n// vue-virtual-scroller を使う\nVue.use(VueVirtualScroller)\n\n// VTooltip を使う\n// タッチデバイスでは無効化する\n// ref: https://v-tooltip.netlify.app/guide/config.html#default-values\nconst trigger = window.matchMedia('(hover: none)').matches ? [] : ['hover', 'focus', 'touch'];\nVTooltip.options.themes.tooltip.showTriggers = trigger;\nVTooltip.options.themes.tooltip.hideTriggers = trigger;\nVTooltip.options.themes.tooltip.delay.show = 0;\nVTooltip.options.offset = [0, 7];\nVue.use(VTooltip);\n\n// Iconify(アイコン)のグローバルコンポーネント\nVue.component('Icon', Icon);\n\n// VTabItem の挙動を改善するグローバルコンポーネント\nVue.component('v-tab-item-fix', VTabItem);\n\n// VTabs の挙動を改善するグローバルコンポーネント\nVue.component('v-tabs-fix', VTabs);\n\n// VTabsItems の挙動を改善するグローバルコンポーネント\nVue.component('v-tabs-items-fix', VTabsItems);\n\n// Vue を初期化\nnew Vue({\n router,\n vuetify,\n render: h => h(App),\n}).$mount('#app');\n","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Navigation.vue?vue&type=style&index=0&id=4fdece88&lang=scss&scoped=true&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Watch.vue?vue&type=style&index=1&id=8b237ea4&lang=scss&scoped=true&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Home.vue?vue&type=style&index=1&id=6a407b07&lang=scss&scoped=true&\""],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/components/TV/Comment.vue?68ee","webpack:///./src/components/TV/Channel.vue?922e","webpack:///./src/components/Header.vue?f201","webpack:///./src/components/TV/Channel.vue?1252","webpack:///./src/views/TV/Watch.vue?a2b7","webpack:///./src/App.vue?db16","webpack:///./src/views/Settings/Base.vue?c1da","webpack:///./src/views/TV/Home.vue?9a3c","webpack:///./src/components/TV/Program.vue?edba","webpack:///./src/App.vue?8c68","webpack:///./src/App.vue","webpack:///./src/components/VTabItem.ts","webpack:///./src/components/VTabsBar.ts","webpack:///./src/components/VTabs.ts","webpack:///./src/components/VTabsItems.ts","webpack:///./src/plugins/vuetify.ts","webpack:///./src/views/TV/Home.vue?71f5","webpack:///./src/components/Header.vue?9fbb","webpack:///./src/components/Header.vue","webpack:///./src/components/Navigation.vue?3b92","webpack:///./src/utils/Utils.ts","webpack:///./src/utils/TVUtils.ts","webpack:///./src/utils/index.ts","webpack:///./src/components/Navigation.vue","webpack:///./src/components/Navigation.vue?eebb","webpack:///./src/components/Navigation.vue?09b1","webpack:///./src/views/TV/Home.vue","webpack:///./src/views/TV/Home.vue?1322","webpack:///./src/views/TV/Home.vue?87a4","webpack:///./src/views/TV/Watch.vue?4d59","webpack:///./src/interface.ts","webpack:///./src/components/TV/Channel.vue?5c74","webpack:///./src/components/TV/Channel.vue","webpack:///./src/components/TV/Channel.vue?9e9d","webpack:///./src/components/TV/Channel.vue?755d","webpack:///./src/components/TV/Comment.vue?ea0f","webpack:///./src/components/TV/Comment.vue","webpack:///./src/components/TV/Comment.vue?5d0b","webpack:///./src/components/TV/Comment.vue?30a7","webpack:///./src/components/TV/Program.vue?0760","webpack:///./src/components/TV/Program.vue","webpack:///./src/components/TV/Program.vue?c0b3","webpack:///./src/components/TV/Program.vue?dfda","webpack:///./src/views/TV/Watch.vue","webpack:///./src/views/TV/Watch.vue?9221","webpack:///./src/views/TV/Watch.vue?b63e","webpack:///./src/views/Settings/General.vue?fbfa","webpack:///./src/views/Settings/Base.vue?e092","webpack:///./src/views/Settings/Base.vue","webpack:///./src/views/Settings/Base.vue?f52e","webpack:///./src/views/Settings/Base.vue?0d0c","webpack:///./src/views/Settings/General.vue","webpack:///./src/views/Settings/General.vue?18d7","webpack:///./src/views/Settings/General.vue?20a3","webpack:///./src/views/Settings/Account.vue?2b0d","webpack:///./src/views/Settings/Account.vue","webpack:///./src/views/Settings/Account.vue?641a","webpack:///./src/views/Settings/Account.vue?a4dd","webpack:///./src/views/Settings/Jikkyo.vue?ede7","webpack:///./src/views/Settings/Jikkyo.vue","webpack:///./src/views/Settings/Jikkyo.vue?e197","webpack:///./src/views/Settings/Jikkyo.vue?9f97","webpack:///./src/views/Settings/Twitter.vue?d285","webpack:///./src/views/Settings/Twitter.vue","webpack:///./src/views/Settings/Twitter.vue?b40c","webpack:///./src/views/Settings/Twitter.vue?2206","webpack:///./src/views/NotFound.vue?f769","webpack:///./src/views/NotFound.vue","webpack:///./src/views/NotFound.vue?a95e","webpack:///./src/views/NotFound.vue?7205","webpack:///./src/router/index.ts","webpack:///./src/service-worker.ts","webpack:///./src/main.ts","webpack:///./src/components/Navigation.vue?98cb","webpack:///./src/views/TV/Watch.vue?556d","webpack:///./src/views/TV/Home.vue?52ac"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","window","oldJsonpFunction","slice","_vm","this","_h","$createElement","_c","_self","attrs","staticRenderFns","script","component","VApp","VTabItem","extend","render","h","props","computedTransition","on","beforeEnter","onBeforeTransition","afterEnter","onAfterTransition","enterCancelled","onTransitionCancelled","beforeLeave","afterLeave","leaveCancelled","enter","onEnter","genWindowItem","VTabsBar","items","methods","register","item","activeItem","internalIndex","sort","a","b","index_a","$slots","default","findIndex","element","$vnode","index_b","$on","onClick","mandatory","selectedValues","updateMandatory","updateItem","indexOf","undefined","updateInternalValue","unregister","constructor","super","options","VTabs","genBar","slider","style","height","convertToUnit","activeClass","centerActive","dark","light","optional","mobileBreakpoint","nextIcon","prevIcon","showArrows","internalValue","callSlider","change","val","ref","setTextColor","computedColor","setBackgroundColor","backgroundColor","genSlider","VTabsItems","updateReverse","oldVal","itemsLength","lastIndex","continuous","Vue","use","Vuetify","theme","themes","primary","secondary","twitter","gray","black","background","base","lighten1","lighten2","lighten3","text","darken1","darken2","darken3","customProperties","staticClass","class","is_loading","model","callback","$$v","tab","expression","_l","Array","from","channels_list","channels_type","_v","_s","channels","channel","directives","rawName","id","Utils","channel_number","channel_name","TVUtils","getChannelForceType","channel_force","getAttribute","viewers","isPinnedChannel","channel_id","$event","preventDefault","stopPropagation","removePinnedChannel","addPinnedChannel","domProps","decorateProgramInfo","program_present","getProgramTime","program_following","getProgramProgress","staticStyle","_e","VBtn","VIcon","VSpacer","VToolbar","Ripple","version","background_count","random","Math","floor","toString","padStart","settings","JSON","parse","localStorage","getItem","default_settings","setItem","stringify","process","location","protocol","host","pinned_channel_ids","tv_streaming_quality","is_latest_panel_display","panel_display_state","panel_active_tab","comment_speed_rate","comment_font_size","comment_delay_time","program","mark","pattern1","RegExp","pattern2","replaced","replace","default_value","is_chideji","match","groups","channel_type","toUpperCase","remocon_id","index","getChannelType","previous_index","next_index","is_short","start_time","dayjs","locale","end_time","duration","format","progress","diff","components","Header","Navigation","interval_ids","Map","created","update","residue_second","Date","getTime","setTimeout","setInterval","beforeDestroy","interval_id","clearInterval","axios","api_base_url","channels_response","console","error","filter","is_display","GR","set","BS","CS","CATV","SKY","STARDIGIO","updatePinnedChannelList","getSettingsItem","setSettingsItem","is_update_tab","pinned_channels","pinned_channel_id","pinned_channel_type","find","has","includes","VTab","is_control_display","is_panel_display","is_fullscreen","controlDisplayTimer","modifiers","$route","params","time","is_background_display","backgroundImage","background_url","channel_previous","channel_next","player","shortcut_key_modal","shortcut_key_column","shortcut_key_column_name","shortcut_keys","icon","icon_height","shortcut","keys","IProgramDefault","service_id","network_id","event_id","title","description","detail","is_free","genre","video_type","video_codec","video_resolution","primary_audio_type","primary_audio_language","primary_audio_sampling_rate","secondary_audio_type","secondary_audio_language","secondary_audio_sampling_rate","IChannelDefault","transport_stream_id","channel_comment","is_subchannel","is_radiochannel","type","required","comment_list","scopedSlots","_u","fn","active","is_manual_scroll","scrollCommentList","is_auto_scrolling","comment_list_element","watch_session","comment_session","keep_seat_interval_id","resize_observer","resize_observer_element","destroy","unobserve","watch","new_channel","old_channel","Promise","resolve","$el","querySelector","is_user_scrolling","onmousedown","event","x","clientX","getBoundingClientRect","left","clientWidth","onmouseup","on_user_scrolling","is_dragging","ontouchstart","ontouchend","ontouchmove","onwheel","onscroll","scrollTop","offsetHeight","scrollHeight","initWatchSession","comment_session_info","initCommentSession","initReserveObserver","watch_session_info","Error","is_success","WebSocket","audience_token","addEventListener","send","message","threadId","yourPostKey","messageServer","uri","readyState","keepIntervalSec","code","log","danmaku","showing","notice","waitTimeSec","onclose","reason","disconnect_reason","comment_list_buffer","is_received_initial_comment","message_server","thread_id","your_post_key","event_raw","thread","resultcode","ping","content","comment","chat","yourpost","color","position","mail","command","split","getCommentColor","getCommentPosition","comment_dict","no","date","document","visibilityState","video","paused","draw","onvisibilitychange","animation_timeout_id","on_resize","video_element","comment_area_element","clientHeight","letter_box_height","threshold","matchMedia","matches","comment_area_vertical_margin","comment_area_width","comment_area_height","gcd","y","gcd_result","comment_area_height_aspect","transition","setProperty","clearTimeout","removeProperty","ResizeObserver","observe","smooth","scrollTo","top","behavior","color_table","close","genre_index","major","middle","detail_text","detail_heading","Channel","Comment","Program","control_interval_id","eventsource","fullscreen_handler","shortcut_key_handler","shortcut_key_pressed_at","now","shortcut_key_list","left_column","shortcuts","right_column","init","removeEventListener","beforeRouteUpdate","to","next","getPreviousAndCurrentAndNextChannel","generatePlayerBackgroundURL","channel_response","response","status","$router","path","KonomiTVCanDestroy","initPlayer","initEventHandler","initShortcutKeyHandler","template","audioItem","classList","add","plugins","mpegts","remove","audioValue","textContent","tran","switchPrimaryAudio","delete","navigator","artwork","src","sizes","mediaSession","metadata","MediaMetadata","artist","setPositionState","playbackRate","setActionHandler","play","pause","is_player_event","is_touch_device","test","userAgent","timeout","activeElement","commentInput","controller","hide","setting","isShow","show","DPlayer","container","lang","live","loop","airplay","autoplay","hotkey","screenshot","volume","defaultQuality","quality","qualities","url","speedRate","fontSize","apiBackend","read","success","pluginOptions","config","enableWorker","liveBufferLatencyChasing","liveBufferLatencyMaxLatency","liveBufferLatencyMinRemain","aribb24","normalFont","gaijiFont","forceStrokeColor","drcsReplacement","enableRawCanvas","useStrokeText","subtitle","setAutoHide","settingOriginPanel","insertAdjacentHTML","settingOriginPanelHeight","settingBox","clipPath","on_play_or_pause","aribb24Superimpose","buffered","end","currentTime","sync","fullscreen_container","fullScreen","isFullScreen","onfullscreenchange","fullscreenElement","webkitFullscreenElement","request","cancel","requestFullscreen","webkitRequestFullscreen","screen","orientation","lock","catch","exitFullscreen","webkitExitFullscreen","unlock","on_canplay","oncanplay","oncanplaythrough","quality_name","EventSource","clients_count","pictureInPictureElement","exitPictureInPicture","requestPictureInPicture","switchVideo","onerror","clear","is_repeat","repeat","tag","tagName","editable","switch_channel_type","shiftKey","switch_remocon_id","Number","switch_channel","getChannelFromRemoconID","ctrlKey","metaKey","toggle","pictureInPictureEnabled","pipButton","click","contains","showDanmaku","showDanmakuToggle","checked","focus","is_destroy_player","VCard","VCardActions","VCardTitle","VCol","VDialog","VDivider","VRow","$set","_t","VList","VListItem","VListItemContent","VListItemIcon","VListItemTitle","VNavigationDrawer","Base","deep","handler","entries","setting_key","setting_value","VSelect","VSlider","_m","VueRouter","routes","redirect","TVHome","TVWatch","SettingsGeneral","SettingsAccount","SettingsJikkyo","SettingsTwitter","NotFound","router","ready","registered","cached","updatefound","updated","offline","productionTip","VueAxios","VueVirtualScroller","trigger","VTooltip","tooltip","showTriggers","hideTriggers","delay","offset","Icon","vuetify","App","$mount"],"mappings":"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","file":"assets/js/app.bf991577.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t\"app\": 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([0,\"chunk-vendors\"]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Comment.vue?vue&type=style&index=0&id=7575b645&lang=scss&scoped=true&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Channel.vue?vue&type=style&index=0&lang=scss&\"","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Header.vue?vue&type=style&index=0&lang=scss&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Channel.vue?vue&type=style&index=1&id=691b389f&lang=scss&scoped=true&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Watch.vue?vue&type=style&index=0&lang=scss&\"","export * from \"-!../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../node_modules/cache-loader/dist/cjs.js??ref--1-0!../node_modules/vue-loader/lib/index.js??vue-loader-options!./App.vue?vue&type=style&index=0&lang=scss&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Base.vue?vue&type=style&index=0&id=18637a38&lang=scss&scoped=true&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Home.vue?vue&type=style&index=0&lang=scss&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Program.vue?vue&type=style&index=0&id=00e07beb&lang=scss&scoped=true&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('v-app',{attrs:{\"id\":\"app\"}},[_c('transition',[_c('router-view')],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./App.vue?vue&type=template&id=4cc455a4&\"\nvar script = {}\nimport style0 from \"./App.vue?vue&type=style&index=0&lang=scss&\"\n\n\n/* normalize component */\nimport normalizer from \"!../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VApp } from 'vuetify/lib/components/VApp';\ninstallComponents(component, {VApp})\n","\nimport { VueConstructor, VNode } from 'vue';\n\nimport VTabItem from 'vuetify/lib/components/VTabs/VTabItem';\n\n// VTabItem は VWindowItem を extend() して実装されている\nexport default (VTabItem as VueConstructor).extend({\n render (h): VNode {\n return h('transition', {\n props: {\n name: (this as any).computedTransition,\n },\n on: {\n // Handlers for enter windows.\n beforeEnter: (this as any).onBeforeTransition,\n afterEnter: (this as any).onAfterTransition,\n enterCancelled: (this as any).onTransitionCancelled,\n\n // Handlers for leave windows.\n beforeLeave: (this as any).onBeforeTransition,\n afterLeave: (this as any).onAfterTransition,\n leaveCancelled: (this as any).onTransitionCancelled,\n\n // Enter handler for height transition.\n enter: (this as any).onEnter,\n }\n // this.showLazyContent() を通さずに常にレンダリングされるようにする\n // 本来は実際に表示されている時だけレンダリングし、負荷を減らすための処理\n // ただチャンネルリストのレンダリングは重いので、最初からレンダリングされていた方がタブの初回切り替えが早くなる\n }, [(this as any).genWindowItem()]);\n }\n});\n","\nimport { VueConstructor } from 'vue';\n\nimport { GroupableInstance } from 'vuetify/lib/components/VItemGroup/VItemGroup';\nimport VTabsBar from 'vuetify/lib/components/VTabs/VTabsBar';\n\n// VTabsBar は VItemGroup を extend() して実装されている\nexport default (VTabsBar as VueConstructor).extend({\n data() {\n return {\n // 一応型定義をしておく\n items: [] as GroupableInstance[],\n }\n },\n methods: {\n\n // タブのデータ配列の先頭に新しい要素が追加されるとそのタブのアニメーションの向きが逆になるバグがあるので、VItemGroup 側の挙動をオーバーライドする\n // DOM 上も VNode 上も正しい順序で並んでいるが、this.items に関しては追加された順になっていてしまっていて齟齬が発生するのが原因\n // ref: https://github.com/vuetifyjs/vuetify/issues/13862\n register(item: GroupableInstance) {\n\n // 現在アクティブなタブの VueComponent を取得\n const activeItem = this.items[(this as any).internalIndex];\n\n // 要素を items に追加\n this.items.push(item);\n\n // this.$slots.default に VNode が、items には単に VueComponent が入っているので、事前に VNode の順番に合わせて並べ替える\n // こうすることで、追加された順ではなく元のデータ配列通りの順番になる\n this.items.sort((a, b) => {\n\n // VueComponent の key が一致する this.$slots.default 内の VNode を探す\n const index_a = this.$slots.default.findIndex((element) => {\n return a.$vnode.key === element.key;\n });\n const index_b = this.$slots.default.findIndex((element) => {\n return b.$vnode.key === element.key;\n });\n\n // index 順で並び替え\n return index_a - index_b;\n });\n\n item.$on('change', () => (this as any).onClick(item));\n if ((this as any).mandatory && !(this as any).selectedValues.length) {\n (this as any).updateMandatory();\n }\n\n // 追加された要素のソート後のインデックスを取得して更新する\n (this as any).updateItem(item, this.items.indexOf(item));\n\n // ソート後の現在アクティブなタブのインデックスを取得し直し、設定する\n // 配列の末尾以外に追加された場合はインデックスが1つずつずれてしまうため、インデックスを設定し直す必要がある\n if (activeItem !== undefined) {\n (this as any).updateInternalValue(this.items.indexOf(activeItem));\n }\n },\n\n unregister(item: GroupableInstance) {\n\n // 現在アクティブなタブの VueComponent を取得\n const activeItem = this.items[(this as any).internalIndex];\n\n // 継承元の unregister() の処理を呼び出す(いわゆる super() )\n // ref: https://github.com/vuejs/vue/issues/2977\n (this.constructor as any).super.options.methods.unregister.call(this, item);\n\n // 配列の末尾以外から削除された場合はインデックスが1つずつずれてしまうため、インデックスを設定し直す必要がある\n if (activeItem !== undefined) {\n (this as any).updateInternalValue(this.items.indexOf(activeItem));\n }\n }\n }\n});\n","\nimport { VueConstructor, VNode } from 'vue';\n\nimport { convertToUnit } from 'vuetify/lib/util/helpers'\nimport VTabs from 'vuetify/lib/components/VTabs/VTabs';\nimport VTabsBar from '@/components/VTabsBar';\n\nexport default (VTabs as VueConstructor).extend({\n methods: {\n\n // VTabsBar は VTabs から暗黙的に生成されるコンポーネントのため、直接上書きすることができない\n // そこで VTabs 自体も上書きし、VTabs で $createElement() される時の VTabsBar を自前でオーバーライドしたものに差し替える\n // ビルド済みのファイルには型定義が入っていないので any を多用せざるを得ない…\n genBar(items: VNode[], slider: VNode | null) {\n const data = {\n style: {\n height: convertToUnit((this as any).height),\n },\n props: {\n activeClass: (this as any).activeClass,\n centerActive: (this as any).centerActive,\n dark: (this as any).dark,\n light: (this as any).light,\n mandatory: !(this as any).optional,\n mobileBreakpoint: (this as any).mobileBreakpoint,\n nextIcon: (this as any).nextIcon,\n prevIcon: (this as any).prevIcon,\n showArrows: (this as any).showArrows,\n value: (this as any).internalValue,\n },\n on: {\n 'call:slider': (this as any).callSlider,\n change: (val: any) => {\n (this as any).internalValue = val;\n },\n },\n ref: 'items',\n };\n\n (this as any).setTextColor((this as any).computedColor, data);\n (this as any).setBackgroundColor((this as any).backgroundColor, data);\n\n // ここでオーバーライドした VTabsBar を使うのが最重要\n // これをやるためだけにわざわざ VTabs に関してもオーバーライドする羽目になってる…\n return (this as any).$createElement(VTabsBar, data, [\n (this as any).genSlider(slider),\n items,\n ]);\n }\n }\n});\n","\nimport { VueConstructor } from 'vue';\n\nimport { GroupableInstance } from 'vuetify/lib/components/VItemGroup/VItemGroup';\nimport VTabsItems from 'vuetify/lib/components/VTabs/VTabsItems';\n\n// VTabsItems は VItemGroup と VWindow を extend() して実装されている\nexport default (VTabsItems as VueConstructor).extend({\n data() {\n return {\n // 一応型定義をしておく\n items: [] as GroupableInstance[],\n }\n },\n methods: {\n\n // タブのデータ配列の先頭に新しい要素が追加されるとそのタブのアニメーションの向きが逆になるバグがあるので、VItemGroup 側の挙動をオーバーライドする\n // DOM 上も VNode 上も正しい順序で並んでいるが、this.items に関しては追加された順になっていてしまっていて齟齬が発生するのが原因\n // ref: https://github.com/vuetifyjs/vuetify/issues/13862\n register(item: GroupableInstance) {\n\n // 現在アクティブなタブの VueComponent を取得\n const activeItem = this.items[(this as any).internalIndex];\n\n // 要素を items に追加\n this.items.push(item);\n\n // this.$slots.default に VNode が、items には単に VueComponent が入っているので、事前に VNode の順番に合わせて並べ替える\n // こうすることで、追加された順ではなく元のデータ配列通りの順番になる\n this.items.sort((a, b) => {\n\n // VueComponent の key が一致する this.$slots.default 内の VNode を探す\n const index_a = this.$slots.default.findIndex((element) => {\n return a.$vnode.key === element.key;\n });\n const index_b = this.$slots.default.findIndex((element) => {\n return b.$vnode.key === element.key;\n });\n\n // index 順で並び替え\n return index_a - index_b;\n });\n\n item.$on('change', () => (this as any).onClick(item));\n if ((this as any).mandatory && !(this as any).selectedValues.length) {\n (this as any).updateMandatory();\n }\n\n // 追加された要素のソート後のインデックスを取得して更新する\n (this as any).updateItem(item, this.items.indexOf(item));\n\n // ソート後の現在アクティブなタブのインデックスを取得し直し、設定する\n // 配列の末尾以外に追加された場合はインデックスが1つずつずれてしまうため、インデックスを設定し直す必要がある\n if (activeItem !== undefined) {\n // 値が異なるときだけ更新する\n // こうしないと、Safari で変なアニメーションがついてしまう\n if (this.items.indexOf(activeItem) !== (this as any).internalValue) {\n (this as any).updateInternalValue(this.items.indexOf(activeItem));\n }\n }\n },\n\n unregister(item: GroupableInstance) {\n\n // 現在アクティブなタブの VueComponent を取得\n const activeItem = this.items[(this as any).internalIndex];\n\n // 継承元の unregister() の処理を呼び出す(いわゆる super() )\n // ref: https://github.com/vuejs/vue/issues/2977\n (this.constructor as any).super.options.methods.unregister.call(this, item);\n\n // 配列の末尾以外から削除された場合はインデックスが1つずつずれてしまうため、インデックスを設定し直す必要がある\n if (activeItem !== undefined) {\n (this as any).updateInternalValue(this.items.indexOf(activeItem));\n }\n },\n\n // 最初のタブから最後のタブに遷移するとアニメーションの向きが逆になるバグがあるので、VWindow 側の挙動をオーバーライドする\n // 本来は VCarousel 用の動作だが、VTabsItems も VWindow を継承しているので、それが適用されてしまっているらしい\n // ref: https://github.com/yuwu9145/vuetify/blob/master/packages/vuetify/src/components/VWindow/VWindow.ts#L239-L252\n updateReverse(val: number, oldVal: number) {\n\n const itemsLength = this.items.length;\n const lastIndex = itemsLength - 1;\n\n if (itemsLength <= 2) return val < oldVal;\n\n // continuous が false の時、常に val < oldVal の結果を返す\n if (!(this as any).continuous) return val < oldVal;\n\n if (val === lastIndex && oldVal === 0) {\n return true;\n } else if (val === 0 && oldVal === lastIndex) {\n return false;\n } else {\n return val < oldVal;\n }\n }\n }\n});\n","\nimport Vue from 'vue';\nimport Vuetify from 'vuetify/lib/framework';\n\nVue.use(Vuetify);\n\nexport default new Vuetify({\n theme: {\n dark: true,\n themes: {\n dark: {\n primary: '#E64F97',\n secondary: '#E64F97',\n twitter: '#4F82E6',\n gray: '#66514C',\n black: '#110A09',\n background: {\n base: '#1E1310',\n lighten1: '#2F221F',\n lighten2: '#433532',\n lighten3: '#4c3c38',\n },\n text: {\n base: '#FFEAEA',\n darken1: '#D9C7C7',\n darken2: '#8E7F7E',\n darken3: '#786968',\n }\n }\n },\n options: {\n customProperties: true,\n },\n },\n});\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"route-container\"},[_c('Header'),_c('main',[_c('Navigation'),_c('div',{staticClass:\"channels-container channels-container--home\",class:{'channels-container--loading': _vm.is_loading}},[_c('v-tabs-fix',{staticClass:\"channels-tab\",attrs:{\"centered\":\"\"},model:{value:(_vm.tab),callback:function ($$v) {_vm.tab=$$v},expression:\"tab\"}},_vm._l((Array.from(_vm.channels_list)),function(ref){\nvar channels_type = ref[0];\nreturn _c('v-tab',{key:channels_type,staticClass:\"channels-tab__item\"},[_vm._v(_vm._s(channels_type))])}),1),_c('v-tabs-items-fix',{staticClass:\"channels-list\",model:{value:(_vm.tab),callback:function ($$v) {_vm.tab=$$v},expression:\"tab\"}},_vm._l((Array.from(_vm.channels_list)),function(ref){\nvar channels_type = ref[0];\nvar channels = ref[1];\nreturn _c('v-tab-item-fix',{key:channels_type,staticClass:\"channels-tabitem\"},[_c('div',{staticClass:\"channels\",class:(\"channels--tab-\" + channels_type + \" channels--length-\" + (channels.length))},[_vm._l((channels),function(channel){return _c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],key:channel.id,staticClass:\"channel\",attrs:{\"to\":(\"/tv/watch/\" + (channel.channel_id))}},[_c('div',{staticClass:\"channel__broadcaster\"},[_c('img',{staticClass:\"channel__broadcaster-icon\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + (channel.channel_id) + \"/logo\")}}),_c('div',{staticClass:\"channel__broadcaster-content\"},[_c('span',{staticClass:\"channel__broadcaster-name\"},[_vm._v(\"Ch: \"+_vm._s(channel.channel_number)+\" \"+_vm._s(channel.channel_name))]),_c('div',{staticClass:\"channel__broadcaster-status\"},[_c('div',{staticClass:\"channel__broadcaster-status-force\",class:(\"channel__broadcaster-status-force--\" + (_vm.TVUtils.getChannelForceType(channel.channel_force)))},[_c('Icon',{attrs:{\"icon\":\"fa-solid:fire-alt\",\"height\":\"12px\"}}),_c('span',{staticClass:\"ml-1\"},[_vm._v(\"勢い:\")]),_c('span',{staticClass:\"ml-1\"},[_vm._v(_vm._s(_vm.TVUtils.getAttribute(channel, 'channel_force', '--'))+\" コメ/分\")])],1),_c('div',{staticClass:\"channel__broadcaster-status-viewers ml-4\"},[_c('Icon',{attrs:{\"icon\":\"fa-solid:eye\",\"height\":\"14px\"}}),_c('span',{staticClass:\"ml-1\"},[_vm._v(\"視聴数:\")]),_c('span',{staticClass:\"ml-1\"},[_vm._v(_vm._s(channel.viewers))])],1)])]),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip\",value:(_vm.isPinnedChannel(channel.channel_id) ? 'ピン留めを外す' : 'ピン留めする'),expression:\"isPinnedChannel(channel.channel_id) ? 'ピン留めを外す' : 'ピン留めする'\"}],staticClass:\"channel__broadcaster-pin\",class:{'channel__broadcaster-pin--pinned': _vm.isPinnedChannel(channel.channel_id)},on:{\"click\":function($event){$event.preventDefault();$event.stopPropagation();_vm.isPinnedChannel(channel.channel_id) ? _vm.removePinnedChannel(channel.channel_id) : _vm.addPinnedChannel(channel.channel_id)},\"mousedown\":function($event){$event.preventDefault();$event.stopPropagation();/* 親要素の波紋が広がらないように */}}},[_c('Icon',{attrs:{\"icon\":\"fluent:pin-20-filled\",\"width\":\"24px\"}})],1)]),_c('div',{staticClass:\"channel__program-present\"},[_c('span',{staticClass:\"channel__program-present-title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_present, 'title'))}}),_c('span',{staticClass:\"channel__program-present-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(channel.program_present)))]),_c('span',{staticClass:\"channel__program-present-description\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_present, 'description'))}})]),_c('v-spacer'),_c('div',{staticClass:\"channel__program-following\"},[_c('div',{staticClass:\"channel__program-following-title\"},[_c('span',{staticClass:\"channel__program-following-title-decorate\"},[_vm._v(\"NEXT\")]),_c('Icon',{staticClass:\"channel__program-following-title-icon\",attrs:{\"icon\":\"fluent:fast-forward-20-filled\",\"width\":\"16px\"}}),_c('span',{staticClass:\"channel__program-following-title-text\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_following, 'title'))}})],1),_c('span',{staticClass:\"channel__program-following-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(channel.program_following)))])]),_c('div',{staticClass:\"channel__progressbar\"},[_c('div',{staticClass:\"channel__progressbar-progress\",style:((\"width:\" + (_vm.TVUtils.getProgramProgress(channel.program_present)) + \"%;\"))})])],1)}),(channels_type === 'ピン留め' && channels.length === 0)?_c('div',{staticClass:\"d-flex justify-center align-center w-100\"},[_c('div',{staticClass:\"d-flex justify-center align-center flex-column\"},[_c('h2',[_vm._v(\"ピン留めされているチャンネルがありません。\")]),_c('div',{staticClass:\"mt-4 text--text text--darken-1\"},[_vm._v(\"各チャンネルの \"),_c('Icon',{staticStyle:{\"position\":\"relative\",\"bottom\":\"-5px\"},attrs:{\"icon\":\"fluent:pin-20-filled\",\"width\":\"22px\"}}),_vm._v(\" アイコンから、よくみるチャンネルをこのタブにピン留めできます。\")],1),_c('div',{staticClass:\"mt-2 text--text text--darken-1\"},[_vm._v(\"チャンネルをピン留めすると、このタブが最初に表示されます。\")])])]):_vm._e()],2)])}),1)],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('v-toolbar',{staticClass:\"header\",attrs:{\"absolute\":\"\",\"color\":\"background\",\"elevation\":\"8\",\"width\":\"100%\"}},[_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"logo ml-3 ml-md-6\",attrs:{\"to\":\"/tv/\"}},[_c('img',{staticClass:\"logo__image\",attrs:{\"src\":\"/assets/img/logo.svg\",\"height\":\"21\"}})]),_c('v-spacer'),_c('v-btn',{staticClass:\"mr-3 mr-md-6\",attrs:{\"icon\":\"\"}},[_c('v-icon',[_vm._v(\"mdi-dots-vertical\")])],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./Header.vue?vue&type=template&id=04bd7f60&\"\nvar script = {}\nimport style0 from \"./Header.vue?vue&type=style&index=0&lang=scss&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VBtn } from 'vuetify/lib/components/VBtn';\nimport { VIcon } from 'vuetify/lib/components/VIcon';\nimport { VSpacer } from 'vuetify/lib/components/VGrid';\nimport { VToolbar } from 'vuetify/lib/components/VToolbar';\ninstallComponents(component, {VBtn,VIcon,VSpacer,VToolbar})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"navigation-container elevation-8\"},[_c('nav',{staticClass:\"navigation\"},[_c('div',{staticClass:\"navigation-scroll\"},[_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/tv/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:tv-20-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"テレビをみる\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/videos/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:movies-and-tv-20-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"ビデオをみる\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/schedules/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:calendar-ltr-20-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"番組表\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/captures/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:image-multiple-24-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"キャプチャ\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/watchlists/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"ic:round-playlist-play\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"ウォッチリスト\")])],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/histories/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:history-16-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"視聴履歴\")])],1),_c('v-spacer'),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"to\":\"/settings/\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:settings-20-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"設定\")])],1),_c('a',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"navigation__link\",attrs:{\"active-class\":\"navigation__link--active\",\"href\":\"https://github.com/tsukumijima/KonomiTV\"}},[_c('Icon',{staticClass:\"navigation__link-icon\",attrs:{\"icon\":\"fluent:info-16-regular\",\"width\":\"26px\"}}),_c('span',{staticClass:\"navigation__link-text\"},[_vm._v(\"version \"+_vm._s(_vm.Utils.version))])],1)],1)])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n/**\n * 共通ユーティリティ\n */\nexport default class Utils {\n\n // バージョン情報\n // ビルド時の環境変数 (vue.config.js に記載) から取得\n static readonly version:string = process.env.VUE_APP_VERSION;\n\n // バックエンドの API のベース URL\n static readonly api_base_url = (() => {\n if (process.env.NODE_ENV === 'development') {\n // デバッグ時はポートを 7000 に強制する\n return `${window.location.protocol}//${window.location.hostname}:7000/api`;\n } else {\n // ビルド後は同じポートを使う\n return `${window.location.protocol}//${window.location.host}/api`;\n }\n })();\n\n // デフォルトの設定値\n static readonly default_settings = {\n\n // ピン留めしているチャンネルの ID (ex: gr011) が入るリスト\n pinned_channel_ids: [] as string[],\n\n // テレビのストリーミング画質(1080p)\n tv_streaming_quality: '1080p' as ('1080p' | '810p' | '720p' | '540p' | '480p' | '360p' | '240p'),\n\n // 前回視聴画面を開いた際にパネルが表示されていたかどうか\n is_latest_panel_display: true as boolean,\n\n // 既定のパネルの表示状態(前回の状態を復元する)\n panel_display_state: 'RestorePreviousState' as ('RestorePreviousState' | 'AlwaysDisplay' | 'AlwaysFold'),\n\n // 既定で表示されるパネルのタブ(番組情報タブ)\n panel_active_tab: 'Program' as ('Program' | 'Channel' | 'Comment' | 'Twitter'),\n\n // コメントの速さ (1倍)\n comment_speed_rate: 1 as number,\n\n // コメントのフォントサイズ (34px)\n comment_font_size: 34 as number,\n\n // コメントの遅延時間 (1秒)\n comment_delay_time: 1 as number,\n };\n\n\n /**\n * プレイヤーの背景画像をランダムで取得し、その URL を返す\n * @returns ランダムで設定されたプレイヤーの背景画像の URL\n */\n static generatePlayerBackgroundURL(): string {\n const background_count = 12; // 12種類から選択\n const random = (Math.floor(Math.random() * background_count) + 1);\n return `/assets/img/player-backgrounds/${random.toString().padStart(2, '0')}.jpg`;\n }\n\n\n /**\n * 設定を LocalStorage から取得する\n * @param key 設定のキー名\n * @returns 設定されている値\n */\n static getSettingsItem(key: string): any | null {\n\n // LocalStorage から KonomiTV-Settings を取得\n // データは JSON で管理し、LocalStorage 上の一つのキーにまとめる\n // キーが存在しない場合はデフォルトの設定値を使う\n const settings:object = JSON.parse(localStorage.getItem('KonomiTV-Settings')) || Utils.default_settings;\n\n // そのキーが保存されているときだけ、設定値を返す\n if (key in settings) {\n return settings[key];\n } else {\n // デフォルトの設定値にあればそれを使う\n if (key in this.default_settings) {\n return this.default_settings[key];\n } else {\n return null;\n }\n }\n }\n\n\n /**\n * 設定を LocalStorage に保存する\n * @param key 設定のキー名\n * @param value 設定する値\n */\n static setSettingsItem(key: string, value: any): void {\n\n // LocalStorage から KonomiTV-Settings を取得\n const settings:object = JSON.parse(localStorage.getItem('KonomiTV-Settings')) || Utils.default_settings;\n\n // そのキーがデフォルトの設定値に定義されているときだけ\n // バージョン違いなどで settings には登録されていないキーだが default_settings には登録されているケースが発生し得るため\n if (key in this.default_settings) {\n\n // 設定値を新しい値で置き換え\n settings[key] = value;\n\n // LocalStorage に保存\n localStorage.setItem('KonomiTV-Settings', JSON.stringify(settings));\n }\n }\n}\n","\nimport dayjs from 'dayjs';\nimport 'dayjs/locale/ja';\n\nimport { IChannel, IProgram } from '@/interface';\n\n/**\n * TV 機能のユーティリティ\n */\nexport class TVUtils {\n\n /**\n * 番組情報中の[字]や[解]などの記号をいい感じに装飾する\n * @param program 番組情報のオブジェクト\n * @param key 番組情報のオブジェクトから取り出すプロパティのキー\n * @returns 装飾した文字列\n */\n static decorateProgramInfo(program: IProgram, key: string): string {\n\n // program が空でないかつ、program[key] が存在する\n if (program !== null && program[key] !== null) {\n\n // 本来 ARIB 外字である記号の一覧\n // ref: https://ja.wikipedia.org/wiki/%E7%95%AA%E7%B5%84%E8%A1%A8\n // ref: https://github.com/xtne6f/EDCB/blob/work-plus-s/EpgDataCap3/EpgDataCap3/ARIB8CharDecode.cpp#L1319\n const mark = '新|終|再|交|映|手|声|多|副|字|文|CC|OP|二|S|B|SS|無|無料' +\n 'C|S1|S2|S3|MV|双|デ|D|N|W|P|H|HV|SD|天|解|料|前|後初|生|販|吹|PPV|' +\n '演|移|他|収|・|英|韓|中|字/日|字/日英|3D|2K|4K|8K|5.1|7.1|22.2|60P|120P|d|HC|HDR|SHV|UHD|VOD|配|初';\n\n // 正規表現を作成\n const pattern1 = new RegExp(`\\\\((二|字|再)\\\\)`, 'g'); // 通常の括弧で囲まれている記号\n const pattern2 = new RegExp(`\\\\[(${mark})\\\\]`, 'g');\n\n // 正規表現で置換した結果を返す\n let replaced = program[key].replace(pattern1, '$1');\n replaced = replaced.replace(pattern2, '$1');\n return replaced;\n\n // 放送休止中\n } else {\n return key == 'title' ? '放送休止': 'この時間は放送を休止しています。';\n }\n }\n\n\n /**\n * オブジェクトからプロパティを取得し、もしプロパティが存在しなければ代替値を返す\n * @param items 対象のオブジェクト\n * @param key オブジェクトから取り出すプロパティのキー\n * @param default_value 取得できなかった際の代替値\n * @returns オブジェクト取得した値 or 代替値\n */\n static getAttribute(items: {[key: string]: any}, key: string, default_value: any): any {\n\n // items が空でないかつ、items[key] が存在する\n if (items !== null && items[key] !== undefined && items[key] !== null) {\n\n // items[key] の内容を返す\n return items[key];\n\n // 指定された代替値を返す\n } else {\n return default_value;\n }\n }\n\n\n /**\n * チャンネル ID からチャンネルタイプを取得する\n * @param channel_id チャンネル ID\n * @param is_chideji GR を「地デジ」と表記するかどうか\n * @returns チャンネルタイプ\n */\n static getChannelType(channel_id: string, is_chideji: boolean = false): string {\n const result = channel_id.match('(?[a-z]+)[0-9]+').groups.channel_type.toUpperCase();\n if (result === 'GR' && is_chideji) {\n return '地デジ';\n } else {\n return result;\n }\n }\n\n\n /**\n * チャンネルの実況勢いから「多」「激多」「祭」を取得する\n * ref: https://ja.wikipedia.org/wiki/%E3%83%8B%E3%82%B3%E3%83%8B%E3%82%B3%E5%AE%9F%E6%B3%81\n * @param channel_force チャンネルの実況勢い\n * @returns normal(普通)or many(多)or so-many(激多)or festival(祭)\n */\n static getChannelForceType(channel_force: number | null): 'normal' | 'many' | 'so-many' | 'festival' {\n\n // 実況勢いが null(=対応する実況チャンネルがない)\n if (channel_force === null) return 'normal';\n\n // 実況勢いが 1000 コメント以上(祭)\n if (channel_force >= 1000) return 'festival';\n // 実況勢いが 200 コメント以上(激多)\n if (channel_force >= 200) return 'so-many';\n // 実況勢いが 100 コメント以上(多)\n if (channel_force >= 100) return 'many';\n\n // それ以外\n return 'normal';\n }\n\n\n /**\n * チャンネルタイプとリモコン番号からチャンネル情報を取得する\n * @param channels_list チャンネルリスト\n * @param channel_type チャンネルタイプ\n * @param remocon_id リモコン番号\n * @returns チャンネル情報\n */\n static getChannelFromRemoconID(channels_list: Map, channel_type: string, remocon_id: number): IChannel | null {\n\n // 指定されたチャンネルタイプのチャンネルを取得\n channel_type = channel_type.replace('GR', '地デジ'); //「GR」は「地デジ」に置換しておく\n const channels = channels_list.get(channel_type);\n\n // リモコン番号が一致するチャンネルを見つけ、一番最初に見つかったものを返す\n for (let index = 0; index < channels.length; index++) {\n const channel = channels[index];\n if (channel.remocon_id === remocon_id) {\n return channel;\n }\n }\n\n // リモコン番号が一致するチャンネルを見つけられなかった\n return null;\n }\n\n\n /**\n * 前・現在・次のチャンネル情報を取得する\n * @param channels_list チャンネルリスト\n * @param channel_id 起点にする現在のチャンネル ID\n * @returns 前・現在・次のチャンネル情報\n */\n static getPreviousAndCurrentAndNextChannel(channels_list: Map, channel_id: string): IChannel[] {\n\n // 前後のチャンネルを取得\n const channels = channels_list.get(this.getChannelType(channel_id, true));\n for (let index = 0; index < channels.length; index++) {\n const element = channels[index];\n\n // チャンネル ID が一致したときだけ\n if (element.channel_id === channel_id) {\n\n // インデックスが最初か最後の時はそれぞれ最後と最初にインデックスを一周させる\n let previous_index = index - 1;\n if (previous_index === -1) previous_index = channels.length - 1;\n let next_index = index + 1;\n if (next_index === channels.length) next_index = 0;\n\n // 前・現在・次のチャンネル情報を返す\n return [channels[previous_index], channels[index], channels[next_index]];\n }\n }\n }\n\n\n /**\n * 番組の放送時刻を取得する\n * @param program 番組情報\n * @param is_short 時刻のみ返すかどうか\n * @returns 番組の放送時刻\n */\n static getProgramTime(program: IProgram, is_short: boolean = false): string {\n\n // program が空でなく、かつ番組時刻が初期値でない\n if (program !== null && program.start_time !== '2000-01-01T00:00:00+09:00') {\n\n // dayjs で日付を扱いやすく\n dayjs.locale('ja'); // ロケールを日本に設定\n const start_time = dayjs(program.start_time);\n const end_time = dayjs(program.end_time);\n const duration = program.duration / 60; // 分換算\n\n // 時刻のみ返す\n if (is_short === true) { // 時刻のみ\n return `${start_time.format('HH:mm')} ~ ${end_time.format('HH:mm')}`;\n // 通常\n } else {\n return `${start_time.format('YYYY/MM/DD (dd) HH:mm')} ~ ${end_time.format('HH:mm')} (${duration}分)`;\n }\n\n // 放送休止中\n } else {\n\n // 時刻のみ返す\n if (is_short === true) {\n return '--:-- ~ --:--';\n // 通常\n } else {\n return '----/--/-- (-) --:-- ~ --:-- (--分)';\n }\n }\n }\n\n\n /**\n * 番組の進捗状況を取得する\n * @param program 番組情報\n * @returns 番組の進捗状況(%単位)\n */\n static getProgramProgress(program: IProgram): number {\n\n // program が空でない\n if (program !== null) {\n\n // 番組開始時刻から何秒進んだか\n const progress = dayjs(dayjs()).diff(program.start_time, 'second');\n\n // %単位の割合を算出して返す\n return progress / program.duration * 100;\n\n // 放送休止中\n } else {\n return 0;\n }\n }\n}\n","\n// 共通ユーティリティをデフォルトとしてインポート\nimport Utils from '@/utils/Utils';\nexport default Utils;\n\n// Utils フォルダ配下のユーティリティを一括でインポートできるように\nexport * from '@/utils/TVUtils';\n","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'Navigation',\n data() {\n return {\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n }\n }\n});\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--15-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Navigation.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--15-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Navigation.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Navigation.vue?vue&type=template&id=4fdece88&scoped=true&\"\nimport script from \"./Navigation.vue?vue&type=script&lang=ts&\"\nexport * from \"./Navigation.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Navigation.vue?vue&type=style&index=0&id=4fdece88&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"4fdece88\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VSpacer } from 'vuetify/lib/components/VGrid';\ninstallComponents(component, {VSpacer})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport { IChannel } from '@/interface';\nimport Header from '@/components/Header.vue';\nimport Navigation from '@/components/Navigation.vue';\nimport Utils, { TVUtils } from '@/utils';\n\nexport default Vue.extend({\n name: 'Home',\n components: {\n Header,\n Navigation,\n },\n data() {\n return {\n\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n TVUtils: TVUtils,\n\n // タブの状態管理\n tab: null as number | null,\n\n // ローディング中かどうか\n is_loading: true,\n\n // インターバル ID\n // ページ遷移時に setInterval(), setTimeout() の実行を止めるのに使う\n // setInterval(), setTimeout() の返り値を登録する\n interval_ids: [] as number[],\n\n // チャンネル情報リスト\n channels_list: new Map() as Map,\n\n // ピン留めしているチャンネルの ID (ex: gr011) が入るリスト\n pinned_channel_ids: [] as string[],\n }\n },\n // 開始時に実行\n created() {\n\n // チャンネル情報を取得\n this.update();\n\n // 00秒までの残り秒数\n // 現在 16:01:34 なら 26 (秒) になる\n const residue_second = 60 - (Math.floor(new Date().getTime() / 1000) % 60);\n\n // 00秒になるまで待ってから\n // 番組は基本1分単位で組まれているため、20秒や45秒など中途半端な秒数で更新してしまうと反映が遅れてしまう\n this.interval_ids.push(window.setTimeout(() => {\n\n // チャンネル情報を更新\n this.update();\n\n // チャンネル情報を定期的に更新\n this.interval_ids.push(window.setInterval(() => {\n this.update();\n }, 30 * 1000)); // 30秒おき\n\n }, residue_second * 1000));\n },\n // 終了前に実行\n beforeDestroy() {\n\n // clearInterval() ですべての setInterval(), setTimeout() の実行を止める\n // clearInterval() と clearTimeout() は中身共通なので問題ない\n for (const interval_id of this.interval_ids) {\n window.clearInterval(interval_id);\n }\n },\n methods: {\n\n // チャンネル情報一覧を取得し、画面を更新する\n async update() {\n\n // チャンネル情報一覧 API にアクセス\n let channels_response;\n try {\n channels_response = await Vue.axios.get(`${Utils.api_base_url}/channels`);\n } catch (error) {\n console.error(error); // エラー内容を表示\n return;\n }\n\n // is_display が true のチャンネルのみに絞り込むフィルタ関数\n // 放送していないサブチャンネルを表示から除外する\n const filter = (channel: IChannel) => {\n return channel.is_display;\n }\n\n // チャンネルリストを再構築\n // 1つでもチャンネルが存在するチャンネルタイプのみ表示するように\n // たとえば SKY (スカパー!プレミアムサービス) のタブは SKY に属すチャンネルが1つもない(=受信できない)なら表示されない\n this.channels_list = new Map();\n if (channels_response.data.GR.length > 0) this.channels_list.set('地デジ', channels_response.data.GR.filter(filter));\n if (channels_response.data.BS.length > 0) this.channels_list.set('BS', channels_response.data.BS.filter(filter));\n if (channels_response.data.CS.length > 0) this.channels_list.set('CS', channels_response.data.CS.filter(filter));\n if (channels_response.data.CATV.length > 0) this.channels_list.set('CATV', channels_response.data.CATV.filter(filter));\n if (channels_response.data.SKY.length > 0) this.channels_list.set('SKY', channels_response.data.SKY.filter(filter));\n if (channels_response.data.STARDIGIO.length > 0) this.channels_list.set('StarDigio', channels_response.data.STARDIGIO.filter(filter));\n\n // ピン留めされているチャンネルのリストを更新\n this.updatePinnedChannelList(this.is_loading ? true : false);\n\n // ローディング状態を解除\n this.is_loading = false;\n },\n\n // チャンネルをピン留めする\n addPinnedChannel(channel_id: string) {\n\n // 現在ピン留めされているチャンネルを取得\n this.pinned_channel_ids = Utils.getSettingsItem('pinned_channel_ids');\n\n // ピン留めするチャンネルの ID を追加\n this.pinned_channel_ids.push(channel_id);\n\n // 設定を保存\n Utils.setSettingsItem('pinned_channel_ids', this.pinned_channel_ids);\n\n // ピン留めされているチャンネルのリストを更新\n this.updatePinnedChannelList();\n },\n\n // チャンネルをピン留めから外す\n removePinnedChannel(channel_id: string) {\n\n // 現在ピン留めされているチャンネルを取得\n this.pinned_channel_ids = Utils.getSettingsItem('pinned_channel_ids');\n\n // ピン留めを外すチャンネルの ID を削除\n this.pinned_channel_ids.splice(this.pinned_channel_ids.indexOf(channel_id), 1);\n\n // 設定を保存\n Utils.setSettingsItem('pinned_channel_ids', this.pinned_channel_ids);\n\n // ピン留めされているチャンネルのリストを更新\n this.updatePinnedChannelList();\n },\n\n // ピン留めされているチャンネルのリストを更新する\n updatePinnedChannelList(is_update_tab: boolean = true) {\n\n // ピン留めされているチャンネルの ID を取得\n this.pinned_channel_ids = Utils.getSettingsItem('pinned_channel_ids');\n\n // ピン留めされているチャンネル情報のリスト\n const pinned_channels = [] as IChannel[];\n\n // チャンネル ID が一致したチャンネルの情報を保存する\n for (const pinned_channel_id of this.pinned_channel_ids) {\n const pinned_channel_type = TVUtils.getChannelType(pinned_channel_id, true);\n pinned_channels.push(this.channels_list.get(pinned_channel_type).find((channel) => {\n return channel.channel_id === pinned_channel_id; // チャンネル ID がピン留めされているチャンネルのものと同じ\n }));\n }\n\n if (!this.channels_list.has('ピン留め')) {\n // タブの一番左にピン留めタブを表示する\n this.channels_list = new Map([['ピン留め', pinned_channels], ...this.channels_list]);\n } else {\n // 既に存在するピン留めタブにチャンネル情報を設定する\n this.channels_list.set('ピン留め', pinned_channels);\n }\n\n // pinned_channels が空の場合は、タブを地デジタブに変更\n // ピン留めができる事を示唆するためにピン留めタブ自体は残す\n if (pinned_channels.length === 0 && is_update_tab === true) {\n this.tab = 1;\n }\n },\n\n // チャンネルがピン留めされているか\n isPinnedChannel(channel_id: string): boolean {\n\n // 引数のチャンネルがピン留めリストに存在するかを返す\n return this.pinned_channel_ids.includes(channel_id);\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Home.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Home.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Home.vue?vue&type=template&id=6a407b07&scoped=true&\"\nimport script from \"./Home.vue?vue&type=script&lang=ts&\"\nexport * from \"./Home.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Home.vue?vue&type=style&index=0&lang=scss&\"\nimport style1 from \"./Home.vue?vue&type=style&index=1&id=6a407b07&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"6a407b07\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VSpacer } from 'vuetify/lib/components/VGrid';\nimport { VTab } from 'vuetify/lib/components/VTabs';\ninstallComponents(component, {VSpacer,VTab})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"route-container\"},[_c('main',{staticClass:\"watch-container\",class:{\n 'watch-container--control-display': _vm.is_control_display,\n 'watch-container--panel-display': _vm.is_panel_display,\n 'watch-container--fullscreen': _vm.is_fullscreen,\n }},[_c('nav',{staticClass:\"watch-navigation\",on:{\"mousemove\":function($event){return _vm.controlDisplayTimer($event)},\"touchmove\":function($event){return _vm.controlDisplayTimer($event)},\"click\":function($event){return _vm.controlDisplayTimer($event)}}},[_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"watch-navigation__icon\",attrs:{\"to\":\"/tv/\"}},[_c('img',{staticClass:\"watch-navigation__icon-image\",attrs:{\"src\":\"/assets/img/icon.svg\",\"width\":\"23px\"}})]),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('テレビをみる'),expression:\"'テレビをみる'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/tv/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:tv-20-regular\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('ビデオをみる'),expression:\"'ビデオをみる'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/videos/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:movies-and-tv-20-regular\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('番組表'),expression:\"'番組表'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/schedules/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:calendar-ltr-20-regular\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('キャプチャ'),expression:\"'キャプチャ'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/captures/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:image-multiple-24-regular\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('ウォッチリスト'),expression:\"'ウォッチリスト'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/watchlists/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"ic:round-playlist-play\",\"width\":\"26px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('視聴履歴'),expression:\"'視聴履歴'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/histories/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:history-16-regular\",\"width\":\"26px\"}})],1),_c('v-spacer'),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:('設定'),expression:\"'設定'\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"to\":\"/settings/\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:settings-20-regular\",\"width\":\"26px\"}})],1),_c('a',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.right\",value:((\"version \" + (_vm.Utils.version))),expression:\"`version ${Utils.version}`\",modifiers:{\"right\":true}}],staticClass:\"watch-navigation__link\",attrs:{\"active-class\":\"watch-navigation__link--active\",\"href\":\"https://github.com/tsukumijima/KonomiTV\"}},[_c('Icon',{staticClass:\"watch-navigation__link-icon\",attrs:{\"icon\":\"fluent:info-16-regular\",\"width\":\"26px\"}})],1)],1),_c('div',{staticClass:\"watch-content\",on:{\"mousemove\":function($event){return _vm.controlDisplayTimer($event, true)},\"touchmove\":function($event){return _vm.controlDisplayTimer($event, true)},\"click\":function($event){return _vm.controlDisplayTimer($event, true)}}},[_c('header',{staticClass:\"watch-header\"},[_c('img',{staticClass:\"watch-header__broadcaster\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + ((_vm.$route.params.channel_id)) + \"/logo\")}}),_c('span',{staticClass:\"watch-header__program-title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(_vm.channel.program_present, 'title'))}}),_c('span',{staticClass:\"watch-header__program-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(_vm.channel.program_present, true)))]),_c('v-spacer'),_c('span',{staticClass:\"watch-header__now\"},[_vm._v(_vm._s(_vm.time))])],1),_c('div',{staticClass:\"watch-player\",class:{'watch-player--loading': _vm.is_loading}},[_c('div',{staticClass:\"watch-player__background\",class:{'watch-player__background--display': _vm.is_background_display},style:({backgroundImage: (\"url(\" + _vm.background_url + \")\")})},[_c('img',{staticClass:\"watch-player__background-logo\",attrs:{\"src\":\"/assets/img/logo.svg\"}})]),_c('div',{staticClass:\"watch-player__dplayer\"}),_c('div',{staticClass:\"watch-player__button\",on:{\"mousemove\":function($event){return _vm.controlDisplayTimer($event)},\"touchmove\":function($event){return _vm.controlDisplayTimer($event)},\"click\":function($event){return _vm.controlDisplayTimer($event)}}},[_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.top\",value:('前のチャンネル'),expression:\"'前のチャンネル'\",modifiers:{\"top\":true}}],staticClass:\"switch-button switch-button-up\",attrs:{\"to\":(\"/tv/watch/\" + (_vm.channel_previous.channel_id))}},[_c('Icon',{staticClass:\"switch-button-icon\",attrs:{\"icon\":\"fluent:ios-arrow-left-24-filled\",\"width\":\"32px\",\"rotate\":\"1\"}})],1),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"switch-button switch-button-panel switch-button-panel--open\",on:{\"click\":function($event){_vm.is_panel_display = !_vm.is_panel_display}}},[_c('Icon',{staticClass:\"switch-button-icon\",attrs:{\"icon\":\"fluent:navigation-16-filled\",\"width\":\"32px\"}})],1),_c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"},{name:\"tooltip\",rawName:\"v-tooltip.bottom\",value:('次のチャンネル'),expression:\"'次のチャンネル'\",modifiers:{\"bottom\":true}}],staticClass:\"switch-button switch-button-down\",attrs:{\"to\":(\"/tv/watch/\" + (_vm.channel_next.channel_id))}},[_c('Icon',{staticClass:\"switch-button-icon\",attrs:{\"icon\":\"fluent:ios-arrow-right-24-filled\",\"width\":\"33px\",\"rotate\":\"1\"}})],1)],1)])]),_c('div',{staticClass:\"watch-panel\",on:{\"mousemove\":function($event){return _vm.controlDisplayTimer($event)},\"touchmove\":function($event){return _vm.controlDisplayTimer($event)},\"click\":function($event){return _vm.controlDisplayTimer($event)}}},[_c('div',{staticClass:\"watch-panel__header\"},[_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-close-button\",on:{\"click\":function($event){_vm.is_panel_display = false}}},[_c('Icon',{staticClass:\"panel-close-button__icon\",attrs:{\"icon\":\"akar-icons:chevron-right\",\"width\":\"25px\"}}),_c('span',{staticClass:\"panel-close-button__text\"},[_vm._v(\"閉じる\")])],1),_c('v-spacer'),_c('div',{staticClass:\"panel-broadcaster\"},[_c('img',{staticClass:\"panel-broadcaster__icon\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + ((_vm.$route.params.channel_id)) + \"/logo\")}}),_c('div',{staticClass:\"panel-broadcaster__number\"},[_vm._v(_vm._s(_vm.channel.channel_number))]),_c('div',{staticClass:\"panel-broadcaster__name\"},[_vm._v(_vm._s(_vm.channel.channel_name))])])],1),_c('div',{staticClass:\"watch-panel__content-container\"},[_c('Program',{staticClass:\"watch-panel__content\",class:{'watch-panel__content--active': _vm.panel_active_tab === 'Program'},attrs:{\"channel\":_vm.channel}}),_c('Channel',{staticClass:\"watch-panel__content\",class:{'watch-panel__content--active': _vm.panel_active_tab === 'Channel'},attrs:{\"channels_list\":_vm.channels_list}}),_c('Comment',{staticClass:\"watch-panel__content\",class:{'watch-panel__content--active': _vm.panel_active_tab === 'Comment'},attrs:{\"channel\":_vm.channel,\"player\":_vm.player}})],1),_c('div',{staticClass:\"watch-panel__navigation\"},[_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-navigation-button\",class:{'panel-navigation-button--active': _vm.panel_active_tab === 'Program'},on:{\"click\":function($event){_vm.panel_active_tab = 'Program'}}},[_c('Icon',{staticClass:\"panel-navigation-button__icon\",attrs:{\"icon\":\"fa-solid:info-circle\",\"width\":\"33px\"}}),_c('span',{staticClass:\"panel-navigation-button__text\"},[_vm._v(\"番組情報\")])],1),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-navigation-button\",class:{'panel-navigation-button--active': _vm.panel_active_tab === 'Channel'},on:{\"click\":function($event){_vm.panel_active_tab = 'Channel'}}},[_c('Icon',{staticClass:\"panel-navigation-button__icon\",attrs:{\"icon\":\"fa-solid:broadcast-tower\",\"width\":\"34px\"}}),_c('span',{staticClass:\"panel-navigation-button__text\"},[_vm._v(\"チャンネル\")])],1),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-navigation-button\",class:{'panel-navigation-button--active': _vm.panel_active_tab === 'Comment'},on:{\"click\":function($event){_vm.panel_active_tab = 'Comment'}}},[_c('Icon',{staticClass:\"panel-navigation-button__icon\",attrs:{\"icon\":\"bi:chat-left-text-fill\",\"width\":\"29px\"}}),_c('span',{staticClass:\"panel-navigation-button__text\"},[_vm._v(\"コメント\")])],1),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"panel-navigation-button\",class:{'panel-navigation-button--active': _vm.panel_active_tab === 'Twitter'},on:{\"click\":function($event){_vm.panel_active_tab = 'Twitter'}}},[_c('Icon',{staticClass:\"panel-navigation-button__icon\",attrs:{\"icon\":\"fa-brands:twitter\",\"width\":\"34px\"}}),_c('span',{staticClass:\"panel-navigation-button__text\"},[_vm._v(\"Twitter\")])],1)])])]),_c('v-dialog',{attrs:{\"max-width\":\"980\",\"transition\":\"slide-y-transition\"},model:{value:(_vm.shortcut_key_modal),callback:function ($$v) {_vm.shortcut_key_modal=$$v},expression:\"shortcut_key_modal\"}},[_c('v-card',[_c('v-card-title',{staticClass:\"px-5 pt-4 pb-3 d-flex align-center font-weight-bold\"},[_c('Icon',{attrs:{\"icon\":\"fluent:keyboard-20-filled\",\"height\":\"28px\"}}),_c('span',{staticClass:\"ml-3\"},[_vm._v(\"キーボードショートカット\")])],1),_c('div',{staticClass:\"px-5 pb-4\"},[_c('v-row',_vm._l((_vm.shortcut_key_list),function(shortcut_key_column,shortcut_key_column_name){return _c('v-col',{key:shortcut_key_column_name,attrs:{\"cols\":\"6\"}},_vm._l((shortcut_key_column),function(shortcut_keys){return _c('div',{key:shortcut_keys.name,staticClass:\"mt-3\"},[_c('div',{staticClass:\"text-subtitle-1 d-flex align-center font-weight-bold\"},[_c('Icon',{attrs:{\"icon\":shortcut_keys.icon,\"height\":shortcut_keys.icon_height}}),_c('span',{staticClass:\"ml-2\"},[_vm._v(_vm._s(shortcut_keys.name))])],1),_vm._l((shortcut_keys.shortcuts),function(shortcut){return _c('div',{key:shortcut.name,staticClass:\"mt-3\"},[_c('div',{staticClass:\"text-subtitle-2 mt-2 d-flex align-center font-weight-medium\"},[_c('span',{staticClass:\"mr-2\",domProps:{\"innerHTML\":_vm._s(shortcut.name)}}),_c('div',{staticClass:\"ml-auto d-flex align-center flex-shrink-0\"},_vm._l((shortcut.keys),function(key,index){return _c('div',{key:key.name,staticClass:\"ml-auto d-flex align-center\"},[(key.icon === true)?_c('Icon',{staticClass:\"shortcut-key\",attrs:{\"icon\":key.name,\"height\":\"18px\"}}):_vm._e(),(key.icon === false)?_c('span',{staticClass:\"shortcut-key\"},[_vm._v(_vm._s(key.name))]):_vm._e(),(index < (shortcut.keys.length - 1))?_c('span',{staticClass:\"shortcut-key-plus\"},[_vm._v(\"+\")]):_vm._e()],1)}),0)])])})],2)}),0)}),1)],1),_c('v-divider'),_c('v-card-actions',{staticClass:\"px-5 py-3\"},[_c('v-spacer'),_c('v-btn',{attrs:{\"color\":\"background lighten-2 px-3\",\"elevation\":\"0\"},on:{\"click\":function($event){_vm.shortcut_key_modal = false}}},[_vm._v(\"閉じる\")])],1)],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n// 番組情報を表すインターフェイス\nexport interface IProgram {\n id: string;\n network_id: number;\n service_id: number;\n event_id: number;\n channel_id: string;\n title: string;\n description: string;\n detail: {[key: string]: string};\n start_time: string;\n end_time: string;\n duration: number;\n is_free: boolean;\n genre: {major: string; middle: string}[];\n video_type: string;\n video_codec: string;\n video_resolution: string;\n primary_audio_type: string;\n primary_audio_language: string;\n primary_audio_sampling_rate: string;\n secondary_audio_type: string | null;\n secondary_audio_language: string | null;\n secondary_audio_sampling_rate: string | null;\n}\n\n// 番組情報を表すインターフェイスのデフォルト値\nexport const IProgramDefault: IProgram = {\n id: 'NID0-SID0',\n service_id: 0,\n network_id: 0,\n event_id: 0,\n channel_id: 'gr000',\n title: '取得中…',\n description: '取得中…',\n detail: {},\n start_time: '2000-01-01T00:00:00+09:00',\n end_time: '2000-01-01T00:00:00+09:00',\n duration: 0,\n is_free: true,\n genre: [],\n video_type: '映像1080i(1125i)、アスペクト比16:9 パンベクトルなし',\n video_codec: 'mpeg2',\n video_resolution: '1080i',\n primary_audio_type: '2/0モード(ステレオ)',\n primary_audio_language: '日本語',\n primary_audio_sampling_rate: '48kHz',\n secondary_audio_type: null,\n secondary_audio_language: null,\n secondary_audio_sampling_rate: null,\n}\n\n// チャンネル情報を表すインターフェイス\nexport interface IChannel {\n id: string;\n network_id: number;\n service_id: number;\n transport_stream_id: number | null;\n remocon_id: number | null;\n channel_id: string;\n channel_number: string;\n channel_name: string;\n channel_type: string;\n channel_force: number | null;\n channel_comment: number | null;\n is_subchannel: boolean;\n is_radiochannel: boolean;\n is_display: boolean;\n viewers: number;\n program_present: IProgram;\n program_following: IProgram;\n}\n\n// チャンネル情報を表すインターフェイスのデフォルト値\nexport const IChannelDefault: IChannel = {\n id: 'NID0-SID0',\n service_id: 0,\n network_id: 0,\n transport_stream_id: null,\n remocon_id: null,\n channel_id: 'gr000',\n channel_number: '---',\n channel_name: '取得中…',\n channel_type: 'GR',\n channel_force: null,\n channel_comment: null,\n is_subchannel: false,\n is_radiochannel: false,\n is_display: true,\n viewers: 0,\n program_present: IProgramDefault,\n program_following: IProgramDefault,\n}\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"channels-container channels-container--watch\"},[_c('v-tabs-fix',{staticClass:\"channels-tab\",attrs:{\"centered\":\"\",\"show-arrows\":\"\"},model:{value:(_vm.tab),callback:function ($$v) {_vm.tab=$$v},expression:\"tab\"}},_vm._l((Array.from(_vm.channels_list)),function(ref){\nvar channels_type = ref[0];\nreturn _c('v-tab',{key:channels_type,staticClass:\"channels-tab__item\"},[_vm._v(\" \"+_vm._s(channels_type)+\" \")])}),1),_c('div',{staticClass:\"channels-list-container\"},[_c('v-tabs-items-fix',{staticClass:\"channels-list\",model:{value:(_vm.tab),callback:function ($$v) {_vm.tab=$$v},expression:\"tab\"}},_vm._l((Array.from(_vm.channels_list)),function(ref){\nvar channels_type = ref[0];\nvar channels = ref[1];\nreturn _c('v-tab-item-fix',{key:channels_type,staticClass:\"channels\"},_vm._l((channels),function(channel){return _c('router-link',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],key:channel.id,staticClass:\"channel\",attrs:{\"to\":(\"/tv/watch/\" + (channel.channel_id))}},[_c('div',{staticClass:\"channel__broadcaster\"},[_c('img',{staticClass:\"channel__broadcaster-icon\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + (channel.channel_id) + \"/logo\")}}),_c('div',{staticClass:\"channel__broadcaster-content\"},[_c('span',{staticClass:\"channel__broadcaster-name\"},[_vm._v(\"Ch: \"+_vm._s(channel.channel_number)+\" \"+_vm._s(channel.channel_name))]),_c('div',{staticClass:\"channel__broadcaster-force\",class:(\"channel__broadcaster-force--\" + (_vm.TVUtils.getChannelForceType(channel.channel_force)))},[_c('Icon',{attrs:{\"icon\":\"fa-solid:fire-alt\",\"height\":\"11px\"}}),_c('span',{staticClass:\"ml-1\"},[_vm._v(_vm._s(_vm.TVUtils.getAttribute(channel, 'channel_force', '-')))])],1)])]),_c('div',{staticClass:\"channel__program-present\"},[_c('span',{staticClass:\"channel__program-present-title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_present, 'title'))}}),_c('span',{staticClass:\"channel__program-present-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(channel.program_present)))])]),_c('div',{staticClass:\"channel__program-following\"},[_c('div',{staticClass:\"channel__program-following-title\"},[_c('span',{staticClass:\"channel__program-following-title-decorate\"},[_vm._v(\"NEXT\")]),_c('Icon',{staticClass:\"channel__program-following-title-icon\",attrs:{\"icon\":\"fluent:fast-forward-20-filled\",\"width\":\"16px\"}}),_c('span',{staticClass:\"channel__program-following-title-text\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(channel.program_following, 'title'))}})],1),_c('span',{staticClass:\"channel__program-following-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(channel.program_following)))])]),_c('div',{staticClass:\"channel__progressbar\"},[_c('div',{staticClass:\"channel__progressbar-progress\",style:((\"width:\" + (_vm.TVUtils.getProgramProgress(channel.program_present)) + \"%;\"))})])])}),1)}),1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue, { PropType } from 'vue';\n\nimport { IChannel } from '@/interface';\nimport Utils, { TVUtils } from '@/utils';\n\nexport default Vue.extend({\n name: 'Channel',\n props: {\n // チャンネル情報リスト\n channels_list: {\n type: Map as PropType>,\n required: true,\n }\n },\n data() {\n return {\n\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n TVUtils: TVUtils,\n\n // タブの状態管理\n tab: null,\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Channel.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Channel.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Channel.vue?vue&type=template&id=691b389f&scoped=true&\"\nimport script from \"./Channel.vue?vue&type=script&lang=ts&\"\nexport * from \"./Channel.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Channel.vue?vue&type=style&index=0&lang=scss&\"\nimport style1 from \"./Channel.vue?vue&type=style&index=1&id=691b389f&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"691b389f\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VTab } from 'vuetify/lib/components/VTabs';\ninstallComponents(component, {VTab})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"comment-container\"},[_c('section',{staticClass:\"comment-header\"},[_c('h2',{staticClass:\"comment-header__title\"},[_c('Icon',{staticClass:\"comment-header__title-icon\",attrs:{\"icon\":\"bi:chat-left-text-fill\",\"height\":\"18.5px\"}}),_c('span',{staticClass:\"comment-header__title-text\"},[_vm._v(\"コメント\")])],1),_c('button',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"comment-header__button ml-auto\"},[_c('Icon',{attrs:{\"icon\":\"heroicons-solid:filter\",\"height\":\"11px\"}}),_c('span',{staticClass:\"ml-1\"},[_vm._v(\"コメントフィルター\")])],1)]),_c('DynamicScroller',{staticClass:\"comment-list\",attrs:{\"direction\":'vertical',\"items\":_vm.comment_list,\"min-item-size\":34},scopedSlots:_vm._u([{key:\"default\",fn:function(ref){\nvar item = ref.item;\nvar active = ref.active;\nreturn [_c('DynamicScrollerItem',{attrs:{\"item\":item,\"active\":active,\"size-dependencies\":[item.text]}},[_c('div',{staticClass:\"comment\"},[_c('span',{staticClass:\"comment__text\"},[_vm._v(_vm._s(item.text))]),_c('span',{staticClass:\"comment__time\"},[_vm._v(_vm._s(item.time))])])])]}}])}),_c('div',{directives:[{name:\"ripple\",rawName:\"v-ripple\"}],staticClass:\"comment-scroll-button elevation-5\",class:{'comment-scroll-button--display': _vm.is_manual_scroll},on:{\"click\":function($event){_vm.is_manual_scroll = false; _vm.scrollCommentList(true);}}},[_c('Icon',{attrs:{\"icon\":\"fluent:arrow-down-12-filled\",\"height\":\"29px\"}})],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { AxiosResponse } from 'axios';\nimport dayjs from 'dayjs';\nimport Vue, { PropType } from 'vue';\n\nimport { IChannel } from '@/interface';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'Comment',\n props: {\n // チャンネル情報\n channel: {\n type: Object as PropType,\n required: true,\n },\n // プレイヤーのインスタンス\n player: {\n type: null as PropType, // 代入当初は null になるため苦肉の策\n required: true,\n }\n },\n data() {\n return {\n\n // 手動スクロール状態かどうか\n is_manual_scroll: false,\n\n // 自動スクロール中かどうか\n // 自動スクロール中の場合、scroll イベントが発火しても無視する\n is_auto_scrolling: false,\n\n // コメントリストの配列\n comment_list: [] as {[key: string]: number | string}[],\n\n // コメントリストの要素\n comment_list_element: null as HTMLElement | null,\n\n // 視聴セッションの WebSocket のインスタンス\n watch_session: null as WebSocket | null,\n\n // コメントセッションの WebSocket のインスタンス\n comment_session: null as WebSocket | null,\n\n // 座席維持用のタイマーのインターバル ID\n keep_seat_interval_id: 0,\n\n // ResizeObserver のインスタンス\n resize_observer: null as ResizeObserver | null,\n\n // ResizeObserver の監視対象の要素\n resize_observer_element: null as HTMLElement | null,\n }\n },\n // 終了前に実行\n beforeDestroy() {\n\n // destroy() を実行\n this.destroy();\n\n // ResizeObserver を終了\n if (this.resize_observer !== null) {\n this.resize_observer.unobserve(this.resize_observer_element);\n }\n },\n watch: {\n\n // チャンネル情報が変更されたとき\n // created() だとチャンネル情報の取得前に実行してしまう\n // this が変わってしまうのでアロー関数は使えない\n async channel(new_channel: IChannel, old_channel: IChannel) {\n\n // 前のチャンネル情報と次のチャンネル情報で channel_id が変わってたら\n if (new_channel.channel_id !== old_channel.channel_id) {\n\n // 0.5秒だけ待ってから\n // 連続してチャンネルを切り替えた時などに毎回コメントサーバーに接続しないように猶予を設ける\n // ただし、最初 (channel_id が gr000 の初期値になっている) だけは待たずに実行する\n if (old_channel.channel_id !== 'gr000') {\n await new Promise(resolve => setTimeout(resolve, 0.5 * 1000));\n // 0.5 秒待った結果、channel_id が既に変更されているので終了\n if (this.channel.channel_id !== new_channel.channel_id) {\n return;\n }\n }\n\n // 前の視聴セッション・コメントセッションを破棄\n this.destroy();\n\n // コメントリストの要素を取得\n if (this.comment_list_element === null) {\n this.comment_list_element = this.$el.querySelector('.comment-list');\n }\n\n // 現在コメントリストがユーザーイベントでスクロールされているかどうか\n let is_user_scrolling = false;\n\n // mousedown → mouseup 中: スクロールバーをマウスでドラッグ\n // 残念ながらスクロールバーのドラッグ中は mousemove のイベントが発火しないため、直接 is_user_scrolling を設定する\n this.comment_list_element.onmousedown = (event: MouseEvent) => {\n // コメントリストの要素の左上を起点としたカーソルのX座標を求める\n const x = event.clientX - this.comment_list_element.getBoundingClientRect().left;\n // 座標が clientWidth 以上であれば、スクロールバー上で mousedown されたものとする\n if (x > this.comment_list_element.clientWidth) is_user_scrolling = true;\n }\n this.comment_list_element.onmouseup = (event: MouseEvent) => {\n // コメントリストの要素の左上を起点としたカーソルのX座標を求める\n const x = event.clientX - this.comment_list_element.getBoundingClientRect().left;\n // 座標が clientWidth 以上であれば、スクロールバー上で mouseup されたものとする\n if (x > this.comment_list_element.clientWidth) is_user_scrolling = false;\n }\n\n // ユーザーによるスクロールイベントで is_user_scrolling を true にする\n // 0.1 秒後に false にする(継続してイベントが発火すれば再び true になる)\n const on_user_scrolling = () => {\n is_user_scrolling = true;\n window.setTimeout(() => is_user_scrolling = false, 100);\n }\n\n // 現在コメントリストがドラッグされているかどうか\n let is_dragging = false;\n // touchstart → touchend 中: スクロールバーをタップでドラッグ\n this.comment_list_element.ontouchstart = () => is_dragging = true;\n this.comment_list_element.ontouchend = () => is_dragging = false;\n // touchmove + is_dragging 中: コメントリストをタップでドラッグしてスクロール\n this.comment_list_element.ontouchmove = () => is_dragging === true ? on_user_scrolling(): '';\n\n // wheel 中: マウスホイールの回転\n this.comment_list_element.onwheel = on_user_scrolling;\n\n // コメントリストがスクロールされた際、自動スクロール中でない&ユーザーイベントで操作されていれば、手動スクロールモードに設定\n // 手動スクロールモードでは自動スクロールを行わず、ユーザーがコメントリストをスクロールできるようにする\n this.comment_list_element.onscroll = async () => {\n\n // scroll イベントは自動スクロールでも発火してしまうので、ユーザーイベントによるスクロールかを確認しないといけない\n // 自動スクロール中かどうかは is_auto_scrolling が true のときで判定できるはずだが、\n // コメントが多くなると is_auto_scrolling が false なのに scroll イベントが遅れて発火してしまうことがある\n if (this.is_auto_scrolling === false && is_user_scrolling === true) {\n\n // 手動スクロールを有効化\n this.is_manual_scroll = true;\n\n // イベント発火時点では scrollTop の値が完全に下にスクロールされていない場合があるため、0.1秒だけ待つ\n await new Promise(resolve => setTimeout(resolve, 100));\n\n // 一番下までスクロールしていたら自動スクロールに戻す\n if ((this.comment_list_element.scrollTop + this.comment_list_element.offsetHeight) >\n (this.comment_list_element.scrollHeight - 10)) { // 一番下から 10px 以内\n this.is_manual_scroll = false; // 手動スクロールを無効化\n }\n }\n }\n\n // 視聴セッションを初期化\n const comment_session_info = await this.initWatchSession();\n\n // コメントセッションを初期化\n await this.initCommentSession(comment_session_info);\n\n // リサイズ時のイベントを初期化\n await this.initReserveObserver();\n }\n }\n },\n methods: {\n\n // 視聴セッションを初期化\n async initWatchSession(): Promise<{[key: string]: string | null}> {\n\n // セッション情報を取得\n let watch_session_info: AxiosResponse;\n try {\n watch_session_info = await Vue.axios.get(`${Utils.api_base_url}/channels/${this.channel.channel_id}/jikkyo`);\n } catch (error) {\n throw new Error(error); // エラー内容を表示\n }\n\n // セッション情報を取得できなかった\n if (watch_session_info.data.is_success === false) {\n throw new Error(watch_session_info.data.detail); // エラー内容を表示\n }\n\n // イベント内で値を返すため、Promise で包む\n return new Promise((resolve) => {\n\n // 視聴セッション WebSocket を開く\n this.watch_session = new WebSocket(watch_session_info.data.audience_token);\n\n // 視聴セッション WebSocket を開いたとき\n this.watch_session.addEventListener('open', () => {\n\n // 視聴セッションをリクエスト\n // 某所で限定公開されている公式ドキュメントいわく、stream フィールドは Optional らしい\n // サーバー負荷軽減のため、映像が不要な場合は必ず省略してくださいとのこと\n this.watch_session.send(JSON.stringify({\n 'type': 'startWatching',\n 'data': {\n 'reconnect': false,\n },\n }));\n });\n\n // 視聴セッション WebSocket からメッセージを受信したとき\n this.watch_session.addEventListener('message', async (event) => {\n\n // 受信したメッセージ\n const message = JSON.parse(event.data);\n\n switch (message.type) {\n\n // 部屋情報(実際には統合されていて、全てアリーナ扱いになっている)\n case 'room': {\n\n // コメントサーバーへの接続情報の入ったオブジェクトを返す\n // デバッグ用で実際には使わないものもある\n return resolve({\n // コメントサーバーへの接続情報\n 'thread_id': message.data.threadId,\n 'your_post_key': (message.data.yourPostKey ? message.data.yourPostKey : null),\n 'message_server': message.data.messageServer.uri,\n });\n }\n\n // 座席情報\n case 'seat': {\n\n // keepIntervalSec の秒数ごとに keepSeat を送信して座席を維持する\n this.keep_seat_interval_id = window.setInterval(() => {\n // セッションがまだ開いていれば\n if (this.watch_session.readyState === 1) {\n // 座席を維持\n this.watch_session.send(JSON.stringify({\n 'type': 'keepSeat',\n }));\n // setInterval を解除\n } else {\n window.clearInterval(this.keep_seat_interval_id);\n }\n }, message.data.keepIntervalSec * 1000);\n break;\n }\n\n // ping-pong\n case 'ping': {\n\n // pong を返してセッションを維持する\n // 送り返さなかった場合勝手にセッションが閉じられてしまう\n this.watch_session.send(JSON.stringify({\n 'type': 'pong',\n }));\n break;\n }\n\n // エラー情報\n case 'error': {\n\n // エラー情報\n let error:string;\n switch (message.data.code) {\n\n case 'CONNECT_ERROR':\n error = 'コメントサーバーに接続できません。';\n break;\n case 'CONTENT_NOT_READY':\n error = 'ニコニコ実況が配信できない状態です。';\n break;\n case 'NO_THREAD_AVAILABLE':\n error = 'コメントスレッドを取得できません。';\n break;\n case 'NO_ROOM_AVAILABLE':\n error = 'コメント部屋を取得できません。';\n break;\n case 'NO_PERMISSION':\n error = 'API にアクセスする権限がありません。';\n break;\n case 'NOT_ON_AIR':\n error = 'ニコニコ実況が放送中ではありません。';\n break;\n case 'BROADCAST_NOT_FOUND':\n error = 'ニコニコ実況の配信情報を取得できません。';\n break;\n case 'INTERNAL_SERVERERROR':\n error = 'ニコニコ実況でサーバーエラーが発生しています。';\n break;\n default:\n error = `ニコニコ実況でエラーが発生しています。(${message.data.code})`;\n break;\n }\n\n // エラー情報を表示\n console.log(`error occurred. code: ${message.data.code}`);\n if (this.player.danmaku.showing) {\n this.player.notice(error);\n }\n\n break;\n }\n\n // 再接続を求められた\n case 'reconnect': {\n\n // 前の視聴セッション・コメントセッションを破棄\n this.destroy();\n\n // waitTimeSec に記載の秒数だけ待ってから再接続する\n await new Promise(resolve => setTimeout(resolve, message.data.waitTimeSec * 1000));\n if (this.player.danmaku.showing) {\n this.player.notice('ニコニコ実況に再接続しています…');\n }\n\n // 視聴セッションを再初期化\n // ドキュメントには reconnect で送られてくる audienceToken で再接続しろと書いてあるんだけど、\n // 確実性的な面で実装が面倒なので当面このままにしておく\n const comment_session_info = await this.initWatchSession();\n\n // コメントセッションを再初期化\n await this.initCommentSession(comment_session_info);\n\n break;\n }\n\n // 視聴セッションが閉じられた(4時のリセットなど)\n case 'disconnect': {\n\n // 実際に接続が閉じられる前に disconnect イベントが送られてきたので、onclose イベントを削除する\n // onclose イベントが発火するのは不意に切断されたときなど最終手段\n if (this.watch_session) this.watch_session.onclose = null;\n\n // 接続切断の理由\n let disconnect_reason;\n switch (message.data.reason) {\n\n case 'TAKEOVER':\n disconnect_reason = 'ニコニコ実況の番組から追い出されました。';\n break;\n case 'NO_PERMISSION':\n disconnect_reason = 'ニコニコ実況の番組の座席を取得できませんでした。';\n break;\n case 'END_PROGRAM':\n disconnect_reason = 'ニコニコ実況がリセットされたか、コミュニティの番組が終了しました。';\n break;\n case 'PING_TIMEOUT':\n disconnect_reason = 'コメントサーバーとの接続生存確認に失敗しました。';\n break;\n case 'TOO_MANY_CONNECTIONS':\n disconnect_reason = 'ニコニコ実況の同一ユーザからの接続数上限を越えています。';\n break;\n case 'TOO_MANY_WATCHINGS':\n disconnect_reason = 'ニコニコ実況の同一ユーザからの視聴番組数上限を越えています。';\n break;\n case 'CROWDED':\n disconnect_reason = 'ニコニコ実況の番組が満席です。';\n break;\n case 'MAINTENANCE_IN':\n disconnect_reason = 'ニコニコ実況はメンテナンス中です。';\n break;\n case 'SERVICE_TEMPORARILY_UNAVAILABLE':\n disconnect_reason = 'ニコニコ実況で一時的にサーバーエラーが発生しています。';\n break;\n default:\n disconnect_reason = `ニコニコ実況との接続が切断されました。(${message.data.reason})`;\n break;\n }\n\n // 接続切断の理由を表示\n console.log(`disconnected. reason: ${message.data.reason}`);\n if (this.player.danmaku.showing) {\n this.player.notice(disconnect_reason);\n }\n\n // 前の視聴セッション・コメントセッションを破棄\n this.destroy();\n\n // 5 秒ほど待ってから再接続する\n await new Promise(resolve => setTimeout(resolve, 5 * 1000));\n if (this.player.danmaku.showing) {\n this.player.notice('ニコニコ実況に再接続しています…');\n }\n\n // 視聴セッションを再初期化\n const comment_session_info = await this.initWatchSession();\n\n // コメントセッションを再初期化\n await this.initCommentSession(comment_session_info);\n\n break;\n }\n }\n });\n\n\n // 視聴セッションの接続が閉じられたとき(ネットワークが切断された場合など)\n // イベントを無効化しやすいように敢えて onclose で実装する\n this.watch_session.onclose = async (event) => {\n\n // 接続切断の理由を表示\n console.log(`disconnected. code: ${event.code}`);\n if (this.player.danmaku.showing) {\n this.player.notice(`ニコニコ実況との接続が切断されました。(code: ${event.code})`);\n }\n\n // 前の視聴セッション・コメントセッションを破棄\n this.destroy();\n\n // 10 秒ほど待ってから再接続する\n // ニコ生側から切断された場合と異なりネットワークが切断された可能性が高いので、間を多めに取る\n await new Promise(resolve => setTimeout(resolve, 10 * 1000));\n if (this.player.danmaku.showing) {\n this.player.notice('ニコニコ実況に再接続しています…');\n }\n\n // 視聴セッションを再初期化\n const comment_session_info = await this.initWatchSession();\n\n // コメントセッションを再初期化\n await this.initCommentSession(comment_session_info);\n };\n });\n },\n\n // コメントセッションを初期化\n async initCommentSession(comment_session_info: {[key: string]: string | null}) {\n\n // タブが非表示状態のときにコメントを格納する配列\n // タブが表示状態になったらコメントリストにのみ表示する(遅れているのでプレイヤーには表示しない)\n let comment_list_buffer = [];\n\n // 最初に送信されてくるコメントを受信し終えたかどうかのフラグ\n let is_received_initial_comment = false;\n\n // コメントセッション WebSocket を開く\n this.comment_session = new WebSocket(comment_session_info.message_server);\n\n // コメントセッション WebSocket を開いたとき\n this.comment_session.addEventListener('open', () => {\n\n // コメント送信をリクエスト\n // このコマンドを送らないとコメントが送信されてこない\n this.comment_session.send(JSON.stringify([\n { 'ping': {'content': 'rs:0'} },\n { 'ping': {'content': 'ps:0'} },\n {\n 'thread': {\n 'version': '20061206', // 設定必須\n 'thread': comment_session_info.thread_id, // スレッド ID\n 'threadkey': comment_session_info.your_post_key, // スレッドキー\n 'user_id': '', // ユーザー ID\n 'res_from': -50, // 最初にコメントを 50 個送信する\n }\n },\n { 'ping': {'content': 'pf:0'} },\n { 'ping': {'content': 'rf:0'} },\n ]));\n });\n\n // 視聴セッション WebSocket からメッセージを受信したとき\n this.comment_session.addEventListener('message', async (event_raw) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n\n // thread メッセージのみ\n if (event.thread !== undefined) {\n\n // 接続成功のコールバックを DPlayer に通知\n if (event.thread.resultcode === 0) {\n\n // 接続失敗のコールバックを DPlayer に通知\n } else {\n const message = 'コメントサーバーに接続できませんでした。';\n console.error('Error: ' + message);\n }\n }\n\n // ping メッセージのみ\n // rf:0 が送られてきたら初回コメントの受信は完了\n if (event.ping !== undefined && event.ping.content === 'rf:0') {\n\n // フラグを立てる\n is_received_initial_comment = true;\n\n // コメントリストを一番下にスクロール\n // 初回コメントは量が多いので、一括でスクロールする\n this.scrollCommentList();\n }\n\n // コメントを取得\n const comment = event.chat;\n\n // コメントがない or 広告用など特殊な場合は弾く\n if (comment === undefined ||\n comment.content === undefined ||\n comment.content.match(/\\/[a-z]+ /)) {\n return;\n }\n\n // 自分のコメントも表示しない\n if (comment.yourpost && comment.yourpost === 1) {\n return;\n }\n\n // 色・位置\n let color = '#FFEAEA'; // 色のデフォルト\n let position = 'right'; // 位置のデフォルト\n if (comment.mail !== undefined && comment.mail !== null) {\n // コマンドをスペースで区切って配列にしたもの\n const command = comment.mail.replace('184', '').split(' ');\n for (const item of command) { // コマンドごとに\n if (this.getCommentColor(item) !== null) {\n color = this.getCommentColor(item);\n }\n if (this.getCommentPosition(item) !== null) {\n position = this.getCommentPosition(item);\n }\n }\n }\n\n // 配信に発生する遅延分待ってから\n // 現状だいたい1秒くらいなので暫定で決め打ち\n // 最初に受信したコメントはリアルタイムなコメントではないため、遅らせないように\n if (is_received_initial_comment) {\n const comment_delay_time = Utils.getSettingsItem('comment_delay_time');\n await new Promise(resolve => setTimeout(resolve, comment_delay_time * 1000));\n }\n\n // コメントリストのコメントが 500 件を超えたら古いものから順に削除する\n // 仮想スクロールとはいえ、さすがに 500 件を超えると重くなりそう\n if (this.comment_list.length > 500) {\n this.comment_list.shift();\n }\n\n // コメントリストへ追加するオブジェクト\n // コメント投稿時刻はフォーマットしてから\n const comment_dict = {\n id: comment.no,\n text: comment.content,\n time: dayjs(comment.date * 1000).format('HH:mm:ss'),\n };\n\n // タブが非表示状態のときは、バッファにコメントを追加するだけで終了する\n // ここで追加すると、タブが表示状態になったときに一斉に描画されて大変なことになる\n if (document.visibilityState === 'hidden') {\n comment_list_buffer.push(comment_dict);\n return;\n }\n\n // コメントリストに追加\n this.comment_list.push(comment_dict);\n\n // // コメントリストを一番下にスクロール\n // 最初に受信したコメントは上の処理で一括でスクロールさせる\n if (is_received_initial_comment) {\n this.scrollCommentList();\n }\n\n // コメント描画 (再生時のみ)\n // 最初に受信したコメントはリアルタイムなコメントではないため、描画しないように\n if (is_received_initial_comment) {\n if (!this.player.video.paused){\n this.player.danmaku.draw({\n text: comment.content,\n color: color,\n type: position,\n });\n }\n }\n });\n\n // タブの表示/非表示の状態が切り替わったときのイベント\n // 表示状態になったときにバッファにあるコメントをコメントリストに表示する\n document.onvisibilitychange = () => {\n if (document.visibilityState === 'visible') {\n this.comment_list.push(...comment_list_buffer); // コメントリストに一括で追加\n comment_list_buffer = []; // バッファをクリア\n this.scrollCommentList(); // コメントリストをスクロール\n }\n };\n },\n\n // リサイズ時のイベントを初期化\n async initReserveObserver() {\n\n // 監視対象の要素\n this.resize_observer_element = document.querySelector('.watch-player');\n\n // タイムアウト ID\n // 一時的に無効にした transition を有効化する際に利用する\n let animation_timeout_id = null;\n\n // プレイヤーの要素がリサイズされた際に発火するイベント\n const on_resize = () => {\n\n // 映像の要素\n const video_element = document.querySelector('.dplayer-video-wrap-aspect');\n\n // コメント描画領域の要素\n const comment_area_element = (document.querySelector('.dplayer-danmaku') as HTMLElement);\n\n // プレイヤー全体と映像の高さの差(レターボックス)から、コメント描画領域の高さを狭める必要があるかを判定する\n // 2で割っているのは単体の差を測るため\n if (this.resize_observer_element === null || this.resize_observer_element.clientHeight === null) return;\n if (video_element === null || video_element.clientHeight === null) return;\n const letter_box_height = (this.resize_observer_element.clientHeight - video_element.clientHeight) / 2;\n\n // 70px or 54px (高さが 450px 以下) 以下ならヘッダー(番組名などの表示)と被るので対応する\n const threshold = window.matchMedia('(max-height: 450px)').matches ? 50 : 66;\n if (letter_box_height < threshold) {\n\n // コメント描画領域に必要な上下マージン\n const comment_area_vertical_margin = (threshold - letter_box_height) * 2;\n\n // 狭めるコメント描画領域の幅\n // 映像の要素の幅をそのまま利用する\n const comment_area_width = video_element.clientWidth;\n\n // 狭めるコメント描画領域の高さ\n const comment_area_height = video_element.clientHeight - comment_area_vertical_margin;\n\n // 狭めるコメント描画領域のアスペクト比を求める\n // https://tech.arc-one.jp/asepct-ratio/\n const gcd = (x: number, y: number) => { // 最大公約数を求める関数\n if(y === 0) return x;\n return gcd(y, x % y);\n }\n // 幅と高さの最大公約数を求める\n const gcd_result = gcd(comment_area_width, comment_area_height);\n // 幅と高さをそれぞれ最大公約数で割ってアスペクト比を算出\n const comment_area_height_aspect = `${comment_area_width / gcd_result} / ${comment_area_height / gcd_result}`;\n\n // 一時的に transition を無効化する\n // アスペクト比の設定は連続して行われるが、その際に transition が適用されるとワンテンポ遅れたアニメーションになってしまう\n comment_area_element.style.transition = 'none';\n\n // コメント描画領域に算出したアスペクト比を設定する\n comment_area_element.style.setProperty('--comment-area-aspect-ratio', comment_area_height_aspect);\n\n // コメント描画領域に必要な上下マージンを設定する\n comment_area_element.style.setProperty('--comment-area-vertical-margin', `${comment_area_vertical_margin}px`);\n\n // 以前セットされた setTimeout() を止める\n window.clearTimeout(animation_timeout_id);\n\n // 0.2秒後に実行する\n // 0.2秒より前にもう一度リサイズイベントが来た場合はタイマーがクリアされるため実行されない\n window.setTimeout(() => {\n\n // 再び transition を有効化する\n comment_area_element.style.transition = '';\n\n }, 0.2 * 1000);\n\n } else {\n\n // コメント描画領域に設定したアスペクト比・上下マージンを削除する\n comment_area_element.style.removeProperty('--comment-area-aspect-ratio');\n comment_area_element.style.removeProperty('--comment-area-vertical-margin');\n }\n }\n\n // 要素の監視を開始\n this.resize_observer = new ResizeObserver(on_resize);\n this.resize_observer.observe(this.resize_observer_element);\n },\n\n // コメントリストを一番下までスクロールする\n async scrollCommentList(smooth: boolean = false) {\n\n // 手動スクロールモードの時は実行しない\n if (this.is_manual_scroll === true) return;\n\n // 自動スクロール中のフラグを立てる\n this.is_auto_scrolling = true;\n\n // 0.01 秒待って実行し、念押しで2回実行しないと完全に最下部までスクロールされない…(ブラウザの描画バグ?)\n // this.$nextTick() は効かなかった\n for (let index = 0; index < 3; index++) {\n await new Promise(resolve => setTimeout(resolve, 0.01 * 1000));\n if (smooth === true) { // スムーズスクロール\n this.comment_list_element.scrollTo({top: this.comment_list_element.scrollHeight, left: 0, behavior: 'smooth'});\n } else {\n this.comment_list_element.scrollTo(0, this.comment_list_element.scrollHeight);\n }\n }\n\n // 0.1 秒待つ(重要)\n await new Promise(resolve => setTimeout(resolve, 0.1 * 1000));\n\n // 自動スクロール中のフラグを降ろす\n this.is_auto_scrolling = false;\n },\n\n /**\n * ニコニコの色指定を 16 進数カラーコードに置換する\n * @param {string} color ニコニコの色指定\n * @return {string} 16 進数カラーコード\n */\n getCommentColor(color: string): string {\n const color_table = {\n 'red': '#E54256',\n 'pink': '#FF8080',\n 'orange': '#FFC000',\n 'yellow': '#FFE133',\n 'green': '#64DD17',\n 'cyan': '#39CCFF',\n 'blue': '#0000FF',\n 'purple': '#D500F9',\n 'black': '#1E1310',\n 'white': '#FFEAEA',\n 'white2': '#CCCC99',\n 'niconicowhite': '#CCCC99',\n 'red2': '#CC0033',\n 'truered': '#CC0033',\n 'pink2': '#FF33CC',\n 'orange2': '#FF6600',\n 'passionorange': '#FF6600',\n 'yellow2': '#999900',\n 'madyellow': '#999900',\n 'green2': '#00CC66',\n 'elementalgreen': '#00CC66',\n 'cyan2': '#00CCCC',\n 'blue2': '#3399FF',\n 'marineblue': '#3399FF',\n 'purple2': '#6633CC',\n 'nobleviolet': '#6633CC',\n 'black2': '#666666',\n };\n if (color_table[color] !== undefined) {\n return color_table[color];\n } else {\n return null;\n }\n },\n\n /**\n * ニコニコの位置指定を DPlayer の位置指定に置換する\n * @param {string} position ニコニコの位置指定\n * @return {string} DPlayer の位置指定\n */\n getCommentPosition(position: string): string {\n switch (position) {\n case 'ue':\n return 'top';\n case 'naka':\n return 'right';\n case 'shita':\n return 'bottom';\n default:\n return null;\n }\n },\n\n // 破棄する\n destroy() {\n\n // コメントリストをクリア\n this.comment_list = [];\n\n // タブの表示/非表示の状態が切り替わったときのイベントを削除\n document.onvisibilitychange = null;\n\n // 視聴セッションを閉じる\n if (this.watch_session !== null) {\n this.watch_session.onclose = null; // WebSocket が閉じられた際のイベントを削除\n this.watch_session.close(); // WebSocket を閉じる\n this.watch_session = null; // null に戻す\n }\n\n // コメントセッションを閉じる\n if (this.comment_session !== null) {\n this.comment_session.onclose = null; // WebSocket が閉じられた際のイベントを削除\n this.comment_session.close(); // WebSocket を閉じる\n this.comment_session = null; // null に戻す\n }\n\n // 座席保持用のタイマーをクリア\n window.clearInterval(this.keep_seat_interval_id);\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Comment.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Comment.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Comment.vue?vue&type=template&id=7575b645&scoped=true&\"\nimport script from \"./Comment.vue?vue&type=script&lang=ts&\"\nexport * from \"./Comment.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Comment.vue?vue&type=style&index=0&id=7575b645&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"7575b645\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installDirectives from \"!../../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"program-container\"},[_c('section',{staticClass:\"program-broadcaster\"},[_c('img',{staticClass:\"program-broadcaster__icon\",attrs:{\"src\":((_vm.Utils.api_base_url) + \"/channels/\" + ((_vm.$route.params.channel_id)) + \"/logo\")}}),_c('div',{staticClass:\"program-broadcaster__number\"},[_vm._v(\"Ch: \"+_vm._s(_vm.channel.channel_number))]),_c('div',{staticClass:\"program-broadcaster__name\"},[_vm._v(_vm._s(_vm.channel.channel_name))])]),_c('section',{staticClass:\"program-info\"},[_c('h1',{staticClass:\"program-info__title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(_vm.channel.program_present, 'title'))}}),_c('div',{staticClass:\"program-info__time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(_vm.channel.program_present)))]),_c('div',{staticClass:\"program-info__description\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(_vm.channel.program_present, 'description'))}}),_c('div',{staticClass:\"program-info__genre-container\"},_vm._l((_vm.TVUtils.getAttribute(_vm.channel.program_present, 'genre', [])),function(genre,genre_index){return _c('div',{key:genre_index,staticClass:\"program-info__genre\"},[_vm._v(\" \"+_vm._s(genre.major)+\" / \"+_vm._s(genre.middle)+\" \")])}),0),_c('div',{staticClass:\"program-info__next\"},[_c('span',{staticClass:\"program-info__next-decorate\"},[_vm._v(\"NEXT\")]),_c('Icon',{staticClass:\"program-info__next-icon\",attrs:{\"icon\":\"fluent:fast-forward-20-filled\",\"width\":\"16px\"}})],1),_c('span',{staticClass:\"program-info__next-title\",domProps:{\"innerHTML\":_vm._s(_vm.TVUtils.decorateProgramInfo(_vm.channel.program_following, 'title'))}}),_c('div',{staticClass:\"program-info__next-time\"},[_vm._v(_vm._s(_vm.TVUtils.getProgramTime(_vm.channel.program_following)))]),_c('div',{staticClass:\"program-info__status\"},[_c('div',{staticClass:\"program-info__status-force\",class:(\"program-info__status-force--\" + (_vm.TVUtils.getChannelForceType(_vm.channel.channel_force)))},[_c('Icon',{attrs:{\"icon\":\"fa-solid:fire-alt\",\"height\":\"14px\"}}),_c('span',{staticClass:\"ml-2\"},[_vm._v(\"勢い:\")]),_c('span',{staticClass:\"ml-2\"},[_vm._v(_vm._s(_vm.TVUtils.getAttribute(_vm.channel, 'channel_force', '--'))+\" コメ/分\")])],1),_c('div',{staticClass:\"program-info__status-viewers ml-5\"},[_c('Icon',{attrs:{\"icon\":\"fa-solid:eye\",\"height\":\"14px\"}}),_c('span',{staticClass:\"ml-2\"},[_vm._v(\"視聴数:\")]),_c('span',{staticClass:\"ml-1\"},[_vm._v(_vm._s(_vm.channel.viewers))])],1)])]),_c('section',{staticClass:\"program-detail-container\"},_vm._l((_vm.TVUtils.getAttribute(_vm.channel.program_present, 'detail', {})),function(detail_text,detail_heading){return _c('div',{key:detail_heading,staticClass:\"program-detail\"},[_c('h2',{staticClass:\"program-detail__heading\"},[_vm._v(_vm._s(detail_heading))]),_c('div',{staticClass:\"program-detail__text\"},[_vm._v(_vm._s(detail_text))])])}),0)])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue, { PropType } from 'vue';\n\nimport { IChannel } from '@/interface';\nimport Utils, { TVUtils } from '@/utils';\n\nexport default Vue.extend({\n name: 'Program',\n props: {\n // チャンネル情報\n channel: {\n type: Object as PropType,\n required: true,\n }\n },\n data() {\n return {\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n TVUtils: TVUtils,\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Program.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Program.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Program.vue?vue&type=template&id=00e07beb&scoped=true&\"\nimport script from \"./Program.vue?vue&type=script&lang=ts&\"\nexport * from \"./Program.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Program.vue?vue&type=style&index=0&id=00e07beb&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"00e07beb\",\n null\n \n)\n\nexport default component.exports","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport { AxiosResponse } from 'axios';\nimport dayjs from 'dayjs';\n// @ts-ignore JavaScript で書かれているので型定義がなく、作ろうとするとややこしくなるので黙殺\nimport DPlayer from 'dplayer';\nimport mpegts from 'mpegts.js';\nimport Vue from 'vue';\n\nimport { IChannel, IChannelDefault } from '@/interface';\nimport Channel from '@/components/TV/Channel.vue';\nimport Comment from '@/components/TV/Comment.vue';\nimport Program from '@/components/TV/Program.vue';\nimport Utils, { TVUtils } from '@/utils';\n\nexport default Vue.extend({\n name: 'Watch',\n components: {\n Channel,\n Comment,\n Program,\n },\n data() {\n return {\n\n // ユーティリティをテンプレートで使えるように\n Utils: Utils,\n TVUtils: TVUtils,\n\n // 現在時刻\n time: dayjs().format('YYYY/MM/DD HH:mm:ss'),\n\n // 表示されるパネルのタブ\n panel_active_tab: Utils.getSettingsItem('panel_active_tab'),\n\n // 背景の URL\n background_url: '',\n\n // プレイヤーのローディング状態\n // 既定でローディングとする\n is_loading: true,\n\n // プレイヤーの背景を表示するか\n // 既定で表示しない\n is_background_display: false,\n\n // コントロールを表示するか\n // 既定で表示する\n is_control_display: true,\n\n // パネルを表示するか\n // panel_display_state が 'AlwaysDisplay' なら常に表示し、'AlwaysFold' なら常に折りたたむ\n // 'RestorePreviousState' なら is_latest_panel_display の値を使い、前回の状態を復元する\n is_panel_display: (() => {\n switch (Utils.getSettingsItem('panel_display_state')) {\n case 'AlwaysDisplay':\n return true;\n case 'AlwaysFold':\n return false;\n case 'RestorePreviousState':\n return Utils.getSettingsItem('is_latest_panel_display');\n }\n })() as boolean,\n\n // フルスクリーン状態かどうか\n is_fullscreen: false,\n\n // インターバル ID\n // ページ遷移時に setInterval(), setTimeout() の実行を止めるのに使う\n // setInterval(), setTimeout() の返り値を登録する\n interval_ids: [] as number[],\n\n // コントロール表示切り替え用のインターバル ID\n // 混ぜるとダメなので独立させる\n control_interval_id: 0,\n\n // チャンネル ID\n channel_id: this.$route.params.channel_id,\n\n // チャンネル情報\n // IChannelDefault に情報取得が完了するまでの間表示される初期値が定義されている\n channel: IChannelDefault,\n\n // 前のチャンネルのチャンネル情報\n channel_previous: IChannelDefault,\n\n // 次のチャンネルのチャンネル情報\n channel_next: IChannelDefault,\n\n // チャンネル情報リスト\n channels_list: new Map() as Map,\n\n // プレイヤー (DPlayer) のインスタンス\n player: null,\n\n // イベントソースのインスタンス\n eventsource: null as EventSource | null,\n\n // フルスクリーン状態が切り替わったときのハンドラー\n fullscreen_handler: null as () => void | null,\n\n // ショートカットキーのハンドラー\n shortcut_key_handler: null as (event: KeyboardEvent) => void | null,\n\n // ショートカットキーの最終押下時刻のタイムスタンプ\n shortcut_key_pressed_at: Date.now(),\n\n // キーボードショートカットの一覧のモーダルを表示するか\n shortcut_key_modal: false,\n\n // キーボードショートカットの一覧に表示するショートカットキーのリスト\n shortcut_key_list: {\n left_column: [\n {\n name: '全般',\n icon: 'fluent:home-20-filled',\n icon_height: '22px',\n shortcuts: [\n { name: '数字キー・テンキーに対応するリモコン番号 (1~12) のチャンネルに切り替える
(同時に Shift キーを押すと、地デジならBS、BSなら地デジのチャンネルを選局する)', keys: [{name: '1~9, 0, -(=), ^(~)', icon: false}] },\n { name: '前のチャンネルに切り替える', keys: [{name: 'fluent:arrow-up-12-filled', icon: true}] },\n { name: '次のチャンネルに切り替える', keys: [{name: 'fluent:arrow-down-12-filled', icon: true}] },\n { name: 'キーボードショートカットの一覧を表示する', keys: [{name: '/(?)', icon: false}] },\n ]\n },\n {\n name: 'パネル',\n icon: 'fluent:panel-right-20-filled',\n icon_height: '24px',\n shortcuts: [\n { name: 'パネルの表示切り替え', keys: [{name: 'P', icon: false}] },\n { name: '番組情報タブを表示する', keys: [{name: 'K', icon: false}] },\n { name: 'チャンネルタブを表示する', keys: [{name: 'L', icon: false}] },\n { name: 'コメントタブを表示する', keys: [{name: ';(+)', icon: false}] },\n { name: 'Twitter タブを表示する', keys: [{name: ':(*)', icon: false}] },\n ]\n }\n ],\n right_column: [\n {\n name: 'プレイヤー',\n icon: 'fluent:play-20-filled',\n icon_height: '20px',\n shortcuts: [\n { name: '再生 / 一時停止の切り替え', keys: [{name: 'Space', icon: false}] },\n { name: '停止して0.25秒早戻し', keys: [{name: 'fluent:arrow-left-12-filled', icon: true}] },\n { name: '停止して0.25秒早送り', keys: [{name: 'fluent:arrow-right-12-filled', icon: true}] },\n { name: 'フルスクリーンの切り替え', keys: [{name: 'F', icon: false}] },\n { name: 'ライブストリームの同期', keys: [{name: 'W', icon: false}] },\n { name: 'Picture-in-Picture の表示切り替え', keys: [{name: 'E', icon: false}] },\n { name: '字幕の表示切り替え', keys: [{name: 'S', icon: false}] },\n { name: 'コメントの表示切り替え', keys: [{name: 'D', icon: false}] },\n { name: 'コメント入力フォームにフォーカスする', keys: [{name: 'M', icon: false}] },\n ]\n }\n ]\n }\n }\n },\n // 開始時に実行\n created() {\n\n // init() を実行\n this.init();\n },\n // 終了前に実行\n beforeDestroy() {\n\n // destroy() を実行\n // 別のページへ遷移するため、DPlayer のインスタンスを確実に破棄する\n // さもなければ、ブラウザがリロードされるまでバックグラウンドで永遠に再生されてしまう\n this.destroy(true);\n\n // ページ上でキーが押されたときのイベントを削除\n if (this.shortcut_key_handler !== null) {\n document.removeEventListener('keydown', this.shortcut_key_handler);\n this.shortcut_key_handler = null;\n }\n },\n // チャンネル切り替え時に実行\n // コンポーネント(インスタンス)は再利用される\n // ref: https://router.vuejs.org/ja/guide/advanced/navigation-guards.html#%E3%83%AB%E3%83%BC%E3%83%88%E5%8D%98%E4%BD%8D%E3%82%AB%E3%82%99%E3%83%BC%E3%83%88%E3%82%99\n beforeRouteUpdate(to, from, next) {\n\n // 前のインスタンスを破棄して終了する\n this.destroy();\n\n // チャンネル ID を次のチャンネルのものに切り替える\n this.channel_id = to.params.channel_id;\n\n // 既に取得済みのチャンネル情報で、前・現在・次のチャンネル情報を更新する\n [this.channel_previous, this.channel, this.channel_next]\n = TVUtils.getPreviousAndCurrentAndNextChannel(this.channels_list, this.channel_id);\n\n // 0.5秒だけ待ってから\n // 連続して押した時などにライブストリームを初期化しないように猶予を設ける\n this.interval_ids.push(window.setTimeout(() => {\n\n // 現在のインスタンスを初期化する\n this.init();\n\n }, 500));\n\n next();\n },\n watch: {\n // 前回視聴画面を開いた際にパネルが表示されていたかどうかを保存\n is_panel_display() {\n Utils.setSettingsItem('is_latest_panel_display', this.is_panel_display);\n }\n },\n methods: {\n\n // 初期化する\n init() {\n\n // ローディング中の背景画像をランダムで設定\n this.background_url = Utils.generatePlayerBackgroundURL();\n\n // コントロール表示タイマーを実行\n this.controlDisplayTimer();\n\n // チャンネル情報を取得\n this.update();\n\n // 現在時刻を1秒おきに更新\n this.interval_ids.push(window.setInterval(() => {\n this.time = dayjs().format('YYYY/MM/DD HH:mm:ss');\n }, 1 * 1000));\n\n // 00秒までの残り秒数\n // 現在 16:01:34 なら 26 (秒) になる\n const residue_second = 60 - (Math.floor(new Date().getTime() / 1000) % 60);\n\n // 00秒になるまで待ってから\n // 番組は基本1分単位で組まれているため、20秒や45秒など中途半端な秒数で更新してしまうと反映が遅れてしまう\n this.interval_ids.push(window.setTimeout(() => {\n\n // チャンネル情報を更新\n this.update();\n\n // チャンネル情報を定期的に更新\n this.interval_ids.push(window.setInterval(() => {\n this.update();\n }, 30 * 1000)); // 30秒おき\n\n }, residue_second * 1000));\n },\n\n // チャンネル情報一覧を取得し、画面を更新する\n async update() {\n\n // チャンネル ID が未定義なら実行しない(フェイルセーフ)\n if (this.$route.params.channel_id === undefined) {\n return;\n }\n\n // チャンネル情報 API にアクセス\n let channel_response: AxiosResponse;\n try {\n channel_response = await Vue.axios.get(`${Utils.api_base_url}/channels/${this.channel_id}`);\n } catch (error) {\n\n // エラー内容を表示\n console.error(error);\n\n // ステータスコードが 422(チャンネルが存在しない)なら 404 ページにリダイレクト\n // 正確には 404 ページ自体がルートとして存在するわけじゃないけど、そもそも存在しないページなら 404 になるので\n if (error.response && error.response.status === 422 && error.response.data.detail === 'Specified channel_id was not found') {\n await this.$router.replace({path: '/not-found/'});\n }\n\n // 処理を中断\n return;\n }\n\n // チャンネル情報を代入\n this.channel = channel_response.data;\n\n // プレイヤーがまだ初期化されていない or 他のチャンネルからの切り替えですでにプレイヤーが初期化されているけど破棄が可能\n // update() 自体は初期化時以外にも1分ごとに定期実行されるため、その際に毎回プレイヤーを再初期化しないようにする\n if (this.player === null || this.player.KonomiTVCanDestroy === true) {\n\n // プレイヤーを初期化\n this.initPlayer();\n\n // イベントハンドラーを初期化\n this.initEventHandler();\n\n // ショートカットキーを初期化\n this.initShortcutKeyHandler();\n }\n\n // 副音声がない番組でプレイヤー上で副音声に切り替えられないように\n // 音声多重放送でもデュアルモノでもない番組のみ\n if ((this.channel.program_present === null) ||\n ((this.channel.program_present.primary_audio_type !== '1/0+1/0モード(デュアルモノ)') &&\n (this.channel.program_present.secondary_audio_type === null))) {\n\n // クラスを付与\n this.player.template.audioItem[1].classList.add('dplayer-setting-audio-item--disabled');\n\n // 現在副音声が選択されている可能性を考慮し、明示的に主音声に切り替える\n if (this.player.plugins.mpegts) {\n window.setTimeout(() => { // プレイヤーの初期化が完了するまで少し待つ\n this.player.template.audioItem[0].classList.add('dplayer-setting-audio-current');\n this.player.template.audioItem[1].classList.remove('dplayer-setting-audio-current');\n this.player.template.audioValue.textContent = this.player.tran('Primary audio');\n try {\n this.player.plugins.mpegts.switchPrimaryAudio();\n } catch (error) {\n // pass\n }\n }, 300);\n }\n\n // 音声多重放送かデュアルモノなので、副音声への切り替えを有効化\n } else {\n\n // クラスを削除\n this.player.template.audioItem[1].classList.remove('dplayer-setting-audio-item--disabled');\n }\n\n // チャンネル情報一覧 API にアクセス\n // チャンネル情報 API と同時にアクセスするとむしろレスポンスが遅くなるので、返ってくるのを待ってから実行\n let channels_response: AxiosResponse;\n try {\n channels_response = await Vue.axios.get(`${Utils.api_base_url}/channels`);\n } catch (error) {\n console.error(error); // エラー内容を表示\n return;\n }\n\n // is_display が true または現在表示中のチャンネルのみに絞り込むフィルタ関数\n // 放送していないサブチャンネルを表示から除外する\n const filter = (channel: IChannel) => {\n return channel.is_display || this.channel_id === channel.channel_id;\n }\n\n // チャンネルリストを再構築\n // 1つでもチャンネルが存在するチャンネルタイプのみ表示するように\n // たとえば SKY (スカパー!プレミアムサービス) のタブは SKY に属すチャンネルが1つもない(=受信できない)なら表示されない\n this.channels_list = new Map();\n this.channels_list.set('ピン留め', []); // ピン留めタブの準備\n if (channels_response.data.GR.length > 0) this.channels_list.set('地デジ', channels_response.data.GR.filter(filter));\n if (channels_response.data.BS.length > 0) this.channels_list.set('BS', channels_response.data.BS.filter(filter));\n if (channels_response.data.CS.length > 0) this.channels_list.set('CS', channels_response.data.CS.filter(filter));\n if (channels_response.data.CATV.length > 0) this.channels_list.set('CATV', channels_response.data.CATV.filter(filter));\n if (channels_response.data.SKY.length > 0) this.channels_list.set('SKY', channels_response.data.SKY.filter(filter));\n if (channels_response.data.STARDIGIO.length > 0) this.channels_list.set('StarDigio', channels_response.data.STARDIGIO.filter(filter));\n\n // ピン留めされているチャンネルの ID を取得\n const pinned_channel_ids = Utils.getSettingsItem('pinned_channel_ids');\n\n // ピン留めされているチャンネル情報のリスト\n const pinned_channels = [] as IChannel[];\n\n // チャンネル ID が一致したチャンネルの情報を保存する\n for (const pinned_channel_id of pinned_channel_ids) {\n const pinned_channel_type = TVUtils.getChannelType(pinned_channel_id, true);\n pinned_channels.push(this.channels_list.get(pinned_channel_type).find((channel) => {\n return channel.channel_id === pinned_channel_id; // チャンネル ID がピン留めされているチャンネルのものと同じ\n }));\n }\n\n // pinned_channels に何か入っていたらピン留めタブを表示するし、そうでなければ表示しない\n if (pinned_channels.length > 0) {\n this.channels_list.set('ピン留め', pinned_channels);\n } else {\n this.channels_list.delete('ピン留め');\n }\n\n // 前と次のチャンネル ID を取得する\n [this.channel_previous, , this.channel_next] = TVUtils.getPreviousAndCurrentAndNextChannel(this.channels_list, this.channel_id);\n\n // MediaSession API を使い、メディア通知の表示をカスタマイズ\n if ('mediaSession' in navigator) {\n\n // アートワークとして表示するアイコン\n const artwork = [\n {src: '/assets/img/icons/icon-maskable-192px.png', sizes: '192x192', type: 'image/png'},\n {src: '/assets/img/icons/icon-maskable-512px.png', sizes: '512x512', type: 'image/png'},\n ];\n\n // メディア通知の表示をカスタマイズ\n navigator.mediaSession.metadata = new MediaMetadata({\n title: this.channel.program_present ? this.channel.program_present.title : '放送休止',\n artist: this.channel.channel_name,\n artwork: artwork,\n });\n\n // 再生状況のステータスを設定\n if ('setPositionState' in navigator.mediaSession) {\n navigator.mediaSession.setPositionState({\n duration: 0, // ライブなので0(長さなしを表すらしい)に設定\n playbackRate: 1, // ライブなので再生速度は常に1になる\n });\n }\n\n // メディア通知上のボタンが押されたときのイベント\n navigator.mediaSession.setActionHandler('play', () => { this.player.play() }); // 再生\n navigator.mediaSession.setActionHandler('pause', () => { this.player.pause() }); // 停止\n navigator.mediaSession.setActionHandler('previoustrack', async () => { // 前のチャンネルに切り替え\n navigator.mediaSession.metadata = new MediaMetadata({\n title: this.channel_previous.program_present ? this.channel_previous.program_present.title : '放送休止',\n artist: this.channel_previous.channel_name,\n artwork: artwork,\n });\n // ルーティングを前のチャンネルに置き換える\n await this.$router.replace({path: `/tv/watch/${this.channel_previous.channel_id}`});\n });\n navigator.mediaSession.setActionHandler('nexttrack', async () => { // 次のチャンネルに切り替え\n navigator.mediaSession.metadata = new MediaMetadata({\n title: this.channel_next.program_present ? this.channel_next.program_present.title : '放送休止',\n artist: this.channel_next.channel_name,\n artwork: artwork,\n });\n // ルーティングを次のチャンネルに置き換える\n await this.$router.replace({path: `/tv/watch/${this.channel_next.channel_id}`});\n });\n }\n },\n\n // マウスが動いたりタップされた時のイベント\n // 3秒間何も操作がなければコントロールを非表示にする\n controlDisplayTimer(event: Event | null = null, is_player_event: boolean = false) {\n\n // タッチデバイスかどうか\n // DPlayer の UA 判定コードと同一\n const is_touch_device = /iPhone|iPad|iPod|Macintosh|Android|Mobile/i.test(navigator.userAgent) && 'ontouchend' in document;\n\n // タッチデバイスで mousemove 、あるいはタッチデバイス以外で touchmove か click が発火した時は実行じない\n if (is_touch_device == true && event !== null && event.type === 'mousemove') return;\n if (is_touch_device == false && event !== null && (event.type === 'touchmove' || event.type === 'click')) return;\n\n // 以前セットされたタイマーを止める\n window.clearTimeout(this.control_interval_id);\n\n // setTimeout に渡すタイマー関数\n const timeout = () => {\n\n // コメント入力フォームにフォーカスされているときは実行しない\n // タイマーを掛け直してから抜ける\n if (document.activeElement === this.player.template.commentInput) {\n this.control_interval_id = window.setTimeout(timeout, 3 * 1000);\n return;\n }\n\n // コントロールを非表示にする\n this.is_control_display = false;\n\n // プレイヤーのコントロールと設定パネルを非表示にする\n if (this.player !== null) {\n this.player.controller.hide();\n this.player.setting.hide();\n }\n }\n\n // タッチデバイスでプレイヤー画面がクリックされたとき\n if (is_touch_device === true && is_player_event === true) {\n\n // プレイヤーのコントロールの表示状態に合わせる\n if (this.player.controller.isShow()) {\n\n // コントロールを表示する\n this.is_control_display = true;\n\n // プレイヤーのコントロールを表示する\n this.player.controller.show();\n\n // 3秒間何も操作がなければコントロールを非表示にする\n // 3秒間の間一度でもマウスが動けばタイマーが解除されてやり直しになる\n this.control_interval_id = window.setTimeout(timeout, 3 * 1000);\n\n } else {\n\n // コントロールを非表示にする\n this.is_control_display = false;\n\n // プレイヤーのコントロールと設定パネルを非表示にする\n this.player.controller.hide();\n this.player.setting.hide();\n }\n\n // それ以外の画面がクリックされたとき\n } else {\n\n // コントロールを表示する\n this.is_control_display = true;\n\n // プレイヤーのコントロールを表示する\n if (this.player !== null) {\n this.player.controller.show();\n }\n\n // 3秒間何も操作がなければコントロールを非表示にする\n // 3秒間の間一度でもマウスが動けばタイマーが解除されてやり直しになる\n this.control_interval_id = window.setTimeout(timeout, 3 * 1000);\n }\n },\n\n // プレイヤーを初期化する\n initPlayer() {\n\n // mpegts.js を window 直下に入れる\n // こうしないと DPlayer が mpegts.js を認識できない\n (window as any).mpegts = mpegts;\n\n // すでに DPlayer が初期化されている場合は破棄する\n // チャンネル切り替え時などが該当する\n if (this.player !== null && this.player.KonomiTVCanDestroy === true) {\n try {\n this.player.destroy();\n } catch (error) {\n // mpegts.js をうまく破棄できない場合\n if (this.player.plugins.mpegts !== undefined) {\n this.player.plugins.mpegts.destroy();\n }\n }\n this.player = null;\n }\n\n // DPlayer を初期化\n this.player = new DPlayer({\n container: this.$el.querySelector('.watch-player__dplayer'),\n theme: '#E64F97', // テーマカラー\n lang: 'ja-jp', // 言語\n live: true, // ライブモード\n loop: false, // ループ再生 (ライブのため無効化)\n airplay: false, // AirPlay 機能 (うまく動かないため無効化)\n autoplay: true, // 自動再生\n hotkey: false, // ショートカットキー(こちらで制御するため無効化)\n screenshot: true, // スクリーンショット\n // screenshotOfEventTriggerOnly: true, // スクリーンショットボタンが押された際、イベントと Blob URL のみ受け取る\n volume: 1.0, // 音量の初期値\n // 映像\n video: {\n // デフォルトの品質\n // ラジオチャンネルでは常に 48KHz/192kbps に固定する\n defaultQuality: (this.channel.is_radiochannel) ? '48kHz/192kbps' : Utils.getSettingsItem('tv_streaming_quality'),\n // 品質リスト\n quality: (() => {\n const qualities = [];\n // ラジオチャンネル\n // API が受け付ける品質の値は通常のチャンネルと同じだが (手抜き…)、実際の品質は 48KHz/192kbps で固定される\n // ラジオチャンネルの場合は、1080p と渡しても 48kHz/192kbps 固定の音声だけの MPEG-TS が配信される\n if (this.channel.is_radiochannel) {\n qualities.push({\n name: '48kHz/192kbps',\n type: 'mpegts',\n url: `${Utils.api_base_url}/streams/live/${this.channel_id}/1080p/mpegts`,\n });\n // 通常のチャンネル\n } else {\n for (const quality of ['1080p', '810p', '720p', '540p', '480p', '360p', '240p']) {\n qualities.push({\n name: quality,\n type: 'mpegts',\n url: `${Utils.api_base_url}/streams/live/${this.channel_id}/${quality}/mpegts`,\n });\n }\n }\n return qualities;\n })(),\n },\n // コメント\n danmaku: {\n speedRate: Utils.getSettingsItem('comment_speed_rate'), // コメントの流れる速度\n fontSize: Utils.getSettingsItem('comment_font_size'), // コメントのフォントサイズ\n },\n // コメント API バックエンド\n apiBackend: {\n // コメント受信時\n read: (options) => {\n // 成功したことにして通知を抑制\n options.success([{}]);\n },\n // コメント送信時\n send: (options) => {\n // TODO: コメント送信は未実装\n options.error('現在、コメントの送信には対応していません。');\n },\n },\n // プラグイン\n pluginOptions: {\n // mpegts.js\n mpegts: {\n config: {\n enableWorker: true, // Web Worker を有効にする\n liveBufferLatencyChasing: true, // HTMLMediaElement の内部バッファによるライブストリームの待機時間を追跡する\n liveBufferLatencyMaxLatency: 3.0, // HTMLMediaElement で許容するバッファの最大値 (秒単位)\n liveBufferLatencyMinRemain: 0.5, // HTMLMediaElement に保持されるバッファの待機時間の最小値 (秒単位)\n }\n },\n // aribb24.js\n aribb24: {\n normalFont: '\"Windows TV MaruGothic\", \"Hiragino Maru Gothic Pro\", \"Yu Gothic Medium\", sans-serif',\n gaijiFont: '\"Windows TV MaruGothic\", \"Hiragino Maru Gothic Pro\", \"Yu Gothic Medium\", sans-serif',\n forceStrokeColor: 'black', // 縁取りする色\n drcsReplacement: true, // DRCS 文字を対応する Unicode 文字に置換\n enableRawCanvas: true, // 高解像度の字幕 Canvas を取得できるように\n useStrokeText: true, // 縁取りに strokeText API を利用\n }\n },\n // 字幕\n subtitle: {\n type: 'aribb24', // aribb24.js を有効化\n }\n });\n\n // デバッグ用にプレイヤーインスタンスも window 直下に入れる\n (window as any).player = this.player;\n\n // プレイヤー側のコントロール非表示タイマーを無効化(上書き)\n // 無効化しておかないと、controlDisplayTimer() と競合してしまう\n // 上書き元のコードは https://github.com/tsukumijima/DPlayer/blob/master/src/js/controller.js#L387-L395 にある\n this.player.controller.setAutoHide = (time: number) => {};\n\n // 設定パネルにショートカット一覧を表示するリンクを動的に追加する\n // タッチデバイスでは実行しない\n const is_touch_device = /iPhone|iPad|iPod|Macintosh|Android|Mobile/i.test(navigator.userAgent) && 'ontouchend' in document;\n if (is_touch_device === false) {\n this.player.template.settingOriginPanel.insertAdjacentHTML('beforeend', `\n
\n キーボードショートカット\n
\n \n \n \n
\n
`)\n\n // 設定パネルの高さを再設定\n const settingOriginPanelHeight = this.player.template.settingOriginPanel.scrollHeight;\n this.player.template.settingBox.style.clipPath = `inset(calc(100% - ${settingOriginPanelHeight}px) 0 0 round 7px)`;\n\n // 設定パネルのショートカット一覧を表示するリンクがクリックされたときのイベント\n // リアクティブではないので、手動でやらないといけない…\n this.$el.querySelector('.dplayer-setting-keyboard-shortcut').addEventListener('click', () => {\n this.player.setting.hide(); // 設定パネルを閉じる\n this.shortcut_key_modal = true;\n });\n }\n\n // 再生/停止されたとき\n // 通知バーからの制御など、画面から以外の外的要因で再生/停止が行われる事もある\n const on_play_or_pause = () => {\n\n // まだ設定パネルが表示されていたら非表示にする\n this.player.setting.hide();\n\n // コントロールを表示する\n this.controlDisplayTimer();\n }\n this.player.on('play', on_play_or_pause);\n this.player.on('pause', on_play_or_pause);\n\n // 画質の切り替えが開始されたとき\n this.player.on('quality_start', () => {\n\n // ローディング中の背景画像をランダムで設定\n this.background_url = Utils.generatePlayerBackgroundURL();\n\n // イベントソースを閉じる\n if (this.eventsource !== null) {\n this.eventsource.close();\n this.eventsource = null;\n }\n\n // 新しい EventSource を作成\n // 画質ごとにイベント API は異なるため、一度破棄してから作り直す\n this.initEventHandler();\n });\n\n // 字幕が非表示の場合でも、文字スーパーは表示する\n this.player.plugins.aribb24Superimpose.show();\n this.player.on('subtitle_hide', () => {\n this.player.plugins.aribb24Superimpose.show();\n });\n\n // 停止状態でかつ再生時間からバッファが 30 秒以上離れていないかを1分おきに監視し、そうなっていたら強制的にシークする\n // mpegts.js の仕様上、MSE に未再生のバッファがたまり過ぎると SourceBuffer が追加できなくなるため、強制的に接続が切断されてしまう\n this.interval_ids.push(window.setInterval(() => {\n if (this.player.video.paused && this.player.video.buffered.end(0) - this.player.video.currentTime > 30) {\n this.player.sync();\n }\n }, 60 * 1000));\n\n // フルスクリーンにするコンテナ要素(コンポーネント全体)\n const fullscreen_container = this.$el;\n this.fullscreen_handler = () => this.is_fullscreen = this.player.fullScreen.isFullScreen();\n if (fullscreen_container.onfullscreenchange !== undefined) {\n fullscreen_container.addEventListener('fullscreenchange', this.fullscreen_handler);\n } else {\n fullscreen_container.addEventListener('webkitfullscreenchange', this.fullscreen_handler);\n }\n\n // DPlayer のフルスクリーン関係のメソッドを無理やり上書きし、KonomiTV の UI と統合する\n // 上書き元のコードは https://github.com/tsukumijima/DPlayer/blob/master/src/js/fullscreen.js にある\n // フルスクリーンかどうか\n this.player.fullScreen.isFullScreen = (type: string) => {\n return !!(document.fullscreenElement || document.webkitFullscreenElement);\n }\n // フルスクリーンをリクエスト\n this.player.fullScreen.request = (type: string) => {\n\n // すでにフルスクリーンだったらキャンセルする\n if (this.player.fullScreen.isFullScreen()) {\n this.player.fullScreen.cancel();\n return;\n }\n\n // フルスクリーンをリクエスト\n // Safari は webkit のベンダープレフィックスが必要\n fullscreen_container.requestFullscreen = fullscreen_container.requestFullscreen || fullscreen_container.webkitRequestFullscreen;\n if (fullscreen_container.requestFullscreen) {\n fullscreen_container.requestFullscreen();\n }\n\n // 画面の向きを横に固定 (Screen Orientation API がサポートされている場合)\n if (screen.orientation) {\n screen.orientation.lock('landscape').catch(() => {});\n }\n }\n // フルスクリーンをキャンセル\n this.player.fullScreen.cancel = (type: string) => {\n\n // フルスクリーンを終了\n // Safari は webkit のベンダープレフィックスが必要\n document.exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen;\n if (document.exitFullscreen) {\n document.exitFullscreen();\n }\n\n // 画面の向きの固定を解除\n if (screen.orientation) {\n screen.orientation.unlock();\n }\n }\n },\n\n // イベントハンドラーを初期化する\n initEventHandler() {\n\n // 必ず最初はローディング状態とする\n this.is_loading = true;\n\n // プレイヤーの背景を非表示にするイベントを登録\n // 実際に再生可能になるのを待ってから実行する\n const on_canplay = () => {\n // 念のためさらに少しだけ待ってから\n window.setTimeout(() => {\n this.is_loading = false;\n // ラジオチャンネルでは映像の代わりに背景画像を表示し続ける\n if (this.channel.is_radiochannel) {\n this.is_background_display = true;\n } else {\n this.is_background_display = false;\n }\n }, 100);\n this.player.video.oncanplay = null;\n this.player.video.oncanplaythrough = null;\n }\n this.player.video.oncanplay = on_canplay;\n this.player.video.oncanplaythrough = on_canplay;\n\n // EventSource を作成\n // ラジオチャンネルの場合は見かけ上の品質と API に渡す品質が異なるので、それに合わせる\n const quality_name = (this.channel.is_radiochannel) ? '1080p' : this.player.quality.name;\n this.eventsource = new EventSource(`${Utils.api_base_url}/streams/live/${this.channel_id}/${quality_name}/events`);\n\n // 初回接続時のイベント\n this.eventsource.addEventListener('initial_update', (event_raw: MessageEvent) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n\n // ステータスが Standby であれば、プレイヤーの背景を表示する\n if (event.status === 'Standby') {\n this.is_background_display = true;\n }\n });\n\n // ステータスが更新されたときのイベント\n this.eventsource.addEventListener('status_update', (event_raw: MessageEvent) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n console.log(`Status: ${event.status} Detail:${event.detail}`);\n\n // 視聴者数を更新\n this.channel.viewers = event.clients_count;\n\n // ステータスごとに処理を振り分け\n switch (event.status) {\n\n // Status: Standby\n case 'Standby': {\n\n // ステータス詳細をプレイヤーに表示\n if (!this.player.template.notice.textContent.includes('画質を')) { // 画質切り替えの表示を上書きしない\n this.player.notice(event.detail, -1);\n }\n\n // プレイヤーの背景を表示する\n this.is_background_display = true;\n\n break;\n }\n\n // Status: ONAir\n case 'ONAir': {\n\n // ステータス詳細をプレイヤーから削除\n if (!this.player.template.notice.textContent.includes('画質を')) { // 画質切り替えの表示を上書きしない\n this.player.notice(this.player.template.notice.textContent, 0.000001);\n }\n\n // 前のプレイヤーインスタンスの Picture-in-Picture ウインドウが残っている場合、終了させてからもう一度切り替える\n // チャンネル切り替えが完了しても前の Picture-in-Picture ウインドウは再利用されないため、一旦終了させるしかない\n if (document.pictureInPictureElement) {\n document.exitPictureInPicture();\n this.player.video.requestPictureInPicture();\n }\n\n break;\n }\n\n // Status: Restart\n case 'Restart': {\n\n // ステータス詳細をプレイヤーに表示\n this.player.notice(event.detail, -1);\n\n // プレイヤーを再起動する\n this.player.switchVideo({\n url: this.player.quality.url,\n type: this.player.quality.type,\n });\n\n // 再起動しただけでは自動再生されないので、明示的に\n this.player.play();\n\n // プレイヤーの背景を表示する\n this.is_background_display = true;\n\n break;\n }\n\n // Status: Offline\n case 'Offline': {\n\n // ステータス詳細をプレイヤーに表示\n // 動画の読み込みエラーが送出された時にメッセージを上書きする\n this.player.notice(event.detail, -1);\n this.player.video.onerror = () => {\n this.player.notice(event.detail, -1);\n this.player.video.onerror = null;\n }\n\n // 描画されたコメントをクリア\n this.player.danmaku.clear()\n\n // 動画を停止する\n this.player.video.pause();\n\n // イベントソースを閉じる(復帰の見込みがないため)\n this.eventsource.close();\n\n // プレイヤーの背景を表示する\n this.is_background_display = true;\n\n break;\n }\n }\n });\n\n // ステータス詳細が更新されたときのイベント\n this.eventsource.addEventListener('detail_update', (event_raw: MessageEvent) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n console.log(`Status: ${event.status} Detail:${event.detail}`);\n\n // 視聴者数を更新\n this.channel.viewers = event.clients_count;\n\n // Standby のときだけプレイヤーに表示\n if (event.status === 'Standby') {\n this.player.notice(event.detail, -1);\n\n // プレイヤーの背景を表示する\n if (!this.is_background_display) {\n this.is_background_display = true;\n }\n }\n });\n\n // クライアント数(だけ)が更新されたときのイベント\n this.eventsource.addEventListener('clients_update', (event_raw: MessageEvent) => {\n\n // イベントを取得\n const event = JSON.parse(event_raw.data);\n\n // 視聴者数を更新\n this.channel.viewers = event.clients_count;\n });\n },\n\n // ショートカットキーを初期化する\n initShortcutKeyHandler() {\n\n // ショートカットキーハンドラー\n this.shortcut_key_handler = (event: KeyboardEvent) => {\n\n // キーリピート(押しっぱなし)状態の場合は基本実行しない\n // 押し続けると何度も同じ動作が実行されて大変な事になる…\n // ただ、キーリピートを使いたい場合もあるので、リピート状態をフラグとして保存する\n let is_repeat = false;\n if (event.repeat) is_repeat = true;\n\n // キーリピート状態は event.repeat を見る事でだいたい検知できるが、最初の何回かは検知できないこともある\n // そこで、0.1 秒以内に連続して発火したキーイベントは間引きも兼ねて実行しない\n const now = Date.now();\n if (now - this.shortcut_key_pressed_at < (0.1 * 1000)) return;\n this.shortcut_key_pressed_at = now; // 最終押下時刻を更新\n\n // input・textarea・contenteditable 状態の要素でなければ\n // 文字入力中にショートカットキーが作動してしまわないように\n const tag = document.activeElement.tagName.toUpperCase();\n const editable = document.activeElement.getAttribute('contenteditable');\n if (tag !== 'INPUT' && tag !== 'TEXTAREA' && editable !== '' && editable !== 'true') {\n\n // ***** 数字キーでチャンネルを切り替える *****\n\n if (is_repeat === false) {\n\n // チャンネルタイプを選択\n // Shift キーが押されていたらチャンネルタイプを地デジならBSに、BSなら地デジにする\n let switch_channel_type = this.channel.channel_type;\n if (event.shiftKey && this.channel.channel_type == 'GR') switch_channel_type = 'BS';\n if (event.shiftKey && this.channel.channel_type == 'BS') switch_channel_type = 'GR';\n\n // 1~9キー\n let switch_remocon_id = null;\n if (event.code === 'Digit1' || event.code === 'Digit2' || event.code === 'Digit3' ||\n event.code === 'Digit4' || event.code === 'Digit5' || event.code === 'Digit6' ||\n event.code === 'Digit7' || event.code === 'Digit8' || event.code === 'Digit9') {\n switch_remocon_id = Number(event.code.replace('Digit', ''));\n }\n // 0キー: 10に割り当て\n if (event.code === 'Digit0') switch_remocon_id = 10;\n // -キー: 11に割り当て\n if (event.code === 'Minus') switch_remocon_id = 11;\n // ^キー: 12に割り当て\n if (event.code === 'Equal') switch_remocon_id = 12;\n // 1~9キー (テンキー)\n if (event.code === 'Numpad1' || event.code === 'Numpad2' || event.code === 'Numpad3' ||\n event.code === 'Numpad4' || event.code === 'Numpad5' || event.code === 'Numpad6' ||\n event.code === 'Numpad7' || event.code === 'Numpad8' || event.code === 'Numpad9') {\n switch_remocon_id = Number(event.code.replace('Numpad', ''));\n }\n // 0キー (テンキー): 10に割り当て\n if (event.code === 'Numpad0') switch_remocon_id = 10;\n\n // この時点でリモコン番号が取得できていたら実行\n if (switch_remocon_id !== null) {\n\n // 切り替え先のチャンネルを取得する\n const switch_channel = TVUtils.getChannelFromRemoconID(this.channels_list, switch_channel_type, switch_remocon_id);\n\n // チャンネルが取得できていれば、ルーティングをそのチャンネルに置き換える\n // 押されたキーに対応するリモコン番号のチャンネルがない場合や、現在と同じチャンネル ID の場合は何も起こらない\n if (switch_channel !== null && switch_channel.channel_id !== this.channel_id) {\n (async () => await this.$router.replace({path: `/tv/watch/${switch_channel.channel_id}`}))();\n return;\n }\n }\n }\n\n // ***** 上下キーでチャンネルを切り替える *****\n\n // ↑キー: 前のチャンネルに切り替え\n if (event.code === 'ArrowUp' && is_repeat === false) {\n event.preventDefault(); // デフォルトのイベントを無効化\n (async () => await this.$router.replace({path: `/tv/watch/${this.channel_previous.channel_id}`}))();\n return;\n }\n // ↓キー: 次のチャンネルに切り替え\n if (event.code === 'ArrowDown' && is_repeat === false) {\n event.preventDefault(); // デフォルトのイベントを無効化\n (async () => await this.$router.replace({path: `/tv/watch/${this.channel_next.channel_id}`}))();\n return;\n }\n\n // ***** キーボードショートカットの一覧を表示する *****\n\n // /(?)キー: キーボードショートカットの一覧を表示する\n if (event.code === 'Slash' && is_repeat === false) {\n this.shortcut_key_modal = !this.shortcut_key_modal;\n return;\n }\n\n // ***** パネルのタブを切り替える *****\n\n if (is_repeat === false) {\n // Pキー: パネルの表示切り替え\n if (event.code === 'KeyP') {\n this.is_panel_display = !this.is_panel_display;\n return;\n }\n // Kキー: 番組情報タブ\n if (event.code === 'KeyK') {\n this.panel_active_tab = 'Program';\n return;\n }\n // Lキー: チャンネルタブ\n if (event.code === 'KeyL') {\n this.panel_active_tab = 'Channel';\n return;\n }\n // ;(+)キー: コメントタブ\n if (event.code === 'Semicolon') {\n this.panel_active_tab = 'Comment';\n return;\n }\n // :(*)キー: Twitterタブ\n if (event.code === 'Quote') {\n this.panel_active_tab = 'Twitter';\n return;\n }\n }\n\n // ***** プレイヤーのショートカットキー *****\n\n // プレイヤーが初期化されていない際や Ctrl or Cmd キーが一緒に押された際に作動しないように\n if (this.player !== null && !event.ctrlKey && !event.metaKey) {\n // ←キー: 停止して0.25秒巻き戻し\n // ここだけキーリピートを許可する\n if (event.code === 'ArrowLeft') {\n event.preventDefault(); // デフォルトのイベントを無効化\n if (this.player.video.paused === false) this.player.video.pause();\n this.player.video.currentTime = this.player.video.currentTime - 0.25;\n return;\n }\n // →キー: 停止して0.25秒早送り\n // ここだけキーリピートを許可する\n if (event.code === 'ArrowRight') {\n event.preventDefault(); // デフォルトのイベントを無効化\n if (this.player.video.paused === false) this.player.video.pause();\n this.player.video.currentTime = this.player.video.currentTime + 0.25;\n return;\n }\n if (is_repeat === false) {\n // Spaceキー: 再生/停止\n if (event.code === 'Space') {\n this.player.toggle();\n return;\n }\n // Fキー: フルスクリーンの切り替え\n if (event.code === 'KeyF') {\n this.player.fullScreen.toggle();\n return;\n }\n // Wキー: ライブストリームの同期\n if (event.code === 'KeyW') {\n this.player.sync();\n return;\n }\n // Eキー: Picture-in-Picture の表示切り替え\n if (event.code === 'KeyE') {\n if (document.pictureInPictureEnabled) {\n this.player.template.pipButton.click();\n }\n return;\n }\n // Sキー: 字幕の表示切り替え\n if (event.code === 'KeyS') {\n this.player.subtitle.toggle();\n if (!this.player.subtitle.container.classList.contains('dplayer-subtitle-hide')) {\n this.player.notice(`${this.player.tran('Show subtitle')}`);\n } else {\n this.player.notice(`${this.player.tran('Hide subtitle')}`);\n }\n return;\n }\n // Dキー: コメントの表示切り替え\n if (event.code === 'KeyD') {\n this.player.template.showDanmaku.click();\n if (this.player.template.showDanmakuToggle.checked) {\n this.player.notice(`${this.player.tran('Show comment')}`);\n } else {\n this.player.notice(`${this.player.tran('Hide comment')}`);\n }\n return;\n }\n // Mキー: コメント入力フォームにフォーカス\n if (event.code === 'KeyM') {\n event.preventDefault(); // デフォルトのイベントを無効化\n this.player.controller.show();\n this.player.comment.show();\n this.controlDisplayTimer();\n window.setTimeout(() => this.player.template.commentInput.focus(), 100);\n return;\n }\n }\n }\n }\n };\n\n // ページ上でキーが押されたときのイベントを登録\n document.addEventListener('keydown', this.shortcut_key_handler);\n },\n\n // 破棄する\n destroy(is_destroy_player = false) {\n\n // clearInterval() ですべての setInterval(), setTimeout() の実行を止める\n // clearInterval() と clearTimeout() は中身共通なので問題ない\n for (const interval_id of this.interval_ids) {\n window.clearInterval(interval_id);\n }\n\n // コントロール表示制御用タイマーを止める\n window.clearTimeout(this.control_interval_id);\n\n // interval_ids をクリア\n this.interval_ids = [];\n\n // 再びローディング状態にする\n this.is_loading = true;\n\n // プレイヤーの背景を隠す\n this.is_background_display = false;\n\n // プレイヤーに破棄が可能なフラグをつける\n this.player.KonomiTVCanDestroy = true;\n\n // イベントソースを閉じる\n if (this.eventsource !== null) {\n this.eventsource.close();\n this.eventsource = null;\n }\n\n // アニメーション分待ってから実行\n this.interval_ids.push(window.setTimeout(() => {\n\n // プレイヤーを停止する\n this.player.video.pause();\n\n // is_destroy_player が true の時は、ここで DPlayer 自体を破棄する\n // false の時は次の initPlayer() が実行されるまで破棄されない\n if (is_destroy_player === true && this.player !== null) {\n try {\n this.player.destroy();\n } catch (error) {\n // mpegts.js をうまく破棄できない場合\n if (this.player.plugins.mpegts !== undefined) {\n this.player.plugins.mpegts.destroy();\n }\n }\n this.player = null;\n }\n\n }, 400)); // 0.4 秒\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Watch.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Watch.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Watch.vue?vue&type=template&id=8b237ea4&scoped=true&\"\nimport script from \"./Watch.vue?vue&type=script&lang=ts&\"\nexport * from \"./Watch.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Watch.vue?vue&type=style&index=0&lang=scss&\"\nimport style1 from \"./Watch.vue?vue&type=style&index=1&id=8b237ea4&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"8b237ea4\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VBtn } from 'vuetify/lib/components/VBtn';\nimport { VCard } from 'vuetify/lib/components/VCard';\nimport { VCardActions } from 'vuetify/lib/components/VCard';\nimport { VCardTitle } from 'vuetify/lib/components/VCard';\nimport { VCol } from 'vuetify/lib/components/VGrid';\nimport { VDialog } from 'vuetify/lib/components/VDialog';\nimport { VDivider } from 'vuetify/lib/components/VDivider';\nimport { VRow } from 'vuetify/lib/components/VGrid';\nimport { VSpacer } from 'vuetify/lib/components/VGrid';\ninstallComponents(component, {VBtn,VCard,VCardActions,VCardTitle,VCol,VDialog,VDivider,VRow,VSpacer})\n\n\n/* vuetify-loader */\nimport installDirectives from \"!../../../node_modules/vuetify-loader/lib/runtime/installDirectives.js\"\nimport Ripple from 'vuetify/lib/directives/ripple'\ninstallDirectives(component, {Ripple})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Base',[_c('h2',{staticClass:\"settings__heading\"},[_c('Icon',{attrs:{\"icon\":\"fa-solid:sliders-h\",\"width\":\"18px\"}}),_c('span',{staticClass:\"ml-3\"},[_vm._v(\"全般\")])],1),_c('div',{staticClass:\"settings__content\"},[_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"テレビのストリーミング画質\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" テレビをライブストリーミングする際の既定の画質を設定します。\"),_c('br'),_vm._v(\" ストリーミング画質はプレイヤーの設定からいつでも切り替えられます。\"),_c('br')]),_c('v-select',{staticClass:\"settings__item-form\",attrs:{\"outlined\":\"\",\"hide-details\":\"\",\"items\":_vm.tv_streaming_quality},model:{value:(_vm.settings.tv_streaming_quality),callback:function ($$v) {_vm.$set(_vm.settings, \"tv_streaming_quality\", $$v)},expression:\"settings.tv_streaming_quality\"}})],1),_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"既定のパネルの表示状態\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" 視聴画面を開いたときに、右側のパネルをどう表示するかを設定します。\"),_c('br')]),_c('v-select',{staticClass:\"settings__item-form\",attrs:{\"outlined\":\"\",\"hide-details\":\"\",\"items\":_vm.panel_display_state},model:{value:(_vm.settings.panel_display_state),callback:function ($$v) {_vm.$set(_vm.settings, \"panel_display_state\", $$v)},expression:\"settings.panel_display_state\"}})],1),_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"既定で表示されるパネルのタブ\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" 視聴画面を開いたときに、右側のパネルで最初に表示されるタブを設定します。\"),_c('br')]),_c('v-select',{staticClass:\"settings__item-form\",attrs:{\"outlined\":\"\",\"hide-details\":\"\",\"items\":_vm.panel_active_tab},model:{value:(_vm.settings.panel_active_tab),callback:function ($$v) {_vm.$set(_vm.settings, \"panel_active_tab\", $$v)},expression:\"settings.panel_active_tab\"}})],1)])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"route-container\"},[_c('Header'),_c('main',[_c('Navigation'),_c('v-card',{staticClass:\"settings-container d-flex px-5 py-5 mx-auto background\",attrs:{\"elevation\":\"0\",\"width\":\"100%\",\"max-width\":\"1000\"}},[_c('div',[_c('v-navigation-drawer',{staticClass:\"settings-navigation flex-shrink-0 background\",attrs:{\"permanent\":\"\",\"width\":\"195\",\"height\":\"auto\"}},[_c('v-list-item',{staticClass:\"px-4\"},[_c('v-list-item-content',[_c('h1',[_vm._v(\"設定\")])])],1),_c('v-list',{staticClass:\"mt-2 px-0\",attrs:{\"nav\":\"\"}},[_c('v-list-item',{staticClass:\"px-4\",attrs:{\"link\":\"\",\"color\":\"primary\",\"to\":\"/settings/general\"}},[_c('v-list-item-icon',{staticClass:\"mr-4\"},[_c('Icon',{staticStyle:{\"padding\":\"0 3px\"},attrs:{\"icon\":\"fa-solid:sliders-h\",\"width\":\"26px\"}})],1),_c('v-list-item-content',[_c('v-list-item-title',[_vm._v(\"全般\")])],1)],1),_c('v-list-item',{staticClass:\"px-4\",attrs:{\"link\":\"\",\"color\":\"primary\",\"to\":\"/settings/account\"}},[_c('v-list-item-icon',{staticClass:\"mr-4\"},[_c('Icon',{attrs:{\"icon\":\"fluent:person-20-filled\",\"width\":\"26px\"}})],1),_c('v-list-item-content',[_c('v-list-item-title',[_vm._v(\"アカウント\")])],1)],1),_c('v-list-item',{staticClass:\"px-4\",attrs:{\"link\":\"\",\"color\":\"primary\",\"to\":\"/settings/jikkyo\"}},[_c('v-list-item-icon',{staticClass:\"mr-4\"},[_c('Icon',{staticStyle:{\"padding\":\"0 2px\"},attrs:{\"icon\":\"bi:chat-left-text-fill\",\"width\":\"26px\"}})],1),_c('v-list-item-content',[_c('v-list-item-title',[_vm._v(\"ニコニコ実況\")])],1)],1),_c('v-list-item',{staticClass:\"px-4\",attrs:{\"link\":\"\",\"color\":\"primary\",\"to\":\"/settings/twitter\"}},[_c('v-list-item-icon',{staticClass:\"mr-4\"},[_c('Icon',{staticStyle:{\"padding\":\"0 1px\"},attrs:{\"icon\":\"fa-brands:twitter\",\"width\":\"26px\"}})],1),_c('v-list-item-content',[_c('v-list-item-title',[_vm._v(\"Twitter\")])],1)],1)],1)],1)],1),_c('v-card',{staticClass:\"settings ml-5 px-7 py-7 background lighten-1\",attrs:{\"width\":\"100%\"}},[_vm._t(\"default\")],2)],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Header from '@/components/Header.vue';\nimport Navigation from '@/components/Navigation.vue';\n\n// 設定のベース画面なので、ロジックは基本置かない\nexport default Vue.extend({\n name: 'SettingsBase',\n components: {\n Header,\n Navigation,\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Base.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Base.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Base.vue?vue&type=template&id=18637a38&scoped=true&\"\nimport script from \"./Base.vue?vue&type=script&lang=ts&\"\nexport * from \"./Base.vue?vue&type=script&lang=ts&\"\nimport style0 from \"./Base.vue?vue&type=style&index=0&id=18637a38&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"18637a38\",\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VCard } from 'vuetify/lib/components/VCard';\nimport { VList } from 'vuetify/lib/components/VList';\nimport { VListItem } from 'vuetify/lib/components/VList';\nimport { VListItemContent } from 'vuetify/lib/components/VList';\nimport { VListItemIcon } from 'vuetify/lib/components/VList';\nimport { VListItemTitle } from 'vuetify/lib/components/VList';\nimport { VNavigationDrawer } from 'vuetify/lib/components/VNavigationDrawer';\ninstallComponents(component, {VCard,VList,VListItem,VListItemContent,VListItemIcon,VListItemTitle,VNavigationDrawer})\n","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Base from '@/views/Settings/Base.vue';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'SettingsGeneral',\n components: {\n Base,\n },\n data() {\n return {\n\n // テレビのストリーミング画質の選択肢\n tv_streaming_quality: [\n {'text': '1080p (1時間あたり約2.31GB / 5.1Mbps)', 'value': '1080p'},\n {'text': '810p (1時間あたり約1.92GB / 4.2Mbps)', 'value': '810p'},\n {'text': '720p (1時間あたり約1.33GB / 3.0Mbps)', 'value': '720p'},\n {'text': '540p (1時間あたり約1.00GB / 2.2Mbps)', 'value': '540p'},\n {'text': '480p (1時間あたり約0.74GB / 1.6Mbps)', 'value': '480p'},\n {'text': '360p (1時間あたり約0.40GB / 0.9Mbps)', 'value': '360p'},\n {'text': '240p (1時間あたり約0.23GB / 0.5Mbps)', 'value': '240p'},\n ],\n\n // 既定のパネルの表示状態の選択肢\n panel_display_state: [\n {'text': '前回の状態を復元する', 'value': 'RestorePreviousState'},\n {'text': '常に表示する', 'value': 'AlwaysDisplay'},\n {'text': '常に折りたたむ', 'value': 'AlwaysFold'},\n ],\n\n // 既定で表示されるパネルのタブの選択肢\n panel_active_tab: [\n {'text': '番組情報タブ', 'value': 'Program'},\n {'text': 'チャンネルタブ', 'value': 'Channel'},\n {'text': 'コメントタブ', 'value': 'Comment'},\n {'text': 'Twitter タブ', 'value': 'Twitter'},\n ],\n\n // 設定値が保存されるオブジェクト\n // ここの値とフォームを v-model で binding する\n settings: (() => {\n // 設定の既定値を取得する\n const settings = {}\n for (const setting of ['tv_streaming_quality', 'panel_display_state', 'panel_active_tab']) {\n settings[setting] = Utils.getSettingsItem(setting);\n }\n return settings;\n })(),\n }\n },\n watch: {\n // settings 内の値の変更を監視する\n settings: {\n deep: true,\n handler() {\n // settings 内の値を順に LocalStorage に保存する\n for (const [setting_key, setting_value] of Object.entries(this.settings)) {\n Utils.setSettingsItem(setting_key, setting_value);\n }\n }\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./General.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./General.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./General.vue?vue&type=template&id=7c670856&\"\nimport script from \"./General.vue?vue&type=script&lang=ts&\"\nexport * from \"./General.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VSelect } from 'vuetify/lib/components/VSelect';\ninstallComponents(component, {VSelect})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Base',[_c('h2',{staticClass:\"settings__heading\"},[_c('Icon',{attrs:{\"icon\":\"fluent:person-20-filled\",\"width\":\"24px\"}}),_c('span',{staticClass:\"ml-2\"},[_vm._v(\"アカウント\")])],1),_c('div',{staticClass:\"settings__content\"},[_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"鋭意開発中…\")])])])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Base from '@/views/Settings/Base.vue';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'SettingsAccount',\n components: {\n Base,\n },\n data() {\n return {\n\n // 設定値が保存されるオブジェクト\n // ここの値とフォームを v-model で binding する\n settings: (() => {\n // 設定の既定値を取得する\n const settings = {}\n for (const setting of []) {\n settings[setting] = Utils.getSettingsItem(setting);\n }\n return settings;\n })(),\n }\n },\n watch: {\n // settings 内の値の変更を監視する\n settings: {\n deep: true,\n handler() {\n // settings 内の値を順に LocalStorage に保存する\n for (const [setting_key, setting_value] of Object.entries(this.settings)) {\n Utils.setSettingsItem(setting_key, setting_value);\n }\n }\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Account.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Account.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Account.vue?vue&type=template&id=19541e55&\"\nimport script from \"./Account.vue?vue&type=script&lang=ts&\"\nexport * from \"./Account.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Base',[_c('h2',{staticClass:\"settings__heading\"},[_c('Icon',{attrs:{\"icon\":\"bi:chat-left-text-fill\",\"width\":\"18px\"}}),_c('span',{staticClass:\"ml-3\"},[_vm._v(\"ニコニコ実況\")])],1),_c('div',{staticClass:\"settings__content\"},[_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"コメントの速さ\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" プレイヤーに流れるコメントの速さを設定します。\"),_c('br'),_vm._v(\" たとえば 1.2 に設定すると、コメントが 1.2 倍速く流れます。\"),_c('br')]),_c('v-slider',{staticClass:\"settings__item-form\",attrs:{\"ticks\":\"always\",\"thumb-label\":\"\",\"hide-details\":\"\",\"step\":0.1,\"min\":0.5,\"max\":2},model:{value:(_vm.settings.comment_speed_rate),callback:function ($$v) {_vm.$set(_vm.settings, \"comment_speed_rate\", $$v)},expression:\"settings.comment_speed_rate\"}})],1),_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"コメントの文字サイズ\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" プレイヤーに流れるコメントの文字サイズの基準値を設定します。\"),_c('br'),_vm._v(\" 実際の文字サイズは画面の大きさに合わせて調整されます。既定の文字サイズは 34px です。\"),_c('br')]),_c('v-slider',{staticClass:\"settings__item-form\",attrs:{\"ticks\":\"always\",\"thumb-label\":\"\",\"hide-details\":\"\",\"min\":20,\"max\":60},model:{value:(_vm.settings.comment_font_size),callback:function ($$v) {_vm.$set(_vm.settings, \"comment_font_size\", $$v)},expression:\"settings.comment_font_size\"}})],1),_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"コメントの遅延時間\")]),_c('div',{staticClass:\"settings__item-label\"},[_vm._v(\" プレイヤーやコメントリストに表示されるコメントを何秒遅らせて反映するかを設定します。\"),_c('br'),_vm._v(\" 通常は 1 秒程度で大丈夫です。ネットワークが遅いなどでタイムラグが大きいときだけ、映像の遅延に合わせて調整してください。\"),_c('br')]),_c('v-slider',{staticClass:\"settings__item-form\",attrs:{\"ticks\":\"always\",\"thumb-label\":\"\",\"hide-details\":\"\",\"step\":0.5,\"min\":0,\"max\":5},model:{value:(_vm.settings.comment_delay_time),callback:function ($$v) {_vm.$set(_vm.settings, \"comment_delay_time\", $$v)},expression:\"settings.comment_delay_time\"}})],1)])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Base from '@/views/Settings/Base.vue';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'SettingsJikkyo',\n components: {\n Base,\n },\n data() {\n return {\n\n // 設定値が保存されるオブジェクト\n // ここの値とフォームを v-model で binding する\n settings: (() => {\n // 設定の既定値を取得する\n const settings = {}\n for (const setting of ['comment_speed_rate', 'comment_font_size', 'comment_delay_time']) {\n settings[setting] = Utils.getSettingsItem(setting);\n }\n return settings;\n })(),\n }\n },\n watch: {\n // settings 内の値の変更を監視する\n settings: {\n deep: true,\n handler() {\n // settings 内の値を順に LocalStorage に保存する\n for (const [setting_key, setting_value] of Object.entries(this.settings)) {\n Utils.setSettingsItem(setting_key, setting_value);\n }\n }\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Jikkyo.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Jikkyo.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Jikkyo.vue?vue&type=template&id=cc7a4024&\"\nimport script from \"./Jikkyo.vue?vue&type=script&lang=ts&\"\nexport * from \"./Jikkyo.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports\n\n/* vuetify-loader */\nimport installComponents from \"!../../../node_modules/vuetify-loader/lib/runtime/installComponents.js\"\nimport { VSlider } from 'vuetify/lib/components/VSlider';\ninstallComponents(component, {VSlider})\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Base',[_c('h2',{staticClass:\"settings__heading\"},[_c('Icon',{attrs:{\"icon\":\"fa-brands:twitter\",\"width\":\"21px\"}}),_c('span',{staticClass:\"ml-3\"},[_vm._v(\"Twitter\")])],1),_c('div',{staticClass:\"settings__content\"},[_c('div',{staticClass:\"settings__item\"},[_c('div',{staticClass:\"settings__item-heading\"},[_vm._v(\"鋭意開発中…\")])])])])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Base from '@/views/Settings/Base.vue';\nimport Utils from '@/utils';\n\nexport default Vue.extend({\n name: 'SettingsAccount',\n components: {\n Base,\n },\n data() {\n return {\n\n // 設定値が保存されるオブジェクト\n // ここの値とフォームを v-model で binding する\n settings: (() => {\n // 設定の既定値を取得する\n const settings = {}\n for (const setting of []) {\n settings[setting] = Utils.getSettingsItem(setting);\n }\n return settings;\n })(),\n }\n },\n watch: {\n // settings 内の値の変更を監視する\n settings: {\n deep: true,\n handler() {\n // settings 内の値を順に LocalStorage に保存する\n for (const [setting_key, setting_value] of Object.entries(this.settings)) {\n Utils.setSettingsItem(setting_key, setting_value);\n }\n }\n }\n }\n});\n\n","import mod from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Twitter.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/ts-loader/index.js??ref--15-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Twitter.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./Twitter.vue?vue&type=template&id=07e6e1f8&\"\nimport script from \"./Twitter.vue?vue&type=script&lang=ts&\"\nexport * from \"./Twitter.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"route-container\"},[_c('Header'),_c('main',[_c('Navigation'),_vm._m(0)],1)],1)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"d-flex justify-center align-center w-100\"},[_c('div',{staticClass:\"d-flex justify-center align-center flex-column\"},[_c('h1',[_vm._v(\"Not Found, or Under Development...\")]),_c('span',{staticClass:\"mt-4 text--text text--darken-1\"},[_vm._v(\"お探しのページは存在しないか、鋭意開発中です。\")])])])}]\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nimport Vue from 'vue';\n\nimport Header from '@/components/Header.vue';\nimport Navigation from '@/components/Navigation.vue';\n\nexport default Vue.extend({\n name: 'Home',\n components: {\n Header,\n Navigation,\n },\n});\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--15-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./NotFound.vue?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--15-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??ref--15-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./NotFound.vue?vue&type=script&lang=ts&\"","import { render, staticRenderFns } from \"./NotFound.vue?vue&type=template&id=161dd190&\"\nimport script from \"./NotFound.vue?vue&type=script&lang=ts&\"\nexport * from \"./NotFound.vue?vue&type=script&lang=ts&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","\nimport Vue from 'vue';\nimport VueRouter from 'vue-router';\n\nimport TVHome from '@/views/TV/Home.vue';\nimport TVWatch from '@/views/TV/Watch.vue';\nimport SettingsGeneral from '@/views/Settings/General.vue';\nimport SettingsAccount from '@/views/Settings/Account.vue';\nimport SettingsJikkyo from '@/views/Settings/Jikkyo.vue';\nimport SettingsTwitter from '@/views/Settings/Twitter.vue';\nimport NotFound from '@/views/NotFound.vue';\n\nVue.use(VueRouter);\n\nconst routes = [\n {\n path: '/',\n redirect: '/tv/',\n },\n {\n path: '/tv/',\n name: 'TV Home',\n component: TVHome,\n },\n {\n path: '/tv/watch/:channel_id',\n name: 'TV Watch',\n component: TVWatch,\n },\n {\n path: '/settings/',\n redirect: '/settings/general',\n },\n {\n path: '/settings/general',\n name: 'Settings General',\n component: SettingsGeneral,\n },\n {\n path: '/settings/account',\n name: 'Settings Account',\n component: SettingsAccount,\n },\n {\n path: '/settings/jikkyo',\n name: 'Settings Jikkyo',\n component: SettingsJikkyo,\n },\n {\n path: '/settings/twitter',\n name: 'Settings Twitter',\n component: SettingsTwitter,\n },\n {\n path: '*',\n name: 'NotFound',\n component: NotFound,\n },\n];\n\nconst router = new VueRouter({\n mode: 'history',\n base: process.env.BASE_URL,\n routes,\n});\n\nexport default router;\n","/* eslint-disable no-console */\n\nimport { register } from 'register-service-worker';\n\nif (process.env.NODE_ENV === 'production') {\n register(`${process.env.BASE_URL}service-worker.js`, {\n ready () {\n console.log(\n 'App is being served from cache by a service worker.\\n' +\n 'For more details, visit https://goo.gl/AFskqB'\n )\n },\n registered () {\n console.log('Service worker has been registered.')\n },\n cached () {\n console.log('Content has been cached for offline use.')\n },\n updatefound () {\n console.log('New content is downloading.')\n },\n updated () {\n console.log('New content is available; please refresh.')\n },\n offline () {\n console.log('No internet connection found. App is running in offline mode.')\n },\n error (error) {\n console.error('Error during service worker registration:', error)\n }\n });\n}\n","\nimport axios from 'axios';\nimport { Icon } from '@iconify/vue2';\nimport Vue from 'vue';\nimport VueAxios from 'vue-axios';\nimport VueVirtualScroller from 'vue-virtual-scroller'\nimport 'vue-virtual-scroller/dist/vue-virtual-scroller.css'\nimport VTooltip from 'v-tooltip';\nimport 'v-tooltip/dist/v-tooltip.css'\n\nimport App from '@/App.vue';\nimport VTabItem from '@/components/VTabItem';\nimport VTabs from '@/components/VTabs';\nimport VTabsItems from '@/components/VTabsItems';\nimport vuetify from '@/plugins/vuetify';\nimport router from '@/router';\nimport '@/service-worker';\n\n// Production Tip を非表示に\nVue.config.productionTip = false;\n\n// Axios を使う\nVue.use(VueAxios, axios);\n\n// vue-virtual-scroller を使う\nVue.use(VueVirtualScroller)\n\n// VTooltip を使う\n// タッチデバイスでは無効化する\n// ref: https://v-tooltip.netlify.app/guide/config.html#default-values\nconst trigger = window.matchMedia('(hover: none)').matches ? [] : ['hover', 'focus', 'touch'];\nVTooltip.options.themes.tooltip.showTriggers = trigger;\nVTooltip.options.themes.tooltip.hideTriggers = trigger;\nVTooltip.options.themes.tooltip.delay.show = 0;\nVTooltip.options.offset = [0, 7];\nVue.use(VTooltip);\n\n// Iconify(アイコン)のグローバルコンポーネント\nVue.component('Icon', Icon);\n\n// VTabItem の挙動を改善するグローバルコンポーネント\nVue.component('v-tab-item-fix', VTabItem);\n\n// VTabs の挙動を改善するグローバルコンポーネント\nVue.component('v-tabs-fix', VTabs);\n\n// VTabsItems の挙動を改善するグローバルコンポーネント\nVue.component('v-tabs-items-fix', VTabsItems);\n\n// Vue を初期化\nnew Vue({\n router,\n vuetify,\n render: h => h(App),\n}).$mount('#app');\n","export * from \"-!../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Navigation.vue?vue&type=style&index=0&id=4fdece88&lang=scss&scoped=true&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Watch.vue?vue&type=style&index=1&id=8b237ea4&lang=scss&scoped=true&\"","export * from \"-!../../../node_modules/mini-css-extract-plugin/dist/loader.js??ref--9-oneOf-1-0!../../../node_modules/css-loader/dist/cjs.js??ref--9-oneOf-1-1!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/src/index.js??ref--9-oneOf-1-2!../../../node_modules/sass-loader/dist/cjs.js??ref--9-oneOf-1-3!../../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Home.vue?vue&type=style&index=1&id=6a407b07&lang=scss&scoped=true&\""],"sourceRoot":""} \ No newline at end of file diff --git a/client/dist/index.html b/client/dist/index.html index 6e77cdfd..7e393a82 100644 --- a/client/dist/index.html +++ b/client/dist/index.html @@ -1 +1 @@ -KonomiTV
\ No newline at end of file +KonomiTV
\ No newline at end of file diff --git a/client/dist/precache-manifest.e73bf034e42f86b9c267034331a574e4.js b/client/dist/precache-manifest.19310fb74dc336db1e4ce7f0a23c5f3c.js similarity index 90% rename from client/dist/precache-manifest.e73bf034e42f86b9c267034331a574e4.js rename to client/dist/precache-manifest.19310fb74dc336db1e4ce7f0a23c5f3c.js index 448bc7b5..b73f17d6 100644 --- a/client/dist/precache-manifest.e73bf034e42f86b9c267034331a574e4.js +++ b/client/dist/precache-manifest.19310fb74dc336db1e4ce7f0a23c5f3c.js @@ -1,7 +1,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ { - "revision": "24fe3c50086cb698c6dc", - "url": "/assets/css/app.7dbdd8c6.css" + "revision": "d94fc954ab79c4550321", + "url": "/assets/css/app.7b2ec17c.css" }, { "revision": "0b61f582b43cdaaab9bd", @@ -64,15 +64,15 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([ "url": "/assets/img/player-backgrounds/12.jpg" }, { - "revision": "24fe3c50086cb698c6dc", - "url": "/assets/js/app.d1a5668b.js" + "revision": "d94fc954ab79c4550321", + "url": "/assets/js/app.bf991577.js" }, { "revision": "0b61f582b43cdaaab9bd", "url": "/assets/js/chunk-vendors.9091e8fb.js" }, { - "revision": "0479e88a7d36cca8c779538c788448a8", + "revision": "939007b574fc4fc94248207e7a13b9d1", "url": "/index.html" }, { diff --git a/client/dist/service-worker.js b/client/dist/service-worker.js index 279a6ede..5bb5e984 100644 --- a/client/dist/service-worker.js +++ b/client/dist/service-worker.js @@ -14,7 +14,7 @@ importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); importScripts( - "/precache-manifest.e73bf034e42f86b9c267034331a574e4.js" + "/precache-manifest.19310fb74dc336db1e4ce7f0a23c5f3c.js" ); workbox.core.setCacheNameDetails({prefix: "KonomiTV"}); diff --git a/client/package.json b/client/package.json index 835c6754..a665bf50 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "KonomiTV", - "version": "0.4.0", + "version": "0.5.0", "private": true, "scripts": { "dev": "vue-cli-service serve", diff --git a/client/src/App.vue b/client/src/App.vue index 83c974e1..e3fddbcd 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -113,7 +113,6 @@ body .route-container { // ルートコンテナ } .v-menu__content { - overflow: hidden; &::-webkit-scrollbar { width: 12px; height: 12px; diff --git a/server/app/constants.py b/server/app/constants.py index 2aac6df4..54941d9a 100644 --- a/server/app/constants.py +++ b/server/app/constants.py @@ -120,4 +120,4 @@ } # バージョン -VERSION = '0.4.0' +VERSION = '0.5.0'