Compare commits

..

32 Commits
3.0.1 ... 3.0.5

Author SHA1 Message Date
Ajay Ramachandran
096737dcbb bump version 2021-09-02 11:44:38 -04:00
Ajay Ramachandran
02360c1f3c Fix centering on submission notice 2021-09-02 11:44:25 -04:00
Ajay Ramachandran
ccd8342ddb Update top contibutors 2021-09-02 00:37:53 -04:00
Ajay Ramachandran
4ae2a42c8c New Crowdin updates (#902) 2021-09-02 00:19:36 -04:00
Ajay Ramachandran
206d7bc2bd bump version 2021-09-02 00:14:46 -04:00
Ajay Ramachandran
0fc9e9b2fb Fix UI issues when text is long
Fixes #914
2021-09-02 00:05:13 -04:00
Ajay Ramachandran
3774ef9756 Fix preview sometimes not skipping
Fixes #915
2021-09-01 19:50:58 -04:00
Ajay Ramachandran
098d879fe2 Merge pull request #922 from ajayyy/basic-selenium
Basic selenium
2021-09-01 16:03:05 -04:00
Ajay Ramachandran
49406b7ac6 Make refresh button work when no segments found
Fixes #885
2021-09-01 15:50:22 -04:00
Ajay Ramachandran
5c704ad241 Fix multiple segments skipped not appearing
Fixes #909, #919, #905
2021-09-01 15:41:46 -04:00
Ajay Ramachandran
681eb61763 Fix highlight appearing as two timestamps in popup 2021-09-01 13:15:15 -04:00
Ajay Ramachandran
71cf9888e8 Fix disable skipping not working for highlight
Resolves #916
2021-09-01 04:24:10 -04:00
Ajay Ramachandran
b1aaa0ac5e Add copy public id button 2021-09-01 04:22:06 -04:00
Ajay Ramachandran
a2c3116bdd Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2021-08-26 18:20:35 -04:00
Ajay Ramachandran
48a49e4136 Make highlight hover text work better on preview bar 2021-08-26 18:20:33 -04:00
Ajay Ramachandran
6de1a58d88 bump version 2021-08-24 02:28:18 -04:00
Ajay Ramachandran
43a9ba0f9e Fix keybind being flaky 2021-08-23 19:51:58 -04:00
Ajay Ramachandran
c3489e54a6 Fix highlight category when minimum duration set 2021-08-23 18:23:03 -04:00
Ajay Ramachandran
75c003b204 Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2021-08-23 15:46:36 -04:00
Ajay Ramachandran
da5de43121 Fix skipping with highlight on invidious 2021-08-23 15:46:35 -04:00
Ajay Ramachandran
d20a44751c bump version 2021-08-23 03:08:01 -04:00
Ajay Ramachandran
15706fd3c4 Fix issue with early highlight breaking skipping 2021-08-22 20:47:46 -04:00
Ajay Ramachandran
a9e43f95f5 Fix highlight auto skipping on music videos 2021-08-22 19:03:24 -04:00
Ajay Ramachandran
11fe87a09e Fix highlight category info appearing to new users 2021-08-22 19:03:05 -04:00
Ajay Ramachandran
52741b2c0a Merge branch 'master' of https://github.com/ajayyy/SponsorBlock 2021-08-22 14:13:03 -04:00
Ajay Ramachandran
09b18a4f6d Fix auto skip on music videos for show overlay 2021-08-22 14:13:02 -04:00
Ajay Ramachandran
4ef8e36821 Fix build step casing 2021-07-30 23:37:13 -04:00
Ajay Ramachandran
788d4bf73c Build before running test 2021-07-30 23:36:31 -04:00
Ajay Ramachandran
d73c666e1f Extract out setup steps 2021-07-30 23:34:15 -04:00
Ajay Ramachandran
3187efaf1a Add test for skipping preview segment 2021-07-30 16:00:59 -04:00
Ajay Ramachandran
b9bbbebc10 Add test for editing 2021-07-30 15:53:57 -04:00
Ajay Ramachandran
d93e9a7d8a Add basic selenium test 2021-07-30 15:04:05 -04:00
36 changed files with 1055 additions and 152 deletions

View File

@@ -3,6 +3,8 @@ module.exports = {
browser: true,
es2021: true,
node: true,
jest: true,
jasmine: true,
},
extends: [
"eslint:recommended",

View File

@@ -1,6 +1,6 @@
module.exports = {
"roots": [
"src"
"test"
],
"transform": {
"^.+\\.ts$": "ts-jest"

View File

@@ -1,7 +1,7 @@
{
"name": "__MSG_fullName__",
"short_name": "SponsorBlock",
"version": "3.0.1",
"version": "3.0.5",
"default_locale": "en",
"description": "__MSG_Description__",
"homepage_url": "https://sponsor.ajay.app",

432
package-lock.json generated
View File

@@ -11,6 +11,7 @@
"dependencies": {
"@types/react": "^16.9.22",
"@types/react-dom": "^16.9.5",
"@types/selenium-webdriver": "^4.0.15",
"babel": "^6.23.0",
"babel-core": "^6.26.3",
"babel-loader": "^8.0.6",
@@ -31,6 +32,7 @@
"@types/jquery": "^3.3.31",
"@typescript-eslint/eslint-plugin": "^4.9.1",
"@typescript-eslint/parser": "^4.9.1",
"chromedriver": "^92.0.0",
"copy-webpack-plugin": "^6.0.3",
"eslint": "^7.15.0",
"eslint-plugin-react": "^7.21.5",
@@ -44,6 +46,7 @@
=======
"jest": "^27.0.6",
"rimraf": "^3.0.0",
"selenium-webdriver": "^4.0.0-beta.4",
"ts-jest": "^27.0.3",
"ts-loader": "^6.2.1",
"typescript": "~4.3",
@@ -22025,6 +22028,12 @@
"node": ">=6"
}
},
"node_modules/@testim/chrome-version": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.0.7.tgz",
"integrity": "sha512-8UT/J+xqCYfn3fKtOznAibsHpiuDshCb0fwgWxRazTT19Igp9ovoXMPhXyLD6m3CKQGTMHgqoxaFfMWaL40Rnw==",
"dev": true
},
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@@ -22235,6 +22244,11 @@
"@types/react": "*"
}
},
"node_modules/@types/selenium-webdriver": {
"version": "4.0.15",
"resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-4.0.15.tgz",
"integrity": "sha512-5760PIZkzhPejy3hsKAdCKe5LJygGdxLKOLxmZL9GEUcFlO5OgzM6G2EbdbvOnaw4xvUSa9Uip6Ipwkih12BPA=="
},
"node_modules/@types/sizzle": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
@@ -23564,6 +23578,15 @@
"integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
"dev": true
},
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dev": true,
"dependencies": {
"follow-redirects": "^1.10.0"
}
},
"node_modules/babel": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
@@ -25415,6 +25438,28 @@
"node": ">=6.0"
}
},
"node_modules/chromedriver": {
"version": "92.0.0",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-92.0.0.tgz",
"integrity": "sha512-IdJ5n5jLL6tCsGQF/fQHF2gDEhVzoYIqktUn6hE/BSsXlCcyDTi45fQbhTEhZlmshM8+BpnRtPuIT5DRbxNqKg==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
"@testim/chrome-version": "^1.0.7",
"axios": "^0.21.1",
"del": "^6.0.0",
"extract-zip": "^2.0.1",
"https-proxy-agent": "^5.0.0",
"proxy-from-env": "^1.1.0",
"tcp-port-used": "^1.0.1"
},
"bin": {
"chromedriver": "bin/chromedriver"
},
"engines": {
"node": ">=10"
}
},
"node_modules/ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
@@ -26176,21 +26221,6 @@
"node": ">=8"
}
},
"node_modules/copy-webpack-plugin/node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/copy-webpack-plugin/node_modules/schema-utils": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
@@ -26425,12 +26455,19 @@
"dev": true
},
"node_modules/debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dependencies": {
"ms": "^2.1.1"
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/decamelize": {
@@ -26777,6 +26814,37 @@
"node": ">=0.10.0"
}
},
"node_modules/del": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz",
"integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==",
"dev": true,
"dependencies": {
"globby": "^11.0.1",
"graceful-fs": "^4.2.4",
"is-glob": "^4.0.1",
"is-path-cwd": "^2.2.0",
"is-path-inside": "^3.0.2",
"p-map": "^4.0.0",
"rimraf": "^3.0.2",
"slash": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/del/node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -28330,6 +28398,41 @@
"node": ">=0.10.0"
}
},
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"bin": {
"extract-zip": "cli.js"
},
"engines": {
"node": ">= 10.17.0"
},
"optionalDependencies": {
"@types/yauzl": "^2.9.1"
}
},
"node_modules/extract-zip/node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dev": true,
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@@ -28719,21 +28822,6 @@
"node": "^10.12.0 || >=12.0.0"
}
},
"node_modules/flat-cache/node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/flatstr": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz",
@@ -28764,6 +28852,26 @@
"readable-stream": "^2.3.6"
}
},
"node_modules/follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -29768,6 +29876,15 @@
"url": "https://github.com/sindresorhus/invert-kv?sponsor=1"
}
},
"node_modules/ip-regex": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
"integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -30106,6 +30223,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-path-cwd": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
"integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/is-path-inside": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
@@ -30218,6 +30344,12 @@
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
"node_modules/is-url": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
"dev": true
},
"node_modules/is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
@@ -30250,6 +30382,20 @@
"integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==",
"dev": true
},
"node_modules/is2": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/is2/-/is2-2.0.7.tgz",
"integrity": "sha512-4vBQoURAXC6hnLFxD4VW7uc04XiwTTl/8ydYJxKvPwkWQrSjInkuM5VZVg6BGr1/natq69zDuvO9lGpLClJqvA==",
"dev": true,
"dependencies": {
"deep-is": "^0.1.3",
"ip-regex": "^4.1.0",
"is-url": "^1.2.4"
},
"engines": {
"node": ">=v0.10.0"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -36718,6 +36864,12 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true
},
"node_modules/prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@@ -37332,9 +37484,9 @@
}
},
"node_modules/rimraf": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.1.tgz",
"integrity": "sha512-IQ4ikL8SjBiEDZfk+DFVwqRK8md24RWMEJkdSlgNLkyyAImcjf8SWvU1qFMDOb4igBClbTQ/ugPqXcRwdFTxZw==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
@@ -37470,6 +37622,21 @@
"seek-table": "bin/seek-bzip-table"
}
},
"node_modules/selenium-webdriver": {
"version": "4.0.0-beta.4",
"resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-beta.4.tgz",
"integrity": "sha512-+s/CIYkWzmnC9WASBxxVj7Lm0dcyl6OaFxwIJaFCT5WCuACiimEEr4lUnOOFP/QlKfkDQ56m+aRczaq2EvJEJg==",
"dev": true,
"dependencies": {
"jszip": "^3.6.0",
"rimraf": "^3.0.2",
"tmp": "^0.2.1",
"ws": ">=7.4.6"
},
"engines": {
"node": ">= 10.15.0"
}
},
"node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -38735,6 +38902,16 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/tcp-port-used": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz",
"integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==",
"dev": true,
"dependencies": {
"debug": "4.3.1",
"is2": "^2.0.6"
}
},
"node_modules/terminal-link": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
@@ -42228,6 +42405,12 @@
"defer-to-connect": "^1.0.1"
}
},
"@testim/chrome-version": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.0.7.tgz",
"integrity": "sha512-8UT/J+xqCYfn3fKtOznAibsHpiuDshCb0fwgWxRazTT19Igp9ovoXMPhXyLD6m3CKQGTMHgqoxaFfMWaL40Rnw==",
"dev": true
},
"@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@@ -42435,6 +42618,11 @@
"@types/react": "*"
}
},
"@types/selenium-webdriver": {
"version": "4.0.15",
"resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-4.0.15.tgz",
"integrity": "sha512-5760PIZkzhPejy3hsKAdCKe5LJygGdxLKOLxmZL9GEUcFlO5OgzM6G2EbdbvOnaw4xvUSa9Uip6Ipwkih12BPA=="
},
"@types/sizzle": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
@@ -43475,6 +43663,15 @@
"integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
"dev": true
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dev": true,
"requires": {
"follow-redirects": "^1.10.0"
}
},
"babel": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel/-/babel-6.23.0.tgz",
@@ -45084,6 +45281,21 @@
"tslib": "^1.9.0"
}
},
"chromedriver": {
"version": "92.0.0",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-92.0.0.tgz",
"integrity": "sha512-IdJ5n5jLL6tCsGQF/fQHF2gDEhVzoYIqktUn6hE/BSsXlCcyDTi45fQbhTEhZlmshM8+BpnRtPuIT5DRbxNqKg==",
"dev": true,
"requires": {
"@testim/chrome-version": "^1.0.7",
"axios": "^0.21.1",
"del": "^6.0.0",
"extract-zip": "^2.0.1",
"https-proxy-agent": "^5.0.0",
"proxy-from-env": "^1.1.0",
"tcp-port-used": "^1.0.1"
}
},
"ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
@@ -45693,15 +45905,6 @@
"find-up": "^4.0.0"
}
},
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"schema-utils": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
@@ -45903,11 +46106,11 @@
"dev": true
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"requires": {
"ms": "^2.1.1"
"ms": "2.1.2"
}
},
"decamelize": {
@@ -46193,6 +46396,30 @@
}
}
},
"del": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz",
"integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==",
"dev": true,
"requires": {
"globby": "^11.0.1",
"graceful-fs": "^4.2.4",
"is-glob": "^4.0.1",
"is-path-cwd": "^2.2.0",
"is-path-inside": "^3.0.2",
"p-map": "^4.0.0",
"rimraf": "^3.0.2",
"slash": "^3.0.0"
},
"dependencies": {
"slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true
}
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -47399,6 +47626,29 @@
}
}
},
"extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"dev": true,
"requires": {
"@types/yauzl": "^2.9.1",
"debug": "^4.1.1",
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"dependencies": {
"get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dev": true,
"requires": {
"pump": "^3.0.0"
}
}
}
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@@ -47721,17 +47971,6 @@
"requires": {
"flatted": "^3.1.0",
"rimraf": "^3.0.2"
},
"dependencies": {
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
}
}
},
"flatstr": {
@@ -47761,6 +48000,12 @@
"readable-stream": "^2.3.6"
}
},
"follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"dev": true
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -48546,6 +48791,12 @@
"integrity": "sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==",
"dev": true
},
"ip-regex": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
"integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==",
"dev": true
},
"ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -48781,6 +49032,12 @@
"dev": true,
"peer": true
},
"is-path-cwd": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
"integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
"dev": true
},
"is-path-inside": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
@@ -48857,6 +49114,12 @@
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
"is-url": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
"dev": true
},
"is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
@@ -48883,6 +49146,17 @@
"integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==",
"dev": true
},
"is2": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/is2/-/is2-2.0.7.tgz",
"integrity": "sha512-4vBQoURAXC6hnLFxD4VW7uc04XiwTTl/8ydYJxKvPwkWQrSjInkuM5VZVg6BGr1/natq69zDuvO9lGpLClJqvA==",
"dev": true,
"requires": {
"deep-is": "^0.1.3",
"ip-regex": "^4.1.0",
"is-url": "^1.2.4"
}
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -53936,6 +54210,12 @@
"ipaddr.js": "1.9.1"
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true
},
"prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@@ -54438,9 +54718,9 @@
"dev": true
},
"rimraf": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.1.tgz",
"integrity": "sha512-IQ4ikL8SjBiEDZfk+DFVwqRK8md24RWMEJkdSlgNLkyyAImcjf8SWvU1qFMDOb4igBClbTQ/ugPqXcRwdFTxZw==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
@@ -54557,6 +54837,18 @@
"commander": "^2.8.1"
}
},
"selenium-webdriver": {
"version": "4.0.0-beta.4",
"resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-beta.4.tgz",
"integrity": "sha512-+s/CIYkWzmnC9WASBxxVj7Lm0dcyl6OaFxwIJaFCT5WCuACiimEEr4lUnOOFP/QlKfkDQ56m+aRczaq2EvJEJg==",
"dev": true,
"requires": {
"jszip": "^3.6.0",
"rimraf": "^3.0.2",
"tmp": "^0.2.1",
"ws": ">=7.4.6"
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -55597,6 +55889,16 @@
"xtend": "^4.0.0"
}
},
"tcp-port-used": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz",
"integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==",
"dev": true,
"requires": {
"debug": "4.3.1",
"is2": "^2.0.6"
}
},
"terminal-link": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",

View File

@@ -6,6 +6,7 @@
"dependencies": {
"@types/react": "^16.9.22",
"@types/react-dom": "^16.9.5",
"@types/selenium-webdriver": "^4.0.15",
"babel": "^6.23.0",
"babel-core": "^6.26.3",
"babel-loader": "^8.0.6",
@@ -21,11 +22,13 @@
"@types/jquery": "^3.3.31",
"@typescript-eslint/eslint-plugin": "^4.9.1",
"@typescript-eslint/parser": "^4.9.1",
"chromedriver": "^92.0.0",
"copy-webpack-plugin": "^6.0.3",
"eslint": "^7.15.0",
"eslint-plugin-react": "^7.21.5",
"jest": "^27.0.6",
"rimraf": "^3.0.0",
"selenium-webdriver": "^4.0.0-beta.4",
"ts-jest": "^27.0.3",
"ts-loader": "^6.2.1",
"typescript": "~4.3",
@@ -53,7 +56,8 @@
"dev:firefox": "npm run build:dev:firefox && concurrently \"npm run web-run:firefox\" \"npm run build:watch:firefox\"",
"dev:firefox-android": "npm run build:dev:firefox && concurrently \"npm run web-run:firefox-android\" \"npm run build:watch:firefox\"",
"clean": "rimraf dist",
"test": "npx jest",
"test": "npm run build:chrome && npx jest",
"test-without-building": "npx jest",
"lint": "eslint src",
"lint:fix": "eslint src --fix"
},

View File

@@ -57,5 +57,35 @@
},
"manualPaused": {
"message": "تم إيقاف الموقت"
},
"confirmMSG": {
"message": "لتحرير أو حذف قيّم فردياً، انقر فوق زر المعلومات أو فتح الإضافة عن طريق النقر على أيقونة الإضافة في الزاوية اليمنى العليا."
},
"clearThis": {
"message": "هل أنت متأكد أنك تريد حذف هذا؟\n\n"
},
"Unknown": {
"message": "حدث خطأ في إرسال توقيت الرعاة الخاص بك، الرجاء المحاولة مرة أخرى لاحقاً."
},
"sponsorFound": {
"message": "يحتوي هذا الفيديو على أجزاء في قاعدة البيانات!"
},
"sponsor404": {
"message": "لم يتم العثور على أجزاء"
},
"sponsorStart": {
"message": "يبدأ الجزء الآن"
},
"sponsorEnd": {
"message": "ينتهي الجزء الآن"
},
"sponsorCancel": {
"message": "إلغاء إنشاء جزء"
},
"noVideoID": {
"message": "لم يتم العثور على فيديو يوتيوب.\nإذا كان هذا غير صحيح، قم بتحديث الصفحة."
},
"refreshSegments": {
"message": "تحديث الأجزاء"
}
}

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Задайте потребителско име"
},
"copyPublicID": {
"message": "Копиране на публичния UserID"
},
"discordAdvert": {
"message": "Елате в официалния Discord сървър, за да давате предложения!"
},

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Nastavit uživatelské jméno"
},
"copyPublicID": {
"message": "Kopírovat veřejné uživatelské ID"
},
"discordAdvert": {
"message": "Připojte se k oficiálnímu Discord serveru k podání návrhů a zpětné vazby!"
},

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Benutzernamen festlegen"
},
"copyPublicID": {
"message": "Öffentliche UserID kopieren"
},
"discordAdvert": {
"message": "Tritt dem offiziellen Discord-Server bei und teile Anregungen und Feedback!"
},
@@ -227,6 +230,21 @@
"showSkipNotice": {
"message": "Zeige Pop-up nach dem Überspringen eines Segments"
},
"noticeVisibilityMode0": {
"message": "Skip-Meldung in voller größe"
},
"noticeVisibilityMode1": {
"message": "Kleine Skip-Meldung für Auto-Skips"
},
"noticeVisibilityMode2": {
"message": "Alles kleine Skip-Meldungen"
},
"noticeVisibilityMode3": {
"message": "Verblasste Skip-Meldung für Auto-Skip"
},
"noticeVisibilityMode4": {
"message": "Alles verblasste Skip-Meldungen"
},
"longDescription": {
"message": "SponsorBlock lässt dich gesponserte Videosegmente, Intros, Outros, Interaktions-Erinnerungen, Musikvideoteile ohne Musik und andere nervige Teile von YouTube-Videos überspringen. SponsorBlock ist eine crowdsourced Browser-Erweiterung, in der jeder die Start- und Endzeit gesponserter Videosegmente und anderer Segmente von YouTube-Videos einreicht. Sobald eine Person diese Informationen einreicht, überspringen alle anderen mit dieser Erweiterung das gesponserte Segment.",
"description": "Full description of the extension on the store pages."
@@ -577,6 +595,9 @@
"autoSkip_POI": {
"message": "Automatisch zum Start springen"
},
"manualSkip_POI": {
"message": "Beim Laden des Videos fragen"
},
"showOverlay_POI": {
"message": "In der Video-Zeitleiste anzeigen"
},
@@ -693,6 +714,10 @@
"help": {
"message": "Hilfe"
},
"GotIt": {
"message": "Verstanden",
"description": "Used as the button to dismiss a tooltip"
},
"experiementOptOut": {
"message": "Abmeldung aller zukünftigen Experimente",
"description": "This is used in a popup about a new experiment to get a list of unlisted videos to back up since all unlisted videos uploaded before 2017 will be set to private."
@@ -706,5 +731,74 @@
"voteRejectedWarning": {
"message": "Abstimmung wegen einer Warnung abgelehnt. Um über sie zu reden, klicke hier, oder schreibe uns später.",
"description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser."
},
"Donate": {
"message": "Spenden"
},
"hideDonationLink": {
"message": "Verstecke Spendenlink"
},
"helpPageThanksForInstalling": {
"message": "Danke fürs installieren von SponsorBlock."
},
"helpPageReviewOptions": {
"message": "Bitte überprüfe die unten stehenden Optionen"
},
"helpPageFeatureDisclaimer": {
"message": "Viele Funktionen sind standardmäßig deaktiviert. Wenn du Intros und Outtros überspringen willst, Invidious verwenden willst, usw. aktiviere sie unten. Du kannst auch UI-Elemente verstecken/anzeigen."
},
"helpPageHowSkippingWorks": {
"message": "Wie überspringen funktioniert"
},
"helpPageHowSkippingWorks1": {
"message": "Videosegmente werden automatisch übersprungen, wenn sie in der Datenbank gefunden werden. Du kannst das Popup öffnen, indem du auf das Erweiterungssymbol klickst, um eine Vorschau zu erhalten, was sie sind."
},
"helpPageHowSkippingWorks2": {
"message": "Wannimmer du ein Segment überspringst, wirst du benachrichtigt. Wenn das Timing falsch erscheint, kannst du as durch klicken auf den Downvote button downvoten! Du kannst auch im Popup voten."
},
"Submitting": {
"message": "Übermitteln"
},
"helpPageSubmitting1": {
"message": "Das übermitteln kann entweder im Popup durch das drücken vom \"Segment Started Jetzt\" Knopf oder im Videoplayer mit den Knöpfen im Player gemacht werden."
},
"helpPageSubmitting2": {
"message": "Mit einem Klick auf den Play-Knopf wird der Beginn eines Segments und mit dem klick auf den Stop-Knopf das ende eines Segments markiert. Du kannst mehrere Sponsoren vorbereiten, bevor du auf Absenden klickst. Das klicken des Upload-Knopfes wird die Segmente übermitteln. Das klicken des Mülleimers löscht es."
},
"Editing": {
"message": "Bearbeitung"
},
"helpPageEditing1": {
"message": "Wenn du etwas falsch gemacht hast, kannst du ein Segment bearbeiten oder löschen nachdem du auf den Auf-Pfeil Knopf gedrückt hast."
},
"helpPageTooSlow": {
"message": "Das ist zu langsam"
},
"helpPageTooSlow1": {
"message": "Es gibt Hotkeys, wenn du diese verwenden möchtest. Drücke die Semikolon-Taste um den Anfang/das Ende eines Sponsor-Segments zu markieren und die Abostrphe-Taste um es zu übermitteln. Diese können in den Optionen geändert werden. Wenn du keine QWERTY-Tastatur verwendest, solltest du eventuell die Keybinds ändern."
},
"helpPageCopyOfDatabase": {
"message": "Kann ich eine kopie der Datenbank erhalten? Was passiert wenn du verschwindest?"
},
"helpPageCopyOfDatabase1": {
"message": "Die Datenbank ist öffentlich und verfügbar unter"
},
"helpPageCopyOfDatabase2": {
"message": "Der Quellcode ist frei verfügbar. Selbst wenn mir etwas passieren würde wären deine Übermittlungen nicht verloren."
},
"helpPageNews": {
"message": "Nachrichten und wie es gemacht wird"
},
"helpPageSourceCode": {
"message": "Wo kann ich den Quellcode kriegen?"
},
"Credits": {
"message": "Credits"
},
"highlightNewFeature": {
"message": "Neu! Gehe mit einem Klick zum Punkt des Videos mit der neuen Highlight Kategorie"
},
"LearnMore": {
"message": "Erfahre mehr"
}
}

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Set Username"
},
"copyPublicID": {
"message": "Copy Public UserID"
},
"discordAdvert": {
"message": "Come join the official discord server to give suggestions and feedback!"
},

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Escoger Nombre De Usuario"
},
"copyPublicID": {
"message": "Copiar el ID de usuario público"
},
"discordAdvert": {
"message": "¡Únete al servidor oficial de discord para darnos sugerencias y comentarios!"
},
@@ -360,16 +363,16 @@
"message": "Comprueba status.sponsor.ajay.app para ver el estado del servidor."
},
"changeUserID": {
"message": "Importar/Exportar tu UserID"
"message": "Importar/Exportar tu ID de usuario"
},
"whatChangeUserID": {
"message": "Esto debería mantenerse privado. Es como una contraseña y no debe ser compartido con nadie. Si alguien tiene esto, pueden imitarte."
},
"setUserID": {
"message": "Establecer la ID de usuario"
"message": "Establecer el ID de usuario"
},
"userIDChangeWarning": {
"message": "Advertencia: El cambio de la ID de usuario es irreversible. ¿Está seguro de que le desea hacerlo? Asegúrese de hacer una copia de respaldo de la anterior por si acaso."
"message": "Advertencia: El cambio del ID de usuario es irreversible. ¿Está seguro de que le desea hacerlo? Asegúrese de hacer una copia de respaldo de la anterior por si acaso."
},
"createdBy": {
"message": "Creado Por"

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Määra kasutajanimi"
},
"copyPublicID": {
"message": "Kopeeri avalik UserID"
},
"discordAdvert": {
"message": "Tule liitu ametliku Discordi serveriga, et anda soovitusi ja tagasisidet!"
},
@@ -227,6 +230,21 @@
"showSkipNotice": {
"message": "Kuva segmendi vahelejätmisel teatis"
},
"noticeVisibilityMode0": {
"message": "Täissuuruses vahelejätmise teavitused"
},
"noticeVisibilityMode1": {
"message": "Väikesed vahelejätmise teavitused autom. vahelejätmistele"
},
"noticeVisibilityMode2": {
"message": "Kõik vahelejätmise teavitused on väikesed"
},
"noticeVisibilityMode3": {
"message": "Hääbuvad vahelejätmise teavitused autom. vahelejätmistele"
},
"noticeVisibilityMode4": {
"message": "Kõik vahelejätmise teavitused hääbuvad"
},
"longDescription": {
"message": "SponsorBlock lubab sul vahele jätta sponsorid, vaheajad, kanali tellimise meeldetuletused ja muud YouTube'i videote tüütud kohad. SponsorBlock on rahva ühistööna toimiv brauserilaiendus, mis lubab igaühel saata sponsoreeritud segmendi algus- ja lõpuaegu ning teiste video segmentide aegu. Kui üks inimene saadab sponsoreeritud segmendi, jätavad teised laienduse kasutajad kohe selle vahele. Laiendus võimaldab ka muusikavideotel mitte-muusika jaotised vahele jätta.",
"description": "Full description of the extension on the store pages."
@@ -723,9 +741,15 @@
"helpPageThanksForInstalling": {
"message": "Täname SponsorBlocki paigaldamise eest."
},
"helpPageNews": {
"message": "Uudised ja kuidas see on valmistatud"
},
"Credits": {
"message": "Tiitrid"
},
"highlightNewFeature": {
"message": "Uus! Mine ühe klõpsuga video eesmärgi juurde uue \"esiletõstu\" kategooriaga"
},
"LearnMore": {
"message": "Lisateave"
}

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Aseta käyttäjänimi"
},
"copyPublicID": {
"message": "Kopio julkinen UserID"
},
"discordAdvert": {
"message": "Liity mukaan viralliselle Discord-palvelimelle, jotta voit antaa ehdotuksia ja palautetta!"
},
@@ -303,7 +306,7 @@
"message": "Ohita {0}?"
},
"skip_to_category": {
"message": "Ohita {0}an?",
"message": "Ohita kohtaan: {0}",
"description": "Used for skipping to things (Skip to Highlight)"
},
"skipped": {
@@ -311,7 +314,7 @@
"description": "Example: Sponsor Skipped"
},
"skipped_to_category": {
"message": "Ohitettiin {0}an",
"message": "Ohitettiin kohtaan: {0}",
"description": "Used for skipping to things (Skipped to Highlight)"
},
"disableAutoSkip": {

View File

@@ -431,6 +431,9 @@
"preview": {
"message": "Előnézet"
},
"unsubmitted": {
"message": "Nincs beküldve"
},
"inspect": {
"message": "Megvizsgál"
},
@@ -495,6 +498,9 @@
"category_outro_description": {
"message": "Stáblista, vagy amikor megjelennek a YouTube zárókártyák. Nem használandó információt tartalmazó következtetésekkor."
},
"category_preview": {
"message": "Előzetes/Ismétlés"
},
"category_music_offtopic": {
"message": "Zene: nem-zene szegmens"
},
@@ -597,5 +603,33 @@
},
"help": {
"message": "Segítség"
},
"GotIt": {
"message": "Értettem",
"description": "Used as the button to dismiss a tooltip"
},
"hideForever": {
"message": "Eltüntetés örökre"
},
"Donate": {
"message": "Támogatás"
},
"Submitting": {
"message": "Küldés"
},
"Editing": {
"message": "Szerkesztés"
},
"helpPageTooSlow": {
"message": "Ez túl lassú"
},
"helpPageNews": {
"message": "Hírek és hogyan készül"
},
"Credits": {
"message": "Készítők"
},
"LearnMore": {
"message": "Tudj meg többet"
}
}

