├── .gitignore ├── .parcelrc ├── README.md ├── dist ├── background.js ├── background.js.map ├── constants.js ├── constants.js.map ├── content.js ├── content.js.map ├── images │ ├── player128.png │ ├── player16.png │ ├── player32.png │ └── player48.png ├── manifest.json ├── popup.94081321.js ├── popup.94081321.js.map └── popup.html ├── images ├── player128.png ├── player16.png ├── player32.png └── player48.png ├── manifest.json ├── package.json ├── release.zip ├── src ├── background.ts ├── constants.ts ├── content.ts ├── popup.html └── popup.tsx ├── static └── manifest.json ├── tsconfig.json ├── yarn-error.log └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .cache/ -------------------------------------------------------------------------------- /.parcelrc: -------------------------------------------------------------------------------- 1 | { 2 | "optimizers": { 3 | "*.js": ["@parcel/optimizer-uglify"], 4 | "*.css": ["@parcel/optimizer-cssnano"], 5 | "*.html": ["@parcel/optimizer-htmlnano"], 6 | "*.{png,jpg,jpeg,svg,...}": ["@parcel/optimizer-imagemin"] 7 | }, 8 | "reporters": ["@parcel/reporter-cli"] 9 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pip-player-chrome-ext 2 | Chrome extension that allows you to play video in picture-in-picture mode 3 | https://chrome.google.com/webstore/detail/%E6%82%AC%E6%B5%AE%E7%94%BB%E4%B8%AD%E7%94%BB%E6%92%AD%E6%94%BE%E5%99%A8/gdcfkpenohoihodlddbcgpdjhmdjepnb 4 | -------------------------------------------------------------------------------- /dist/background.js: -------------------------------------------------------------------------------- 1 | parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c {\r\n return list.map((word) => {\r\n return new chrome.declarativeContent.PageStateMatcher({\r\n pageUrl: {hostContains: word},\r\n })\r\n });\r\n}\r\nchrome.runtime.onInstalled.addListener(function() {\r\n chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {\r\n chrome.declarativeContent.onPageChanged.addRules([{\r\n conditions: genConditions(paths),\r\n actions: [new chrome.declarativeContent.ShowPageAction()]\r\n }]);\r\n });\r\n});\r\n"]} -------------------------------------------------------------------------------- /dist/constants.js: -------------------------------------------------------------------------------- 1 | parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c0&&o[o.length-1])&&(6===i[0]||2===i[0])){u=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]1&&chrome.runtime.sendMessage({multiVideo:!0}),e}();return e?a(e):setTimeout(l,1e3),e}chrome.runtime.onMessage.addListener(function(n,r,i){var u,s=n.command;"play"===s&&l(),"original-player-play"===s&&function(){e(this,void 0,void 0,function(){return t(this,function(e){switch(e.label){case 0:return[4,document.exitPictureInPicture()];case 1:return e.sent(),o("QUIT"),[2]}})})}(),"play-next"===s&&(u=document.querySelectorAll("video").length,c>=u-1?c=0:c++,a(document.querySelectorAll("video")[c]))})}(); 5 | },{"./constants":"eKDL"}]},{},["hNRT"], null) 6 | //# sourceMappingURL=/content.js.map -------------------------------------------------------------------------------- /dist/content.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["constants.ts","content.ts"],"names":[],"mappings":"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","file":"content.js","sourceRoot":"..\\src","sourcesContent":["export const stateMachine = {\r\n idle: {\r\n PLAY: 'attemptingToPlay',\r\n },\r\n attemptingToPlay: {\r\n SUCCESS: 'playing',\r\n FAIL: 'error',\r\n },\r\n playing: {\r\n QUIT: 'idle',\r\n },\r\n error: {\r\n PLAY: 'attemptingToPlay',\r\n },\r\n};\r\n\r\nexport type Commands =\r\n | 'play'\r\n | 'original-player-play'\r\n | 'play-next'\r\n | 'mute'\r\n | {continuous: boolean}\r\n | {multiVideo: boolean};\r\n","import { stateMachine, Commands } from \"./constants\";\r\n\r\n(function() {\r\n interface HTMLVideoElementNew extends HTMLVideoElement {\r\n requestPictureInPicture: () => Promise;\r\n }\r\n\r\n let state: keyof typeof stateMachine = \"idle\";\r\n const transition = (\r\n action: \"PLAY\" | \"SUCCESS\" | \"FAIL\" | \"QUIT\" | \"PLAY\"\r\n ) => {\r\n const currentState = stateMachine[state];\r\n if (action in currentState) {\r\n state = (currentState as any)[action];\r\n }\r\n chrome.runtime.sendMessage({ state });\r\n };\r\n\r\n const reset = () => {\r\n state = \"idle\";\r\n chrome.runtime.sendMessage({ state });\r\n };\r\n\r\n const siteToQuerySelectorMap = {\r\n douyu: '[id^=\"__video\"]',\r\n huya: \"#huya_video\",\r\n huomao: \"#live-video\"\r\n };\r\n\r\n let currentVideoIndex = 0;\r\n\r\n function getVideoEl() {\r\n const origin = document.location.origin;\r\n let video: HTMLVideoElementNew | null;\r\n\r\n const matchedSite = Object.keys(\r\n siteToQuerySelectorMap\r\n ).find(sitePartialName => origin.includes(sitePartialName));\r\n\r\n if (matchedSite) {\r\n video = document.querySelector(\r\n siteToQuerySelectorMap[\r\n matchedSite as keyof typeof siteToQuerySelectorMap\r\n ]\r\n );\r\n } else {\r\n video = document.querySelector(\"video\") as HTMLVideoElementNew;\r\n }\r\n\r\n // if there're more than 1