fix(lint) make sure eslint also runs on TypeScript files (#11777)

Co-authored-by: robertpin <robert.pin9@gmail.com>
Co-authored-by: Gabriel Borlea <gabriel.borlea@8x8.com>
This commit is contained in:
Saúl Ibarra Corretgé 2022-07-11 14:30:37 +02:00 committed by GitHub
parent 61a6ce2a2e
commit b0deb9ec0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 1063 additions and 200 deletions

647
package-lock.json generated
View File

@ -148,6 +148,8 @@
"@types/react-native": "0.67.6",
"@types/react-redux": "7.1.24",
"@types/uuid": "8.3.4",
"@typescript-eslint/eslint-plugin": "5.30.5",
"@typescript-eslint/parser": "5.30.4",
"babel-loader": "8.2.3",
"babel-plugin-optional-require": "0.3.1",
"circular-dependency-plugin": "5.2.0",
@ -5644,6 +5646,392 @@
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz",
"integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw=="
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.5.tgz",
"integrity": "sha512-lftkqRoBvc28VFXEoRgyZuztyVUQ04JvUnATSPtIRFAccbXTWL6DEtXGYMcbg998kXw1NLUJm7rTQ9eUt+q6Ig==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.30.5",
"@typescript-eslint/type-utils": "5.30.5",
"@typescript-eslint/utils": "5.30.5",
"debug": "^4.3.4",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.2.0",
"regexpp": "^3.2.0",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.5.tgz",
"integrity": "sha512-NJ6F+YHHFT/30isRe2UTmIGGAiXKckCyMnIV58cE3JkHmaD6e5zyEYm5hBDv0Wbin+IC0T1FWJpD3YqHUG/Ydg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.30.5",
"@typescript-eslint/visitor-keys": "5.30.5"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.5.tgz",
"integrity": "sha512-kZ80w/M2AvsbRvOr3PjaNh6qEW1LFqs2pLdo2s5R38B2HYXG8Z0PP48/4+j1QHJFL3ssHIbJ4odPRS8PlHrFfw==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.5.tgz",
"integrity": "sha512-D+xtGo9HUMELzWIUqcQc0p2PO4NyvTrgIOK/VnSH083+8sq0tiLozNRKuLarwHYGRuA6TVBQSuuLwJUDWd3aaA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.30.5",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
"dev": true,
"engines": {
"node": ">= 4"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@typescript-eslint/parser": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.4.tgz",
"integrity": "sha512-/ge1HtU63wVoED4VnlU2o+FPFmi017bPYpeSrCmd8Ycsti4VSxXrmcpXXm7JpI4GT0Aa7qviabv1PEp6L5bboQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.30.4",
"@typescript-eslint/types": "5.30.4",
"@typescript-eslint/typescript-estree": "5.30.4",
"debug": "^4.3.4"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.4.tgz",
"integrity": "sha512-DNzlQwGSiGefz71JwaHrpcaAX3zYkEcy8uVuan3YMKOa6qeW/y+7SaD8KIsIAruASwq6P+U4BjWBWtM2O+mwBQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.30.4",
"@typescript-eslint/visitor-keys": "5.30.4"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.5.tgz",
"integrity": "sha512-k9+ejlv1GgwN1nN7XjVtyCgE0BTzhzT1YsQF0rv4Vfj2U9xnslBgMYYvcEYAFVdvhuEscELJsB7lDkN7WusErw==",
"dev": true,
"dependencies": {
"@typescript-eslint/utils": "5.30.5",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/types": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.4.tgz",
"integrity": "sha512-NTEvqc+Vvu8Q6JeAKryHk2eqLKqsr2St3xhIjhOjQv5wQUBhaTuix4WOSacqj0ONWfKVU12Eug3LEAB95GBkMA==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.4.tgz",
"integrity": "sha512-V4VnEs6/J9/nNizaA12IeU4SAeEYaiKr7XndLNfV5+3zZSB4hIu6EhHJixTKhvIqA+EEHgBl6re8pivBMLLO1w==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.30.4",
"@typescript-eslint/visitor-keys": "5.30.4",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@typescript-eslint/utils": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.5.tgz",
"integrity": "sha512-o4SSUH9IkuA7AYIfAvatldovurqTAHrfzPApOZvdUq01hHojZojCFXx06D/aFpKCgWbMPRdJBWAC3sWp3itwTA==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.30.5",
"@typescript-eslint/types": "5.30.5",
"@typescript-eslint/typescript-estree": "5.30.5",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.5.tgz",
"integrity": "sha512-NJ6F+YHHFT/30isRe2UTmIGGAiXKckCyMnIV58cE3JkHmaD6e5zyEYm5hBDv0Wbin+IC0T1FWJpD3YqHUG/Ydg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.30.5",
"@typescript-eslint/visitor-keys": "5.30.5"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.5.tgz",
"integrity": "sha512-kZ80w/M2AvsbRvOr3PjaNh6qEW1LFqs2pLdo2s5R38B2HYXG8Z0PP48/4+j1QHJFL3ssHIbJ4odPRS8PlHrFfw==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.5.tgz",
"integrity": "sha512-qGTc7QZC801kbYjAr4AgdOfnokpwStqyhSbiQvqGBLixniAKyH+ib2qXIVo4P9NgGzwyfD9I0nlJN7D91E1VpQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.30.5",
"@typescript-eslint/visitor-keys": "5.30.5",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.5.tgz",
"integrity": "sha512-D+xtGo9HUMELzWIUqcQc0p2PO4NyvTrgIOK/VnSH083+8sq0tiLozNRKuLarwHYGRuA6TVBQSuuLwJUDWd3aaA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.30.5",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@typescript-eslint/utils/node_modules/semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.4.tgz",
"integrity": "sha512-ulKGse3mruSc8x6l8ORSc6+1ORyJzKmZeIaRTu/WpaF/jx3vHvEn5XZUKF9XaVg2710mFmTAUlLcLYLPp/Zf/Q==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.30.4",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@vladmandic/human": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/@vladmandic/human/-/human-2.6.5.tgz",
@ -18684,6 +19072,27 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"dependencies": {
"tslib": "^1.8.1"
},
"engines": {
"node": ">= 6"
},
"peerDependencies": {
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
}
},
"node_modules/tsutils/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@ -24339,6 +24748,227 @@
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz",
"integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw=="
},
"@typescript-eslint/eslint-plugin": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.5.tgz",
"integrity": "sha512-lftkqRoBvc28VFXEoRgyZuztyVUQ04JvUnATSPtIRFAccbXTWL6DEtXGYMcbg998kXw1NLUJm7rTQ9eUt+q6Ig==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.30.5",
"@typescript-eslint/type-utils": "5.30.5",
"@typescript-eslint/utils": "5.30.5",
"debug": "^4.3.4",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.2.0",
"regexpp": "^3.2.0",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"dependencies": {
"@typescript-eslint/scope-manager": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.5.tgz",
"integrity": "sha512-NJ6F+YHHFT/30isRe2UTmIGGAiXKckCyMnIV58cE3JkHmaD6e5zyEYm5hBDv0Wbin+IC0T1FWJpD3YqHUG/Ydg==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.30.5",
"@typescript-eslint/visitor-keys": "5.30.5"
}
},
"@typescript-eslint/types": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.5.tgz",
"integrity": "sha512-kZ80w/M2AvsbRvOr3PjaNh6qEW1LFqs2pLdo2s5R38B2HYXG8Z0PP48/4+j1QHJFL3ssHIbJ4odPRS8PlHrFfw==",
"dev": true
},
"@typescript-eslint/visitor-keys": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.5.tgz",
"integrity": "sha512-D+xtGo9HUMELzWIUqcQc0p2PO4NyvTrgIOK/VnSH083+8sq0tiLozNRKuLarwHYGRuA6TVBQSuuLwJUDWd3aaA==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.30.5",
"eslint-visitor-keys": "^3.3.0"
}
},
"eslint-visitor-keys": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
"dev": true
},
"ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
"dev": true
},
"semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
}
}
},
"@typescript-eslint/parser": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.4.tgz",
"integrity": "sha512-/ge1HtU63wVoED4VnlU2o+FPFmi017bPYpeSrCmd8Ycsti4VSxXrmcpXXm7JpI4GT0Aa7qviabv1PEp6L5bboQ==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.30.4",
"@typescript-eslint/types": "5.30.4",
"@typescript-eslint/typescript-estree": "5.30.4",
"debug": "^4.3.4"
}
},
"@typescript-eslint/scope-manager": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.4.tgz",
"integrity": "sha512-DNzlQwGSiGefz71JwaHrpcaAX3zYkEcy8uVuan3YMKOa6qeW/y+7SaD8KIsIAruASwq6P+U4BjWBWtM2O+mwBQ==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.30.4",
"@typescript-eslint/visitor-keys": "5.30.4"
}
},
"@typescript-eslint/type-utils": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.5.tgz",
"integrity": "sha512-k9+ejlv1GgwN1nN7XjVtyCgE0BTzhzT1YsQF0rv4Vfj2U9xnslBgMYYvcEYAFVdvhuEscELJsB7lDkN7WusErw==",
"dev": true,
"requires": {
"@typescript-eslint/utils": "5.30.5",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/types": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.4.tgz",
"integrity": "sha512-NTEvqc+Vvu8Q6JeAKryHk2eqLKqsr2St3xhIjhOjQv5wQUBhaTuix4WOSacqj0ONWfKVU12Eug3LEAB95GBkMA==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.4.tgz",
"integrity": "sha512-V4VnEs6/J9/nNizaA12IeU4SAeEYaiKr7XndLNfV5+3zZSB4hIu6EhHJixTKhvIqA+EEHgBl6re8pivBMLLO1w==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.30.4",
"@typescript-eslint/visitor-keys": "5.30.4",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
},
"dependencies": {
"semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
}
}
},
"@typescript-eslint/utils": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.5.tgz",
"integrity": "sha512-o4SSUH9IkuA7AYIfAvatldovurqTAHrfzPApOZvdUq01hHojZojCFXx06D/aFpKCgWbMPRdJBWAC3sWp3itwTA==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.30.5",
"@typescript-eslint/types": "5.30.5",
"@typescript-eslint/typescript-estree": "5.30.5",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
"dependencies": {
"@typescript-eslint/scope-manager": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.5.tgz",
"integrity": "sha512-NJ6F+YHHFT/30isRe2UTmIGGAiXKckCyMnIV58cE3JkHmaD6e5zyEYm5hBDv0Wbin+IC0T1FWJpD3YqHUG/Ydg==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.30.5",
"@typescript-eslint/visitor-keys": "5.30.5"
}
},
"@typescript-eslint/types": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.5.tgz",
"integrity": "sha512-kZ80w/M2AvsbRvOr3PjaNh6qEW1LFqs2pLdo2s5R38B2HYXG8Z0PP48/4+j1QHJFL3ssHIbJ4odPRS8PlHrFfw==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.5.tgz",
"integrity": "sha512-qGTc7QZC801kbYjAr4AgdOfnokpwStqyhSbiQvqGBLixniAKyH+ib2qXIVo4P9NgGzwyfD9I0nlJN7D91E1VpQ==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.30.5",
"@typescript-eslint/visitor-keys": "5.30.5",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"semver": "^7.3.7",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.30.5",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.5.tgz",
"integrity": "sha512-D+xtGo9HUMELzWIUqcQc0p2PO4NyvTrgIOK/VnSH083+8sq0tiLozNRKuLarwHYGRuA6TVBQSuuLwJUDWd3aaA==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.30.5",
"eslint-visitor-keys": "^3.3.0"
}
},
"eslint-visitor-keys": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
"dev": true
},
"semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
}
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.30.4",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.4.tgz",
"integrity": "sha512-ulKGse3mruSc8x6l8ORSc6+1ORyJzKmZeIaRTu/WpaF/jx3vHvEn5XZUKF9XaVg2710mFmTAUlLcLYLPp/Zf/Q==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.30.4",
"eslint-visitor-keys": "^3.3.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
"dev": true
}
}
},
"@vladmandic/human": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/@vladmandic/human/-/human-2.6.5.tgz",
@ -34413,6 +35043,23 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
},
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
}
}
},
"type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",