View File

@@ -281,6 +281,18 @@
"skip_category": {
"message": "Lewati {0}?"
},
"skip_to_category": {
"message": "Lompat ke {0}?",
"description": "Used for skipping to things (Skip to Highlight)"
},
"skipped": {
"message": "{0} dilewati",
"description": "Example: Sponsor Skipped"
},
"skipped_to_category": {
"message": "Melewati ke {0}",
"description": "Used for skipping to things (Skipped to Highlight)"
},
"disableAutoSkip": {
"message": "Nonaktifkan Lewati Otomatis"
},
@@ -344,6 +356,9 @@
"keybindCurrentlySet": {
"message": ". Saat ini diatur pada:"
},
"supportOtherSites": {
"message": "Dukung Situs Youtube Pihak Ketiga"
},
"optionsInfo": {
"message": "Aktifkan dukungan Invidious, nonaktifkan lewati otomatis, tombol sembunyi dan lainnya."
},
@@ -428,6 +443,9 @@
"preview": {
"message": "Pratinjau"
},
"unsubmitted": {
"message": "Belum dikirim"
},
"inspect": {
"message": "Inspeksi"
},
@@ -492,6 +510,12 @@
"category_outro_description": {
"message": "Kredit atau saat kartu akhir YouTube muncul. Tidak untuk kesimpulan dengan informasi."
},
"category_preview": {
"message": "Pratinjau/Rekap"
},
"category_preview_description": {
"message": "Rekapan singkat dari episode sebelumnya, atau pratinjau tentang apa yang akan terjadi nanti di video. Dimaksudkan untuk klip bersama yang di edit, bukan ringkasan yang diucapkan."
},
"category_music_offtopic": {
"message": "Musik: Bagian Non-Musik"
},
@@ -519,9 +543,22 @@
"disable": {
"message": "Nonaktif"
},
"manualSkip_POI": {
"message": "Tanya saat video dimuat"
},
"showOverlay_POI": {
"message": "Tampilkan di Bilah Waktu"
},
"autoSkipOnMusicVideos": {
"message": "Lewati semua segmen secara otomatis ketika ada segmen non-music"
},
"colorFormatIncorrect": {
"message": "Warna anda tidak diformat dengan benar. Harusnya terdiri dari 3 atau 6 digit kode heksa dengan tagar di awal."
},
"previewColor": {
"message": "Warna yang Belum Dikirim",
"description": "Referring to submissions that have not been sent to the server yet."
},
"seekBarColor": {
"message": "Warna Bilah Waktu"
},
@@ -622,7 +659,29 @@
"categoryUpdate2": {
"message": "Buka opsi untuk melewati intro, outro, merch, dll."
},
"help": {
"message": "Bantuan"
},
"GotIt": {
"message": "Mengerti",
"description": "Used as the button to dismiss a tooltip"
},
"hideForever": {
"message": "Sembunyikan selamanya"
},
"Donate": {
"message": "Donasi"
},
"hideDonationLink": {
"message": "Sembunyikan tautan donasi"
},
"helpPageThanksForInstalling": {
"message": "Terima kasih telah menginstall SponsorBlock."
},
"helpPageReviewOptions": {
"message": "Haram ditinjau opsi di bawah ini"
},
"helpPageHowSkippingWorks": {
"message": "Cara kerja melewati segmen"
}
}

View File

