mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-04 11:44:00 +00:00
Merge branch 'master' into feature/emoji_rfc
This commit is contained in:
commit
e87dbcd0fd
20 changed files with 518 additions and 211 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "frankerfacez",
|
"name": "frankerfacez",
|
||||||
"author": "Dan Salvato LLC",
|
"author": "Dan Salvato LLC",
|
||||||
"version": "4.31.1",
|
"version": "4.31.6",
|
||||||
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
"description": "FrankerFaceZ is a Twitch enhancement suite.",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
@ -42,9 +42,9 @@
|
||||||
"extract-loader": "^2.0.1",
|
"extract-loader": "^2.0.1",
|
||||||
"file-loader": "^4.3.0",
|
"file-loader": "^4.3.0",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"jszip": "^3.7.1",
|
|
||||||
"raw-loader": "^3.1.0",
|
"raw-loader": "^3.1.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
|
"sass": "^1.43.4",
|
||||||
"sass-loader": "^7.3.1",
|
"sass-loader": "^7.3.1",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"terser-webpack-plugin": "4",
|
"terser-webpack-plugin": "4",
|
||||||
|
@ -70,6 +70,7 @@
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"graphql": "^16.0.1",
|
"graphql": "^16.0.1",
|
||||||
"graphql-tag": "^2.12.6",
|
"graphql-tag": "^2.12.6",
|
||||||
|
"jszip": "^3.7.1",
|
||||||
"js-cookie": "^2.2.1",
|
"js-cookie": "^2.2.1",
|
||||||
"markdown-it": "^12.2.0",
|
"markdown-it": "^12.2.0",
|
||||||
"markdown-it-link-attributes": "^3.0.0",
|
"markdown-it-link-attributes": "^3.0.0",
|
||||||
|
@ -78,7 +79,6 @@
|
||||||
"raven-js": "^3.27.2",
|
"raven-js": "^3.27.2",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"safe-regex": "^2.1.1",
|
"safe-regex": "^2.1.1",
|
||||||
"sass": "^1.43.4",
|
|
||||||
"sortablejs": "^1.14.0",
|
"sortablejs": "^1.14.0",
|
||||||
"sourcemapped-stacktrace": "^1.1.11",
|
"sourcemapped-stacktrace": "^1.1.11",
|
||||||
"text-diff": "^1.0.1",
|
"text-diff": "^1.0.1",
|
||||||
|
|
38
pnpm-lock.yaml
generated
38
pnpm-lock.yaml
generated
|
@ -78,6 +78,7 @@ dependencies:
|
||||||
graphql: 16.0.1
|
graphql: 16.0.1
|
||||||
graphql-tag: 2.12.6_graphql@16.0.1
|
graphql-tag: 2.12.6_graphql@16.0.1
|
||||||
js-cookie: 2.2.1
|
js-cookie: 2.2.1
|
||||||
|
jszip: 3.7.1
|
||||||
markdown-it: 12.2.0
|
markdown-it: 12.2.0
|
||||||
markdown-it-link-attributes: 3.0.0
|
markdown-it-link-attributes: 3.0.0
|
||||||
mnemonist: 0.38.5
|
mnemonist: 0.38.5
|
||||||
|
@ -85,7 +86,6 @@ dependencies:
|
||||||
raven-js: 3.27.2
|
raven-js: 3.27.2
|
||||||
react: 17.0.2
|
react: 17.0.2
|
||||||
safe-regex: 2.1.1
|
safe-regex: 2.1.1
|
||||||
sass: 1.43.4
|
|
||||||
sortablejs: 1.14.0
|
sortablejs: 1.14.0
|
||||||
sourcemapped-stacktrace: 1.1.11
|
sourcemapped-stacktrace: 1.1.11
|
||||||
text-diff: 1.0.1
|
text-diff: 1.0.1
|
||||||
|
@ -117,9 +117,9 @@ devDependencies:
|
||||||
extract-loader: 2.0.1
|
extract-loader: 2.0.1
|
||||||
file-loader: 4.3.0_webpack@4.46.0
|
file-loader: 4.3.0_webpack@4.46.0
|
||||||
json-loader: 0.5.7
|
json-loader: 0.5.7
|
||||||
jszip: 3.7.1
|
|
||||||
raw-loader: 3.1.0_webpack@4.46.0
|
raw-loader: 3.1.0_webpack@4.46.0
|
||||||
rimraf: 3.0.2
|
rimraf: 3.0.2
|
||||||
|
sass: 1.43.4
|
||||||
sass-loader: 7.3.1_webpack@4.46.0
|
sass-loader: 7.3.1_webpack@4.46.0
|
||||||
semver: 7.3.5
|
semver: 7.3.5
|
||||||
terser-webpack-plugin: 4.2.3_webpack@4.46.0
|
terser-webpack-plugin: 4.2.3_webpack@4.46.0
|
||||||
|
@ -988,6 +988,7 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
normalize-path: 3.0.0
|
normalize-path: 3.0.0
|
||||||
picomatch: 2.3.0
|
picomatch: 2.3.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/aproba/1.2.0:
|
/aproba/1.2.0:
|
||||||
resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==}
|
resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==}
|
||||||
|
@ -1173,6 +1174,7 @@ packages:
|
||||||
/binary-extensions/2.2.0:
|
/binary-extensions/2.2.0:
|
||||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/binary/0.3.0:
|
/binary/0.3.0:
|
||||||
resolution: {integrity: sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=}
|
resolution: {integrity: sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=}
|
||||||
|
@ -1260,6 +1262,7 @@ packages:
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dependencies:
|
dependencies:
|
||||||
fill-range: 7.0.1
|
fill-range: 7.0.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/brorand/1.1.0:
|
/brorand/1.1.0:
|
||||||
resolution: {integrity: sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=}
|
resolution: {integrity: sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=}
|
||||||
|
@ -1513,6 +1516,7 @@ packages:
|
||||||
readdirp: 3.6.0
|
readdirp: 3.6.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.2
|
fsevents: 2.3.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/chownr/1.1.4:
|
/chownr/1.1.4:
|
||||||
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
|
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
|
||||||
|
@ -1760,7 +1764,6 @@ packages:
|
||||||
|
|
||||||
/core-util-is/1.0.3:
|
/core-util-is/1.0.3:
|
||||||
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/create-ecdh/4.0.4:
|
/create-ecdh/4.0.4:
|
||||||
resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==}
|
resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==}
|
||||||
|
@ -2593,6 +2596,7 @@ packages:
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range: 5.0.1
|
to-regex-range: 5.0.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/finalhandler/1.1.2:
|
/finalhandler/1.1.2:
|
||||||
resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==}
|
resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==}
|
||||||
|
@ -2748,6 +2752,7 @@ packages:
|
||||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/fstream/1.0.12:
|
/fstream/1.0.12:
|
||||||
|
@ -2804,6 +2809,7 @@ packages:
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
dependencies:
|
dependencies:
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
/glob/7.2.0:
|
/glob/7.2.0:
|
||||||
resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
|
resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
|
||||||
|
@ -3107,7 +3113,7 @@ packages:
|
||||||
|
|
||||||
/immediate/3.0.6:
|
/immediate/3.0.6:
|
||||||
resolution: {integrity: sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=}
|
resolution: {integrity: sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=}
|
||||||
dev: true
|
dev: false
|
||||||
|
|
||||||
/import-fresh/3.3.0:
|
/import-fresh/3.3.0:
|
||||||
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
||||||
|
@ -3157,7 +3163,6 @@ packages:
|
||||||
|
|
||||||
/inherits/2.0.4:
|
/inherits/2.0.4:
|
||||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/internal-ip/6.2.0:
|
/internal-ip/6.2.0:
|
||||||
resolution: {integrity: sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg==}
|
resolution: {integrity: sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg==}
|
||||||
|
@ -3243,6 +3248,7 @@ packages:
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dependencies:
|
dependencies:
|
||||||
binary-extensions: 2.2.0
|
binary-extensions: 2.2.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/is-boolean-object/1.1.2:
|
/is-boolean-object/1.1.2:
|
||||||
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
|
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
|
||||||
|
@ -3327,6 +3333,7 @@ packages:
|
||||||
/is-extglob/2.1.1:
|
/is-extglob/2.1.1:
|
||||||
resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=}
|
resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/is-fullwidth-code-point/3.0.0:
|
/is-fullwidth-code-point/3.0.0:
|
||||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||||
|
@ -3338,6 +3345,7 @@ packages:
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
is-extglob: 2.1.1
|
is-extglob: 2.1.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/is-ip/3.1.0:
|
/is-ip/3.1.0:
|
||||||
resolution: {integrity: sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==}
|
resolution: {integrity: sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==}
|
||||||
|
@ -3368,6 +3376,7 @@ packages:
|
||||||
/is-number/7.0.0:
|
/is-number/7.0.0:
|
||||||
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||||
engines: {node: '>=0.12.0'}
|
engines: {node: '>=0.12.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/is-path-cwd/2.2.0:
|
/is-path-cwd/2.2.0:
|
||||||
resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==}
|
resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==}
|
||||||
|
@ -3466,7 +3475,6 @@ packages:
|
||||||
|
|
||||||
/isarray/1.0.0:
|
/isarray/1.0.0:
|
||||||
resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=}
|
resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/isexe/2.0.0:
|
/isexe/2.0.0:
|
||||||
resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=}
|
resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=}
|
||||||
|
@ -3564,7 +3572,7 @@ packages:
|
||||||
pako: 1.0.11
|
pako: 1.0.11
|
||||||
readable-stream: 2.3.7
|
readable-stream: 2.3.7
|
||||||
set-immediate-shim: 1.0.1
|
set-immediate-shim: 1.0.1
|
||||||
dev: true
|
dev: false
|
||||||
|
|
||||||
/kind-of/3.2.2:
|
/kind-of/3.2.2:
|
||||||
resolution: {integrity: sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=}
|
resolution: {integrity: sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=}
|
||||||
|
@ -3602,7 +3610,7 @@ packages:
|
||||||
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
|
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
immediate: 3.0.6
|
immediate: 3.0.6
|
||||||
dev: true
|
dev: false
|
||||||
|
|
||||||
/linkify-it/3.0.3:
|
/linkify-it/3.0.3:
|
||||||
resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==}
|
resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==}
|
||||||
|
@ -4079,6 +4087,7 @@ packages:
|
||||||
/normalize-path/3.0.0:
|
/normalize-path/3.0.0:
|
||||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/npm-run-path/4.0.1:
|
/npm-run-path/4.0.1:
|
||||||
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
||||||
|
@ -4314,7 +4323,6 @@ packages:
|
||||||
|
|
||||||
/pako/1.0.11:
|
/pako/1.0.11:
|
||||||
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
|
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/parallel-transform/1.2.0:
|
/parallel-transform/1.2.0:
|
||||||
resolution: {integrity: sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==}
|
resolution: {integrity: sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==}
|
||||||
|
@ -4425,6 +4433,7 @@ packages:
|
||||||
/picomatch/2.3.0:
|
/picomatch/2.3.0:
|
||||||
resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==}
|
resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==}
|
||||||
engines: {node: '>=8.6'}
|
engines: {node: '>=8.6'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/pify/2.3.0:
|
/pify/2.3.0:
|
||||||
resolution: {integrity: sha1-7RQaasBDqEnqWISY59yosVMw6Qw=}
|
resolution: {integrity: sha1-7RQaasBDqEnqWISY59yosVMw6Qw=}
|
||||||
|
@ -4548,7 +4557,6 @@ packages:
|
||||||
|
|
||||||
/process-nextick-args/2.0.1:
|
/process-nextick-args/2.0.1:
|
||||||
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/process/0.11.10:
|
/process/0.11.10:
|
||||||
resolution: {integrity: sha1-czIwDoQBYb2j5podHZGn1LwW8YI=}
|
resolution: {integrity: sha1-czIwDoQBYb2j5podHZGn1LwW8YI=}
|
||||||
|
@ -4719,7 +4727,6 @@ packages:
|
||||||
safe-buffer: 5.1.2
|
safe-buffer: 5.1.2
|
||||||
string_decoder: 1.1.1
|
string_decoder: 1.1.1
|
||||||
util-deprecate: 1.0.2
|
util-deprecate: 1.0.2
|
||||||
dev: true
|
|
||||||
|
|
||||||
/readable-stream/3.6.0:
|
/readable-stream/3.6.0:
|
||||||
resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==}
|
resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==}
|
||||||
|
@ -4745,6 +4752,7 @@ packages:
|
||||||
engines: {node: '>=8.10.0'}
|
engines: {node: '>=8.10.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
picomatch: 2.3.0
|
picomatch: 2.3.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/rechoir/0.7.1:
|
/rechoir/0.7.1:
|
||||||
resolution: {integrity: sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==}
|
resolution: {integrity: sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==}
|
||||||
|
@ -4889,7 +4897,6 @@ packages:
|
||||||
|
|
||||||
/safe-buffer/5.1.2:
|
/safe-buffer/5.1.2:
|
||||||
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
|
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/safe-buffer/5.2.1:
|
/safe-buffer/5.2.1:
|
||||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||||
|
@ -4931,7 +4938,7 @@ packages:
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar: 3.5.2
|
chokidar: 3.5.2
|
||||||
dev: false
|
dev: true
|
||||||
|
|
||||||
/schema-utils/1.0.0:
|
/schema-utils/1.0.0:
|
||||||
resolution: {integrity: sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==}
|
resolution: {integrity: sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==}
|
||||||
|
@ -5045,7 +5052,7 @@ packages:
|
||||||
/set-immediate-shim/1.0.1:
|
/set-immediate-shim/1.0.1:
|
||||||
resolution: {integrity: sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=}
|
resolution: {integrity: sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: false
|
||||||
|
|
||||||
/set-value/4.1.0:
|
/set-value/4.1.0:
|
||||||
resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==}
|
resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==}
|
||||||
|
@ -5353,7 +5360,6 @@ packages:
|
||||||
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
|
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer: 5.1.2
|
safe-buffer: 5.1.2
|
||||||
dev: true
|
|
||||||
|
|
||||||
/string_decoder/1.3.0:
|
/string_decoder/1.3.0:
|
||||||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
||||||
|
@ -5547,6 +5553,7 @@ packages:
|
||||||
engines: {node: '>=8.0'}
|
engines: {node: '>=8.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
is-number: 7.0.0
|
is-number: 7.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/to-regex/3.0.2:
|
/to-regex/3.0.2:
|
||||||
resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==}
|
resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==}
|
||||||
|
@ -5697,7 +5704,6 @@ packages:
|
||||||
|
|
||||||
/util-deprecate/1.0.2:
|
/util-deprecate/1.0.2:
|
||||||
resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=}
|
resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/util/0.10.3:
|
/util/0.10.3:
|
||||||
resolution: {integrity: sha1-evsa/lCAUkZInj23/g7TeTNqwPk=}
|
resolution: {integrity: sha1-evsa/lCAUkZInj23/g7TeTNqwPk=}
|
||||||
|
|
27
src/i18n.js
27
src/i18n.js
|
@ -15,8 +15,6 @@ import NewTransCore from 'utilities/translation-core';
|
||||||
|
|
||||||
const fetchJSON = (url, options) => fetch(url, options).then(r => r.ok ? r.json() : null).catch(() => null);
|
const fetchJSON = (url, options) => fetch(url, options).then(r => r.ok ? r.json() : null).catch(() => null);
|
||||||
|
|
||||||
const API_SERVER = 'https://api-test.frankerfacez.com';
|
|
||||||
|
|
||||||
const STACK_SPLITTER = /\s*at\s+(.+?)\s+\((.+)\)$/,
|
const STACK_SPLITTER = /\s*at\s+(.+?)\s+\((.+)\)$/,
|
||||||
SOURCE_SPLITTER = /^(.+):\/\/(.+?)(?:\?[a-zA-Z0-9]+)?:(\d+:\d+)$/;
|
SOURCE_SPLITTER = /^(.+):\/\/(.+?)(?:\?[a-zA-Z0-9]+)?:(\d+:\d+)$/;
|
||||||
|
|
||||||
|
@ -691,29 +689,24 @@ export class TranslationManager extends Module {
|
||||||
const chunks = await Promise.all(promises);
|
const chunks = await Promise.all(promises);
|
||||||
const result = {};
|
const result = {};
|
||||||
|
|
||||||
|
let ignored = 0;
|
||||||
|
|
||||||
for(const chunk of chunks) {
|
for(const chunk of chunks) {
|
||||||
if (! chunk)
|
if (! chunk)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for(const [key,val] of Object.entries(chunk))
|
for(const [key,val] of Object.entries(chunk)) {
|
||||||
|
if (typeof val === 'string' && val.length > 0)
|
||||||
result[key] = val;
|
result[key] = val;
|
||||||
|
else
|
||||||
|
ignored++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignored > 0)
|
||||||
|
this.log.debug(`Ignored ${ignored} invalid values while loading ${locale} chunks.`);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
/*const resp = await fetch(`${API_SERVER}/v2/i18n/locale/${locale}`);
|
|
||||||
if ( ! resp.ok ) {
|
|
||||||
if ( resp.status === 404 ) {
|
|
||||||
this.log.info(`Cannot Load Locale: ${locale}`);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.warn(`Cannot Load Locale: ${locale} -- Status: ${resp.status}`);
|
|
||||||
throw new Error(`http error ${resp.status} loading phrases`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await resp.json();
|
|
||||||
return data?.phrases;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async setLocale(new_locale) {
|
async setLocale(new_locale) {
|
||||||
|
|
|
@ -311,7 +311,13 @@ export default class Actions extends Module {
|
||||||
{reason_text ? <div class="tw-pd-05 tw-border-b">
|
{reason_text ? <div class="tw-pd-05 tw-border-b">
|
||||||
{reason_text}
|
{reason_text}
|
||||||
</div> : null}
|
</div> : null}
|
||||||
|
<div class="scrollable-area" data-simplebar>
|
||||||
|
<div class="simplebar-scroll-content">
|
||||||
|
<div class="simplebar-content">
|
||||||
<ul>{reason_elements}</ul>
|
<ul>{reason_elements}</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>);
|
</div>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -502,6 +502,12 @@ export default class Badges extends Module {
|
||||||
message = container[fine.accessor]?.return?.stateNode?.props?.message;
|
message = container[fine.accessor]?.return?.stateNode?.props?.message;
|
||||||
if ( ! message )
|
if ( ! message )
|
||||||
message = fine.searchParent(container, n => n.props?.message)?.props?.message;
|
message = fine.searchParent(container, n => n.props?.message)?.props?.message;
|
||||||
|
if ( ! message && this.root.flavor === 'clips' ) {
|
||||||
|
const lines = this.resolve('site.chat.line');
|
||||||
|
const node = fine.searchParent(container, n => n.props?.node)?.props?.node;
|
||||||
|
if ( lines && node )
|
||||||
|
message = lines.messages.get(node);
|
||||||
|
}
|
||||||
if ( ! message )
|
if ( ! message )
|
||||||
message = fine.searchParent(container, n => n.props?.node)?.props?.node?._ffz_message;
|
message = fine.searchParent(container, n => n.props?.node)?.props?.node?._ffz_message;
|
||||||
if ( ! message )
|
if ( ! message )
|
||||||
|
|
|
@ -498,6 +498,8 @@ export default class Emotes extends Module {
|
||||||
if ( ! line || ! opener )
|
if ( ! line || ! opener )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const rect = target.getBoundingClientRect();
|
||||||
|
|
||||||
opener.onShowEmoteCard({
|
opener.onShowEmoteCard({
|
||||||
channelID: line.props.channelID || '',
|
channelID: line.props.channelID || '',
|
||||||
channelLogin: line.props.channelLogin || '',
|
channelLogin: line.props.channelLogin || '',
|
||||||
|
@ -505,7 +507,8 @@ export default class Emotes extends Module {
|
||||||
emoteCode: target.alt,
|
emoteCode: target.alt,
|
||||||
sourceID: 'chat',
|
sourceID: 'chat',
|
||||||
referrerID: '',
|
referrerID: '',
|
||||||
initialTopOffset: target.getBoundingClientRect().bottom
|
initialTopOffset: rect.bottom,
|
||||||
|
initialBottomOffset: rect.top
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1854,6 +1854,24 @@ export default class Chat extends Module {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeTokenizer(tokenizer) {
|
||||||
|
let type;
|
||||||
|
if ( typeof tokenizer === 'string' ) type = tokenizer;
|
||||||
|
else type = tokenizer.type;
|
||||||
|
|
||||||
|
tokenizer = this.tokenizers[type];
|
||||||
|
if ( ! tokenizer )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if ( tokenizer.tooltip )
|
||||||
|
delete this.tooltips.types[type];
|
||||||
|
|
||||||
|
const idx = this.__tokenizers.indexOf(tokenizer);
|
||||||
|
if ( idx !== -1 )
|
||||||
|
this.__tokenizers.splice(idx, 1);
|
||||||
|
|
||||||
|
return tokenizer;
|
||||||
|
}
|
||||||
|
|
||||||
addRichProvider(provider) {
|
addRichProvider(provider) {
|
||||||
const type = provider.type;
|
const type = provider.type;
|
||||||
|
@ -1869,12 +1887,39 @@ export default class Chat extends Module {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeRichProvider(provider) {
|
||||||
|
let type;
|
||||||
|
if ( typeof provider === 'string' ) type = provider;
|
||||||
|
else type = provider.type;
|
||||||
|
|
||||||
tokenizeString(message, msg) {
|
provider = this.rich_providers[type];
|
||||||
|
if ( ! provider )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
const idx = this.__rich_providers.indexOf(provider);
|
||||||
|
if ( idx !== -1 )
|
||||||
|
this.__rich_providers.splice(idx, 1);
|
||||||
|
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tokenizeString(message, msg, user, haltable = false) {
|
||||||
let tokens = [{type: 'text', text: message}];
|
let tokens = [{type: 'text', text: message}];
|
||||||
|
|
||||||
for(const tokenizer of this.__tokenizers)
|
for(const tokenizer of this.__tokenizers) {
|
||||||
tokens = tokenizer.process.call(this, tokens, msg);
|
if ( ! tokenizer.process )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const new_tokens = tokenizer.process.call(this, tokens, msg, user, haltable);
|
||||||
|
if ( new_tokens )
|
||||||
|
tokens = new_tokens;
|
||||||
|
|
||||||
|
if ( haltable && msg.ffz_halt_tokens ) {
|
||||||
|
msg.ffz_halt_tokens = undefined;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
@ -1914,7 +1959,13 @@ export default class Chat extends Module {
|
||||||
let tokens = [{type: 'text', text: msg.message}];
|
let tokens = [{type: 'text', text: msg.message}];
|
||||||
|
|
||||||
for(const tokenizer of this.__tokenizers) {
|
for(const tokenizer of this.__tokenizers) {
|
||||||
tokens = tokenizer.process.call(this, tokens, msg, user, haltable);
|
if ( ! tokenizer.process )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const new_tokens = tokenizer.process.call(this, tokens, msg, user, haltable);
|
||||||
|
if ( new_tokens )
|
||||||
|
tokens = new_tokens;
|
||||||
|
|
||||||
if ( haltable && msg.ffz_halt_tokens ) {
|
if ( haltable && msg.ffz_halt_tokens ) {
|
||||||
msg.ffz_halt_tokens = undefined;
|
msg.ffz_halt_tokens = undefined;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const FilterTester = {
|
||||||
|
|
||||||
process(tokens, msg) {
|
process(tokens, msg) {
|
||||||
if ( ! tokens || ! tokens.length || ! this.context.get('chat.filtering.debug') )
|
if ( ! tokens || ! tokens.length || ! this.context.get('chat.filtering.debug') )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
msg.filters = [];
|
msg.filters = [];
|
||||||
|
|
||||||
|
@ -178,9 +178,7 @@ export const Links = {
|
||||||
|
|
||||||
process(tokens) {
|
process(tokens) {
|
||||||
if ( ! tokens || ! tokens.length )
|
if ( ! tokens || ! tokens.length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
//const use_new = this.experiments.getAssignment('new_links');
|
|
||||||
|
|
||||||
const out = [];
|
const out = [];
|
||||||
for(const token of tokens) {
|
for(const token of tokens) {
|
||||||
|
@ -189,7 +187,6 @@ export const Links = {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//LINK_REGEX.lastIndex = 0;
|
|
||||||
NEW_LINK_REGEX.lastIndex = 0;
|
NEW_LINK_REGEX.lastIndex = 0;
|
||||||
const text = token.text;
|
const text = token.text;
|
||||||
let idx = 0, match;
|
let idx = 0, match;
|
||||||
|
@ -251,41 +248,6 @@ Links.tooltip.delayHide = function(target) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Rich Content
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
/*export const RichContent = {
|
|
||||||
type: 'rich-content',
|
|
||||||
|
|
||||||
render(token, e) {
|
|
||||||
return e('div', {
|
|
||||||
className: 'ffz--rich-content elevation-1 mg-y-05',
|
|
||||||
}, e('a', {
|
|
||||||
className: 'clips-chat-card flex flex-nowrap pd-05',
|
|
||||||
target: '_blank',
|
|
||||||
href: token.url
|
|
||||||
}, [
|
|
||||||
e('div', {
|
|
||||||
className: 'clips-chat-card__thumb align-items-center flex justify-content-center'
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
},
|
|
||||||
|
|
||||||
process(tokens, msg) {
|
|
||||||
if ( ! tokens || ! tokens.length )
|
|
||||||
return tokens;
|
|
||||||
|
|
||||||
for(const token of tokens) {
|
|
||||||
if ( token.type !== 'link' )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Replies (Styled Like Mentions)
|
// Replies (Styled Like Mentions)
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
@ -333,10 +295,6 @@ export const Replies = {
|
||||||
reply.parentMessageBody
|
reply.parentMessageBody
|
||||||
])
|
])
|
||||||
];
|
];
|
||||||
},
|
|
||||||
|
|
||||||
process(tokens) {
|
|
||||||
return tokens;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,11 +309,11 @@ export const Mentions = {
|
||||||
|
|
||||||
component: () => import(/* webpackChunkName: 'vue-chat' */ './components/chat-mention.vue'),
|
component: () => import(/* webpackChunkName: 'vue-chat' */ './components/chat-mention.vue'),
|
||||||
|
|
||||||
oldRender(token, createElement) {
|
/*oldRender(token, createElement) {
|
||||||
return (<strong class={`chat-line__message-mention${token.me ? ' ffz--mention-me' : ''}`}>
|
return (<strong class={`chat-line__message-mention${token.me ? ' ffz--mention-me' : ''}`}>
|
||||||
{token.text}
|
{token.text}
|
||||||
</strong>);
|
</strong>);
|
||||||
},
|
},*/
|
||||||
|
|
||||||
render(token, createElement) {
|
render(token, createElement) {
|
||||||
let color = token.color;
|
let color = token.color;
|
||||||
|
@ -376,7 +334,7 @@ export const Mentions = {
|
||||||
|
|
||||||
process(tokens, msg, user) {
|
process(tokens, msg, user) {
|
||||||
if ( ! tokens || ! tokens.length )
|
if ( ! tokens || ! tokens.length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const can_highlight_user = user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own'),
|
const can_highlight_user = user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own'),
|
||||||
priority = this.context.get('chat.filtering.mention-priority');
|
priority = this.context.get('chat.filtering.mention-priority');
|
||||||
|
@ -467,19 +425,17 @@ export const UserHighlights = {
|
||||||
|
|
||||||
process(tokens, msg, user) {
|
process(tokens, msg, user) {
|
||||||
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const list = this.context.get('__filter:highlight-users');
|
const list = this.context.get('__filter:highlight-users');
|
||||||
if ( ! list || ! list.length )
|
if ( ! list || ! list.length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const u = msg.user;
|
const u = msg.user;
|
||||||
for(const [priority, color, regex] of list) {
|
for(const [priority, color, regex] of list) {
|
||||||
if ( regex.test(u.login) || regex.test(u.displayName) )
|
if ( regex.test(u.login) || regex.test(u.displayName) )
|
||||||
this.applyHighlight(msg, priority, color, 'user');
|
this.applyHighlight(msg, priority, color, 'user');
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,12 +445,12 @@ export const BlockedUsers = {
|
||||||
|
|
||||||
process(tokens, msg, user, haltable) {
|
process(tokens, msg, user, haltable) {
|
||||||
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const u = msg.user,
|
const u = msg.user,
|
||||||
regexes = this.context.get('__filter:block-users');
|
regexes = this.context.get('__filter:block-users');
|
||||||
if ( ! regexes )
|
if ( ! regexes )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
if ( regexes[1] && (regexes[1].test(u.login) || regexes[1].test(u.displayName)) ) {
|
if ( regexes[1] && (regexes[1].test(u.login) || regexes[1].test(u.displayName)) ) {
|
||||||
msg.deleted = true;
|
msg.deleted = true;
|
||||||
|
@ -504,8 +460,6 @@ export const BlockedUsers = {
|
||||||
|
|
||||||
} else if ( ! msg.deleted && regexes[0] && (regexes[0].test(u.login) || regexes[0].test(u.displayName)) )
|
} else if ( ! msg.deleted && regexes[0] && (regexes[0].test(u.login) || regexes[0].test(u.displayName)) )
|
||||||
msg.deleted = true;
|
msg.deleted = true;
|
||||||
|
|
||||||
return tokens;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,17 +484,17 @@ export const BadgeStuff = {
|
||||||
|
|
||||||
process(tokens, msg, user, haltable) {
|
process(tokens, msg, user, haltable) {
|
||||||
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const highlights = this.context.get('__filter:highlight-badges'),
|
const highlights = this.context.get('__filter:highlight-badges'),
|
||||||
list = this.context.get('__filter:block-badges');
|
list = this.context.get('__filter:block-badges');
|
||||||
|
|
||||||
if ( ! highlights && ! list )
|
if ( ! highlights && ! list )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const keys = getBadgeIDs(msg);
|
const keys = getBadgeIDs(msg);
|
||||||
if ( ! keys || ! keys.length )
|
if ( ! keys || ! keys.length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
for(const badge of keys) {
|
for(const badge of keys) {
|
||||||
if ( list && list[1].includes(badge) ) {
|
if ( list && list[1].includes(badge) ) {
|
||||||
|
@ -548,7 +502,7 @@ export const BadgeStuff = {
|
||||||
msg.ffz_removed = true;
|
msg.ffz_removed = true;
|
||||||
if ( haltable )
|
if ( haltable )
|
||||||
msg.ffz_halt_tokens = true;
|
msg.ffz_halt_tokens = true;
|
||||||
return tokens;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( list && ! msg.deleted && list[0].includes(badge) )
|
if ( list && ! msg.deleted && list[0].includes(badge) )
|
||||||
|
@ -560,8 +514,6 @@ export const BadgeStuff = {
|
||||||
this.applyHighlight(msg, details[0], details[1], 'badge');
|
this.applyHighlight(msg, details[0], details[1], 'badge');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,14 +561,14 @@ export const CustomHighlights = {
|
||||||
|
|
||||||
process(tokens, msg, user) {
|
process(tokens, msg, user) {
|
||||||
if ( ! tokens || ! tokens.length )
|
if ( ! tokens || ! tokens.length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const data = this.context.get('__filter:highlight-terms');
|
const data = this.context.get('__filter:highlight-terms');
|
||||||
if ( ! data )
|
if ( ! data )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
let had_match = false;
|
let had_match = false;
|
||||||
if ( data.non ) {
|
if ( data.non ) {
|
||||||
|
@ -781,14 +733,14 @@ export const BlockedTerms = {
|
||||||
|
|
||||||
process(tokens, msg, user, haltable) {
|
process(tokens, msg, user, haltable) {
|
||||||
if ( ! tokens || ! tokens.length )
|
if ( ! tokens || ! tokens.length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
if ( user && user.login && user.login == msg.user.login && ! this.context.get('chat.filtering.process-own') )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const regexes = this.context.get('__filter:block-terms');
|
const regexes = this.context.get('__filter:block-terms');
|
||||||
if ( ! regexes )
|
if ( ! regexes )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
if ( regexes.remove ) {
|
if ( regexes.remove ) {
|
||||||
tokens = blocked_process(tokens, msg, regexes.remove, true, haltable);
|
tokens = blocked_process(tokens, msg, regexes.remove, true, haltable);
|
||||||
|
@ -863,7 +815,7 @@ export const AutomoddedTerms = {
|
||||||
|
|
||||||
process(tokens, msg, user, haltable) {
|
process(tokens, msg, user, haltable) {
|
||||||
if ( ! tokens || ! tokens.length || ! msg.flags || ! Array.isArray(msg.flags.list) )
|
if ( ! tokens || ! tokens.length || ! msg.flags || ! Array.isArray(msg.flags.list) )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const cats = msg.flags.preferences,
|
const cats = msg.flags.preferences,
|
||||||
flagged = msg.flags.list.filter(x => {
|
flagged = msg.flags.list.filter(x => {
|
||||||
|
@ -882,7 +834,7 @@ export const AutomoddedTerms = {
|
||||||
f_length = flagged.length;
|
f_length = flagged.length;
|
||||||
|
|
||||||
if ( ! f_length )
|
if ( ! f_length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const out = [];
|
const out = [];
|
||||||
let idx = 0,
|
let idx = 0,
|
||||||
|
@ -898,7 +850,7 @@ export const AutomoddedTerms = {
|
||||||
msg.ffz_removed = true;
|
msg.ffz_removed = true;
|
||||||
if ( haltable )
|
if ( haltable )
|
||||||
msg.ffz_halt_tokens = true;
|
msg.ffz_halt_tokens = true;
|
||||||
return tokens;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const token of tokens) {
|
for(const token of tokens) {
|
||||||
|
@ -1050,13 +1002,13 @@ export const CheerEmotes = {
|
||||||
|
|
||||||
process(tokens, msg) {
|
process(tokens, msg) {
|
||||||
if ( ! tokens || ! tokens.length || ! msg.bits )
|
if ( ! tokens || ! tokens.length || ! msg.bits )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const room = this.getRoom(msg.roomID, msg.roomLogin, true),
|
const room = this.getRoom(msg.roomID, msg.roomLogin, true),
|
||||||
actions = room && room.bitsConfig;
|
actions = room && room.bitsConfig;
|
||||||
|
|
||||||
if ( ! actions )
|
if ( ! actions )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const matcher = new RegExp(`^(${Object.keys(actions).join('|')})(\\d+)$`, 'i');
|
const matcher = new RegExp(`^(${Object.keys(actions).join('|')})(\\d+)$`, 'i');
|
||||||
|
|
||||||
|
@ -1464,10 +1416,10 @@ export const AddonEmotes = {
|
||||||
|
|
||||||
process(tokens, msg) {
|
process(tokens, msg) {
|
||||||
if ( ! tokens || ! tokens.length )
|
if ( ! tokens || ! tokens.length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
if ( this.context.get('chat.emotes.enabled') !== 2 )
|
if ( this.context.get('chat.emotes.enabled') !== 2 )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const emotes = this.emotes.getEmotes(
|
const emotes = this.emotes.getEmotes(
|
||||||
msg.user.id,
|
msg.user.id,
|
||||||
|
@ -1477,7 +1429,7 @@ export const AddonEmotes = {
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( ! emotes )
|
if ( ! emotes )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const big = this.context.get('chat.emotes.2x'),
|
const big = this.context.get('chat.emotes.2x'),
|
||||||
anim = this.context.get('chat.emotes.animated'),
|
anim = this.context.get('chat.emotes.animated'),
|
||||||
|
@ -1508,12 +1460,14 @@ export const AddonEmotes = {
|
||||||
// Is this emote a modifier?
|
// Is this emote a modifier?
|
||||||
if ( emote.modifier && last_token && last_token.modifiers && (!text.length || (text.length === 1 && text[0] === '')) ) {
|
if ( emote.modifier && last_token && last_token.modifiers && (!text.length || (text.length === 1 && text[0] === '')) ) {
|
||||||
if ( last_token.modifiers.indexOf(emote.token) === -1 ) {
|
if ( last_token.modifiers.indexOf(emote.token) === -1 ) {
|
||||||
if ( big )
|
last_token.modifiers.push(
|
||||||
last_token.modifiers.push(Object.assign({
|
Object.assign({
|
||||||
big
|
big,
|
||||||
}, emote.token));
|
anim
|
||||||
else
|
},
|
||||||
last_token.modifiers.push(emote.token);
|
emote.token
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -1574,14 +1528,15 @@ export const Emoji = {
|
||||||
|
|
||||||
process(tokens) {
|
process(tokens) {
|
||||||
if ( ! tokens || ! tokens.length )
|
if ( ! tokens || ! tokens.length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const splitter = this.emoji.splitter,
|
const splitter = this.emoji.splitter,
|
||||||
style = this.context.get('chat.emoji.style'),
|
style = this.context.get('chat.emoji.style');
|
||||||
out = [];
|
|
||||||
|
|
||||||
if ( style === 0 )
|
if ( style === 0 )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
|
const out = [];
|
||||||
|
|
||||||
for(const token of tokens) {
|
for(const token of tokens) {
|
||||||
if ( ! token )
|
if ( ! token )
|
||||||
|
@ -1648,10 +1603,10 @@ export const TwitchEmotes = {
|
||||||
|
|
||||||
process(tokens, msg) {
|
process(tokens, msg) {
|
||||||
if ( ! msg.ffz_emotes )
|
if ( ! msg.ffz_emotes )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
if ( this.context.get('chat.emotes.enabled') < 1 )
|
if ( this.context.get('chat.emotes.enabled') < 1 )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
const data = msg.ffz_emotes,
|
const data = msg.ffz_emotes,
|
||||||
anim = this.context.get('chat.emotes.animated'),
|
anim = this.context.get('chat.emotes.animated'),
|
||||||
|
@ -1666,11 +1621,12 @@ export const TwitchEmotes = {
|
||||||
emotes.push([emote_id, match.startIndex, match.endIndex + 1]);
|
emotes.push([emote_id, match.startIndex, match.endIndex + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const out = [],
|
const e_length = emotes.length;
|
||||||
e_length = emotes.length;
|
|
||||||
|
|
||||||
if ( ! e_length )
|
if ( ! e_length )
|
||||||
return tokens;
|
return;
|
||||||
|
|
||||||
|
const out = [];
|
||||||
|
|
||||||
emotes.sort((a,b) => a[1] !== b[1] ? a[1] - b[1] : b[0] - a[0]);
|
emotes.sort((a,b) => a[1] !== b[1] ? a[1] - b[1] : b[0] - a[0]);
|
||||||
|
|
||||||
|
|
|
@ -237,7 +237,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
code: pick_random(CODES),
|
code: pick_random(CODES),
|
||||||
experiments_locked: true, //this.item.is_locked(),
|
experiments_locked: this.item.is_locked(),
|
||||||
sort_by: 1,
|
sort_by: 1,
|
||||||
unused: false,
|
unused: false,
|
||||||
unique_id: this.item.unique_id(),
|
unique_id: this.item.unique_id(),
|
||||||
|
|
|
@ -91,6 +91,8 @@
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="tw-mg-l-1 tw-button tw-button--text"
|
class="tw-mg-l-1 tw-button tw-button--text"
|
||||||
|
:class="es_waiting && 'tw-button--disabled'"
|
||||||
|
:disabled="es_waiting"
|
||||||
@click="refresh"
|
@click="refresh"
|
||||||
>
|
>
|
||||||
<span class="tw-button__text ffz-i-arrows-cw">
|
<span class="tw-button__text ffz-i-arrows-cw">
|
||||||
|
@ -257,6 +259,7 @@ export default {
|
||||||
is_custom: stuff[1],
|
is_custom: stuff[1],
|
||||||
rich_data: null,
|
rich_data: null,
|
||||||
raw_loading: false,
|
raw_loading: false,
|
||||||
|
es_waiting: false,
|
||||||
raw_data: null,
|
raw_data: null,
|
||||||
length: 0,
|
length: 0,
|
||||||
|
|
||||||
|
@ -330,14 +333,17 @@ export default {
|
||||||
this.chat = this.item.getChat();
|
this.chat = this.item.getChat();
|
||||||
this.settings = this.chat.resolve('settings');
|
this.settings = this.chat.resolve('settings');
|
||||||
|
|
||||||
this.chat.on('chat:update-link-resolver', this.checkRefreshRaw, this);
|
this.refreshES = debounce(this.refresh, 1000, true);
|
||||||
this.settings.on(':changed:debug.link-resolver.source', this.updateExamples, this);
|
|
||||||
this.updateExamples();
|
|
||||||
|
|
||||||
this.rebuildData = debounce(this.rebuildData, 250);
|
this.rebuildData = debounce(this.rebuildData, 250);
|
||||||
this.refreshRaw = debounce(this.refreshRaw, 250);
|
this.refreshRaw = debounce(this.refreshRaw, 250);
|
||||||
this.onTextChange = debounce(this.onTextChange, 500);
|
this.onTextChange = debounce(this.onTextChange, 500);
|
||||||
this.updateExamples = debounce(this.updateExamples, 500);
|
this.updateExamples = debounce(this.updateExamples, 500);
|
||||||
|
this.updateEventSource = debounce(this.updateEventSource, 500);
|
||||||
|
|
||||||
|
this.chat.on('chat:update-link-resolver', this.checkRefreshRaw, this);
|
||||||
|
this.settings.on(':changed:debug.link-resolver.source', this.changeProvider, this);
|
||||||
|
this.updateExamples();
|
||||||
|
this.updateEventSource();
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -361,12 +367,44 @@ export default {
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.chat.off('chat:update-link-resolver', this.checkRefreshRaw, this);
|
this.chat.off('chat:update-link-resolver', this.checkRefreshRaw, this);
|
||||||
this.settings.off(':changed:debug.link-resolver.source', this.updateExamples, this);
|
this.settings.off(':changed:debug.link-resolver.source', this.changeProvider, this);
|
||||||
this.chat = null;
|
this.chat = null;
|
||||||
this.settings = null;
|
this.settings = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
changeProvider() {
|
||||||
|
this.updateEventSource();
|
||||||
|
this.updateExamples();
|
||||||
|
},
|
||||||
|
|
||||||
|
updateEventSource() {
|
||||||
|
const provider = this.settings.get('debug.link-resolver.source');
|
||||||
|
if ( provider !== 'dev' ) {
|
||||||
|
if ( this.es ) {
|
||||||
|
this.es.close();
|
||||||
|
this.es = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.es_waiting = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.es )
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.es = new EventSource('https://localhost:8002/sse');
|
||||||
|
this.es.addEventListener('error', () => {
|
||||||
|
this.es_waiting = true;
|
||||||
|
});
|
||||||
|
this.es.addEventListener('message', () => {
|
||||||
|
if ( this.es_waiting ) {
|
||||||
|
this.es_waiting = false;
|
||||||
|
this.refreshES();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
saveState() {
|
saveState() {
|
||||||
try {
|
try {
|
||||||
window.history.replaceState({
|
window.history.replaceState({
|
||||||
|
|
|
@ -110,7 +110,7 @@
|
||||||
:context="context"
|
:context="context"
|
||||||
:item="currentItem"
|
:item="currentItem"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
:nav_keys="nav_keys"
|
:nav-keys="navKeys"
|
||||||
@change-item="changeItem"
|
@change-item="changeItem"
|
||||||
@mark-seen="markSeen"
|
@mark-seen="markSeen"
|
||||||
@navigate="navigate"
|
@navigate="navigate"
|
||||||
|
@ -257,7 +257,7 @@ export default {
|
||||||
navigate(...keys) {
|
navigate(...keys) {
|
||||||
let item;
|
let item;
|
||||||
for(const key of keys) {
|
for(const key of keys) {
|
||||||
item = this.nav_keys[key];
|
item = this.navKeys[key];
|
||||||
if ( item )
|
if ( item )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
ref="children"
|
ref="children"
|
||||||
:context="context"
|
:context="context"
|
||||||
:item="i"
|
:item="i"
|
||||||
:nav_keys="nav_keys"
|
:nav-keys="navKeys"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
@change-item="changeItem"
|
@change-item="changeItem"
|
||||||
@mark-seen="markSeen"
|
@mark-seen="markSeen"
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['item', 'context', 'filter', 'nav_keys'],
|
props: ['item', 'context', 'filter', 'navKeys'],
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
breadcrumbs() {
|
breadcrumbs() {
|
||||||
|
|
|
@ -462,7 +462,7 @@ export default class MainMenu extends Module {
|
||||||
tree = this.getSettingsTree();
|
tree = this.getSettingsTree();
|
||||||
|
|
||||||
root.nav = tree;
|
root.nav = tree;
|
||||||
root.nav_keys = tree.keys;
|
root.navKeys = tree.keys;
|
||||||
|
|
||||||
let current, restored = true;
|
let current, restored = true;
|
||||||
|
|
||||||
|
@ -1119,7 +1119,7 @@ export default class MainMenu extends Module {
|
||||||
nav: settings,
|
nav: settings,
|
||||||
currentItem: current,
|
currentItem: current,
|
||||||
restoredItem: true, // restored, -- Look into making this smoother later.
|
restoredItem: true, // restored, -- Look into making this smoother later.
|
||||||
nav_keys: settings.keys,
|
navKeys: settings.keys,
|
||||||
|
|
||||||
has_unseen,
|
has_unseen,
|
||||||
|
|
||||||
|
|
|
@ -287,8 +287,14 @@ export default class Metadata extends Module {
|
||||||
icon: 'ffz-i-download',
|
icon: 'ffz-i-download',
|
||||||
|
|
||||||
click(src) {
|
click(src) {
|
||||||
const link = createElement('a', {target: '_blank', href: src});
|
const title = this.settings.get('context.title');
|
||||||
|
const name = title.replace(/[\\/:"*?<>|]+/, '_') + '.mp4';
|
||||||
|
|
||||||
|
const link = createElement('a', {target: '_blank', download: name, href: src, style: {display: 'none'}});
|
||||||
|
|
||||||
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
|
link.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,6 +404,9 @@ export default class Metadata extends Module {
|
||||||
if ( ! this.settings.get('metadata.player-stats') || ! data.delay )
|
if ( ! this.settings.get('metadata.player-stats') || ! data.delay )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if ( data.old )
|
||||||
|
return null;
|
||||||
|
|
||||||
const delayed = data.drift > 5000 ? '(!) ' : '';
|
const delayed = data.drift > 5000 ? '(!) ' : '';
|
||||||
|
|
||||||
if ( data.old )
|
if ( data.old )
|
||||||
|
|
|
@ -18,6 +18,7 @@ export default class Line extends Module {
|
||||||
this.inject('i18n');
|
this.inject('i18n');
|
||||||
|
|
||||||
this.inject('chat');
|
this.inject('chat');
|
||||||
|
this.inject('chat.overrides');
|
||||||
this.inject('site.fine');
|
this.inject('site.fine');
|
||||||
|
|
||||||
this.ChatLine = this.fine.define(
|
this.ChatLine = this.fine.define(
|
||||||
|
@ -75,12 +76,37 @@ export default class Line extends Module {
|
||||||
action_italic = action_style >= 2,
|
action_italic = action_style >= 2,
|
||||||
action_color = action_style === 1 || action_style === 3,
|
action_color = action_style === 1 || action_style === 3,
|
||||||
user = msg.user,
|
user = msg.user,
|
||||||
color = t.parent.colors.process(user.color),
|
raw_color = t.overrides.getColor(user.id) || user.color,
|
||||||
|
color = t.parent.colors.process(raw_color),
|
||||||
|
|
||||||
u = t.site.getUser();
|
u = t.site.getUser();
|
||||||
|
|
||||||
const tokens = msg.ffz_tokens = msg.ffz_tokens || t.chat.tokenizeMessage(msg, u);
|
const tokens = msg.ffz_tokens = msg.ffz_tokens || t.chat.tokenizeMessage(msg, u);
|
||||||
|
|
||||||
|
const user_block = t.chat.formatUser(user, createElement);
|
||||||
|
const override_name = t.overrides.getName(user.id);
|
||||||
|
|
||||||
|
const user_props = {
|
||||||
|
className: `clip-chat__message-author tw-font-size-5 ffz-link notranslate tw-strong${override_name ? ' ffz--name-override tw-relative ffz-il-tooltip__container' : ''} ${msg.ffz_user_class ?? ''}`,
|
||||||
|
href: `https://www.twitch.tv/${user.login}/clips`,
|
||||||
|
style: { color }
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( msg.ffz_user_props )
|
||||||
|
Object.assign(user_props, msg.ffz_user_props);
|
||||||
|
|
||||||
|
if ( msg.ffz_user_style )
|
||||||
|
Object.assign(user_props.style, msg.ffz_user_style);
|
||||||
|
|
||||||
|
const user_bits = createElement('a', user_props, override_name ? [
|
||||||
|
createElement('span', {
|
||||||
|
className: 'chat-author__display-name'
|
||||||
|
}, override_name),
|
||||||
|
createElement('div', {
|
||||||
|
className: 'ffz-il-tooltip ffz-il-tooltip--down ffz-il-tooltip--align-center'
|
||||||
|
}, user_block)
|
||||||
|
] : user_block);
|
||||||
|
|
||||||
return (<div class="tw-mg-b-1" style={{marginBottom:'0 !important'}}>
|
return (<div class="tw-mg-b-1" style={{marginBottom:'0 !important'}}>
|
||||||
<div
|
<div
|
||||||
data-a-target="tw-animation-target"
|
data-a-target="tw-animation-target"
|
||||||
|
@ -95,11 +121,7 @@ export default class Line extends Module {
|
||||||
<span class="chat-line__message--badges">{
|
<span class="chat-line__message--badges">{
|
||||||
t.chat.badges.render(msg, createElement)
|
t.chat.badges.render(msg, createElement)
|
||||||
}</span>
|
}</span>
|
||||||
<a
|
{user_bits}
|
||||||
class="clip-chat__message-author tw-font-size-5 ffz-link notranslate tw-strong"
|
|
||||||
href={`https://www.twitch.tv/${user.login}/clips`}
|
|
||||||
style={{color}}
|
|
||||||
>{ t.chat.formatUser(user, createElement) }</a>
|
|
||||||
<div class="tw-inline-block tw-mg-r-05">{
|
<div class="tw-inline-block tw-mg-r-05">{
|
||||||
is_action ? '' : ':'
|
is_action ? '' : ':'
|
||||||
}</div>
|
}</div>
|
||||||
|
|
|
@ -1534,6 +1534,30 @@ export default class ChatHook extends Module {
|
||||||
if ( msg.type === types.RewardGift && ! t.chat.context.get('chat.bits.show-rewards') )
|
if ( msg.type === types.RewardGift && ! t.chat.context.get('chat.bits.show-rewards') )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if ( msg.type === types.CommunityIntroduction ) {
|
||||||
|
// TODO: Make this better.
|
||||||
|
msg = {
|
||||||
|
type: types.Message,
|
||||||
|
badgeDynamicData: {},
|
||||||
|
badges: {},
|
||||||
|
id: msg.id,
|
||||||
|
isFirstMsg: true,
|
||||||
|
message: msg.message,
|
||||||
|
messageBody: msg.message,
|
||||||
|
messageParts: [
|
||||||
|
{type: 0, content: msg.message}
|
||||||
|
],
|
||||||
|
messageType: 0,
|
||||||
|
channel: msg.channel,
|
||||||
|
timestamp: new Date(),
|
||||||
|
user: {
|
||||||
|
userDisplayName: msg.displayName,
|
||||||
|
userLogin: msg.login,
|
||||||
|
userID: msg.userID
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if ( msg.type === types.Message ) {
|
if ( msg.type === types.Message ) {
|
||||||
const m = t.chat.standardizeMessage(msg),
|
const m = t.chat.standardizeMessage(msg),
|
||||||
cont = inst._ffz_connector ?? inst.ffzGetConnector();
|
cont = inst._ffz_connector ?? inst.ffzGetConnector();
|
||||||
|
@ -2010,6 +2034,21 @@ export default class ChatHook extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
scheduleMystery(mystery) { // eslint-disable-line class-methods-use-this
|
||||||
|
if ( ! mystery.line )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( mystery._timer )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mystery._timer = setTimeout(() => requestAnimationFrame(() => {
|
||||||
|
mystery._timer = null;
|
||||||
|
if ( mystery.line )
|
||||||
|
mystery.line.forceUpdate();
|
||||||
|
}), 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wrapChatService(cls) {
|
wrapChatService(cls) {
|
||||||
const t = this,
|
const t = this,
|
||||||
old_mount = cls.prototype.componentDidMount,
|
old_mount = cls.prototype.componentDidMount,
|
||||||
|
@ -2213,7 +2252,7 @@ export default class ChatHook extends Module {
|
||||||
mysteries[key] = null;
|
mysteries[key] = null;
|
||||||
|
|
||||||
if ( mystery.line )
|
if ( mystery.line )
|
||||||
mystery.line.forceUpdate();
|
t.scheduleMystery(mystery);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2242,6 +2281,15 @@ export default class ChatHook extends Module {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*this.onCommunityIntroductionEvent = function(e) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
} catch(err) {
|
||||||
|
t.log.capture(err, {extra: e});
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
const old_anonsubgift = this.onAnonSubscriptionGiftEvent;
|
const old_anonsubgift = this.onAnonSubscriptionGiftEvent;
|
||||||
this.onAnonSubscriptionGiftEvent = function(e) {
|
this.onAnonSubscriptionGiftEvent = function(e) {
|
||||||
try {
|
try {
|
||||||
|
@ -2265,7 +2313,7 @@ export default class ChatHook extends Module {
|
||||||
mysteries[key] = null;
|
mysteries[key] = null;
|
||||||
|
|
||||||
if ( mystery.line )
|
if ( mystery.line )
|
||||||
mystery.line.forceUpdate();
|
t.scheduleMystery(mystery);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,57 @@
|
||||||
|
|
||||||
import Module from 'utilities/module';
|
import Module from 'utilities/module';
|
||||||
import { findReactFragment } from 'utilities/dom';
|
import { findReactFragment } from 'utilities/dom';
|
||||||
|
import { FFZEvent } from 'utilities/events';
|
||||||
|
import { getTwitchEmoteSrcSet, has, getTwitchEmoteURL } from 'utilities/object';
|
||||||
import { TWITCH_POINTS_SETS, TWITCH_GLOBAL_SETS, TWITCH_PRIME_SETS, KNOWN_CODES, REPLACEMENTS, REPLACEMENT_BASE, KEYS } from 'utilities/constants';
|
import { TWITCH_POINTS_SETS, TWITCH_GLOBAL_SETS, TWITCH_PRIME_SETS, KNOWN_CODES, REPLACEMENTS, REPLACEMENT_BASE, KEYS } from 'utilities/constants';
|
||||||
|
|
||||||
import Twilight from 'site';
|
import Twilight from 'site';
|
||||||
import { FFZEvent } from 'src/utilities/events';
|
|
||||||
import { getTwitchEmoteSrcSet, getTwitchEmoteURL } from 'src/utilities/object';
|
|
||||||
import {EMOJI_JOINER} from 'src/modules/chat/emoji';
|
import {EMOJI_JOINER} from 'src/modules/chat/emoji';
|
||||||
|
|
||||||
|
// Prefer using these statically-allocated collators to String.localeCompare
|
||||||
|
const locale = Intl.Collator();
|
||||||
|
const localeCaseInsensitive = Intl.Collator(undefined, {sensitivity: 'accent'});
|
||||||
|
|
||||||
|
// Describes how an emote matches against a given input
|
||||||
|
// Higher values represent a more exact match
|
||||||
|
const NO_MATCH = 0;
|
||||||
|
const NON_PREFIX_MATCH = 1;
|
||||||
|
const CASE_INSENSITIVE_PREFIX_MATCH = 2;
|
||||||
|
const EXACT_PREFIX_MATCH = 3;
|
||||||
|
|
||||||
|
function getNodeText(node) {
|
||||||
|
if ( ! node )
|
||||||
|
return '';
|
||||||
|
|
||||||
|
if ( node.type === 'emote' )
|
||||||
|
return node.emoteName;
|
||||||
|
|
||||||
|
if ( node.type === 'text' )
|
||||||
|
return node.text;
|
||||||
|
|
||||||
|
if ( Array.isArray(node.children) )
|
||||||
|
return node.children.map(getNodeText).join('');
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNodeOffset(nodes, path) {
|
||||||
|
let offset = 0, pidx = 0, n = nodes;
|
||||||
|
|
||||||
|
while(pidx < path.length) {
|
||||||
|
const p = path[pidx];
|
||||||
|
|
||||||
|
for(let i = 0; i < p; i++)
|
||||||
|
offset += getNodeText(n[i]).length;
|
||||||
|
|
||||||
|
n = Array.isArray(n[p]) ? n[p] : n[p]?.children;
|
||||||
|
pidx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
export default class Input extends Module {
|
export default class Input extends Module {
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
super(...args);
|
super(...args);
|
||||||
|
@ -85,6 +129,15 @@ export default class Input extends Module {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.settings.add('chat.tab-complete.prioritize-prefix-matches', {
|
||||||
|
default: false,
|
||||||
|
ui: {
|
||||||
|
path: 'Chat > Input >> Tab Completion',
|
||||||
|
title: 'Prioritize emotes that start with user input.',
|
||||||
|
component: 'setting-check-box'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
|
|
||||||
|
@ -308,7 +361,7 @@ export default class Input extends Module {
|
||||||
if ( inst.chatInputRef instanceof Element ) {
|
if ( inst.chatInputRef instanceof Element ) {
|
||||||
const style = getComputedStyle(inst.chatInputRef),
|
const style = getComputedStyle(inst.chatInputRef),
|
||||||
height = style && parseFloat(style.lineHeight || 18) || 18,
|
height = style && parseFloat(style.lineHeight || 18) || 18,
|
||||||
t = height * 1 + 20,
|
t = height * 1 + 20.5,
|
||||||
i = Math.ceil((inst.chatInputRef.scrollHeight - t) / height),
|
i = Math.ceil((inst.chatInputRef.scrollHeight - t) / height),
|
||||||
a = Math.min(1 + i, 4);
|
a = Math.min(1 + i, 4);
|
||||||
|
|
||||||
|
@ -330,6 +383,46 @@ export default class Input extends Module {
|
||||||
inst.tempInput = '';
|
inst.tempInput = '';
|
||||||
inst.messageHistoryPos = -1;
|
inst.messageHistoryPos = -1;
|
||||||
|
|
||||||
|
inst.ffzGetValue = function() {
|
||||||
|
if ( inst.chatInputRef && typeof inst.chatInputRef.value === 'string' )
|
||||||
|
return inst.chatInputRef.value;
|
||||||
|
|
||||||
|
if ( inst.state.value && typeof inst.state.value === 'string' )
|
||||||
|
return inst.state.value;
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
inst.ffzGetSelection = function() {
|
||||||
|
if ( typeof inst.chatInputRef?.selectionEnd === 'number' ) {
|
||||||
|
return [inst.chatInputRef.selectionStart, inst.chatInputRef.selectionEnd]
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( inst.chatInputRef?.state?.slateEditor ) {
|
||||||
|
const editor = inst.chatInputRef.state.slateEditor,
|
||||||
|
sel = editor.selection,
|
||||||
|
nodes = editor.children;
|
||||||
|
|
||||||
|
if ( ! sel?.anchor?.path || ! sel?.focus?.path )
|
||||||
|
return [0,0];
|
||||||
|
|
||||||
|
const first = getNodeOffset(nodes, sel.anchor.path) + sel.anchor.offset,
|
||||||
|
second = getNodeOffset(nodes, sel.focus.path) + sel.focus.offset;
|
||||||
|
|
||||||
|
if ( first < second )
|
||||||
|
return [first, second];
|
||||||
|
else
|
||||||
|
return [second, first];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [0,0];
|
||||||
|
}
|
||||||
|
|
||||||
|
inst.ffzSetSelection = function(start, end) {
|
||||||
|
if ( inst.chatInputRef?.setSelectionRange )
|
||||||
|
inst.chatInputRef.setSelectionRange(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
inst.onKeyDown = function(event) {
|
inst.onKeyDown = function(event) {
|
||||||
try {
|
try {
|
||||||
const code = event.charCode || event.keyCode;
|
const code = event.charCode || event.keyCode;
|
||||||
|
@ -340,33 +433,40 @@ export default class Input extends Module {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( inst.autocompleteInputRef && t.chat.context.get('chat.mru.enabled') && ! event.shiftKey && ! event.ctrlKey && ! event.altKey ) {
|
const val = inst.ffzGetValue();
|
||||||
|
|
||||||
|
if ( inst.autocompleteInputRef && inst.chatInputRef && t.chat.context.get('chat.mru.enabled') && ! event.shiftKey && ! event.ctrlKey && ! event.altKey ) {
|
||||||
|
const sel = inst.ffzGetSelection();
|
||||||
|
|
||||||
// Arrow Up
|
// Arrow Up
|
||||||
if ( code === 38 && inst.chatInputRef.selectionStart === 0 ) {
|
if ( code === 38 && sel[0] === 0 && sel[1] === 0 ) {
|
||||||
if ( ! inst.messageHistory.length )
|
if ( ! inst.messageHistory.length )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( inst.chatInputRef.value && inst.messageHistoryPos === -1 )
|
if ( val && inst.messageHistoryPos === -1 )
|
||||||
inst.tempInput = inst.chatInputRef.value;
|
inst.tempInput = val;
|
||||||
|
|
||||||
if ( inst.messageHistoryPos < inst.messageHistory.length - 1 ) {
|
if ( inst.messageHistoryPos < inst.messageHistory.length - 1 ) {
|
||||||
inst.messageHistoryPos++;
|
inst.messageHistoryPos++;
|
||||||
inst.autocompleteInputRef.setValue(inst.messageHistory[inst.messageHistoryPos]);
|
inst.autocompleteInputRef.setValue(inst.messageHistory[inst.messageHistoryPos]);
|
||||||
|
inst.ffzSetSelection(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Arrow Down
|
// Arrow Down
|
||||||
} else if ( code === 40 && inst.chatInputRef.selectionStart == inst.chatInputRef.value.length ) {
|
} else if ( code === 40 && sel[0] >= val.length && sel[1] === sel[0] ) {
|
||||||
if ( ! inst.messageHistory.length )
|
if ( ! inst.messageHistory.length )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ( inst.messageHistoryPos > 0 ) {
|
if ( inst.messageHistoryPos > 0 ) {
|
||||||
inst.messageHistoryPos--;
|
inst.messageHistoryPos--;
|
||||||
inst.autocompleteInputRef.setValue(inst.messageHistory[inst.messageHistoryPos]);
|
inst.autocompleteInputRef.setValue(inst.messageHistory[inst.messageHistoryPos]);
|
||||||
|
inst.ffzSetSelection(inst.messageHistory[inst.messageHistoryPos].length);
|
||||||
|
|
||||||
} else if ( inst.messageHistoryPos === 0 ) {
|
} else if ( inst.messageHistoryPos === 0 ) {
|
||||||
inst.autocompleteInputRef.setValue(inst.tempInput);
|
inst.autocompleteInputRef.setValue(inst.tempInput);
|
||||||
|
inst.ffzSetSelection(inst.tempInput.length);
|
||||||
inst.messageHistoryPos = -1;
|
inst.messageHistoryPos = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,10 +493,13 @@ export default class Input extends Module {
|
||||||
inst.onMessageSend = function(event) {
|
inst.onMessageSend = function(event) {
|
||||||
try {
|
try {
|
||||||
if ( t.chat.context.get('chat.mru.enabled') ) {
|
if ( t.chat.context.get('chat.mru.enabled') ) {
|
||||||
if (! inst.messageHistory.length || inst.messageHistory[0] !== inst.chatInputRef.value) {
|
const val = inst.ffzGetValue();
|
||||||
inst.messageHistory.unshift(inst.chatInputRef.value);
|
if (val && val.length) {
|
||||||
|
if (! inst.messageHistory.length || inst.messageHistory[0] !== val) {
|
||||||
|
inst.messageHistory.unshift(val);
|
||||||
inst.messageHistory = inst.messageHistory.slice(0, 20);
|
inst.messageHistory = inst.messageHistory.slice(0, 20);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
inst.messageHistoryPos = -1;
|
inst.messageHistoryPos = -1;
|
||||||
inst.tempInput = '';
|
inst.tempInput = '';
|
||||||
}
|
}
|
||||||
|
@ -493,7 +596,10 @@ export default class Input extends Module {
|
||||||
inst.doesEmoteMatchTerm = function(emote, term) {
|
inst.doesEmoteMatchTerm = function(emote, term) {
|
||||||
const emote_name = emote.name || emote.token;
|
const emote_name = emote.name || emote.token;
|
||||||
if ( ! emote_name )
|
if ( ! emote_name )
|
||||||
return false;
|
return NO_MATCH;
|
||||||
|
|
||||||
|
if (emote_name.startsWith(term))
|
||||||
|
return EXACT_PREFIX_MATCH;
|
||||||
|
|
||||||
let emote_lower = emote.tokenLower;
|
let emote_lower = emote.tokenLower;
|
||||||
if ( ! emote_lower )
|
if ( ! emote_lower )
|
||||||
|
@ -501,13 +607,13 @@ export default class Input extends Module {
|
||||||
|
|
||||||
const term_lower = term.toLowerCase();
|
const term_lower = term.toLowerCase();
|
||||||
if (emote_lower.startsWith(term_lower))
|
if (emote_lower.startsWith(term_lower))
|
||||||
return true;
|
return CASE_INSENSITIVE_PREFIX_MATCH;
|
||||||
|
|
||||||
const idx = emote_name.indexOf(term.charAt(0).toUpperCase());
|
const idx = emote_name.indexOf(term.charAt(0).toUpperCase());
|
||||||
if (idx !== -1)
|
if (idx !== -1 && emote_lower.slice(idx + 1).startsWith(term_lower.slice(1)))
|
||||||
return emote_lower.slice(idx + 1).startsWith(term_lower.slice(1));
|
return NON_PREFIX_MATCH;
|
||||||
|
|
||||||
return false;
|
return NO_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
inst.getMatchedEmotes = function(input) {
|
inst.getMatchedEmotes = function(input) {
|
||||||
|
@ -527,7 +633,7 @@ export default class Input extends Module {
|
||||||
results = Array.isArray(results) ? results.concat(emoji) : emoji;
|
results = Array.isArray(results) ? results.concat(emoji) : emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
results = t.sortFavorites(results);
|
results = t.sortEmotes(results);
|
||||||
return limitResults && results.length > 25 ? results.slice(0, 25) : results;
|
return limitResults && results.length > 25 ? results.slice(0, 25) : results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,21 +674,50 @@ export default class Input extends Module {
|
||||||
|
|
||||||
|
|
||||||
// eslint-disable-next-line class-methods-use-this
|
// eslint-disable-next-line class-methods-use-this
|
||||||
sortFavorites(results) {
|
sortEmotes(emotes) {
|
||||||
if (!this.chat.context.get('chat.tab-complete.prioritize-favorites')) {
|
const preferFavorites = this.chat.context.get('chat.tab-complete.prioritize-favorites');
|
||||||
return results;
|
const canBeTriggeredByTab = this.chat.context.get('chat.tab-complete.emotes-without-colon');
|
||||||
|
const prioritizePrefixMatches = this.chat.context.get('chat.tab-complete.prioritize-prefix-matches');
|
||||||
|
|
||||||
|
return emotes.sort((a, b) => {
|
||||||
|
const aStr = a.matched || a.replacement;
|
||||||
|
const bStr = b.matched || b.replacement;
|
||||||
|
|
||||||
|
// Prefer favorites over non-favorites, if enabled
|
||||||
|
if (preferFavorites && (a.favorite ^ b.favorite))
|
||||||
|
return 0 - a.favorite + b.favorite;
|
||||||
|
|
||||||
|
if (prioritizePrefixMatches) {
|
||||||
|
// Prefer emoji over emotes if tab-complete is enabled, disprefer them otherwise
|
||||||
|
const aIsEmoji = !!a.matched;
|
||||||
|
const bIsEmoji = !!b.matched;
|
||||||
|
if (aIsEmoji ^ bIsEmoji) {
|
||||||
|
if (canBeTriggeredByTab) return 0 - aIsEmoji + bIsEmoji;
|
||||||
|
else return 0 - bIsEmoji + aIsEmoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
return results.sort((a, b) => {
|
// Prefer case-sensitive prefix matches
|
||||||
if (a.favorite) {
|
const aStartsWithInput = (a.match_type === EXACT_PREFIX_MATCH);
|
||||||
return b.favorite ? a.replacement.localeCompare(b.replacement) : -1;
|
const bStartsWithInput = (b.match_type === EXACT_PREFIX_MATCH);
|
||||||
}
|
if (aStartsWithInput && bStartsWithInput)
|
||||||
else if (b.favorite) {
|
return locale.compare(aStr, bStr);
|
||||||
return 1;
|
else if (aStartsWithInput) return -1;
|
||||||
}
|
else if (bStartsWithInput) return 1;
|
||||||
else {
|
|
||||||
a.replacement.localeCompare(b.replacement)
|
// Else prefer case-insensitive prefix matches
|
||||||
|
const aStartsWithInputCI = (a.match_type === CASE_INSENSITIVE_PREFIX_MATCH);
|
||||||
|
const bStartsWithInputCI = (b.match_type === CASE_INSENSITIVE_PREFIX_MATCH);
|
||||||
|
if (aStartsWithInputCI && bStartsWithInputCI)
|
||||||
|
return localeCaseInsensitive.compare(aStr, bStr);
|
||||||
|
else if (aStartsWithInputCI) return -1;
|
||||||
|
else if (bStartsWithInputCI) return 1;
|
||||||
|
|
||||||
|
// Else alphabetize
|
||||||
|
return locale.compare(aStr, bStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep unsorted order for non-favorite items if prefix matching is not enabled.
|
||||||
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,19 +812,21 @@ export default class Input extends Module {
|
||||||
search = input.startsWith(':') ? input.slice(1) : input;
|
search = input.startsWith(':') ? input.slice(1) : input;
|
||||||
|
|
||||||
for(const emote of emotes) {
|
for(const emote of emotes) {
|
||||||
if ( inst.doesEmoteMatchTerm(emote, search) ) {
|
const match_type = inst.doesEmoteMatchTerm(emote, search);
|
||||||
|
if ( match_type !== NO_MATCH ) {
|
||||||
const element = {
|
const element = {
|
||||||
current: input,
|
current: input,
|
||||||
emote,
|
emote,
|
||||||
replacement: emote.token,
|
replacement: emote.token,
|
||||||
element: inst.renderEmoteSuggestion(emote),
|
element: inst.renderEmoteSuggestion(emote),
|
||||||
favorite: emote.favorite,
|
favorite: emote.favorite,
|
||||||
count: this.EmoteUsageCount[emote.token] || 0
|
count: this.EmoteUsageCount[emote.token] || 0,
|
||||||
|
match_type
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( element.count > 0 )
|
if ( element.count > 0 )
|
||||||
results_usage.push(element);
|
results_usage.push(element);
|
||||||
else if ( emote.token.toLowerCase().startsWith(search) )
|
else if ( match_type > NON_PREFIX_MATCH )
|
||||||
results_starting.push(element);
|
results_starting.push(element);
|
||||||
else
|
else
|
||||||
results_other.push(element);
|
results_other.push(element);
|
||||||
|
@ -697,8 +834,8 @@ export default class Input extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
results_usage.sort((a,b) => b.count - a.count);
|
results_usage.sort((a,b) => b.count - a.count);
|
||||||
results_starting.sort((a,b) => a.replacement.localeCompare(b.replacement));
|
results_starting.sort((a,b) => locale.compare(a.replacement, b.replacement));
|
||||||
results_other.sort((a,b) => a.replacement.localeCompare(b.replacement));
|
results_other.sort((a,b) => locale.compare(a.replacement, b.replacement));
|
||||||
|
|
||||||
return results_usage.concat(results_starting).concat(results_other);
|
return results_usage.concat(results_starting).concat(results_other);
|
||||||
}
|
}
|
||||||
|
@ -835,14 +972,16 @@ export default class Input extends Module {
|
||||||
results = [];
|
results = [];
|
||||||
|
|
||||||
for(const emote of emotes) {
|
for(const emote of emotes) {
|
||||||
if ( inst.doesEmoteMatchTerm(emote, search) )
|
const match_type = inst.doesEmoteMatchTerm(emote, search)
|
||||||
|
if ( match_type !== NO_MATCH )
|
||||||
results.push({
|
results.push({
|
||||||
current: input,
|
current: input,
|
||||||
emote,
|
emote,
|
||||||
replacement: emote.token,
|
replacement: emote.token,
|
||||||
element: inst.renderEmoteSuggestion(emote),
|
element: inst.renderEmoteSuggestion(emote),
|
||||||
favorite: emote.favorite,
|
favorite: emote.favorite,
|
||||||
count: 0 // TODO: Count stuff?
|
count: 0, // TODO: Count stuff?
|
||||||
|
match_type
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,6 @@ const SUB_TIERS = {
|
||||||
3000: 3
|
3000: 3
|
||||||
};
|
};
|
||||||
|
|
||||||
function getGiftThemeURL(theme) {
|
|
||||||
return `https://static-cdn.jtvnw.net/subs-image-assets/TUN-${theme}.png`;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default class ChatLine extends Module {
|
export default class ChatLine extends Module {
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
|
@ -489,18 +485,26 @@ other {# messages were deleted by a moderator.}
|
||||||
const user_block = t.chat.formatUser(user, e);
|
const user_block = t.chat.formatUser(user, e);
|
||||||
const override_name = t.overrides.getName(user.id);
|
const override_name = t.overrides.getName(user.id);
|
||||||
|
|
||||||
|
const user_props = {
|
||||||
|
className: `chat-line__username notranslate${override_name ? ' ffz--name-override tw-relative ffz-il-tooltip__container' : ''} ${msg.ffz_user_class ?? ''}`,
|
||||||
|
role: 'button',
|
||||||
|
style: { color },
|
||||||
|
onClick: this.ffz_user_click_handler,
|
||||||
|
onContextMenu: t.actions.handleUserContext
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( msg.ffz_user_props )
|
||||||
|
Object.assign(user_props, msg.ffz_user_props);
|
||||||
|
|
||||||
|
if ( msg.ffz_user_style )
|
||||||
|
Object.assign(user_props.style, msg.ffz_user_style);
|
||||||
|
|
||||||
const user_bits = [
|
const user_bits = [
|
||||||
t.actions.renderInline(msg, this.props.showModerationIcons, u, r, e),
|
t.actions.renderInline(msg, this.props.showModerationIcons, u, r, e),
|
||||||
e('span', {
|
e('span', {
|
||||||
className: 'chat-line__message--badges'
|
className: 'chat-line__message--badges'
|
||||||
}, t.chat.badges.render(msg, e)),
|
}, t.chat.badges.render(msg, e)),
|
||||||
e('span', {
|
e('span', user_props, override_name ? [
|
||||||
className: `chat-line__username notranslate${override_name ? ' ffz--name-override tw-relative ffz-il-tooltip__container' : ''}`,
|
|
||||||
role: 'button',
|
|
||||||
style: { color },
|
|
||||||
onClick: this.ffz_user_click_handler,
|
|
||||||
onContextMenu: t.actions.handleUserContext
|
|
||||||
}, override_name ? [
|
|
||||||
e('span', {
|
e('span', {
|
||||||
className: 'chat-author__display-name'
|
className: 'chat-author__display-name'
|
||||||
}, override_name),
|
}, override_name),
|
||||||
|
|
|
@ -47,6 +47,7 @@ export default class VideoChatHook extends Module {
|
||||||
this.inject('site.web_munch');
|
this.inject('site.web_munch');
|
||||||
|
|
||||||
this.inject('chat');
|
this.inject('chat');
|
||||||
|
this.inject('chat.overrides');
|
||||||
this.injectAs('site_chat', 'site.chat');
|
this.injectAs('site_chat', 'site.chat');
|
||||||
this.inject('site.chat.chat_line.rich_content');
|
this.inject('site.chat.chat_line.rich_content');
|
||||||
|
|
||||||
|
@ -248,7 +249,8 @@ export default class VideoChatHook extends Module {
|
||||||
action_italic = action_style >= 2,
|
action_italic = action_style >= 2,
|
||||||
action_color = action_style === 1 || action_style === 3,
|
action_color = action_style === 1 || action_style === 3,
|
||||||
user = msg.user,
|
user = msg.user,
|
||||||
color = t.site_chat.colors.process(user.color),
|
raw_color = t.overrides.getColor(user.id) || user.color,
|
||||||
|
color = t.site_chat.colors.process(raw_color),
|
||||||
|
|
||||||
u = t.site.getUser();
|
u = t.site.getUser();
|
||||||
|
|
||||||
|
@ -313,18 +315,38 @@ export default class VideoChatHook extends Module {
|
||||||
const tokens = msg.ffz_tokens = msg.ffz_tokens || t.chat.tokenizeMessage(msg, u),
|
const tokens = msg.ffz_tokens = msg.ffz_tokens || t.chat.tokenizeMessage(msg, u),
|
||||||
rich_content = FFZRichContent && t.chat.pluckRichContent(tokens, msg);
|
rich_content = FFZRichContent && t.chat.pluckRichContent(tokens, msg);
|
||||||
|
|
||||||
|
const user_block = t.chat.formatUser(user, createElement);
|
||||||
|
const override_name = t.overrides.getName(user.id);
|
||||||
|
|
||||||
|
const user_props = {
|
||||||
|
className: `video-chat__message-author notranslate${override_name ? ' ffz--name-override tw-relative ffz-il-tooltip__container' : ''} ${msg.ffz_user_class ?? ''}`,
|
||||||
|
'data-test-selector': 'comment-author-selector',
|
||||||
|
href: `/${user.login}`,
|
||||||
|
rel: 'noopener noreferrer',
|
||||||
|
target: '_blank',
|
||||||
|
style: { color }
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( msg.ffz_user_props )
|
||||||
|
Object.assign(user_props, msg.ffz_user_props);
|
||||||
|
|
||||||
|
if ( msg.ffz_user_style )
|
||||||
|
Object.assign(user_props.style, msg.ffz_user_style);
|
||||||
|
|
||||||
|
const user_bits = createElement('a', user_props, override_name ? [
|
||||||
|
createElement('span', {
|
||||||
|
className: 'chat-author__display-name'
|
||||||
|
}, override_name),
|
||||||
|
createElement('div', {
|
||||||
|
className: 'ffz-il-tooltip ffz-il-tooltip--down ffz-il-tooltip--align-center'
|
||||||
|
}, user_block)
|
||||||
|
] : user_block);
|
||||||
|
|
||||||
let out = (<div class="tw-flex-grow-1" data-room-id={msg.roomID} data-room={msg.roomLogin} data-user-id={user.id} data-user={user.login}>
|
let out = (<div class="tw-flex-grow-1" data-room-id={msg.roomID} data-room={msg.roomLogin} data-user-id={user.id} data-user={user.login}>
|
||||||
<span class="chat-line__message--badges">{
|
<span class="chat-line__message--badges">{
|
||||||
t.chat.badges.render(msg, createElement)
|
t.chat.badges.render(msg, createElement)
|
||||||
}</span>
|
}</span>
|
||||||
<a
|
{user_bits}
|
||||||
class="video-chat__message-author notranslate"
|
|
||||||
data-test-selector="comment-author-selector"
|
|
||||||
href={`/${user.login}`}
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
style={{color}}
|
|
||||||
>{t.chat.formatUser(user, createElement)}</a>
|
|
||||||
<div data-test-selector="comment-message-selector" class="tw-inline video-chat__message">
|
<div data-test-selector="comment-message-selector" class="tw-inline video-chat__message">
|
||||||
<span>{is_action ? ' ' : ': '}</span>
|
<span>{is_action ? ' ' : ': '}</span>
|
||||||
<span
|
<span
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
|
|
||||||
.ffz--inline-reasons {
|
.ffz--inline-reasons {
|
||||||
max-width: 30rem;
|
max-width: 30rem;
|
||||||
|
|
||||||
|
.scrollable-area {
|
||||||
|
max-height: min(90vh, max(30rem, 50vh));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ffz--inline-actions {
|
.ffz--inline-actions {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue