// ==UserScript==
// @name Miss Player | 影院模式 (单手播放器)
// @name:en Miss Player | Theater Mode (One-handed Player)
// @name:ja Miss Player | シアターモード (片手プレーヤー)
// @name:vi Miss Player | Chế Độ Rạp Hát (Trình Phát Một Tay)
// @name:zh-CN Miss Player | 影院模式 (单手播放器)
// @name:zh-TW Miss Player | 影院模式 (單手播放器)
// @description MissAV去广告|单手模式|MissAV自动展开详情|MissAV自动高画质|MissAV重定向支持|MissAV自动登录|定制播放器|多语言支持 支持 jable po*nhub 等通用
// @description:en MissAV ad-free|one-handed mode|MissAV auto-expand details|MissAV auto high quality|MissAV redirect support|MissAV auto login|custom player|multilingual support for jable po*nhub etc.
// @description:ja MissAV広告ブロック|片手モード|MissAV自動詳細表示|MissAV自動高画質|MissAVリダイレクト対応|MissAV自動ログイン|カスタムプレーヤー|jable po*nhubなどに対応した多言語サポート
// @description:vi MissAV không quảng cáo|chế độ một tay|MissAV tự động mở rộng chi tiết|MissAV tự động chất lượng cao|Hỗ trợ chuyển hướng MissAV|MissAV tự động đăng nhập|trình phát tùy chỉnh|hỗ trợ đa ngôn ngữ cho jable po*nhub v.v.
// @description:zh-CN MissAV去广告|单手模式|MissAV自动展开详情|MissAV自动高画质|MissAV重定向支持|MissAV自动登录|定制播放器|多语言支持 支持 jable po*nhub 等通用
// @description:zh-TW MissAV去廣告|單手模式|MissAV自動展開詳情|MissAV自動高畫質|MissAV重定向支持|MissAV自動登錄|定制播放器|多語言支持 支持 jable po*nhub 等通用
// @version 5.1.6
// @author Chris_C
// @match *://*.missav.ws/*
// @match *://*.missav.ai/*
// @match *://*.jable.tv/*
// @match *://*/*
// @grant none
// @icon https://missav.ws/img/favicon.ico
// @license MIT
// @namespace loadingi.local
// @noframes
// @run-at document-start
// ==/UserScript==
(() => {
"use strict";
var __webpack_modules__ = {
"./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].use[2]!./src/player/ui/style.css": (module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ "./node_modules/css-loader/dist/runtime/noSourceMaps.js");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `:root{\n --shadcn-background:0 0% 0%;\n --shadcn-foreground:0 0% 100%;\n --shadcn-card:0 0% 5%;\n --shadcn-card-foreground:0 0% 95%;\n --shadcn-popover:0 0% 10%;\n --shadcn-popover-foreground:0 0% 95%;\n --shadcn-primary:210 10% 90%;\n --shadcn-primary-foreground:210 20% 10%;\n --shadcn-secondary:0 0% 15%;\n --shadcn-secondary-foreground:0 0% 95%;\n --shadcn-muted:0 0% 30%;\n --shadcn-muted-foreground:0 0% 70%;\n --shadcn-accent:212 40% 30%;\n --shadcn-accent-foreground:0 0% 95%;\n --shadcn-destructive:0 50% 40%;\n --shadcn-destructive-foreground:0 0% 95%;\n --shadcn-border:0 0% 30%;\n --shadcn-input:0 0% 15%;\n --shadcn-ring:212 70% 45%;\n --shadcn-green:142 50% 45%;\n --shadcn-green-foreground:0 0% 95%;\n --shadcn-blue:211 70% 55%;\n --shadcn-blue-foreground:0 0% 95%;\n --shadcn-red:0 60% 50%;\n --shadcn-red-foreground:0 0% 95%;\n --shadcn-orange:25 80% 50%;\n --shadcn-orange-foreground:0 0% 95%;\n --shadcn-purple:262 60% 60%;\n --shadcn-purple-foreground:0 0% 95%;\n --shadcn-radius:0.5rem;\n --shadcn-radius-sm:0.3rem;\n --shadcn-radius-lg:0.8rem;\n --button-sm:20px;\n --button-md:32px;\n --button-lg:40px;\n --button-xl:48px;\n --anim-quick:0.2s cubic-bezier(0.4, 0, 0.2, 1);\n --anim-smooth:0.3s cubic-bezier(0.16, 1, 0.3, 1);\n --anim-bounce:0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n --shadow-sm:0 2px 5px rgba(0, 0, 0, 0.2);\n --shadow-md:0 4px 10px rgba(0, 0, 0, 0.25);\n --shadow-lg:0 8px 20px rgba(0, 0, 0, 0.3);\n --font-sans:"SF Pro Display", "SF Pro", "Segoe UI", "Microsoft YaHei", "微软雅黑", "PingFang SC", "苹方", "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";\n}\nhtml, body, button, input, select, textarea{\n font-family:var(--font-sans);\n}\n*, *::before, *::after{\n font-family:inherit;\n}\n\n.tm-video-overlay *{\n font-family:var(--font-sans);\n}\n.tm-floating-button{\n position:fixed;\n bottom:30px;\n left:50%;\n transform:translateX(-50%);\n padding:0;\n width:56px;\n height:56px;\n border-radius:50%;\n background-color:transparent;\n color:rgb(254, 98, 142);\n border:none;\n display:flex;\n align-items:center;\n justify-content:center;\n z-index:9980;\n cursor:pointer;\n transition:all var(--anim-smooth);\n overflow:visible;\n}\n\n.tm-floating-button svg{\n width:48px;\n height:48px;\n filter:drop-shadow(0 0 10px rgba(254, 98, 142, 0.9));\n transition:all var(--anim-smooth);\n animation:breathing-glow 3s infinite ease-in-out;\n}\n\n.tm-floating-button:hover{\n transform:translateX(-50%) scale(1.1);\n}\n\n.tm-floating-button:hover svg{\n animation-play-state:paused;\n filter:drop-shadow(0 0 20px rgba(254, 98, 142, 1.0));\n}\n\n.tm-floating-button:active{\n transform:translateX(-50%) scale(0.95);\n}\n@keyframes breathing-glow{\n 0%{\n filter:drop-shadow(0 0 8px rgba(254, 98, 142, 0.7));\n transform:scale(0.97);\n }\n 50%{\n filter:drop-shadow(0 0 25px rgba(254, 98, 142, 1.0));\n transform:scale(1.03);\n }\n 100%{\n filter:drop-shadow(0 0 8px rgba(254, 98, 142, 0.7));\n transform:scale(0.97);\n }\n}\n@media screen and (orientation: landscape){\n .tm-floating-button{\n left:auto;\n right:20px;\n transform:translateX(0);\n }\n \n .tm-floating-button:hover{\n transform:translateX(0) scale(1.1);\n }\n \n .tm-floating-button:active{\n transform:translateX(0) scale(0.95);\n }\n \n .tm-floating-button svg{\n animation:breathing-glow-landscape 3s infinite ease-in-out;\n }\n}\n@keyframes breathing-glow-landscape{\n 0%{\n filter:drop-shadow(0 0 8px rgba(254, 98, 142, 0.7));\n transform:scale(0.97);\n }\n 50%{\n filter:drop-shadow(0 0 25px rgba(254, 98, 142, 1.0));\n transform:scale(1.03);\n }\n 100%{\n filter:drop-shadow(0 0 8px rgba(254, 98, 142, 0.7));\n transform:scale(0.97);\n }\n}\n.tm-video-overlay{\n position:fixed;\n top:0;\n left:0;\n right:0;\n height:100vh;\n background-color:rgba(35, 17, 29, 0.8);\n z-index:9990;\n display:flex;\n flex-direction:column;\n align-items:center;\n justify-content:flex-start;\n backdrop-filter:blur(30px);\n -webkit-backdrop-filter:blur(30px);\n padding:0;\n}\n.tm-player-container{\n position:fixed;\n top:0;\n bottom:0;\n left:0;\n right:0;\n width:100%;\n background-color:transparent;\n display:flex;\n flex-direction:column;\n align-items:center;\n justify-content:flex-start;\n z-index:9991;\n height:100%;\n overflow:visible;\n pointer-events:auto;\n}\n.tm-button-container{\n width:100%;\n display:flex;\n justify-content:space-between;\n padding:6px 10px;\n box-sizing:border-box;\n z-index:9993;\n position:absolute;\n top:0;\n left:0;\n}\n\n.tm-video-container{\n position:relative;\n overflow:hidden;\n width:100%;\n height:auto;\n max-height:80vh;\n margin-top:44px;\n display:flex;\n align-items:flex-start;\n justify-content:center;\n background-color:hsl(var(--shadcn-card));\n border-radius:var(--shadcn-radius-lg);\n box-shadow:var(--shadow-lg);\n z-index:9992;\n}\n\n.tm-video-wrapper{\n position:relative;\n overflow:hidden;\n width:100%;\n height:100%;\n display:flex;\n justify-content:center;\n align-items:center;\n will-change:transform;\n border-radius:var(--shadcn-radius) var(--shadcn-radius) 0 0;\n}\n.tm-video-wrapper video{\n width:auto !important; \n height:100% !important; \n max-width:none !important; \n object-fit:contain !important; \n transition:transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n touch-action:pan-y; \n cursor:grab; \n}\n.tm-handle-container{\n left:0;\n right:0;\n bottom:10px;\n height:30px;\n display:flex;\n justify-content:center;\n align-items:center;\n z-index:9992;\n width:100%;\n}\n\n.tm-resize-handle{\n position:absolute;\n height:5px;\n width:134px;\n max-width:134px;\n background-color:hsla(var(--shadcn-foreground) / 0.6);\n border-radius:2.5px;\n cursor:ns-resize;\n touch-action:none;\n opacity:0.5;\n will-change:transform;\n transition:all var(--anim-quick);\n box-shadow:none;\n}\n\n.tm-resize-handle::after{\n content:\'\';\n position:absolute;\n left:-10px;\n right:-10px;\n top:-15px;\n bottom:-15px;\n background:transparent;\n}\n\n.tm-resize-handle:hover{\n opacity:1;\n background-color:hsla(var(--shadcn-foreground) / 0.8);\n}\n.tm-control-button-base{\n color:hsl(var(--shadcn-secondary-foreground));\n border-radius:50%;\n display:flex;\n align-items:center;\n justify-content:center;\n cursor:pointer;\n transition:all var(--anim-quick);\n backdrop-filter:blur(12px);\n -webkit-backdrop-filter:blur(12px);\n box-shadow:var(--shadow-sm);\n}\n.tm-close-button{\n position:relative;\n width:var(--button-md);\n height:var(--button-md);\n border-radius:calc(var(--button-md) / 2);\n background-color:hsla(var(--shadcn-secondary) / 0.5);\n color:hsl(var(--shadcn-secondary-foreground));\n border:1px solid hsla(var(--shadcn-border) / 0.1);\n display:flex;\n align-items:center;\n justify-content:center;\n cursor:pointer;\n transition:all var(--anim-smooth);\n z-index:9994;\n}\n\n.tm-close-button:hover{\n background-color:hsl(var(--shadcn-destructive));\n transform:scale(1.1);\n box-shadow:var(--shadow-md);\n}\n\n.tm-close-button:active{\n transform:scale(0.9);\n}\n.tm-settings-button{\n position:relative;\n width:var(--button-md);\n height:var(--button-md);\n border-radius:calc(var(--button-md) / 2);\n background-color:hsla(var(--shadcn-secondary) / 0.7);\n color:hsl(var(--shadcn-secondary-foreground));\n border:1px solid hsla(var(--shadcn-border) / 0.2);\n display:flex;\n align-items:center;\n justify-content:center;\n z-index:9993;\n cursor:pointer;\n transition:all var(--anim-quick);\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n box-shadow:var(--shadow-sm);\n}\n\n.tm-settings-button:hover{\n background-color:hsla(var(--shadcn-accent) / 0.9);\n transform:scale(1.1) rotate(30deg);\n box-shadow:var(--shadow-md);\n}\n\n.tm-settings-button:active{\n transform:scale(0.9);\n}\n.tm-settings-panel{\n position:absolute;\n top:calc(env(safe-area-inset-top, 8px) + 60px);\n right:16px;\n background-color:hsla(var(--shadcn-card) / 0.7);\n backdrop-filter:blur(15px);\n -webkit-backdrop-filter:blur(15px);\n border-radius:var(--shadcn-radius);\n border:1px solid hsla(var(--shadcn-border) / 0.1);\n padding:12px;\n box-shadow:var(--shadow-md);\n z-index:9996;\n min-width:200px;\n transform:translateY(-10px);\n opacity:0;\n pointer-events:none;\n transition:transform var(--anim-smooth), opacity var(--anim-smooth);\n}\n\n.tm-settings-panel.active{\n transform:translateY(0);\n opacity:1;\n pointer-events:auto;\n}\n.tm-settings-option{\n display:flex;\n justify-content:space-between;\n align-items:center;\n padding:10px;\n border-radius:var(--shadcn-radius-sm);\n margin-bottom:8px;\n transition:background-color var(--anim-quick);\n}\n\n.tm-settings-option:hover{\n background-color:hsla(var(--shadcn-muted) / 0.5);\n}\n\n.tm-settings-option:last-child{\n margin-bottom:0;\n}\n.tm-settings-label{\n cursor:pointer;\n flex:1;\n}\n.tm-toggle-input{\n position:absolute;\n left:-9999px;\n}\n.tm-settings-panel{\n display:none;\n}\n\n.tm-settings-panel.visible{\n display:block;\n}\n.tm-start-time-container.active{\n background-color:hsl(var(--shadcn-green) / 0.15);\n border-color:hsl(var(--shadcn-green) / 0.4);\n}\n\n.tm-start-time-container:not(.active){\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n border-color:hsl(var(--shadcn-border) / 0.1);\n}\n.tm-end-time-container.active{\n background-color:hsl(var(--shadcn-orange) / 0.15);\n border-color:hsl(var(--shadcn-orange) / 0.4);\n}\n\n.tm-end-time-container:not(.active){\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n border-color:hsl(var(--shadcn-border) / 0.1);\n}\n.tm-set-loop-start-label.active{\n color:hsl(var(--shadcn-green));\n opacity:1;\n}\n\n.tm-set-loop-start-label:not(.active){\n opacity:0.9;\n}\n.tm-set-loop-end-label.active{\n color:hsl(var(--shadcn-orange));\n opacity:1;\n}\n\n.tm-set-loop-end-label:not(.active){\n opacity:0.9;\n}\n.tm-loop-start-position.active, .tm-loop-end-position.active{\n color:hsl(var(--shadcn-foreground));\n opacity:1;\n}\n\n.tm-loop-start-position:not(.active), .tm-loop-end-position:not(.active){\n color:hsl(var(--shadcn-muted-foreground));\n opacity:0.9;\n}\n.tm-loop-toggle-button.active{\n background-color:hsl(var(--shadcn-red) / 0.1);\n border-color:hsl(var(--shadcn-red) / 0.3);\n}\n\n.tm-loop-toggle-button:active{\n transform:scale(0.98);\n}\n.tm-loop-range{\n position:absolute;\n height:4px;\n background:linear-gradient(90deg, \n hsla(var(--shadcn-green) / 0.3) 0%, \n hsla(var(--shadcn-orange) / 0.3) 100%);\n top:50%;\n transform:translateY(-50%);\n border-radius:2px;\n opacity:0;\n transition:opacity 0.3s ease;\n z-index:1;\n pointer-events:none;\n}\n\n.tm-loop-range.active{\n opacity:0.7;\n box-shadow:0 0 8px rgba(0, 0, 0, 0.1);\n}\n.tm-progress-bar-container:hover .tm-loop-range.active{\n opacity:0.9;\n height:6px;\n}\n.tm-loop-marker{\n position:absolute;\n width:4px;\n height:100%;\n top:0;\n transform:translateX(-50%);\n z-index:3;\n transition:opacity 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow 0.2s cubic-bezier(0.25, 0.1, 0.25, 1);\n backdrop-filter:blur(4px);\n -webkit-backdrop-filter:blur(4px);\n}\n.tm-loop-start-marker{\n background-color:hsla(var(--shadcn-green) / 0.5);\n border-radius:2px;\n box-shadow:0 0 6px hsla(var(--shadcn-green) / 0.3);\n}\n.tm-loop-end-marker{\n background-color:hsla(var(--shadcn-orange) / 0.5);\n border-radius:2px;\n box-shadow:0 0 6px hsla(var(--shadcn-orange) / 0.3);\n}\n.tm-loop-marker:hover{\n cursor:pointer;\n z-index:4;\n}\n\n.tm-loop-start-marker:hover{\n background-color:hsla(var(--shadcn-green) / 0.7);\n box-shadow:0 0 10px hsla(var(--shadcn-green) / 0.5);\n}\n\n.tm-loop-end-marker:hover{\n background-color:hsla(var(--shadcn-orange) / 0.7);\n box-shadow:0 0 10px hsla(var(--shadcn-orange) / 0.5);\n}\n.tm-loop-marker.active{\n opacity:1;\n}\n\n.tm-loop-marker:not(.active){\n opacity:0.7;\n}\n.tm-loop-marker::before{\n content:attr(data-label);\n position:absolute;\n top:-24px;\n left:50%;\n transform:translateX(-50%);\n background-color:hsla(var(--shadcn-card) / 0.7);\n color:hsl(var(--shadcn-card-foreground));\n font-size:10px;\n font-weight:600;\n padding:2px 8px;\n border-radius:10px;\n opacity:0;\n transition:opacity 0.2s ease, transform 0.2s ease;\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n box-shadow:0 2px 4px rgba(0, 0, 0, 0.1);\n border:1px solid hsla(var(--shadcn-border) / 0.1);\n white-space:nowrap;\n z-index:5;\n}\n\n.tm-loop-start-marker::before{\n content:"循环起点";\n}\n\n.tm-loop-end-marker::before{\n content:"循环终点";\n}\n\n.tm-loop-marker:hover::before{\n opacity:1;\n transform:translateX(-50%) translateY(-4px);\n}\n.tm-start-time-container-hover{\n background-color:hsl(var(--shadcn-green) / 0.1);\n border-color:hsl(var(--shadcn-green) / 0.3);\n}\n\n.tm-start-time-container-default{\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n border-color:hsl(var(--shadcn-border) / 0.1);\n}\n\n.tm-end-time-container-hover{\n background-color:hsl(var(--shadcn-orange) / 0.1);\n border-color:hsl(var(--shadcn-orange) / 0.3);\n}\n\n.tm-end-time-container-default{\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n border-color:hsl(var(--shadcn-border) / 0.1);\n}\n.tm-loop-button-hover{\n background-color:hsl(var(--shadcn-accent) / 0.3);\n transform:translateY(-1px);\n}\n\n.tm-loop-button-active{\n background-color:hsl(var(--shadcn-muted) / 0.7);\n}\n\n.tm-loop-button-default{\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n transform:translateY(0);\n}\n.tm-indicator-base{\n position:absolute;\n padding:8px 16px;\n background-color:hsla(var(--shadcn-card) / 0.6);\n color:hsl(var(--shadcn-card-foreground));\n border-radius:var(--shadcn-radius);\n opacity:0;\n backdrop-filter:blur(15px);\n -webkit-backdrop-filter:blur(15px);\n box-shadow:var(--shadow-md);\n border:1px solid hsla(var(--shadcn-border) / 0.1);\n transform:translateY(20px);\n transition:opacity var(--anim-smooth), transform var(--anim-smooth);\n pointer-events:none;\n z-index:9994;\n font-size:15px;\n font-weight:500;\n}\n\n.tm-indicator-base.visible{\n opacity:1;\n transform:translateY(0);\n pointer-events:auto;\n}\n.tm-pause-indicator{\n width:80px;\n height:80px;\n}\n.tm-playback-rate-indicator{\n top:30%;\n border-radius:var(--shadcn-radius);\n padding:10px 16px;\n font-size:16px;\n font-weight:bold;\n}\n.tm-progress-row{\n display:flex;\n flex-direction:column;\n width:100%;\n box-sizing:border-box;\n}\n\n.tm-seek-control-row{\n display:flex;\n flex-direction:row;\n justify-content:space-between;\n width:100%;\n box-sizing:border-box;\n}\n\n.tm-loop-control-row{\n display:flex;\n justify-content:space-between;\n align-items:center;\n width:100%;\n box-sizing:border-box;\n position:relative;\n}\n\n.tm-playback-control-row{\n display:flex;\n justify-content:space-between;\n align-items:center;\n position:relative;\n width:100%;\n max-height:45px;\n height:45px;\n border-radius:8px;\n box-sizing:border-box;\n}\n.tm-left-controls, .tm-center-controls, .tm-right-controls{\n flex:1;\n display:flex;\n height:100%;\n align-items:center;\n}\n\n.tm-left-controls{\n justify-content:flex-start;\n}\n\n.tm-center-controls{\n justify-content:center;\n}\n\n.tm-right-controls{\n justify-content:flex-end;\n}\n.tm-time-display{\n display:flex;\n justify-content:space-between;\n color:hsl(var(--shadcn-foreground) / 0.9);\n font-size:12px;\n margin-top:-2px;\n font-variant-numeric:tabular-nums;\n gap:8px;\n}\n\n.tm-time-display-container{\n display:flex;\n justify-content:space-between;\n width:100%;\n padding:0px 1px;\n margin-bottom:4px;\n}\n\n.tm-current-time, .tm-total-duration{\n color:hsl(var(--shadcn-card-foreground) / 0.9);\n font-size:0.8rem;\n min-width:60px;\n font-variant-numeric:tabular-nums;\n font-weight:400;\n line-height:1;\n}\n\n.tm-current-time{\n text-align:left;\n}\n\n.tm-total-duration{\n text-align:right;\n}\n\n.tm-loop-control{\n display:flex;\n align-items:center;\n gap:6px;\n}\n\n.tm-start-time-container, .tm-end-time-container{\n display:flex;\n align-items:center;\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n border:1px solid hsl(var(--shadcn-border) / 0.1);\n border-radius:6px;\n padding:4px 4px;\n cursor:pointer;\n transition:all 0.2s ease;\n}\n.tm-start-time-container:hover{\n background-color:hsl(var(--shadcn-green) / 0.1);\n border-color:hsl(var(--shadcn-green) / 0.3);\n transform:translateY(-1px);\n}\n\n.tm-end-time-container:hover{\n background-color:hsl(var(--shadcn-orange) / 0.1);\n border-color:hsl(var(--shadcn-orange) / 0.3);\n transform:translateY(-1px);\n}\n\n.tm-set-loop-start-label, .tm-set-loop-end-label{\n font-size:1rem;\n font-weight:600;\n padding:0px 4px;\n display:flex;\n align-items:center;\n justify-content:center;\n}\n.tm-set-loop-start-label{\n color:hsl(var(--shadcn-green));\n}\n.tm-set-loop-end-label{\n color:hsl(var(--shadcn-orange));\n}\n\n.tm-loop-toggle-button{\n display:flex;\n align-items:center;\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n border:1px solid hsl(var(--shadcn-border) / 0.1);\n border-radius:6px;\n padding:4px 8px;\n font-size:0.875rem;\n cursor:pointer;\n transition:all 0.2s ease;\n font-weight:500;\n gap:6px;\n color:hsl(var(--shadcn-foreground));\n}\n.tm-loop-toggle-label{\n font-size:1rem;\n font-weight:600;\n padding:0px 4px;\n display:flex;\n align-items:center;\n justify-content:center;\n color:hsl(var(--shadcn-muted-foreground) / 0.9);\n transition:color 0.2s ease;\n}\n.tm-loop-toggle-label.active{\n color:hsl(var(--shadcn-red));\n}\n.tm-loop-toggle-button.active{\n background-color:hsl(var(--shadcn-red) / 0.1);\n border-color:hsl(var(--shadcn-red) / 0.3);\n}\n\n.tm-loop-toggle-button:not(.active){\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n border-color:hsl(var(--shadcn-border) / 0.1);\n}\n\n.tm-loop-toggle-button:active{\n transform:scale(0.98);\n}\n\n.tm-loop-indicator-circle{\n transition:fill 0.2s ease;\n}\n\n.tm-loop-toggle-button.active .tm-loop-indicator-circle{\n fill:hsl(var(--shadcn-red));\n}\n.tm-rewind-group, .tm-forward-group{\n display:flex;\n flex-direction:column;\n width:50%;\n gap:8px;\n align-items:center;\n}\n\n.tm-rewind-buttons-container{\n display:flex;\n flex-direction:row-reverse;\n flex-wrap:wrap;\n width:100%;\n justify-content:flex-end;\n align-content:flex-start;\n gap:6px;\n}\n\n.tm-forward-buttons-container{\n display:flex;\n flex-direction:row;\n flex-wrap:wrap;\n width:100%;\n justify-content:flex-end;\n align-content:flex-start;\n gap:6px;\n}\n.tm-loop-start-position, .tm-loop-end-position{\n color:hsl(var(--shadcn-muted-foreground));\n font-size:0.875rem;\n min-width:70px;\n text-align:center;\n display:inline-block;\n font-variant-numeric:tabular-nums;\n}\n.tm-time-control-button{\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n color:hsl(var(--shadcn-secondary-foreground));\n border:1px solid hsl(var(--shadcn-border) / 0.1);\n border-radius:var(--shadcn-radius-sm);\n padding:0;\n font-size:0.75rem;\n cursor:pointer;\n transition:all 0.2s cubic-bezier(.25,.8,.25,1);\n white-space:nowrap;\n font-weight:500;\n box-shadow:0 1px 2px rgba(0,0,0,0.05);\n width:var(--button-xl);\n height:var(--button-lg);\n display:flex;\n align-items:center;\n justify-content:center;\n flex:0 0 auto;\n}\n\n.tm-time-control-button:hover{\n background-color:hsl(var(--shadcn-accent) / 0.6);\n transform:translateY(-1px);\n box-shadow:0 2px 4px rgba(0,0,0,0.1);\n}\n\n.tm-time-control-button:active{\n transform:scale(0.95);\n box-shadow:none;\n}\n\n.tm-time-control-button-active{\n transform:scale(0.95);\n box-shadow:none;\n}\n\n.tm-time-control-button-after-active{\n transform:none;\n box-shadow:0 2px 5px rgba(0, 0, 0, 0.15);\n}\n\n.tm-time-control-button-inner{\n display:flex;\n align-items:center;\n justify-content:center;\n}\n\n.tm-rewind-icon{\n margin-right:-2px;\n}\n\n.tm-forward-icon{\n margin-left:-2px;\n}\n\n.tm-time-text-margin-left{\n margin-left:2px;\n}\n\n.tm-time-text-margin-right{\n margin-right:2px;\n}\n.tm-control-button-hover{\n background-color:hsl(var(--shadcn-accent) / 0.3);\n transform:none;\n}\n\n.tm-control-button-default{\n background-color:hsl(var(--shadcn-secondary) / 0.5);\n transform:none;\n}\n.tm-control-buttons{\n position:absolute;\n bottom:calc(10px + env(safe-area-inset-bottom, 0px));\n left:50%;\n transform:translateX(-50%);\n width:95%;\n max-width:700px;\n min-width:350px;\n background-color:hsla(var(--shadcn-card) / 0.8);\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n z-index:9991;\n padding:12px;\n padding-bottom:12px;\n border-radius:12px;\n border:1px solid hsla(var(--shadcn-border) / 0.1);\n box-shadow:0 2px 10px rgba(0, 0, 0, 0.2);\n transition:opacity 0.3s ease, transform 0.3s ease;\n gap:10px;\n display:flex;\n flex-direction:column;\n align-items:center;\n justify-content:center;\n}\nbody.controls-hidden .tm-player-container .tm-control-buttons{\n opacity:0;\n transform:translateX(-50%) translateY(20px);\n pointer-events:none;\n}\nbody:not(.controls-hidden) .tm-player-container .tm-control-buttons{\n opacity:1;\n transform:translateX(-50%) translateY(0);\n pointer-events:auto;\n}\nbody.controls-hidden .tm-player-container .tm-button-container{\n opacity:0;\n transform:translateY(-20px);\n pointer-events:none;\n}\nbody:not(.controls-hidden) .tm-player-container .tm-button-container{\n opacity:1;\n transform:translateY(0);\n pointer-events:auto;\n}\n.tm-control-button{\n position:relative;\n width:var(--button-md);\n height:var(--button-md);\n border-radius:calc(var(--button-md) / 2);\n background-color:hsla(var(--shadcn-secondary) / 0.6);\n color:hsl(var(--shadcn-secondary-foreground));\n border:1px solid hsla(var(--shadcn-border) / 0.1);\n display:flex;\n align-items:center;\n justify-content:center;\n cursor:pointer;\n transition:all var(--anim-quick);\n}\n\n.tm-control-button:hover{\n background-color:hsla(var(--shadcn-accent) / 0.7);\n transform:translateY(-2px);\n box-shadow:var(--shadow-sm);\n}\n\n.tm-control-button:active{\n transform:scale(0.95);\n box-shadow:none;\n}\n\n.tm-control-button.active{\n background-color:hsla(var(--shadcn-blue) / 0.7);\n color:hsl(var(--shadcn-blue-foreground));\n box-shadow:0 0 0 2px hsla(var(--shadcn-blue) / 0.3);\n}\n\n.tm-control-button svg,\n.tm-control-button img{\n width:16px;\n height:16px;\n}\n.tm-control-row{\n display:flex;\n justify-content:center;\n align-items:center;\n gap:8px;\n margin-top:4px;\n opacity:1;\n transition:opacity var(--anim-quick), height var(--anim-quick);\n height:auto;\n overflow:hidden;\n}\n\n.tm-control-row.hidden{\n opacity:0;\n height:0;\n margin:0;\n}\n.tm-time-control-button-hover{\n background-color:hsl(var(--shadcn-accent) / 0.6);\n transform:none;\n box-shadow:0 2px 4px rgba(0,0,0,0.1);\n}\n\n.tm-time-control-button-active{\n transform:scale(0.95);\n box-shadow:none;\n}\n\n.tm-time-control-button-default{\n transform:translateY(0);\n box-shadow:0 1px 2px rgba(0,0,0,0.05);\n}\n\n.tm-time-control-button-after-active{\n transform:none;\n box-shadow:0 2px 5px rgba(0, 0, 0, 0.15);\n}\n@media screen and (orientation: landscape){\n .tm-video-container{\n width:100%;\n height:100vh !important;\n max-height:100vh !important;\n min-height:auto !important;\n margin:0;\n padding:0;\n padding-left:env(safe-area-inset-left, 16px);\n padding-right:env(safe-area-inset-right, 16px);\n border-radius:0;\n box-shadow:none;\n display:flex;\n justify-content:center;\n align-items:center;\n background-color:black;\n }\n .tm-video-wrapper{\n width:100%;\n height:100%;\n border-radius:0;\n display:flex;\n justify-content:center;\n align-items:center;\n overflow:hidden;\n }\n .tm-video-wrapper video{\n width:100% !important;\n height:auto !important;\n max-height:100vh !important;\n object-fit:contain !important;\n }\n .tm-video-wrapper.video-portrait video{\n width:auto !important;\n height:100% !important;\n max-width:100% !important;\n }\n .tm-button-container{\n position:absolute;\n top:0;\n left:0;\n right:0;\n z-index:9995;\n background-color:transparent;\n padding:16px;\n padding-top:calc(env(safe-area-inset-top, 8px) + 8px);\n display:flex;\n justify-content:space-between;\n transition:opacity 0.3s ease, transform 0.3s ease;\n }\n .tm-video-overlay.controls-hidden .tm-button-container{\n opacity:0;\n transform:translateY(-20px);\n pointer-events:none;\n }\n .tm-video-overlay .tm-button-container{\n opacity:1;\n transform:translateY(0);\n pointer-events:auto;\n }\n .tm-settings-button{\n display:flex;\n background-color:hsla(var(--shadcn-secondary) / 0.3);\n backdrop-filter:blur(4px);\n -webkit-backdrop-filter:blur(4px);\n }\n .tm-close-button{\n background-color:hsla(var(--shadcn-secondary) / 0.3);\n backdrop-filter:blur(4px);\n -webkit-backdrop-filter:blur(4px);\n }\n .tm-control-buttons{\n position:absolute;\n bottom:calc(10px + env(safe-area-inset-bottom, 0px));\n left:50%;\n transform:translateX(-50%);\n width:90%;\n max-width:700px;\n min-width:350px;\n background-color:hsla(var(--shadcn-card) / 0.3);\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n z-index:9994;\n padding:12px;\n padding-bottom:12px;\n border-radius:12px;\n border:1px solid hsla(var(--shadcn-border) / 0.1);\n box-shadow:0 2px 10px rgba(0, 0, 0, 0.2);\n transition:opacity 0.3s ease, transform 0.3s ease;\n }\n .tm-video-overlay.controls-hidden .tm-control-buttons{\n opacity:0;\n transform:translateX(-50%) translateY(20px);\n pointer-events:none;\n }\n .tm-video-overlay .tm-control-buttons{\n opacity:1;\n transform:translateX(-50%) translateY(0);\n pointer-events:auto;\n }\n .tm-video-overlay{\n background-color:black;\n backdrop-filter:none;\n -webkit-backdrop-filter:none;\n }\n .tm-floating-button{\n bottom:30px;\n left:50%;\n transform:translateX(-50%);\n padding:0;\n width:calc(var(--button-xl));\n height:calc(var(--button-xl));\n }\n}\n.tm-time-indicator{\n position:absolute;\n background-color:hsla(var(--shadcn-card) / 0.8);\n color:hsl(var(--shadcn-card-foreground));\n padding:4px 8px;\n border-radius:4px;\n font-size:12px;\n font-weight:500;\n pointer-events:none;\n z-index:9995;\n opacity:0;\n transform:translateY(-8px);\n transition:opacity 0.2s, transform 0.2s;\n box-shadow:0 2px 8px rgba(0, 0, 0, 0.2);\n border:1px solid hsla(var(--shadcn-border) / 0.1);\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n}\n.tm-volume-control{\n display:flex;\n align-items:center;\n gap:8px;\n height:40px;\n padding:0 8px;\n background-color:transparent;\n transition:opacity 0.3s ease;\n}\n.tm-volume-control-no-slider{\n width:auto;\n padding:0;\n}\n\n.tm-volume-control-no-slider .tm-volume-button{\n margin:0 8px;\n}\n.tm-volume-button{\n display:flex;\n align-items:center;\n justify-content:center;\n width:32px;\n height:32px;\n padding:4px;\n border:none;\n border-radius:50%;\n background:transparent;\n color:#fff;\n cursor:pointer;\n transition:background-color 0.2s ease;\n}\n\n.tm-volume-button:hover{\n background-color:hsla(var(--shadcn-secondary) / 0.2);\n}\n\n.tm-volume-button svg{\n width:20px;\n height:20px;\n}\n.tm-volume-slider-container{\n position:relative;\n width:0;\n height:40px;\n display:flex;\n align-items:center;\n overflow:hidden;\n transition:width 0.3s ease;\n opacity:0;\n}\n@media (hover: hover){\n .tm-volume-control:hover .tm-volume-slider-container{\n width:80px;\n opacity:1;\n }\n}\n.tm-volume-control.dragging .tm-volume-slider-container{\n width:80px;\n opacity:1;\n}\n.tm-volume-slider-track{\n position:relative;\n width:100%;\n height:4px;\n background-color:hsla(var(--shadcn-secondary) / 0.3);\n border-radius:2px;\n cursor:pointer;\n}\n.tm-volume-slider-level{\n position:absolute;\n left:0;\n top:0;\n height:100%;\n background-color:#fff;\n border-radius:2px;\n pointer-events:none;\n transition:width 0.1s ease;\n}\n.tm-volume-value{\n position:absolute;\n top:-24px;\n left:50%;\n transform:translateX(-50%);\n background-color:hsla(var(--shadcn-secondary) / 0.8);\n color:#fff;\n padding:2px 6px;\n border-radius:4px;\n font-size:12px;\n opacity:0;\n transition:opacity 0.2s ease;\n pointer-events:none;\n backdrop-filter:blur(4px);\n}\n.tm-volume-control.dragging .tm-volume-value{\n opacity:1;\n}\n@media (hover: none){\n .tm-volume-control{\n touch-action:none;\n }\n \n .tm-volume-slider-track{\n height:6px;\n }\n \n .tm-volume-button{\n width:40px;\n height:40px;\n }\n}\n@media (prefers-color-scheme: dark){\n .tm-volume-slider-level{\n background-color:hsl(var(--shadcn-primary));\n }\n \n .tm-volume-button svg{\n stroke:hsl(var(--shadcn-primary));\n }\n}\n.tm-toggle-switch{\n position:relative;\n display:inline-block;\n width:40px;\n height:24px;\n}\n\n.tm-toggle-switch input{\n opacity:0;\n width:0;\n height:0;\n}\n\n.tm-toggle-slider{\n position:absolute;\n cursor:pointer;\n top:0;\n left:0;\n right:0;\n bottom:0;\n background-color:hsla(var(--shadcn-muted) / 0.7);\n border-radius:12px;\n transition:var(--anim-quick);\n}\n\n.tm-toggle-slider:before{\n position:absolute;\n content:"";\n height:20px;\n width:20px;\n left:2px;\n bottom:2px;\n background-color:hsl(var(--shadcn-foreground));\n border-radius:50%;\n transition:var(--anim-quick);\n box-shadow:0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n.tm-toggle-slider.checked{\n background-color:hsl(var(--shadcn-blue));\n}\n\n.tm-toggle-slider.checked:before{\n transform:translateX(16px);\n}\n.tm-playback-rate-slider{\n display:flex;\n align-items:center;\n margin-left:0;\n height:30px;\n width:100%;\n max-width:110px;\n background:hsl(var(--shadcn-card) / 0.85);\n border-radius:6px;\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n position:relative;\n overflow:hidden;\n box-shadow:0 1px 3px rgba(0, 0, 0, 0.08);\n transition:box-shadow 0.2s ease, transform 0.2s ease;\n cursor:pointer;\n}\n\n.tm-playback-rate-slider:hover{\n box-shadow:0 2px 6px rgba(0, 0, 0, 0.1);\n transform:translateY(-1px);\n}\n\n.tm-playback-rate-slider.dragging{\n box-shadow:0 1px 4px rgba(0, 0, 0, 0.12);\n background:hsla(var(--shadcn-card) / 0.9);\n}\n\n.tm-slider-container{\n width:100%;\n height:100%;\n background:hsla(var(--shadcn-secondary) / 0.5);\n position:relative;\n overflow:hidden;\n display:flex;\n align-items:center;\n}\n\n.tm-slider-level{\n position:absolute;\n top:0;\n left:0;\n height:100%;\n background:hsl(0 0% 50% / 0.8);\n width:50%;\n transform-origin:left;\n transition:width 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n z-index:1;\n}\n\n.tm-slider-text{\n display:flex;\n justify-content:space-between;\n width:100%;\n padding:0 10px;\n z-index:2;\n position:relative;\n}\n.tm-speed-label{\n color:hsl(var(--shadcn-muted-foreground));\n font-size:12px;\n font-weight:400;\n transition:color var(--anim-quick);\n}\n\n.tm-playback-rate-slider:hover .tm-speed-label{\n color:hsl(var(--shadcn-foreground));\n}\n\n.tm-speed-value{\n color:hsl(var(--shadcn-foreground));\n font-size:12px;\n font-weight:600;\n font-variant-numeric:tabular-nums;\n}\n.tm-speed-value.fast{\n color:hsl(var(--shadcn-orange));\n}\n\n.tm-speed-value.slow{\n color:hsl(var(--shadcn-blue));\n}\n\n.tm-speed-value.normal{\n color:hsl(var(--shadcn-foreground));\n}\n.tm-progress-controls{\n position:relative;\n width:100%;\n bottom:0;\n left:0;\n right:0;\n display:flex;\n flex-direction:column;\n z-index:9991;\n border-radius:0 0 var(--shadcn-radius-lg) var(--shadcn-radius-lg);\n font-family:var(--font-sans);\n transition:opacity var(--anim-smooth);\n}\n.tm-progress-bar-container{\n position:relative;\n height:12px;\n display:flex;\n align-items:center;\n cursor:pointer;\n user-select:none;\n -webkit-user-select:none;\n -moz-user-select:none;\n -ms-user-select:none;\n touch-action:none;\n}\n.tm-progress-bar{\n width:100%;\n height:8px;\n background-color:hsla(var(--shadcn-muted) / 0.5);\n border-radius:8px;\n overflow:hidden;\n position:relative;\n transition:height 0.15s;\n}\n\n.tm-progress-bar:hover{\n height:6px;\n}\n.tm-progress-bar-expanded{\n height:16px !important;\n}\n\n.tm-progress-bar-normal{\n height:8px !important;\n}\n.tm-progress-bar.tm-dragging{\n height:16px !important;\n background-color:hsla(var(--shadcn-muted-foreground) / 0.7);\n cursor:grabbing;\n}\n.tm-progress-bar-container:has(.tm-dragging){\n cursor:grabbing;\n}\n.tm-progress-indicator{\n height:100%;\n width:0%;\n background-color:hsla(var(--shadcn-muted) / 0.8);\n border-radius:0;\n position:absolute;\n left:0;\n top:0;\n transition:width 0.1s linear;\n overflow:hidden;\n}\n.tm-dragging .tm-progress-indicator{\n background-color:hsl(var(--shadcn-card-foreground));\n box-shadow:none;\n transition:none;\n}\n.tm-progress-handle{\n width:12px;\n height:12px;\n background-color:hsl(var(--shadcn-blue));\n border:2px solid hsl(var(--shadcn-card));\n border-radius:50%;\n position:absolute;\n top:50%;\n left:0%;\n transform:translate(0, -50%);\n z-index:2;\n opacity:1;\n transition:opacity 0.15s, width 0.15s, height 0.15s, box-shadow 0.15s;\n box-shadow:0 0 0 4px hsl(var(--shadcn-blue) / 0.2);\n cursor:grab;\n}\n\n.tm-progress-handle:hover,\n.tm-progress-handle.dragging{\n transform:translate(0, -50%) scale(1.1);\n box-shadow:0 0 0 6px hsl(var(--shadcn-blue) / 0.3);\n}\n.tm-settings-label{\n cursor:pointer;\n flex:1;\n font-family:var(--font-sans);\n font-size:14px;\n color:hsl(var(--shadcn-foreground));\n}\n.tm-playback-control-row button{\n display:flex;\n align-items:center;\n justify-content:center;\n width:36px;\n height:36px;\n padding:0px;\n border:none;\n border-radius:50%;\n background-color:transparent;\n color:#fff;\n cursor:pointer;\n transition:all 0.15s ease;\n -webkit-tap-highlight-color:transparent;\n}\n\n.tm-playback-control-row button:hover{\n background-color:hsla(var(--shadcn-secondary) / 0.15);\n transform:scale(1.05);\n}\n\n.tm-playback-control-row button:active{\n transform:scale(0.95);\n}\n\n.tm-playback-control-row button svg{\n width:22px;\n height:22px;\n stroke:currentColor;\n stroke-width:2;\n fill:none;\n}\n@media (hover: none){\n .tm-playback-control-row button{\n width:36px;\n height:36px;\n }\n}\n@media (prefers-color-scheme: dark){\n .tm-playback-control-row button svg{\n stroke:hsl(var(--shadcn-primary));\n }\n} `, ""]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/ui/style.css?./node_modules/css-loader/dist/cjs.js??ruleSet%5B1%5D.rules%5B1%5D.use%5B1%5D!./node_modules/postcss-loader/dist/cjs.js??ruleSet%5B1%5D.rules%5B1%5D.use%5B2%5D');
},
"./node_modules/css-loader/dist/runtime/api.js": module => {
eval('\n\n/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n*/\nmodule.exports = function (cssWithMappingToString) {\n var list = [];\n\n // return the list of modules as css string\n list.toString = function toString() {\n return this.map(function (item) {\n var content = "";\n var needLayer = typeof item[5] !== "undefined";\n if (item[4]) {\n content += "@supports (".concat(item[4], ") {");\n }\n if (item[2]) {\n content += "@media ".concat(item[2], " {");\n }\n if (needLayer) {\n content += "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {");\n }\n content += cssWithMappingToString(item);\n if (needLayer) {\n content += "}";\n }\n if (item[2]) {\n content += "}";\n }\n if (item[4]) {\n content += "}";\n }\n return content;\n }).join("");\n };\n\n // import a list of modules into the list\n list.i = function i(modules, media, dedupe, supports, layer) {\n if (typeof modules === "string") {\n modules = [[null, modules, undefined]];\n }\n var alreadyImportedModules = {};\n if (dedupe) {\n for (var k = 0; k < this.length; k++) {\n var id = this[k][0];\n if (id != null) {\n alreadyImportedModules[id] = true;\n }\n }\n }\n for (var _k = 0; _k < modules.length; _k++) {\n var item = [].concat(modules[_k]);\n if (dedupe && alreadyImportedModules[item[0]]) {\n continue;\n }\n if (typeof layer !== "undefined") {\n if (typeof item[5] === "undefined") {\n item[5] = layer;\n } else {\n item[1] = "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {").concat(item[1], "}");\n item[5] = layer;\n }\n }\n if (media) {\n if (!item[2]) {\n item[2] = media;\n } else {\n item[1] = "@media ".concat(item[2], " {").concat(item[1], "}");\n item[2] = media;\n }\n }\n if (supports) {\n if (!item[4]) {\n item[4] = "".concat(supports);\n } else {\n item[1] = "@supports (".concat(item[4], ") {").concat(item[1], "}");\n item[4] = supports;\n }\n }\n list.push(item);\n }\n };\n return list;\n};\n\n//# sourceURL=webpack://miss-noad-video-player/./node_modules/css-loader/dist/runtime/api.js?');
},
"./node_modules/css-loader/dist/runtime/noSourceMaps.js": module => {
eval("\n\nmodule.exports = function (i) {\n return i[1];\n};\n\n//# sourceURL=webpack://miss-noad-video-player/./node_modules/css-loader/dist/runtime/noSourceMaps.js?");
},
"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js": module => {
eval('\n\nvar stylesInDOM = [];\nfunction getIndexByIdentifier(identifier) {\n var result = -1;\n for (var i = 0; i < stylesInDOM.length; i++) {\n if (stylesInDOM[i].identifier === identifier) {\n result = i;\n break;\n }\n }\n return result;\n}\nfunction modulesToDom(list, options) {\n var idCountMap = {};\n var identifiers = [];\n for (var i = 0; i < list.length; i++) {\n var item = list[i];\n var id = options.base ? item[0] + options.base : item[0];\n var count = idCountMap[id] || 0;\n var identifier = "".concat(id, " ").concat(count);\n idCountMap[id] = count + 1;\n var indexByIdentifier = getIndexByIdentifier(identifier);\n var obj = {\n css: item[1],\n media: item[2],\n sourceMap: item[3],\n supports: item[4],\n layer: item[5]\n };\n if (indexByIdentifier !== -1) {\n stylesInDOM[indexByIdentifier].references++;\n stylesInDOM[indexByIdentifier].updater(obj);\n } else {\n var updater = addElementStyle(obj, options);\n options.byIndex = i;\n stylesInDOM.splice(i, 0, {\n identifier: identifier,\n updater: updater,\n references: 1\n });\n }\n identifiers.push(identifier);\n }\n return identifiers;\n}\nfunction addElementStyle(obj, options) {\n var api = options.domAPI(options);\n api.update(obj);\n var updater = function updater(newObj) {\n if (newObj) {\n if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap && newObj.supports === obj.supports && newObj.layer === obj.layer) {\n return;\n }\n api.update(obj = newObj);\n } else {\n api.remove();\n }\n };\n return updater;\n}\nmodule.exports = function (list, options) {\n options = options || {};\n list = list || [];\n var lastIdentifiers = modulesToDom(list, options);\n return function update(newList) {\n newList = newList || [];\n for (var i = 0; i < lastIdentifiers.length; i++) {\n var identifier = lastIdentifiers[i];\n var index = getIndexByIdentifier(identifier);\n stylesInDOM[index].references--;\n }\n var newLastIdentifiers = modulesToDom(newList, options);\n for (var _i = 0; _i < lastIdentifiers.length; _i++) {\n var _identifier = lastIdentifiers[_i];\n var _index = getIndexByIdentifier(_identifier);\n if (stylesInDOM[_index].references === 0) {\n stylesInDOM[_index].updater();\n stylesInDOM.splice(_index, 1);\n }\n }\n lastIdentifiers = newLastIdentifiers;\n };\n};\n\n//# sourceURL=webpack://miss-noad-video-player/./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js?');
},
"./node_modules/style-loader/dist/runtime/insertBySelector.js": module => {
eval('\n\nvar memo = {};\n\n/* istanbul ignore next */\nfunction getTarget(target) {\n if (typeof memo[target] === "undefined") {\n var styleTarget = document.querySelector(target);\n\n // Special case to return head of iframe instead of iframe itself\n if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n try {\n // This will throw an exception if access to iframe is blocked\n // due to cross-origin restrictions\n styleTarget = styleTarget.contentDocument.head;\n } catch (e) {\n // istanbul ignore next\n styleTarget = null;\n }\n }\n memo[target] = styleTarget;\n }\n return memo[target];\n}\n\n/* istanbul ignore next */\nfunction insertBySelector(insert, style) {\n var target = getTarget(insert);\n if (!target) {\n throw new Error("Couldn\'t find a style target. This probably means that the value for the \'insert\' parameter is invalid.");\n }\n target.appendChild(style);\n}\nmodule.exports = insertBySelector;\n\n//# sourceURL=webpack://miss-noad-video-player/./node_modules/style-loader/dist/runtime/insertBySelector.js?');
},
"./node_modules/style-loader/dist/runtime/insertStyleElement.js": module => {
eval('\n\n/* istanbul ignore next */\nfunction insertStyleElement(options) {\n var element = document.createElement("style");\n options.setAttributes(element, options.attributes);\n options.insert(element, options.options);\n return element;\n}\nmodule.exports = insertStyleElement;\n\n//# sourceURL=webpack://miss-noad-video-player/./node_modules/style-loader/dist/runtime/insertStyleElement.js?');
},
"./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js": (module, __unused_webpack_exports, __webpack_require__) => {
eval('\n\n/* istanbul ignore next */\nfunction setAttributesWithoutAttributes(styleElement) {\n var nonce = true ? __webpack_require__.nc : 0;\n if (nonce) {\n styleElement.setAttribute("nonce", nonce);\n }\n}\nmodule.exports = setAttributesWithoutAttributes;\n\n//# sourceURL=webpack://miss-noad-video-player/./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js?');
},
"./node_modules/style-loader/dist/runtime/styleDomAPI.js": module => {
eval('\n\n/* istanbul ignore next */\nfunction apply(styleElement, options, obj) {\n var css = "";\n if (obj.supports) {\n css += "@supports (".concat(obj.supports, ") {");\n }\n if (obj.media) {\n css += "@media ".concat(obj.media, " {");\n }\n var needLayer = typeof obj.layer !== "undefined";\n if (needLayer) {\n css += "@layer".concat(obj.layer.length > 0 ? " ".concat(obj.layer) : "", " {");\n }\n css += obj.css;\n if (needLayer) {\n css += "}";\n }\n if (obj.media) {\n css += "}";\n }\n if (obj.supports) {\n css += "}";\n }\n var sourceMap = obj.sourceMap;\n if (sourceMap && typeof btoa !== "undefined") {\n css += "\\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */");\n }\n\n // For old IE\n /* istanbul ignore if */\n options.styleTagTransform(css, styleElement, options.options);\n}\nfunction removeStyleElement(styleElement) {\n // istanbul ignore if\n if (styleElement.parentNode === null) {\n return false;\n }\n styleElement.parentNode.removeChild(styleElement);\n}\n\n/* istanbul ignore next */\nfunction domAPI(options) {\n if (typeof document === "undefined") {\n return {\n update: function update() {},\n remove: function remove() {}\n };\n }\n var styleElement = options.insertStyleElement(options);\n return {\n update: function update(obj) {\n apply(styleElement, options, obj);\n },\n remove: function remove() {\n removeStyleElement(styleElement);\n }\n };\n}\nmodule.exports = domAPI;\n\n//# sourceURL=webpack://miss-noad-video-player/./node_modules/style-loader/dist/runtime/styleDomAPI.js?');
},
"./node_modules/style-loader/dist/runtime/styleTagTransform.js": module => {
eval("\n\n/* istanbul ignore next */\nfunction styleTagTransform(css, styleElement) {\n if (styleElement.styleSheet) {\n styleElement.styleSheet.cssText = css;\n } else {\n while (styleElement.firstChild) {\n styleElement.removeChild(styleElement.firstChild);\n }\n styleElement.appendChild(document.createTextNode(css));\n }\n}\nmodule.exports = styleTagTransform;\n\n//# sourceURL=webpack://miss-noad-video-player/./node_modules/style-loader/dist/runtime/styleTagTransform.js?");
},
"./src/adblock/AdBlockConfig.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\r\n * 广告屏蔽配置管理类\r\n * 负责管理和提供各网站的广告屏蔽配置\r\n */\n/**\r\n * 配置管理类\r\n */\nvar AdBlockConfig = /*#__PURE__*/function () {\n /**\r\n * 创建配置管理实例\r\n * @param {Object} siteConfig - 站点特定配置\r\n */\n function AdBlockConfig() {\n var siteConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _classCallCheck(this, AdBlockConfig);\n // 广告选择器\n this.adSelectors = siteConfig.adSelectors || [];\n\n // 自定义样式\n this.customStyles = siteConfig.customStyles || [];\n\n // 被阻止的URL模式集合\n this.blockedUrlPatternsSet = new Set(siteConfig.blockedUrlPatterns || []);\n\n // 预编译的广告关键词正则表达式\n this.adKeywordsRegex = /ads|analytics|tracker|affiliate|stat|pixel|banner|pop|click|outstream\\.video|vast|vmap|preroll|midroll|postroll|adserve/i;\n }\n\n /**\r\n * 检查配置是否为空\r\n * @returns {boolean} 是否为空配置\r\n */\n return _createClass(AdBlockConfig, [{\n key: "isEmpty",\n value: function isEmpty() {\n return this.adSelectors.length === 0 && this.customStyles.length === 0 && this.blockedUrlPatternsSet.size === 0;\n }\n\n /**\r\n * 检查URL是否应当被阻止\r\n * @param {string} url - 待检查的URL\r\n * @returns {boolean} 是否应当阻止\r\n */\n }, {\n key: "shouldBlockUrl",\n value: function shouldBlockUrl(url) {\n if (!url || typeof url !== \'string\') return false;\n\n // 使用预编译的正则表达式检查\n if (this.adKeywordsRegex.test(url)) {\n return true;\n }\n\n // 使用Set的has方法更快地检查特定域名\n var _iterator = _createForOfIteratorHelper(this.blockedUrlPatternsSet),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var pattern = _step.value;\n if (url.includes(pattern)) {\n return true;\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n return false;\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdBlockConfig);\n\n//# sourceURL=webpack://miss-noad-video-player/./src/adblock/AdBlockConfig.js?');
},
"./src/adblock/DOMCleaner.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\r\n * DOM清理类\r\n * 负责移除DOM中的广告元素和监控DOM变化\r\n */\n/**\r\n * DOM清理类\r\n */\nvar DOMCleaner = /*#__PURE__*/function () {\n /**\r\n * 创建DOM清理实例\r\n * @param {Object} config - 广告屏蔽配置\r\n */\n function DOMCleaner(config) {\n _classCallCheck(this, DOMCleaner);\n this.config = config;\n this.CLEANUP_THROTTLE = 500; // 节流时间:500ms\n this.observer = null; // MutationObserver实例\n }\n\n /**\r\n * 清理iframe - 优化为只清理新iframe\r\n * @param {NodeList} iframeElements - 可选的iframe元素列表\r\n */\n return _createClass(DOMCleaner, [{\n key: "cleanIframes",\n value: function cleanIframes() {\n var iframeElements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var iframes = iframeElements || document.getElementsByTagName(\'iframe\');\n for (var i = 0; i < iframes.length; i++) {\n var iframe = iframes[i];\n // 只保留播放器相关iframe,移除其他广告iframe\n if (iframe.src && !iframe.src.includes(\'plyr.io\')) {\n iframe.remove();\n }\n }\n }\n\n /**\r\n * 移除广告元素\r\n * @param {boolean} force - 是否强制清理\r\n */\n }, {\n key: "removeAdElements",\n value: function removeAdElements() {\n var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n if (this.config.adSelectors.length === 0) {\n return; // 无选择器,不需要清理\n }\n for (var i = 0; i < this.config.adSelectors.length; i++) {\n try {\n var elements = document.querySelectorAll(this.config.adSelectors[i]);\n for (var j = 0; j < elements.length; j++) {\n elements[j].remove();\n }\n } catch (e) {\n // 忽略选择器错误\n }\n }\n }\n\n /**\r\n * 设置DOM变化监听\r\n */\n }, {\n key: "observeDOMChanges",\n value: function observeDOMChanges() {\n var _this = this;\n // 如果已经在观察,则不重复设置\n if (this.observer) {\n return;\n }\n var pendingChanges = false;\n var frameChanges = false;\n var processingTimeout = null;\n var processChanges = function processChanges() {\n if (pendingChanges) {\n _this.removeAdElements();\n pendingChanges = false;\n }\n if (frameChanges) {\n _this.cleanIframes();\n frameChanges = false;\n }\n processingTimeout = null;\n };\n this.observer = new MutationObserver(function (mutations) {\n var hasNewNodes = false;\n var hasNewIframes = false;\n\n // 快速检查是否有相关变化\n for (var i = 0; i < mutations.length; i++) {\n var mutation = mutations[i];\n if (mutation.addedNodes.length) {\n hasNewNodes = true;\n // 检查是否有新增的iframe\n for (var j = 0; j < mutation.addedNodes.length; j++) {\n var node = mutation.addedNodes[j];\n if (node.nodeName === \'IFRAME\') {\n hasNewIframes = true;\n break;\n }\n }\n }\n if (hasNewNodes && hasNewIframes) break; // 找到所需信息后立即退出循环\n }\n if (hasNewNodes) {\n pendingChanges = true;\n }\n if (hasNewIframes) {\n frameChanges = true;\n }\n\n // 使用节流处理DOM变化\n if ((pendingChanges || frameChanges) && !processingTimeout) {\n processingTimeout = setTimeout(processChanges, 50);\n }\n });\n\n // 开始观察整个文档\n this.observer.observe(document.documentElement, {\n childList: true,\n subtree: true\n });\n }\n\n /**\r\n * 停止DOM变化监听\r\n */\n }, {\n key: "disconnect",\n value: function disconnect() {\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DOMCleaner);\n\n//# sourceURL=webpack://miss-noad-video-player/./src/adblock/DOMCleaner.js?');
},
"./src/adblock/RequestBlocker.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\r\n * 请求拦截类\r\n * 负责拦截和阻止广告相关网络请求\r\n */\n/**\r\n * 请求拦截类\r\n */\nvar RequestBlocker = /*#__PURE__*/function () {\n /**\r\n * 创建请求拦截实例\r\n * @param {Object} config - 广告屏蔽配置\r\n */\n function RequestBlocker(config) {\n _classCallCheck(this, RequestBlocker);\n this.config = config;\n }\n\n /**\r\n * 拦截XMLHttpRequest和Fetch请求\r\n */\n return _createClass(RequestBlocker, [{\n key: "blockTrackingRequests",\n value: function blockTrackingRequests() {\n // 拦截XMLHttpRequest\n var originalXHR = XMLHttpRequest.prototype.open;\n var config = this.config;\n\n // 使用普通函数而不是箭头函数,保留正确的this上下文\n XMLHttpRequest.prototype.open = function (method, url) {\n if (typeof url === \'string\' && config.shouldBlockUrl(url)) {\n // 返回一个虚拟方法,避免脚本错误\n this.send = function () {};\n this.onload = null;\n this.onerror = null;\n return;\n }\n return originalXHR.apply(this, arguments);\n };\n\n // 拦截Fetch请求\n var originalFetch = window.fetch;\n window.fetch = function (url, options) {\n // 处理 Request 对象作为参数的情况\n var urlToCheck = url;\n if (url instanceof Request) {\n urlToCheck = url.url;\n }\n if (typeof urlToCheck === \'string\' && config.shouldBlockUrl(urlToCheck)) {\n // 返回一个解析为空的Response,避免错误\n return Promise.resolve(new Response(\'\', {\n status: 200,\n headers: {\n \'Content-Type\': \'text/plain\'\n }\n }));\n }\n return originalFetch.apply(this, arguments);\n };\n }\n\n /**\r\n * 拦截iframe加载\r\n */\n }, {\n key: "blockIframeLoading",\n value: function blockIframeLoading() {\n var createElementOriginal = document.createElement;\n var config = this.config;\n document.createElement = function (tag) {\n var element = createElementOriginal.call(document, tag);\n if (tag.toLowerCase() === \'iframe\') {\n // 正确实现src属性的拦截\n var originalSrc = element.src;\n Object.defineProperty(element, \'src\', {\n set: function set(value) {\n if (typeof value === \'string\' && config.shouldBlockUrl(value)) {\n return;\n }\n originalSrc = value;\n },\n get: function get() {\n return originalSrc;\n }\n });\n\n // 监控setAttribute\n var originalSetAttribute = element.setAttribute;\n element.setAttribute = function (name, value) {\n if (name === \'src\' && typeof value === \'string\' && config.shouldBlockUrl(value)) {\n return;\n }\n return originalSetAttribute.call(this, name, value);\n };\n }\n return element;\n };\n }\n\n /**\r\n * 阻止弹窗\r\n */\n }, {\n key: "blockPopups",\n value: function blockPopups() {\n window.open = function () {\n return null;\n };\n if (typeof unsafeWindow !== \'undefined\') {\n unsafeWindow.open = function () {\n return null;\n };\n }\n }\n\n /**\r\n * 初始化所有拦截功能\r\n */\n }, {\n key: "init",\n value: function init() {\n this.blockIframeLoading();\n this.blockTrackingRequests();\n this.blockPopups();\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RequestBlocker);\n\n//# sourceURL=webpack://miss-noad-video-player/./src/adblock/RequestBlocker.js?');
},
"./src/adblock/StyleManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\r\n * 样式管理类\r\n * 负责创建和应用广告屏蔽相关的CSS样式\r\n */\n/**\r\n * 样式管理类\r\n */\nvar StyleManager = /*#__PURE__*/function () {\n /**\r\n * 创建样式管理实例\r\n * @param {Object} config - 广告屏蔽配置\r\n */\n function StyleManager(config) {\n _classCallCheck(this, StyleManager);\n this.config = config;\n }\n\n /**\r\n * 创建并应用广告屏蔽样式\r\n */\n return _createClass(StyleManager, [{\n key: "applyAdBlockStyles",\n value: function applyAdBlockStyles() {\n // 如果无样式,则直接返回\n if (this.config.adSelectors.length === 0 && this.config.customStyles.length === 0) {\n return;\n }\n\n // 创建样式元素\n var styleElement = document.createElement(\'style\');\n styleElement.id = \'adblock-styles\';\n styleElement.type = \'text/css\';\n\n // 构建广告屏蔽CSS\n var css = \'\';\n\n // 添加广告选择器样式\n if (this.config.adSelectors.length > 0) {\n css += this.config.adSelectors.join(\', \') + \' { display: none !important; visibility: hidden !important; height: 0 !important; min-height: 0 !important; }\';\n }\n\n // 添加自定义样式\n if (this.config.customStyles.length > 0) {\n css += \'\\n\' + this.config.customStyles.map(function (item) {\n return "".concat(item.selector, " { ").concat(item.styles, " }");\n }).join(\'\\n\');\n }\n\n // 设置样式内容\n styleElement.textContent = css;\n\n // 添加到文档头部\n document.head.appendChild(styleElement);\n }\n }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StyleManager);\n\n//# sourceURL=webpack://miss-noad-video-player/./src/adblock/StyleManager.js?');
},
"./src/adblock/index.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ "./src/utils/index.js");\n/* harmony import */ var _AdBlockConfig__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AdBlockConfig */ "./src/adblock/AdBlockConfig.js");\n/* harmony import */ var _StyleManager__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./StyleManager */ "./src/adblock/StyleManager.js");\n/* harmony import */ var _DOMCleaner__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./DOMCleaner */ "./src/adblock/DOMCleaner.js");\n/* harmony import */ var _RequestBlocker__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./RequestBlocker */ "./src/adblock/RequestBlocker.js");\n/* harmony import */ var _sites_missav__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./sites/missav */ "./src/adblock/sites/missav.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\r\n * 广告屏蔽模块入口\r\n * 此模块负责屏蔽网站上的广告内容,提供更好的用户体验\r\n */\n\n\n\n\n\n\n\n\n/**\r\n * 根据网站URL获取适合的配置\r\n * @param {string} url - 当前网站URL\r\n * @returns {Object} 站点特定配置\r\n */\nfunction getSiteConfig(url) {\n // 目前只支持missav,未来可以扩展\n if (/^https?:\\/\\/(www\\.)?(missav|thisav)\\.(com|ws|ai)/.test(url)) {\n return _sites_missav__WEBPACK_IMPORTED_MODULE_5__["default"];\n }\n\n // 返回默认空配置\n return {\n adSelectors: [],\n customStyles: [],\n blockedUrlPatterns: []\n };\n}\n\n/**\r\n * 广告屏蔽器类\r\n */\nvar AdBlocker = /*#__PURE__*/function () {\n function AdBlocker() {\n _classCallCheck(this, AdBlocker);\n var siteConfig = getSiteConfig(window.location.href);\n this.config = new _AdBlockConfig__WEBPACK_IMPORTED_MODULE_1__["default"](siteConfig);\n this.styleManager = new _StyleManager__WEBPACK_IMPORTED_MODULE_2__["default"](this.config);\n this.domCleaner = new _DOMCleaner__WEBPACK_IMPORTED_MODULE_3__["default"](this.config);\n this.requestBlocker = new _RequestBlocker__WEBPACK_IMPORTED_MODULE_4__["default"](this.config);\n }\n\n /**\r\n * 防止被检测到AdBlock\r\n */\n return _createClass(AdBlocker, [{\n key: "preventDetection",\n value: function preventDetection() {\n window.AdBlock = false;\n window.adblock = false;\n window.adsbygoogle = {\n loaded: true\n };\n if (typeof unsafeWindow !== \'undefined\') {\n unsafeWindow.AdBlock = false;\n unsafeWindow.adblock = false;\n unsafeWindow.adsbygoogle = {\n loaded: true\n };\n }\n }\n\n /**\r\n * 设置定期清理\r\n */\n }, {\n key: "setupPeriodicCleaning",\n value: function setupPeriodicCleaning() {\n var _this = this;\n // 首次运行强制清理\n this.domCleaner.removeAdElements(true);\n this.domCleaner.observeDOMChanges();\n\n // 定时检查,2秒一次\n setInterval(function () {\n return _this.domCleaner.removeAdElements();\n }, 2000);\n }\n\n /**\r\n * 初始化广告屏蔽器\r\n */\n }, {\n key: "init",\n value: function init() {\n var _this2 = this;\n // 检查当前网站是否需要启用广告屏蔽\n if (this.config.isEmpty()) {\n return; // 无配置,不启用\n }\n // 防止被检测\n this.preventDetection();\n\n // 应用样式(尽早执行)\n this.styleManager.applyAdBlockStyles();\n\n // 初始化请求拦截器\n this.requestBlocker.init();\n\n // 当DOM加载后执行\n if (document.readyState === \'loading\') {\n document.addEventListener(\'DOMContentLoaded\', function () {\n return _this2.setupPeriodicCleaning();\n });\n } else {\n this.setupPeriodicCleaning();\n }\n }\n }]);\n}(); // 导出广告屏蔽器\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdBlocker);\n\n//# sourceURL=webpack://miss-noad-video-player/./src/adblock/index.js?');
},
"./src/adblock/sites/missav.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/**\r\n * Missav网站广告屏蔽配置\r\n * 包含特定于missav.ws/ai/com域名的广告选择器和URL模式\r\n */\n\n/**\r\n * missav网站的广告选择器\r\n */\nvar adSelectors = ['div[class=\"space-y-6 mb-6\"]',\n// 页面右侧便 视频广告\n'div[class*=\"root--\"][class*=\"bottomRight--\"]',\n// 页面右下角视频广告 \n'div[class=\"grid md:grid-cols-2 gap-8\"]',\n// 视频下方新域名推广\n'ul[class=\"mb-4 list-none text-nord14 grid grid-cols-2 gap-2\"]',\n// 视频简介下方链接推广\n'div[class=\"space-y-5 mb-5\"]',\n// 页面底部视频广告\n'iframe[src*=\"ads\"]', 'iframe[src*=\"banner\"]', 'iframe[src*=\"pop\"]', 'iframe[data-ad]', 'iframe[id*=\"ads\"]', 'iframe[class*=\"ads\"]', 'iframe:not([src*=\"plyr.io\"])' // 屏蔽所有非播放器的iframe\n];\n\n/**\r\n * missav网站的自定义样式\r\n */\nvar customStyles = [{\n // 影片列表文字标题完整显示\n selector: 'div[class=\"my-2 text-sm text-nord4 truncate\"]',\n styles: 'white-space: normal !important;'\n}, {\n // 设置页面背景色为黑色\n selector: 'body',\n styles: 'background-color: #000000 !important;'\n}, {\n // 设置z-max元素的z-index\n selector: 'div[class*=\"z-max\"]',\n styles: 'z-index: 9000 !important;'\n}];\n\n/**\r\n * 需要屏蔽的URL模式\r\n */\nvar blockedUrlPatterns = ['exoclick.com', 'juicyads.com', 'popads.net', 'adsterra.com', 'trafficjunky.com', 'adnium.com', 'ad-maven.com', 'browser-update.org', 'mopvip.icu', 'toppages.pw', 'cpmstar.com', 'propellerads.com', 'tsyndicate.com', 'syndication.exosrv.com', 'ads.exosrv.com', 'tsyndicate.com/sdk', 'cdn.tsyndicate.com', 'adsco.re', 'adscpm.site', 'a-ads.com', 'ad-delivery.net', 'outbrain.com', 'taboola.com', 'mgid.com', 'revcontent.com', 'adnxs.com', 'pubmatic.com', 'rubiconproject.com', 'openx.net', 'criteo.com', 'doubleclick.net'];\n\n// 导出missav配置\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n adSelectors: adSelectors,\n customStyles: customStyles,\n blockedUrlPatterns: blockedUrlPatterns,\n // 未来可以添加网站特有的配置\n isVideoSite: true,\n domains: ['missav.ws', 'missav.ai', 'missav.com', 'thisav.com']\n});\n\n//# sourceURL=webpack://miss-noad-video-player/./src/adblock/sites/missav.js?");
},
"./src/autologin/LoginManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LoginManager: () => (/* binding */ LoginManager)\n/* harmony export */ });\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils.js */ "./src/autologin/utils.js");\n/* harmony import */ var _MissavLoginProvider_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MissavLoginProvider.js */ "./src/autologin/MissavLoginProvider.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return r; }; var t, r = {}, e = Object.prototype, n = e.hasOwnProperty, o = "function" == typeof Symbol ? Symbol : {}, i = o.iterator || "@@iterator", a = o.asyncIterator || "@@asyncIterator", u = o.toStringTag || "@@toStringTag"; function c(t, r, e, n) { return Object.defineProperty(t, r, { value: e, enumerable: !n, configurable: !n, writable: !n }); } try { c({}, ""); } catch (t) { c = function c(t, r, e) { return t[r] = e; }; } function h(r, e, n, o) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype); return c(a, "_invoke", function (r, e, n) { var o = 1; return function (i, a) { if (3 === o) throw Error("Generator is already running"); if (4 === o) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var u = n.delegate; if (u) { var c = d(u, n); if (c) { if (c === f) continue; return c; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (1 === o) throw o = 4, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = 3; var h = s(r, e, n); if ("normal" === h.type) { if (o = n.done ? 4 : 2, h.arg === f) continue; return { value: h.arg, done: n.done }; } "throw" === h.type && (o = 4, n.method = "throw", n.arg = h.arg); } }; }(r, n, new Context(o || [])), !0), a; } function s(t, r, e) { try { return { type: "normal", arg: t.call(r, e) }; } catch (t) { return { type: "throw", arg: t }; } } r.wrap = h; var f = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var l = {}; c(l, i, function () { return this; }); var p = Object.getPrototypeOf, y = p && p(p(x([]))); y && y !== e && n.call(y, i) && (l = y); var v = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(l); function g(t) { ["next", "throw", "return"].forEach(function (r) { c(t, r, function (t) { return this._invoke(r, t); }); }); } function AsyncIterator(t, r) { function e(o, i, a, u) { var c = s(t[o], t, i); if ("throw" !== c.type) { var h = c.arg, f = h.value; return f && "object" == _typeof(f) && n.call(f, "__await") ? r.resolve(f.__await).then(function (t) { e("next", t, a, u); }, function (t) { e("throw", t, a, u); }) : r.resolve(f).then(function (t) { h.value = t, a(h); }, function (t) { return e("throw", t, a, u); }); } u(c.arg); } var o; c(this, "_invoke", function (t, n) { function i() { return new r(function (r, o) { e(t, n, r, o); }); } return o = o ? o.then(i, i) : i(); }, !0); } function d(r, e) { var n = e.method, o = r.i[n]; if (o === t) return e.delegate = null, "throw" === n && r.i["return"] && (e.method = "return", e.arg = t, d(r, e), "throw" === e.method) || "return" !== n && (e.method = "throw", e.arg = new TypeError("The iterator does not provide a \'" + n + "\' method")), f; var i = s(o, r.i, e.arg); if ("throw" === i.type) return e.method = "throw", e.arg = i.arg, e.delegate = null, f; var a = i.arg; return a ? a.done ? (e[r.r] = a.value, e.next = r.n, "return" !== e.method && (e.method = "next", e.arg = t), e.delegate = null, f) : a : (e.method = "throw", e.arg = new TypeError("iterator result is not an object"), e.delegate = null, f); } function w(t) { this.tryEntries.push(t); } function m(r) { var e = r[4] || {}; e.type = "normal", e.arg = t, r[4] = e; } function Context(t) { this.tryEntries = [[-1]], t.forEach(w, this), this.reset(!0); } function x(r) { if (null != r) { var e = r[i]; if (e) return e.call(r); if ("function" == typeof r.next) return r; if (!isNaN(r.length)) { var o = -1, a = function e() { for (; ++o < r.length;) if (n.call(r, o)) return e.value = r[o], e.done = !1, e; return e.value = t, e.done = !0, e; }; return a.next = a; } } throw new TypeError(_typeof(r) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, c(v, "constructor", GeneratorFunctionPrototype), c(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = c(GeneratorFunctionPrototype, u, "GeneratorFunction"), r.isGeneratorFunction = function (t) { var r = "function" == typeof t && t.constructor; return !!r && (r === GeneratorFunction || "GeneratorFunction" === (r.displayName || r.name)); }, r.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, c(t, u, "GeneratorFunction")), t.prototype = Object.create(v), t; }, r.awrap = function (t) { return { __await: t }; }, g(AsyncIterator.prototype), c(AsyncIterator.prototype, a, function () { return this; }), r.AsyncIterator = AsyncIterator, r.async = function (t, e, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(h(t, e, n, o), i); return r.isGeneratorFunction(e) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, g(v), c(v, u, "Generator"), c(v, i, function () { return this; }), c(v, "toString", function () { return "[object Generator]"; }), r.keys = function (t) { var r = Object(t), e = []; for (var n in r) e.unshift(n); return function t() { for (; e.length;) if ((n = e.pop()) in r) return t.value = n, t.done = !1, t; return t.done = !0, t; }; }, r.values = x, Context.prototype = { constructor: Context, reset: function reset(r) { if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(m), !r) for (var e in this) "t" === e.charAt(0) && n.call(this, e) && !isNaN(+e.slice(1)) && (this[e] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0][4]; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(r) { if (this.done) throw r; var e = this; function n(t) { a.type = "throw", a.arg = r, e.next = t; } for (var o = e.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i[4], u = this.prev, c = i[1], h = i[2]; if (-1 === i[0]) return n("end"), !1; if (!c && !h) throw Error("try statement without catch or finally"); if (null != i[0] && i[0] <= u) { if (u < c) return this.method = "next", this.arg = t, n(c), !0; if (u < h) return n(h), !1; } } }, abrupt: function abrupt(t, r) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var n = this.tryEntries[e]; if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) { var o = n; break; } } o && ("break" === t || "continue" === t) && o[0] <= r && r <= o[2] && (o = null); var i = o ? o[4] : {}; return i.type = t, i.arg = r, o ? (this.method = "next", this.next = o[2], f) : this.complete(i); }, complete: function complete(t, r) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && r && (this.next = r), f; }, finish: function finish(t) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var e = this.tryEntries[r]; if (e[2] === t) return this.complete(e[4], e[3]), m(e), f; } }, "catch": function _catch(t) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var e = this.tryEntries[r]; if (e[0] === t) { var n = e[4]; if ("throw" === n.type) { var o = n.arg; m(e); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(r, e, n) { return this.delegate = { i: x(r), r: e, n: n }, "next" === this.method && (this.arg = t), f; } }, r; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\n * 登录管理器 - 负责管理多个网站的登录逻辑\n */\n\n\nvar LoginManager = /*#__PURE__*/function () {\n /**\n * 构造函数\n */\n function LoginManager() {\n _classCallCheck(this, LoginManager);\n // 登录信息\n this.userEmail = \'\';\n this.userPassword = \'\';\n this.autoLogin = true;\n\n // 登录提供者列表\n this.providers = [new _MissavLoginProvider_js__WEBPACK_IMPORTED_MODULE_1__.MissavLoginProvider()];\n\n // 当前活跃的提供者\n this.activeProvider = null;\n }\n\n /**\n * 初始化登录管理器\n */\n return _createClass(LoginManager, [{\n key: "init",\n value: (function () {\n var _init = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n // 加载存储的登录信息\n this.loadLoginInfo();\n\n // 根据当前URL选择合适的登录提供者\n this.activeProvider = this.getMatchingProvider();\n\n // 如果没有合适的提供者,不执行后续操作\n if (this.activeProvider) {\n _context.next = 4;\n break;\n }\n return _context.abrupt("return");\n case 4:\n _context.next = 6;\n return this.activeProvider.addAutoLoginOption(this.handleLoginInfoChange.bind(this));\n case 6:\n _context.next = 8;\n return this.checkLoginAndAutoLogin();\n case 8:\n case "end":\n return _context.stop();\n }\n }, _callee, this);\n }));\n function init() {\n return _init.apply(this, arguments);\n }\n return init;\n }()\n /**\n * 处理登录信息变更\n * @param {Object} info - 变更的登录信息\n * @param {string} [info.email] - 邮箱\n * @param {string} [info.password] - 密码\n * @param {boolean} [info.autoLogin] - 是否自动登录\n */\n )\n }, {\n key: "handleLoginInfoChange",\n value: function handleLoginInfoChange(info) {\n if (info.email !== undefined) {\n this.userEmail = info.email;\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.setValue(\'userEmail\', info.email);\n }\n if (info.password !== undefined) {\n this.userPassword = info.password;\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.setValue(\'userPassword\', info.password);\n }\n if (info.autoLogin !== undefined) {\n this.autoLogin = info.autoLogin;\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.setValue(\'autoLogin\', info.autoLogin);\n }\n }\n\n /**\n * 加载存储的登录信息\n */\n }, {\n key: "loadLoginInfo",\n value: function loadLoginInfo() {\n this.userEmail = _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.getValue(\'userEmail\', \'\');\n this.userPassword = _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.getValue(\'userPassword\', \'\');\n this.autoLogin = _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.getValue(\'autoLogin\', true);\n }\n\n /**\n * 获取匹配当前网站的登录提供者\n * @returns {Object|null} 匹配的登录提供者或null\n */\n }, {\n key: "getMatchingProvider",\n value: function getMatchingProvider() {\n var _iterator = _createForOfIteratorHelper(this.providers),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var provider = _step.value;\n if (provider.isSupportedSite()) {\n return provider;\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n return null;\n }\n\n /**\n * 检查登录状态并执行自动登录\n */\n }, {\n key: "checkLoginAndAutoLogin",\n value: (function () {\n var _checkLoginAndAutoLogin = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n var isLoggedIn;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n if (this.activeProvider) {\n _context2.next = 2;\n break;\n }\n return _context2.abrupt("return");\n case 2:\n _context2.prev = 2;\n _context2.next = 5;\n return this.activeProvider.checkLoginStatus();\n case 5:\n isLoggedIn = _context2.sent;\n if (!(!isLoggedIn && this.autoLogin && this.userEmail && this.userPassword)) {\n _context2.next = 9;\n break;\n }\n _context2.next = 9;\n return this.activeProvider.login(this.userEmail, this.userPassword);\n case 9:\n _context2.next = 13;\n break;\n case 11:\n _context2.prev = 11;\n _context2.t0 = _context2["catch"](2);\n case 13:\n case "end":\n return _context2.stop();\n }\n }, _callee2, this, [[2, 11]]);\n }));\n function checkLoginAndAutoLogin() {\n return _checkLoginAndAutoLogin.apply(this, arguments);\n }\n return checkLoginAndAutoLogin;\n }()\n /**\n * 手动执行登录操作\n * @param {string} email - 用户邮箱\n * @param {string} password - 用户密码\n * @returns {Promise<boolean>} 登录是否成功\n */\n )\n }, {\n key: "login",\n value: (function () {\n var _login = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(email, password) {\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n if (this.activeProvider) {\n _context3.next = 2;\n break;\n }\n return _context3.abrupt("return", false);\n case 2:\n // 更新登录信息\n this.handleLoginInfoChange({\n email: email,\n password: password\n });\n\n // 执行登录\n _context3.next = 5;\n return this.activeProvider.login(email, password);\n case 5:\n return _context3.abrupt("return", _context3.sent);\n case 6:\n case "end":\n return _context3.stop();\n }\n }, _callee3, this);\n }));\n function login(_x, _x2) {\n return _login.apply(this, arguments);\n }\n return login;\n }())\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/autologin/LoginManager.js?');
},
"./src/autologin/MissavLoginProvider.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ MissavLoginProvider: () => (/* binding */ MissavLoginProvider)\n/* harmony export */ });\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils.js */ "./src/autologin/utils.js");\n/* harmony import */ var _i18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./i18n.js */ "./src/autologin/i18n.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return r; }; var t, r = {}, e = Object.prototype, n = e.hasOwnProperty, o = "function" == typeof Symbol ? Symbol : {}, i = o.iterator || "@@iterator", a = o.asyncIterator || "@@asyncIterator", u = o.toStringTag || "@@toStringTag"; function c(t, r, e, n) { return Object.defineProperty(t, r, { value: e, enumerable: !n, configurable: !n, writable: !n }); } try { c({}, ""); } catch (t) { c = function c(t, r, e) { return t[r] = e; }; } function h(r, e, n, o) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype); return c(a, "_invoke", function (r, e, n) { var o = 1; return function (i, a) { if (3 === o) throw Error("Generator is already running"); if (4 === o) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var u = n.delegate; if (u) { var c = d(u, n); if (c) { if (c === f) continue; return c; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (1 === o) throw o = 4, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = 3; var h = s(r, e, n); if ("normal" === h.type) { if (o = n.done ? 4 : 2, h.arg === f) continue; return { value: h.arg, done: n.done }; } "throw" === h.type && (o = 4, n.method = "throw", n.arg = h.arg); } }; }(r, n, new Context(o || [])), !0), a; } function s(t, r, e) { try { return { type: "normal", arg: t.call(r, e) }; } catch (t) { return { type: "throw", arg: t }; } } r.wrap = h; var f = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var l = {}; c(l, i, function () { return this; }); var p = Object.getPrototypeOf, y = p && p(p(x([]))); y && y !== e && n.call(y, i) && (l = y); var v = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(l); function g(t) { ["next", "throw", "return"].forEach(function (r) { c(t, r, function (t) { return this._invoke(r, t); }); }); } function AsyncIterator(t, r) { function e(o, i, a, u) { var c = s(t[o], t, i); if ("throw" !== c.type) { var h = c.arg, f = h.value; return f && "object" == _typeof(f) && n.call(f, "__await") ? r.resolve(f.__await).then(function (t) { e("next", t, a, u); }, function (t) { e("throw", t, a, u); }) : r.resolve(f).then(function (t) { h.value = t, a(h); }, function (t) { return e("throw", t, a, u); }); } u(c.arg); } var o; c(this, "_invoke", function (t, n) { function i() { return new r(function (r, o) { e(t, n, r, o); }); } return o = o ? o.then(i, i) : i(); }, !0); } function d(r, e) { var n = e.method, o = r.i[n]; if (o === t) return e.delegate = null, "throw" === n && r.i["return"] && (e.method = "return", e.arg = t, d(r, e), "throw" === e.method) || "return" !== n && (e.method = "throw", e.arg = new TypeError("The iterator does not provide a \'" + n + "\' method")), f; var i = s(o, r.i, e.arg); if ("throw" === i.type) return e.method = "throw", e.arg = i.arg, e.delegate = null, f; var a = i.arg; return a ? a.done ? (e[r.r] = a.value, e.next = r.n, "return" !== e.method && (e.method = "next", e.arg = t), e.delegate = null, f) : a : (e.method = "throw", e.arg = new TypeError("iterator result is not an object"), e.delegate = null, f); } function w(t) { this.tryEntries.push(t); } function m(r) { var e = r[4] || {}; e.type = "normal", e.arg = t, r[4] = e; } function Context(t) { this.tryEntries = [[-1]], t.forEach(w, this), this.reset(!0); } function x(r) { if (null != r) { var e = r[i]; if (e) return e.call(r); if ("function" == typeof r.next) return r; if (!isNaN(r.length)) { var o = -1, a = function e() { for (; ++o < r.length;) if (n.call(r, o)) return e.value = r[o], e.done = !1, e; return e.value = t, e.done = !0, e; }; return a.next = a; } } throw new TypeError(_typeof(r) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, c(v, "constructor", GeneratorFunctionPrototype), c(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = c(GeneratorFunctionPrototype, u, "GeneratorFunction"), r.isGeneratorFunction = function (t) { var r = "function" == typeof t && t.constructor; return !!r && (r === GeneratorFunction || "GeneratorFunction" === (r.displayName || r.name)); }, r.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, c(t, u, "GeneratorFunction")), t.prototype = Object.create(v), t; }, r.awrap = function (t) { return { __await: t }; }, g(AsyncIterator.prototype), c(AsyncIterator.prototype, a, function () { return this; }), r.AsyncIterator = AsyncIterator, r.async = function (t, e, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(h(t, e, n, o), i); return r.isGeneratorFunction(e) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, g(v), c(v, u, "Generator"), c(v, i, function () { return this; }), c(v, "toString", function () { return "[object Generator]"; }), r.keys = function (t) { var r = Object(t), e = []; for (var n in r) e.unshift(n); return function t() { for (; e.length;) if ((n = e.pop()) in r) return t.value = n, t.done = !1, t; return t.done = !0, t; }; }, r.values = x, Context.prototype = { constructor: Context, reset: function reset(r) { if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(m), !r) for (var e in this) "t" === e.charAt(0) && n.call(this, e) && !isNaN(+e.slice(1)) && (this[e] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0][4]; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(r) { if (this.done) throw r; var e = this; function n(t) { a.type = "throw", a.arg = r, e.next = t; } for (var o = e.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i[4], u = this.prev, c = i[1], h = i[2]; if (-1 === i[0]) return n("end"), !1; if (!c && !h) throw Error("try statement without catch or finally"); if (null != i[0] && i[0] <= u) { if (u < c) return this.method = "next", this.arg = t, n(c), !0; if (u < h) return n(h), !1; } } }, abrupt: function abrupt(t, r) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var n = this.tryEntries[e]; if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) { var o = n; break; } } o && ("break" === t || "continue" === t) && o[0] <= r && r <= o[2] && (o = null); var i = o ? o[4] : {}; return i.type = t, i.arg = r, o ? (this.method = "next", this.next = o[2], f) : this.complete(i); }, complete: function complete(t, r) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && r && (this.next = r), f; }, finish: function finish(t) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var e = this.tryEntries[r]; if (e[2] === t) return this.complete(e[4], e[3]), m(e), f; } }, "catch": function _catch(t) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var e = this.tryEntries[r]; if (e[0] === t) { var n = e[4]; if ("throw" === n.type) { var o = n.arg; m(e); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(r, e, n) { return this.delegate = { i: x(r), r: e, n: n }, "next" === this.method && (this.arg = t), f; } }, r; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\n * MissAV网站登录提供程序\n */\n\n\nvar MissavLoginProvider = /*#__PURE__*/function () {\n /**\n * 构造函数\n */\n function MissavLoginProvider() {\n _classCallCheck(this, MissavLoginProvider);\n // 域名列表 - 支持多个平行域名\n this.domains = [\'missav.ws\', \'missav.ai\', \'missav.com\', \'thisav.com\'];\n }\n\n /**\n * 检查当前网站是否由本提供程序支持\n * @returns {boolean} 是否支持当前网站\n */\n return _createClass(MissavLoginProvider, [{\n key: "isSupportedSite",\n value: function isSupportedSite() {\n var currentDomain = window.location.hostname;\n return this.domains.some(function (domain) {\n return currentDomain.includes(domain);\n });\n }\n\n /**\n * 登录处理函数\n * @param {string} email - 用户邮箱\n * @param {string} password - 用户密码\n * @returns {Promise<boolean>} 登录是否成功\n */\n }, {\n key: "login",\n value: (function () {\n var _login = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(email, password) {\n var _response$headers$get, response, errorText, data, text;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (!(!email || !password)) {\n _context.next = 3;\n break;\n }\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.toast(_i18n_js__WEBPACK_IMPORTED_MODULE_1__.I18n.translate(\'accountNull\'), 2000, \'#FF0000\', \'#ffffff\', \'top\');\n return _context.abrupt("return", false);\n case 3:\n _context.prev = 3;\n _context.next = 6;\n return fetch(\'https://missav.ws/cn/api/login\', {\n method: \'POST\',\n headers: {\n \'Content-Type\': \'application/json\'\n },\n body: JSON.stringify({\n email: email,\n password: password,\n remember: true\n })\n });\n case 6:\n response = _context.sent;\n if (response.ok) {\n _context.next = 13;\n break;\n }\n _context.next = 10;\n return response.text();\n case 10:\n errorText = _context.sent;\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.toast("\\u767B\\u5F55\\u5931\\u8D25: ".concat(errorText), 2000, \'#FF0000\', \'#ffffff\', \'top\');\n throw new Error(_i18n_js__WEBPACK_IMPORTED_MODULE_1__.I18n.translate(\'networkFailed\'));\n case 13:\n if (!((_response$headers$get = response.headers.get(\'Content-Type\')) !== null && _response$headers$get !== void 0 && _response$headers$get.includes(\'application/json\'))) {\n _context.next = 19;\n break;\n }\n _context.next = 16;\n return response.json();\n case 16:\n data = _context.sent;\n _context.next = 24;\n break;\n case 19:\n _context.next = 21;\n return response.text();\n case 21:\n text = _context.sent;\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.toast(_i18n_js__WEBPACK_IMPORTED_MODULE_1__.I18n.translate(\'loginFailed\'), 2000, \'#FF0000\', \'#ffffff\', \'top\');\n throw new Error(_i18n_js__WEBPACK_IMPORTED_MODULE_1__.I18n.translate(\'loginFailed\'));\n case 24:\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.toast(_i18n_js__WEBPACK_IMPORTED_MODULE_1__.I18n.translate(\'loginSuccess\'), 2000, \'rgb(18, 187, 2)\', \'#ffffff\', \'top\');\n\n // 登录成功后刷新页面\n setTimeout(function () {\n location.reload();\n }, 1000);\n return _context.abrupt("return", true);\n case 29:\n _context.prev = 29;\n _context.t0 = _context["catch"](3);\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.toast("\\u9519\\u8BEF\\u53D1\\u751F: ".concat(_context.t0.message), 2000, \'#FF0000\', \'#ffffff\', \'top\');\n return _context.abrupt("return", false);\n case 33:\n case "end":\n return _context.stop();\n }\n }, _callee, null, [[3, 29]]);\n }));\n function login(_x, _x2) {\n return _login.apply(this, arguments);\n }\n return login;\n }()\n /**\n * 检查登录状态\n * @returns {Promise<boolean>} 是否已登录\n */\n )\n }, {\n key: "checkLoginStatus",\n value: (function () {\n var _checkLoginStatus = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n var isLoggedIn;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.prev = 0;\n _context2.next = 3;\n return this.checkLoginByAPI();\n case 3:\n isLoggedIn = _context2.sent;\n if (!(isLoggedIn !== null)) {\n _context2.next = 6;\n break;\n }\n return _context2.abrupt("return", isLoggedIn);\n case 6:\n return _context2.abrupt("return", this.checkLoginByDOM());\n case 9:\n _context2.prev = 9;\n _context2.t0 = _context2["catch"](0);\n return _context2.abrupt("return", false);\n case 12:\n case "end":\n return _context2.stop();\n }\n }, _callee2, this, [[0, 9]]);\n }));\n function checkLoginStatus() {\n return _checkLoginStatus.apply(this, arguments);\n }\n return checkLoginStatus;\n }()\n /**\n * 使用API检测登录状态\n * @returns {Promise<boolean|null>} 登录状态或null(检测失败)\n */\n )\n }, {\n key: "checkLoginByAPI",\n value: (function () {\n var _checkLoginByAPI = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {\n var url, response, data;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.prev = 0;\n url = \'https://missav.ws/api/actresses/1016525/view\';\n _context3.next = 4;\n return fetch(url, {\n method: \'GET\',\n credentials: \'include\' // 确保发送cookies\n });\n case 4:\n response = _context3.sent;\n if (response.ok) {\n _context3.next = 7;\n break;\n }\n return _context3.abrupt("return", null);\n case 7:\n _context3.next = 9;\n return response.json();\n case 9:\n data = _context3.sent;\n return _context3.abrupt("return", data.user !== null);\n case 13:\n _context3.prev = 13;\n _context3.t0 = _context3["catch"](0);\n return _context3.abrupt("return", null);\n case 16:\n case "end":\n return _context3.stop();\n }\n }, _callee3, null, [[0, 13]]);\n }));\n function checkLoginByAPI() {\n return _checkLoginByAPI.apply(this, arguments);\n }\n return checkLoginByAPI;\n }()\n /**\n * 使用DOM元素检测登录状态\n * @returns {boolean} 是否已登录\n */\n )\n }, {\n key: "checkLoginByDOM",\n value: function checkLoginByDOM() {\n try {\n // 检查页面上的各种可能表明登录状态的元素\n var loginButton = document.querySelector(\'button[x-on\\\\:click="currentPage = \\\'login\\\'"]\');\n var userAvatar = document.querySelector(\'.relative.ml-3 img.h-8.w-8.rounded-full\');\n var userMenu = document.querySelector(\'[x-data="{userDropdownOpen: false}"]\');\n\n // 如果没有登录按钮或有用户相关元素,说明可能已登录\n return !loginButton || userAvatar || userMenu;\n } catch (error) {\n return false;\n }\n }\n\n /**\n * 添加自动登录选项到登录表单\n * @param {Function} onLoginInfoChange - 登录信息变更回调\n * @returns {Promise<void>}\n */\n }, {\n key: "addAutoLoginOption",\n value: (function () {\n var _addAutoLoginOption = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(onLoginInfoChange) {\n var loginRememberContainer, autoLoginDiv, rememberMeDiv, autoLogin, loginForm, loginButton;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.prev = 0;\n _context4.next = 3;\n return _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.waitForElement(\'form[x-show="currentPage === \\\'login\\\'"] .relative.flex.items-start.justify-between\');\n case 3:\n loginRememberContainer = _context4.sent;\n // 创建自动登录选项\n autoLoginDiv = document.createElement(\'div\');\n autoLoginDiv.className = \'flex\';\n autoLoginDiv.innerHTML = "\\n <div class=\\"flex items-center h-5\\">\\n <input id=\\"auto_login\\" type=\\"checkbox\\" class=\\"focus:ring-primary h-4 w-4 text-primary border-gray-300 rounded __text_mode_custom_bg__\\">\\n </div>\\n <div class=\\"ml-3 text-sm\\">\\n <label for=\\"auto_login\\" class=\\"font-medium text-nord4\\">".concat(_i18n_js__WEBPACK_IMPORTED_MODULE_1__.I18n.translate(\'autoLogin\'), "</label>\\n </div>\\n ");\n\n // 获取"记住我"元素\n rememberMeDiv = loginRememberContainer.querySelector(\'.flex\'); // 在记住我和忘记密码之间插入自动登录选项\n rememberMeDiv.parentNode.insertBefore(autoLoginDiv, rememberMeDiv.nextSibling);\n\n // 加载自动登录设置状态,默认为勾选状态\n autoLogin = _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.getValue(\'autoLogin\', true);\n document.getElementById(\'auto_login\').checked = autoLogin;\n\n // 监听自动登录复选框变化\n document.getElementById(\'auto_login\').addEventListener(\'change\', function () {\n var isAutoLogin = document.getElementById(\'auto_login\').checked;\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.setValue(\'autoLogin\', isAutoLogin);\n if (onLoginInfoChange) {\n onLoginInfoChange({\n autoLogin: isAutoLogin\n });\n }\n });\n\n // 监听登录表单提交\n loginForm = document.querySelector(\'form[x-show="currentPage === \\\'login\\\'"]\');\n if (loginForm) {\n // 监听登录按钮点击\n loginButton = loginForm.querySelector(\'button[type="submit"]\');\n if (loginButton) {\n loginButton.addEventListener(\'click\', function () {\n setTimeout(function () {\n var emailInput = document.getElementById(\'login_email\');\n var passwordInput = document.getElementById(\'login_password\');\n var autoLoginCheckbox = document.getElementById(\'auto_login\');\n if (emailInput && passwordInput && autoLoginCheckbox && autoLoginCheckbox.checked) {\n var email = emailInput.value;\n var password = passwordInput.value;\n\n // 保存登录信息\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.setValue(\'userEmail\', email);\n _utils_js__WEBPACK_IMPORTED_MODULE_0__.LoginUtils.setValue(\'userPassword\', password);\n if (onLoginInfoChange) {\n onLoginInfoChange({\n email: email,\n password: password,\n autoLogin: true\n });\n }\n }\n }, 100);\n });\n }\n }\n _context4.next = 18;\n break;\n case 16:\n _context4.prev = 16;\n _context4.t0 = _context4["catch"](0);\n case 18:\n case "end":\n return _context4.stop();\n }\n }, _callee4, null, [[0, 16]]);\n }));\n function addAutoLoginOption(_x3) {\n return _addAutoLoginOption.apply(this, arguments);\n }\n return addAutoLoginOption;\n }())\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/autologin/MissavLoginProvider.js?');
},
"./src/autologin/i18n.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ I18n: () => (/* binding */ I18n)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * 多语言系统 - 用于自动登录功能的国际化支持\n */\nvar I18n = /*#__PURE__*/function () {\n function I18n() {\n _classCallCheck(this, I18n);\n }\n return _createClass(I18n, null, [{\n key: \"userLang\",\n get:\n /**\n * 获取用户浏览器当前语言\n * @returns {string} 用户当前语言代码\n */\n function get() {\n return navigator.languages && navigator.languages[0] || navigator.language || 'en';\n }\n\n /**\n * 语言字符串集合\n * @type {Object}\n */\n }, {\n key: \"translate\",\n value:\n /**\n * 翻译函数 - 将ID转换为当前语言的字符串\n * @param {string} id - 要翻译的字符串ID\n * @param {string} [lang=''] - 可选的指定语言,默认使用用户语言\n * @returns {string} 翻译后的字符串\n */\n function translate(id) {\n var lang = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';\n var selectedLang = lang || this.userLang;\n return (this.strings[selectedLang] || this.strings.en)[id] || this.strings.en[id];\n }\n }]);\n}();\n_defineProperty(I18n, \"strings\", {\n 'en': {\n accountNull: 'Error: Email or password is empty.',\n loginSuccess: 'Login successful, refreshing the page.',\n networkFailed: 'Status code error.',\n loginFailed: 'Login failed, incorrect email or password. Check console for error details.',\n autoLogin: 'Auto Login'\n },\n 'zh-CN': {\n accountNull: '邮箱或密码为空',\n loginSuccess: '登录成功,即将刷新页面。',\n networkFailed: '状态码错误',\n loginFailed: '登录失败,邮箱或密码错误,可以在控制台查看错误信息。',\n autoLogin: '自动登录'\n },\n 'zh-TW': {\n accountNull: '郵箱或密碼為空',\n loginSuccess: '登錄成功,即將刷新頁面。',\n networkFailed: '狀態碼錯誤',\n loginFailed: '登錄失敗,郵箱或密碼錯誤,可以在控制台查看錯誤信息。',\n autoLogin: '自動登錄'\n },\n 'ja': {\n accountNull: 'エラー:メールアドレスまたはパスワードが空です。',\n loginSuccess: 'ログイン成功、ページを更新します。',\n networkFailed: 'ステータスコードエラー',\n loginFailed: 'ログインに失敗しました。メールアドレスまたはパスワードが間違っています。エラーの詳細はコンソールで確認できます。',\n autoLogin: '自動ログイン'\n },\n 'vi': {\n accountNull: 'Lỗi: Email hoặc mật khẩu trống.',\n loginSuccess: 'Đăng nhập thành công, đang làm mới trang.',\n networkFailed: 'Lỗi mã trạng thái.',\n loginFailed: 'Đăng nhập không thành công, email hoặc mật khẩu không chính xác. Xem chi tiết lỗi trên bảng điều khiển.',\n autoLogin: 'Đăng nhập tự động'\n }\n});\n\n//# sourceURL=webpack://miss-noad-video-player/./src/autologin/i18n.js?");
},
"./src/autologin/index.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ I18n: () => (/* reexport safe */ _i18n_js__WEBPACK_IMPORTED_MODULE_2__.I18n),\n/* harmony export */ LoginManager: () => (/* reexport safe */ _LoginManager_js__WEBPACK_IMPORTED_MODULE_0__.LoginManager),\n/* harmony export */ LoginUtils: () => (/* reexport safe */ _utils_js__WEBPACK_IMPORTED_MODULE_1__.LoginUtils),\n/* harmony export */ MissavLoginProvider: () => (/* reexport safe */ _MissavLoginProvider_js__WEBPACK_IMPORTED_MODULE_3__.MissavLoginProvider),\n/* harmony export */ initAutoLogin: () => (/* binding */ initAutoLogin)\n/* harmony export */ });\n/* harmony import */ var _LoginManager_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./LoginManager.js */ "./src/autologin/LoginManager.js");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ "./src/autologin/utils.js");\n/* harmony import */ var _i18n_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./i18n.js */ "./src/autologin/i18n.js");\n/* harmony import */ var _MissavLoginProvider_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./MissavLoginProvider.js */ "./src/autologin/MissavLoginProvider.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return r; }; var t, r = {}, e = Object.prototype, n = e.hasOwnProperty, o = "function" == typeof Symbol ? Symbol : {}, i = o.iterator || "@@iterator", a = o.asyncIterator || "@@asyncIterator", u = o.toStringTag || "@@toStringTag"; function c(t, r, e, n) { return Object.defineProperty(t, r, { value: e, enumerable: !n, configurable: !n, writable: !n }); } try { c({}, ""); } catch (t) { c = function c(t, r, e) { return t[r] = e; }; } function h(r, e, n, o) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype); return c(a, "_invoke", function (r, e, n) { var o = 1; return function (i, a) { if (3 === o) throw Error("Generator is already running"); if (4 === o) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var u = n.delegate; if (u) { var c = d(u, n); if (c) { if (c === f) continue; return c; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (1 === o) throw o = 4, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = 3; var h = s(r, e, n); if ("normal" === h.type) { if (o = n.done ? 4 : 2, h.arg === f) continue; return { value: h.arg, done: n.done }; } "throw" === h.type && (o = 4, n.method = "throw", n.arg = h.arg); } }; }(r, n, new Context(o || [])), !0), a; } function s(t, r, e) { try { return { type: "normal", arg: t.call(r, e) }; } catch (t) { return { type: "throw", arg: t }; } } r.wrap = h; var f = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var l = {}; c(l, i, function () { return this; }); var p = Object.getPrototypeOf, y = p && p(p(x([]))); y && y !== e && n.call(y, i) && (l = y); var v = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(l); function g(t) { ["next", "throw", "return"].forEach(function (r) { c(t, r, function (t) { return this._invoke(r, t); }); }); } function AsyncIterator(t, r) { function e(o, i, a, u) { var c = s(t[o], t, i); if ("throw" !== c.type) { var h = c.arg, f = h.value; return f && "object" == _typeof(f) && n.call(f, "__await") ? r.resolve(f.__await).then(function (t) { e("next", t, a, u); }, function (t) { e("throw", t, a, u); }) : r.resolve(f).then(function (t) { h.value = t, a(h); }, function (t) { return e("throw", t, a, u); }); } u(c.arg); } var o; c(this, "_invoke", function (t, n) { function i() { return new r(function (r, o) { e(t, n, r, o); }); } return o = o ? o.then(i, i) : i(); }, !0); } function d(r, e) { var n = e.method, o = r.i[n]; if (o === t) return e.delegate = null, "throw" === n && r.i["return"] && (e.method = "return", e.arg = t, d(r, e), "throw" === e.method) || "return" !== n && (e.method = "throw", e.arg = new TypeError("The iterator does not provide a \'" + n + "\' method")), f; var i = s(o, r.i, e.arg); if ("throw" === i.type) return e.method = "throw", e.arg = i.arg, e.delegate = null, f; var a = i.arg; return a ? a.done ? (e[r.r] = a.value, e.next = r.n, "return" !== e.method && (e.method = "next", e.arg = t), e.delegate = null, f) : a : (e.method = "throw", e.arg = new TypeError("iterator result is not an object"), e.delegate = null, f); } function w(t) { this.tryEntries.push(t); } function m(r) { var e = r[4] || {}; e.type = "normal", e.arg = t, r[4] = e; } function Context(t) { this.tryEntries = [[-1]], t.forEach(w, this), this.reset(!0); } function x(r) { if (null != r) { var e = r[i]; if (e) return e.call(r); if ("function" == typeof r.next) return r; if (!isNaN(r.length)) { var o = -1, a = function e() { for (; ++o < r.length;) if (n.call(r, o)) return e.value = r[o], e.done = !1, e; return e.value = t, e.done = !0, e; }; return a.next = a; } } throw new TypeError(_typeof(r) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, c(v, "constructor", GeneratorFunctionPrototype), c(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = c(GeneratorFunctionPrototype, u, "GeneratorFunction"), r.isGeneratorFunction = function (t) { var r = "function" == typeof t && t.constructor; return !!r && (r === GeneratorFunction || "GeneratorFunction" === (r.displayName || r.name)); }, r.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, c(t, u, "GeneratorFunction")), t.prototype = Object.create(v), t; }, r.awrap = function (t) { return { __await: t }; }, g(AsyncIterator.prototype), c(AsyncIterator.prototype, a, function () { return this; }), r.AsyncIterator = AsyncIterator, r.async = function (t, e, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(h(t, e, n, o), i); return r.isGeneratorFunction(e) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, g(v), c(v, u, "Generator"), c(v, i, function () { return this; }), c(v, "toString", function () { return "[object Generator]"; }), r.keys = function (t) { var r = Object(t), e = []; for (var n in r) e.unshift(n); return function t() { for (; e.length;) if ((n = e.pop()) in r) return t.value = n, t.done = !1, t; return t.done = !0, t; }; }, r.values = x, Context.prototype = { constructor: Context, reset: function reset(r) { if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(m), !r) for (var e in this) "t" === e.charAt(0) && n.call(this, e) && !isNaN(+e.slice(1)) && (this[e] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0][4]; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(r) { if (this.done) throw r; var e = this; function n(t) { a.type = "throw", a.arg = r, e.next = t; } for (var o = e.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i[4], u = this.prev, c = i[1], h = i[2]; if (-1 === i[0]) return n("end"), !1; if (!c && !h) throw Error("try statement without catch or finally"); if (null != i[0] && i[0] <= u) { if (u < c) return this.method = "next", this.arg = t, n(c), !0; if (u < h) return n(h), !1; } } }, abrupt: function abrupt(t, r) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var n = this.tryEntries[e]; if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) { var o = n; break; } } o && ("break" === t || "continue" === t) && o[0] <= r && r <= o[2] && (o = null); var i = o ? o[4] : {}; return i.type = t, i.arg = r, o ? (this.method = "next", this.next = o[2], f) : this.complete(i); }, complete: function complete(t, r) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && r && (this.next = r), f; }, finish: function finish(t) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var e = this.tryEntries[r]; if (e[2] === t) return this.complete(e[4], e[3]), m(e), f; } }, "catch": function _catch(t) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var e = this.tryEntries[r]; if (e[0] === t) { var n = e[4]; if ("throw" === n.type) { var o = n.arg; m(e); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(r, e, n) { return this.delegate = { i: x(r), r: e, n: n }, "next" === this.method && (this.arg = t), f; } }, r; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }\n/**\n * 自动登录模块 - 主入口\n * 支持多个网站的自动登录功能\n */\n\n\n\n\n\n// 导出所有模块,方便其他模块使用\n\n\n/**\n * 初始化自动登录模块\n * @returns {Promise<LoginManager>} 初始化后的登录管理器实例\n */\nfunction initAutoLogin() {\n return _initAutoLogin.apply(this, arguments);\n}\nfunction _initAutoLogin() {\n _initAutoLogin = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var loginManager;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n // 创建并初始化登录管理器\n loginManager = new _LoginManager_js__WEBPACK_IMPORTED_MODULE_0__.LoginManager();\n _context.next = 4;\n return loginManager.init();\n case 4:\n return _context.abrupt("return", loginManager);\n case 7:\n _context.prev = 7;\n _context.t0 = _context["catch"](0);\n return _context.abrupt("return", null);\n case 10:\n case "end":\n return _context.stop();\n }\n }, _callee, null, [[0, 7]]);\n }));\n return _initAutoLogin.apply(this, arguments);\n}\n\n//# sourceURL=webpack://miss-noad-video-player/./src/autologin/index.js?');
},
"./src/autologin/utils.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LoginUtils: () => (/* binding */ LoginUtils)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\r\n * 工具函数集合 - 自动登录模块专用\r\n */\nvar LoginUtils = /*#__PURE__*/function () {\n function LoginUtils() {\n _classCallCheck(this, LoginUtils);\n }\n return _createClass(LoginUtils, null, [{\n key: "toast",\n value:\n /**\r\n * 显示Toast消息通知\r\n * @param {string} msg - 要显示的消息\r\n * @param {number} [duration=3000] - 显示持续时间(毫秒)\r\n * @param {string} [bgColor=\'rgba(0, 0, 0, 0.8)\'] - 背景颜色\r\n * @param {string} [textColor=\'#fff\'] - 文字颜色\r\n * @param {string} [position=\'top\'] - 位置(top/bottom/center)\r\n */\n function toast(msg) {\n var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3000;\n var bgColor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : \'rgba(0, 0, 0, 0.8)\';\n var textColor = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : \'#fff\';\n var position = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : \'top\';\n var toast = document.createElement(\'div\');\n toast.innerText = msg;\n toast.style.cssText = "\\n position: fixed;\\n z-index: 100000;\\n left: 50%;\\n transform: translateX(-50%);\\n padding: 10px 15px;\\n border-radius: 4px;\\n color: ".concat(textColor, ";\\n background: ").concat(bgColor, ";\\n font-size: 14px;\\n max-width: 80%;\\n text-align: center;\\n word-break: break-all;\\n ");\n\n // 设置位置\n if (position === \'top\') {\n toast.style.top = \'10%\';\n } else if (position === \'bottom\') {\n toast.style.bottom = \'10%\';\n } else if (position === \'center\') {\n toast.style.top = \'50%\';\n toast.style.transform = \'translate(-50%, -50%)\';\n }\n document.body.appendChild(toast);\n setTimeout(function () {\n toast.style.opacity = \'0\';\n toast.style.transition = \'opacity 0.5s\';\n setTimeout(function () {\n document.body.removeChild(toast);\n }, 500);\n }, duration);\n }\n\n /**\r\n * 节流函数 - 限制函数执行频率\r\n * @param {Function} fn - 要执行的函数\r\n * @param {number} delay - 延迟时间(ms)\r\n * @returns {Function} - 节流后的函数\r\n */\n }, {\n key: "throttle",\n value: function throttle(fn, delay) {\n var lastCall = 0;\n return function () {\n var now = Date.now();\n if (now - lastCall >= delay) {\n lastCall = now;\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return fn.apply(this, args);\n }\n };\n }\n\n /**\r\n * 等待DOM元素出现\r\n * @param {string} selector - CSS选择器\r\n * @param {number} [timeout=10000] - 超时时间(ms)\r\n * @param {number} [interval=100] - 检查间隔(ms)\r\n * @returns {Promise<Element>} - 返回找到的元素\r\n */\n }, {\n key: "waitForElement",\n value: function waitForElement(selector) {\n var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10000;\n var interval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 100;\n return new Promise(function (resolve, reject) {\n var element = document.querySelector(selector);\n if (element) {\n return resolve(element);\n }\n var start = Date.now();\n var intervalId = setInterval(function () {\n var element = document.querySelector(selector);\n if (element) {\n clearInterval(intervalId);\n return resolve(element);\n }\n if (Date.now() - start > timeout) {\n clearInterval(intervalId);\n reject(new Error("\\u7B49\\u5F85\\u5143\\u7D20 ".concat(selector, " \\u8D85\\u65F6")));\n }\n }, interval);\n });\n }\n\n /**\r\n * 获取本地存储的数据\r\n * @param {string} key - 存储键名\r\n * @param {*} defaultValue - 默认值\r\n * @returns {*} - 存储的值或默认值\r\n */\n }, {\n key: "getValue",\n value: function getValue(key, defaultValue) {\n try {\n // 优先使用localStorage\n var value = localStorage.getItem("autologin_".concat(key));\n if (value !== null) {\n try {\n return JSON.parse(value);\n } catch (e) {\n return value;\n }\n }\n return defaultValue;\n } catch (e) {\n return defaultValue;\n }\n }\n\n /**\r\n * 设置本地存储数据\r\n * @param {string} key - 存储键名\r\n * @param {*} value - 要存储的值\r\n */\n }, {\n key: "setValue",\n value: function setValue(key, value) {\n try {\n var storageValue = _typeof(value) === \'object\' ? JSON.stringify(value) : value;\n localStorage.setItem("autologin_".concat(key), storageValue);\n } catch (e) {}\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/autologin/utils.js?');
},
"./src/constants/i18n.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ I18n: () => (/* binding */ I18n),\n/* harmony export */ __: () => (/* binding */ __)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * 多语言系统 - 用于整个脚本的国际化支持\n */\nvar I18n = /*#__PURE__*/function () {\n function I18n() {\n _classCallCheck(this, I18n);\n }\n return _createClass(I18n, null, [{\n key: \"userLang\",\n get:\n /**\n * 获取用户浏览器当前语言\n * @returns {string} 用户当前语言代码\n */\n function get() {\n return navigator.languages && navigator.languages[0] || navigator.language || 'en';\n }\n\n /**\n * 语言字符串集合 - 包含所有脚本使用的文本\n * @type {Object}\n */\n }, {\n key: \"translate\",\n value:\n /**\n * 翻译函数 - 将ID转换为当前语言的字符串\n * @param {string} id - 要翻译的字符串ID\n * @param {string} [lang=''] - 可选的指定语言,默认使用用户语言\n * @returns {string} 翻译后的字符串\n */\n function translate(id) {\n var lang = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';\n var selectedLang = lang || this.userLang;\n // 首先尝试精确匹配语言代码,然后尝试匹配语言前缀,最后使用英语作为后备\n var langObj = this.strings[selectedLang] || this.strings[selectedLang.split('-')[0]] || this.strings.en;\n return langObj[id] || this.strings.en[id];\n }\n }]);\n}();\n\n/**\n * 简便的翻译函数,可直接在代码中使用\n * @param {string} id - 要翻译的字符串ID\n * @param {string} [lang=''] - 可选的指定语言,默认使用用户语言\n * @returns {string} 翻译后的字符串\n */\n_defineProperty(I18n, \"strings\", {\n 'en': {\n // 元数据\n scriptName: 'Miss Player | Cinema Mode (One-handed Player)',\n scriptDescription: 'MissAV ad-free|One-handed mode|MissAV auto-expand details|MissAV auto high quality|MissAV redirect support|MissAV auto login|Custom player supporting jable po*nhub etc',\n // 控制台日志信息\n viewportConfigured: 'Viewport configured to support safe area',\n stylesInjected: 'Styles injected',\n enhancerInitialized: 'User experience enhancer module initialized',\n loginModuleInitialized: 'Auto login module initialized',\n initializationComplete: 'Initialization complete',\n initializationFailed: 'Initialization failed',\n // 界面文本\n play: 'Play',\n pause: 'Pause',\n mute: 'Mute',\n unmute: 'Unmute',\n fullscreen: 'Fullscreen',\n exitFullscreen: 'Exit Fullscreen',\n settings: 'Settings',\n quality: 'Quality',\n speed: 'Speed',\n // 设置选项\n autoplay: 'Auto Play',\n loop: 'Loop',\n autoQuality: 'Auto Quality',\n // 消息提示\n loadingError: 'Failed to load video',\n networkError: 'Network error',\n loginSuccess: 'Login successful',\n loginFailed: 'Login failed'\n },\n 'zh-CN': {\n // 元数据\n scriptName: 'Miss Player | 影院模式 (单手播放器)',\n scriptDescription: 'MissAV去广告|单手模式|MissAV自动展开详情|MissAV自动高画质|MissAV重定向支持|MissAV自动登录|定制播放器 支持 jable po*nhub 等通用',\n // 控制台日志信息\n viewportConfigured: '已配置viewport以支持安全区域',\n stylesInjected: '样式注入完成',\n enhancerInitialized: '用户体验增强模块已初始化',\n loginModuleInitialized: '自动登录模块已初始化',\n initializationComplete: '初始化完成',\n initializationFailed: '初始化失败',\n // 界面文本\n play: '播放',\n pause: '暂停',\n mute: '静音',\n unmute: '取消静音',\n fullscreen: '全屏',\n exitFullscreen: '退出全屏',\n settings: '设置',\n quality: '画质',\n speed: '速度',\n // 设置选项\n autoplay: '自动播放',\n loop: '循环播放',\n autoQuality: '自动画质',\n // 消息提示\n loadingError: '视频加载失败',\n networkError: '网络错误',\n loginSuccess: '登录成功',\n loginFailed: '登录失败'\n },\n 'zh-TW': {\n // 元数据\n scriptName: 'Miss Player | 影院模式 (單手播放器)',\n scriptDescription: 'MissAV去廣告|單手模式|MissAV自動展開詳情|MissAV自動高畫質|MissAV重定向支持|MissAV自動登錄|定制播放器 支持 jable po*nhub 等通用',\n // 控制台日志信息\n viewportConfigured: '已配置viewport以支持安全區域',\n stylesInjected: '樣式注入完成',\n enhancerInitialized: '用戶體驗增強模塊已初始化',\n loginModuleInitialized: '自動登錄模塊已初始化',\n initializationComplete: '初始化完成',\n initializationFailed: '初始化失敗',\n // 界面文本\n play: '播放',\n pause: '暫停',\n mute: '靜音',\n unmute: '取消靜音',\n fullscreen: '全屏',\n exitFullscreen: '退出全屏',\n settings: '設置',\n quality: '畫質',\n speed: '速度',\n // 设置选项\n autoplay: '自動播放',\n loop: '循環播放',\n autoQuality: '自動畫質',\n // 消息提示\n loadingError: '視頻加載失敗',\n networkError: '網絡錯誤',\n loginSuccess: '登錄成功',\n loginFailed: '登錄失敗'\n },\n 'ja': {\n // 元数据\n scriptName: 'Miss Player | シネマモード (片手プレーヤー)',\n scriptDescription: 'MissAV広告なし|片手モード|MissAV自動詳細展開|MissAV自動高画質|MissAVリダイレクトサポート|MissAV自動ログイン|jable po*nhub などをサポートするカスタムプレーヤー',\n // 控制台日志信息\n viewportConfigured: 'セーフエリアをサポートするためにビューポートを設定しました',\n stylesInjected: 'スタイルが注入されました',\n enhancerInitialized: 'ユーザー体験向上モジュールが初期化されました',\n loginModuleInitialized: '自動ログインモジュールが初期化されました',\n initializationComplete: '初期化が完了しました',\n initializationFailed: '初期化に失敗しました',\n // 界面文本\n play: '再生',\n pause: '一時停止',\n mute: 'ミュート',\n unmute: 'ミュート解除',\n fullscreen: '全画面',\n exitFullscreen: '全画面解除',\n settings: '設定',\n quality: '画質',\n speed: '速度',\n // 设置选项\n autoplay: '自動再生',\n loop: 'ループ再生',\n autoQuality: '自動画質',\n // 消息提示\n loadingError: '動画の読み込みに失敗しました',\n networkError: 'ネットワークエラー',\n loginSuccess: 'ログイン成功',\n loginFailed: 'ログイン失敗'\n },\n 'vi': {\n // 元数据\n scriptName: 'Miss Player | Chế độ Rạp chiếu phim (Trình phát một tay)',\n scriptDescription: 'MissAV không quảng cáo|Chế độ một tay|MissAV tự động mở rộng chi tiết|MissAV tự động chất lượng cao|Hỗ trợ chuyển hướng MissAV|Đăng nhập tự động MissAV|Trình phát tùy chỉnh hỗ trợ jable po*nhub v.v.',\n // 控制台日志信息\n viewportConfigured: 'Đã cấu hình viewport để hỗ trợ vùng an toàn',\n stylesInjected: 'Đã tiêm CSS',\n enhancerInitialized: 'Đã khởi tạo mô-đun nâng cao trải nghiệm người dùng',\n loginModuleInitialized: 'Đã khởi tạo mô-đun đăng nhập tự động',\n initializationComplete: 'Khởi tạo hoàn tất',\n initializationFailed: 'Khởi tạo thất bại',\n // 界面文本\n play: 'Phát',\n pause: 'Tạm dừng',\n mute: 'Tắt tiếng',\n unmute: 'Bật tiếng',\n fullscreen: 'Toàn màn hình',\n exitFullscreen: 'Thoát toàn màn hình',\n settings: 'Cài đặt',\n quality: 'Chất lượng',\n speed: 'Tốc độ',\n // 设置选项\n autoplay: 'Tự động phát',\n loop: 'Lặp lại',\n autoQuality: 'Chất lượng tự động',\n // 消息提示\n loadingError: 'Không thể tải video',\n networkError: 'Lỗi mạng',\n loginSuccess: 'Đăng nhập thành công',\n loginFailed: 'Đăng nhập thất bại'\n }\n});\nfunction __(id) {\n var lang = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';\n return I18n.translate(id, lang);\n}\n\n//# sourceURL=webpack://miss-noad-video-player/./src/constants/i18n.js?");
},
"./src/constants/index.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ initCSSVariables: () => (/* binding */ initCSSVariables)\n/* harmony export */ });\n/**\n * 加载CSS样式\n */\nfunction initCSSVariables() {\n // 直接导入 CSS 文件,webpack 会通过 style-loader 处理\n __webpack_require__(/*! ../player/ui/style.css */ "./src/player/ui/style.css");\n}\n\n//# sourceURL=webpack://miss-noad-video-player/./src/constants/index.js?');
},
"./src/index.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ I18n: () => (/* reexport safe */ _constants_i18n_js__WEBPACK_IMPORTED_MODULE_7__.I18n),\n/* harmony export */ ModularVideoPlayer: () => (/* reexport safe */ _player_index_js__WEBPACK_IMPORTED_MODULE_8__.CustomVideoPlayer),\n/* harmony export */ UserExperienceEnhancer: () => (/* reexport safe */ _userExperienceEnhancer__WEBPACK_IMPORTED_MODULE_6__.UserExperienceEnhancer),\n/* harmony export */ Utils: () => (/* reexport safe */ _utils_utils_js__WEBPACK_IMPORTED_MODULE_3__.Utils),\n/* harmony export */ VideoSwipeManager: () => (/* reexport safe */ _player_managers_videoSwipeManager_js__WEBPACK_IMPORTED_MODULE_9__.VideoSwipeManager),\n/* harmony export */ __: () => (/* reexport safe */ _constants_i18n_js__WEBPACK_IMPORTED_MODULE_7__.__),\n/* harmony export */ "default": () => (/* reexport safe */ _player_index_js__WEBPACK_IMPORTED_MODULE_8__.CustomVideoPlayer)\n/* harmony export */ });\n/* harmony import */ var _constants_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants/index.js */ "./src/constants/index.js");\n/* harmony import */ var _player_ui_FloatingButton_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./player/ui/FloatingButton.js */ "./src/player/ui/FloatingButton.js");\n/* harmony import */ var _player_state_PlayerState_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./player/state/PlayerState.js */ "./src/player/state/PlayerState.js");\n/* harmony import */ var _utils_utils_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./utils/utils.js */ "./src/utils/utils.js");\n/* harmony import */ var _autologin_index_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./autologin/index.js */ "./src/autologin/index.js");\n/* harmony import */ var _adblock__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./adblock */ "./src/adblock/index.js");\n/* harmony import */ var _userExperienceEnhancer__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./userExperienceEnhancer */ "./src/userExperienceEnhancer/index.js");\n/* harmony import */ var _constants_i18n_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./constants/i18n.js */ "./src/constants/i18n.js");\n/* harmony import */ var _player_index_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./player/index.js */ "./src/player/index.js");\n/* harmony import */ var _player_managers_videoSwipeManager_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./player/managers/videoSwipeManager.js */ "./src/player/managers/videoSwipeManager.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return r; }; var t, r = {}, e = Object.prototype, n = e.hasOwnProperty, o = "function" == typeof Symbol ? Symbol : {}, i = o.iterator || "@@iterator", a = o.asyncIterator || "@@asyncIterator", u = o.toStringTag || "@@toStringTag"; function c(t, r, e, n) { return Object.defineProperty(t, r, { value: e, enumerable: !n, configurable: !n, writable: !n }); } try { c({}, ""); } catch (t) { c = function c(t, r, e) { return t[r] = e; }; } function h(r, e, n, o) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype); return c(a, "_invoke", function (r, e, n) { var o = 1; return function (i, a) { if (3 === o) throw Error("Generator is already running"); if (4 === o) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var u = n.delegate; if (u) { var c = d(u, n); if (c) { if (c === f) continue; return c; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (1 === o) throw o = 4, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = 3; var h = s(r, e, n); if ("normal" === h.type) { if (o = n.done ? 4 : 2, h.arg === f) continue; return { value: h.arg, done: n.done }; } "throw" === h.type && (o = 4, n.method = "throw", n.arg = h.arg); } }; }(r, n, new Context(o || [])), !0), a; } function s(t, r, e) { try { return { type: "normal", arg: t.call(r, e) }; } catch (t) { return { type: "throw", arg: t }; } } r.wrap = h; var f = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var l = {}; c(l, i, function () { return this; }); var p = Object.getPrototypeOf, y = p && p(p(x([]))); y && y !== e && n.call(y, i) && (l = y); var v = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(l); function g(t) { ["next", "throw", "return"].forEach(function (r) { c(t, r, function (t) { return this._invoke(r, t); }); }); } function AsyncIterator(t, r) { function e(o, i, a, u) { var c = s(t[o], t, i); if ("throw" !== c.type) { var h = c.arg, f = h.value; return f && "object" == _typeof(f) && n.call(f, "__await") ? r.resolve(f.__await).then(function (t) { e("next", t, a, u); }, function (t) { e("throw", t, a, u); }) : r.resolve(f).then(function (t) { h.value = t, a(h); }, function (t) { return e("throw", t, a, u); }); } u(c.arg); } var o; c(this, "_invoke", function (t, n) { function i() { return new r(function (r, o) { e(t, n, r, o); }); } return o = o ? o.then(i, i) : i(); }, !0); } function d(r, e) { var n = e.method, o = r.i[n]; if (o === t) return e.delegate = null, "throw" === n && r.i["return"] && (e.method = "return", e.arg = t, d(r, e), "throw" === e.method) || "return" !== n && (e.method = "throw", e.arg = new TypeError("The iterator does not provide a \'" + n + "\' method")), f; var i = s(o, r.i, e.arg); if ("throw" === i.type) return e.method = "throw", e.arg = i.arg, e.delegate = null, f; var a = i.arg; return a ? a.done ? (e[r.r] = a.value, e.next = r.n, "return" !== e.method && (e.method = "next", e.arg = t), e.delegate = null, f) : a : (e.method = "throw", e.arg = new TypeError("iterator result is not an object"), e.delegate = null, f); } function w(t) { this.tryEntries.push(t); } function m(r) { var e = r[4] || {}; e.type = "normal", e.arg = t, r[4] = e; } function Context(t) { this.tryEntries = [[-1]], t.forEach(w, this), this.reset(!0); } function x(r) { if (null != r) { var e = r[i]; if (e) return e.call(r); if ("function" == typeof r.next) return r; if (!isNaN(r.length)) { var o = -1, a = function e() { for (; ++o < r.length;) if (n.call(r, o)) return e.value = r[o], e.done = !1, e; return e.value = t, e.done = !0, e; }; return a.next = a; } } throw new TypeError(_typeof(r) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, c(v, "constructor", GeneratorFunctionPrototype), c(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = c(GeneratorFunctionPrototype, u, "GeneratorFunction"), r.isGeneratorFunction = function (t) { var r = "function" == typeof t && t.constructor; return !!r && (r === GeneratorFunction || "GeneratorFunction" === (r.displayName || r.name)); }, r.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, c(t, u, "GeneratorFunction")), t.prototype = Object.create(v), t; }, r.awrap = function (t) { return { __await: t }; }, g(AsyncIterator.prototype), c(AsyncIterator.prototype, a, function () { return this; }), r.AsyncIterator = AsyncIterator, r.async = function (t, e, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(h(t, e, n, o), i); return r.isGeneratorFunction(e) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, g(v), c(v, u, "Generator"), c(v, i, function () { return this; }), c(v, "toString", function () { return "[object Generator]"; }), r.keys = function (t) { var r = Object(t), e = []; for (var n in r) e.unshift(n); return function t() { for (; e.length;) if ((n = e.pop()) in r) return t.value = n, t.done = !1, t; return t.done = !0, t; }; }, r.values = x, Context.prototype = { constructor: Context, reset: function reset(r) { if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(m), !r) for (var e in this) "t" === e.charAt(0) && n.call(this, e) && !isNaN(+e.slice(1)) && (this[e] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0][4]; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(r) { if (this.done) throw r; var e = this; function n(t) { a.type = "throw", a.arg = r, e.next = t; } for (var o = e.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i[4], u = this.prev, c = i[1], h = i[2]; if (-1 === i[0]) return n("end"), !1; if (!c && !h) throw Error("try statement without catch or finally"); if (null != i[0] && i[0] <= u) { if (u < c) return this.method = "next", this.arg = t, n(c), !0; if (u < h) return n(h), !1; } } }, abrupt: function abrupt(t, r) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var n = this.tryEntries[e]; if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) { var o = n; break; } } o && ("break" === t || "continue" === t) && o[0] <= r && r <= o[2] && (o = null); var i = o ? o[4] : {}; return i.type = t, i.arg = r, o ? (this.method = "next", this.next = o[2], f) : this.complete(i); }, complete: function complete(t, r) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && r && (this.next = r), f; }, finish: function finish(t) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var e = this.tryEntries[r]; if (e[2] === t) return this.complete(e[4], e[3]), m(e), f; } }, "catch": function _catch(t) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var e = this.tryEntries[r]; if (e[0] === t) { var n = e[4]; if ("throw" === n.type) { var o = n.arg; m(e); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(r, e, n) { return this.delegate = { i: x(r), r: e, n: n }, "next" === this.method && (this.arg = t), f; } }, r; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }\n\n\n\n\n\n\n\n\n\n// 确保最早执行URL重定向检查\n_userExperienceEnhancer__WEBPACK_IMPORTED_MODULE_6__.earlyUrlRedirector.checkAndRedirect();\n\n/**\n * 配置viewport以支持iOS安全区域\n */\nfunction setupViewport() {\n var viewportMeta = document.querySelector(\'meta[name="viewport"]\');\n\n // 如果页面中没有viewport meta标签,则创建一个\n if (!viewportMeta) {\n viewportMeta = document.createElement(\'meta\');\n viewportMeta.name = \'viewport\';\n document.head.appendChild(viewportMeta);\n }\n\n // 更新viewport内容,添加viewport-fit=cover以支持安全区域\n viewportMeta.content = \'width=device-width, initial-scale=1.0, viewport-fit=cover\';\n}\n\n/**\n * 脚本入口函数\n */\n(function () {\n \'use strict\';\n\n // 全局状态管理和播放器实例\n var playerState = null;\n var videoPlayerInstance = null;\n\n /**\n * 注入CSS样式\n */\n function injectStyles() {\n // 确保样式只注入一次\n if (document.getElementById(\'tm-player-styles\')) return;\n\n // 配置viewport以支持安全区域\n setupViewport();\n\n // 注入CSS变量和样式\n (0,_constants_index_js__WEBPACK_IMPORTED_MODULE_0__.initCSSVariables)();\n\n // 控制台日志 - 便于调试\n }\n\n /**\n * 启动脚本\n */\n function startScript() {\n return _startScript.apply(this, arguments);\n } // 确保在 document idle 时执行\n function _startScript() {\n _startScript = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var userExperienceEnhancer, floatingButton, loginManager, adBlocker;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n // 首先注入样式\n injectStyles();\n\n // 初始化用户体验增强模块(包含URL重定向功能)\n // 传递true以跳过重定向检查,因为已经在前面执行过了\n userExperienceEnhancer = (0,_userExperienceEnhancer__WEBPACK_IMPORTED_MODULE_6__.initUserExperienceEnhancer)(true);\n // 创建状态管理实例\n playerState = new _player_state_PlayerState_js__WEBPACK_IMPORTED_MODULE_2__.PlayerState();\n\n // 加载设置\n playerState.loadSettings();\n\n // 创建浮动按钮实例并初始化\n floatingButton = new _player_ui_FloatingButton_js__WEBPACK_IMPORTED_MODULE_1__.FloatingButton({\n playerState: playerState\n }); // 初始化浮动按钮\n floatingButton.init();\n\n // 初始化自动登录模块\n _context.next = 9;\n return (0,_autologin_index_js__WEBPACK_IMPORTED_MODULE_4__.initAutoLogin)();\n case 9:\n loginManager = _context.sent;\n if (loginManager) {}\n\n // 初始化广告屏蔽模块\n adBlocker = new _adblock__WEBPACK_IMPORTED_MODULE_5__["default"]();\n adBlocker.init();\n\n // 控制台日志 - 便于调试\n _context.next = 17;\n break;\n case 15:\n _context.prev = 15;\n _context.t0 = _context["catch"](0);\n case 17:\n case "end":\n return _context.stop();\n }\n }, _callee, null, [[0, 15]]);\n }));\n return _startScript.apply(this, arguments);\n }\n if (document.readyState === \'complete\' || document.readyState === \'interactive\') {\n setTimeout(startScript, 100); // 延迟100ms确保DOM完全加载\n } else {\n document.addEventListener(\'DOMContentLoaded\', function () {\n return setTimeout(startScript, 100);\n });\n }\n})();\n\n/**\n * 统一导出API,使用模块化版本\n */\n\n\n// 导出工具类和其他组件\n\n\n\n\n\n// 为兼容性考虑,同时导出为ModularVideoPlayer\n\n\n//# sourceURL=webpack://miss-noad-video-player/./src/index.js?');
},
"./src/player/CustomVideoPlayer.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CustomVideoPlayer: () => (/* binding */ CustomVideoPlayer)\n/* harmony export */ });\n/* harmony import */ var _core_PlayerCore_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core/PlayerCore.js */ "./src/player/core/PlayerCore.js");\n/* harmony import */ var _ui_UIManager_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui/UIManager.js */ "./src/player/ui/UIManager.js");\n/* harmony import */ var _managers_ControlManager_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./managers/ControlManager.js */ "./src/player/managers/ControlManager.js");\n/* harmony import */ var _managers_DragManager_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./managers/DragManager.js */ "./src/player/managers/DragManager.js");\n/* harmony import */ var _managers_LoopManager_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./managers/LoopManager.js */ "./src/player/managers/LoopManager.js");\n/* harmony import */ var _managers_ProgressManager_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./managers/ProgressManager.js */ "./src/player/managers/ProgressManager.js");\n/* harmony import */ var _managers_EventManager_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./managers/EventManager.js */ "./src/player/managers/EventManager.js");\n/* harmony import */ var _managers_SettingsManager_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./managers/SettingsManager.js */ "./src/player/managers/SettingsManager.js");\n/* harmony import */ var _managers_videoSwipeManager_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./managers/videoSwipeManager.js */ "./src/player/managers/videoSwipeManager.js");\n/* harmony import */ var _utils_utils_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../utils/utils.js */ "./src/utils/utils.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n\n\n\n\n\n\n\n\n\n\n\n/**\n * 自定义视频播放器控制器 - 模块化重构版本\n */\nvar CustomVideoPlayer = /*#__PURE__*/function () {\n function CustomVideoPlayer() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _classCallCheck(this, CustomVideoPlayer);\n // 创建核心播放器\n this.playerCore = new _core_PlayerCore_js__WEBPACK_IMPORTED_MODULE_0__.PlayerCore(options);\n\n // 保存调用按钮引用\n this.callingButton = options.callingButton || null;\n\n // 初始化管理器\n this.managers = {};\n\n // 初始状态\n this.initialized = false;\n }\n\n /**\n * 初始化播放器\n */\n return _createClass(CustomVideoPlayer, [{\n key: "init",\n value: function init() {\n var _this = this;\n if (this.initialized) return;\n\n // 如果PlayerCore不存在,重新创建\n if (!this.playerCore) {\n this.playerCore = new _core_PlayerCore_js__WEBPACK_IMPORTED_MODULE_0__.PlayerCore({\n callingButton: this.callingButton\n });\n }\n\n // 初始化核心播放器\n this.playerCore.init();\n if (!this.playerCore.targetVideo) {\n // 如果是从浮动按钮调用的,则重新显示按钮\n if (this.callingButton) {\n this.callingButton.style.display = \'flex\';\n }\n return;\n }\n\n // 创建UI管理器\n var uiManager = new _ui_UIManager_js__WEBPACK_IMPORTED_MODULE_1__.UIManager(this.playerCore);\n var uiElements = uiManager.createUI();\n this.managers.uiManager = uiManager;\n\n // 创建设置管理器\n var settingsManager = new _managers_SettingsManager_js__WEBPACK_IMPORTED_MODULE_7__.SettingsManager(this.playerCore, uiElements);\n settingsManager.init();\n this.managers.settingsManager = settingsManager;\n\n // 创建控制管理器\n var controlManager = new _managers_ControlManager_js__WEBPACK_IMPORTED_MODULE_2__.ControlManager(this.playerCore, uiElements);\n var progressControls = controlManager.createProgressControls();\n var controlButtons = controlManager.createControlButtonsContainer();\n this.managers.controlManager = controlManager;\n\n // 将控制管理器设置到playerCore上,以便UIManager可以访问到它\n this.playerCore.controlManager = controlManager;\n\n // 创建进度管理器\n var progressManager = new _managers_ProgressManager_js__WEBPACK_IMPORTED_MODULE_5__.ProgressManager(this.playerCore, uiElements);\n progressManager.init({\n progressBarElement: controlManager.progressBarElement,\n progressIndicator: controlManager.progressIndicator,\n currentTimeDisplay: controlManager.currentTimeDisplay,\n totalDurationDisplay: controlManager.totalDurationDisplay,\n timeIndicator: controlManager.timeIndicator\n });\n this.managers.progressManager = progressManager;\n\n // 创建循环管理器\n var loopManager = new _managers_LoopManager_js__WEBPACK_IMPORTED_MODULE_4__.LoopManager(this.playerCore, uiElements);\n loopManager.init({\n loopStartMarker: controlManager.loopStartMarker,\n loopEndMarker: controlManager.loopEndMarker,\n loopRangeElement: controlManager.loopRangeElement,\n currentPositionDisplay: controlManager.currentPositionDisplay,\n durationDisplay: controlManager.durationDisplay,\n loopToggleButton: controlManager.loopToggleButton\n });\n this.managers.loopManager = loopManager;\n\n // 设置循环管理器引用到控制管理器\n controlManager.setLoopManager(loopManager);\n\n // 创建拖动管理器\n var dragManager = new _managers_DragManager_js__WEBPACK_IMPORTED_MODULE_3__.DragManager(this.playerCore, uiElements);\n dragManager.init();\n this.managers.dragManager = dragManager;\n\n // 初始化VideoSwipeManager\n if (this.playerCore.targetVideo && uiElements.videoWrapper && uiElements.handle) {\n this.swipeManager = new _managers_videoSwipeManager_js__WEBPACK_IMPORTED_MODULE_8__.VideoSwipeManager(this.playerCore.targetVideo, uiElements.videoWrapper, uiElements.handle);\n this.managers.swipeManager = this.swipeManager;\n }\n\n // 创建事件管理器 - 必须在所有其他管理器之后创建\n var eventManager = new _managers_EventManager_js__WEBPACK_IMPORTED_MODULE_6__.EventManager(this.playerCore, uiElements, this.managers);\n eventManager.init();\n this.managers.eventManager = eventManager;\n\n // 组装DOM - 移到所有管理器初始化之后\n uiManager.assembleDOM();\n\n // 应用设置\n settingsManager.updateControlRowsVisibility();\n\n // 恢复视频状态\n this.playerCore.restoreVideoState();\n\n // 更新进度条\n progressManager.updateProgressBar();\n\n // 更新当前时间显示\n progressManager.updateCurrentTimeDisplay();\n\n // 为iOS设备的Safari浏览器设置统一的safe area背景色\n _utils_utils_js__WEBPACK_IMPORTED_MODULE_9__.Utils.updateSafariThemeColor(\'#000000\', true);\n\n // 立即更新视频大小和各UI元素位置\n setTimeout(function () {\n if (_this.swipeManager) {\n _this.swipeManager.updateSize();\n }\n dragManager.updateHandlePosition();\n }, 100);\n\n // 额外的延迟检查,确保URL参数相关的UI元素都被正确更新\n setTimeout(function () {\n // 强制再次更新循环点时间显示\n if (loopManager) {\n loopManager._updateUI();\n loopManager.updateLoopTimeDisplay();\n loopManager.updateLoopMarkers();\n }\n\n // 强制更新进度条和时间显示\n if (progressManager) {\n progressManager.updateProgressBar();\n progressManager.updateCurrentTimeDisplay();\n }\n }, 500);\n this.initialized = true;\n }\n\n /**\n * 关闭播放器\n */\n }, {\n key: "close",\n value: function close() {\n // 调用PlayerCore的close方法\n this.playerCore.close(this.managers.uiManager.overlay, this.managers.uiManager.container, this.managers.uiManager.playerContainer);\n\n // 清理事件监听器\n if (this.managers.eventManager) {\n this.managers.eventManager.cleanup();\n }\n\n // 清理SwipeManager\n if (this.swipeManager) {\n this.swipeManager.destroy();\n this.swipeManager = null;\n }\n\n // 清理所有管理器\n for (var key in this.managers) {\n if (this.managers[key] && typeof this.managers[key].cleanup === \'function\') {\n this.managers[key].cleanup();\n }\n this.managers[key] = null;\n }\n\n // 重置状态\n this.initialized = false;\n this.managers = {};\n this.playerCore = null;\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/CustomVideoPlayer.js?');
},
"./src/player/core/PlayerCore.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PlayerCore: () => (/* binding */ PlayerCore)\n/* harmony export */ });\n/* harmony import */ var _utils_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/utils.js */ "./src/utils/utils.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n\n\n/**\n * 播放器核心类 - 负责播放器的基本功能和状态管理\n */\nvar PlayerCore = /*#__PURE__*/function () {\n function PlayerCore() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _classCallCheck(this, PlayerCore);\n // 常量定义\n this.defaultPlaybackRate = 1.0; // 默认播放速度\n\n // 状态变量\n this.targetVideo = null; // 目标视频元素\n this.videoState = {\n currentTime: 0,\n isPlaying: false,\n volume: 1,\n playbackRate: 1\n };\n\n // 配置和选项\n this.options = Object.assign({\n containerId: \'tm-video-container\',\n startLooped: false,\n startMuted: false\n }, options);\n\n // 保存调用按钮\n this.callingButton = this.options.callingButton || null;\n\n // 状态标记\n this.initialized = false;\n }\n\n /**\n * 初始化播放器\n */\n return _createClass(PlayerCore, [{\n key: "init",\n value: function init() {\n if (this.initialized) return;\n\n // 清理可能存在的旧overlay\n this.cleanupExistingOverlays();\n\n // 查找目标视频\n this.targetVideo = this.findTargetVideo();\n if (!this.targetVideo) {\n // 如果是从浮动按钮调用的,则重新显示按钮\n if (this.callingButton) {\n this.callingButton.style.display = \'flex\';\n }\n return;\n }\n\n // 保存视频状态\n this.saveVideoState();\n\n // 初始化完成标记\n this.initialized = true;\n return this.targetVideo;\n }\n\n /**\n * 清理可能存在的旧overlay元素\n */\n }, {\n key: "cleanupExistingOverlays",\n value: function cleanupExistingOverlays() {\n // 查找所有现有的overlay元素\n var existingOverlays = document.querySelectorAll(\'.tm-video-overlay\');\n if (existingOverlays.length > 0) {\n existingOverlays.forEach(function (overlay) {\n if (overlay && overlay.parentNode) {\n overlay.parentNode.removeChild(overlay);\n }\n });\n }\n }\n\n /**\n * 查找页面中的视频元素\n * @returns {HTMLVideoElement|null} 找到的视频元素或null\n */\n }, {\n key: "findTargetVideo",\n value: function findTargetVideo() {\n var potentialVideo = null;\n\n // --- Strategy 1: Specific known selectors ---\n var specificSelectors = [\'#player video\',\n // Common ID\n \'#video video\',\n // Common ID\n \'div.plyr__video-wrapper video\',\n // Plyr\n \'.video-js video\',\n // Video.js\n \'#player > video\',\n // Direct child\n \'#video-player > video\',\n // Another common ID\n \'video[preload]:not([muted])\' // Videos likely to be main content\n ];\n for (var _i = 0, _specificSelectors = specificSelectors; _i < _specificSelectors.length; _i++) {\n var selector = _specificSelectors[_i];\n potentialVideo = document.querySelector(selector);\n if (potentialVideo) {\n return potentialVideo;\n }\n }\n\n // --- Strategy 2: Find all videos and prioritize ---\n var allVideos = Array.from(document.querySelectorAll(\'video\'));\n if (allVideos.length === 0) {\n return null;\n }\n if (allVideos.length === 1) {\n return allVideos[0];\n }\n\n // Filter out potentially hidden or invalid videos and calculate area\n var visibleVideos = allVideos.map(function (video) {\n return {\n element: video,\n rect: video.getBoundingClientRect()\n };\n }).filter(function (item) {\n return item.rect.width > 50 && item.rect.height > 50;\n }) // Basic visibility/size check\n .map(function (item) {\n return _objectSpread(_objectSpread({}, item), {}, {\n area: item.rect.width * item.rect.height\n });\n }).sort(function (a, b) {\n return b.area - a.area;\n }); // Sort by area descending\n\n if (visibleVideos.length > 0) {\n return visibleVideos[0].element;\n }\n\n // --- Strategy 3: Fallback to first video if filtering fails ---\n\n return allVideos[0];\n }\n\n /**\n * 保存视频状态\n */\n }, {\n key: "saveVideoState",\n value: function saveVideoState() {\n if (!this.targetVideo) return;\n this.originalParent = this.targetVideo.parentNode;\n this.originalIndex = Array.from(this.originalParent.children).indexOf(this.targetVideo);\n this.videoState = {\n currentTime: this.targetVideo.currentTime,\n isPaused: this.targetVideo.paused,\n videoSrc: this.targetVideo.src,\n posterSrc: this.targetVideo.poster,\n wasMuted: this.targetVideo.muted,\n controls: this.targetVideo.controls // 保存原始控制组件状态\n };\n }\n\n /**\n * 恢复视频状态\n */\n }, {\n key: "restoreVideoState",\n value: function restoreVideoState() {\n try {\n // 设置默认播放速度\n this.targetVideo.playbackRate = this.defaultPlaybackRate;\n\n // 恢复播放位置\n this.targetVideo.currentTime = this.videoState.currentTime;\n\n // 尝试播放视频\n var playPromise = this.targetVideo.play();\n if (playPromise !== undefined) {\n playPromise["catch"](function (error) {});\n }\n } catch (e) {}\n }\n\n /**\n * 关闭播放器并恢复原始视频\n */\n }, {\n key: "close",\n value: function close(overlay, container, playerContainer) {\n if (!overlay) return;\n\n // 保存当前视频状态以便下次打开\n this.videoState.currentTime = this.targetVideo.currentTime;\n this.videoState.isPlaying = !this.targetVideo.paused;\n this.videoState.volume = this.targetVideo.volume;\n this.videoState.playbackRate = this.targetVideo.playbackRate;\n\n // 如果视频正在播放,暂停它\n if (!this.targetVideo.paused) {\n this.targetVideo.pause();\n }\n\n // 恢复原始的视频样式\n if (this.originalParent && this.targetVideo && this.targetVideo.parentNode) {\n if (this.targetVideo.parentNode !== this.originalParent) {\n // 移动回原始位置\n if (this.originalIndex !== -1 && this.originalParent.childNodes.length > this.originalIndex) {\n this.originalParent.insertBefore(this.targetVideo, this.originalParent.childNodes[this.originalIndex]);\n } else {\n this.originalParent.appendChild(this.targetVideo);\n }\n\n // 移除自定义样式\n this.targetVideo.style.width = \'\';\n this.targetVideo.style.height = \'\';\n this.targetVideo.style.maxHeight = \'\';\n this.targetVideo.style.margin = \'\';\n this.targetVideo.style.position = \'\';\n }\n }\n\n // 移除叠加层\n if (overlay.parentNode) {\n overlay.parentNode.removeChild(overlay);\n }\n\n // 移除播放器容器\n if (playerContainer && playerContainer.parentNode) {\n playerContainer.parentNode.removeChild(playerContainer);\n }\n\n // 移除body上的控制状态类\n document.body.classList.remove(\'controls-hidden\');\n\n // 如果添加了全屏切换样式,移除它\n var fullscreenStyle = document.getElementById(\'tm-fullscreen-style\');\n if (fullscreenStyle) {\n fullscreenStyle.parentNode.removeChild(fullscreenStyle);\n }\n\n // 重置状态\n this.initialized = false;\n\n // 恢复Safari主题色\n _utils_utils_js__WEBPACK_IMPORTED_MODULE_0__.Utils.restoreSafariThemeColor();\n\n // 如果是从浮动按钮调用的,则重新显示按钮\n if (this.callingButton) {\n this.callingButton.style.display = \'flex\';\n }\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/core/PlayerCore.js?');
},
"./src/player/index.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CustomVideoPlayer: () => (/* reexport safe */ _CustomVideoPlayer_js__WEBPACK_IMPORTED_MODULE_0__.CustomVideoPlayer)\n/* harmony export */ });\n/* harmony import */ var _CustomVideoPlayer_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./CustomVideoPlayer.js */ "./src/player/CustomVideoPlayer.js");\n/**\n * 播放器模块入口文件\n * 导出模块化的自定义视频播放器\n */\n\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/index.js?');
},
"./src/player/managers/ControlManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ControlManager: () => (/* binding */ ControlManager)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * 控制管理器类 - 负责播放器控制按钮和相关功能\n */\nvar ControlManager = /*#__PURE__*/function () {\n function ControlManager(playerCore, uiElements) {\n _classCallCheck(this, ControlManager);\n // 核心引用\n this.playerCore = playerCore;\n this.targetVideo = playerCore.targetVideo;\n\n // UI元素引用\n this.uiElements = uiElements;\n\n // 控制按钮容器和元素\n this.controlButtonsContainer = null; // 控制按钮容器\n this.playPauseButton = null; // 播放/暂停按钮\n this.muteButton = null; // 静音按钮\n this.progressBarElement = null; // 进度条元素\n this.progressIndicator = null; // 进度指示器\n this.currentTimeDisplay = null; // 当前时间显示\n this.totalDurationDisplay = null; // 总时长显示\n this.timeIndicator = null; // 时间指示器\n this.progressControlsContainer = null; // 进度控制容器\n\n // 暂停和倍速指示器\n this.pauseIndicator = null; // 暂停指示器\n this.playbackRateIndicator = null; // 倍速指示器\n\n // 循环控制相关\n this.loopManager = null; // 循环管理器实例引用\n this.loopStartMarker = null;\n this.loopEndMarker = null;\n this.loopStartDisplay = null;\n this.loopEndDisplay = null;\n\n // 拖动状态\n this.isDraggingProgress = false; // 是否正在拖动进度条\n this.clickLock = false; // 防止快速多次点击视频区域\n this.clickLockTimeout = null; // 点击锁定计时器\n\n // 音量控制相关\n this.volumeSlider = null; // 音量滑杆元素\n this.volumeLevel = null; // 音量滑杆填充条\n this.volumeValue = null; // 音量值显示\n this.lastVolume = 1; // 记录静音前的音量\n this.supportsVolumeControl = this.checkVolumeControlSupport(); // 检查是否支持音量控制\n }\n\n /**\n * 检查浏览器是否支持音量控制\n * @returns {boolean} 是否支持音量控制\n */\n return _createClass(ControlManager, [{\n key: \"checkVolumeControlSupport\",\n value: function checkVolumeControlSupport() {\n // iOS 和 iPadOS 设备不支持 JS 控制音量\n var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;\n return !isIOS;\n }\n\n /**\n * 初始化控制管理器\n */\n }, {\n key: \"init\",\n value: function init() {\n // 创建进度条控制\n this.progressControlsContainer = this.createProgressControls();\n\n // 创建控制按钮容器\n this.controlButtonsContainer = this.createControlButtonsContainer();\n\n // 初始化事件监听器\n this.initEventListeners();\n\n // 返回创建的元素\n return {\n progressControlsContainer: this.progressControlsContainer,\n controlButtonsContainer: this.controlButtonsContainer\n };\n }\n\n /**\n * 设置循环管理器引用\n */\n }, {\n key: \"setLoopManager\",\n value: function setLoopManager(loopManager) {\n this.loopManager = loopManager;\n }\n\n /**\n * 初始化事件监听器\n */\n }, {\n key: \"initEventListeners\",\n value: function initEventListeners() {\n var _this = this;\n // 视频时间更新监听\n this.targetVideo.addEventListener('timeupdate', this.updateProgressBar.bind(this));\n this.targetVideo.addEventListener('timeupdate', this.updateCurrentTimeDisplay.bind(this));\n\n // 视频元数据加载完成监听\n this.targetVideo.addEventListener('loadedmetadata', function () {\n _this.updateProgressBar();\n _this.updateLoopTimeDisplay();\n _this.updateLoopMarkers();\n });\n\n // 进度条点击和拖动监听\n this.progressBarElement.addEventListener('click', this.handleProgressClick.bind(this));\n this.progressBarElement.addEventListener('mousedown', this.startProgressDrag.bind(this));\n this.progressBarElement.addEventListener('touchstart', this.startProgressDrag.bind(this), {\n passive: false\n });\n\n // 注释掉视频包装器点击事件,由UIManager统一处理\n // 视频包装器点击事件已移至UIManager,避免重复绑定和逻辑冲突\n\n // 监听视频播放状态变化,更新播放/暂停按钮\n this.targetVideo.addEventListener('play', function () {\n _this.updatePlayPauseButton();\n });\n this.targetVideo.addEventListener('pause', function () {\n _this.updatePlayPauseButton();\n _this.showPauseIndicator(); // 显示暂停指示器\n });\n\n // 监听视频静音状态变化\n this.targetVideo.addEventListener('volumechange', function () {\n _this.updateMuteButton();\n });\n\n // 监听视频倍速变化\n this.targetVideo.addEventListener('ratechange', function () {\n if (_this.playbackRateSlider) {\n var currentRate = _this.targetVideo.playbackRate;\n // 计算对应的百分比位置\n var percentage = (currentRate - 0.1) / (3.0 - 0.1) * 100;\n // 更新滑块位置(如果不是由滑块触发的变化)\n if (_this.updatePlaybackRateSlider) {\n _this.updatePlaybackRateSlider(percentage);\n }\n // 显示倍速指示器\n _this.showPlaybackRateIndicator(currentRate);\n }\n });\n\n // 循环功能监听\n if (this.loopManager) {\n this.targetVideo.addEventListener('timeupdate', function () {\n _this.loopManager.checkAndLoop();\n });\n }\n }\n\n /**\n * 创建进度条控制组件\n */\n }, {\n key: \"createProgressControls\",\n value: function createProgressControls() {\n var _this2 = this;\n // 创建内置进度条控制区\n this.progressControlsContainer = document.createElement('div');\n this.progressControlsContainer.className = 'tm-progress-controls';\n\n // 时间显示容器 - 现在放在进度条上方\n var timeDisplayContainer = document.createElement('div');\n timeDisplayContainer.className = 'tm-time-display-container';\n\n // 当前时间显示\n this.currentTimeDisplay = document.createElement('span');\n this.currentTimeDisplay.className = 'tm-current-time';\n this.currentTimeDisplay.textContent = '00:00:00';\n\n // 剩余时间显示\n this.totalDurationDisplay = document.createElement('span');\n this.totalDurationDisplay.className = 'tm-total-duration';\n this.totalDurationDisplay.textContent = '-00:00:00';\n\n // 进度条容器\n var progressBarContainer = document.createElement('div');\n progressBarContainer.className = 'tm-progress-bar-container';\n this.progressBarElement = document.createElement('div');\n this.progressBarElement.className = 'tm-progress-bar';\n\n // 进度指示器\n this.progressIndicator = document.createElement('div');\n this.progressIndicator.className = 'tm-progress-indicator';\n\n // 进度条和指示器的鼠标/触摸事件\n progressBarContainer.addEventListener('mouseenter', function () {\n _this2.progressBarElement.classList.add('tm-progress-bar-expanded');\n });\n progressBarContainer.addEventListener('mouseleave', function () {\n if (!_this2.isDraggingProgress) {\n _this2.progressBarElement.classList.add('tm-progress-bar-normal');\n _this2.progressBarElement.classList.remove('tm-progress-bar-expanded');\n }\n });\n\n // 添加触摸事件,处理触摸时进度条变高\n progressBarContainer.addEventListener('touchstart', function () {\n _this2.progressBarElement.classList.add('tm-progress-bar-expanded');\n _this2.progressBarElement.classList.remove('tm-progress-bar-normal');\n }, {\n passive: true\n });\n progressBarContainer.addEventListener('touchend', function () {\n if (!_this2.isDraggingProgress) {\n _this2.progressBarElement.classList.add('tm-progress-bar-normal');\n _this2.progressBarElement.classList.remove('tm-progress-bar-expanded');\n }\n });\n\n // 添加循环标记容器\n this.loopStartMarker = document.createElement('div');\n this.loopStartMarker.className = 'tm-loop-marker tm-loop-start-marker';\n this.loopStartMarker.style.display = 'none';\n this.loopEndMarker = document.createElement('div');\n this.loopEndMarker.className = 'tm-loop-marker tm-loop-end-marker';\n this.loopEndMarker.style.display = 'none';\n\n // 添加循环区间连接元素\n this.loopRangeElement = document.createElement('div');\n this.loopRangeElement.className = 'tm-loop-range';\n this.loopRangeElement.style.display = 'none';\n\n // 组装时间显示\n timeDisplayContainer.appendChild(this.currentTimeDisplay);\n timeDisplayContainer.appendChild(this.totalDurationDisplay);\n\n // 组装进度条组件\n this.progressBarElement.appendChild(this.progressIndicator);\n progressBarContainer.appendChild(this.progressBarElement);\n progressBarContainer.appendChild(this.loopStartMarker);\n progressBarContainer.appendChild(this.loopEndMarker);\n progressBarContainer.appendChild(this.loopRangeElement);\n\n // 添加到进度控制容器 - 先添加时间显示,然后是进度条\n this.progressControlsContainer.appendChild(timeDisplayContainer);\n this.progressControlsContainer.appendChild(progressBarContainer);\n return this.progressControlsContainer;\n }\n\n /**\n * 创建视频控制按钮容器\n */\n }, {\n key: \"createControlButtonsContainer\",\n value: function createControlButtonsContainer() {\n var _this3 = this;\n // 创建控制按钮容器 - 固定在页面底部\n this.controlButtonsContainer = document.createElement('div');\n this.controlButtonsContainer.className = 'tm-control-buttons';\n\n // 创建进度条行作为第一行\n var progressRow = document.createElement('div');\n progressRow.className = 'tm-progress-row';\n\n // 添加进度控制区到进度条行\n progressRow.appendChild(this.progressControlsContainer);\n\n // 添加进度条行作为第一行\n this.controlButtonsContainer.appendChild(progressRow);\n\n // 创建第一行:快退和快进按钮\n var seekControlRow = document.createElement('div');\n seekControlRow.className = 'tm-seek-control-row';\n\n // 创建第二行:时间显示和循环控制按钮\n var loopControlRow = document.createElement('div');\n loopControlRow.className = 'tm-loop-control-row';\n\n // 创建时间显示区 - 第二行左侧\n var timeDisplay = document.createElement('div');\n timeDisplay.className = 'tm-time-display';\n\n // 创建循环控制区 - 第二行右侧\n var loopControl = document.createElement('div');\n loopControl.className = 'tm-loop-control';\n\n // 创建快退按钮组 - 左侧\n var rewindGroup = document.createElement('div');\n rewindGroup.className = 'tm-rewind-group';\n\n // 创建快进按钮组 - 右侧\n var forwardGroup = document.createElement('div');\n forwardGroup.className = 'tm-forward-group';\n\n // 创建快退按钮行(响应式容器,按钮从右到左排列)\n var rewindButtonsContainer = document.createElement('div');\n rewindButtonsContainer.className = 'tm-rewind-buttons-container';\n\n // 创建快进按钮行(响应式容器,按钮从左到右排列)\n var forwardButtonsContainer = document.createElement('div');\n forwardButtonsContainer.className = 'tm-forward-buttons-container';\n\n // 将按钮容器添加到各自的组\n rewindGroup.appendChild(rewindButtonsContainer);\n forwardGroup.appendChild(forwardButtonsContainer);\n\n // 组装组到主行\n seekControlRow.appendChild(rewindGroup);\n seekControlRow.appendChild(forwardGroup);\n\n // 添加快退按钮 - 按钮将按照4,3,2,1,6,5的顺序从右到左排列\n this.addTimeControlButton(rewindButtonsContainer, '-5s', function () {\n return _this3.seekRelative(-5);\n });\n this.addTimeControlButton(rewindButtonsContainer, '-10s', function () {\n return _this3.seekRelative(-10);\n });\n this.addTimeControlButton(rewindButtonsContainer, '-30s', function () {\n return _this3.seekRelative(-30);\n });\n this.addTimeControlButton(rewindButtonsContainer, '-1m', function () {\n return _this3.seekRelative(-60);\n });\n this.addTimeControlButton(rewindButtonsContainer, '-5m', function () {\n return _this3.seekRelative(-300);\n });\n this.addTimeControlButton(rewindButtonsContainer, '-10m', function () {\n return _this3.seekRelative(-600);\n });\n\n // 添加快进按钮 - 按钮将按照1,2,3,4,5,6的顺序从左到右排列\n this.addTimeControlButton(forwardButtonsContainer, '+5s', function () {\n return _this3.seekRelative(5);\n });\n this.addTimeControlButton(forwardButtonsContainer, '+10s', function () {\n return _this3.seekRelative(10);\n });\n this.addTimeControlButton(forwardButtonsContainer, '+30s', function () {\n return _this3.seekRelative(30);\n });\n this.addTimeControlButton(forwardButtonsContainer, '+1m', function () {\n return _this3.seekRelative(60);\n });\n this.addTimeControlButton(forwardButtonsContainer, '+5m', function () {\n return _this3.seekRelative(300);\n });\n this.addTimeControlButton(forwardButtonsContainer, '+10m', function () {\n return _this3.seekRelative(600);\n });\n\n // 创建时间显示\n this.currentPositionDisplay = document.createElement('span');\n this.currentPositionDisplay.className = 'tm-loop-start-position';\n this.currentPositionDisplay.textContent = '00:00:00';\n\n // 循环开始点按钮 (A) - 改为纯文本标签\n this.setLoopStartButton = document.createElement('span');\n this.setLoopStartButton.className = 'tm-set-loop-start-label';\n this.setLoopStartButton.innerHTML = 'A';\n\n // 结束时间显示\n this.durationDisplay = document.createElement('span');\n this.durationDisplay.className = 'tm-loop-end-position';\n this.durationDisplay.textContent = '00:00:00';\n\n // 循环结束点按钮 (B) - 改为纯文本标签\n this.setLoopEndButton = document.createElement('span');\n this.setLoopEndButton.className = 'tm-set-loop-end-label';\n this.setLoopEndButton.innerHTML = 'B';\n\n // 创建开始时间容器\n var startTimeContainer = document.createElement('div');\n startTimeContainer.className = 'tm-start-time-container';\n\n // 创建结束时间容器\n var endTimeContainer = document.createElement('div');\n endTimeContainer.className = 'tm-end-time-container';\n\n // 添加开始时间容器点击事件\n startTimeContainer.addEventListener('click', function () {\n if (_this3.loopManager) {\n _this3.loopManager.setLoopStart();\n } else {}\n });\n\n // 简化悬停效果,使用CSS处理\n startTimeContainer.addEventListener('mouseover', function () {\n // CSS已处理悬停样式\n return; // 添加空语句以避免lint错误\n });\n startTimeContainer.addEventListener('mouseout', function () {\n // CSS已处理离开样式\n return; // 添加空语句以避免lint错误\n });\n\n // 添加结束时间容器点击事件\n endTimeContainer.addEventListener('click', function () {\n if (_this3.loopManager) {\n _this3.loopManager.setLoopEnd();\n } else {}\n });\n\n // 简化悬停效果,使用CSS处理\n endTimeContainer.addEventListener('mouseover', function () {\n // CSS已处理悬停样式\n return; // 添加空语句以避免lint错误\n });\n endTimeContainer.addEventListener('mouseout', function () {\n // CSS已处理离开样式\n return; // 添加空语句以避免lint错误\n });\n\n // 组装开始时间容器\n startTimeContainer.appendChild(this.setLoopStartButton);\n startTimeContainer.appendChild(this.currentPositionDisplay);\n\n // 组装结束时间容器\n endTimeContainer.appendChild(this.setLoopEndButton);\n endTimeContainer.appendChild(this.durationDisplay);\n\n // 添加循环按钮 - 直接在 loopControl 中创建\n var loopButton = document.createElement('div');\n loopButton.className = 'tm-loop-toggle-button';\n loopButton.innerHTML = \"\\n <span class=\\\"tm-loop-toggle-label\\\">Loop</span>\\n <svg width=\\\"12\\\" height=\\\"12\\\" style=\\\"vertical-align: middle;\\\">\\n <circle class=\\\"tm-loop-indicator-circle\\\" cx=\\\"6\\\" cy=\\\"6\\\" r=\\\"5\\\" fill=\\\"hsl(var(--shadcn-muted-foreground) / 0.5)\\\"></circle>\\n </svg>\\n \";\n loopControl.appendChild(loopButton);\n\n // 获取创建的按钮元素\n var loopToggleButtonElement = loopButton;\n\n // 简化悬停效果,使用CSS处理\n loopToggleButtonElement.addEventListener('mouseover', function () {\n // CSS已处理悬停样式\n return; // 添加空语句以避免lint错误\n });\n loopToggleButtonElement.addEventListener('mouseout', function () {\n // CSS已处理离开样式\n return; // 添加空语句以避免lint错误\n });\n\n // 添加点击事件\n loopToggleButtonElement.addEventListener('click', function () {\n if (_this3.loopManager) {\n _this3.loopManager.toggleLoop();\n } else {}\n });\n this.loopToggleButton = loopToggleButtonElement; // 存储按钮引用\n\n // 组装控制区域\n timeDisplay.appendChild(startTimeContainer);\n timeDisplay.appendChild(endTimeContainer);\n loopControlRow.appendChild(timeDisplay);\n loopControlRow.appendChild(loopControl);\n this.controlButtonsContainer.appendChild(seekControlRow);\n this.controlButtonsContainer.appendChild(loopControlRow);\n\n // 播放控制行:播放/暂停、静音和倍速按钮\n var playbackControlRow = document.createElement('div');\n playbackControlRow.className = 'tm-playback-control-row';\n\n // 创建左侧区域 - 放置静音按钮和音量控制\n var leftControlsArea = document.createElement('div');\n leftControlsArea.className = 'tm-left-controls';\n leftControlsArea.style.display = 'flex';\n leftControlsArea.style.alignItems = 'center';\n leftControlsArea.style.gap = '6px';\n leftControlsArea.style.flex = '1';\n\n // 创建音量控制滑杆\n this.createVolumeSlider(leftControlsArea);\n\n // 创建中间区域 - 放置播放/暂停按钮\n var centerControlsArea = document.createElement('div');\n centerControlsArea.className = 'tm-center-controls';\n centerControlsArea.style.display = 'flex';\n centerControlsArea.style.alignItems = 'center';\n centerControlsArea.style.justifyContent = 'center';\n centerControlsArea.style.flex = '1';\n\n // 创建右侧区域 - 放置速度控制\n var rightControlsArea = document.createElement('div');\n rightControlsArea.className = 'tm-right-controls';\n rightControlsArea.style.display = 'flex';\n rightControlsArea.style.alignItems = 'center';\n rightControlsArea.style.justifyContent = 'flex-end';\n rightControlsArea.style.flex = '1';\n rightControlsArea.style.gap = '6px';\n\n // 添加这些区域到控制行\n playbackControlRow.appendChild(leftControlsArea);\n playbackControlRow.appendChild(centerControlsArea);\n playbackControlRow.appendChild(rightControlsArea);\n\n // 播放/暂停按钮\n this.playPauseButton = this.addControlButton(centerControlsArea, '', function () {\n if (_this3.targetVideo.paused) {\n _this3.targetVideo.play();\n _this3.updatePlayPauseButton();\n } else {\n _this3.targetVideo.pause();\n _this3.updatePlayPauseButton();\n }\n });\n\n // 创建倍速滑块控制器\n this.createPlaybackRateSlider(rightControlsArea);\n this.controlButtonsContainer.appendChild(playbackControlRow);\n\n // 初始化按钮状态\n this.updatePlayPauseButton();\n this.updateMuteButton();\n return this.controlButtonsContainer;\n }\n\n /**\n * 创建倍速滑块控制器\n */\n }, {\n key: \"createPlaybackRateSlider\",\n value: function createPlaybackRateSlider(container) {\n var _this4 = this;\n var playbackRateSlider = document.createElement('div');\n playbackRateSlider.className = 'tm-playback-rate-slider';\n\n // 滑块相关常量定义\n var MIN_SPEED = 0.1;\n var MAX_SPEED = 3.0;\n var STEP = 0.1;\n var isDragging = false;\n var lastPercentage = 30; // 默认1.0倍速,范围0.1-3.0的30%\n var currentSpeed = 1.0;\n var rafId = null;\n\n // 滑块容器\n var sliderContainer = document.createElement('div');\n sliderContainer.className = 'tm-slider-container';\n\n // 滑块填充区域\n var sliderLevel = document.createElement('div');\n sliderLevel.className = 'tm-slider-level';\n\n // 滑块标记\n var sliderMarks = document.createElement('div');\n sliderMarks.className = 'tm-slider-marks';\n\n // 添加主要标记点 - 0.5x, 1.0x, 1.5x, 2.0x, 3.0x\n var marksPositions = [{\n pos: Math.round((0.5 - MIN_SPEED) / (MAX_SPEED - MIN_SPEED) * 100),\n label: '0.5x'\n }, {\n pos: Math.round((1.0 - MIN_SPEED) / (MAX_SPEED - MIN_SPEED) * 100),\n label: '1.0x'\n }, {\n pos: Math.round((1.5 - MIN_SPEED) / (MAX_SPEED - MIN_SPEED) * 100),\n label: '1.5x'\n }, {\n pos: Math.round((2.0 - MIN_SPEED) / (MAX_SPEED - MIN_SPEED) * 100),\n label: '2.0x'\n }, {\n pos: Math.round((3.0 - MIN_SPEED) / (MAX_SPEED - MIN_SPEED) * 100),\n label: '3.0x'\n }];\n marksPositions.forEach(function (_ref) {\n var pos = _ref.pos,\n label = _ref.label;\n var mark = document.createElement('div');\n mark.className = 'tm-slider-mark';\n mark.style.left = \"\".concat(pos, \"%\");\n sliderMarks.appendChild(mark);\n });\n\n // 滑块文本区域\n var sliderText = document.createElement('div');\n sliderText.className = 'tm-slider-text';\n\n // Speed标签\n var speedLabel = document.createElement('div');\n speedLabel.className = 'tm-speed-label';\n speedLabel.textContent = 'Speed';\n\n // 速度值显示\n var speedValue = document.createElement('div');\n speedValue.className = 'tm-speed-value';\n speedValue.textContent = '1.0x';\n\n // 组装DOM结构\n sliderText.appendChild(speedLabel);\n sliderText.appendChild(speedValue);\n sliderContainer.appendChild(sliderMarks);\n sliderContainer.appendChild(sliderLevel);\n sliderContainer.appendChild(sliderText);\n playbackRateSlider.appendChild(sliderContainer);\n\n // 将滑块添加到控制区域\n container.appendChild(playbackRateSlider);\n\n // 更新滑块函数\n var updateSlider = function updateSlider(percentage) {\n sliderLevel.style.width = \"\".concat(percentage, \"%\");\n\n // 计算速度值:从MIN_SPEED到MAX_SPEED,步长为STEP\n var speedRange = MAX_SPEED - MIN_SPEED;\n var speed = MIN_SPEED + percentage / 100 * speedRange;\n\n // 将速度值四舍五入到最近的STEP倍数\n speed = Math.round(speed / STEP) * STEP;\n\n // 确保不超出范围\n speed = Math.max(MIN_SPEED, Math.min(MAX_SPEED, speed));\n\n // 如果速度变化,更新显示\n if (speed !== currentSpeed) {\n currentSpeed = speed;\n\n // 更新视频播放速度\n _this4.targetVideo.playbackRate = speed;\n\n // 更新显示文本\n speedValue.textContent = \"\".concat(speed.toFixed(1), \"x\");\n\n // 根据速度调整颜色\n speedValue.classList.remove('tm-speed-value-fast', 'tm-speed-value-slow', 'tm-speed-value-normal');\n if (speed > 1.5) {\n speedValue.classList.add('tm-speed-value-fast');\n } else if (speed < 0.8) {\n speedValue.classList.add('tm-speed-value-slow');\n } else {\n speedValue.classList.add('tm-speed-value-normal');\n }\n }\n };\n\n // 拖动过程函数\n var drag = function drag(e) {\n if (!isDragging) return;\n handleDragEvent(e);\n };\n\n // 拖动开始函数\n var startDrag = function startDrag(e) {\n isDragging = true;\n playbackRateSlider.classList.add('dragging');\n playbackRateSlider.classList.add('tm-playback-slider-dragging');\n handleDragEvent(e);\n };\n\n // 拖动结束函数\n var endDrag = function endDrag() {\n if (!isDragging) return;\n isDragging = false;\n playbackRateSlider.classList.remove('dragging');\n playbackRateSlider.classList.remove('tm-playback-slider-dragging');\n playbackRateSlider.classList.add('tm-playback-slider-default');\n if (rafId) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n };\n\n // 处理拖动事件\n var handleDragEvent = function handleDragEvent(e) {\n e.preventDefault();\n var clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX;\n var rect = sliderContainer.getBoundingClientRect();\n var width = rect.width;\n if (rafId) {\n cancelAnimationFrame(rafId);\n }\n rafId = requestAnimationFrame(function () {\n var percentage = (clientX - rect.left) / width * 100;\n percentage = Math.max(0, Math.min(100, percentage));\n\n // 添加吸附效果 - 预设的倍速点\n var snapPoints = marksPositions.map(function (mark) {\n return mark.pos;\n });\n var snapThreshold = 5;\n var _iterator = _createForOfIteratorHelper(snapPoints),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var point = _step.value;\n if (Math.abs(percentage - point) < snapThreshold) {\n percentage = point;\n\n // 添加触觉反馈(如果设备支持)\n if (window.navigator.vibrate) {\n window.navigator.vibrate(5);\n }\n break;\n }\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n lastPercentage = percentage;\n updateSlider(percentage);\n });\n };\n\n // 添加事件监听\n sliderContainer.addEventListener('mousedown', startDrag, {\n passive: false\n });\n sliderContainer.addEventListener('touchstart', startDrag, {\n passive: false\n });\n window.addEventListener('mousemove', drag, {\n passive: false\n });\n window.addEventListener('touchmove', drag, {\n passive: false\n });\n window.addEventListener('mouseup', endDrag);\n window.addEventListener('touchend', endDrag);\n window.addEventListener('mouseleave', endDrag);\n\n // 双击重置为1.0倍速\n playbackRateSlider.addEventListener('dblclick', function () {\n lastPercentage = 30; // 30%对应1.0倍速\n updateSlider(30);\n });\n\n // 初始更新一次滑块\n updateSlider(30);\n this.playbackRateSlider = playbackRateSlider; // 保存引用\n this.updatePlaybackRateSlider = updateSlider; // 保存更新函数\n }\n\n /**\n * 创建音量控制滑杆\n * @param {HTMLElement} container 滑杆容器\n */\n }, {\n key: \"createVolumeSlider\",\n value: function createVolumeSlider(container) {\n var _this5 = this;\n // 创建音量控制容器\n var volumeControl = document.createElement('div');\n volumeControl.className = 'tm-volume-control';\n\n // 创建音量图标按钮\n var volumeButton = document.createElement('button');\n volumeButton.className = 'tm-volume-button';\n volumeButton.innerHTML = this.getVolumeIcon(this.targetVideo.volume);\n\n // 创建滑杆容器\n var sliderContainer = document.createElement('div');\n sliderContainer.className = 'tm-volume-slider-container';\n\n // 创建滑杆轨道\n var sliderTrack = document.createElement('div');\n sliderTrack.className = 'tm-volume-slider-track';\n\n // 创建滑杆填充条\n this.volumeLevel = document.createElement('div');\n this.volumeLevel.className = 'tm-volume-slider-level';\n this.volumeLevel.style.width = \"\".concat(this.targetVideo.volume * 100, \"%\");\n\n // 创建音量值显示\n this.volumeValue = document.createElement('div');\n this.volumeValue.className = 'tm-volume-value';\n this.volumeValue.textContent = \"\".concat(Math.round(this.targetVideo.volume * 100), \"%\");\n\n // 组装DOM结构\n sliderTrack.appendChild(this.volumeLevel);\n sliderContainer.appendChild(sliderTrack);\n sliderContainer.appendChild(this.volumeValue);\n volumeControl.appendChild(volumeButton);\n\n // 仅在支持音量控制的设备上显示滑杆\n if (this.supportsVolumeControl) {\n volumeControl.appendChild(sliderContainer);\n } else {\n // 在不支持音量控制的设备上添加特殊样式类\n volumeControl.classList.add('tm-volume-control-no-slider');\n }\n\n // 存储引用\n this.volumeSlider = volumeControl;\n\n // 滑杆交互相关变量\n var isDragging = false;\n var isExpanded = false;\n var expandTimeout = null;\n\n // 更新音量的函数\n var updateVolume = function updateVolume(clientX) {\n if (!_this5.supportsVolumeControl) return; // 不支持音量控制时不执行\n\n var rect = sliderTrack.getBoundingClientRect();\n var width = rect.width;\n var percentage = (clientX - rect.left) / width * 100;\n percentage = Math.max(0, Math.min(100, percentage));\n _this5.targetVideo.volume = percentage / 100;\n _this5.targetVideo.muted = false;\n _this5.updateVolumeUI();\n };\n\n // 展开滑杆函数\n var expandSlider = function expandSlider() {\n if (!_this5.supportsVolumeControl) return; // 不支持音量控制时不执行\n\n if (expandTimeout) {\n clearTimeout(expandTimeout);\n }\n volumeControl.classList.add('expanded');\n isExpanded = true;\n };\n\n // 收起滑杆函数\n var collapseSlider = function collapseSlider() {\n if (!_this5.supportsVolumeControl) return; // 不支持音量控制时不执行\n\n if (!isDragging) {\n volumeControl.classList.remove('expanded');\n isExpanded = false;\n }\n };\n\n // 音量按钮点击事件\n volumeButton.addEventListener('click', function (e) {\n e.stopPropagation();\n if (_this5.supportsVolumeControl && !isExpanded) {\n // 在支持音量控制的设备上,首次点击展开滑杆\n expandSlider();\n // 3秒后自动收起\n expandTimeout = setTimeout(collapseSlider, 3000);\n } else {\n // 如果已经展开或不支持音量控制,则切换静音状态\n if (_this5.targetVideo.volume === 0 || _this5.targetVideo.muted) {\n _this5.targetVideo.muted = false;\n if (_this5.supportsVolumeControl) {\n // 只在支持音量控制的设备上修改音量属性\n _this5.targetVideo.volume = _this5.lastVolume;\n }\n } else {\n if (_this5.supportsVolumeControl) {\n // 只在支持音量控制的设备上保存并修改音量值\n _this5.lastVolume = _this5.targetVideo.volume;\n _this5.targetVideo.volume = 0;\n } else {\n // 在iOS等设备上只使用muted属性\n _this5.targetVideo.muted = true;\n }\n }\n _this5.updateVolumeUI();\n }\n });\n\n // 仅在支持音量控制的设备上添加滑杆相关事件\n if (this.supportsVolumeControl) {\n // 滑杆点击事件\n sliderTrack.addEventListener('click', function (e) {\n e.stopPropagation();\n updateVolume(e.clientX);\n });\n\n // 滑杆触摸事件\n sliderTrack.addEventListener('touchstart', function (e) {\n e.stopPropagation();\n isDragging = true;\n volumeControl.classList.add('dragging');\n expandSlider();\n updateVolume(e.touches[0].clientX);\n }, {\n passive: false\n });\n sliderTrack.addEventListener('touchmove', function (e) {\n if (!isDragging) return;\n e.preventDefault();\n updateVolume(e.touches[0].clientX);\n }, {\n passive: false\n });\n sliderTrack.addEventListener('touchend', function () {\n isDragging = false;\n volumeControl.classList.remove('dragging');\n // 延迟收起滑杆\n setTimeout(collapseSlider, 1500);\n });\n\n // 滑杆鼠标事件\n sliderTrack.addEventListener('mousedown', function (e) {\n e.stopPropagation();\n isDragging = true;\n volumeControl.classList.add('dragging');\n expandSlider();\n updateVolume(e.clientX);\n });\n document.addEventListener('mousemove', function (e) {\n if (!isDragging) return;\n e.preventDefault();\n updateVolume(e.clientX);\n });\n document.addEventListener('mouseup', function () {\n if (isDragging) {\n isDragging = false;\n volumeControl.classList.remove('dragging');\n // 延迟收起滑杆\n setTimeout(collapseSlider, 1500);\n }\n });\n }\n\n // 添加到容器\n container.appendChild(volumeControl);\n }\n\n /**\n * 获取音量图标\n * @param {number} volume 当前音量值\n * @returns {string} 音量图标的SVG字符串\n */\n }, {\n key: \"getVolumeIcon\",\n value: function getVolumeIcon(volume) {\n // 先检查muted状态,确保静音图标在所有设备上正确显示\n if (this.targetVideo.muted || volume === 0) {\n return \"<svg width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M11 5L6 9H2V15H6L11 19V5Z\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M23 9L17 15\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M17 9L23 15\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\";\n } else if (this.supportsVolumeControl && volume < 0.5) {\n return \"<svg width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M11 5L6 9H2V15H6L11 19V5Z\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M15.54 8.46C16.4774 9.39764 17.0039 10.6692 17.0039 12C17.0039 13.3308 16.4774 14.6024 15.54 15.54\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\";\n } else {\n return \"<svg width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M11 5L6 9H2V15H6L11 19V5Z\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M15.54 8.46C16.4774 9.39764 17.0039 10.6692 17.0039 12C17.0039 13.3308 16.4774 14.6024 15.54 15.54\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M19.07 4.93C20.9447 6.80527 21.9979 9.34855 21.9979 12C21.9979 14.6515 20.9447 17.1947 19.07 19.07\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\";\n }\n }\n\n /**\n * 更新音量UI\n */\n }, {\n key: \"updateVolumeUI\",\n value: function updateVolumeUI() {\n if (!this.volumeSlider) return;\n var volume;\n if (this.supportsVolumeControl) {\n volume = this.targetVideo.muted ? 0 : this.targetVideo.volume;\n } else {\n // 在iOS设备上,只根据muted状态显示\n volume = this.targetVideo.muted ? 0 : 1;\n }\n var volumeButton = this.volumeSlider.querySelector('.tm-volume-button');\n\n // 更新音量图标\n if (volumeButton) {\n volumeButton.innerHTML = this.getVolumeIcon(volume);\n }\n\n // 如果不支持音量控制,只更新图标\n if (!this.supportsVolumeControl) return;\n\n // 更新滑杆\n if (this.volumeLevel) {\n // 确保滑杆宽度从2px开始(与CSS中的left: 2px对应)\n var levelWidth = Math.max(0, Math.min(100, volume * 100));\n this.volumeLevel.style.width = \"calc(\".concat(levelWidth, \"% - 2px)\");\n }\n\n // 更新音量值显示\n if (this.volumeValue) {\n // 显示百分比,四舍五入到整数\n var volumePercent = Math.round(volume * 100);\n this.volumeValue.textContent = \"\".concat(volumePercent, \"%\");\n\n // 根据音量值添加不同的类名\n this.volumeValue.classList.remove('volume-high', 'volume-medium', 'volume-low', 'volume-muted');\n if (volume === 0 || this.targetVideo.muted) {\n this.volumeValue.classList.add('volume-muted');\n } else if (volume < 0.3) {\n this.volumeValue.classList.add('volume-low');\n } else if (volume < 0.7) {\n this.volumeValue.classList.add('volume-medium');\n } else {\n this.volumeValue.classList.add('volume-high');\n }\n }\n }\n\n /**\n * 更新播放/暂停按钮状态\n */\n }, {\n key: \"updatePlayPauseButton\",\n value: function updatePlayPauseButton() {\n if (!this.playPauseButton) return;\n\n // 根据当前视频状态更新图标\n if (this.targetVideo.paused) {\n this.playPauseButton.innerHTML = \"\\n <svg width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M18 12L7 5V19L18 12Z\\\" fill=\\\"currentColor\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\\n \";\n } else {\n this.playPauseButton.innerHTML = \"\\n <svg width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M10 4H6V20H10V4Z\\\" fill=\\\"currentColor\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M18 4H14V20H18V4Z\\\" fill=\\\"currentColor\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\\n \";\n }\n }\n\n /**\n * 更新静音按钮状态\n */\n }, {\n key: \"updateMuteButton\",\n value: function updateMuteButton() {\n if (!this.muteButton) return;\n\n // 根据当前视频状态更新图标\n if (this.targetVideo.muted) {\n this.muteButton.innerHTML = \"\\n <svg width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M11 5L6 9H2V15H6L11 19V5Z\\\" fill=\\\"currentColor\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M23 9L17 15\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M17 9L23 15\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\\n \";\n } else {\n this.muteButton.innerHTML = \"\\n <svg width=\\\"24\\\" height=\\\"24\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M11 5L6 9H2V15H6L11 19V5Z\\\" fill=\\\"currentColor\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M15.54 8.46C16.4774 9.39764 17.004 10.6692 17.004 11.995C17.004 13.3208 16.4774 14.5924 15.54 15.53\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M18.54 5.46C20.4246 7.34535 21.4681 9.90302 21.4681 12.575C21.4681 15.247 20.4246 17.8047 18.54 19.69\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\\n \";\n }\n }\n\n /**\n * 更新进度条\n */\n }, {\n key: \"updateProgressBar\",\n value: function updateProgressBar() {\n if (!this.targetVideo || !this.progressBarElement || !this.progressIndicator) return;\n var currentTime = this.targetVideo.currentTime;\n var duration = this.targetVideo.duration;\n if (isNaN(duration) || duration <= 0) return;\n\n // 计算进度百分比\n var progressPercent = currentTime / duration * 100;\n\n // 更新进度指示器的宽度\n this.progressIndicator.style.width = \"\".concat(progressPercent, \"%\");\n\n // 更新时间显示\n this.updateCurrentTimeDisplay();\n\n // 如果启用了循环播放,检查是否需要循环\n if (this.loopManager && this.loopManager.loopActive && this.loopManager.loopStartTime !== null && this.loopManager.loopEndTime !== null) {\n if (currentTime >= this.loopManager.loopEndTime) {\n // 回到循环起点\n this.targetVideo.currentTime = this.loopManager.loopStartTime;\n }\n }\n }\n\n /**\n * 更新当前时间显示\n */\n }, {\n key: \"updateCurrentTimeDisplay\",\n value: function updateCurrentTimeDisplay() {\n if (!this.targetVideo || !this.currentTimeDisplay || !this.totalDurationDisplay) return;\n var currentTime = this.targetVideo.currentTime;\n var duration = this.targetVideo.duration;\n if (isNaN(duration)) return;\n\n // 更新当前时间显示\n this.currentTimeDisplay.textContent = this.formatTime(currentTime);\n\n // 计算并显示剩余时长,而不是总时长\n var remainingTime = duration - currentTime;\n this.totalDurationDisplay.textContent = \"-\".concat(this.formatTime(remainingTime));\n }\n\n /**\n * 添加时间控制按钮\n * @param {HTMLElement} container 按钮容器\n * @param {string} text 按钮文本\n * @param {Function} callback 点击回调函数\n * @returns {HTMLElement} 创建的按钮元素\n */\n }, {\n key: \"addTimeControlButton\",\n value: function addTimeControlButton(container, text, callback) {\n // 计算透明度:根据跳转时间计算透明度\n var calculateOpacity = function calculateOpacity(text) {\n // 提取时间值和单位\n var value = parseInt(text.replace(/[+-]/g, ''));\n var unit = text.includes('m') ? 'm' : 's';\n\n // 定义透明度区间\n var opacity = 0.5; // 默认透明度\n\n // 秒级跳转按钮透明度较低\n if (unit === 's') {\n if (value <= 5) opacity = 0.5;else if (value <= 10) opacity = 0.6;else opacity = 0.7; // 30s\n }\n // 分钟级跳转按钮透明度较高\n else if (unit === 'm') {\n if (value === 1) opacity = 0.8;else if (value === 5) opacity = 0.9;else opacity = 1.0; // 10m\n }\n return opacity;\n };\n var opacity = calculateOpacity(text);\n var button = document.createElement('button');\n button.className = 'tm-time-control-button';\n button.style.backgroundColor = \"hsl(var(--shadcn-secondary) / \".concat(opacity, \")\");\n\n // 检查文本是否包含时间指示\n var isRewind = text.includes('-');\n var isForward = text.includes('+');\n var pureText = text.replace(/[+-]/g, ''); // 移除加减号\n\n // 创建SVG图标\n var rewindSvg = \"<svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 12 24\\\" fill=\\\"none\\\" class=\\\"tm-rewind-icon\\\">\\n <path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M3.70711 4.29289C3.31658 3.90237 2.68342 3.90237 2.29289 4.29289L-4.70711 11.2929C-5.09763 11.6834 -5.09763 12.3166 -4.70711 12.7071L2.29289 19.7071C2.68342 20.0976 3.31658 20.0976 3.70711 19.7071C4.09763 19.3166 4.09763 18.6834 3.70711 18.2929L-2.58579 12L3.70711 5.70711C4.09763 5.31658 4.09763 4.68342 3.70711 4.29289Z\\\" fill=\\\"currentColor\\\"/>\\n </svg>\";\n var forwardSvg = \"<svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 12 24\\\" fill=\\\"none\\\" class=\\\"tm-forward-icon\\\">\\n <path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M8.29289 4.29289C8.68342 3.90237 9.31658 3.90237 9.70711 4.29289L16.7071 11.2929C17.0976 11.6834 17.0976 12.3166 16.7071 12.7071L9.70711 19.7071C9.31658 20.0976 8.68342 20.0976 8.29289 19.7071C7.90237 19.3166 7.90237 18.6834 8.29289 18.2929L14.5858 12L8.29289 5.70711C7.90237 5.31658 7.90237 4.68342 8.29289 4.29289Z\\\" fill=\\\"currentColor\\\"/>\\n </svg>\";\n\n // 设置按钮内容\n if (isRewind) {\n button.innerHTML = \"<div class=\\\"tm-time-control-button-inner\\\">\".concat(rewindSvg, \"<span class=\\\"tm-time-text-margin-left\\\">\").concat(pureText, \"</span></div>\");\n } else if (isForward) {\n button.innerHTML = \"<div class=\\\"tm-time-control-button-inner\\\"><span class=\\\"tm-time-text-margin-right\\\">\".concat(pureText, \"</span>\").concat(forwardSvg, \"</div>\");\n } else {\n button.textContent = text;\n }\n button.addEventListener('click', callback);\n\n // 添加悬停效果\n button.addEventListener('mouseover', function () {\n button.classList.add('tm-time-control-button-hover');\n button.classList.remove('tm-time-control-button-default');\n });\n button.addEventListener('mouseout', function () {\n button.classList.add('tm-time-control-button-default');\n button.classList.remove('tm-time-control-button-hover', 'tm-time-control-button-active', 'tm-time-control-button-after-active');\n });\n\n // 点击效果\n button.addEventListener('mousedown', function () {\n button.classList.add('tm-time-control-button-active');\n button.classList.remove('tm-time-control-button-hover', 'tm-time-control-button-default', 'tm-time-control-button-after-active');\n });\n button.addEventListener('mouseup', function () {\n button.classList.add('tm-time-control-button-after-active');\n button.classList.remove('tm-time-control-button-active', 'tm-time-control-button-hover', 'tm-time-control-button-default');\n });\n container.appendChild(button);\n return button;\n }\n\n /**\n * 相对时间跳转\n * @param {number} seconds 跳转的秒数,正数表示向前,负数表示向后\n */\n }, {\n key: \"seekRelative\",\n value: function seekRelative(seconds) {\n if (!this.targetVideo) return;\n var newTime = Math.max(0, Math.min(this.targetVideo.duration, this.targetVideo.currentTime + seconds));\n this.targetVideo.currentTime = newTime;\n }\n\n /**\n * 格式化时间\n */\n }, {\n key: \"formatTime\",\n value: function formatTime(seconds) {\n var hours = Math.floor(seconds / 3600);\n var minutes = Math.floor(seconds % 3600 / 60);\n var remainingSeconds = Math.floor(seconds % 60);\n return \"\".concat(hours, \":\").concat(minutes.toString().padStart(2, '0'), \":\").concat(remainingSeconds.toString().padStart(2, '0'));\n }\n\n /**\n * 添加控制按钮\n * @param {HTMLElement} container 按钮容器\n * @param {string} text 按钮文本\n * @param {Function} callback 点击回调函数\n * @returns {HTMLElement} 创建的按钮元素\n */\n }, {\n key: \"addControlButton\",\n value: function addControlButton(container, text, callback) {\n var button = document.createElement('button');\n button.className = 'tm-control-button';\n button.textContent = text;\n button.addEventListener('click', callback);\n\n // 添加悬停效果\n button.addEventListener('mouseover', function () {\n button.classList.add('tm-control-button-hover');\n button.classList.remove('tm-control-button-default');\n });\n button.addEventListener('mouseout', function () {\n button.classList.add('tm-control-button-default');\n button.classList.remove('tm-control-button-hover');\n });\n container.appendChild(button);\n return button;\n }\n\n /**\n * 显示暂停指示器\n */\n }, {\n key: \"showPauseIndicator\",\n value: function showPauseIndicator() {\n var _this6 = this;\n // 如果指示器已存在,则移除它\n if (this.pauseIndicator) {\n if (this.pauseIndicator.parentNode) {\n this.pauseIndicator.parentNode.removeChild(this.pauseIndicator);\n }\n this.pauseIndicator = null;\n }\n\n // 创建暂停指示器元素\n this.pauseIndicator = document.createElement('div');\n this.pauseIndicator.className = 'tm-indicator-base tm-pause-indicator';\n\n // 设置样式定位到视频中心\n this.pauseIndicator.style.position = 'absolute';\n this.pauseIndicator.style.top = '50%';\n this.pauseIndicator.style.left = '50%';\n this.pauseIndicator.style.transform = 'translate(-50%, -50%)';\n this.pauseIndicator.style.display = 'flex';\n this.pauseIndicator.style.justifyContent = 'center';\n this.pauseIndicator.style.alignItems = 'center';\n\n // 添加暂停图标\n this.pauseIndicator.innerHTML = \"\\n <svg width=\\\"32\\\" height=\\\"32\\\" viewBox=\\\"0 0 32 32\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M14,6v20c0,1.1-0.9,2-2,2H8c-1.1,0-2-0.9-2-2V6c0-1.1,0.9-2,2-2h4C13.1,4,14,4.9,14,6z M24,4h-4\\n c-1.1,0-2,0.9-2,2v20c0,1.1,0.9,2,2,2h4c1.1,0,2-0.9,2-2V6C26,4.9,25.1,4,24,4z\\\" fill=\\\"white\\\"/>\\n </svg>\\n \";\n\n // 添加到视频包装器\n this.uiElements.videoWrapper.appendChild(this.pauseIndicator);\n\n // 延迟一帧后显示,确保过渡动画生效\n requestAnimationFrame(function () {\n _this6.pauseIndicator.classList.add('visible');\n });\n\n // 1秒后开始淡出\n setTimeout(function () {\n if (_this6.pauseIndicator) {\n _this6.pauseIndicator.classList.remove('visible');\n\n // 等待过渡效果完成后移除元素\n setTimeout(function () {\n if (_this6.pauseIndicator && _this6.pauseIndicator.parentNode) {\n _this6.pauseIndicator.parentNode.removeChild(_this6.pauseIndicator);\n _this6.pauseIndicator = null;\n }\n }, 300); // 过渡效果持续时间\n }\n }, 1000);\n }\n\n /**\n * 显示播放倍速指示器\n * @param {number} rate - 当前播放速度\n */\n }, {\n key: \"showPlaybackRateIndicator\",\n value: function showPlaybackRateIndicator(rate) {\n var _this7 = this;\n // 如果指示器已存在,清除之前的定时器并移除它\n if (this.playbackRateIndicator) {\n clearTimeout(this.playbackRateIndicator.hideTimeout);\n if (this.playbackRateIndicator.parentNode) {\n this.playbackRateIndicator.parentNode.removeChild(this.playbackRateIndicator);\n }\n this.playbackRateIndicator = null;\n }\n\n // 创建倍速指示器\n this.playbackRateIndicator = document.createElement('div');\n this.playbackRateIndicator.className = 'tm-indicator-base tm-playback-rate-indicator';\n\n // 设置样式\n this.playbackRateIndicator.style.position = 'absolute';\n this.playbackRateIndicator.style.top = '20%';\n this.playbackRateIndicator.style.left = '50%';\n this.playbackRateIndicator.style.transform = 'translateX(-50%)';\n\n // 设置倍速文本\n this.playbackRateIndicator.textContent = \"\".concat(rate.toFixed(1), \"x\");\n\n // 根据速度调整颜色\n if (rate > 1.5) {\n this.playbackRateIndicator.style.color = 'hsl(var(--shadcn-orange))';\n } else if (rate < 0.8) {\n this.playbackRateIndicator.style.color = 'hsl(var(--shadcn-blue))';\n }\n\n // 添加到视频包装器\n this.uiElements.videoWrapper.appendChild(this.playbackRateIndicator);\n\n // 延迟一帧后显示,确保过渡动画生效\n requestAnimationFrame(function () {\n _this7.playbackRateIndicator.classList.add('visible');\n });\n\n // 1.5秒后开始淡出\n this.playbackRateIndicator.hideTimeout = setTimeout(function () {\n if (_this7.playbackRateIndicator) {\n _this7.playbackRateIndicator.classList.remove('visible');\n\n // 等待过渡效果完成后移除元素\n setTimeout(function () {\n if (_this7.playbackRateIndicator && _this7.playbackRateIndicator.parentNode) {\n _this7.playbackRateIndicator.parentNode.removeChild(_this7.playbackRateIndicator);\n _this7.playbackRateIndicator = null;\n }\n }, 300); // 过渡效果持续时间\n }\n }, 1500);\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/managers/ControlManager.js?");
},
"./src/player/managers/DragManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DragManager: () => (/* binding */ DragManager)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\n * 拖动管理器类 - 负责拖动和大小调整功能\n */\nvar DragManager = /*#__PURE__*/function () {\n function DragManager(playerCore, uiElements) {\n _classCallCheck(this, DragManager);\n // 核心引用\n this.playerCore = playerCore;\n this.targetVideo = playerCore.targetVideo;\n\n // UI元素引用\n this.uiElements = uiElements;\n this.container = uiElements.container;\n this.handle = uiElements.handle;\n\n // 拖动状态管理\n this.isDraggingHandle = false; // 是否正在拖动句柄\n this.startX = 0;\n this.startY = 0;\n this.startWidth = 0;\n this.startHeight = 0;\n this.handleMoveHandler = null; // 句柄移动事件处理函数\n this.handleEndHandler = null; // 句柄释放事件处理函数\n }\n\n /**\n * 初始化拖动管理器\n */\n return _createClass(DragManager, [{\n key: "init",\n value: function init() {\n // 设置拖动处理事件\n this.handle.addEventListener(\'mousedown\', this.startHandleDrag.bind(this));\n this.handle.addEventListener(\'touchstart\', this.startHandleDrag.bind(this), {\n passive: false\n });\n return this;\n }\n\n /**\n * 更新手柄位置\n */\n }, {\n key: "updateHandlePosition",\n value: function updateHandlePosition() {\n if (!this.uiElements.handleContainer || !this.container) return;\n\n // 获取视频容器的位置信息\n var containerRect = this.container.getBoundingClientRect();\n var videoWrapperRect = this.uiElements.videoWrapper.getBoundingClientRect();\n\n // 设置手柄位置在视频容器下方\n this.uiElements.handleContainer.style.top = "".concat(videoWrapperRect.bottom, "px");\n }\n\n /**\n * 开始手柄拖动 (只处理Y轴,X轴由swipeManager处理)\n */\n }, {\n key: "startHandleDrag",\n value: function startHandleDrag(e) {\n this.isDraggingHandle = true;\n this.handle.style.cursor = \'grabbing\';\n var touch = e.type.includes(\'touch\');\n this.startY = touch ? e.touches[0].clientY : e.clientY;\n this.startHeight = this.container.offsetHeight;\n var moveHandler = this._handleDragMove.bind(this);\n var endHandler = this._handleDragEnd.bind(this);\n if (touch) {\n document.addEventListener(\'touchmove\', moveHandler, {\n passive: false\n });\n document.addEventListener(\'touchend\', endHandler);\n document.addEventListener(\'touchcancel\', endHandler);\n } else {\n document.addEventListener(\'mousemove\', moveHandler);\n document.addEventListener(\'mouseup\', endHandler);\n }\n\n // 存储事件处理函数以便移除\n this.handleMoveHandler = moveHandler;\n this.handleEndHandler = endHandler;\n e.preventDefault();\n }\n\n /**\n * 手柄移动处理 (只处理Y轴)\n */\n }, {\n key: "_handleDragMove",\n value: function _handleDragMove(e) {\n if (!this.isDraggingHandle) return;\n e.preventDefault();\n var touch = e.type.includes(\'touch\');\n var currentY = touch ? e.touches[0].clientY : e.clientY;\n var deltaY = currentY - this.startY;\n\n // 获取容器当前的最小高度作为约束\n var minHeight = parseFloat(this.container.style.minHeight) || window.innerWidth * (9 / 16);\n\n // 处理Y轴 (调整高度)\n var newHeight = Math.max(minHeight, this.startHeight + deltaY);\n this.container.style.height = newHeight + \'px\';\n\n // updateHandlePosition会被ResizeObserver自动调用\n }\n\n /**\n * 手柄拖动结束\n */\n }, {\n key: "_handleDragEnd",\n value: function _handleDragEnd(e) {\n if (!this.isDraggingHandle) return;\n this.isDraggingHandle = false;\n this.handle.style.cursor = \'grab\';\n\n // 移除监听器\n document.removeEventListener(\'touchmove\', this.handleMoveHandler);\n document.removeEventListener(\'touchend\', this.handleEndHandler);\n document.removeEventListener(\'touchcancel\', this.handleEndHandler);\n document.removeEventListener(\'mousemove\', this.handleMoveHandler);\n document.removeEventListener(\'mouseup\', this.handleEndHandler);\n\n // 清理存储的引用\n this.handleMoveHandler = null;\n this.handleEndHandler = null;\n if (e.type.startsWith(\'touch\')) {\n e.preventDefault();\n }\n }\n\n /**\n * 处理鼠标按下事件\n */\n }, {\n key: "handleMouseDown",\n value: function handleMouseDown(event) {\n if (event.button !== 0) return; // 只处理左键点击\n\n this.isDraggingHandle = true;\n this.startY = event.clientY;\n this.startHeight = this.uiElements.handleContainer.offsetHeight;\n this.handleMoveHandler = this.handleMouseMove.bind(this);\n this.handleEndHandler = this.handleMouseUp.bind(this);\n\n // 添加事件监听器\n document.addEventListener(\'mousemove\', this.handleMoveHandler);\n document.addEventListener(\'mouseup\', this.handleEndHandler);\n\n // 更新手柄位置\n this.updateHandlePosition();\n }\n\n /**\n * 处理鼠标移动事件\n */\n }, {\n key: "handleMouseMove",\n value: function handleMouseMove(event) {\n if (!this.isDraggingHandle) return;\n var deltaY = event.clientY - this.startY;\n var newHeight = this.startHeight + deltaY;\n if (newHeight < 50 || newHeight > 200) return; // 限制手柄高度范围\n\n this.uiElements.handleContainer.style.height = "".concat(newHeight, "px");\n this.updateHandlePosition();\n }\n\n /**\n * 处理鼠标释放事件\n */\n }, {\n key: "handleMouseUp",\n value: function handleMouseUp(event) {\n this.isDraggingHandle = false;\n\n // 移除事件监听器\n document.removeEventListener(\'mousemove\', this.handleMoveHandler);\n document.removeEventListener(\'mouseup\', this.handleEndHandler);\n\n // 更新手柄位置\n this.updateHandlePosition();\n }\n\n /**\n * 处理鼠标离开事件\n */\n }, {\n key: "handleMouseLeave",\n value: function handleMouseLeave(event) {\n this.isDraggingHandle = false;\n\n // 移除事件监听器\n document.removeEventListener(\'mousemove\', this.handleMoveHandler);\n document.removeEventListener(\'mouseup\', this.handleEndHandler);\n\n // 更新手柄位置\n this.updateHandlePosition();\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/managers/DragManager.js?');
},
"./src/player/managers/EventManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ EventManager: () => (/* binding */ EventManager)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\n * 事件管理器类 - 负责事件监听和处理\n */\nvar EventManager = /*#__PURE__*/function () {\n function EventManager(playerCore, uiElements, managers) {\n _classCallCheck(this, EventManager);\n // 核心引用\n this.playerCore = playerCore;\n this.targetVideo = playerCore.targetVideo;\n\n // UI元素引用\n this.uiElements = uiElements;\n\n // 管理器引用\n this.managers = managers;\n\n // 状态变量\n this.resizeObserver = null; // ResizeObserver 实例\n this.clickLock = false; // 防止快速多次点击视频区域\n this.clickLockTimeout = null; // 点击锁定计时器\n }\n\n /**\n * 初始化事件管理器\n */\n return _createClass(EventManager, [{\n key: "init",\n value: function init() {\n // 绑定基本方法\n this.handleWindowResizeBound = this.handleWindowResize.bind(this);\n this.handleContainerResizeBound = this.handleContainerResize.bind(this);\n this.handleOverlayTouchMoveBound = function (e) {\n return e.preventDefault();\n };\n\n // 初始化点击状态锁\n this.clickLock = false;\n this.clickLockTimeout = null;\n\n // 注释绑定视频包装器点击,由UIManager统一处理\n // this.handleVideoWrapperClickBound = this.handleVideoWrapperClick.bind(this);\n // this.uiElements.videoWrapper.addEventListener(\'click\', this.handleVideoWrapperClickBound);\n\n // 绑定按钮事件\n this.handleCloseButtonClickBound = this.handleCloseButtonClick.bind(this);\n if (this.uiElements.closeBtn) {\n this.uiElements.closeBtn.addEventListener(\'click\', this.handleCloseButtonClickBound);\n }\n this.handleSettingsButtonClickBound = this.handleSettingsButtonClick.bind(this);\n if (this.uiElements.settingsBtn) {\n this.uiElements.settingsBtn.addEventListener(\'click\', this.handleSettingsButtonClickBound);\n }\n\n // 添加窗口大小变化事件\n window.addEventListener(\'resize\', this.handleWindowResizeBound);\n\n // 设置容器大小观察器\n if (this.uiElements.container && typeof ResizeObserver !== \'undefined\') {\n this.resizeObserver = new ResizeObserver(this.handleContainerResizeBound);\n this.resizeObserver.observe(this.uiElements.container);\n }\n\n // 阻止overlay上的默认触摸行为,防止iOS Safari上的橡皮筋效果\n if (this.uiElements.overlay) {\n this.uiElements.overlay.addEventListener(\'touchmove\', this.handleOverlayTouchMoveBound, {\n passive: false\n });\n }\n\n // 设置视频事件监听器\n this.initVideoEventListeners();\n }\n\n /**\n * 初始化视频事件监听器\n */\n }, {\n key: "initVideoEventListeners",\n value: function initVideoEventListeners() {\n var _this = this;\n // 视频元数据加载完成监听\n this.handleMetadataLoadedBound = function () {\n if (_this.managers.progressManager) {\n _this.managers.progressManager.updateProgressBar();\n }\n if (_this.managers.loopManager) {\n _this.managers.loopManager.updateLoopTimeDisplay();\n _this.managers.loopManager.updateLoopMarkers();\n }\n if (_this.managers.dragManager) {\n _this.managers.dragManager.updateHandlePosition();\n }\n if (_this.managers.uiManager) {\n _this.managers.uiManager.updateContainerMinHeight();\n }\n\n // 更新SwipeManager以处理动态视频宽度\n if (_this.managers.swipeManager) {\n _this.managers.swipeManager.updateSize();\n }\n };\n this.targetVideo.addEventListener(\'loadedmetadata\', this.handleMetadataLoadedBound);\n\n // 视频可以播放时也更新容器高度\n this.handleCanPlayBound = function () {\n if (_this.managers.uiManager) {\n _this.managers.uiManager.updateContainerMinHeight();\n }\n\n // 更新SwipeManager以处理动态视频宽度\n if (_this.managers.swipeManager) {\n _this.managers.swipeManager.updateSize();\n }\n };\n this.targetVideo.addEventListener(\'canplay\', this.handleCanPlayBound);\n\n // 视频尺寸变化时更新\n this.handleVideoResizeBound = function () {\n if (_this.managers.uiManager) {\n _this.managers.uiManager.updateContainerMinHeight();\n }\n\n // 更新SwipeManager以处理动态视频宽度\n if (_this.managers.swipeManager) {\n _this.managers.swipeManager.updateSize();\n }\n };\n this.targetVideo.addEventListener(\'resize\', this.handleVideoResizeBound);\n\n // 监听视频播放状态变化\n this.handlePlayBound = function () {\n if (_this.managers.controlManager) {\n _this.managers.controlManager.updatePlayPauseButton();\n }\n };\n this.targetVideo.addEventListener(\'play\', this.handlePlayBound);\n this.handlePauseBound = function () {\n if (_this.managers.controlManager) {\n _this.managers.controlManager.updatePlayPauseButton();\n _this.managers.controlManager.showPauseIndicator();\n }\n };\n this.targetVideo.addEventListener(\'pause\', this.handlePauseBound);\n }\n\n /**\n * 处理视频包装器点击事件\n */\n }, {\n key: "handleVideoWrapperClick",\n value: function handleVideoWrapperClick(e) {\n var _this2 = this;\n // 确保点击事件不被其他控制元素阻挡\n if (e.target === this.uiElements.videoWrapper || e.target === this.targetVideo) {\n // 检查锁定状态,防止快速多次触发\n if (this.clickLock) {\n return;\n }\n\n // 检查是否刚完成拖动操作,如果是则不触发暂停/播放\n if (this.managers.swipeManager && typeof this.managers.swipeManager.wasRecentlyDragging === \'function\' && this.managers.swipeManager.wasRecentlyDragging()) {\n return;\n }\n\n // 设置点击锁定,防止短时间内重复触发\n this.clickLock = true;\n // 清除可能存在的旧定时器\n if (this.clickLockTimeout) {\n clearTimeout(this.clickLockTimeout);\n }\n // 500毫秒后解除锁定\n this.clickLockTimeout = setTimeout(function () {\n _this2.clickLock = false;\n _this2.clickLockTimeout = null;\n }, 500);\n if (this.targetVideo.paused) {\n this.targetVideo.play();\n } else {\n this.targetVideo.pause();\n if (this.managers.controlManager) {\n this.managers.controlManager.showPauseIndicator();\n }\n }\n if (this.managers.controlManager) {\n this.managers.controlManager.updatePlayPauseButton();\n }\n }\n }\n\n /**\n * 处理关闭按钮点击事件\n */\n }, {\n key: "handleCloseButtonClick",\n value: function handleCloseButtonClick() {\n // 先移除所有事件监听器\n this.cleanup();\n // 然后关闭播放器\n this.playerCore.close(this.uiElements.overlay, this.uiElements.container, this.uiElements.playerContainer);\n }\n\n /**\n * 处理设置按钮点击事件\n */\n }, {\n key: "handleSettingsButtonClick",\n value: function handleSettingsButtonClick() {\n if (this.managers.settingsManager) {\n this.managers.settingsManager.toggleSettingsPanel();\n }\n }\n\n /**\n * 处理窗口大小变化\n */\n }, {\n key: "handleWindowResize",\n value: function handleWindowResize() {\n // 更新视频大小和位置\n if (this.managers.uiManager) {\n this.managers.uiManager.updateContainerMinHeight();\n }\n if (this.managers.dragManager) {\n this.managers.dragManager.updateHandlePosition();\n }\n\n // 更新SwipeManager以处理动态视频宽度\n if (this.managers.swipeManager) {\n this.managers.swipeManager.updateSize();\n }\n }\n\n /**\n * 处理容器大小变化 (由 ResizeObserver 触发)\n */\n }, {\n key: "handleContainerResize",\n value: function handleContainerResize() {\n // 更新拖动手柄位置\n if (this.managers.dragManager) {\n this.managers.dragManager.updateHandlePosition();\n }\n\n // 更新SwipeManager以处理动态视频宽度\n if (this.managers.swipeManager) {\n this.managers.swipeManager.updateSize();\n }\n }\n\n /**\n * 清理所有事件监听器\n */\n }, {\n key: "cleanup",\n value: function cleanup() {\n // 移除窗口事件\n window.removeEventListener(\'resize\', this.handleWindowResizeBound);\n\n // 停止ResizeObserver\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n // 清除计时器\n if (this.clickLockTimeout) {\n clearTimeout(this.clickLockTimeout);\n this.clickLockTimeout = null;\n }\n\n // 视频包装器点击事件已由UIManager统一处理,此处不需要移除\n\n // 移除关闭按钮事件\n if (this.uiElements.closeBtn) {\n this.uiElements.closeBtn.removeEventListener(\'click\', this.handleCloseButtonClickBound);\n }\n\n // 移除设置按钮事件\n if (this.uiElements.settingsBtn) {\n this.uiElements.settingsBtn.removeEventListener(\'click\', this.handleSettingsButtonClickBound);\n }\n\n // 移除视频事件监听器\n if (this.targetVideo) {\n this.targetVideo.removeEventListener(\'loadedmetadata\', this.handleMetadataLoadedBound);\n this.targetVideo.removeEventListener(\'canplay\', this.handleCanPlayBound);\n this.targetVideo.removeEventListener(\'resize\', this.handleVideoResizeBound);\n this.targetVideo.removeEventListener(\'play\', this.handlePlayBound);\n this.targetVideo.removeEventListener(\'pause\', this.handlePauseBound);\n }\n\n // 移除overlay的touchmove事件\n if (this.uiElements.overlay) {\n this.uiElements.overlay.removeEventListener(\'touchmove\', this.handleOverlayTouchMoveBound);\n }\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/managers/EventManager.js?');
},
"./src/player/managers/LoopManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LoopManager: () => (/* binding */ LoopManager)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * 循环管理器类 - 负责循环播放功能\n */\nvar LoopManager = /*#__PURE__*/function () {\n function LoopManager(playerCore, uiElements) {\n _classCallCheck(this, LoopManager);\n // 核心引用\n this.playerCore = playerCore;\n this.targetVideo = playerCore.targetVideo;\n\n // UI元素引用\n this.uiElements = uiElements;\n\n // 循环控制相关\n this.loopStartTime = null;\n this.loopEndTime = null;\n this.loopActive = false;\n this.loopStartMarker = null;\n this.loopEndMarker = null;\n this.loopRangeElement = null;\n this.currentPositionDisplay = null;\n this.durationDisplay = null;\n this.loopToggleButton = null;\n\n // 时间更新处理器\n this._handleLoopTimeUpdate = this._handleLoopTimeUpdate.bind(this);\n }\n\n /**\n * 初始化循环管理器\n */\n return _createClass(LoopManager, [{\n key: \"init\",\n value: function init(loopElements) {\n this.loopStartMarker = loopElements.loopStartMarker;\n this.loopEndMarker = loopElements.loopEndMarker;\n this.loopRangeElement = loopElements.loopRangeElement;\n this.currentPositionDisplay = loopElements.currentPositionDisplay;\n this.durationDisplay = loopElements.durationDisplay;\n this.loopToggleButton = loopElements.loopToggleButton;\n\n // 解析URL参数设置循环点\n this._parseUrlHashParams();\n return this;\n }\n\n /**\n * 状态管理方法 - 统一更新状态并触发UI更新\n * @param {Object} newState - 要更新的状态对象\n */\n }, {\n key: \"setState\",\n value: function setState(newState) {\n // 记录状态变化的日志(便于调试)\n\n // 更新状态\n Object.assign(this, newState);\n\n // 触发UI更新\n this._updateUI();\n\n // 返回this以支持链式调用\n return this;\n }\n\n /**\n * 解析URL hash参数并设置循环点\n */\n }, {\n key: \"_parseUrlHashParams\",\n value: function _parseUrlHashParams() {\n var _this = this;\n if (!window.location.hash) return;\n var hash = window.location.hash.substring(1); // 去掉#\n\n // 检查是否有时间区间 (格式: 00:00:09-00:00:13)\n if (hash.includes('-')) {\n var _hash$split = hash.split('-'),\n _hash$split2 = _slicedToArray(_hash$split, 2),\n startTime = _hash$split2[0],\n endTime = _hash$split2[1];\n var startSeconds = this._parseTimeString(startTime);\n var endSeconds = this._parseTimeString(endTime);\n if (startSeconds !== null && endSeconds !== null) {\n // 设置循环点(不使用setState避免提前更新UI)\n var newState = {\n loopStartTime: startSeconds,\n loopEndTime: endSeconds\n };\n\n // 等视频元数据加载完成后再跳转和启用循环\n var _handleMetadata = function handleMetadata() {\n // 直接更新时间显示,避免时序问题\n if (_this.currentPositionDisplay) {\n _this.currentPositionDisplay.textContent = _this.formatTimeWithHours(startSeconds);\n _this.currentPositionDisplay.classList.add('active');\n var startContainer = document.querySelector('.tm-start-time-container');\n if (startContainer) startContainer.classList.add('active');\n }\n if (_this.durationDisplay) {\n _this.durationDisplay.textContent = _this.formatTimeWithHours(endSeconds);\n _this.durationDisplay.classList.add('active');\n var endContainer = document.querySelector('.tm-end-time-container');\n if (endContainer) endContainer.classList.add('active');\n }\n\n // 跳转到开始点\n _this.targetVideo.currentTime = startSeconds;\n\n // 保留对missav网站的特殊检查\n if (window.location.hostname.includes('missav')) {\n // 在missav网站上,循环播放是默认启用的\n newState.loopActive = true;\n } else {\n // 在其他网站上,也需要启用循环\n newState.loopActive = true;\n }\n\n // 统一更新状态和UI(将触发_updateUI,更新所有按钮状态)\n _this.setState(newState);\n\n // 强制更新标记点和进度条\n _this.updateLoopMarkers();\n\n // 添加事件监听器\n _this.targetVideo.removeEventListener('timeupdate', _this._handleLoopTimeUpdate);\n _this.targetVideo.addEventListener('timeupdate', _this._handleLoopTimeUpdate);\n\n // 自动播放视频\n if (_this.targetVideo.paused) {\n _this.targetVideo.play()[\"catch\"](function (error) {});\n }\n\n // 移除监听器\n _this.targetVideo.removeEventListener('loadedmetadata', _handleMetadata);\n };\n if (this.targetVideo.readyState >= 1) {\n _handleMetadata();\n } else {\n this.targetVideo.addEventListener('loadedmetadata', _handleMetadata);\n }\n }\n }\n // 检查是否只有单个时间点 (格式: 00:00:09)\n else if (hash.match(/^\\d{2}:\\d{2}:\\d{2}$/)) {\n var _startSeconds = this._parseTimeString(hash);\n if (_startSeconds !== null) {\n // 等视频元数据加载完成后再跳转\n var _handleMetadata2 = function handleMetadata() {\n // 直接更新时间显示,避免时序问题\n if (_this.currentPositionDisplay) {\n _this.currentPositionDisplay.textContent = _this.formatTimeWithHours(_startSeconds);\n _this.currentPositionDisplay.classList.add('active');\n var startContainer = document.querySelector('.tm-start-time-container');\n if (startContainer) startContainer.classList.add('active');\n }\n\n // 跳转到指定时间点并更新状态\n _this.targetVideo.currentTime = _startSeconds;\n\n // 更新状态(将触发_updateUI,更新A按钮样式)\n _this.setState({\n loopStartTime: _startSeconds\n });\n\n // 强制更新标记点\n _this.updateLoopMarkers();\n\n // 移除监听器\n _this.targetVideo.removeEventListener('loadedmetadata', _handleMetadata2);\n };\n if (this.targetVideo.readyState >= 1) {\n _handleMetadata2();\n } else {\n this.targetVideo.addEventListener('loadedmetadata', _handleMetadata2);\n }\n }\n }\n }\n\n /**\n * 将时间字符串解析为秒数\n * @param {string} timeString - 格式为 \"HH:MM:SS\" 的时间字符串\n * @returns {number|null} - 解析出的秒数,或null(如果解析失败)\n */\n }, {\n key: \"_parseTimeString\",\n value: function _parseTimeString(timeString) {\n if (!timeString) return null;\n var match = timeString.match(/^(\\d{2}):(\\d{2}):(\\d{2})$/);\n if (!match) return null;\n var hours = parseInt(match[1], 10);\n var minutes = parseInt(match[2], 10);\n var seconds = parseInt(match[3], 10);\n return hours * 3600 + minutes * 60 + seconds;\n }\n\n /**\n * 更新URL,添加循环点信息\n */\n }, {\n key: \"_updateUrlHash\",\n value: function _updateUrlHash() {\n var hash = '';\n if (this.loopStartTime !== null) {\n hash = this.formatTimeWithHours(this.loopStartTime);\n if (this.loopEndTime !== null) {\n hash += \"-\".concat(this.formatTimeWithHours(this.loopEndTime));\n }\n }\n\n // 使用history.replaceState更新URL而不添加历史记录\n if (hash) {\n var newUrl = window.location.pathname + window.location.search + '#' + hash;\n window.history.replaceState(null, '', newUrl);\n }\n }\n\n // 模拟点击-复制开始时间\n }, {\n key: \"_clickCopyStartTime\",\n value: function _clickCopyStartTime() {\n var startTimeButton = document.querySelector('input#clip-start-time + a');\n startTimeButton.click();\n }\n\n // 模拟点击-复制结束时间\n }, {\n key: \"_clickCopyEndTime\",\n value: function _clickCopyEndTime() {\n var endTimeButton = document.querySelector('input#clip-end-time + a');\n endTimeButton.click();\n }\n\n // 模拟点击-切换循环播放\n }, {\n key: \"_toggleLooping\",\n value: function _toggleLooping() {\n var loopButton = document.querySelector('.sm\\\\:ml-6 button');\n loopButton.click();\n }\n\n /**\n * 设置循环结束点 - 复制当前播放时间\n */\n }, {\n key: \"setLoopEnd\",\n value: function setLoopEnd() {\n if (!this.targetVideo) return;\n var currentTime = this.targetVideo.currentTime;\n if (window.location.hostname.includes('missav')) {\n this._clickCopyEndTime();\n // 使用setState更新状态\n this.setState({\n loopEndTime: currentTime\n });\n } else {\n // 如果开始点已设置,确保结束点在开始点之后\n if (this.loopStartTime !== null && currentTime <= this.loopStartTime) {\n return;\n }\n\n // 使用setState更新状态\n this.setState({\n loopEndTime: currentTime\n });\n // 更新URL\n this._updateUrlHash();\n }\n\n // 触觉反馈\n if (window.navigator.vibrate) {\n window.navigator.vibrate(10);\n }\n }\n\n /**\n * 设置循环开始点 - 复制当前播放时间\n */\n }, {\n key: \"setLoopStart\",\n value: function setLoopStart() {\n if (!this.targetVideo) return;\n var currentTime = this.targetVideo.currentTime;\n if (window.location.hostname.includes('missav')) {\n this._clickCopyStartTime();\n // 使用setState更新状态\n this.setState({\n loopStartTime: currentTime\n });\n } else {\n // 如果结束点已设置,确保开始点在结束点之前\n if (this.loopEndTime !== null && currentTime >= this.loopEndTime) {\n return;\n }\n\n // 使用setState更新状态\n this.setState({\n loopStartTime: currentTime\n });\n // 更新URL\n this._updateUrlHash();\n }\n\n // 触觉反馈\n if (window.navigator.vibrate) {\n window.navigator.vibrate(10);\n }\n }\n\n /**\n * 启用/禁用循环播放 - 切换循环状态\n */\n }, {\n key: \"toggleLoop\",\n value: function toggleLoop() {\n if (window.location.hostname.includes('missav')) {\n this._toggleLooping();\n } else {\n // 检查是否已设置开始和结束时间\n if (this.loopStartTime === null || this.loopEndTime === null) {\n return;\n }\n\n // 切换循环状态\n var newLoopActive = !this.loopActive;\n\n // 根据新状态执行相应操作\n if (newLoopActive) {\n this.enableLoop();\n } else {\n this.disableLoop();\n }\n }\n }\n\n /**\n * 启用循环播放\n */\n }, {\n key: \"enableLoop\",\n value: function enableLoop() {\n if (!this.targetVideo || this.loopStartTime === null || this.loopEndTime === null) {\n return;\n }\n // 更新状态\n this.setState({\n loopActive: true\n });\n\n // 移除原有监听器,确保不重复添加\n this.targetVideo.removeEventListener('timeupdate', this._handleLoopTimeUpdate);\n\n // 添加时间更新监听器\n this.targetVideo.addEventListener('timeupdate', this._handleLoopTimeUpdate);\n\n // 如果当前时间不在循环范围内,跳转到循环起始点\n if (this.targetVideo.currentTime < this.loopStartTime || this.targetVideo.currentTime > this.loopEndTime) {\n this.targetVideo.currentTime = this.loopStartTime;\n }\n\n // 无论视频是否暂停,都开始播放\n if (this.targetVideo.paused) {\n this.targetVideo.play()[\"catch\"](function (error) {});\n }\n\n // 触觉反馈\n if (window.navigator.vibrate) {\n window.navigator.vibrate([10, 30, 10]);\n }\n }\n\n /**\n * 禁用循环播放\n */\n }, {\n key: \"disableLoop\",\n value: function disableLoop() {\n if (!this.loopActive) return;\n // 移除事件监听器\n this.targetVideo.removeEventListener('timeupdate', this._handleLoopTimeUpdate);\n\n // 更新状态\n this.setState({\n loopActive: false\n });\n }\n\n /**\n * 循环播放时间更新处理器\n * 在播放到结束点时自动跳回开始点\n */\n }, {\n key: \"_handleLoopTimeUpdate\",\n value: function _handleLoopTimeUpdate() {\n if (!this.loopActive || this.loopStartTime === null || this.loopEndTime === null) return;\n var currentTime = this.targetVideo.currentTime;\n\n // 如果当前时间超过了循环结束点或小于开始点,跳回循环开始点\n if (currentTime >= this.loopEndTime || currentTime < this.loopStartTime) {\n this.targetVideo.currentTime = this.loopStartTime;\n }\n }\n\n /**\n * 更新所有UI元素\n */\n }, {\n key: \"_updateUI\",\n value: function _updateUI() {\n // 更新循环时间显示(A和B按钮)\n this.updateLoopTimeDisplay();\n\n // 更新循环标记点\n this.updateLoopMarkers();\n\n // 更新循环按钮样式\n this._updateLoopButtonStyle();\n }\n\n /**\n * 更新循环开关按钮状态\n */\n }, {\n key: \"_updateLoopButtonStyle\",\n value: function _updateLoopButtonStyle() {\n if (!this.loopToggleButton) return;\n if (this.loopActive) {\n // 激活状态 - 使用CSS类控制样式\n this.loopToggleButton.classList.add('active');\n\n // 更新指示器圆圈颜色 - 通过CSS类控制\n var indicator = this.loopToggleButton.querySelector('.tm-loop-indicator-circle');\n if (indicator) {\n indicator.setAttribute('fill', 'hsl(var(--shadcn-red))');\n }\n\n // 更新标签样式 - 通过CSS类控制\n var label = this.loopToggleButton.querySelector('.tm-loop-toggle-label');\n if (label) {\n label.classList.add('active'); // 添加.active类\n }\n } else {\n // 非激活状态 - 移除CSS类\n this.loopToggleButton.classList.remove('active');\n\n // 更新指示器圆圈颜色\n var _indicator = this.loopToggleButton.querySelector('.tm-loop-indicator-circle');\n if (_indicator) {\n _indicator.setAttribute('fill', 'hsl(var(--shadcn-muted-foreground) / 0.5)');\n }\n\n // 更新标签样式\n var _label = this.loopToggleButton.querySelector('.tm-loop-toggle-label');\n if (_label) {\n _label.classList.remove('active'); // 移除.active类\n }\n }\n }\n\n /**\n * 更新开始时间容器样式\n */\n }, {\n key: \"_updateStartTimeContainerStyle\",\n value: function _updateStartTimeContainerStyle() {\n var startContainer = document.querySelector('.tm-start-time-container');\n if (!startContainer) return;\n if (this.loopStartTime !== null) {\n // 更新时间文本\n this.currentPositionDisplay.textContent = this.formatTimeWithHours(this.loopStartTime);\n\n // 添加激活样式\n this.currentPositionDisplay.classList.add('active');\n startContainer.classList.add('active');\n\n // 确保A按钮的样式已应用\n var aButton = startContainer.querySelector('.tm-loop-start-button');\n if (aButton) {\n aButton.classList.add('active');\n }\n } else {\n // 未设置开始时间的默认样式\n this.currentPositionDisplay.textContent = '00:00:00';\n\n // 移除激活样式\n this.currentPositionDisplay.classList.remove('active');\n startContainer.classList.remove('active');\n\n // 重置A按钮样式\n var _aButton = startContainer.querySelector('.tm-loop-start-button');\n if (_aButton) {\n _aButton.classList.remove('active');\n }\n }\n }\n\n /**\n * 更新结束时间容器样式\n */\n }, {\n key: \"_updateEndTimeContainerStyle\",\n value: function _updateEndTimeContainerStyle() {\n var endContainer = document.querySelector('.tm-end-time-container');\n if (!endContainer) return;\n if (this.loopEndTime !== null) {\n // 更新时间文本\n this.durationDisplay.textContent = this.formatTimeWithHours(this.loopEndTime);\n\n // 添加激活样式\n this.durationDisplay.classList.add('active');\n endContainer.classList.add('active');\n\n // 确保B按钮的样式已应用\n var bButton = endContainer.querySelector('.tm-loop-end-button');\n if (bButton) {\n bButton.classList.add('active');\n }\n } else {\n // 未设置结束时间的默认样式\n this.durationDisplay.textContent = '00:00:00';\n\n // 移除激活样式\n this.durationDisplay.classList.remove('active');\n endContainer.classList.remove('active');\n\n // 重置B按钮样式\n var _bButton = endContainer.querySelector('.tm-loop-end-button');\n if (_bButton) {\n _bButton.classList.remove('active');\n }\n }\n }\n\n /**\n * 更新循环时间显示\n */\n }, {\n key: \"updateLoopTimeDisplay\",\n value: function updateLoopTimeDisplay() {\n // 更新开始时间显示\n this._updateStartTimeContainerStyle();\n\n // 更新结束时间显示\n this._updateEndTimeContainerStyle();\n }\n\n /**\n * 创建和更新循环标记点\n */\n }, {\n key: \"updateLoopMarkers\",\n value: function updateLoopMarkers() {\n var _this2 = this;\n if (!this.targetVideo || !this.loopStartMarker || !this.loopEndMarker) return;\n var progressBarElement = document.querySelector('.tm-progress-bar');\n if (!progressBarElement) return;\n var progressWidth = progressBarElement.offsetWidth;\n var duration = this.targetVideo.duration;\n if (duration <= 0 || !progressWidth) return;\n\n // 创建标记点辅助函数\n var createMarker = function createMarker(time, isStart) {\n var marker = isStart ? _this2.loopStartMarker : _this2.loopEndMarker;\n if (time !== null && !isNaN(time) && time >= 0 && time <= duration) {\n var position = time / duration * 100;\n marker.style.left = \"\".concat(position, \"%\");\n marker.style.display = 'block';\n\n // 更新标记状态 - 循环激活时应用active类\n if (_this2.loopActive) {\n marker.classList.add('active');\n } else {\n marker.classList.remove('active');\n }\n\n // 添加悬停提示\n marker.setAttribute('title', isStart ? \"\\u5FAA\\u73AF\\u8D77\\u70B9: \".concat(_this2.formatTimeWithHours(time)) : \"\\u5FAA\\u73AF\\u7EC8\\u70B9: \".concat(_this2.formatTimeWithHours(time)));\n\n // 设置额外的数据属性用于显示标签\n marker.setAttribute('data-time', _this2.formatTimeWithHours(time));\n } else {\n marker.style.display = 'none';\n }\n };\n\n // 更新 A 和 B 点位置\n createMarker(this.loopStartTime, true);\n createMarker(this.loopEndTime, false);\n\n // 如果循环已激活且两个标记点都存在,创建视觉连接效果\n if (this.loopActive && this.loopStartTime !== null && this.loopEndTime !== null) {\n // 使用CSS类管理状态\n this.loopStartMarker.classList.add('active');\n this.loopEndMarker.classList.add('active');\n\n // 更新循环区间连接元素\n if (this.loopRangeElement) {\n var startPosition = this.loopStartTime / duration * 100;\n var endPosition = this.loopEndTime / duration * 100;\n\n // 计算宽度和位置\n var width = endPosition - startPosition;\n if (width > 0) {\n this.loopRangeElement.style.left = \"\".concat(startPosition, \"%\");\n this.loopRangeElement.style.width = \"\".concat(width, \"%\");\n this.loopRangeElement.style.display = 'block';\n this.loopRangeElement.classList.add('active');\n } else {\n this.loopRangeElement.style.display = 'none';\n }\n }\n } else {\n this.loopStartMarker.classList.remove('active');\n this.loopEndMarker.classList.remove('active');\n\n // 隐藏循环区间连接元素\n if (this.loopRangeElement) {\n this.loopRangeElement.classList.remove('active');\n this.loopRangeElement.style.display = 'none';\n }\n }\n }\n\n /**\n * 格式化时间(含小时)\n */\n }, {\n key: \"formatTimeWithHours\",\n value: function formatTimeWithHours(timeInSeconds) {\n if (isNaN(timeInSeconds) || timeInSeconds < 0) {\n return '00:00:00';\n }\n var totalSeconds = Math.floor(timeInSeconds);\n var hours = Math.floor(totalSeconds / 3600);\n var minutes = Math.floor(totalSeconds % 3600 / 60);\n var seconds = totalSeconds % 60;\n return \"\".concat(hours.toString().padStart(2, '0'), \":\").concat(minutes.toString().padStart(2, '0'), \":\").concat(seconds.toString().padStart(2, '0'));\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/managers/LoopManager.js?");
},
"./src/player/managers/ProgressManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ProgressManager: () => (/* binding */ ProgressManager)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\n * 进度管理器类 - 负责进度条和时间显示功能\n */\nvar ProgressManager = /*#__PURE__*/function () {\n function ProgressManager(playerCore, uiElements) {\n _classCallCheck(this, ProgressManager);\n // 核心引用\n this.playerCore = playerCore;\n this.targetVideo = playerCore.targetVideo;\n\n // UI元素引用\n this.uiElements = uiElements;\n this.progressBarElement = null; // 进度条元素\n this.progressIndicator = null; // 进度指示器\n this.currentTimeDisplay = null; // 当前时间显示\n this.totalDurationDisplay = null; // 总时长显示\n this.timeIndicator = null; // 时间指示器\n\n // 拖动状态\n this.isDraggingProgress = false; // 是否正在拖动进度条\n this.progressHandleMoveHandler = null; // 进度条移动事件处理函数\n this.progressHandleUpHandler = null; // 进度条释放事件处理函数\n this.lastDragX = 0; // 上次拖动位置的X坐标\n this.isTouchDevice = \'ontouchstart\' in window; // 检测是否为触摸设备\n }\n\n /**\n * 初始化进度管理器\n */\n return _createClass(ProgressManager, [{\n key: "init",\n value: function init(progressElements) {\n this.progressBarElement = progressElements.progressBarElement;\n this.progressIndicator = progressElements.progressIndicator;\n this.currentTimeDisplay = progressElements.currentTimeDisplay;\n this.totalDurationDisplay = progressElements.totalDurationDisplay;\n this.timeIndicator = progressElements.timeIndicator;\n\n // 进度条容器元素 (父元素)\n this.progressBarContainer = this.progressBarElement.parentElement;\n\n // 添加进度条事件监听\n this.progressBarElement.addEventListener(\'click\', this.handleProgressClick.bind(this));\n\n // 为整个进度条容器添加拖动事件监听,增加可点击/拖动区域\n this.progressBarContainer.addEventListener(\'mousedown\', this.startProgressDrag.bind(this));\n this.progressBarContainer.addEventListener(\'touchstart\', this.startProgressDrag.bind(this), {\n passive: false\n });\n\n // 监听视频时间更新\n this.targetVideo.addEventListener(\'timeupdate\', this.updateProgressBar.bind(this));\n return this;\n }\n\n /**\n * 更新进度条\n */\n }, {\n key: "updateProgressBar",\n value: function updateProgressBar() {\n if (!this.targetVideo || !this.progressBarElement || !this.progressIndicator) return;\n var currentTime = this.targetVideo.currentTime;\n var duration = this.targetVideo.duration;\n if (isNaN(duration) || duration <= 0) return;\n\n // 计算进度百分比\n var progressPercent = currentTime / duration * 100;\n\n // 更新进度指示器的宽度\n this.progressIndicator.style.width = "".concat(progressPercent, "%");\n\n // 更新时间显示\n this.updateCurrentTimeDisplay();\n }\n\n /**\n * 更新当前时间显示\n */\n }, {\n key: "updateCurrentTimeDisplay",\n value: function updateCurrentTimeDisplay() {\n if (!this.targetVideo || !this.currentTimeDisplay || !this.totalDurationDisplay) return;\n var currentTime = this.targetVideo.currentTime;\n var duration = this.targetVideo.duration;\n if (isNaN(duration)) return;\n\n // 更新当前时间显示\n this.currentTimeDisplay.textContent = this.formatTime(currentTime);\n\n // 计算并显示剩余时长,而不是总时长\n var remainingTime = duration - currentTime;\n this.totalDurationDisplay.textContent = "-".concat(this.formatTime(remainingTime));\n }\n\n /**\n * 格式化时间\n */\n }, {\n key: "formatTime",\n value: function formatTime(seconds) {\n if (isNaN(seconds) || seconds < 0) {\n return \'00:00:00\';\n }\n var totalSeconds = Math.floor(seconds);\n var hours = Math.floor(totalSeconds / 3600);\n var minutes = Math.floor(totalSeconds % 3600 / 60);\n var remainingSeconds = totalSeconds % 60;\n return "".concat(hours.toString().padStart(2, \'0\'), ":").concat(minutes.toString().padStart(2, \'0\'), ":").concat(remainingSeconds.toString().padStart(2, \'0\'));\n }\n\n /**\n * 处理进度条点击\n */\n }, {\n key: "handleProgressClick",\n value: function handleProgressClick(e) {\n // 如果正在拖动进度条,则忽略点击事件\n if (this.isDraggingProgress) return;\n\n // 获取进度条的位置信息\n var rect = this.progressBarElement.getBoundingClientRect();\n\n // 计算点击位置相对于进度条的比例 (0-1)\n var relativePos = (e.clientX - rect.left) / rect.width;\n\n // 计算目标时间\n var duration = this.targetVideo.duration;\n if (isNaN(duration)) return;\n var targetTime = duration * relativePos;\n\n // 设置视频当前时间\n this.targetVideo.currentTime = targetTime;\n\n // 更新进度条\n this.updateProgressBar();\n }\n\n /**\n * 相对时间跳转\n */\n }, {\n key: "seekRelative",\n value: function seekRelative(seconds) {\n if (!this.targetVideo) return;\n var newTime = Math.max(0, Math.min(this.targetVideo.duration, this.targetVideo.currentTime + seconds));\n this.targetVideo.currentTime = newTime;\n }\n\n /**\n * 开始进度条拖动\n */\n }, {\n key: "startProgressDrag",\n value: function startProgressDrag(e) {\n // 阻止默认行为,防止选择文本或触发其他事件\n e.preventDefault();\n e.stopPropagation();\n\n // 设置拖动状态\n this.isDraggingProgress = true;\n\n // 保存初始点击位置\n this.lastDragX = e.type.includes(\'touch\') ? e.touches[0].clientX : e.clientX;\n\n // 保持进度条高度以获得更好的拖动体验\n this.progressBarElement.classList.add(\'tm-progress-bar-expanded\');\n this.progressBarElement.classList.remove(\'tm-progress-bar-normal\');\n\n // 添加拖动状态标记\n this.progressBarElement.classList.add(\'tm-dragging\');\n\n // 显示时间指示器\n if (this.timeIndicator) {\n this.timeIndicator.style.display = \'block\';\n this.timeIndicator.style.opacity = \'1\';\n this.updateTimeIndicator(e);\n }\n\n // 绑定移动和释放事件处理函数\n var moveHandler = this.handleProgressMove.bind(this);\n var upHandler = this.handleProgressUp.bind(this);\n\n // 清除之前可能存在的事件监听\n this.removeProgressEventListeners();\n\n // 添加事件监听 - 使用 document 以捕获所有移动事件,即使鼠标移出进度条\n if (e.type.includes(\'touch\')) {\n document.addEventListener(\'touchmove\', moveHandler, {\n passive: false\n });\n document.addEventListener(\'touchend\', upHandler, {\n passive: false\n });\n document.addEventListener(\'touchcancel\', upHandler, {\n passive: false\n });\n } else {\n document.addEventListener(\'mousemove\', moveHandler);\n document.addEventListener(\'mouseup\', upHandler);\n document.addEventListener(\'mouseleave\', upHandler);\n }\n this.progressHandleMoveHandler = moveHandler;\n this.progressHandleUpHandler = upHandler;\n\n // 立即调整到点击位置(与handleProgressClick的功能一致)\n var rect = this.progressBarElement.getBoundingClientRect();\n var clientX = e.type.includes(\'touch\') ? e.touches[0].clientX : e.clientX;\n var relativePos = (clientX - rect.left) / rect.width;\n relativePos = Math.max(0, Math.min(1, relativePos));\n var duration = this.targetVideo.duration;\n if (!isNaN(duration)) {\n var newTime = duration * relativePos;\n this.targetVideo.currentTime = newTime;\n this.progressIndicator.style.width = "".concat(relativePos * 100, "%");\n this.updateCurrentTimeDisplay();\n }\n }\n\n /**\n * 处理进度条拖动移动\n */\n }, {\n key: "handleProgressMove",\n value: function handleProgressMove(e) {\n // 如果不是处于拖动状态,则退出\n if (!this.isDraggingProgress) return;\n\n // 阻止默认行为\n e.preventDefault();\n\n // 获取当前位置\n var clientX = e.type.includes(\'touch\') ? e.touches[0].clientX : e.clientX;\n\n // 更新时间指示器\n this.updateTimeIndicator(e);\n\n // 计算新的进度位置\n var rect = this.progressBarElement.getBoundingClientRect();\n\n // 确保进度条元素可见并有宽度\n if (rect.width <= 0) return;\n\n // 计算相对位置 (0-1)\n var relativePos = (clientX - rect.left) / rect.width;\n relativePos = Math.max(0, Math.min(1, relativePos));\n\n // 计算新时间\n var duration = this.targetVideo.duration;\n if (isNaN(duration)) return;\n var newTime = duration * relativePos;\n\n // 更新进度指示器位置\n this.progressIndicator.style.width = "".concat(relativePos * 100, "%");\n\n // 实时更新视频播放位置\n this.targetVideo.currentTime = newTime;\n\n // 更新时间显示\n this.currentTimeDisplay.textContent = this.formatTime(newTime);\n var remainingTime = duration - newTime;\n this.totalDurationDisplay.textContent = "-".concat(this.formatTime(remainingTime));\n\n // 更新最后拖动位置\n this.lastDragX = clientX;\n }\n\n /**\n * 处理进度条释放\n */\n }, {\n key: "handleProgressUp",\n value: function handleProgressUp(e) {\n // 如果不是处于拖动状态,则退出\n if (!this.isDraggingProgress) return;\n\n // 计算最终位置并设置视频时间\n var rect = this.progressBarElement.getBoundingClientRect();\n var clientX = e.type.includes(\'touch\') ? e.changedTouches && e.changedTouches[0] ? e.changedTouches[0].clientX : this.lastDragX : e.clientX || this.lastDragX;\n\n // 计算相对位置 (0-1)\n var relativePos = (clientX - rect.left) / rect.width;\n relativePos = Math.max(0, Math.min(1, relativePos));\n\n // 设置视频当前时间\n var duration = this.targetVideo.duration;\n if (!isNaN(duration)) {\n this.targetVideo.currentTime = duration * relativePos;\n }\n\n // 隐藏时间指示器\n if (this.timeIndicator) {\n this.timeIndicator.style.opacity = \'0\';\n }\n\n // 移除拖动状态标记\n this.progressBarElement.classList.remove(\'tm-dragging\');\n\n // 恢复进度条高度\n if (!this.progressBarElement.classList.contains(\'tm-progress-bar-hovered\')) {\n this.progressBarElement.classList.add(\'tm-progress-bar-normal\');\n this.progressBarElement.classList.remove(\'tm-progress-bar-expanded\');\n }\n\n // 清理状态和事件\n this.isDraggingProgress = false;\n this.lastDragX = 0; // 重置拖动坐标\n\n // 移除事件监听\n this.removeProgressEventListeners();\n }\n\n /**\n * 移除进度条相关事件监听\n */\n }, {\n key: "removeProgressEventListeners",\n value: function removeProgressEventListeners() {\n if (this.progressHandleMoveHandler) {\n document.removeEventListener(\'mousemove\', this.progressHandleMoveHandler);\n document.removeEventListener(\'touchmove\', this.progressHandleMoveHandler);\n }\n if (this.progressHandleUpHandler) {\n document.removeEventListener(\'mouseup\', this.progressHandleUpHandler);\n document.removeEventListener(\'touchend\', this.progressHandleUpHandler);\n document.removeEventListener(\'touchcancel\', this.progressHandleUpHandler);\n document.removeEventListener(\'mouseleave\', this.progressHandleUpHandler);\n }\n this.progressHandleMoveHandler = null;\n this.progressHandleUpHandler = null;\n }\n\n /**\n * 更新时间指示器位置和内容\n */\n }, {\n key: "updateTimeIndicator",\n value: function updateTimeIndicator(e) {\n if (!this.timeIndicator || !this.targetVideo) return;\n var clientX = e.type.includes(\'touch\') ? e.touches[0].clientX : e.clientX;\n var clientY = e.type.includes(\'touch\') ? e.touches[0].clientY : e.clientY;\n\n // 获取视频容器的位置\n var videoRect = this.uiElements.videoWrapper.getBoundingClientRect();\n var progressRect = this.progressBarElement.getBoundingClientRect();\n\n // 计算指示器位置,确保始终在视频区域内部\n var leftPos = Math.max(videoRect.left + 10, Math.min(videoRect.right - 10, clientX));\n\n // 计算垂直位置 - 放在进度条上方一定距离\n var topPos = progressRect.top - 20;\n\n // 设置指示器位置\n this.timeIndicator.style.left = "".concat(leftPos, "px");\n this.timeIndicator.style.top = "".concat(topPos, "px");\n\n // 计算时间\n var relativePos = (clientX - progressRect.left) / progressRect.width;\n var boundedPos = Math.max(0, Math.min(1, relativePos));\n var duration = this.targetVideo.duration;\n if (isNaN(duration)) return;\n var time = duration * boundedPos;\n\n // 更新指示器内容\n this.timeIndicator.textContent = "".concat(this.formatTime(time), " / ").concat(this.formatTime(duration));\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/managers/ProgressManager.js?');
},
"./src/player/managers/SettingsManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SettingsManager: () => (/* binding */ SettingsManager)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * 设置管理器类 - 负责播放器设置功能\n */\nvar SettingsManager = /*#__PURE__*/function () {\n function SettingsManager(playerCore, uiElements) {\n _classCallCheck(this, SettingsManager);\n // 核心引用\n this.playerCore = playerCore;\n this.targetVideo = playerCore.targetVideo;\n\n // UI元素引用\n this.uiElements = uiElements;\n this.settingsPanel = uiElements.settingsPanel;\n\n // 事件处理器\n this.overlayClickHandler = null;\n\n // 用户设置\n this.settings = {\n showSeekControlRow: true,\n // 显示快进快退按钮\n showLoopControlRow: true,\n // 显示循环控制按钮\n showPlaybackControlRow: true,\n // 显示播放控制按钮\n showProgressBar: true // 显示进度条\n };\n }\n\n /**\n * 初始化设置管理器\n */\n return _createClass(SettingsManager, [{\n key: \"init\",\n value: function init() {\n // 加载保存的设置\n this.loadSettings();\n\n // 创建设置面板内容\n this.createSettingsPanel();\n return this;\n }\n\n /**\n * 创建设置面板内容\n */\n }, {\n key: \"createSettingsPanel\",\n value: function createSettingsPanel() {\n var _this = this;\n // 添加设置选项\n var settingsOptions = document.createElement('div');\n settingsOptions.className = 'tm-settings-options';\n settingsOptions.style.display = 'flex';\n settingsOptions.style.flexDirection = 'column';\n settingsOptions.style.gap = '12px';\n\n // 添加显示进度条选项\n var progressBarOption = this.createSettingOption('显示-进度条', 'showProgressBar', this.settings.showProgressBar, function (checked) {\n _this.settings.showProgressBar = checked;\n _this.saveSettings();\n _this.updateControlRowsVisibility();\n });\n\n // 添加显示快进快退控制行选项\n var seekControlRowOption = this.createSettingOption('显示-进度跳转', 'showSeekControlRow', this.settings.showSeekControlRow, function (checked) {\n _this.settings.showSeekControlRow = checked;\n _this.saveSettings();\n _this.updateControlRowsVisibility();\n });\n\n // 添加显示循环控制行选项\n var loopControlRowOption = this.createSettingOption('显示-循环控制', 'showLoopControlRow', this.settings.showLoopControlRow, function (checked) {\n _this.settings.showLoopControlRow = checked;\n _this.saveSettings();\n _this.updateControlRowsVisibility();\n });\n\n // 添加显示播放控制行选项\n var playbackControlRowOption = this.createSettingOption('显示-播放倍速', 'showPlaybackControlRow', this.settings.showPlaybackControlRow, function (checked) {\n _this.settings.showPlaybackControlRow = checked;\n _this.saveSettings();\n _this.updateControlRowsVisibility();\n });\n settingsOptions.appendChild(progressBarOption);\n settingsOptions.appendChild(seekControlRowOption);\n settingsOptions.appendChild(loopControlRowOption);\n settingsOptions.appendChild(playbackControlRowOption);\n this.settingsPanel.appendChild(settingsOptions);\n }\n\n /**\n * 创建设置选项\n * @param {string} labelText 选项标签文本\n * @param {string} settingKey 设置键名\n * @param {boolean} initialValue 初始值\n * @param {Function} onChange 值变化时的回调函数\n * @returns {HTMLElement} 设置选项元素\n */\n }, {\n key: \"createSettingOption\",\n value: function createSettingOption(labelText, settingKey, initialValue, onChange) {\n var optionContainer = document.createElement('div');\n optionContainer.className = 'tm-settings-option';\n optionContainer.id = \"tm-setting-\".concat(settingKey);\n var label = document.createElement('label');\n label.className = 'tm-settings-label';\n label.textContent = labelText;\n\n // 创建一个开关样式的复选框\n var toggleContainer = document.createElement('div');\n toggleContainer.className = 'tm-toggle-switch';\n\n // 创建一个隐藏的复选框用于状态保存\n var toggleInput = document.createElement('input');\n toggleInput.type = 'checkbox';\n toggleInput.checked = initialValue;\n toggleInput.className = 'tm-toggle-input';\n var toggleSlider = document.createElement('span');\n toggleSlider.className = initialValue ? 'tm-toggle-slider checked' : 'tm-toggle-slider';\n\n // 添加 tabIndex 使其可聚焦\n optionContainer.tabIndex = 0;\n toggleContainer.appendChild(toggleInput);\n toggleContainer.appendChild(toggleSlider);\n\n // 添加点击处理\n var toggleSwitch = function toggleSwitch(e) {\n e.preventDefault();\n e.stopPropagation();\n\n // 更新复选框状态\n toggleInput.checked = !toggleInput.checked;\n\n // 更新样式\n if (toggleInput.checked) {\n toggleSlider.className = 'tm-toggle-slider checked';\n } else {\n toggleSlider.className = 'tm-toggle-slider';\n }\n\n // 执行回调函数\n if (typeof onChange === 'function') {\n onChange(toggleInput.checked);\n }\n };\n\n // 让整个选项可点击\n optionContainer.addEventListener('click', toggleSwitch);\n\n // 添加键盘支持\n optionContainer.addEventListener('keydown', function (e) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggleSwitch(e);\n }\n });\n optionContainer.appendChild(label);\n optionContainer.appendChild(toggleContainer);\n return optionContainer;\n }\n\n /**\n * 切换设置面板显示状态\n */\n }, {\n key: \"toggleSettingsPanel\",\n value: function toggleSettingsPanel() {\n var _this2 = this;\n var isVisible = this.settingsPanel.classList.contains('active');\n if (isVisible) {\n this.closeSettingsPanel();\n } else {\n this.settingsPanel.style.display = 'block';\n\n // 使用动画淡入\n setTimeout(function () {\n _this2.settingsPanel.classList.add('active');\n }, 10);\n\n // 添加点击overlay背景关闭设置面板的事件\n this.overlayClickHandler = function (e) {\n // 如果点击的不是设置面板内的元素,则关闭设置面板\n if (!_this2.settingsPanel.contains(e.target) && e.target !== _this2.uiElements.settingsBtn) {\n _this2.closeSettingsPanel();\n }\n };\n\n // 延迟添加事件监听器,避免与当前点击冲突\n setTimeout(function () {\n if (_this2.uiElements.overlay) {\n _this2.uiElements.overlay.addEventListener('click', _this2.overlayClickHandler);\n }\n }, 50);\n }\n }\n\n /**\n * 关闭设置面板\n */\n }, {\n key: \"closeSettingsPanel\",\n value: function closeSettingsPanel() {\n var _this3 = this;\n this.settingsPanel.classList.remove('active');\n\n // 移除点击事件监听器\n if (this.uiElements.overlay && this.overlayClickHandler) {\n this.uiElements.overlay.removeEventListener('click', this.overlayClickHandler);\n this.overlayClickHandler = null;\n }\n\n // 等待动画完成后隐藏\n setTimeout(function () {\n _this3.settingsPanel.style.display = 'none';\n }, 300);\n }\n\n /**\n * 加载设置\n */\n }, {\n key: \"loadSettings\",\n value: function loadSettings() {\n try {\n // 创建临时函数来获取设置\n var getValue = function getValue(key, defaultValue) {\n try {\n if (typeof GM_getValue === 'function') {\n return GM_getValue(key, defaultValue);\n } else {\n var value = localStorage.getItem(\"missNoAD_\".concat(key));\n return value !== null ? JSON.parse(value) : defaultValue;\n }\n } catch (e) {\n return defaultValue;\n }\n };\n\n // 加载设置,如果不存在则使用默认值\n this.settings.showProgressBar = getValue('showProgressBar', true);\n this.settings.showSeekControlRow = getValue('showSeekControlRow', true);\n this.settings.showLoopControlRow = getValue('showLoopControlRow', true);\n this.settings.showPlaybackControlRow = getValue('showPlaybackControlRow', true);\n } catch (error) {}\n }\n\n /**\n * 保存设置\n */\n }, {\n key: \"saveSettings\",\n value: function saveSettings() {\n try {\n // 创建临时函数来保存设置\n var setValue = function setValue(key, value) {\n try {\n if (typeof GM_setValue === 'function') {\n GM_setValue(key, value);\n return true;\n } else {\n localStorage.setItem(\"missNoAD_\".concat(key), JSON.stringify(value));\n return true;\n }\n } catch (e) {\n return false;\n }\n };\n setValue('showProgressBar', this.settings.showProgressBar);\n setValue('showSeekControlRow', this.settings.showSeekControlRow);\n setValue('showLoopControlRow', this.settings.showLoopControlRow);\n setValue('showPlaybackControlRow', this.settings.showPlaybackControlRow);\n } catch (error) {}\n }\n\n /**\n * 更新控制行的可见性\n */\n }, {\n key: \"updateControlRowsVisibility\",\n value: function updateControlRowsVisibility() {\n var controlButtonsContainer = document.querySelector('.tm-control-buttons');\n if (!controlButtonsContainer) return;\n var seekControlRow = controlButtonsContainer.querySelector('.tm-seek-control-row');\n var loopControlRow = controlButtonsContainer.querySelector('.tm-loop-control-row');\n var playbackControlRow = controlButtonsContainer.querySelector('.tm-playback-control-row');\n var progressRow = controlButtonsContainer.querySelector('.tm-progress-row');\n if (progressRow) {\n progressRow.style.display = this.settings.showProgressBar ? 'flex' : 'none';\n }\n if (seekControlRow) {\n seekControlRow.style.display = this.settings.showSeekControlRow ? 'flex' : 'none';\n }\n if (loopControlRow) {\n loopControlRow.style.display = this.settings.showLoopControlRow ? 'flex' : 'none';\n }\n if (playbackControlRow) {\n playbackControlRow.style.display = this.settings.showPlaybackControlRow ? 'flex' : 'none';\n }\n }\n\n /**\n * 更新设置项\n * @param {string} key 设置键名\n * @param {any} value 设置值\n */\n }, {\n key: \"updateSetting\",\n value: function updateSetting(key, value) {\n if (this.settings.hasOwnProperty(key)) {\n this.settings[key] = value;\n this.saveSettings();\n\n // 如果涉及UI可见性,更新UI\n if (key.startsWith('show') && key.endsWith('Row')) {\n this.updateControlRowsVisibility();\n }\n }\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/managers/SettingsManager.js?");
},
"./src/player/managers/videoSwipeManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ VideoSwipeManager: () => (/* binding */ VideoSwipeManager)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\n * 视频水平移动管理器 - 全新模块化设计\n */\nvar VideoSwipeManager = /*#__PURE__*/function () {\n function VideoSwipeManager(videoElement, containerElement, handleElement) {\n _classCallCheck(this, VideoSwipeManager);\n // 核心元素引用\n this.video = videoElement;\n this.container = containerElement;\n this.handle = handleElement;\n\n // 状态管理\n this.offset = 0; // 当前水平偏移量\n this.maxOffset = 0; // 最大偏移量限制\n this.isDragging = false; // 视频拖动状态\n this.isHandleDragging = false; // 手柄拖动状态\n this.startX = 0; // 拖动起始X坐标\n this.startOffset = 0; // 拖动起始偏移量\n this.lastSnapPosition = null; // 上次吸附位置,用于判断是否需要震动\n this.wasDragging = false; // 新增:标记是否刚完成拖动操作\n this.dragEndTimestamp = 0; // 新增:记录拖动结束的时间戳\n this.dragDistance = 0; // 新增:记录拖动距离\n this.minDragDistance = 10; // 新增:最小有效拖动距离(像素)\n\n // 视频尺寸信息\n this.videoWidth = 0; // 视频自然宽度\n this.videoHeight = 0; // 视频自然高度\n this.containerWidth = 0; // 容器宽度\n this.containerHeight = 0; // 容器高度\n this.videoScale = 1; // 视频缩放比例\n\n // 惯性滚动相关\n this.velocityTracker = {\n positions: [],\n // 存储最近的位置记录\n lastTimestamp: 0,\n // 上次记录时间\n currentVelocity: 0 // 当前速度\n };\n\n // 手柄惯性滚动数据\n this.handleVelocityTracker = {\n positions: [],\n // 存储最近的位置记录\n lastTimestamp: 0,\n // 上次记录时间\n currentVelocity: 0 // 当前速度\n };\n\n // 动画状态\n this.animation = {\n active: false,\n // 是否有动画正在进行\n rafId: null,\n // requestAnimationFrame ID\n targetOffset: 0,\n // 动画目标偏移量\n startTime: 0,\n // 动画开始时间\n duration: 0 // 动画持续时间\n };\n\n // 事件处理函数(使用箭头函数绑定this)\n this._pointerDownHandler = this._handlePointerDown.bind(this);\n this._pointerMoveHandler = this._handlePointerMove.bind(this);\n this._pointerUpHandler = this._handlePointerUp.bind(this);\n\n // 手柄事件处理函数\n this._handlePointerDownHandler = this._handleHandlePointerDown.bind(this);\n this._handlePointerMoveHandler = this._handleHandlePointerMove.bind(this);\n this._handlePointerUpHandler = this._handleHandlePointerUp.bind(this);\n\n // 初始化\n this._init();\n }\n\n /**\n * 初始化管理器\n */\n return _createClass(VideoSwipeManager, [{\n key: "_init",\n value: function _init() {\n var _this = this;\n // 设置视频元素性能相关样式,不修改原始布局样式\n this.video.style.willChange = \'transform\'; // 优化性能\n this.video.style.transition = \'transform 0.2s cubic-bezier(0.215, 0.61, 0.355, 1)\';\n\n // 注意:不再设置 width, height 或 objectFit,尊重原始样式\n\n // 添加视频事件监听\n this.video.addEventListener(\'pointerdown\', this._pointerDownHandler);\n\n // 添加手柄事件监听\n if (this.handle) {\n this.handle.style.willChange = \'transform, left\'; // 优化性能\n this.handle.style.transition = \'left 0.2s cubic-bezier(0.215, 0.61, 0.355, 1), width 0.2s ease\';\n this.handle.addEventListener(\'pointerdown\', this._handlePointerDownHandler);\n }\n\n // 初始更新约束条件\n this._updateConstraints();\n\n // 视频加载或尺寸变化时更新约束\n this.video.addEventListener(\'loadedmetadata\', function () {\n _this._updateConstraints();\n });\n this.video.addEventListener(\'canplay\', function () {\n _this._updateConstraints();\n });\n }\n\n /**\n * 计算视频的有效边界和可移动范围\n * @private\n */\n }, {\n key: "_updateVideoDimensions",\n value: function _updateVideoDimensions() {\n // 获取视频自然尺寸\n this.videoWidth = this.video.videoWidth || this.video.naturalWidth || 0;\n this.videoHeight = this.video.videoHeight || this.video.naturalHeight || 0;\n\n // 获取容器尺寸\n this.containerWidth = this.container.offsetWidth;\n this.containerHeight = this.container.offsetHeight;\n\n // 如果视频或容器尺寸无效,则不继续计算\n if (this.videoWidth <= 0 || this.videoHeight <= 0 || this.containerWidth <= 0 || this.containerHeight <= 0) {\n this.videoScale = 1;\n this.maxOffset = 0;\n return false;\n }\n\n // 获取视频元素的当前实际尺寸\n var videoRect = this.video.getBoundingClientRect();\n var actualVideoWidth = videoRect.width;\n var actualVideoHeight = videoRect.height;\n\n // 计算视频缩放比例\n this.videoScale = actualVideoHeight / this.videoHeight;\n\n // 计算最大水平偏移量 (视频超出容器的部分的一半)\n var overflow = Math.max(0, actualVideoWidth - this.containerWidth);\n this.maxOffset = overflow / 2;\n return true;\n }\n\n /**\n * 更新约束条件(如最大偏移量)\n */\n }, {\n key: "_updateConstraints",\n value: function _updateConstraints() {\n // 更新视频尺寸和约束\n var dimensionsUpdated = this._updateVideoDimensions();\n\n // 如果尺寸计算失败或视频宽度不超过容器,则无需移动\n if (!dimensionsUpdated || this.maxOffset <= 0) {\n // 重置到居中位置\n this._applyOffset(0, false);\n // 更新手柄状态为禁用移动,但宽度相应设置\n this._updateHandleState(false);\n return false;\n }\n\n // 限制当前偏移量在新的范围内\n this.offset = Math.max(-this.maxOffset, Math.min(this.offset, this.maxOffset));\n\n // 应用可能调整后的偏移量\n this._applyOffset(this.offset, false);\n\n // 更新手柄状态为可用\n this._updateHandleState(true);\n return true;\n }\n\n /**\n * 应用偏移量到视频元素\n * @param {number} offset - 要应用的偏移量\n * @param {boolean} animate - 是否使用动画过渡\n */\n }, {\n key: "_applyOffset",\n value: function _applyOffset(offset) {\n var animate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n // 确保偏移量在有效范围内\n this.offset = Math.max(-this.maxOffset, Math.min(offset, this.maxOffset));\n if (animate) {\n this.video.style.transition = \'transform 0.2s cubic-bezier(0.215, 0.61, 0.355, 1)\';\n } else {\n this.video.style.transition = \'none\';\n }\n\n // 使用transform而不是left,利用GPU加速\n this.video.style.transform = "translateX(".concat(this.offset, "px)");\n\n // 同步更新手柄位置\n this._updateHandlePosition();\n return this;\n }\n\n /**\n * 更新手柄状态\n * @param {boolean} enabled - 手柄是否应该启用\n */\n }, {\n key: "_updateHandleState",\n value: function _updateHandleState(enabled) {\n if (!this.handle) return;\n\n // 更新手柄宽度\n this._updateHandleWidth();\n if (enabled) {\n this.handle.style.cursor = \'grab\';\n this.video.style.cursor = \'grab\';\n\n // 只有在视频比容器宽时才允许移动\n var handleContainer = this.handle.parentElement;\n if (handleContainer) {\n handleContainer.style.cursor = \'grab\';\n }\n } else {\n // 视频完全可见或未超出容器时,手柄宽度适应但禁用拖动\n this.handle.style.cursor = \'default\';\n this.video.style.cursor = \'default\';\n // 不再设置手柄位置,使用_updateHandlePosition方法统一处理\n }\n\n // 立即更新手柄位置以反映视频偏移\n this._updateHandlePosition();\n }\n\n /**\n * 更新手柄宽度\n */\n }, {\n key: "_updateHandleWidth",\n value: function _updateHandleWidth() {\n if (!this.handle) return;\n\n // 使用固定的手柄宽度,不再动态计算\n var handleWidthPercent = 30; // 固定宽度30%\n\n // 应用手柄宽度\n this.handle.style.width = "".concat(handleWidthPercent, "%");\n }\n\n /**\n * 更新手柄位置\n */\n }, {\n key: "_updateHandlePosition",\n value: function _updateHandlePosition() {\n if (!this.handle) return;\n var handleContainer = this.handle.parentElement;\n if (!handleContainer) return;\n\n // 如果视频宽度不超过容器,居中显示手柄\n if (this.maxOffset <= 0) {\n // 居中手柄\n this.handle.style.left = \'50%\';\n this.handle.style.transform = \'translateX(-50%)\';\n return;\n }\n var containerWidth = handleContainer.offsetWidth;\n var handleWidth = this.handle.offsetWidth;\n\n // 计算手柄可移动的范围\n var handleMovableRange = containerWidth - handleWidth;\n\n // 视频偏移范围: [-maxOffset, maxOffset]\n // 手柄位置范围: [0, handleMovableRange]\n // 调整为反向移动:当视频偏移为最大负值时,手柄位置为最右侧,反之亦然\n var offsetRatio = 1 - (this.offset + this.maxOffset) / (2 * this.maxOffset);\n var handleLeftPx = offsetRatio * handleMovableRange;\n\n // 更新手柄位置 (使用百分比让布局更灵活)\n var handleLeftPercent = handleLeftPx / containerWidth * 100;\n\n // // 平滑过渡\n // if (!this.isHandleDragging) {\n // this.handle.style.transition = \'left 0.2s cubic-bezier(0.215, 0.61, 0.355, 1)\';\n // } else {\n // this.handle.style.transition = \'none\';\n // }\n\n this.handle.style.left = "".concat(handleLeftPercent, "%");\n this.handle.style.transform = \'\'; // 清除可能存在的transform\n }\n\n /**\n * 记录速度数据\n * @param {number} x - 当前x坐标\n */\n }, {\n key: "_trackVelocity",\n value: function _trackVelocity(x) {\n var now = Date.now();\n var tracker = this.velocityTracker;\n\n // 添加新位置记录\n tracker.positions.push({\n x: x,\n time: now\n });\n\n // 只保留最近100ms内的记录\n while (tracker.positions.length > 1 && now - tracker.positions[0].time > 100) {\n tracker.positions.shift();\n }\n\n // 计算当前速度 (像素/毫秒)\n if (tracker.positions.length > 1) {\n var first = tracker.positions[0];\n var last = tracker.positions[tracker.positions.length - 1];\n var deltaTime = last.time - first.time;\n if (deltaTime > 0) {\n tracker.currentVelocity = (last.x - first.x) / deltaTime;\n }\n }\n tracker.lastTimestamp = now;\n }\n\n /**\n * 应用惯性滚动\n */\n }, {\n key: "_applyInertia",\n value: function _applyInertia() {\n if (Math.abs(this.velocityTracker.currentVelocity) < 0.1) return;\n\n // 计算最终位置\n var velocity = this.velocityTracker.currentVelocity; // 像素/毫秒\n var deceleration = 0.002; // 减速率\n var distance = velocity * velocity / (2 * deceleration) * Math.sign(velocity);\n\n // 计算目标偏移量(考虑边界)\n var targetOffset = this.offset + distance;\n targetOffset = Math.max(-this.maxOffset, Math.min(targetOffset, this.maxOffset));\n\n // 计算动画持续时间(速度越快,时间越长)\n var duration = Math.min(Math.abs(velocity / deceleration) * 0.8,\n // 基于物理的持续时间\n 400 // 最大不超过400ms\n );\n\n // 开始动画\n this._animateTo(targetOffset, duration);\n }\n\n /**\n * 动画滚动到指定偏移量\n * @param {number} targetOffset - 目标偏移量\n * @param {number} duration - 动画持续时间(毫秒)\n */\n }, {\n key: "_animateTo",\n value: function _animateTo(targetOffset) {\n var _this2 = this;\n var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;\n // 取消可能正在进行的动画\n if (this.animation.active) {\n cancelAnimationFrame(this.animation.rafId);\n }\n\n // 更新动画状态\n this.animation.active = true;\n this.animation.targetOffset = targetOffset;\n this.animation.startTime = Date.now();\n this.animation.duration = duration;\n\n // 开始动画帧循环\n var _animate = function animate() {\n var now = Date.now();\n var elapsed = now - _this2.animation.startTime;\n if (elapsed >= duration) {\n // 动画结束\n _this2._applyOffset(targetOffset, false);\n _this2.animation.active = false;\n return;\n }\n\n // 使用easeOutCubic缓动函数计算当前位置\n var progress = 1 - Math.pow(1 - elapsed / duration, 3);\n var currentOffset = _this2.offset + (targetOffset - _this2.offset) * progress;\n _this2._applyOffset(currentOffset, false);\n _this2.animation.rafId = requestAnimationFrame(_animate);\n };\n this.animation.rafId = requestAnimationFrame(_animate);\n }\n\n /**\n * 处理指针按下事件 (视频元素)\n * @param {PointerEvent} e - 指针事件\n */\n }, {\n key: "_handlePointerDown",\n value: function _handlePointerDown(e) {\n // 如果视频宽度不超过容器,则不处理\n if (this.maxOffset <= 0) return;\n\n // 只处理主指针\n if (!e.isPrimary) return;\n\n // 停止可能正在进行的动画\n if (this.animation.active) {\n cancelAnimationFrame(this.animation.rafId);\n this.animation.active = false;\n }\n\n // 初始化拖动状态\n this.isDragging = true;\n this.startX = e.clientX;\n this.startOffset = this.offset;\n this.dragDistance = 0; // 重置拖动距离\n\n // 重置速度追踪器\n this.velocityTracker.positions = [];\n this.velocityTracker.lastTimestamp = Date.now();\n this.velocityTracker.currentVelocity = 0;\n\n // 记录初始位置\n this._trackVelocity(e.clientX);\n\n // 更新视觉状态\n this.video.style.cursor = \'grabbing\';\n this.video.style.transition = \'none\';\n\n // 如果支持指针捕获,捕获指针\n if (this.video.setPointerCapture) {\n this.video.setPointerCapture(e.pointerId);\n }\n\n // 添加事件监听\n this.video.addEventListener(\'pointermove\', this._pointerMoveHandler);\n this.video.addEventListener(\'pointerup\', this._pointerUpHandler);\n this.video.addEventListener(\'pointercancel\', this._pointerUpHandler);\n\n // 触觉反馈 (如果设备支持)\n if (window.navigator.vibrate) {\n window.navigator.vibrate(5);\n }\n\n // 阻止默认行为,如文本选择\n e.preventDefault();\n }\n\n /**\n * 处理指针移动事件 (视频元素)\n * @param {PointerEvent} e - 指针事件\n */\n }, {\n key: "_handlePointerMove",\n value: function _handlePointerMove(e) {\n if (!this.isDragging || !e.isPrimary) return;\n\n // 计算位移\n var deltaX = e.clientX - this.startX;\n this.dragDistance = Math.max(this.dragDistance, Math.abs(deltaX)); // 更新最大拖动距离\n\n var newOffset = Math.max(-this.maxOffset, Math.min(this.startOffset + deltaX, this.maxOffset));\n\n // 应用新偏移量\n this._applyOffset(newOffset, false);\n\n // 记录位置用于计算速度\n this._trackVelocity(e.clientX);\n\n // 阻止默认行为,如页面滚动\n e.preventDefault();\n }\n\n /**\n * 处理指针抬起/取消事件 (视频元素)\n * @param {PointerEvent} e - 指针事件\n */\n }, {\n key: "_handlePointerUp",\n value: function _handlePointerUp(e) {\n if (!this.isDragging || !e.isPrimary) return;\n\n // 更新状态\n this.isDragging = false;\n\n // 只有当拖动距离超过最小值时才设置拖动标记\n if (this.dragDistance > this.minDragDistance) {\n this.wasDragging = true;\n this.dragEndTimestamp = Date.now();\n } else {\n this.wasDragging = false;\n }\n\n // 释放指针捕获\n if (this.video.releasePointerCapture) {\n this.video.releasePointerCapture(e.pointerId);\n }\n\n // 移除事件监听\n this.video.removeEventListener(\'pointermove\', this._pointerMoveHandler);\n this.video.removeEventListener(\'pointerup\', this._pointerUpHandler);\n this.video.removeEventListener(\'pointercancel\', this._pointerUpHandler);\n\n // 恢复视觉状态\n this.video.style.cursor = \'grab\';\n\n // 应用惯性滚动\n this._applyInertia();\n\n // 阻止默认行为\n e.preventDefault();\n }\n\n /**\n * 处理手柄的指针按下事件\n * @param {PointerEvent} e - 指针事件\n */\n }, {\n key: "_handleHandlePointerDown",\n value: function _handleHandlePointerDown(e) {\n // 如果视频宽度不超过容器,则不处理\n if (this.maxOffset <= 0) return;\n\n // 只处理主指针\n if (!e.isPrimary) return;\n\n // 停止可能正在进行的动画\n if (this.animation.active) {\n cancelAnimationFrame(this.animation.rafId);\n this.animation.active = false;\n }\n\n // 初始化拖动状态\n this.isHandleDragging = true;\n this.startX = e.clientX;\n this.dragDistance = 0; // 重置拖动距离\n\n // 记录初始偏移和手柄位置\n this.startOffset = this.offset;\n var handleContainer = this.handle.parentElement;\n var containerWidth = handleContainer ? handleContainer.offsetWidth : 0;\n\n // 如果手柄容器有效,计算手柄位置比例\n if (containerWidth > 0) {\n var handleRect = this.handle.getBoundingClientRect();\n this.startHandleLeft = handleRect.left - handleContainer.getBoundingClientRect().left;\n this.startHandleLeftPercent = this.startHandleLeft / containerWidth * 100;\n } else {\n this.startHandleLeft = 0;\n this.startHandleLeftPercent = 0;\n }\n\n // 更新视觉状态\n this.handle.style.cursor = \'grabbing\';\n this.handle.style.transition = \'none\';\n\n // 如果支持指针捕获,捕获指针\n if (this.handle.setPointerCapture) {\n this.handle.setPointerCapture(e.pointerId);\n }\n\n // 添加事件监听\n this.handle.addEventListener(\'pointermove\', this._handlePointerMoveHandler);\n this.handle.addEventListener(\'pointerup\', this._handlePointerUpHandler);\n this.handle.addEventListener(\'pointercancel\', this._handlePointerUpHandler);\n\n // 触觉反馈 (如果设备支持)\n if (window.navigator.vibrate) {\n window.navigator.vibrate(5);\n }\n\n // 阻止默认行为\n e.preventDefault();\n }\n\n /**\n * 处理手柄的指针移动事件\n * @param {PointerEvent} e - 指针事件\n */\n }, {\n key: "_handleHandlePointerMove",\n value: function _handleHandlePointerMove(e) {\n if (!this.isHandleDragging || !e.isPrimary) return;\n var handleContainer = this.handle.parentElement;\n if (!handleContainer) return;\n var containerWidth = handleContainer.offsetWidth;\n var handleWidth = this.handle.offsetWidth;\n\n // 如果容器或手柄宽度无效,则不处理\n if (containerWidth <= 0 || handleWidth <= 0) return;\n\n // 计算位移\n var deltaX = e.clientX - this.startX;\n this.dragDistance = Math.max(this.dragDistance, Math.abs(deltaX)); // 更新最大拖动距离\n\n // 计算手柄新位置 (像素)\n var newHandleLeft = this.startHandleLeft + deltaX;\n\n // 限制手柄位置在容器范围内\n var maxHandleLeft = containerWidth - handleWidth;\n newHandleLeft = Math.max(0, Math.min(newHandleLeft, maxHandleLeft));\n\n // 记录位置用于计算手柄速度\n this._trackHandleVelocity(newHandleLeft);\n\n // 定义吸附位置和阈值\n var snapPositions = [0,\n // 左侧\n maxHandleLeft / 2,\n // 中间\n maxHandleLeft // 右侧\n ];\n var snapThreshold = 15; // 吸附阈值(像素)\n var didSnap = false;\n\n // 检查是否需要吸附\n for (var _i = 0, _snapPositions = snapPositions; _i < _snapPositions.length; _i++) {\n var snapPos = _snapPositions[_i];\n if (Math.abs(newHandleLeft - snapPos) < snapThreshold) {\n // 距离小于阈值,进行吸附\n newHandleLeft = snapPos;\n didSnap = true;\n\n // 如果设备支持触觉反馈且之前未吸附到此位置\n if (window.navigator.vibrate && (!this.lastSnapPosition || this.lastSnapPosition !== snapPos)) {\n window.navigator.vibrate(15); // 较强的震动表示吸附\n this.lastSnapPosition = snapPos;\n }\n break;\n }\n }\n\n // 如果未吸附,重置上次吸附位置记录\n if (!didSnap) {\n this.lastSnapPosition = null;\n }\n\n // 计算手柄位置百分比\n var newHandleLeftPercent = newHandleLeft / containerWidth * 100;\n\n // 应用手柄位置\n this.handle.style.left = "".concat(newHandleLeftPercent, "%");\n\n // 将手柄位置映射回视频偏移 - 反向移动\n // 手柄位置范围: [0, maxHandleLeft]\n // 视频偏移范围: [-this.maxOffset, this.maxOffset]\n var handleRatio = maxHandleLeft > 0 ? newHandleLeft / maxHandleLeft : 0; // 0 到 1, 避免除零\n // 改为反向映射 (1 - handleRatio) 来反转方向\n var newOffset = (1 - handleRatio) * 2 * this.maxOffset - this.maxOffset;\n\n // 应用视频偏移\n this.video.style.transform = "translateX(".concat(newOffset, "px)");\n this.video.style.transition = \'none\';\n this.offset = newOffset;\n\n // 阻止默认行为\n e.preventDefault();\n }\n\n /**\n * 处理手柄的指针抬起/取消事件\n * @param {PointerEvent} e - 指针事件\n */\n }, {\n key: "_handleHandlePointerUp",\n value: function _handleHandlePointerUp(e) {\n if (!this.isHandleDragging || !e.isPrimary) return;\n\n // 更新状态\n this.isHandleDragging = false;\n\n // 只有当拖动距离超过最小值时才设置拖动标记\n if (this.dragDistance > this.minDragDistance) {\n this.wasDragging = true;\n this.dragEndTimestamp = Date.now();\n } else {\n this.wasDragging = false;\n }\n\n // 重置上次吸附位置记录,以便下次拖动时能正确触发震动\n this.lastSnapPosition = null;\n\n // 释放指针捕获\n if (this.handle.releasePointerCapture) {\n this.handle.releasePointerCapture(e.pointerId);\n }\n\n // 移除事件监听\n this.handle.removeEventListener(\'pointermove\', this._handlePointerMoveHandler);\n this.handle.removeEventListener(\'pointerup\', this._handlePointerUpHandler);\n this.handle.removeEventListener(\'pointercancel\', this._handlePointerUpHandler);\n\n // 恢复视觉状态\n this.handle.style.cursor = \'grab\';\n\n // 应用手柄惯性\n this._applyHandleInertia();\n\n // 阻止默认行为\n e.preventDefault();\n }\n\n /**\n * 记录手柄速度数据\n * @param {number} position - 当前手柄位置\n */\n }, {\n key: "_trackHandleVelocity",\n value: function _trackHandleVelocity(position) {\n var now = Date.now();\n var tracker = this.handleVelocityTracker;\n\n // 添加新位置记录\n tracker.positions.push({\n position: position,\n time: now\n });\n\n // 只保留最近100ms内的记录\n while (tracker.positions.length > 1 && now - tracker.positions[0].time > 100) {\n tracker.positions.shift();\n }\n\n // 计算当前速度 (像素/毫秒)\n if (tracker.positions.length > 1) {\n var first = tracker.positions[0];\n var last = tracker.positions[tracker.positions.length - 1];\n var deltaTime = last.time - first.time;\n if (deltaTime > 0) {\n tracker.currentVelocity = (last.position - first.position) / deltaTime;\n }\n }\n tracker.lastTimestamp = now;\n }\n\n /**\n * 应用手柄惯性滚动\n */\n }, {\n key: "_applyHandleInertia",\n value: function _applyHandleInertia() {\n if (Math.abs(this.handleVelocityTracker.currentVelocity) < 0.1) return;\n var handleContainer = this.handle.parentElement;\n if (!handleContainer) return;\n var containerWidth = handleContainer.offsetWidth;\n var handleWidth = this.handle.offsetWidth;\n var maxHandleLeft = containerWidth - handleWidth;\n\n // 获取当前手柄位置(像素)\n var handleRect = this.handle.getBoundingClientRect();\n var containerRect = handleContainer.getBoundingClientRect();\n var currentHandleLeft = handleRect.left - containerRect.left;\n\n // 计算最终位置\n var velocity = this.handleVelocityTracker.currentVelocity; // 像素/毫秒\n var deceleration = 0.002; // 减速率\n var distance = velocity * velocity / (2 * deceleration) * Math.sign(velocity);\n\n // 计算目标手柄位置(考虑边界)\n var targetHandleLeft = currentHandleLeft + distance;\n targetHandleLeft = Math.max(0, Math.min(targetHandleLeft, maxHandleLeft));\n\n // 检查最终位置是否需要吸附\n var snapPositions = [0,\n // 左侧\n maxHandleLeft / 2,\n // 中间\n maxHandleLeft // 右侧\n ];\n var snapThreshold = 30; // 惯性滚动的吸附阈值更大\n\n // 寻找最近的吸附点\n var closestSnapPos = targetHandleLeft;\n var minDistance = Number.MAX_VALUE;\n for (var _i2 = 0, _snapPositions2 = snapPositions; _i2 < _snapPositions2.length; _i2++) {\n var snapPos = _snapPositions2[_i2];\n var _distance = Math.abs(targetHandleLeft - snapPos);\n if (_distance < snapThreshold && _distance < minDistance) {\n closestSnapPos = snapPos;\n minDistance = _distance;\n }\n }\n\n // 应用吸附\n if (minDistance < Number.MAX_VALUE) {\n targetHandleLeft = closestSnapPos;\n }\n\n // 计算手柄位置百分比\n var targetHandleLeftPercent = targetHandleLeft / containerWidth * 100;\n\n // 计算对应的视频偏移量 - 反向映射\n var handleRatio = maxHandleLeft > 0 ? targetHandleLeft / maxHandleLeft : 0;\n var targetOffset = (1 - handleRatio) * 2 * this.maxOffset - this.maxOffset;\n\n // 设置过渡效果\n this.handle.style.transition = \'left 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)\';\n this.video.style.transition = \'transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)\';\n\n // 应用最终位置\n this.handle.style.left = "".concat(targetHandleLeftPercent, "%");\n this.video.style.transform = "translateX(".concat(targetOffset, "px)");\n this.offset = targetOffset;\n\n // 触觉反馈 (如果设备支持且吸附到某个位置)\n if (minDistance < Number.MAX_VALUE && window.navigator.vibrate) {\n window.navigator.vibrate(10);\n }\n\n // 重置速度追踪器\n this.handleVelocityTracker.positions = [];\n this.handleVelocityTracker.currentVelocity = 0;\n }\n\n /**\n * 设置视频偏移量\n * @param {number} offset - 要设置的偏移量\n * @param {boolean} animate - 是否使用动画过渡\n */\n }, {\n key: "setOffset",\n value: function setOffset(offset) {\n var animate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n return this._applyOffset(offset, animate);\n }\n\n /**\n * 重置管理器到初始状态\n * @param {boolean} animate - 是否使用动画\n * @returns {VideoSwipeManager} 当前实例,支持链式调用\n */\n }, {\n key: "reset",\n value: function reset() {\n var animate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n this._applyOffset(0, animate);\n this.wasDragging = false; // 重置拖动标记\n return this;\n }\n\n /**\n * 更新尺寸和约束\n * @returns {VideoSwipeManager} 当前实例,支持链式调用\n */\n }, {\n key: "updateSize",\n value: function updateSize() {\n // 强制获取视频和容器的最新尺寸\n if (this.video && this.container) {\n // 输出诊断信息\n var videoRect = this.video.getBoundingClientRect();\n var containerRect = this.container.getBoundingClientRect();\n // 更新约束\n var result = this._updateConstraints();\n } else {}\n return this;\n }\n\n /**\n * 销毁管理器并清理资源\n */\n }, {\n key: "destroy",\n value: function destroy() {\n // 移除事件监听\n if (this.video) {\n this.video.removeEventListener(\'pointerdown\', this._pointerDownHandler);\n this.video.style.transform = \'\';\n this.video.style.willChange = \'\';\n this.video.style.transition = \'\';\n this.video.style.cursor = \'\';\n }\n if (this.handle) {\n this.handle.removeEventListener(\'pointerdown\', this._handlePointerDownHandler);\n this.handle.style.willChange = \'\';\n this.handle.style.transition = \'\';\n this.handle.style.left = \'\';\n this.handle.style.width = \'\';\n this.handle.style.cursor = \'\';\n }\n\n // 取消可能正在进行的动画\n if (this.animation.active) {\n cancelAnimationFrame(this.animation.rafId);\n this.animation.active = false;\n }\n\n // 重置标记\n this.wasDragging = false;\n }\n\n /**\n * 检查是否刚完成拖动操作\n * @param {number} threshold - 时间阈值(毫秒)\n * @returns {boolean} 是否刚完成拖动\n */\n }, {\n key: "wasRecentlyDragging",\n value: function wasRecentlyDragging() {\n var threshold = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 150;\n if (!this.wasDragging) return false;\n var timeSinceDragEnd = Date.now() - this.dragEndTimestamp;\n\n // 如果超过阈值,重置标记\n if (timeSinceDragEnd > threshold) {\n this.wasDragging = false;\n return false;\n }\n return true;\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/managers/videoSwipeManager.js?');
},
"./src/player/state/PlayerState.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PlayerState: () => (/* binding */ PlayerState)\n/* harmony export */ });\n/* harmony import */ var _utils_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/utils.js */ "./src/utils/utils.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n\n\n/**\r\n * 播放器状态管理类\r\n */\nvar PlayerState = /*#__PURE__*/function () {\n function PlayerState() {\n _classCallCheck(this, PlayerState);\n // 播放器设置\n this.settings = {\n showSeekControlRow: true,\n // 显示快进快退控制行\n showLoopControlRow: true,\n // 显示循环控制行\n showPlaybackControlRow: true // 显示播放控制行\n };\n\n // 添加存储方法\n this._setupStorageMethods();\n }\n\n /**\r\n * 设置存储方法\r\n * @private\r\n */\n return _createClass(PlayerState, [{\n key: "_setupStorageMethods",\n value: function _setupStorageMethods() {\n // 检查是否有油猴API可用\n this.hasGMAPI = typeof GM_getValue === \'function\' && typeof GM_setValue === \'function\';\n }\n\n /**\r\n * 安全获取存储的值\r\n * @param {string} key - 键名\r\n * @param {any} defaultValue - 默认值\r\n * @returns {any} - 存储的值或默认值\r\n */\n }, {\n key: "getValue",\n value: function getValue(key, defaultValue) {\n try {\n if (this.hasGMAPI) {\n return GM_getValue(key, defaultValue);\n } else {\n var value = localStorage.getItem("missNoAD_".concat(key));\n return value !== null ? JSON.parse(value) : defaultValue;\n }\n } catch (e) {\n return defaultValue;\n }\n }\n\n /**\r\n * 安全存储值\r\n * @param {string} key - 键名\r\n * @param {any} value - 要存储的值\r\n * @returns {boolean} - 是否成功存储\r\n */\n }, {\n key: "setValue",\n value: function setValue(key, value) {\n try {\n if (this.hasGMAPI) {\n GM_setValue(key, value);\n return true;\n } else {\n localStorage.setItem("missNoAD_".concat(key), JSON.stringify(value));\n return true;\n }\n } catch (e) {\n return false;\n }\n }\n\n /**\r\n * 加载保存的设置\r\n */\n }, {\n key: "loadSettings",\n value: function loadSettings() {\n try {\n this.settings.showSeekControlRow = this.getValue(\'showSeekControlRow\', true);\n this.settings.showLoopControlRow = this.getValue(\'showLoopControlRow\', true);\n this.settings.showPlaybackControlRow = this.getValue(\'showPlaybackControlRow\', true);\n } catch (error) {}\n }\n\n /**\r\n * 保存设置\r\n */\n }, {\n key: "saveSettings",\n value: function saveSettings() {\n try {\n this.setValue(\'showSeekControlRow\', this.settings.showSeekControlRow);\n this.setValue(\'showLoopControlRow\', this.settings.showLoopControlRow);\n this.setValue(\'showPlaybackControlRow\', this.settings.showPlaybackControlRow);\n } catch (error) {}\n }\n\n /**\r\n * 更新设置\r\n * @param {string} key - 设置键名\r\n * @param {any} value - 设置值\r\n */\n }, {\n key: "updateSetting",\n value: function updateSetting(key, value) {\n if (key in this.settings) {\n this.settings[key] = value;\n this.saveSettings();\n }\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/state/PlayerState.js?');
},
"./src/player/ui/FloatingButton.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ FloatingButton: () => (/* binding */ FloatingButton)\n/* harmony export */ });\n/* harmony import */ var _utils_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/utils.js */ "./src/utils/utils.js");\n/* harmony import */ var _index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../index.js */ "./src/player/index.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n\n\n\n/**\n * 浮动按钮类\n */\nvar FloatingButton = /*#__PURE__*/function () {\n function FloatingButton() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _classCallCheck(this, FloatingButton);\n this.button = null;\n this.videoPlayer = null;\n this.resizeTimeout = null;\n this.playerState = options.playerState || null;\n this.videoCheckInterval = null;\n this.mutationObserver = null;\n }\n\n /**\n * 初始化浮动按钮\n */\n return _createClass(FloatingButton, [{\n key: "init",\n value: function init() {\n // 清理可能存在的旧按钮\n this.cleanupExistingButtons();\n\n // 检查页面是否存在视频元素\n if (_utils_utils_js__WEBPACK_IMPORTED_MODULE_0__.Utils.findVideoElement()) {\n // 创建新按钮\n this.createButton();\n\n // 监听窗口大小变化,更新按钮位置\n window.addEventListener(\'resize\', this.handleResize.bind(this));\n\n // 监听屏幕方向变化\n window.matchMedia("(orientation: portrait)").addEventListener("change", this.handleResize.bind(this));\n\n // 监听DOM变化,处理视频元素的动态添加/移除\n this.setupMutationObserver();\n } else {\n // 开始周期性检查视频元素\n this.startVideoElementCheck();\n\n // 监听DOM变化,处理视频元素的动态添加\n this.setupMutationObserver();\n }\n }\n\n /**\n * 设置MutationObserver监听DOM变化\n */\n }, {\n key: "setupMutationObserver",\n value: function setupMutationObserver() {\n // 清理可能存在的旧观察者\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n }\n\n // 创建新的观察者\n this.mutationObserver = new MutationObserver(this.handleDomMutations.bind(this));\n\n // 开始观察整个文档的变化\n this.mutationObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n }\n\n /**\n * 处理DOM变化\n */\n }, {\n key: "handleDomMutations",\n value: function handleDomMutations() {\n var _this = this;\n // 使用防抖函数限制调用频率\n if (this.mutationTimeout) clearTimeout(this.mutationTimeout);\n this.mutationTimeout = setTimeout(function () {\n var hasVideo = _utils_utils_js__WEBPACK_IMPORTED_MODULE_0__.Utils.findVideoElement();\n\n // 如果有视频元素但没有按钮,创建按钮\n if (hasVideo && !_this.button) {\n _this.createButton();\n\n // 监听窗口大小变化,更新按钮位置\n window.addEventListener(\'resize\', _this.handleResize.bind(_this));\n\n // 监听屏幕方向变化\n window.matchMedia("(orientation: portrait)").addEventListener("change", _this.handleResize.bind(_this));\n }\n // 如果有按钮但没有视频元素,隐藏按钮\n else if (!hasVideo && _this.button) {\n _this.button.style.display = \'none\';\n }\n // 如果有视频元素且有按钮,确保按钮显示\n else if (hasVideo && _this.button && _this.button.style.display === \'none\') {\n _this.button.style.display = \'flex\';\n }\n }, 300);\n }\n\n /**\n * 开始周期性检查视频元素\n * 针对动态加载视频的网站,可能初始加载时没有视频,但后续会加载\n */\n }, {\n key: "startVideoElementCheck",\n value: function startVideoElementCheck() {\n var _this2 = this;\n // 清除可能存在的旧计时器\n if (this.videoCheckInterval) {\n clearInterval(this.videoCheckInterval);\n }\n\n // 设置新计时器,每2秒检查一次\n this.videoCheckInterval = setInterval(function () {\n if (_utils_utils_js__WEBPACK_IMPORTED_MODULE_0__.Utils.findVideoElement()) {\n // 只有当按钮不存在时才创建\n if (!_this2.button) {\n // 找到视频元素,创建按钮\n _this2.createButton();\n\n // 监听窗口大小变化,更新按钮位置\n window.addEventListener(\'resize\', _this2.handleResize.bind(_this2));\n\n // 监听屏幕方向变化\n window.matchMedia("(orientation: portrait)").addEventListener("change", _this2.handleResize.bind(_this2));\n } else if (_this2.button.style.display === \'none\') {\n // 按钮存在但被隐藏,重新显示\n _this2.button.style.display = \'flex\';\n }\n\n // 停止检查\n clearInterval(_this2.videoCheckInterval);\n _this2.videoCheckInterval = null;\n }\n }, 2000);\n }\n\n /**\n * 清理可能存在的旧浮动按钮\n */\n }, {\n key: "cleanupExistingButtons",\n value: function cleanupExistingButtons() {\n // 查找所有现有的浮动按钮\n var existingButtons = document.querySelectorAll(\'.tm-floating-button\');\n if (existingButtons.length > 0) {\n existingButtons.forEach(function (button) {\n if (button && button.parentNode) {\n button.parentNode.removeChild(button);\n }\n });\n }\n }\n\n /**\n * 处理窗口大小变化\n */\n }, {\n key: "handleResize",\n value: function handleResize() {\n var _this3 = this;\n // 使用节流函数限制调用频率\n if (this.resizeTimeout) clearTimeout(this.resizeTimeout);\n this.resizeTimeout = setTimeout(function () {\n // 检查页面是否存在视频元素\n if (_utils_utils_js__WEBPACK_IMPORTED_MODULE_0__.Utils.findVideoElement()) {\n // 无论横屏还是竖屏都显示按钮\n _this3.button.style.display = \'flex\';\n\n // 更新按钮位置\n _this3.updateButtonPosition();\n } else {\n // 没有视频元素,隐藏按钮\n if (_this3.button) _this3.button.style.display = \'none\';\n }\n }, 200);\n }\n\n /**\n * 创建浮动按钮\n */\n }, {\n key: "createButton",\n value: function createButton() {\n var _this4 = this;\n // 创建浮动按钮 - 使用CSS类而不是内联样式\n this.button = _utils_utils_js__WEBPACK_IMPORTED_MODULE_0__.Utils.createElementWithStyle(\'button\', \'tm-floating-button\');\n\n // 使用更简洁的播放按钮SVG图标\n var icon = "\\n <svg width=\\"48\\" height=\\"48\\" viewBox=\\"0 0 68 48\\" fill=\\"none\\">\\n <path class=\\"tm-play-button-bg\\" d=\\"M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z\\" fill=\\"rgb(254, 98, 142)\\"></path>\\n <path d=\\"M 45,24 27,14 27,34\\" fill=\\"#fff\\"></path>\\n </svg>\\n ";\n this.button.innerHTML = icon;\n\n // 添加点击事件处理器\n this.button.addEventListener(\'click\', function () {\n _this4.handleButtonClick();\n });\n\n // 显示按钮\n this.button.style.display = \'flex\';\n\n // 添加到文档\n document.body.appendChild(this.button);\n\n // 初始位置\n this.updateButtonPosition();\n return this.button;\n }\n\n /**\n * 更新按钮位置,考虑安全区域和屏幕方向\n */\n }, {\n key: "updateButtonPosition",\n value: function updateButtonPosition() {\n if (!this.button) return;\n var safeArea = _utils_utils_js__WEBPACK_IMPORTED_MODULE_0__.Utils.getSafeAreaInsets();\n\n // 获取当前屏幕方向\n var isPortrait = _utils_utils_js__WEBPACK_IMPORTED_MODULE_0__.Utils.isPortrait();\n if (isPortrait) {\n // 竖屏模式 - 按钮在底部居中\n this.button.style.bottom = "".concat(Math.max(20, safeArea.bottom), "px");\n this.button.style.right = \'auto\';\n this.button.style.left = \'50%\';\n // 重置transform以保持hover和active效果正常\n this.button.style.transform = \'translateX(-50%)\';\n } else {\n // 横屏模式 - 按钮在右下角且加大安全距离\n this.button.style.bottom = "".concat(Math.max(20, safeArea.bottom + 10), "px");\n this.button.style.right = "".concat(Math.max(20, safeArea.right + 10), "px");\n this.button.style.left = \'auto\';\n // 重置transform以保持hover和active效果正常\n this.button.style.transform = \'translateX(0)\';\n }\n\n // 确保z-index始终正确设置,防止在屏幕旋转时被覆盖\n this.button.style.zIndex = \'9980\';\n }\n\n /**\n * 处理按钮点击\n */\n }, {\n key: "handleButtonClick",\n value: function handleButtonClick() {\n // 隐藏按钮\n this.button.style.display = \'none\';\n\n // 每次点击都创建新的视频播放器实例\n this.videoPlayer = new _index_js__WEBPACK_IMPORTED_MODULE_1__.CustomVideoPlayer({\n playerState: this.playerState,\n callingButton: this.button // 确保传递按钮引用\n });\n\n // 初始化播放器\n this.videoPlayer.init();\n }\n\n /**\n * 移除浮动按钮\n */\n }, {\n key: "remove",\n value: function remove() {\n if (this.button && this.button.parentNode) {\n this.button.parentNode.removeChild(this.button);\n }\n\n // 移除事件监听器\n window.removeEventListener(\'resize\', this.handleResize);\n\n // 清除计时器\n if (this.videoCheckInterval) {\n clearInterval(this.videoCheckInterval);\n this.videoCheckInterval = null;\n }\n\n // 断开MutationObserver\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = null;\n }\n\n // 清除引用\n this.button = null;\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/ui/FloatingButton.js?');
},
"./src/player/ui/UIManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ UIManager: () => (/* binding */ UIManager)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * UI管理器类 - 负责创建和管理播放器UI元素\n */\nvar UIManager = /*#__PURE__*/function () {\n function UIManager(playerCore) {\n _classCallCheck(this, UIManager);\n // 核心播放器引用\n this.playerCore = playerCore;\n this.targetVideo = playerCore.targetVideo;\n\n // UI 元素引用\n this.overlay = null; // 背景遮罩\n this.container = null; // 主容器\n this.playerContainer = null; // 播放器容器\n this.videoWrapper = null; // 视频包装器\n this.handleContainer = null; // 句柄容器\n this.handle = null; // 句柄元素\n this.closeBtn = null; // 关闭按钮\n this.settingsBtn = null; // 设置按钮\n this.settingsPanel = null; // 设置面板\n this.buttonContainer = null; // 按钮容器\n\n // 窗口和安全区\n this.safeArea = {\n top: 44,\n bottom: 34\n }; // 默认安全区域值\n\n // 屏幕方向状态\n this.isLandscape = false;\n\n // 控制界面状态\n this.controlsVisible = true;\n this.controlsHideTimeout = null;\n this.isMouseOverControls = false; // 鼠标是否在控制面板上\n\n // 导入样式\n this.loadStyles();\n }\n\n /**\n * 加载所需的样式文件\n */\n return _createClass(UIManager, [{\n key: \"loadStyles\",\n value: function loadStyles() {}\n\n /**\n * 创建UI界面\n */\n }, {\n key: \"createUI\",\n value: function createUI() {\n // 创建遮罩和视频容器\n this.createOverlayAndContainer();\n\n // 创建播放器容器\n this.createPlayerContainer();\n\n // 创建视频包装器\n this.createVideoWrapper();\n\n // 创建调整手柄\n this.createResizeHandle();\n\n // 创建关闭按钮\n this.createCloseButton();\n\n // 创建设置按钮\n this.createSettingsButton();\n\n // 创建按钮容器\n this.createButtonContainer();\n\n // 创建设置面板\n this.createSettingsPanel();\n\n // 添加屏幕方向变化监听(只设置window事件,overlay相关事件在组装DOM后设置)\n this.setupOrientationListener();\n return {\n overlay: this.overlay,\n container: this.container,\n playerContainer: this.playerContainer,\n videoWrapper: this.videoWrapper,\n handleContainer: this.handleContainer,\n handle: this.handle,\n closeBtn: this.closeBtn,\n settingsBtn: this.settingsBtn,\n settingsPanel: this.settingsPanel,\n buttonContainer: this.buttonContainer\n };\n }\n\n /**\n * 创建遮罩和容器\n */\n }, {\n key: \"createOverlayAndContainer\",\n value: function createOverlayAndContainer() {\n // 创建遮罩层 - 使用预定义样式类\n this.overlay = document.createElement('div');\n this.overlay.className = 'tm-video-overlay';\n\n // 显式设置z-index,确保在任何情况下都高于浮动按钮\n this.overlay.style.zIndex = '9990';\n\n // 不再手动添加paddingTop和paddingBottom,使用CSS的safe-area-inset变量\n\n // 计算默认高度和最小高度\n var defaultHeight = window.innerWidth * (4 / 5);\n var defaultMinHeight = window.innerWidth * (9 / 16); // 默认16:9比例\n\n // 创建视频容器 - 使用预定义样式类\n this.container = document.createElement('div');\n this.container.className = 'tm-video-container';\n this.container.style.height = \"\".concat(defaultHeight, \"px\");\n this.container.style.minHeight = \"\".concat(defaultMinHeight, \"px\");\n }\n\n /**\n * 创建播放器容器\n */\n }, {\n key: \"createPlayerContainer\",\n value: function createPlayerContainer() {\n this.playerContainer = document.createElement('div');\n this.playerContainer.className = 'tm-player-container';\n }\n\n /**\n * 创建视频包装器\n */\n }, {\n key: \"createVideoWrapper\",\n value: function createVideoWrapper() {\n var _this = this;\n this.videoWrapper = document.createElement('div');\n this.videoWrapper.className = 'tm-video-wrapper';\n\n // 如果已经存在视频元素,先从父节点移除\n if (this.targetVideo && this.targetVideo.parentNode) {\n this.targetVideo.parentNode.removeChild(this.targetVideo);\n }\n\n // 禁用原生视频控件\n this.targetVideo.controls = false;\n\n // 添加视频到包装器\n this.videoWrapper.appendChild(this.targetVideo);\n\n // 添加视频元数据加载事件,用于检测视频比例\n this.targetVideo.addEventListener('loadedmetadata', function () {\n _this.updateVideoAspectRatio();\n });\n\n // 长按检测变量\n var longPressTimer = null;\n var isLongPress = false;\n var originalPlaybackRate = 1.0;\n\n // 鼠标/触摸按下事件 - 开始检测长按\n var handlePointerDown = function handlePointerDown(e) {\n // 确保点击事件不是从控制按钮冒泡上来的\n if (e.target.closest('.tm-control-buttons, .tm-button-container, .tm-control-button, .tm-close-button, .tm-settings-button')) {\n return;\n }\n\n // 清除可能存在的定时器\n if (longPressTimer) {\n clearTimeout(longPressTimer);\n }\n\n // 记录原始播放速度\n originalPlaybackRate = _this.playerCore.targetVideo.playbackRate;\n isLongPress = false;\n\n // 设置长按定时器 (3秒)\n longPressTimer = setTimeout(function () {\n // 触发长按事件\n isLongPress = true;\n // 保存当前播放速度\n originalPlaybackRate = _this.playerCore.targetVideo.playbackRate;\n // 设置为3倍速\n _this.playerCore.targetVideo.playbackRate = 3.0;\n\n // 添加视觉提示\n var speedIndicator = document.createElement('div');\n speedIndicator.className = 'tm-speed-indicator';\n speedIndicator.textContent = '3x';\n speedIndicator.style.position = 'absolute';\n speedIndicator.style.top = '50%';\n speedIndicator.style.left = '50%';\n speedIndicator.style.transform = 'translate(-50%, -50%)';\n speedIndicator.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';\n speedIndicator.style.color = 'white';\n speedIndicator.style.padding = '8px 16px';\n speedIndicator.style.borderRadius = '4px';\n speedIndicator.style.fontSize = '24px';\n speedIndicator.style.fontWeight = 'bold';\n speedIndicator.style.zIndex = '9999';\n _this.videoWrapper.appendChild(speedIndicator);\n\n // 触觉反馈\n if (window.navigator.vibrate) {\n window.navigator.vibrate(50);\n }\n\n // 如果视频当前是暂停的,开始播放\n if (_this.playerCore.targetVideo.paused) {\n _this.playerCore.targetVideo.play();\n }\n }, 800); // 800ms的长按时间,减少等待感\n };\n\n // 鼠标/触摸释放事件 - 结束长按\n var handlePointerUp = function handlePointerUp(e) {\n // 清除长按定时器\n if (longPressTimer) {\n clearTimeout(longPressTimer);\n longPressTimer = null;\n }\n\n // 如果是长按状态,恢复原始播放速度并阻止冒泡\n if (isLongPress) {\n // 恢复原始播放速度\n _this.playerCore.targetVideo.playbackRate = originalPlaybackRate;\n\n // 移除速度指示器\n var speedIndicator = _this.videoWrapper.querySelector('.tm-speed-indicator');\n if (speedIndicator) {\n speedIndicator.remove();\n }\n\n // 防止触发点击事件\n e.preventDefault();\n e.stopPropagation();\n isLongPress = false;\n return;\n }\n };\n\n // 鼠标/触摸移动离开事件 - 结束长按\n var handlePointerLeave = function handlePointerLeave(e) {\n // 在鼠标/触摸离开视频区域时也要清除长按\n if (longPressTimer) {\n clearTimeout(longPressTimer);\n longPressTimer = null;\n }\n\n // 如果是长按状态,恢复原始播放速度\n if (isLongPress) {\n _this.playerCore.targetVideo.playbackRate = originalPlaybackRate;\n\n // 移除速度指示器\n var speedIndicator = _this.videoWrapper.querySelector('.tm-speed-indicator');\n if (speedIndicator) {\n speedIndicator.remove();\n }\n isLongPress = false;\n }\n };\n\n // 添加鼠标事件监听\n this.videoWrapper.addEventListener('mousedown', handlePointerDown);\n this.videoWrapper.addEventListener('mouseup', handlePointerUp);\n this.videoWrapper.addEventListener('mouseleave', handlePointerLeave);\n\n // 添加触摸事件监听\n this.videoWrapper.addEventListener('touchstart', handlePointerDown, {\n passive: true\n });\n this.videoWrapper.addEventListener('touchend', handlePointerUp);\n this.videoWrapper.addEventListener('touchcancel', handlePointerLeave);\n\n // 添加点击事件用于显示/隐藏控制界面(横竖屏均有效)\n this.videoWrapper.addEventListener('click', function (e) {\n // 如果是长按触发的,不执行点击操作\n if (isLongPress) {\n return;\n }\n\n // 确保点击事件不是从控制按钮冒泡上来的\n if (e.target.closest('.tm-control-buttons, .tm-button-container, .tm-control-button, .tm-close-button, .tm-settings-button')) {\n return;\n }\n\n // 播放/暂停切换函数\n var togglePlayPause = function togglePlayPause() {\n if (!_this.playerCore.targetVideo) return;\n if (_this.playerCore.targetVideo.paused) {\n _this.playerCore.targetVideo.play();\n } else {\n _this.playerCore.targetVideo.pause();\n if (_this.playerCore.controlManager) {\n _this.playerCore.controlManager.showPauseIndicator();\n }\n }\n if (_this.playerCore.controlManager) {\n _this.playerCore.controlManager.updatePlayPauseButton();\n }\n };\n if (_this.isLandscape) {\n // 横屏模式下,如果控制界面当前是隐藏状态,则只显示控制界面而不触发暂停\n if (!_this.controlsVisible) {\n _this.showControls();\n _this.autoHideControls();\n return;\n }\n\n // 横屏模式下,如果控制界面已显示,则切换播放/暂停状态\n togglePlayPause();\n } else {\n // 竖屏模式下,直接触发暂停/播放功能\n togglePlayPause();\n }\n });\n }\n\n /**\n * 创建拖动调整手柄\n */\n }, {\n key: \"createResizeHandle\",\n value: function createResizeHandle() {\n var _this2 = this;\n // 创建手柄容器\n this.handleContainer = document.createElement('div');\n this.handleContainer.className = 'tm-handle-container';\n\n // 创建手柄\n this.handle = document.createElement('div');\n this.handle.className = 'tm-resize-handle';\n\n // 添加透明的更大点击区域\n this.handle.insertAdjacentHTML('beforeend', \"\\n <div style=\\\"\\n position: absolute;\\n left: -10px;\\n right: -10px;\\n top: -15px;\\n bottom: -15px;\\n background: transparent;\\n \\\"></div>\\n \");\n\n // 悬停效果\n this.handle.addEventListener('mouseenter', function () {\n _this2.handle.style.opacity = '1';\n _this2.handle.style.backgroundColor = 'hsla(var(--shadcn-foreground) / 0.8)';\n });\n this.handle.addEventListener('mouseleave', function () {\n if (!_this2.isDraggingHandle) {\n _this2.handle.style.opacity = '0.5';\n _this2.handle.style.backgroundColor = 'hsla(var(--shadcn-foreground) / 0.6)';\n }\n });\n\n // 添加拖动时的 grabbing 光标\n this.handle.addEventListener('mousedown', function () {\n _this2.handle.style.cursor = 'grabbing';\n // 添加震动反馈\n if (window.navigator.vibrate) {\n window.navigator.vibrate(5);\n }\n });\n\n // 鼠标松开或移出手柄时恢复 grab\n document.addEventListener('mouseup', function () {\n if (!_this2.isDraggingHandle) {\n _this2.handle.style.cursor = 'grab';\n }\n });\n\n // 添加触摸事件处理\n this.handle.addEventListener('touchstart', function () {\n _this2.handle.style.opacity = '1';\n _this2.handle.style.backgroundColor = 'hsla(var(--shadcn-foreground) / 0.8)';\n // 添加震动反馈\n if (window.navigator.vibrate) {\n window.navigator.vibrate(5);\n }\n }, {\n passive: true\n });\n this.handle.addEventListener('touchend', function () {\n if (!_this2.isDraggingHandle) {\n _this2.handle.style.opacity = '0.5';\n _this2.handle.style.backgroundColor = 'hsla(var(--shadcn-foreground) / 0.6)';\n }\n });\n\n // 将手柄添加到其容器中\n this.handleContainer.appendChild(this.handle);\n }\n\n /**\n * 创建关闭按钮\n */\n }, {\n key: \"createCloseButton\",\n value: function createCloseButton() {\n var _this3 = this;\n this.closeBtn = document.createElement('button');\n this.closeBtn.className = 'tm-close-button tm-control-button-base';\n\n // 现代化的关闭图标\n var closeIcon = \"\\n <svg width=\\\"20\\\" height=\\\"20\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M18 6L6 18M6 6L18 18\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\\n \";\n this.closeBtn.innerHTML = closeIcon;\n\n // 添加悬停效果\n this.closeBtn.addEventListener('mouseenter', function () {\n _this3.closeBtn.style.backgroundColor = 'hsla(var(--shadcn-destructive) / 0.9)';\n _this3.closeBtn.style.transform = 'scale(1.1)';\n });\n this.closeBtn.addEventListener('mouseleave', function () {\n _this3.closeBtn.style.backgroundColor = 'hsla(var(--shadcn-background) / 0.7)';\n _this3.closeBtn.style.transform = 'scale(1)';\n });\n }\n\n /**\n * 创建设置按钮\n */\n }, {\n key: \"createSettingsButton\",\n value: function createSettingsButton() {\n var _this4 = this;\n this.settingsBtn = document.createElement('button');\n this.settingsBtn.className = 'tm-settings-button tm-control-button-base';\n\n // 现代化的设置图标\n var settingsIcon = \"\\n <svg width=\\\"20\\\" height=\\\"20\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n <path d=\\\"M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n <path d=\\\"M19.4 15C19.1277 15.6171 19.2583 16.3378 19.73 16.82L19.79 16.88C20.1837 17.2737 20.4009 17.7994 20.4009 18.345C20.4009 18.8906 20.1837 19.4163 19.79 19.81C19.4163 20.2037 18.8906 20.4209 18.345 20.4209C17.7994 20.4209 17.2737 20.2037 16.91 19.81L16.85 19.75C16.3678 19.2783 15.6471 19.1477 15.03 19.42C14.4301 19.6801 14.0386 20.2502 14.03 20.89V21C14.03 21.5304 13.8193 22.0391 13.4442 22.4142C13.0691 22.7893 12.5604 23 12.03 23C11.4996 23 10.9909 22.7893 10.6158 22.4142C10.2407 22.0391 10.03 21.5304 10.03 21V20.91C10.0112 20.2556 9.5979 19.6818 8.98 19.43C8.36289 19.1577 7.64221 19.2883 7.16 19.76L7.1 19.82C6.73629 20.2137 6.21056 20.4309 5.665 20.4309C5.11944 20.4309 4.59371 20.2137 4.23 19.82C3.83628 19.4463 3.61911 18.9206 3.61911 18.375C3.61911 17.8294 3.83628 17.3037 4.23 16.93L4.29 16.87C4.76167 16.3878 4.89231 15.6671 4.62 15.05C4.35995 14.4501 3.78985 14.0586 3.15 14.05H3C2.46957 14.05 1.96086 13.8393 1.58579 13.4642C1.21071 13.0891 1 12.5804 1 12.05C1 11.5196 1.21071 11.0109 1.58579 10.6358C1.96086 10.2607 2.46957 10.05 3 10.05H3.09C3.74435 10.0312 4.31814 9.61788 4.57 9C4.84231 8.38289 4.71167 7.66221 4.24 7.18L4.18 7.12C3.78628 6.75629 3.56911 6.23056 3.56911 5.685C3.56911 5.13944 3.78628 4.61371 4.18 4.25C4.55371 3.85628 5.07944 3.63911 5.625 3.63911C6.17056 3.63911 6.69629 3.85628 7.07 4.25L7.13 4.31C7.61221 4.78167 8.33289 4.91231 8.95 4.64H9C9.59994 4.37995 9.99144 3.80985 10 3.17V3C10 2.46957 10.2107 1.96086 10.5858 1.58579C10.9609 1.21071 11.4696 1 12 1C12.5304 1 13.0391 1.21071 13.4142 1.58579C13.7893 1.96086 14 2.46957 14 3V3.09C14.0086 3.72985 14.4001 4.29995 15 4.56C15.6171 4.83231 16.3378 4.70167 16.82 4.23L16.88 4.17C17.2437 3.77628 17.7694 3.55911 18.325 3.55911C18.8806 3.55911 19.4063 3.77628 19.77 4.17C20.1637 4.54371 20.3809 5.06944 20.3809 5.615C20.3809 6.16056 20.1637 6.68629 19.77 7.06L19.71 7.12C19.2383 7.60221 19.1077 8.32289 19.38 8.94L19.4 9C19.66 9.59994 20.2301 9.99144 20.87 10H21C21.5304 10 22.0391 10.2107 22.4142 10.5858C22.7893 10.9609 23 11.4696 23 12C23 12.5304 22.7893 13.0391 22.4142 13.4142C22.0391 13.7893 21.5304 14 21 14H20.91C20.2702 14.0086 19.7001 14.4001 19.44 15H19.4Z\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n </svg>\\n \";\n this.settingsBtn.innerHTML = settingsIcon;\n\n // 添加悬停效果\n this.settingsBtn.addEventListener('mouseenter', function () {\n _this4.settingsBtn.style.backgroundColor = 'hsla(var(--shadcn-accent) / 0.9)';\n _this4.settingsBtn.style.transform = 'rotate(45deg)';\n });\n this.settingsBtn.addEventListener('mouseleave', function () {\n _this4.settingsBtn.style.backgroundColor = 'hsla(var(--shadcn-background) / 0.7)';\n _this4.settingsBtn.style.transform = 'rotate(0deg)';\n });\n }\n\n /**\n * 创建设置面板\n */\n }, {\n key: \"createSettingsPanel\",\n value: function createSettingsPanel() {\n this.settingsPanel = document.createElement('div');\n this.settingsPanel.className = 'tm-settings-panel';\n this.settingsPanel.style.display = 'none';\n }\n\n /**\n * 创建按钮容器\n */\n }, {\n key: \"createButtonContainer\",\n value: function createButtonContainer() {\n this.buttonContainer = document.createElement('div');\n this.buttonContainer.className = 'tm-button-container';\n this.buttonContainer.style.display = 'flex';\n this.buttonContainer.style.alignItems = 'center';\n this.buttonContainer.style.gap = '10px';\n this.buttonContainer.style.zIndex = '99999';\n }\n\n /**\n * 设置屏幕方向变化监听器\n */\n }, {\n key: \"setupOrientationListener\",\n value: function setupOrientationListener() {\n var _this5 = this;\n // 检测当前屏幕方向\n this.checkOrientation();\n\n // 添加屏幕方向变化监听\n window.addEventListener('orientationchange', function () {\n // 等待方向变化完成后再判断屏幕方向\n setTimeout(function () {\n _this5.checkOrientation();\n }, 300);\n });\n\n // 添加窗口大小变化监听(用于桌面端模拟和某些不支持orientationchange的设备)\n window.addEventListener('resize', function () {\n _this5.checkOrientation();\n });\n }\n\n /**\n * 设置交互事件监听器(在DOM组装后调用)\n */\n }, {\n key: \"setupInteractionListeners\",\n value: function setupInteractionListeners() {\n var _this6 = this;\n // 确保overlay已创建\n if (!this.overlay) return;\n\n // 添加鼠标移动和触摸移动监听,用于在横屏模式下保持控制界面可见\n this.overlay.addEventListener('mousemove', function () {\n if (_this6.isLandscape) {\n _this6.showControls();\n _this6.autoHideControls();\n }\n });\n this.overlay.addEventListener('touchmove', function () {\n if (_this6.isLandscape) {\n _this6.showControls();\n _this6.autoHideControls();\n }\n }, {\n passive: true\n });\n\n // 为控制按钮添加触摸开始事件,防止点击控制按钮时隐藏控制界面\n this.overlay.addEventListener('touchstart', function (e) {\n if (_this6.isLandscape && e.target.closest('.tm-control-button, .tm-time-control-button, .tm-close-button')) {\n // 触摸控制按钮时重置自动隐藏计时器\n _this6.showControls();\n _this6.autoHideControls();\n e.stopPropagation(); // 阻止冒泡到视频包装器\n }\n }, {\n passive: false\n });\n\n // 为控制面板添加鼠标进入和离开事件\n if (this.playerCore.controlManager && this.playerCore.controlManager.controlButtonsContainer) {\n var controlButtons = this.playerCore.controlManager.controlButtonsContainer;\n controlButtons.addEventListener('mouseenter', function () {\n _this6.isMouseOverControls = true;\n // 鼠标进入控制面板时,清除隐藏定时器\n if (_this6.controlsHideTimeout) {\n clearTimeout(_this6.controlsHideTimeout);\n _this6.controlsHideTimeout = null;\n }\n });\n controlButtons.addEventListener('mouseleave', function () {\n _this6.isMouseOverControls = false;\n // 鼠标离开控制面板时,重新设置自动隐藏\n if (_this6.isLandscape) {\n _this6.autoHideControls();\n }\n });\n }\n\n // 为设置按钮和按钮容器添加鼠标进入和离开事件\n if (this.settingsBtn) {\n this.settingsBtn.addEventListener('mouseenter', function () {\n _this6.isMouseOverControls = true;\n if (_this6.controlsHideTimeout) {\n clearTimeout(_this6.controlsHideTimeout);\n _this6.controlsHideTimeout = null;\n }\n });\n this.settingsBtn.addEventListener('mouseleave', function () {\n _this6.isMouseOverControls = false;\n if (_this6.isLandscape) {\n _this6.autoHideControls();\n }\n });\n }\n if (this.buttonContainer) {\n this.buttonContainer.addEventListener('mouseenter', function () {\n _this6.isMouseOverControls = true;\n if (_this6.controlsHideTimeout) {\n clearTimeout(_this6.controlsHideTimeout);\n _this6.controlsHideTimeout = null;\n }\n });\n this.buttonContainer.addEventListener('mouseleave', function () {\n _this6.isMouseOverControls = false;\n if (_this6.isLandscape) {\n _this6.autoHideControls();\n }\n });\n }\n\n // 为设置面板添加鼠标进入和离开事件\n if (this.settingsPanel) {\n this.settingsPanel.addEventListener('mouseenter', function () {\n _this6.isMouseOverControls = true;\n if (_this6.controlsHideTimeout) {\n clearTimeout(_this6.controlsHideTimeout);\n _this6.controlsHideTimeout = null;\n }\n });\n this.settingsPanel.addEventListener('mouseleave', function () {\n _this6.isMouseOverControls = false;\n if (_this6.isLandscape) {\n _this6.autoHideControls();\n }\n });\n }\n }\n\n /**\n * 检测并处理屏幕方向\n */\n }, {\n key: \"checkOrientation\",\n value: function checkOrientation() {\n // 通过窗口宽高比判断屏幕方向\n var isLandscapeNow = window.innerWidth > window.innerHeight;\n\n // 方向发生变化时处理\n if (this.isLandscape !== isLandscapeNow) {\n this.isLandscape = isLandscapeNow;\n this.handleOrientationChange();\n }\n }\n\n /**\n * 处理屏幕方向变化\n */\n }, {\n key: \"handleOrientationChange\",\n value: function handleOrientationChange() {\n // 方向变化时更新容器最小高度\n this.updateContainerMinHeight();\n\n // 更新视频比例相关样式\n this.updateVideoAspectRatio();\n\n // 如果存在控制管理器,通知其刷新UI\n if (this.playerCore.controlManager) {\n this.playerCore.controlManager.updateProgressBar();\n this.playerCore.controlManager.updateCurrentTimeDisplay();\n\n // 更新控制面板显示\n this.updateControlPanelVisibility();\n }\n\n // 横屏时隐藏调整手柄\n if (this.handleContainer) {\n this.handleContainer.style.display = this.isLandscape ? 'none' : 'flex';\n }\n\n // 横屏模式下自动显示控制界面,并设置定时隐藏\n if (this.isLandscape) {\n this.showControls();\n this.autoHideControls();\n } else {\n // 竖屏模式下始终显示控制界面\n this.showControls();\n // 清除任何可能存在的定时器\n if (this.controlsHideTimeout) {\n clearTimeout(this.controlsHideTimeout);\n this.controlsHideTimeout = null;\n }\n }\n }\n\n /**\n * 更新控制面板各行的可见性\n */\n }, {\n key: \"updateControlPanelVisibility\",\n value: function updateControlPanelVisibility() {\n if (!this.playerCore.controlManager) return;\n var controlButtons = this.playerCore.controlManager.controlButtonsContainer;\n if (!controlButtons) return;\n\n // 查找各控制行\n var progressRow = controlButtons.querySelector('.tm-progress-row');\n var seekControlRow = controlButtons.querySelector('.tm-seek-control-row');\n var loopControlRow = controlButtons.querySelector('.tm-loop-control-row');\n var playbackControlRow = controlButtons.querySelector('.tm-playback-control-row');\n if (this.isLandscape) {\n // 横屏模式下,显示所有控制行\n if (progressRow) {\n progressRow.style.display = 'flex';\n progressRow.style.backgroundColor = 'transparent';\n }\n if (seekControlRow) {\n seekControlRow.style.display = 'flex';\n seekControlRow.style.justifyContent = 'center';\n seekControlRow.style.alignItems = 'center';\n seekControlRow.style.gap = '20px';\n seekControlRow.style.backgroundColor = 'transparent';\n }\n if (loopControlRow) {\n loopControlRow.style.display = 'flex';\n loopControlRow.style.backgroundColor = 'transparent';\n }\n if (playbackControlRow) {\n playbackControlRow.style.display = 'flex';\n playbackControlRow.style.backgroundColor = 'transparent';\n }\n\n // 设置按钮也显示\n if (this.settingsBtn) {\n this.settingsBtn.style.display = 'flex';\n this.settingsBtn.style.backgroundColor = 'hsla(var(--shadcn-secondary) / 0.3)';\n this.settingsBtn.style.backdropFilter = 'blur(4px)';\n }\n\n // 调整快退快进按钮组的布局\n var rewindGroup = controlButtons.querySelector('.tm-rewind-group');\n var forwardGroup = controlButtons.querySelector('.tm-forward-group');\n if (rewindGroup) {\n rewindGroup.style.width = 'auto';\n rewindGroup.style.flex = '0 1 auto';\n }\n if (forwardGroup) {\n forwardGroup.style.width = 'auto';\n forwardGroup.style.flex = '0 1 auto';\n }\n } else {\n // 竖屏模式下恢复默认显示\n if (progressRow) progressRow.style.display = '';\n if (seekControlRow) {\n seekControlRow.style.display = '';\n seekControlRow.style.justifyContent = '';\n seekControlRow.style.alignItems = '';\n seekControlRow.style.gap = '';\n }\n if (loopControlRow) loopControlRow.style.display = '';\n if (playbackControlRow) playbackControlRow.style.display = '';\n\n // 恢复设置按钮样式\n if (this.settingsBtn) {\n this.settingsBtn.style.display = '';\n this.settingsBtn.style.backgroundColor = '';\n this.settingsBtn.style.backdropFilter = '';\n }\n\n // 恢复快退快进按钮组的布局\n var _rewindGroup = controlButtons.querySelector('.tm-rewind-group');\n var _forwardGroup = controlButtons.querySelector('.tm-forward-group');\n if (_rewindGroup) {\n _rewindGroup.style.width = '';\n _rewindGroup.style.flex = '';\n }\n if (_forwardGroup) {\n _forwardGroup.style.width = '';\n _forwardGroup.style.flex = '';\n }\n }\n }\n\n /**\n * 更新视频纵横比相关样式\n */\n }, {\n key: \"updateVideoAspectRatio\",\n value: function updateVideoAspectRatio() {\n if (!this.videoWrapper || !this.targetVideo) return;\n var videoWidth = this.targetVideo.videoWidth;\n var videoHeight = this.targetVideo.videoHeight;\n if (videoWidth && videoHeight) {\n var videoRatio = videoWidth / videoHeight;\n var isVideoPortrait = videoRatio < 1; // 视频是否为竖屏比例\n\n // 根据视频比例调整视频包装器样式\n if (isVideoPortrait) {\n this.videoWrapper.classList.add('video-portrait');\n } else {\n this.videoWrapper.classList.remove('video-portrait');\n }\n }\n }\n\n /**\n * 显示控制界面\n */\n }, {\n key: \"showControls\",\n value: function showControls() {\n if (!this.overlay) return;\n this.overlay.classList.remove('controls-hidden');\n document.body.classList.remove('controls-hidden');\n this.controlsVisible = true;\n\n // 清除可能存在的隐藏定时器\n if (this.controlsHideTimeout) {\n clearTimeout(this.controlsHideTimeout);\n this.controlsHideTimeout = null;\n }\n }\n\n /**\n * 隐藏控制界面\n */\n }, {\n key: \"hideControls\",\n value: function hideControls() {\n if (!this.overlay || !this.isLandscape) return;\n this.overlay.classList.add('controls-hidden');\n document.body.classList.add('controls-hidden');\n this.controlsVisible = false;\n }\n\n /**\n * 切换控制界面显示/隐藏\n */\n }, {\n key: \"toggleControlsVisibility\",\n value: function toggleControlsVisibility() {\n if (this.controlsVisible) {\n this.hideControls();\n } else {\n this.showControls();\n // 显示后设置自动隐藏\n this.autoHideControls();\n }\n }\n\n /**\n * 设置自动隐藏控制界面\n */\n }, {\n key: \"autoHideControls\",\n value: function autoHideControls() {\n var _this7 = this;\n // 只在横屏模式下设置自动隐藏\n if (!this.isLandscape) return;\n\n // 如果鼠标在控制面板上,不设置自动隐藏\n if (this.isMouseOverControls) return;\n\n // 清除可能存在的定时器\n if (this.controlsHideTimeout) {\n clearTimeout(this.controlsHideTimeout);\n }\n\n // 设置3秒后自动隐藏\n this.controlsHideTimeout = setTimeout(function () {\n _this7.hideControls();\n }, 3000);\n }\n\n /**\n * 更新视频容器的最小高度\n */\n }, {\n key: \"updateContainerMinHeight\",\n value: function updateContainerMinHeight() {\n if (!this.container || !this.targetVideo) return;\n\n // 横屏模式下不需要设置最小高度,CSS会处理\n if (this.isLandscape) {\n return;\n }\n var videoWidth = this.targetVideo.videoWidth || this.targetVideo.naturalWidth;\n var videoHeight = this.targetVideo.videoHeight || this.targetVideo.naturalHeight;\n if (videoWidth && videoHeight) {\n // 使用视频原始比例计算最小高度\n var minHeight = window.innerWidth * (videoHeight / videoWidth);\n this.container.style.minHeight = \"\".concat(minHeight, \"px\");\n }\n }\n\n /**\n * 组装DOM结构\n */\n }, {\n key: \"assembleDOM\",\n value: function assembleDOM() {\n // 确保先将视频包装器添加到容器\n this.container.appendChild(this.videoWrapper);\n\n // 将关闭按钮和设置按钮添加到按钮容器\n this.buttonContainer.appendChild(this.closeBtn);\n this.buttonContainer.appendChild(this.settingsBtn);\n\n // 将按钮容器添加到播放器容器\n this.playerContainer.appendChild(this.buttonContainer);\n\n // 将容器添加到播放器容器\n this.playerContainer.appendChild(this.container);\n\n // 将手柄容器添加到播放器容器\n this.playerContainer.appendChild(this.handleContainer);\n\n // 添加设置面板到播放器容器\n this.playerContainer.appendChild(this.settingsPanel);\n\n // 如果存在控制按钮,也添加到播放器容器内\n if (this.playerCore.controlManager && this.playerCore.controlManager.controlButtonsContainer) {\n this.playerContainer.appendChild(this.playerCore.controlManager.controlButtonsContainer);\n }\n\n // 将overlay添加到document.body\n document.body.appendChild(this.overlay);\n\n // 将playerContainer与overlay同级添加到document.body,而不是作为overlay的子元素\n document.body.appendChild(this.playerContainer);\n\n // 立即更新容器最小高度\n this.updateContainerMinHeight();\n\n // 在DOM组装完成后设置交互监听器\n this.setupInteractionListeners();\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/ui/UIManager.js?");
},
"./src/player/ui/style.css": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../../../node_modules/style-loader/dist/runtime/styleDomAPI.js */ "./node_modules/style-loader/dist/runtime/styleDomAPI.js");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../../../node_modules/style-loader/dist/runtime/insertBySelector.js */ "./node_modules/style-loader/dist/runtime/insertBySelector.js");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js */ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../../../node_modules/style-loader/dist/runtime/insertStyleElement.js */ "./node_modules/style-loader/dist/runtime/insertStyleElement.js");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../../../node_modules/style-loader/dist/runtime/styleTagTransform.js */ "./node_modules/style-loader/dist/runtime/styleTagTransform.js");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _node_modules_css_loader_dist_cjs_js_ruleSet_1_rules_1_use_1_node_modules_postcss_loader_dist_cjs_js_ruleSet_1_rules_1_use_2_style_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../../../node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].use[1]!../../../node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].use[2]!./style.css */ "./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].use[2]!./src/player/ui/style.css");\n\n \n \n \n \n \n \n \n \n \n\nvar options = {};\n\noptions.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());\noptions.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());\noptions.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, "head");\noptions.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());\noptions.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());\n\nvar update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_ruleSet_1_rules_1_use_1_node_modules_postcss_loader_dist_cjs_js_ruleSet_1_rules_1_use_2_style_css__WEBPACK_IMPORTED_MODULE_6__["default"], options);\n\n\n\n\n /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_ruleSet_1_rules_1_use_1_node_modules_postcss_loader_dist_cjs_js_ruleSet_1_rules_1_use_2_style_css__WEBPACK_IMPORTED_MODULE_6__["default"] && _node_modules_css_loader_dist_cjs_js_ruleSet_1_rules_1_use_1_node_modules_postcss_loader_dist_cjs_js_ruleSet_1_rules_1_use_2_style_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals ? _node_modules_css_loader_dist_cjs_js_ruleSet_1_rules_1_use_1_node_modules_postcss_loader_dist_cjs_js_ruleSet_1_rules_1_use_2_style_css__WEBPACK_IMPORTED_MODULE_6__["default"].locals : undefined);\n\n\n//# sourceURL=webpack://miss-noad-video-player/./src/player/ui/style.css?');
},
"./src/userExperienceEnhancer/DetailExpander.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DetailExpander: () => (/* binding */ DetailExpander)\n/* harmony export */ });\n/* harmony import */ var _utils_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/utils.js */ "./src/utils/utils.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\r\n * 详情自动展开类\r\n * 负责自动展开视频的详细信息\r\n */\n\n\n\n/**\r\n * 详情展开器类\r\n */\nvar DetailExpander = /*#__PURE__*/function () {\n function DetailExpander() {\n _classCallCheck(this, DetailExpander);\n // 配置\n this.maxAttempts = 3; // 最大尝试次数\n this.attemptInterval = 1000; // 尝试间隔时间(ms)\n }\n\n /**\r\n * 展开详情的选择器\r\n * @type {string}\r\n */\n return _createClass(DetailExpander, [{\n key: "SHOW_MORE_SELECTOR",\n get: function get() {\n return \'a.text-nord13.font-medium.flex.items-center\';\n }\n\n /**\r\n * 自动展开详情\r\n */\n }, {\n key: "autoExpandDetails",\n value: function autoExpandDetails() {\n var _this = this;\n // 立即尝试展开一次\n this.expandDetailsSingle();\n\n // 多次尝试,因为有时候页面加载较慢\n var attempts = 0;\n var attemptInterval = setInterval(function () {\n if (_this.expandDetailsSingle() || ++attempts >= _this.maxAttempts) {\n clearInterval(attemptInterval);\n }\n }, this.attemptInterval);\n }\n\n /**\r\n * 执行单次展开尝试\r\n * @returns {boolean} 是否成功展开\r\n */\n }, {\n key: "expandDetailsSingle",\n value: function expandDetailsSingle() {\n try {\n var showMoreButton = document.querySelector(this.SHOW_MORE_SELECTOR);\n if (showMoreButton) {\n showMoreButton.click();\n return true;\n }\n } catch (error) {}\n return false;\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/userExperienceEnhancer/DetailExpander.js?');
},
"./src/userExperienceEnhancer/QualityManager.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ QualityManager: () => (/* binding */ QualityManager)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\r\n * 视频画质管理类\r\n * 负责自动设置视频的最高画质\r\n */\n\n/**\r\n * 画质管理器类\r\n */\nvar QualityManager = /*#__PURE__*/function () {\n function QualityManager() {\n _classCallCheck(this, QualityManager);\n // 配置\n this.maxAttempts = 20; // 最大尝试次数\n this.attemptInterval = 500; // 尝试间隔时间(ms)\n }\n\n /**\r\n * 自动设置最高画质\r\n */\n return _createClass(QualityManager, [{\n key: "setupAutoHighestQuality",\n value: function setupAutoHighestQuality() {\n var _this = this;\n // 立即尝试一次\n if (this.setHighestQualitySingle()) {\n return;\n }\n\n // 失败则定时尝试\n var attempts = 0;\n var checkInterval = setInterval(function () {\n if (_this.setHighestQualitySingle() || ++attempts >= _this.maxAttempts) {\n clearInterval(checkInterval);\n }\n }, this.attemptInterval);\n\n // 页面完全加载后再尝试一次\n window.addEventListener(\'load\', function () {\n return _this.setHighestQualitySingle();\n });\n }\n\n /**\r\n * 执行单次设置最高画质尝试\r\n * @returns {boolean} 是否成功设置\r\n */\n }, {\n key: "setHighestQualitySingle",\n value: function setHighestQualitySingle() {\n try {\n // 检查播放器\n var player = window.player || (typeof unsafeWindow !== \'undefined\' ? unsafeWindow.player : null);\n if (!player || !player.config || !player.config.quality || !player.config.quality.options || !player.config.quality.options.length) {\n return false;\n }\n\n // 设置最高画质\n var maxQuality = Math.max.apply(Math, _toConsumableArray(player.config.quality.options));\n // 同时设置属性和方法\n player.quality = maxQuality;\n player.config.quality.selected = maxQuality;\n if (typeof player.quality === \'function\') {\n player.quality(maxQuality);\n }\n return true;\n } catch (error) {\n return false;\n }\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/userExperienceEnhancer/QualityManager.js?');
},
"./src/userExperienceEnhancer/UrlRedirector.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ UrlRedirector: () => (/* binding */ UrlRedirector)\n/* harmony export */ });\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\n * URL重定向类\n * 负责将特定域名重定向到目标域名\n */\n\n/**\n * URL重定向器类\n */\nvar UrlRedirector = /*#__PURE__*/function () {\n function UrlRedirector() {\n _classCallCheck(this, UrlRedirector);\n // 配置重定向规则\n this.redirectRules = [{\n // 匹配missav.com和thisav.com和 missav.ws 和 missav123.com 和 missav.live\n pattern: /^https?:\\/\\/(www\\.)?(missav|thisav|missav123)\\.com\\/?|^https?:\\/\\/(www\\.)?missav\\.ws\\/?|^https?:\\/\\/(www\\.)?missav\\.live\\/?/i,\n targetDomain: \'missav.ai\'\n }];\n\n // 立即执行重定向检查\n this.immediateRedirect();\n }\n\n /**\n * 立即执行重定向检查,在页面加载最早时执行\n */\n return _createClass(UrlRedirector, [{\n key: "immediateRedirect",\n value: function immediateRedirect() {\n // 立即检查当前URL\n this.checkAndRedirect();\n }\n\n /**\n * 检查当前URL并执行重定向\n * @returns {boolean} 是否执行了重定向\n */\n }, {\n key: "checkAndRedirect",\n value: function checkAndRedirect() {\n var currentUrl = window.location.href;\n\n // 检查每条重定向规则\n var _iterator = _createForOfIteratorHelper(this.redirectRules),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var rule = _step.value;\n if (rule.pattern.test(currentUrl)) {\n // 执行重定向\n var newUrl = this.applyRedirect(currentUrl, rule);\n if (newUrl !== currentUrl) {\n // 使用replace而不是href赋值,避免在浏览历史中留下记录\n window.location.replace(newUrl);\n return true;\n }\n }\n }\n\n // 未触发重定向\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n return false;\n }\n\n /**\n * 应用重定向规则,生成新URL\n * @param {string} url - 当前URL\n * @param {Object} rule - 重定向规则\n * @returns {string} 重定向后的URL\n */\n }, {\n key: "applyRedirect",\n value: function applyRedirect(url, rule) {\n // 替换域名部分\n if (rule.targetDomain) {\n // 处理各种域名情况\n var newUrl = url;\n\n // 处理.com域名\n newUrl = newUrl.replace(/^(https?:\\/\\/)(www\\.)?(missav|thisav|missav123)\\.com\\/?/i, "$1".concat(rule.targetDomain, "/"));\n\n // 如果URL未变化,则尝试替换.ws域名\n if (newUrl === url) {\n newUrl = url.replace(/^(https?:\\/\\/)(www\\.)?missav\\.ws\\/?/i, "$1".concat(rule.targetDomain, "/"));\n }\n\n // 如果URL还未变化,则尝试替换.live域名\n if (newUrl === url) {\n newUrl = url.replace(/^(https?:\\/\\/)(www\\.)?missav\\.live\\/?/i, "$1".concat(rule.targetDomain, "/"));\n }\n return newUrl;\n }\n return url;\n }\n }]);\n}();\n\n//# sourceURL=webpack://miss-noad-video-player/./src/userExperienceEnhancer/UrlRedirector.js?');
},
"./src/userExperienceEnhancer/index.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DetailExpander: () => (/* reexport safe */ _DetailExpander_js__WEBPACK_IMPORTED_MODULE_0__.DetailExpander),\n/* harmony export */ QualityManager: () => (/* reexport safe */ _QualityManager_js__WEBPACK_IMPORTED_MODULE_1__.QualityManager),\n/* harmony export */ UrlRedirector: () => (/* reexport safe */ _UrlRedirector_js__WEBPACK_IMPORTED_MODULE_2__.UrlRedirector),\n/* harmony export */ UserExperienceEnhancer: () => (/* binding */ UserExperienceEnhancer),\n/* harmony export */ earlyUrlRedirector: () => (/* binding */ earlyUrlRedirector),\n/* harmony export */ initUserExperienceEnhancer: () => (/* binding */ initUserExperienceEnhancer)\n/* harmony export */ });\n/* harmony import */ var _DetailExpander_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DetailExpander.js */ "./src/userExperienceEnhancer/DetailExpander.js");\n/* harmony import */ var _QualityManager_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./QualityManager.js */ "./src/userExperienceEnhancer/QualityManager.js");\n/* harmony import */ var _UrlRedirector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./UrlRedirector.js */ "./src/userExperienceEnhancer/UrlRedirector.js");\n/* harmony import */ var _utils_utils_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/utils.js */ "./src/utils/utils.js");\nfunction _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }\nfunction _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }\n/**\n * 用户体验增强模块入口\n * 负责管理和协调各种增强用户体验的功能\n */\n\n\n\n\n\n\n// 立即创建并执行URL重定向检查,确保在页面加载最早阶段执行\nvar earlyUrlRedirector = new _UrlRedirector_js__WEBPACK_IMPORTED_MODULE_2__.UrlRedirector();\n\n/**\n * 用户体验增强器类\n * 整合了自动展开详情、自动高画质、URL重定向等功能\n */\nvar UserExperienceEnhancer = /*#__PURE__*/function () {\n function UserExperienceEnhancer() {\n _classCallCheck(this, UserExperienceEnhancer);\n this.detailExpander = new _DetailExpander_js__WEBPACK_IMPORTED_MODULE_0__.DetailExpander();\n this.qualityManager = new _QualityManager_js__WEBPACK_IMPORTED_MODULE_1__.QualityManager();\n this.urlRedirector = earlyUrlRedirector; // 使用提前创建的重定向器实例\n }\n\n /**\n * 初始化用户体验增强功能\n * @param {boolean} skipRedirectCheck - 是否跳过URL重定向检查(如果在其他地方已经执行过)\n */\n return _createClass(UserExperienceEnhancer, [{\n key: "init",\n value: function init() {\n var _this = this;\n var skipRedirectCheck = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n // 检查是否需要执行URL重定向\n if (!skipRedirectCheck) {\n // 执行URL重定向检查,如果已重定向则不继续执行后续功能\n if (this.urlRedirector.checkAndRedirect()) {\n return;\n }\n }\n\n // DOM加载完成后执行其他功能\n if (document.readyState === \'loading\') {\n document.addEventListener(\'DOMContentLoaded\', function () {\n _this.initFeatures();\n });\n } else {\n this.initFeatures();\n }\n }\n\n /**\n * 初始化各项功能\n */\n }, {\n key: "initFeatures",\n value: function initFeatures() {\n try {\n this.detailExpander.autoExpandDetails();\n this.qualityManager.setupAutoHighestQuality();\n } catch (error) {}\n }\n }]);\n}();\n\n// 导出各个组件,便于单独使用\n\n\n\n // 导出提前初始化的实例\n\n/**\n * 初始化用户体验增强功能\n * @param {boolean} skipRedirectCheck - 是否跳过URL重定向检查\n * @returns {UserExperienceEnhancer} 用户体验增强器实例\n */\nfunction initUserExperienceEnhancer() {\n var skipRedirectCheck = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n var enhancer = new UserExperienceEnhancer();\n enhancer.init(skipRedirectCheck);\n return enhancer;\n}\n\n//# sourceURL=webpack://miss-noad-video-player/./src/userExperienceEnhancer/index.js?');
},
"./src/utils/index.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Utils: () => (/* binding */ Utils),\n/* harmony export */ copyToClipboard: () => (/* reexport safe */ _otherUtils__WEBPACK_IMPORTED_MODULE_0__.copyToClipboard),\n/* harmony export */ debounce: () => (/* reexport safe */ _otherUtils__WEBPACK_IMPORTED_MODULE_0__.debounce),\n/* harmony export */ getLocalStorage: () => (/* reexport safe */ _otherUtils__WEBPACK_IMPORTED_MODULE_0__.getLocalStorage),\n/* harmony export */ getUrlParam: () => (/* reexport safe */ _otherUtils__WEBPACK_IMPORTED_MODULE_0__.getUrlParam),\n/* harmony export */ isMobileDevice: () => (/* reexport safe */ _otherUtils__WEBPACK_IMPORTED_MODULE_0__.isMobileDevice),\n/* harmony export */ setLocalStorage: () => (/* reexport safe */ _otherUtils__WEBPACK_IMPORTED_MODULE_0__.setLocalStorage)\n/* harmony export */ });\n/* harmony import */ var _otherUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./otherUtils */ \"./src/utils/otherUtils.js\");\n/**\r\n * 常用工具函数集合\r\n */\n\n/**\r\n * 工具函数对象\r\n */\nvar Utils = {\n /**\r\n * Toast 通知函数\r\n * @param {string} msg - 消息内容\r\n * @param {number} duration - 显示时长(毫秒)\r\n * @param {string} bgColor - 背景颜色\r\n * @param {string} textColor - 文字颜色\r\n * @param {string} position - 位置(top/bottom/center)\r\n */\n Toast: function Toast(msg) {\n var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3000;\n var bgColor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'rgba(0, 0, 0, 0.8)';\n var textColor = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '#fff';\n var position = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'top';\n var toast = document.createElement('div');\n toast.innerText = msg;\n toast.style.cssText = \"\\n position: fixed;\\n z-index: 100000;\\n left: 50%;\\n transform: translateX(-50%);\\n padding: 10px 15px;\\n border-radius: 4px;\\n color: \".concat(textColor, \";\\n background: \").concat(bgColor, \";\\n font-size: 14px;\\n max-width: 80%;\\n text-align: center;\\n word-break: break-all;\\n \");\n\n // 设置位置\n if (position === 'top') {\n toast.style.top = '10%';\n } else if (position === 'bottom') {\n toast.style.bottom = '10%';\n } else if (position === 'center') {\n toast.style.top = '50%';\n toast.style.transform = 'translate(-50%, -50%)';\n }\n document.body.appendChild(toast);\n setTimeout(function () {\n toast.style.opacity = '0';\n toast.style.transition = 'opacity 0.5s';\n setTimeout(function () {\n document.body.removeChild(toast);\n }, 500);\n }, duration);\n },\n /**\r\n * 节流函数 - 限制函数执行频率\r\n * @param {Function} fn - 需要节流的函数 \r\n * @param {number} delay - 延迟时间(毫秒)\r\n * @returns {Function} 节流后的函数\r\n */\n throttle: function throttle(fn, delay) {\n var lastCall = 0;\n return function () {\n var now = Date.now();\n if (now - lastCall >= delay) {\n lastCall = now;\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return fn.apply(this, args);\n }\n };\n },\n /**\r\n * 等待DOM元素出现\r\n * @param {string} selector - CSS选择器 \r\n * @param {number} timeout - 超时时间(毫秒)\r\n * @param {number} interval - 检查间隔(毫秒)\r\n * @returns {Promise<Element>} DOM元素\r\n */\n waitForElement: function waitForElement(selector) {\n var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10000;\n var interval = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 100;\n return new Promise(function (resolve, reject) {\n var element = document.querySelector(selector);\n if (element) {\n return resolve(element);\n }\n var start = Date.now();\n var intervalId = setInterval(function () {\n var element = document.querySelector(selector);\n if (element) {\n clearInterval(intervalId);\n return resolve(element);\n }\n if (Date.now() - start > timeout) {\n clearInterval(intervalId);\n reject(new Error(\"\\u7B49\\u5F85\\u5143\\u7D20 \".concat(selector, \" \\u8D85\\u65F6\")));\n }\n }, interval);\n });\n },\n /**\r\n * 动态加载脚本\r\n * @param {string} url - 脚本URL\r\n * @returns {Promise<void>} 加载完成的Promise\r\n */\n loadScript: function loadScript(url) {\n return new Promise(function (resolve, reject) {\n var script = document.createElement('script');\n script.src = url;\n script.onload = function () {\n return resolve();\n };\n script.onerror = function (e) {\n return reject(new Error(\"\\u811A\\u672C\\u52A0\\u8F7D\\u5931\\u8D25: \".concat(url)));\n };\n document.head.appendChild(script);\n });\n },\n /**\r\n * 检查元素是否在视口中\r\n * @param {Element} element - 要检查的元素\r\n * @returns {boolean} 是否在视口中\r\n */\n isInViewport: function isInViewport(element) {\n var rect = element.getBoundingClientRect();\n return rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);\n },\n /**\r\n * 格式化时间\r\n * @param {number} seconds - 秒数\r\n * @returns {string} 格式化后的时间字符串\r\n */\n formatTime: function formatTime(seconds) {\n var h = Math.floor(seconds / 3600);\n var m = Math.floor(seconds % 3600 / 60);\n var s = Math.floor(seconds % 60);\n var hDisplay = h > 0 ? String(h).padStart(2, '0') + ':' : '';\n var mDisplay = String(m).padStart(2, '0') + ':';\n var sDisplay = String(s).padStart(2, '0');\n return hDisplay + mDisplay + sDisplay;\n }\n};\n\n// 导出其他工具,如有需要\n // 确保这行存在时,otherUtils.js文件已存在\n\n//# sourceURL=webpack://miss-noad-video-player/./src/utils/index.js?");
},
"./src/utils/otherUtils.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ copyToClipboard: () => (/* binding */ copyToClipboard),\n/* harmony export */ debounce: () => (/* binding */ debounce),\n/* harmony export */ getLocalStorage: () => (/* binding */ getLocalStorage),\n/* harmony export */ getUrlParam: () => (/* binding */ getUrlParam),\n/* harmony export */ isMobileDevice: () => (/* binding */ isMobileDevice),\n/* harmony export */ setLocalStorage: () => (/* binding */ setLocalStorage)\n/* harmony export */ });\n/**\r\n * 其他辅助工具函数\r\n */\n\n/**\r\n * 防抖函数 - 延迟执行函数直到停止调用一段时间后\r\n * @param {Function} fn - 需要防抖的函数\r\n * @param {number} delay - 延迟时间(毫秒)\r\n * @returns {Function} 防抖后的函数\r\n */\nfunction debounce(fn, delay) {\n var timer = null;\n return function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n var context = this;\n clearTimeout(timer);\n timer = setTimeout(function () {\n fn.apply(context, args);\n }, delay);\n };\n}\n\n/**\r\n * 存储数据到本地存储\r\n * @param {string} key - 存储键名\r\n * @param {any} value - 存储值\r\n */\nfunction setLocalStorage(key, value) {\n try {\n localStorage.setItem(key, JSON.stringify(value));\n } catch (e) {}\n}\n\n/**\r\n * 从本地存储获取数据\r\n * @param {string} key - 存储键名\r\n * @param {any} defaultValue - 默认值\r\n * @returns {any} 获取的值\r\n */\nfunction getLocalStorage(key) {\n var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n try {\n var item = localStorage.getItem(key);\n return item ? JSON.parse(item) : defaultValue;\n } catch (e) {\n return defaultValue;\n }\n}\n\n/**\r\n * 检测是否为移动设备\r\n * @returns {boolean} 是否为移动设备\r\n */\nfunction isMobileDevice() {\n return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n}\n\n/**\r\n * 获取URL参数\r\n * @param {string} name - 参数名\r\n * @param {string} url - URL,默认为当前页面URL\r\n * @returns {string|null} 参数值\r\n */\nfunction getUrlParam(name) {\n var url = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window.location.href;\n name = name.replace(/[\\[\\]]/g, '\\\\$&');\n var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');\n var results = regex.exec(url);\n if (!results) return null;\n if (!results[2]) return '';\n return decodeURIComponent(results[2].replace(/\\+/g, ' '));\n}\n\n/**\r\n * 复制文本到剪贴板\r\n * @param {string} text - 要复制的文本\r\n * @returns {Promise<boolean>} 是否复制成功\r\n */\nfunction copyToClipboard(text) {\n return new Promise(function (resolve) {\n // 尝试使用现代API\n if (navigator.clipboard && navigator.clipboard.writeText) {\n navigator.clipboard.writeText(text).then(function () {\n return resolve(true);\n })[\"catch\"](function () {\n // 降级到传统方法\n fallbackCopyToClipboard(text) ? resolve(true) : resolve(false);\n });\n } else {\n // 使用传统方法\n fallbackCopyToClipboard(text) ? resolve(true) : resolve(false);\n }\n });\n}\n\n/**\r\n * 传统的复制到剪贴板方法\r\n * @param {string} text - 要复制的文本\r\n * @returns {boolean} 是否复制成功\r\n */\nfunction fallbackCopyToClipboard(text) {\n var textArea = document.createElement('textarea');\n textArea.value = text;\n textArea.style.position = 'fixed';\n textArea.style.left = '-999999px';\n textArea.style.top = '-999999px';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n var success = false;\n try {\n success = document.execCommand('copy');\n } catch (e) {}\n document.body.removeChild(textArea);\n return success;\n}\n\n//# sourceURL=webpack://miss-noad-video-player/./src/utils/otherUtils.js?");
},
"./src/utils/utils.js": (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ Utils: () => (/* binding */ Utils)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * 工具类 - 通用功能函数集合\n */\nvar Utils = /*#__PURE__*/function () {\n function Utils() {\n _classCallCheck(this, Utils);\n }\n return _createClass(Utils, null, [{\n key: \"throttle\",\n value:\n /**\n * 节流函数 - 限制函数执行频率\n * @param {Function} fn - 要执行的函数\n * @param {number} delay - 延迟时间(ms)\n * @returns {Function} - 节流后的函数\n */\n function throttle(fn) {\n var delay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;\n var lastCall = 0;\n return function () {\n var now = Date.now();\n if (now - lastCall < delay) return;\n lastCall = now;\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n return fn.apply(this, args);\n };\n }\n\n /**\n * 防抖函数 - 延迟执行直到操作停止\n * @param {Function} fn - 要执行的函数\n * @param {number} delay - 延迟时间(ms)\n * @returns {Function} - 防抖后的函数\n */\n }, {\n key: \"debounce\",\n value: function debounce(fn) {\n var delay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;\n var timer = null;\n return function () {\n var _this = this;\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n if (timer) clearTimeout(timer);\n timer = setTimeout(function () {\n fn.apply(_this, args);\n timer = null;\n }, delay);\n };\n }\n\n /**\n * 检测是否为iOS设备\n * @returns {boolean} - 是否为iOS设备\n */\n }, {\n key: \"isIOS\",\n value: function isIOS() {\n if (this._cache.isIOS === null) {\n this._cache.isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;\n }\n return this._cache.isIOS;\n }\n\n /**\n * 检测是否为Safari浏览器\n * @returns {boolean} - 是否为Safari浏览器\n */\n }, {\n key: \"isSafari\",\n value: function isSafari() {\n return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n }\n\n /**\n * 检测是否为竖屏模式\n * @returns {boolean} - 是否为竖屏模式\n */\n }, {\n key: \"isPortrait\",\n value: function isPortrait() {\n return window.innerHeight > window.innerWidth;\n }\n\n /**\n * 检查设备和屏幕方向\n * @returns {boolean} - 当前是否为竖屏状态\n */\n }, {\n key: \"checkDeviceAndOrientation\",\n value: function checkDeviceAndOrientation() {\n return this.isPortrait();\n }\n\n /**\n * 获取设备安全区域尺寸\n * @returns {Object} - 安全区域尺寸 {top, right, bottom, left}\n */\n }, {\n key: \"getSafeAreaInsets\",\n value: function getSafeAreaInsets() {\n var defaultTopInset = 44; // 默认顶部安全区域\n var defaultBottomInset = 34; // 默认底部安全区域\n var defaultSideInset = 16; // 默认左右安全区域\n\n var style = window.getComputedStyle(document.documentElement);\n return {\n top: parseInt(style.getPropertyValue('--sat') || style.getPropertyValue('--safe-area-inset-top') || '0', 10) || defaultTopInset,\n right: parseInt(style.getPropertyValue('--sar') || style.getPropertyValue('--safe-area-inset-right') || '0', 10) || defaultSideInset,\n bottom: parseInt(style.getPropertyValue('--sab') || style.getPropertyValue('--safe-area-inset-bottom') || '0', 10) || defaultBottomInset,\n left: parseInt(style.getPropertyValue('--sal') || style.getPropertyValue('--safe-area-inset-left') || '0', 10) || defaultSideInset\n };\n }\n\n /**\n * 创建带样式的HTML元素\n * @param {string} tag - HTML标签名\n * @param {string} className - CSS类名\n * @param {string} style - 内联样式\n * @returns {HTMLElement} - 创建的元素\n */\n }, {\n key: \"createElementWithStyle\",\n value: function createElementWithStyle(tag, className, style) {\n var element = document.createElement(tag);\n if (className) element.className = className;\n if (style) element.style.cssText = style;\n return element;\n }\n\n /**\n * 创建SVG图标\n * @param {string} path - SVG路径\n * @param {number} size - 图标大小\n * @returns {SVGElement} - SVG图标元素\n */\n }, {\n key: \"createSVGIcon\",\n value: function createSVGIcon(path) {\n var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 24;\n var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', size);\n svg.setAttribute('height', size);\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('fill', 'none');\n svg.setAttribute('stroke', 'currentColor');\n svg.setAttribute('stroke-width', '2');\n svg.setAttribute('stroke-linecap', 'round');\n svg.setAttribute('stroke-linejoin', 'round');\n var pathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n pathElement.setAttribute('d', path);\n svg.appendChild(pathElement);\n return svg;\n }\n\n /**\n * 检测页面中是否存在视频元素\n * @returns {HTMLVideoElement|null} - 找到的视频元素或null\n */\n }, {\n key: \"findVideoElement\",\n value: function findVideoElement() {\n // 常见视频选择器\n var specificSelectors = ['#player video',\n // 常见ID\n '#video video',\n // 常见ID\n 'div.plyr__video-wrapper video',\n // Plyr\n '.video-js video',\n // Video.js\n '#player > video',\n // 直接子元素\n '#video-player > video',\n // 另一个常见ID\n 'video[preload]:not([muted])',\n // 可能是主要内容的视频\n 'video[src]',\n // 带有src属性的视频\n 'video.video-main',\n // 主视频类\n 'main video',\n // 主要内容区域中的视频\n 'video' // 所有视频(最低优先级)\n ];\n\n // 按优先级顺序查找视频元素\n for (var _i = 0, _specificSelectors = specificSelectors; _i < _specificSelectors.length; _i++) {\n var selector = _specificSelectors[_i];\n var videos = document.querySelectorAll(selector);\n if (videos.length > 0) {\n return videos[0]; // 返回第一个匹配的视频元素\n }\n }\n return null; // 未找到视频元素\n }\n\n /**\n * 格式化时间为 mm:ss 或 hh:mm:ss\n * @param {number} seconds - 秒数\n * @returns {string} - 格式化后的时间字符串\n */\n }, {\n key: \"formatTime\",\n value: function formatTime(seconds) {\n var hours = Math.floor(seconds / 3600);\n var minutes = Math.floor(seconds % 3600 / 60);\n var secs = Math.floor(seconds % 60);\n if (hours > 0) {\n return \"\".concat(hours, \":\").concat(minutes < 10 ? '0' : '').concat(minutes, \":\").concat(secs < 10 ? '0' : '').concat(secs);\n }\n return \"\".concat(minutes, \":\").concat(secs < 10 ? '0' : '').concat(secs);\n }\n\n /**\n * 设置或更新Safari的主题色\n * @param {string} color - 主题色\n * @param {boolean} saveOriginal - 是否保存原始颜色值\n */\n }, {\n key: \"updateSafariThemeColor\",\n value: function updateSafariThemeColor() {\n var color = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '#000000';\n var saveOriginal = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n // 仅在Safari浏览器中执行\n if (!this.isSafari() && !this.isIOS()) return;\n\n // 获取当前主题色标签\n var metaThemeColor = document.querySelector('meta[name=\"theme-color\"]');\n\n // 保存原始颜色值(如果需要)\n if (saveOriginal && metaThemeColor && !this._theme.original.dark) {\n this._theme.original.dark = metaThemeColor.content;\n }\n\n // 如果标签不存在,创建新标签\n if (!metaThemeColor) {\n metaThemeColor = document.createElement('meta');\n metaThemeColor.name = 'theme-color';\n document.head.appendChild(metaThemeColor);\n }\n\n // 设置颜色值\n metaThemeColor.content = color;\n }\n\n /**\n * 恢复Safari的原始主题色\n */\n }, {\n key: \"restoreSafariThemeColor\",\n value: function restoreSafariThemeColor() {\n // 仅在有保存的原始颜色时恢复\n if (this._theme.original.dark) {\n this.updateSafariThemeColor(this._theme.original.dark);\n } else {\n // 如果没有原始颜色,移除主题色标签\n var metaThemeColor = document.querySelector('meta[name=\"theme-color\"]');\n if (metaThemeColor && metaThemeColor.parentNode) {\n metaThemeColor.parentNode.removeChild(metaThemeColor);\n }\n }\n }\n }]);\n}();\n// 缓存常用的检测结果\n_defineProperty(Utils, \"_cache\", {\n isIOS: null,\n safeAreaInsets: null,\n lastOrientation: null\n});\n// 主题颜色相关\n_defineProperty(Utils, \"_theme\", {\n original: {\n light: null,\n dark: null\n }\n});\n\n//# sourceURL=webpack://miss-noad-video-player/./src/utils/utils.js?");
}
};
var __webpack_module_cache__ = {};
function __webpack_require__(n) {
var e = __webpack_module_cache__[n];
if (void 0 !== e) {
return e.exports;
}
var t = __webpack_module_cache__[n] = {
"id": n,
"exports": {}
};
__webpack_modules__[n](t, t.exports, __webpack_require__);
return t.exports;
}
(() => {
__webpack_require__.n = n => {
var e = n && n.__esModule ? () => n["default"] : () => n;
__webpack_require__.d(e, {
"a": e
});
return e;
};
})();
(() => {
__webpack_require__.d = (n, e) => {
for (var t in e) {
if (__webpack_require__.o(e, t) && !__webpack_require__.o(n, t)) {
Object.defineProperty(n, t, {
"enumerable": true,
"get": e[t]
});
}
}
};
})();
(() => {
__webpack_require__.o = (n, e) => Object.prototype.hasOwnProperty.call(n, e);
})();
(() => {
__webpack_require__.r = n => {
if ("undefined" !== typeof Symbol && Symbol.toStringTag) {
Object.defineProperty(n, Symbol.toStringTag, {
"value": "Module"
});
}
Object.defineProperty(n, "__esModule", {
"value": true
});
};
})();
(() => {
__webpack_require__.nc = void 0;
})();
var __webpack_exports__ = __webpack_require__("./src/index.js");
})();