@@ -227,6 +227,21 @@
"showSkipNotice": {
"message": "구간을 건너뛴 후 알림 표시"
},
"noticeVisibilityMode0": {
"message": "건너뛰기 알림 크게"
},
"noticeVisibilityMode1": {
"message": "자동 건너뛰기에 대해서는 건너뛰기 알림 작게"
},
"noticeVisibilityMode2": {
"message": "모든 건너뛰기 알림 작게"
},
"noticeVisibilityMode3": {
"message": "자동 건너뛰기에 대해서는 건너뛰기 알림 숨김"
},
"noticeVisibilityMode4": {
"message": "모든 건너뛰기 알림 숨김"
},
"longDescription": {
"message": "SponsorBlock을 사용하면 영상에서 스폰서 광고, 인트로 영상, 아웃트로 영상, 구독 광고와 그 외 쓸데없는 부분을 즉시 건너뛸 수 있습니다. SponsorBlock은 모든 사람들이 참여하는 브라우저 확장 기능으로 확장 기능 사용자는 스폰서 광고 또는 다른 광고의 시작 시간과 끝 시간을 확인하여 서버로 전송할 수 있습니다. 이러한 정보가 전송되면 그 영상을 보는 다른 사용자들은 광고 구간이 나오기 전에 자동으로 건너뛸 수 있습니다. SponsorBlock을 사용하면 뮤직 비디오에서 음악이나 노래가 아닌 구간도 건너뛸 수 있습니다.",
"description": "Full description of the extension on the store pages."
@@ -744,6 +759,9 @@
"helpPageSubmitting1": {
"message": "\"광고 구간 시작\" 버튼을 누른 다음 팝업에서 제출할 수도 있으며 동영상 플레이어 내 버튼으로 제출할 수도 있습니다."
},
"helpPageSubmitting2": {
"message": "재생 아이콘을 누르면 구간의 시점을 정할 수 있고 중지 아이콘을 누르면 구간의 종점을 정할 수 있습니다. 제출하기 전 여러 구간을 설정할 수 있습니다. 업로드 아이콘을 눌러 제출할 수 있습니다. 휴지통 아이콘을 눌러 구간을 제거할 수 있습니다."
},
"Editing": {
"message": "수정"
},
@@ -753,6 +771,18 @@
"helpPageTooSlow": {
"message": "너무 느립니다"
},
"helpPageTooSlow1": {
"message": "원하는 경우 단축키를 이용할 수 있습니다. 쌍반점 키를 눌러 스폰서 구간의 시점/종점을 설정할 수 있으며 작은따옴표 키를 눌러 구간을 제출할 수 있습니다. 설정에서 이를 변경할 수 있습니다. QWERTY 자판을 사용하지 않는 경우, 단축키 설정을 변경해야 할 수 있습니다."
},
"helpPageCopyOfDatabase": {
"message": "데이터베이스의 사본을 구할 수 있을까요? 개발자에게 무슨 일이 생기면 어떻게 되는 거죠?"
},
"helpPageCopyOfDatabase1": {
"message": "데이터베이스는 공개되어 있으며 다음 주소를 통해 접근할 수 있습니다"
},
"helpPageCopyOfDatabase2": {
"message": "소스 코드는 자유롭게 이용할 수 있습니다. 따라서 제게 무슨 일이 생기더라도, 기여 사항이 사라지는 일은 없습니다."
},
"helpPageNews": {
"message": "소식 및 제작 방법"
},

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Gebruikersnaam instellen"
},
"copyPublicID": {
"message": "Publieke gebruikers-ID kopiëren"
},
"discordAdvert": {
"message": "Word lid van de officiële Discord-server om suggesties en feedback te geven!"
},

View File

@@ -287,6 +287,10 @@
"skip_category": {
"message": "Pominąć {0}?"
},
"skip_to_category": {
"message": "Przejść do {0}?",
"description": "Used for skipping to things (Skip to Highlight)"
},
"disableAutoSkip": {
"message": "Wyłącz autopomijanie"
},
@@ -538,6 +542,9 @@
"category_music_offtopic_short": {
"message": "Bez muzyki"
},
"category_poi_highlight": {
"message": "Podświetlone"
},
"category_livestream_messages": {
"message": "Transmisja live: Dotacja/Czytanie wiadomości"
},
@@ -682,5 +689,14 @@
"voteRejectedWarning": {
"message": "Głosowanie odrzucone z powodu ostrzeżenia. Kliknij, aby otworzyć czat w celu rozwiązania problemu lub wróć później, gdy będziesz miał czas.",
"description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser."
},
"helpPageSourceCode": {
"message": "Gdzie mogę otrzymać kod źródłowy?"
},
"Credits": {
"message": "Autorzy"
},
"LearnMore": {
"message": "Dowiedz się więcej"
}
}

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Установить имя пользователя"
},
"copyPublicID": {
"message": "Копировать публичный UserID"
},
"discordAdvert": {
"message": "Присоединяйтесь к официальному серверу Discord, чтобы оставить предложения и обратную связь!"
},

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Nastaviť Používateľské meno"
},
"copyPublicID": {
"message": "Skopírovať verejné ID používateľa"
},
"discordAdvert": {
"message": "Pripojte sa k oficiálnemu Discord serveru a zanechajte nám pripomienky!"
},

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Ange användarnamn"
},
"copyPublicID": {
"message": "Kopiera publikt Användar-ID"
},
"discordAdvert": {
"message": "Gå med i den officiella discordservern för att ge förslag och feedback!"
},

View File

@@ -161,6 +161,9 @@
"setUsername": {
"message": "Встановити ім'я користувача"
},
"copyPublicID": {
"message": "Копіювати публічний UserID"
},
"discordAdvert": {
"message": "Приєднуйтесь до офіційного сервера Discord, щоб залишити пропозиції і зворотний зв'язок!"
},
@@ -227,6 +230,21 @@
"showSkipNotice": {
"message": "Показувати сповіщення після пропуску сегмента"
},
"noticeVisibilityMode0": {
"message": "Повнорозмірні сповіщення про пропуски"
},
"noticeVisibilityMode1": {
"message": "Зменшені сповіщення для автоматичних пропусків"
},
"noticeVisibilityMode2": {
"message": "Всі сповіщення зменшеного розміру"
},
"noticeVisibilityMode3": {
"message": "Напівпрозорі сповіщення для автоматичних пропусків"
},
"noticeVisibilityMode4": {
"message": "Напівпрозорі сповіщення для всіх пропусків"
},
"longDescription": {
"message": "SponsorBlock дозволяє пропускати спонсорські вставки, початкові і кінцеві заставки, прохання підписатися і інше в відео на YouTube. SponsorBlock - колективне розширення, яке дозволяє кожному надіслати час початку і кінця подібних сегментів в відео. Після того, як хто-небудь надсилає цю інформацію, всі інші користувачі розширення будуть автоматично пропускати ці сегменти. Так само можна пропускати частини кліпів без музики.",
"description": "Full description of the extension on the store pages."
@@ -696,6 +714,10 @@
"help": {
"message": "Довідка"
},
"GotIt": {
"message": "Зрозуміло",
"description": "Used as the button to dismiss a tooltip"
},
"experiementOptOut": {
"message": "Відмова від усіх майбутніх експериментів",
"description": "This is used in a popup about a new experiment to get a list of unlisted videos to back up since all unlisted videos uploaded before 2017 will be set to private."
@@ -709,5 +731,74 @@
"voteRejectedWarning": {
"message": "Голосування відхилено через попередження. Натисніть, щоб відкрити чат для вирішення цієї проблеми, або поверніться пізніше.",
"description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser."
},
"Donate": {
"message": "Пожертвувати"
},
"hideDonationLink": {
"message": "Приховати посилання на пожертвування"
},
"helpPageThanksForInstalling": {
"message": "Дякую за встановлення SponsorBlock."
},
"helpPageReviewOptions": {
"message": "Будь ласка, ознайомтеся з налаштуваннями нижче"
},
"helpPageFeatureDisclaimer": {
"message": "Багато функцій за замовчуванням відключені. Якщо ви хочете пропускати початкові і кінцеві заставки, використовувати Invidious, тощо, увімкніть їх нижче. Ви також можете приховати / показати елементи інтерфейсу."
},
"helpPageHowSkippingWorks": {
"message": "Як працює пропуск"
},
"helpPageHowSkippingWorks1": {
"message": "Сегменти відео будуть автоматично пропущені, якщо вони знаходяться в базі даних. Ви можете відкрити спливаюче вікно, натиснувши на значок розширення, щоб подивитися, які сегменти додані."
},
"helpPageHowSkippingWorks2": {
"message": "Коли ви будете пропускати сегмент, ви отримаєте сповіщення. Якщо час здасться вам неправильним, проголосуйте проти, натиснувши на палець вниз! Ви також можете проголосувати у спливаючому вікні."
},
"Submitting": {
"message": "Відправлення"
},
"helpPageSubmitting1": {
"message": "Відправлення може бути виконана у спливаючому вікні натисканням на кнопку \"Сегмент починається звідси\" або кнопками в відеоплеєрі."
},
"helpPageSubmitting2": {
"message": "Натискання на кнопку відтворення означає початок сегмента і натискання на кнопку стоп позначає його кінець. Ви можете позначити кілька сегментів перед тим, як натиснути на кнопку відправлення. Натискання на кошик видалить все."
},
"Editing": {
"message": "Редагування"
},
"helpPageEditing1": {
"message": "Якщо ви зробили щось не так, ви можете відредагувати або видалити сегменти, натиснувши на кнопку зі стрілкою вгору."
},
"helpPageTooSlow": {
"message": "Це занадто повільно"
},
"helpPageTooSlow1": {
"message": "Все це також можна робити за допомогою гарячих клавіш. Натисніть \"ж\" для вказівки початку/кінця сегмента, \"є\" для відправки. Клавіші можуть бути змінені в налаштуваннях. Якщо ви не використовуєте QWERTY, то варто відразу поміняти гарячі клавіші."
},
"helpPageCopyOfDatabase": {
"message": "Чи можу я отримати копію бази даних? Що якщо ви пропадете?"
},
"helpPageCopyOfDatabase1": {
"message": "База даних доступна для всіх тут:"
},
"helpPageCopyOfDatabase2": {
"message": "Вихідний код у відкритому доступі, так що навіть якщо щось трапиться зі мною, ваш вклад не пропаде."
},
"helpPageNews": {
"message": "Новини та як це зроблено"
},
"helpPageSourceCode": {
"message": "Де можна отримати вихідний код?"
},
"Credits": {
"message": "Автори"
},
"highlightNewFeature": {
"message": "Новинка! Переходьте відразу до головного моменту відео за допомогою нової категорії \"Важливе\""
},
"LearnMore": {
"message": "Дізнатися більше"
}
}

View File

@@ -227,6 +227,21 @@
"showSkipNotice": {
"message": "Hiển thị thông báo sau khi bỏ qua quảng cáo"
},
"noticeVisibilityMode0": {
"message": "Thông báo bỏ qua với kích thước đầy đủ"
},
"noticeVisibilityMode1": {
"message": "Thông báo bỏ qua kích thước nhỏ nếu phân đoạn được tự động bỏ qua"
},
"noticeVisibilityMode2": {
"message": "Thông báo bỏ qua kích thước nhỏ cho toàn bộ phân đoạn"
},
"noticeVisibilityMode3": {
"message": "Thông báo bỏ qua mờ nếu phân đoạn được tự động bỏ qua"
},
"noticeVisibilityMode4": {
"message": "Thông báo bỏ qua mờ cho tất cả các phân đoạn"
},
"longDescription": {
"message": "SponsorBlock giúp bạn bỏ qua quảng cáo từ nhà tài trợ, đoạn giới thiệu, đoạn kết, lời nhắc đăng ký kênh, và những phần khó chịu khác trong các video Youtube. SponsorBlock là một tiện ích mở rộng cho trình duyệt, cho phép tất cả người dùng đăng thời điểm bắt đầu và kết thúc của những đoạn quảng cáo từ nhà tài trợ và các đoạn khác trong video Youtube. Sau khi một người đăng thông tin này lên, tất cả mọi người dùng tiện ích mở rộng này sẽ bỏ qua đoạn quảng cáo đó. Bạn cũng có thể bỏ qua phần không có nhạc trong những video âm nhạc.",
"description": "Full description of the extension on the store pages."
@@ -682,5 +697,14 @@
"voteRejectedWarning": {
"message": "Bỏ phiếu bị từ chối do có cảnh báo. Nhấp để mở cuộc trò chuyện để giải quyết hoặc quay lại sau.",
"description": "This is an integrated chat panel that will appearing allowing them to talk to the Discord/Matrix chat without leaving their browser."
},
"hideDonationLink": {
"message": "Ẩn link donate"
},
"helpPageThanksForInstalling": {
"message": "Cảm ơn bạn đã cài đặt SponsorBlock."
},
"helpPageTooSlow": {
"message": "Quá chậm"
}
}

View File

@@ -140,7 +140,6 @@
min-width: 350px;
max-width: 50%;
border-radius: 5px;
border-spacing: 5px 10px;
padding-left: 5px;
padding-right: 5px;
@@ -148,13 +147,20 @@
border-collapse: unset;
}
.sponsorSkipNotice {
min-width: 350px;
.sponsorSkipNoticeTableContainer {
background-color: rgba(28, 28, 28, 0.9);
border-radius: 5px;
min-width: 100%;
}
.sponsorSkipNotice {
transition: all 0.1s ease-out;
}
.sponsorSkipNoticeLimitWidth {
min-width: calc(100% - 50px);
}
.sponsorSkipNotice .hidden {
display: none;
}
@@ -311,7 +317,6 @@
.sponsorTimesInfoMessage {
font-size: 13.3333px;
color: rgb(235, 235, 235);
text-align: center;
}
.voteButton {

View File

@@ -119,7 +119,7 @@
<a href="https://github.com/ajayyy/SponsorBlockServer/graphs/contributors">SponsorBlockServer contributors</a> and
<a href="https://github.com/ajayyy/SponsorBlockSite/graphs/contributors">SponsorBlockSite contributors</a> such
as <a href="https://github.com/NDevTK">NDev</a>, <a href="https://github.com/Joe-Dowd">Joe Dowd</a>,
<a href="https://github.com/bershanskiy">Anton Bershanskiy</a> and more.
<a href="https://mchang.name/">Michael Chang</a> and more.
</p>
<p>The awesome <a href="https://github.com/omarroth/invidious/wiki/API">Invidious API</a> is used to grab the time the video was published.</p>

View File

@@ -265,7 +265,7 @@ background-color:#ec1c1c;
align-items: center;
}
.sbSlimButton, #additionalButtons>button, button#setUsernameButton, #submitUsername {
.sbSlimButton, #additionalButtons>button, button#setUsernameButton, #submitUsername, #copyUserID {
background: none;
border: none;
color: white;
@@ -341,6 +341,14 @@ label>p, #disableExtension>p, #usernameValue, #usernameElement > div > p,#sponso
cursor: pointer;
}
#copyUserID {
width: 100%;
}
#setUsernameContainer {
display: flex;
}
#usernameElement > div, #sponsorTimesContributionsContainer > div {
display: flex;
flex-flow: column nowrap;