View File

@ -153,6 +153,8 @@
"@types/react-native": "0.67.6",
"@types/react-redux": "7.1.24",
"@types/uuid": "8.3.4",
"@typescript-eslint/eslint-plugin": "5.30.5",
"@typescript-eslint/parser": "5.30.4",
"babel-loader": "8.2.3",
"babel-plugin-optional-require": "0.3.1",
"circular-dependency-plugin": "5.2.0",
@ -188,9 +190,9 @@
},
"license": "Apache-2.0",
"scripts": {
"lint": "eslint --max-warnings 0 .",
"lint": "eslint --ext .js,.ts,.tsx --max-warnings 0 .",
"lang-sort": "./resources/lang-sort.sh",
"lint-fix": "eslint --max-warnings 0 --fix .",
"lint-fix": "eslint --ext .js,.ts,.tsx --max-warnings 0 --fix .",
"postinstall": "patch-package --error-on-fail && jetify",
"validate": "npm ls",
"start": "make dev"

View File

@ -6,6 +6,27 @@ module.exports = {
'@jitsi/eslint-config/react',
'.eslintrc-react-native.js'
],
'overrides': [
{
'files': [ '*.ts', '*.tsx' ],
parser: '@typescript-eslint/parser',
rules: {
'no-undef': 'off',
'no-use-before-define': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'no-prototype-builtins': 'off'
},
'plugins': [ '@typescript-eslint' ],
'extends': [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended'
]
}
],
'rules': {
'flowtype/no-types-missing-file-annotation': 0,

View File

@ -44,7 +44,7 @@ export * from './actions.any';
* scheme, or a mere room name.
* @returns {Function}
*/
export function appNavigate(uri: ?string) {
export function appNavigate(uri?: string) {
logger.info(`appNavigate to ${uri}`);
return async (dispatch: Dispatch<any>, getState: Function) => {

View File

@ -1,10 +1,10 @@
import { IAnalyticsState } from "../analytics/reducer"
import { IAuthenticationState } from "../authentication/reducer"
import { IAVModerationState } from "../av-moderation/reducer"
import { IAppState } from "../base/app/reducer"
import { IAudioOnlyState } from "../base/audio-only/reducer"
import { IConferenceState } from "../base/conference/reducer"
import { IConfig } from "../base/config/configType"
import { IAnalyticsState } from '../analytics/reducer';
import { IAuthenticationState } from '../authentication/reducer';
import { IAVModerationState } from '../av-moderation/reducer';
import { IAppState } from '../base/app/reducer';
import { IAudioOnlyState } from '../base/audio-only/reducer';
import { IConferenceState } from '../base/conference/reducer';
import { IConfig } from '../base/config/configType';
export interface IStore {
getState: Function,

View File

@ -1,6 +1,8 @@
/* eslint-disable import/order */
import ReducerRegistry from '../base/redux/ReducerRegistry';
// @ts-ignore
import { assign } from '../base/redux/functions';
import ReducerRegistry from '../base/redux/ReducerRegistry';
import {
CANCEL_LOGIN,

View File

@ -1,4 +1,4 @@
import { MEDIA_TYPE, type MediaType } from '../base/media/constants';
import { MEDIA_TYPE } from '../base/media/constants';
/**
* Mapping between a media type and the witelist reducer key.

View File

@ -3,6 +3,7 @@ import type { MediaType } from '../base/media/constants';
import {
PARTICIPANT_LEFT,
PARTICIPANT_UPDATED
// @ts-ignore
} from '../base/participants';
import ReducerRegistry from '../base/redux/ReducerRegistry';
@ -52,7 +53,7 @@ function _updatePendingParticipant(mediaType: MediaType, participant: any, state
let arrayItemChanged = false;
const storeKey = MEDIA_TYPE_TO_PENDING_STORE_KEY[mediaType];
const arr = state[storeKey];
const newArr = arr.map((pending: { id: string} ) => {
const newArr = arr.map((pending: { id: string}) => {
if (pending.id === participant.id) {
arrayItemChanged = true;

View File

@ -1,9 +1,13 @@
/* eslint-disable import/order */
// @ts-ignore
import { LOCKED_LOCALLY, LOCKED_REMOTELY } from '../../room-lock';
// @ts-ignore
import { CONNECTION_WILL_CONNECT, SET_LOCATION_URL } from '../connection';
// @ts-ignore
import { JitsiConferenceErrors } from '../lib-jitsi-meet';
// @ts-ignore
import { assign, set } from '../redux';
import ReducerRegistry from '../redux/ReducerRegistry';
@ -28,6 +32,7 @@ import {
SET_START_MUTED_POLICY,
SET_START_REACTIONS_MUTED
} from './actionTypes';
// @ts-ignore
import { isRoomValid } from './functions';
@ -376,7 +381,8 @@ function _p2pStatusChanged(state: any, action: any) {
* @returns {Object} The new state of the feature base/conference after the
* reduction of the specified action.
*/
function _setPassword(state: any, { conference, method, password }: {conference: any, method: Object, password: string}) {
function _setPassword(state: any, { conference, method, password }
: {conference: any, method: Object, password: string}) {
switch (method) {
case conference.join:
return assign(state, {

View File

@ -187,7 +187,7 @@ export interface IConfig {
notifyAllParticipants?: boolean;
};
transcribingEnabled?: boolean;
transcribeWithAppLanguage?: boolean;
transcribeWithAppLanguage?: boolean;
preferredTranscribeLanguage?: string;
autoCaptionOnRecord?: boolean;
transcription?: {
@ -464,4 +464,4 @@ export interface IConfig {
tileTime?: number;
};
locationURL?: string;
}
}

View File

@ -1,6 +1,8 @@
/* eslint-disable import/order */
import _ from 'lodash';
import { CONFERENCE_INFO } from '../../conference/components/constants';
// @ts-ignore
import { equals } from '../redux';
import ReducerRegistry from '../redux/ReducerRegistry';
@ -13,10 +15,11 @@ import {
OVERWRITE_CONFIG
} from './actionTypes';
import { IConfig } from './configType';
// @ts-ignore
import { _cleanupConfig } from './functions';
declare var interfaceConfig: any;
declare let interfaceConfig: any;
/**
* The initial state of the feature base/config when executing in a
@ -307,15 +310,18 @@ function _translateLegacyConfig(oldValue: IConfig) {
filteredConferenceInfo.forEach(key => {
newValue.conferenceInfo = oldValue.conferenceInfo ?? {};
// hideRecordingLabel does not mean not render it at all, but autoHide it
if (key === 'hideRecordingLabel') {
newValue.conferenceInfo.alwaysVisible
= (newValue.conferenceInfo?.alwaysVisible ?? []).filter(c => !CONFERENCE_HEADER_MAPPING[key].includes(c));
= (newValue.conferenceInfo?.alwaysVisible ?? [])
.filter(c => !CONFERENCE_HEADER_MAPPING[key].includes(c));
newValue.conferenceInfo.autoHide
= _.union(newValue.conferenceInfo.autoHide, CONFERENCE_HEADER_MAPPING[key]);
} else {
newValue.conferenceInfo.alwaysVisible
= (newValue.conferenceInfo.alwaysVisible ?? []).filter(c => !CONFERENCE_HEADER_MAPPING[key].includes(c));
= (newValue.conferenceInfo.alwaysVisible ?? [])
.filter(c => !CONFERENCE_HEADER_MAPPING[key].includes(c));
newValue.conferenceInfo.autoHide
= (newValue.conferenceInfo.autoHide ?? []).filter(c => !CONFERENCE_HEADER_MAPPING[key].includes(c));
}

View File

@ -15,6 +15,6 @@ const BottomSheetContainer: () => JSX.Element = () => {
{ React.createElement(sheet, sheetProps) }
</Fragment>
);
}
};
export default BottomSheetContainer;

View File

@ -1,16 +1,23 @@
/* eslint-disable import/order */
import './middleware.any.js';
// @ts-ignore
import { MiddlewareRegistry } from '../redux';
import { IStore } from '../../app/types';
import { SET_VIDEO_MUTED } from './actionTypes';
import LocalRecordingManager from '../../recording/components/Recording/LocalRecordingManager.web';
// @ts-ignore
import { openDialog } from '../dialog';
// @ts-ignore
import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../../notifications';
import LocalRecordingManager from '../../recording/components/Recording/LocalRecordingManager.web';
// @ts-ignore
import StopRecordingDialog from '../../recording/components/Recording/web/StopRecordingDialog';
// @ts-ignore
import { openDialog } from '../dialog';
// @ts-ignore
import { MiddlewareRegistry } from '../redux';
import { SET_VIDEO_MUTED } from './actionTypes';
/**
* Implements the entry point of the middleware of the feature base/media.
*
@ -19,22 +26,24 @@ import StopRecordingDialog from '../../recording/components/Recording/web/StopRe
*/
MiddlewareRegistry.register((store: IStore) => (next: Function) => (action: any) => {
const { dispatch } = store;
switch(action.type) {
case SET_VIDEO_MUTED: {
if (LocalRecordingManager.isRecordingLocally() && LocalRecordingManager.selfRecording.on) {
if (action.muted && LocalRecordingManager.selfRecording.withVideo) {
dispatch(openDialog(StopRecordingDialog, { localRecordingVideoStop: true }));
return;
} else if (!action.muted && !LocalRecordingManager.selfRecording.withVideo) {
dispatch(showNotification({
titleKey: 'recording.localRecordingNoVideo',
descriptionKey: 'recording.localRecordingVideoWarning',
uid: 'recording.localRecordingNoVideo'
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
}
switch (action.type) {
case SET_VIDEO_MUTED: {
if (LocalRecordingManager.isRecordingLocally() && LocalRecordingManager.selfRecording.on) {
if (action.muted && LocalRecordingManager.selfRecording.withVideo) {
dispatch(openDialog(StopRecordingDialog, { localRecordingVideoStop: true }));
return;
} else if (!action.muted && !LocalRecordingManager.selfRecording.withVideo) {
dispatch(showNotification({
titleKey: 'recording.localRecordingNoVideo',
descriptionKey: 'recording.localRecordingVideoWarning',
uid: 'recording.localRecordingNoVideo'
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
}
}
}
}
return next(action);
});

View File

@ -7,10 +7,11 @@ import {
} from 'react-native-paper';
import BaseTheme from '../../../ui/components/BaseTheme.native';
import styles from './styles';
import { BUTTON_MODES, BUTTON_TYPES } from '../../constants';
import { ButtonProps } from '../../types';
import styles from './styles';
const Button: React.FC<ButtonProps> = ({
accessibilityLabel,
@ -35,16 +36,16 @@ const Button: React.FC<ButtonProps> = ({
if (type === PRIMARY) {
buttonLabelStyles = styles.buttonLabelPrimary;
color = BaseTheme.palette.action01;
mode = CONTAINED
mode = CONTAINED;
} else if (type === SECONDARY) {
buttonLabelStyles = styles.buttonLabelSecondary;
color = BaseTheme.palette.action02;
mode = CONTAINED
mode = CONTAINED;
} else if (type === DESTRUCTIVE) {
color = BaseTheme.palette.actionDanger;
buttonLabelStyles = styles.buttonLabelDestructive;
mode = CONTAINED
} else {
mode = CONTAINED;
} else {
color = buttonColor;
buttonLabelStyles = styles.buttonLabel;
}
@ -56,7 +57,7 @@ const Button: React.FC<ButtonProps> = ({
buttonStyles = styles.button;
}
if ( type === TERTIARY) {
if (type === TERTIARY) {
return (
<TouchableRipple
accessibilityLabel = { accessibilityLabel }
@ -69,9 +70,9 @@ const Button: React.FC<ButtonProps> = ({
] }>
<Text
style = { [
buttonLabelStyles,
labelStyle
] }>{ t(label) }</Text>
buttonLabelStyles,
labelStyle
] }>{ t(label) }</Text>
</TouchableRipple>
);
}

View File

@ -3,10 +3,11 @@ import { TouchableRipple } from 'react-native-paper';
import { Icon } from '../../../icons';
import BaseTheme from '../../../ui/components/BaseTheme.native';
import styles from './styles';
import { BUTTON_TYPES } from '../../constants';
import { IconButtonProps } from '../../types';
import styles from './styles';
const IconButton: React.FC<IconButtonProps> = ({
accessibilityLabel,
@ -33,7 +34,7 @@ const IconButton: React.FC<IconButtonProps> = ({
color = BaseTheme.palette.icon02;
iconButtonContainerStyles = styles.iconButtonContainerSecondary;
rippleColor = BaseTheme.palette.action02;
} else if ( type === TERTIARY) {
} else if (type === TERTIARY) {
color = BaseTheme.palette.icon01;
iconButtonContainerStyles = styles.iconButtonContainer;
rippleColor = BaseTheme.palette.action03;

View File

@ -5,14 +5,14 @@ import type { Reducer } from 'redux';
* The type of the dictionary/map which associates a reducer (function) with the
* name of he Redux state property managed by the reducer.
*/
declare type NameReducerMap<S, A> = { [name: string]: Reducer<S, Action<any>> };
type NameReducerMap<S> = { [name: string]: Reducer<S, Action<any>> };
/**
* A registry for Redux reducers, allowing features to register themselves
* without needing to create additional inter-feature dependencies.
*/
class ReducerRegistry {
_elements: NameReducerMap<any, any>;
_elements: NameReducerMap<any>;
/**
* Creates a ReducerRegistry instance.
@ -35,7 +35,7 @@ class ReducerRegistry {
* included (such as reducers from third-party modules).
* @returns {Function}
*/
combineReducers(additional: NameReducerMap<any, any> = {}) {
combineReducers(additional: NameReducerMap<any> = {}) {
// $FlowExpectedError
return combineReducers({
...this._elements,

View File

@ -1,7 +1,7 @@
/**
* Checks whether we are loaded in iframe.
*
* @returns Whether the current page is loaded in an iframe.
* @returns {boolean} Whether the current page is loaded in an iframe.
*/
export function inIframe(): boolean {
if (navigator.product === 'ReactNative') {

View File

@ -5,9 +5,9 @@ import BaseTheme from '../../../../base/ui/components/BaseTheme.native';
/**
* React component for Audio icon.
*
* @returns {JSX.Element} - the Audio icon.
*
*
* @returns {JSX.Element} - The Audio icon.
*
*/
const AudioIcon = () : JSX.Element => (<Icon
color = { BaseTheme.palette.text06 }

View File

@ -5,8 +5,8 @@ import BaseTheme from '../../../../base/ui/components/BaseTheme.native';
/**
* Implements an end meeting icon.
*
* @returns {JSX.Element} - the end meeting icon.
*
* @returns {JSX.Element} - The end meeting icon.
*/
const EndMeetingIcon = () : JSX.Element => (<Icon
color = { BaseTheme.palette.icon01 }

View File

@ -1,14 +1,13 @@
import React, { useCallback } from 'react';
import { useState } from 'react';
import React, { useCallback, useState } from 'react';
import { View, TouchableOpacity } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import {
createShortcutEvent,
sendAnalytics,
ACTION_SHORTCUT_PRESSED as PRESSED,
ACTION_SHORTCUT_RELEASED as RELEASED
} from '../../../../analytics';
import { getFeatureFlag, AUDIO_MUTE_BUTTON_ENABLED } from '../../../../base/flags';
import { Icon, IconMicrophone, IconMicrophoneEmptySlash } from '../../../../base/icons';
import { MEDIA_TYPE } from '../../../../base/media';
@ -41,7 +40,7 @@ const MicrophoneButton = () : JSX.Element => {
}, [ audioMuted, disabled ]);
const onLongPress = useCallback(() => {
if ( !disabled && !audioMuted) {
if (!disabled && !audioMuted) {
sendAnalytics(createShortcutEvent(
'push.to.talk',
PRESSED,
@ -49,7 +48,7 @@ const MicrophoneButton = () : JSX.Element => {
LONG_PRESS));
setLongPress(true);
}
}, [audioMuted, disabled, setLongPress]);
}, [ audioMuted, disabled, setLongPress ]);
const onPressOut = useCallback(() => {
if (longPress) {
@ -62,13 +61,13 @@ const MicrophoneButton = () : JSX.Element => {
));
dispatch(muteLocal(true, MEDIA_TYPE.AUDIO));
}
}, [longPress, setLongPress]);
}, [ longPress, setLongPress ]);
return (
<TouchableOpacity
onLongPress = { onLongPress }
onPressIn = { onPressIn }
onLongPress={ onLongPress }
onPressOut={ onPressOut } >
onPressOut = { onPressOut } >
<View
style = { [
styles.microphoneStyles.container,

View File

@ -1,16 +1,16 @@
import React from 'react';
import { StyleProp, Text, View, ViewStyle } from 'react-native';
import { useSelector } from 'react-redux';
import { Text, View } from 'react-native';
import { getConferenceName } from '../../../../base/conference/functions';
import { ConnectionIndicator } from '../../../../connection-indicator';
import { getFeatureFlag, MEETING_NAME_ENABLED } from '../../../../base/flags';
import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet';
import { connect } from '../../../../base/redux';;
import { RecordingLabel } from '../../../../recording';
import { getLocalParticipant } from '../../../../base/participants';
import { connect } from '../../../../base/redux';
import ConnectionIndicator from '../../../../connection-indicator/components/native/ConnectionIndicator';
import RecordingLabel from '../../../../recording/components/native/RecordingLabel';
import { VideoQualityLabel } from '../../../../video-quality';
import { getLocalParticipant } from '../../../../base/participants';
import styles from './styles';
@ -36,30 +36,30 @@ type Props = {
* @returns {JSX.Element}
*/
const TitleBar = (props: Props) : JSX.Element => {
const localParticipant = useSelector(getLocalParticipant);
const localParticipant = useSelector(getLocalParticipant);
const localParticipantId = localParticipant?.id;
return (<>
<View
pointerEvents = 'box-none'
style = { styles.titleBarWrapper }>
style = { styles.titleBarWrapper as StyleProp<ViewStyle> }>
<View
pointerEvents = 'box-none'
style = { styles.roomNameWrapper }>
<View style = { styles.qualityLabelContainer }>
style = { styles.roomNameWrapper as StyleProp<ViewStyle> }>
<View style = { styles.qualityLabelContainer as StyleProp<ViewStyle> }>
<VideoQualityLabel />
</View>
<ConnectionIndicator
participantId = { localParticipantId }
iconStyle = { styles.connectionIndicatorIcon } />
<View style = { styles.headerLabels }>
iconStyle = { styles.connectionIndicatorIcon }
participantId = { localParticipantId } />
<View style = { styles.headerLabels as StyleProp<ViewStyle> }>
<RecordingLabel mode = { JitsiRecordingConstants.mode.FILE } />
<RecordingLabel mode = { JitsiRecordingConstants.mode.STREAM } />
</View>
{
props._meetingNameEnabled
&& <View style = { styles.roomNameView }>
&& <View style = { styles.roomNameView as StyleProp<ViewStyle> }>
<Text
numberOfLines = { 1 }
style = { styles.roomName }>
@ -70,7 +70,7 @@ const TitleBar = (props: Props) : JSX.Element => {
</View>
</View>
</>);
}
};
/**
* Maps part of the Redux store to the props of this component.

View File

@ -1,13 +1,17 @@
/* eslint-disable import/order */
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
// @ts-ignore
import { IconMenuDown } from '../../../base/icons';
// @ts-ignore
import { Label } from '../../../base/label';
// @ts-ignore
import { Tooltip } from '../../../base/tooltip';
// @ts-ignore
import { setTopPanelVisible } from '../../../filmstrip/actions.web';
@ -20,11 +24,11 @@ const ToggleTopPanelLabel = () => {
}, []);
return topPanelHidden && (<Tooltip
content={t('toggleTopPanelLabel') }
content = { t('toggleTopPanelLabel') }
position = { 'bottom' }>
<Label
icon={IconMenuDown}
onClick = { onClick }/>
icon = { IconMenuDown }
onClick = { onClick } />
</Tooltip>);
};

View File

@ -1,5 +1,5 @@
import React from 'react';
import { Image } from 'react-native';
import { Image, ImageStyle, StyleProp, ViewStyle } from 'react-native';
import { SvgUri } from 'react-native-svg';
// @ts-ignore
@ -40,7 +40,7 @@ const BrandingImageBackground: React.FC<Props> = ({ uri }:Props) => {
// Align the <min-y> of the element's viewBox
// with the smallest Y value of the viewport.
preserveAspectRatio = 'xMinYMin'
style = { styles.brandingImageBackgroundSvg }
style = { styles.brandingImageBackgroundSvg as StyleProp<ViewStyle> }
uri = { imgSrc }
viewBox = '0 0 400 650'
width = '100%' />
@ -50,7 +50,7 @@ const BrandingImageBackground: React.FC<Props> = ({ uri }:Props) => {
= (
<Image
source = {{ uri: imgSrc }}
style = { styles.brandingImageBackground } />
style = { styles.brandingImageBackground as StyleProp<ImageStyle> } />
);
}

View File

@ -4,12 +4,12 @@ export default {
* {@code BrandingImageBackground} Style.
*/
brandingImageBackgroundSvg: {
position: 'absolute' as 'absolute'
position: 'absolute'
},
brandingImageBackground: {
height: '100%',
position: 'absolute' as 'absolute',
position: 'absolute',
width: '100%'
}
};

View File

@ -36,7 +36,7 @@ export interface FaceLandmarksHelper {
}
/**
* Helper class for human library
* Helper class for human library.
*/
export class HumanHelper implements FaceLandmarksHelper {
protected human: Human | undefined;
@ -44,6 +44,7 @@ export class HumanHelper implements FaceLandmarksHelper {
protected baseUrl: string;
private detectionInProgress = false;
private lastValidFaceBox: FaceBox | undefined;
/**
* Configuration for human.
*/
@ -66,7 +67,7 @@ export class HumanHelper implements FaceLandmarksHelper {
},
mesh: { enabled: false },
iris: { enabled: false },
emotion: {
emotion: {
enabled: false,
modelPath: 'emotion.json'
},
@ -78,12 +79,23 @@ export class HumanHelper implements FaceLandmarksHelper {
segmentation: { enabled: false }
};
/**
* Constructor function for the helper which initialize the helper.
*
* @param {InitInput} input - The input for the helper.
* @returns {void}
*/
constructor({ baseUrl, detectionTypes }: InitInput) {
this.faceDetectionTypes = detectionTypes;
this.baseUrl = baseUrl;
this.init();
}
/**
* Initializes the human helper with the available tfjs backend for the given detection types.
*
* @returns {Promise<void>}
*/
async init(): Promise<void> {
if (!this.human) {
@ -95,7 +107,7 @@ export class HumanHelper implements FaceLandmarksHelper {
}
if (this.faceDetectionTypes.length > 0 && this.config.face) {
this.config.face.enabled = true
this.config.face.enabled = true;
}
if (this.faceDetectionTypes.includes(DETECTION_TYPES.FACE_BOX) && this.config.face?.detector) {
@ -107,16 +119,24 @@ export class HumanHelper implements FaceLandmarksHelper {
}
const initialHuman = new Human(this.config);
try {
await initialHuman.load();
} catch (err) {
console.error(err);
}
this.human = initialHuman;
}
}
/**
* Gets the face box from the detections, if there is no valid detections it will return undefined..
*
* @param {Array<FaceResult>} detections - The array with the detections.
* @param {number} threshold - Face box position change threshold.
* @returns {FaceBox | undefined}
*/
getFaceBox(detections: Array<FaceResult>, threshold: number): FaceBox | undefined {
if (this.getFaceCount(detections) !== 1) {
return;
@ -127,18 +147,24 @@ export class HumanHelper implements FaceLandmarksHelper {
left: Math.round(detections[0].boxRaw[0] * 100),
right: Math.round((detections[0].boxRaw[0] + detections[0].boxRaw[2]) * 100)
};
faceBox.width = Math.round(faceBox.right - faceBox.left);
if (this.lastValidFaceBox && threshold && Math.abs(this.lastValidFaceBox.left - faceBox.left) < threshold) {
return;
}
this.lastValidFaceBox = faceBox;
return faceBox;
}
/**
* Gets the face expression from the detections, if there is no valid detections it will return undefined.
*
* @param {Array<FaceResult>} detections - The array with the detections.
* @returns {string | undefined}
*/
getFaceExpression(detections: Array<FaceResult>): string | undefined {
if (this.getFaceCount(detections) !== 1) {
return;
@ -149,6 +175,12 @@ export class HumanHelper implements FaceLandmarksHelper {
}
}
/**
* Gets the face count from the detections, which is the number of detections.
*
* @param {Array<FaceResult>} detections - The array with the detections.
* @returns {number}
*/
getFaceCount(detections: Array<FaceResult> | undefined): number {
if (detections) {
return detections.length;
@ -157,44 +189,56 @@ export class HumanHelper implements FaceLandmarksHelper {
return 0;
}
/**
* Gets the detections from the image captured from the track.
*
* @param {ImageBitmap | ImageData} image - The image captured from the track,
* if OffscreenCanvas available it will be ImageBitmap, otherwise it will be ImageData.
* @returns {Promise<Array<FaceResult>>}
*/
async getDetections(image: ImageBitmap | ImageData): Promise<Array<FaceResult>> {
if (!this.human || !this.faceDetectionTypes.length) {
return [];
}
this.human.tf.engine().startScope();
const imageTensor = this.human.tf.browser.fromPixels(image);
const { face: detections } = await this.human.detect(imageTensor, this.config);
this.human.tf.engine().endScope();
return detections.filter(detection => detection.score > FACE_DETECTION_SCORE_THRESHOLD);
}
return detections.filter(detection => detection.score > FACE_DETECTION_SCORE_THRESHOLD);
}
/**
* Gathers together all the data from the detections, it's the function that will be called in the worker.
*
* @param {DetectInput} input - The input for the detections.
* @returns {Promise<DetectOutput>}
*/
public async detect({ image, threshold } : DetectInput): Promise<DetectOutput> {
let detections;
let faceExpression;
let faceBox;
this.detectionInProgress = true;
detections = await this.getDetections(image);
const detections = await this.getDetections(image);
if (this.faceDetectionTypes.includes(DETECTION_TYPES.FACE_EXPRESSIONS)) {
faceExpression = this.getFaceExpression(detections);
}
if (this.faceDetectionTypes.includes(DETECTION_TYPES.FACE_BOX)) {
//if more than one face is detected the face centering will be disabled.
if (this.getFaceCount(detections) > 1 ) {
// if more than one face is detected the face centering will be disabled.
if (this.getFaceCount(detections) > 1) {
this.faceDetectionTypes.splice(this.faceDetectionTypes.indexOf(DETECTION_TYPES.FACE_BOX), 1);
//face-box for re-centering
// face-box for re-centering
faceBox = {
left: 0,
right: 100,
width: 100,
width: 100
};
} else {
faceBox = this.getFaceBox(detections, threshold);
@ -204,14 +248,19 @@ export class HumanHelper implements FaceLandmarksHelper {
this.detectionInProgress = false;
return {
faceExpression,
return {
faceExpression,
faceBox,
faceCount: this.getFaceCount(detections)
}
};
}
/**
* Returns the detection state.
*
* @returns {boolean}
*/
public getDetectionInProgress(): boolean {
return this.detectionInProgress;
}
}
}

View File

@ -59,4 +59,4 @@ export const DETECTION_TYPES = {
/**
* Threshold for detection score of face.
*/
export const FACE_DETECTION_SCORE_THRESHOLD = 0.6;
export const FACE_DETECTION_SCORE_THRESHOLD = 0.6;

View File

@ -1,5 +1,5 @@
import { FaceLandmarksHelper, HumanHelper } from './FaceLandmarksHelper';
import { DETECT_FACE, INIT_WORKER } from './constants';
import { FaceLandmarksHelper, HumanHelper }from './FaceLandmarksHelper';
let helper: FaceLandmarksHelper;

View File

@ -13,14 +13,14 @@ import styles from './styles';
const GifsMenuFooter = (): JSX.Element => {
const { t } = useTranslation();
return(
<View style={ styles.credit }>
return (
<View style = { styles.credit }>
<Text
style={ styles.creditText }>{ t('poweredby') }</Text>
style = { styles.creditText }>{ t('poweredby') }</Text>
<Image
source = { require('../../../../../images/GIPHY_logo.png') } />
</View>
)
);
};
export default GifsMenuFooter;

View File

@ -5,7 +5,6 @@ import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { Chat, ChatAndPolls } from '../../../../../chat';
import Conference from '../../../../../conference/components/native/Conference';
import CarMode from '../../../../../conference/components/native/carmode/CarMode';
import { getDisablePolls } from '../../../../../conference/functions';

View File

@ -16,7 +16,7 @@ export const rootNavigationRef = React.createRef();
* @param {Object} params - Params to pass to the destination route.
* @returns {Function}
*/
export function navigateRoot(name: string, params: Object) {
export function navigateRoot(name: string, params?: Object) {
return rootNavigationRef.current?.navigate(name, params);
}

View File

@ -1,3 +1,4 @@
/* eslint-disable import/order */
import { makeStyles } from '@material-ui/core';
import React, { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
@ -5,16 +6,22 @@ import { useSelector } from 'react-redux';
// @ts-ignore
import { Avatar } from '../../../../../base/avatar';
// @ts-ignore
import { ContextMenu, ContextMenuItemGroup } from '../../../../../base/components';
// @ts-ignore
import { isLocalParticipantModerator } from '../../../../../base/participants';
// @ts-ignore
import { getBreakoutRooms } from '../../../../../breakout-rooms/functions';
// @ts-ignore
import { showOverflowDrawer } from '../../../../../toolbox/functions.web';
// @ts-ignore
import SendToRoomButton from '../../../../../video-menu/components/web/SendToRoomButton';
// @ts-ignore
import { AVATAR_SIZE } from '../../../../constants';
@ -74,7 +81,7 @@ export const RoomParticipantContextMenu = ({
const styles = useStyles();
const { t } = useTranslation();
const isLocalModerator = useSelector(isLocalParticipantModerator);
const lowerMenu = useCallback(() => onSelect(true), [onSelect]);
const lowerMenu = useCallback(() => onSelect(true), [ onSelect ]);
const rooms: Object = useSelector(getBreakoutRooms);
const overflowDrawer = useSelector(showOverflowDrawer);
@ -88,7 +95,8 @@ export const RoomParticipantContextMenu = ({
}
return null;
}).filter(Boolean), [ entity, rooms ]);
})
.filter(Boolean), [ entity, rooms ]);
return isLocalModerator && (
<ContextMenu

View File

@ -1,6 +1,6 @@
import React, { useCallback } from 'react';
import { View } from 'react-native';
import { useDispatch, useSelector} from "react-redux";
import { useDispatch, useSelector } from 'react-redux';
import { openDialog, openSheet } from '../../../base/dialog';
import { IconHorizontalPoints } from '../../../base/icons';
@ -28,7 +28,7 @@ const ParticipantsPaneFooter = (): JSX.Element => {
const showMoreActions = useSelector(isMoreActionsVisible);
const showMuteAll = useSelector(isMuteAllVisible);
return(
return (
<View style = { styles.participantsPaneFooter }>
{
showMuteAll && (
@ -49,7 +49,7 @@ const ParticipantsPaneFooter = (): JSX.Element => {
)
}
</View>
)
);
};
export default ParticipantsPaneFooter;

View File

@ -1,16 +1,18 @@
/* eslint-disable import/order */
import React, { PureComponent } from 'react';
import { Text, View } from 'react-native';
// @ts-ignore
import { Avatar } from '../../../base/avatar';
// @ts-ignore
import { BottomSheet, hideSheet } from '../../../base/dialog';
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
import { translate } from '../../../base/i18n';
import { connect } from '../../../base/redux';
import { getBreakoutRooms } from '../../../breakout-rooms/functions';
import SendToBreakoutRoom from '../../../video-menu/components/native/SendToBreakoutRoom';
import styles from '../../../video-menu/components/native/styles';
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
/**
* Size of the rendered avatar in the menu.

View File

@ -1,11 +1,12 @@
// @ts-ignore
import { IStore } from '../app/types';
/* eslint-disable import/order */
// @ts-ignore
import { MiddlewareRegistry } from '../base/redux';
import { PARTICIPANTS_PANE_CLOSE, PARTICIPANTS_PANE_OPEN } from './actionTypes';
declare var APP: any;
declare let APP: any;
/**
* Middleware which intercepts participants pane actions.
@ -13,18 +14,19 @@ declare var APP: any;
* @param {IStore} store - The redux store.
* @returns {Function}
*/
MiddlewareRegistry.register((store: IStore) => (next:Function) => (action:any) => {
switch(action.type) {
case PARTICIPANTS_PANE_OPEN:
if (typeof APP !== 'undefined') {
APP.API.notifyParticipantsPaneToggled(true);
}
break;
case PARTICIPANTS_PANE_CLOSE:
if (typeof APP !== 'undefined') {
APP.API.notifyParticipantsPaneToggled(false);
}
break;
MiddlewareRegistry.register(() => (next:Function) => (action:any) => {
switch (action.type) {
case PARTICIPANTS_PANE_OPEN:
if (typeof APP !== 'undefined') {
APP.API.notifyParticipantsPaneToggled(true);
}
break;
case PARTICIPANTS_PANE_CLOSE:
if (typeof APP !== 'undefined') {
APP.API.notifyParticipantsPaneToggled(false);
}
break;
}
return next(action);
});

View File

@ -4,7 +4,10 @@ import {
BackHandler,
View,
TextInput,
Platform
Platform,
StyleProp,
TextStyle,
ViewStyle
} from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
@ -29,6 +32,7 @@ import AudioMuteButton from '../../toolbox/components/AudioMuteButton';
import VideoMuteButton from '../../toolbox/components/VideoMuteButton';
import { isDisplayNameRequired } from '../functions';
import { PrejoinProps } from '../types';
import styles from './styles';
@ -92,7 +96,7 @@ const Prejoin: React.FC<PrejoinProps> = ({ navigation }: PrejoinProps) => {
return () => BackHandler.removeEventListener('hardwareBackPress', goBack);
}, [ ]);
}, []);
useLayoutEffect(() => {
navigation.setOptions({
@ -127,12 +131,12 @@ const Prejoin: React.FC<PrejoinProps> = ({ navigation }: PrejoinProps) => {
<LargeVideo />
</View>
<View style = { contentContainerStyles }>
<View style = { styles.formWrapper }>
<View style = { styles.formWrapper as StyleProp<ViewStyle> }>
<TextInput
onChangeText = { onChangeDisplayName }
placeholder = { t('dialog.enterDisplayName') }
placeholderTextColor = { BaseTheme.palette.text03 }
style = { styles.field }
style = { styles.field as StyleProp<TextStyle> }
value = { displayName } />
<Button
accessibilityLabel = 'prejoin.joinMeeting'

View File

@ -1,3 +1,3 @@
interface PrejoinProps {
navigation: Object;
export interface PrejoinProps {
navigation: any;
}

View File

@ -13,6 +13,7 @@ import { ReactionsAction } from './reducer';
* Sets the reaction queue.
*
* @param {Array} queue - The new queue.
* @returns {ReactionsAction}
*/
export function setReactionQueue(queue: Array<ReactionEmojiProps>): ReactionsAction {
return {
@ -26,6 +27,7 @@ export function setReactionQueue(queue: Array<ReactionEmojiProps>): ReactionsAct
* Removes a reaction from the queue.
*
* @param {string} uid - Id of the reaction to be removed.
* @returns {Function}
*/
export function removeReaction(uid: string): Function {
return (dispatch: Function, getState: Function) => {
@ -38,6 +40,8 @@ export function removeReaction(uid: string): Function {
/**
* Sends the reactions buffer to everyone in the conference.
*
* @returns {ReactionsAction}
*/
export function sendReactions(): ReactionsAction {
return {
@ -49,6 +53,7 @@ export function sendReactions(): ReactionsAction {
* Adds a reaction to the local buffer.
*
* @param {string} reaction - The reaction to be added.
* @returns {ReactionsAction}
*/
export function addReactionToBuffer(reaction: string): ReactionsAction {
return {
@ -59,6 +64,8 @@ export function addReactionToBuffer(reaction: string): ReactionsAction {
/**
* Clears the reaction buffer.
*
* @returns {ReactionsAction}
*/
export function flushReactionBuffer(): ReactionsAction {
return {
@ -70,6 +77,7 @@ export function flushReactionBuffer(): ReactionsAction {
* Adds a reaction message to the chat.
*
* @param {string} message - The reaction message.
* @returns {ReactionsAction}
*/
export function addReactionsToChat(message: string): ReactionsAction {
return {
@ -82,6 +90,7 @@ export function addReactionsToChat(message: string): ReactionsAction {
* Adds reactions to the animation queue.
*
* @param {Array} reactions - The reactions to be animated.
* @returns {ReactionsAction}
*/
export function pushReactions(reactions: Array<string>): ReactionsAction {
return {

View File

@ -6,6 +6,8 @@ import { ReactionsAction } from './reducer';
/**
* Toggles the visibility of the reactions menu.
*
* @returns {void}
*/
export function toggleReactionsMenuVisibility(): ReactionsAction {
return {
@ -15,6 +17,8 @@ export function toggleReactionsMenuVisibility(): ReactionsAction {
/**
* Displays the disable sounds notification.
*
* @returns {void}
*/
export function displayReactionSoundsNotification(): ReactionsAction {
return {

View File

@ -1,10 +1,13 @@
/* eslint-disable import/order */
import React, { Component } from 'react';
// @ts-ignore
import { IStore } from '../../../app/types';
// @ts-ignore
import { connect } from '../../../base/redux';
import { removeReaction } from '../../actions.any';
import { REACTIONS } from '../../constants';
import { IStore } from '../../../app/types';
type Props = {
@ -86,8 +89,10 @@ class ReactionEmoji extends Component<Props, State> {
}
}
const mapDispatchToProps = (dispatch: IStore['dispatch']) => ({
reactionRemove: (uid: string) => dispatch(removeReaction(uid))
});
const mapDispatchToProps = (dispatch: IStore['dispatch']) => {
return {
reactionRemove: (uid: string) => dispatch(removeReaction(uid))
};
};
export default connect(null, mapDispatchToProps)(ReactionEmoji);
export default connect(undefined, mapDispatchToProps)(ReactionEmoji);

View File

@ -1,3 +1,4 @@
/* eslint-disable import/order */
import { withStyles } from '@material-ui/styles';
import clsx from 'clsx';
import React, { Component } from 'react';
@ -7,21 +8,29 @@ import {
createReactionMenuEvent,
createToolbarEvent,
sendAnalytics
// @ts-ignore
} from '../../../analytics';
import { IStore } from '../../../app/types';
// @ts-ignore
import { isMobileBrowser } from '../../../base/environment/utils';
// @ts-ignore
import { translate } from '../../../base/i18n';
// @ts-ignore
import { getLocalParticipant, hasRaisedHand, raiseHand } from '../../../base/participants';
// @ts-ignore
import { connect } from '../../../base/redux';
// @ts-ignore
import { GifsMenu, GifsMenuButton } from '../../../gifs/components';
// @ts-ignore
import { isGifEnabled, isGifsMenuOpen } from '../../../gifs/functions';
// @ts-ignore
import { dockToolbox } from '../../../toolbox/actions.web';
import { addReactionToBuffer } from '../../actions.any';
@ -88,8 +97,6 @@ type Props = {
t: Function
};
declare var APP: Object;
const styles = (theme: any) => {
return {
overflow: {
@ -201,6 +208,7 @@ class ReactionsMenu extends Component<Props> {
accessibilityLabel = { t(`toolbar.accessibilityLabel.${key}`) }
icon = { REACTIONS[key].emoji }
key = { key }
// eslint-disable-next-line react/jsx-no-bind
onClick = { doSendReaction }
toggled = { false }
tooltip = { `${t(`toolbar.${key}`)} (${modifierKey} + ${REACTIONS[key].shortcutChar})` } />);
@ -274,6 +282,7 @@ function mapDispatchToProps(dispatch: IStore['dispatch']) {
...bindActionCreators(
{
_dockToolbox: dockToolbox
// @ts-ignore
}, dispatch)
};
@ -282,5 +291,6 @@ function mapDispatchToProps(dispatch: IStore['dispatch']) {
export default translate(connect(
mapStateToProps,
mapDispatchToProps
// @ts-ignore
)(withStyles(styles)(ReactionsMenu)));

View File

@ -1,17 +1,21 @@
// @flow
/* eslint-disable import/order */
import React, { useCallback } from 'react';
// @ts-ignore
import { useSelector } from 'react-redux';
// @ts-ignore
import { isMobileBrowser } from '../../../base/environment/utils';
// @ts-ignore
import { translate } from '../../../base/i18n';
// @ts-ignore
import { IconArrowUp } from '../../../base/icons';
// @ts-ignore
import { connect } from '../../../base/redux';
// @ts-ignore
import ToolboxButtonWithIconPopup from '../../../base/toolbox/components/web/ToolboxButtonWithIconPopup';
import { toggleReactionsMenuVisibility } from '../../actions.web';
@ -73,9 +77,6 @@ type Props = {
t: Function
};
declare var APP: Object;
/**
* Button used for the reactions menu.
*

View File

@ -1,9 +1,12 @@
/* eslint-disable import/order */
import { v4 as uuidv4 } from 'uuid';
// @ts-ignore
import { getFeatureFlag, REACTIONS_ENABLED } from '../base/flags';
// @ts-ignore
import { getLocalParticipant } from '../base/participants';
// @ts-ignore
import { extractFqnFromPath } from '../dynamic-branding/functions.any';
@ -14,6 +17,7 @@ import logger from './logger';
* Returns the queue of reactions.
*
* @param {Object} state - The state of the application.
* @returns {Array}
*/
export function getReactionsQueue(state: any): Array<ReactionEmojiProps> {
return state['features/reactions'].queue;
@ -23,6 +27,7 @@ export function getReactionsQueue(state: any): Array<ReactionEmojiProps> {
* Returns chat message from reactions buffer.
*
* @param {Array} buffer - The reactions buffer.
* @returns {string}
*/
export function getReactionMessageFromBuffer(buffer: Array<string>): string {
return buffer.map<string>(reaction => REACTIONS[reaction].message).reduce((acc, val) => `${acc}${val}`);
@ -32,6 +37,7 @@ export function getReactionMessageFromBuffer(buffer: Array<string>): string {
* Returns reactions array with uid.
*
* @param {Array} buffer - The reactions buffer.
* @returns {Array}
*/
export function getReactionsWithId(buffer: Array<string>): Array<ReactionEmojiProps> {
return buffer.map<ReactionEmojiProps>(reaction => {
@ -47,6 +53,7 @@ export function getReactionsWithId(buffer: Array<string>): Array<ReactionEmojiPr
*
* @param {Object} state - The redux state object.
* @param {Array} reactions - Reactions array to be sent.
* @returns {void}
*/
export async function sendReactionsWebhook(state: any, reactions: Array<string>) {
const { webhookProxyUrl: url } = state['features/base/config'];
@ -93,6 +100,7 @@ export async function sendReactionsWebhook(state: any, reactions: Array<string>)
* Returns unique reactions from the reactions buffer.
*
* @param {Array} reactions - The reactions buffer.
* @returns {Array}
*/
function getUniqueReactions(reactions: Array<string>): Array<string> {
return [ ...new Set(reactions) ];
@ -103,6 +111,7 @@ function getUniqueReactions(reactions: Array<string>): Array<string> {
*
* @param {Array} reactions - Array of reactions.
* @param {string} reaction - Reaction to get frequency for.
* @returns {number}
*/
function getReactionFrequency(reactions: Array<string>, reaction: string): number {
return reactions.filter(r => r === reaction).length;
@ -112,6 +121,7 @@ function getReactionFrequency(reactions: Array<string>, reaction: string): numbe
* Returns the threshold number for a given frequency.
*
* @param {number} frequency - Frequency of reaction.
* @returns {number}
*/
function getSoundThresholdByFrequency(frequency: number): number {
for (const i of SOUNDS_THRESHOLDS) {
@ -127,6 +137,7 @@ function getSoundThresholdByFrequency(frequency: number): number {
* Returns unique reactions with threshold.
*
* @param {Array} reactions - The reactions buffer.
* @returns {Array}
*/
export function getReactionsSoundsThresholds(reactions: Array<string>): Array<ReactionThreshold> {
const unique = getUniqueReactions(reactions);
@ -143,6 +154,7 @@ export function getReactionsSoundsThresholds(reactions: Array<string>): Array<Re
* Whether or not the reactions are enabled.
*
* @param {Object} state - The Redux state object.
* @returns {boolean}
*/
export function isReactionsEnabled(state: any): boolean {
const { disableReactions } = state['features/base/config'];

View File

@ -2,6 +2,7 @@
* Returns the visibility state of the reactions menu.
*
* @param {Object} state - The state of the application.
* @returns {boolean}
*/
export function getReactionsMenuVisibility(state: any): boolean {
return state['features/reactions'].visible;

View File

@ -1,30 +1,41 @@
/* eslint-disable import/order */
// @ts-ignore
import { batch } from 'react-redux';
// @ts-ignore
import { createReactionSoundsDisabledEvent, sendAnalytics } from '../analytics';
// @ts-ignore
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
import { IStore } from '../app/types';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app/actionTypes';
import {
CONFERENCE_JOIN_IN_PROGRESS,
SET_START_REACTIONS_MUTED,
setStartReactionsMuted
// @ts-ignore
} from '../base/conference';
import {
getParticipantById,
getParticipantCount,
isLocalParticipantModerator
// @ts-ignore
} from '../base/participants';
// @ts-ignore
import { MiddlewareRegistry } from '../base/redux';
import { SETTINGS_UPDATED } from '../base/settings/actionTypes';
// @ts-ignore
import { updateSettings } from '../base/settings/actions';
// @ts-ignore
import { playSound, registerSound, unregisterSound } from '../base/sounds';
// @ts-ignore
import { getDisabledSounds } from '../base/sounds/functions.any';
// @ts-ignore
import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications';
@ -60,7 +71,6 @@ import {
} from './functions.any';
import logger from './logger';
import { RAISE_HAND_SOUND_FILE } from './sounds';
import { IStore } from '../app/types';
/**
* Middleware which intercepts Reactions actions to handle changes to the
@ -241,6 +251,7 @@ MiddlewareRegistry.register((store: IStore) => (next: Function) => (action:any)
* @param {Object} store - The redux store. Used to calculate and dispatch
* updates.
* @private
* @returns {void}
*/
function _onMuteReactionsCommand(attributes: MuteCommandAttributes = {}, id: string, store: IStore) {
const state = store.getState();
@ -267,6 +278,7 @@ function _onMuteReactionsCommand(attributes: MuteCommandAttributes = {}, id: str
}
const oldState = Boolean(state['features/base/conference'].startReactionsMuted);
// @ts-ignore
const newState = attributes.startReactionsMuted === 'true';

View File

@ -10,20 +10,24 @@ import {
} from './actionTypes';
import { ReactionEmojiProps } from './constants';
interface State {
interface IReactionsState {
/**
* The indicator that determines whether the reactions menu is visible.
*/
visible: boolean,
/**
* An array that contains the reactions buffer to be sent.
*/
buffer: Array<string>,
/**
* A number, non-zero value which identifies the timer created by a call
* to setTimeout().
*/
timeoutID: number|null,
/**
* The array of reactions to animate.
*/
@ -35,19 +39,23 @@ interface State {
notificationDisplayed: boolean
}
export interface ReactionsAction extends Partial<State> {
export interface ReactionsAction extends Partial<IReactionsState> {
/**
* The message to be added to the chat.
*/
message?: string,
/**
* The reaction to be added to buffer.
*/
reaction?: string,
/**
* The reactions to be added to the animation queue.
*/
reactions?: Array<string>,
/**
* The action type.
*/
@ -58,8 +66,9 @@ export interface ReactionsAction extends Partial<State> {
* Returns initial state for reactions' part of Redux store.
*
* @private
* @returns {IReactionsState}
*/
function _getInitialState(): State {
function _getInitialState(): IReactionsState {
return {
visible: false,
buffer: [],
@ -71,7 +80,7 @@ function _getInitialState(): State {
ReducerRegistry.register(
'features/reactions',
(state: State = _getInitialState(), action: ReactionsAction) => {
(state: IReactionsState = _getInitialState(), action: ReactionsAction) => {
switch (action.type) {
case TOGGLE_REACTIONS_VISIBLE:

View File

@ -1,36 +1,40 @@
interface IReduxStore {
dispatch: Function;
getState: Function;
}
import { IStore } from '../../../app/types';
interface ILocalRecordingManager {
addAudioTrackToLocalRecording: (track: MediaStreamTrack) => void;
stopLocalRecording: () => void;
startLocalRecording: (store: IReduxStore) => void;
startLocalRecording: (store: IStore) => void;
isRecordingLocally: () => boolean;
}
const LocalRecordingManager: ILocalRecordingManager = {
/**
* Adds audio track to the recording stream.
*
* @param {MediaStreamTrack} track - Track to be added,.
* @returns {void}
*/
addAudioTrackToLocalRecording(track) {
},
addAudioTrackToLocalRecording() { },
/**
* Stops local recording.
*
* @returns {void}
* */
stopLocalRecording() {
},
stopLocalRecording() { },
/**
* Starts a local recording.
*
* @param {IStore} store - The Redux store.
* @returns {void}
*/
async startLocalRecording(store) {
},
async startLocalRecording() { },
/**
* Whether or not we're currently recording locally.
*
* @returns {boolean}
*/
isRecordingLocally() {
return false;

View File

@ -1,22 +1,24 @@
/* eslint-disable import/order */
import { v4 as uuidV4 } from 'uuid';
import fixWebmDuration from 'webm-duration-fix';
import { IStore } from '../../../app/types';
// @ts-ignore
import { getRoomName } from '../../../base/conference';
// @ts-ignore
import { MEDIA_TYPE } from '../../../base/media';
// @ts-ignore
import { getTrackState, getLocalTrack } from '../../../base/tracks';
import { inIframe } from '../../../base/util/iframeUtils';
// @ts-ignore
import { stopLocalVideoRecording } from '../../actions.any';
declare var APP: any;
interface IReduxStore {
dispatch: Function;
getState: Function;
}
declare let APP: any;
interface SelfRecording {
on: boolean;
@ -37,7 +39,7 @@ interface ILocalRecordingManager {
getFilename: () => string;
saveRecording: (recordingData: Blob[], filename: string) => void;
stopLocalRecording: () => void;
startLocalRecording: (store: IReduxStore, onlySelf: boolean) => void;
startLocalRecording: (store: IStore, onlySelf: boolean) => void;
isRecordingLocally: () => boolean;
totalSize: number;
selfRecording: SelfRecording;
@ -48,15 +50,16 @@ const getMimeType = (): string => {
'video/mp4;codecs=h264',
'video/webm;codecs=h264',
'video/webm;codecs=vp9',
'video/webm;codecs=vp8',
'video/webm;codecs=vp8'
];
for(let type of possibleTypes) {
if(MediaRecorder.isTypeSupported(type)) {
for (const type of possibleTypes) {
if (MediaRecorder.isTypeSupported(type)) {
return type;
}
}
throw new Error("No MIME Type supported by MediaRecorder");
}
throw new Error('No MIME Type supported by MediaRecorder');
};
const VIDEO_BIT_RATE = 2500000; // 2.5Mbps in bits
@ -86,6 +89,8 @@ const LocalRecordingManager: ILocalRecordingManager = {
/**
* Initializes audio context used for mixing audio tracks.
*
* @returns {void}
*/
initializeAudioMixer() {
this.audioContext = new AudioContext();
@ -94,6 +99,9 @@ const LocalRecordingManager: ILocalRecordingManager = {
/**
* Mixes multiple audio tracks to the destination media stream.
*
* @param {MediaStream} stream - The stream to mix.
* @returns {void}
* */
mixAudioStream(stream) {
if (stream.getAudioTracks().length > 0 && this.audioDestination) {
@ -103,9 +111,12 @@ const LocalRecordingManager: ILocalRecordingManager = {
/**
* Adds audio track to the recording stream.
*
* @param {MediaStreamTrack} track - The track to be added.
* @returns {void}
*/
addAudioTrackToLocalRecording(track) {
if(this.selfRecording.on) {
if (this.selfRecording.on) {
return;
}
if (track) {
@ -117,6 +128,8 @@ const LocalRecordingManager: ILocalRecordingManager = {
/**
* Returns a filename based ono the Jitsi room name in the URL and timestamp.
*
* @returns {string}
* */
getFilename() {
const now = new Date();
@ -127,15 +140,21 @@ const LocalRecordingManager: ILocalRecordingManager = {
/**
* Saves local recording to file.
*
* @param {Array} recordingData - The recording data.
* @param {string} filename - The name of the file.
* @returns {void}
* */
async saveRecording(recordingData, filename) {
// @ts-ignore
const blob = await fixWebmDuration(new Blob(recordingData, { type: this.mediaType }));
// @ts-ignore
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
const extension = this.mediaType.slice(this.mediaType.indexOf('/') + 1, this.mediaType.indexOf(';'))
const extension = this.mediaType.slice(this.mediaType.indexOf('/') + 1, this.mediaType.indexOf(';'));
a.style.display = 'none';
a.href = url;
a.download = `${filename}.${extension}`;
@ -144,6 +163,8 @@ const LocalRecordingManager: ILocalRecordingManager = {
/**
* Stops local recording.
*
* @returns {void}
* */
stopLocalRecording() {
if (this.recorder) {
@ -157,9 +178,14 @@ const LocalRecordingManager: ILocalRecordingManager = {
/**
* Starts a local recording.
*
* @param {IStore} store - The redux store.
* @param {boolean} onlySelf - Whether to record only self streams.
* @returns {void}
*/
async startLocalRecording(store, onlySelf) {
const { dispatch, getState } = store;
// @ts-ignore
const supportsCaptureHandle = Boolean(navigator.mediaDevices.setCaptureHandleConfig) && !inIframe();
const tabId = uuidV4();
@ -170,25 +196,27 @@ const LocalRecordingManager: ILocalRecordingManager = {
let gdmStream: MediaStream = new MediaStream();
const tracks = getTrackState(getState());
if(onlySelf) {
if (onlySelf) {
let audioTrack: MediaStreamTrack | undefined = getLocalTrack(tracks, MEDIA_TYPE.AUDIO)?.jitsiTrack?.track;
let videoTrack: MediaStreamTrack | undefined = getLocalTrack(tracks, MEDIA_TYPE.VIDEO)?.jitsiTrack?.track;
if(!audioTrack) {
if (!audioTrack) {
APP.conference.muteAudio(false);
setTimeout(() => APP.conference.muteAudio(true), 100);
await new Promise((resolve) => {
await new Promise(resolve => {
setTimeout(resolve, 100);
});
}
if(videoTrack && videoTrack.readyState !== 'live') {
if (videoTrack && videoTrack.readyState !== 'live') {
videoTrack = undefined;
}
audioTrack = getLocalTrack(getTrackState(getState()), MEDIA_TYPE.AUDIO)?.jitsiTrack?.track;
if(!audioTrack && !videoTrack) {
throw new Error('NoLocalStreams')
if (!audioTrack && !videoTrack) {
throw new Error('NoLocalStreams');
}
this.selfRecording.withVideo = Boolean(videoTrack);
const localTracks = [];
audioTrack && localTracks.push(audioTrack);
videoTrack && localTracks.push(videoTrack);
this.stream = new MediaStream(localTracks);
@ -204,7 +232,8 @@ const LocalRecordingManager: ILocalRecordingManager = {
// @ts-ignore
gdmStream = await navigator.mediaDevices.getDisplayMedia({
// @ts-ignore
video: { displaySurface: 'browser', frameRate: 30 },
video: { displaySurface: 'browser',
frameRate: 30 },
audio: {
autoGainControl: false,
channelCount: 2,
@ -212,6 +241,7 @@ const LocalRecordingManager: ILocalRecordingManager = {
noiseSuppression: false
}
});
// @ts-ignore
const isBrowser = gdmStream.getVideoTracks()[0].getSettings().displaySurface === 'browser';
@ -232,7 +262,7 @@ const LocalRecordingManager: ILocalRecordingManager = {
}
});
this.stream = new MediaStream([
...(this.audioDestination?.stream.getAudioTracks() || []),
...this.audioDestination?.stream.getAudioTracks() || [],
gdmStream.getVideoTracks()[0]
]);
}
@ -251,7 +281,7 @@ const LocalRecordingManager: ILocalRecordingManager = {
}
});
if(!onlySelf) {
if (!onlySelf) {
this.recorder.addEventListener('stop', () => {
this.stream?.getTracks().forEach((track: MediaStreamTrack) => track.stop());
gdmStream?.getTracks().forEach((track: MediaStreamTrack) => track.stop());
@ -271,6 +301,8 @@ const LocalRecordingManager: ILocalRecordingManager = {
/**
* Whether or not we're currently recording locally.
*
* @returns {boolean}
*/
isRecordingLocally() {
return Boolean(this.recorder);

View File

@ -34,7 +34,7 @@ class OpenCarmodeButton extends AbstractButton<AbstractButtonProps, any, any> {
* @private
* @returns {Object}
*/
function _mapStateToProps(state: Object, ownProps: AbstractButtonProps): Object {
function _mapStateToProps(state: Object, ownProps: AbstractButtonProps): Object {
const enabled = getFeatureFlag(state, CAR_MODE_ENABLED, true);
const { visible = enabled } = ownProps;

View File

@ -22,8 +22,9 @@ const ScreenSharingButton = props => (
* Maps (parts of) the redux state to the associated props for the
* {@code ScreenSharingButton} component.
*
* @param state - The Redux state.
* @param {Object} state - The Redux state.
* @private
* @returns {Object}
*/
function _mapStateToProps(state: object): object {
return {