View File

@@ -19,7 +19,7 @@
<p id="loadingIndicator">__MSG_noVideoID__</p>
<!-- If the video was found in the database -->
<p id="videoFound"></p>
<button class="sbSlimButton hidden" id="refreshSegmentsButton" title="__MSG_refreshSegments__">
<button class="sbSlimButton" id="refreshSegmentsButton" title="__MSG_refreshSegments__">
<img id="refreshSegments" src="/icons/refresh.svg"/>
</button>
</div>
@@ -90,6 +90,9 @@
<button id="setUsernameButton" title="__MSG_setUsername__">
<img src="/icons/pencil.svg" alt="__MSG_setUsername__" width="16" height="16" id="sbPopupIconEdit">
</button>
<button id="copyUserID" title="__MSG_copyPublicID__">
<img src="/icons/clipboard.svg" alt="__MSG_copyPublicID__" width="16" height="16" id="sbPopupIconCopyUserID">
</button>
</div>
<div id="setUsername" style="display: none">
<div id="setUsernameStatusContainer" style="display: none">

View File

@@ -81,7 +81,7 @@ chrome.runtime.onInstalled.addListener(function () {
//save this UUID
Config.config.userID = newUserID;
Config.config.highlightCategoryUpdate = false;
Config.config.highlightCategoryUpdate = true;
}
}, 1500);
});

View File

@@ -25,6 +25,7 @@ export interface NoticeProps {
bottomRow?: React.ReactElement[],
smaller?: boolean,
limitWidth?: boolean,
// Callback for when this is closed
closeListener: () => void,
@@ -102,65 +103,69 @@ class NoticeComponent extends React.Component<NoticeProps, NoticeState> {
onMouseEnter={(e) => this.onMouseEnter(e) }
onMouseLeave={() => this.timerMouseLeave()}
style={noticeStyle} >
<table className={"sponsorSkipObject sponsorSkipNotice"
<div className={"sponsorSkipNoticeTableContainer"
+ (this.props.fadeIn ? " sponsorSkipNoticeFadeIn" : "")
+ (this.state.startFaded ? " sponsorSkipNoticeFaded" : "") } >
<tbody>
+ (this.state.startFaded ? " sponsorSkipNoticeFaded" : "") }>
<table className={"sponsorSkipObject sponsorSkipNotice"
+ (this.props.limitWidth ? " sponsorSkipNoticeLimitWidth" : "")}>
<tbody>
{/* First row */}
<tr id={"sponsorSkipNoticeFirstRow" + this.idSuffix}>
{/* Left column */}
<td className="noticeLeftIcon">
{/* Logo */}
<img id={"sponsorSkipLogo" + this.idSuffix}
className="sponsorSkipLogo sponsorSkipObject"
src={chrome.extension.getURL("icons/IconSponsorBlocker256px.png")}>
</img>
{/* First row */}
<tr id={"sponsorSkipNoticeFirstRow" + this.idSuffix}
className="sponsorSkipNoticeFirstRow">
{/* Left column */}
<td className="noticeLeftIcon">
{/* Logo */}
<img id={"sponsorSkipLogo" + this.idSuffix}
className="sponsorSkipLogo sponsorSkipObject"
src={chrome.extension.getURL("icons/IconSponsorBlocker256px.png")}>
</img>
<span id={"sponsorSkipMessage" + this.idSuffix}
style={{float: "left"}}
className="sponsorSkipMessage sponsorSkipObject">
{this.state.noticeTitle}
</span>
{this.props.firstColumn}
</td>
{this.props.firstRow}
{/* Right column */}
<td className="sponsorSkipNoticeRightSection"
style={{top: "9.32px"}}>
{/* Time left */}
{this.props.timed ? (
<span id={"sponsorSkipNoticeTimeLeft" + this.idSuffix}
onClick={() => this.toggleManualPause()}
className="sponsorSkipObject sponsorSkipNoticeTimeLeft">
{this.getCountdownElements()}
<span id={"sponsorSkipMessage" + this.idSuffix}
style={{float: "left"}}
className="sponsorSkipMessage sponsorSkipObject">
{this.state.noticeTitle}
</span>
) : ""}
{this.props.firstColumn}
</td>
{this.props.firstRow}
{/* Right column */}
<td className="sponsorSkipNoticeRightSection"
style={{top: "9.32px"}}>
{/* Time left */}
{this.props.timed ? (
<span id={"sponsorSkipNoticeTimeLeft" + this.idSuffix}
onClick={() => this.toggleManualPause()}
className="sponsorSkipObject sponsorSkipNoticeTimeLeft">
{this.getCountdownElements()}
</span>
) : ""}
{/* Close button */}
<img src={chrome.extension.getURL("icons/close.png")}
className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeCloseButton sponsorSkipNoticeRightButton"
onClick={() => this.close()}>
</img>
</td>
</tr>
{/* Close button */}
<img src={chrome.extension.getURL("icons/close.png")}
className="sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeCloseButton sponsorSkipNoticeRightButton"
onClick={() => this.close()}>
</img>
</td>
</tr>
{this.props.children}
{this.props.children}
{!this.props.smaller && this.props.bottomRow ?
this.props.bottomRow
: null}
{!this.props.smaller && this.props.bottomRow ?
this.props.bottomRow
: null}
</tbody>
</table>
</tbody>
</table>
</div>
{/* Add as a hidden table to keep the height constant */}
{this.props.smaller && this.props.bottomRow ?

View File

@@ -165,6 +165,7 @@ class SkipNoticeComponent extends React.Component<SkipNoticeProps, SkipNoticeSta
ref={this.noticeRef}
closeListener={() => this.closeListener()}
smaller={this.state.smaller}
limitWidth={true}
firstColumn={firstColumn}
bottomRow={[...this.getMessageBoxes(), ...this.getBottomRow() ]}
onMouseEnter={() => this.onMouseEnter() } >

View File

@@ -444,8 +444,7 @@ function startSponsorSchedule(includeIntersectingSegments = false, currentTime?:
}
// Don't skip if this category should not be skipped
if (utils.getCategorySelection(currentSkip.category)?.option === CategorySkipOption.ShowOverlay
&& skipInfo.array !== sponsorTimesSubmitting) return;
if (!shouldSkip(currentSkip) && skipInfo.array !== sponsorTimesSubmitting) return;
const skippingFunction = () => {
let forcedSkipTime: number = null;
@@ -579,7 +578,7 @@ function setupVideoListeners() {
const currentPoiSegment = sponsorTimes.find((segment) =>
getCategoryActionType(segment.category) === CategoryActionType.POI &&
video.currentTime - segment.segment[0] > 0 &&
video.currentTime - segment.segment[0] < video.duration * 0.006); // Approximate size on preview bar
video.currentTime - segment.segment[0] < previewBar.getMinimumSize(true));
if (currentPoiSegment && !skipNotices.some((notice) => notice.segments.some((s) => s.UUID === currentPoiSegment.UUID))) {
skipToTime({
v: video,
@@ -676,7 +675,8 @@ async function sponsorsLookup(id: string, keepOldSubmissions = true) {
// Hide all submissions smaller than the minimum duration
if (Config.config.minDuration !== 0) {
for (let i = 0; i < sponsorTimes.length; i++) {
if (sponsorTimes[i].segment[1] - sponsorTimes[i].segment[0] < Config.config.minDuration) {
if (sponsorTimes[i].segment[1] - sponsorTimes[i].segment[0] < Config.config.minDuration
&& getCategoryActionType(sponsorTimes[i].category) !== CategoryActionType.POI) {
sponsorTimes[i].hidden = SponsorHideType.MinimumDuration;
}
}
@@ -962,14 +962,14 @@ function getNextSkipIndex(currentTime: number, includeIntersectingSegments: bool
if ((minUnsubmittedSponsorTimeIndex === -1 && minSponsorTimeIndex !== -1) ||
sponsorStartTimes[minSponsorTimeIndex] < unsubmittedSponsorStartTimes[minUnsubmittedSponsorTimeIndex]) {
return {
array: sponsorTimes,
array: sponsorTimes.filter((segment) => getCategoryActionType(segment.category) === CategoryActionType.Skippable),
index: minSponsorTimeIndex,
endIndex: endTimeIndex,
openNotice: true
};
} else {
return {
array: sponsorTimesSubmitting,
array: sponsorTimesSubmitting.filter((segment) => getCategoryActionType(segment.category) === CategoryActionType.Skippable),
index: minUnsubmittedSponsorTimeIndex,
endIndex: previewEndTimeIndex,
openNotice: false
@@ -993,7 +993,7 @@ function getNextSkipIndex(currentTime: number, includeIntersectingSegments: bool
function getLatestEndTimeIndex(sponsorTimes: SponsorTime[], index: number, hideHiddenSponsors = true): number {
// Only combine segments for AutoSkip
if (index == -1 ||
shouldAutoSkip(sponsorTimes[index])) return index;
!shouldAutoSkip(sponsorTimes[index])) return index;
// Default to the normal endTime
let latestEndTimeIndex = index;
@@ -1038,7 +1038,7 @@ function getStartTimes(sponsorTimes: SponsorTime[], includeIntersectingSegments:
if ((minimum === undefined
|| ((includeNonIntersectingSegments && sponsorTimes[i].segment[0] >= minimum)
|| (includeIntersectingSegments && sponsorTimes[i].segment[0] < minimum && sponsorTimes[i].segment[1] > minimum)))
&& (!onlySkippableSponsors || utils.getCategorySelection(sponsorTimes[i].category).option !== CategorySkipOption.ShowOverlay)
&& (!onlySkippableSponsors || shouldSkip(sponsorTimes[i]))
&& (!hideHiddenSponsors || sponsorTimes[i].hidden === SponsorHideType.Visible)
&& getCategoryActionType(sponsorTimes[i].category) === CategoryActionType.Skippable) {
@@ -1085,10 +1085,13 @@ function sendTelemetryAndCount(skippingSegments: SponsorTime[], secondsSkipped:
//skip from the start time to the end time for a certain index sponsor time
function skipToTime({v, skipTime, skippingSegments, openNotice, forceAutoSkip, unskipTime}: SkipToTimeParams): void {
if (Config.config.disableSkipping) return;
// There will only be one submission if it is manual skip
const autoSkip: boolean = forceAutoSkip || shouldAutoSkip(skippingSegments[0]);
if ((autoSkip || sponsorTimesSubmitting.includes(skippingSegments[0])) && v.currentTime !== skipTime[1]) {
if ((autoSkip || sponsorTimesSubmitting.some((time) => time.segment === skippingSegments[0].segment))
&& v.currentTime !== skipTime[1]) {
// Fix for looped videos not working when skipping to the end #426
// for some reason you also can't skip to 1 second before the end
if (v.loop && v.duration > 1 && skipTime[1] >= v.duration - 1) {
@@ -1190,6 +1193,12 @@ function createButton(baseID: string, title: string, callback: () => void, image
function shouldAutoSkip(segment: SponsorTime): boolean {
return utils.getCategorySelection(segment.category)?.option === CategorySkipOption.AutoSkip ||
(Config.config.autoSkipOnMusicVideos && sponsorTimes.some((s) => s.category === "music_offtopic")
&& getCategoryActionType(segment.category) === CategoryActionType.Skippable);
}
function shouldSkip(segment: SponsorTime): boolean {
return utils.getCategorySelection(segment.category)?.option !== CategorySkipOption.ShowOverlay ||
(Config.config.autoSkipOnMusicVideos && sponsorTimes.some((s) => s.category === "music_offtopic"));
}
@@ -1451,11 +1460,13 @@ function openInfoMenu() {
const logo = <HTMLImageElement> popup.querySelector("#sponsorBlockPopupLogo");
const settings = <HTMLImageElement> popup.querySelector("#sbPopupIconSettings");
const edit = <HTMLImageElement> popup.querySelector("#sbPopupIconEdit");
const copy = <HTMLImageElement> popup.querySelector("#sbPopupIconCopyUserID");
const check = <HTMLImageElement> popup.querySelector("#sbPopupIconCheck");
const refreshSegments = <HTMLImageElement> popup.querySelector("#refreshSegments");
logo.src = chrome.extension.getURL("icons/IconSponsorBlocker256px.png");
settings.src = chrome.extension.getURL("icons/settings.svg");
edit.src = chrome.extension.getURL("icons/pencil.svg");
copy.src = chrome.extension.getURL("icons/clipboard.svg");
check.src = chrome.extension.getURL("icons/check.svg");
refreshSegments.src = chrome.extension.getURL("icons/refresh.svg");
@@ -1620,7 +1631,8 @@ async function sendSubmitMessage() {
// Check to see if any of the submissions are below the minimum duration set
if (Config.config.minDuration > 0) {
for (let i = 0; i < sponsorTimesSubmitting.length; i++) {
if (sponsorTimesSubmitting[i].segment[1] - sponsorTimesSubmitting[i].segment[0] < Config.config.minDuration) {
if (sponsorTimesSubmitting[i].segment[1] - sponsorTimesSubmitting[i].segment[0] < Config.config.minDuration
&& getCategoryActionType(sponsorTimesSubmitting[i].category) !== CategoryActionType.POI) {
const confirmShort = chrome.i18n.getMessage("shortCheck") + "\n\n" +
getSegmentsMessage(sponsorTimesSubmitting);

View File

@@ -102,10 +102,12 @@ class PreviewBar {
let segment: PreviewBarSegment | null = null;
let currentSegmentLength = Infinity;
for (const seg of this.segments) {
for (const seg of this.segments) {//
const segmentLength = seg.segment[1] - seg.segment[0];
const minSize = this.getMinimumSize(seg.showLarger);
const startTime = segmentLength !== 0 ? seg.segment[0] : Math.floor(seg.segment[0]);
const endTime = segmentLength !== 0 ? seg.segment[1] : Math.ceil(seg.segment[1]);
const endTime = segmentLength > minSize ? seg.segment[1] : Math.ceil(seg.segment[0] + minSize);
if (startTime <= timeInSeconds && endTime >= timeInSeconds) {
if (segmentLength < currentSegmentLength) {
currentSegmentLength = segmentLength;
@@ -218,6 +220,13 @@ class PreviewBar {
timeToPercentage(time: number): string {
return Math.min(100, time / this.videoDuration * 100) + '%';
}
/*
* Approximate size on preview bar for smallest element (due to &nbsp)
*/
getMinimumSize(showLarger = false): number {
return this.videoDuration * (showLarger ? 0.006 : 0.003);
}
}
export default PreviewBar;

View File

@@ -51,7 +51,7 @@ export class SkipButtonControlBar {
const leftControlsContainer = document.querySelector(".ytp-left-controls");
this.chapterText = document.querySelector(".ytp-chapter-container");
if (!leftControlsContainer.contains(this.container)) {
if (leftControlsContainer && !leftControlsContainer.contains(this.container)) {
leftControlsContainer.insertBefore(this.container, this.chapterText);
}
}

View File

@@ -1,9 +1,10 @@
import Config from "./config";
import Utils from "./utils";
import { SponsorTime, SponsorHideType } from "./types";
import { SponsorTime, SponsorHideType, CategoryActionType } from "./types";
import { Message, MessageResponse } from "./messageTypes";
import { showDonationLink } from "./utils/configUtils";
import { getCategoryActionType } from "./utils/categoryUtils";
const utils = new Utils();
interface MessageListener {
@@ -96,6 +97,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
"usernameInput",
"usernameValue",
"submitUsername",
"sbPopupIconCopyUserID",
// More
"submissionSection",
"mainControls",
@@ -134,6 +136,7 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
PageElements.optionsButton.addEventListener("click", openOptions);
PageElements.helpButton.addEventListener("click", openHelp);
PageElements.refreshSegmentsButton.addEventListener("click", refreshSegments);
PageElements.sbPopupIconCopyUserID.addEventListener("click", async () => navigator.clipboard.writeText(await utils.getHash(Config.config.userID)));
/** If true, the content script is in the process of creating a new segment. */
let creatingSegment = false;
@@ -291,12 +294,10 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
if (request.found) {
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound");
PageElements.refreshSegmentsButton.classList.remove("hidden");
displayDownloadedSponsorTimes(request);
} else {
PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404");
PageElements.refreshSegmentsButton.classList.add("hidden");
}
}
@@ -401,7 +402,10 @@ async function runThePopup(messageListener?: MessageListener): Promise<void> {
const textNode = document.createTextNode(utils.shortCategoryName(segmentTimes[i].category) + extraInfo);
const segmentTimeFromToNode = document.createElement("div");
segmentTimeFromToNode.innerText = utils.getFormattedTime(segmentTimes[i].segment[0], true) + " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segmentTimes[i].segment[1], true);
segmentTimeFromToNode.innerText = utils.getFormattedTime(segmentTimes[i].segment[0], true) +
(getCategoryActionType(segmentTimes[i].category) !== CategoryActionType.POI
? " " + chrome.i18n.getMessage("to") + " " + utils.getFormattedTime(segmentTimes[i].segment[1], true)
: "");
segmentTimeFromToNode.style.margin = "5px";
sponsorTimeButton.appendChild(categoryColorCircle);

View File

@@ -54,7 +54,7 @@ class SkipNotice {
}
setShowKeybindHint(value: boolean): void {
this.skipNoticeRef.current.setState({
this.skipNoticeRef?.current?.setState({
showKeybindHint: value
});
}
@@ -69,7 +69,7 @@ class SkipNotice {
}
toggleSkip(): void {
this.skipNoticeRef.current.prepAction(SkipNoticeAction.Unskip);
this.skipNoticeRef?.current?.prepAction(SkipNoticeAction.Unskip);
}
}

119
test/selenium.test.ts Normal file
View File

@@ -0,0 +1,119 @@
import { Builder, By, until, WebDriver } from "selenium-webdriver";
import * as Chrome from "selenium-webdriver/chrome";
import * as Path from "path";
test("Selenium Chrome test", async () => {
const driver = await setup();
try {
await waitForInstall(driver);
// This video has no ads
await goToVideo(driver, "jNQXAC9IVRw");
await createSegment(driver, "4", "10.33", "0:04.000 to 0:10.330");
await editSegments(driver, 0, "0:04.000", "0:10.330", "5", "13.211", "0:05.000 to 0:13.211", false);
await autoskipSegment(driver, 5, 13.211);
} finally {
await driver.quit();
}
}, 100_000);
async function setup(): Promise<WebDriver> {
const options = new Chrome.Options();
options.addArguments("--load-extension=" + Path.join(__dirname, "../dist/"));
options.addArguments("--mute-audio");
options.addArguments("--disable-features=PreloadMediaEngagementData, MediaEngagementBypassAutoplayPolicies")
const driver = await new Builder().forBrowser("chrome").setChromeOptions(options).build();
driver.manage().setTimeouts({
implicit: 5000
});
return driver;
}
async function waitForInstall(driver: WebDriver, startingTab = 0): Promise<void> {
// Selenium only knows about the one tab it's on,
// so we can't wait for the help page to appear
await driver.sleep(3000);
const handles = await driver.getAllWindowHandles();
await driver.switchTo().window(handles[startingTab]);
}
async function goToVideo(driver: WebDriver, videoId: string): Promise<void> {
await driver.get("https://www.youtube.com/watch?v=" + videoId);
await driver.wait(until.elementIsVisible(await driver.findElement(By.className("ytd-video-primary-info-renderer"))));
}
async function createSegment(driver: WebDriver, startTime: string, endTime: string, expectedDisplayedTime: string): Promise<void> {
const startSegmentButton = await driver.findElement(By.id("startSegmentButton"));
const cancelSegmentButton = await driver.findElement(By.id("cancelSegmentButton"));
await driver.executeScript("document.querySelector('video').currentTime = " + startTime);
await startSegmentButton.click();
await driver.wait(until.elementIsVisible(cancelSegmentButton));
await driver.executeScript("document.querySelector('video').currentTime = " + endTime);
await startSegmentButton.click();
await driver.wait(until.elementIsNotVisible(cancelSegmentButton));
const submitButton = await driver.findElement(By.id("submitButton"));
await submitButton.click();
const sponsorTimeDisplays = await driver.findElements(By.className("sponsorTimeDisplay"));
const sponsorTimeDisplay = sponsorTimeDisplays[sponsorTimeDisplays.length - 1];
await driver.wait(until.elementTextIs(sponsorTimeDisplay, expectedDisplayedTime));
}
async function editSegments(driver: WebDriver, index: number, expectedStartTimeBox: string, expectedEndTimeBox: string,
startTime: string, endTime: string, expectedDisplayedTime: string, openSubmitBox: boolean): Promise<void> {
if (openSubmitBox) {
const submitButton = await driver.findElement(By.id("submitButton"));
await submitButton.click();
}
let editButton = await driver.findElement(By.id("sponsorTimeEditButtonSubmissionNotice" + index));
let sponsorTimeDisplays = await driver.findElements(By.className("sponsorTimeDisplay"));
let sponsorTimeDisplay = sponsorTimeDisplays[index];
await sponsorTimeDisplay.click();
// Ensure edit time appears
await driver.findElement(By.id("submittingTime0SubmissionNotice" + index));
// Try the edit button too
await editButton.click();
await editButton.click();
const startTimeBox = await driver.findElement(By.id("submittingTime0SubmissionNotice" + index));
expect((await startTimeBox.getAttribute("value"))).toBe(expectedStartTimeBox);
await startTimeBox.clear();
await startTimeBox.sendKeys(startTime);
const endTimeBox = await driver.findElement(By.id("submittingTime1SubmissionNotice" + index));
expect((await endTimeBox.getAttribute("value"))).toBe(expectedEndTimeBox);
await endTimeBox.clear();
await endTimeBox.sendKeys(endTime);
editButton = await driver.findElement(By.id("sponsorTimeEditButtonSubmissionNotice" + index));
await editButton.click();
sponsorTimeDisplays = await driver.findElements(By.className("sponsorTimeDisplay"));
sponsorTimeDisplay = sponsorTimeDisplays[index];
await driver.wait(until.elementTextIs(sponsorTimeDisplay, expectedDisplayedTime));
}
async function autoskipSegment(driver: WebDriver, startTime: number, endTime: number): Promise<void> {
const video = await driver.findElement(By.css("video"));
await driver.executeScript("document.querySelector('video').currentTime = " + (startTime - 0.5));
await driver.executeScript("document.querySelector('video').play()");
await driver.sleep(1300);
expect(parseFloat(await video.getAttribute("currentTime"))).toBeGreaterThan(endTime);
await driver.executeScript("document.querySelector('video').pause()");
}