mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-07-21 14:37:47 +00:00
Compare commits
39 Commits
8741
...
tests-wait
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11a6e94541 | ||
|
|
e1e262fb68 | ||
|
|
b0a96b32d2 | ||
|
|
dac9b5e244 | ||
|
|
d15cfd845a | ||
|
|
91e4ac1665 | ||
|
|
fda42e5230 | ||
|
|
142d4441c1 | ||
|
|
5814c4dda7 | ||
|
|
8c1dc03363 | ||
|
|
ff6fc198f1 | ||
|
|
f1a0012fc1 | ||
|
|
85522aea25 | ||
|
|
000c370c64 | ||
|
|
a762d585b8 | ||
|
|
ded8f22363 | ||
|
|
c3e1c9d568 | ||
|
|
8901132af9 | ||
|
|
71f92f6e17 | ||
|
|
76166df81a | ||
|
|
eb2ba39289 | ||
|
|
048b089acd | ||
|
|
b774f18f80 | ||
|
|
dbe4e6a784 | ||
|
|
d2e52d2c2a | ||
|
|
b5ad984dab | ||
|
|
81ce664ad7 | ||
|
|
181ef92e1f | ||
|
|
79dbc2d1ee | ||
|
|
f56ce78b9d | ||
|
|
8269b88796 | ||
|
|
252ef4604a | ||
|
|
fc816aa149 | ||
|
|
6de18fe82d | ||
|
|
5b7e3bb2d7 | ||
|
|
bc08b38791 | ||
|
|
6613f630d7 | ||
|
|
719b6d68c8 | ||
|
|
6a62c5120f |
@@ -28,6 +28,14 @@ android {
|
||||
ndk {
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON", "-DANDROID_STL=c++_shared"
|
||||
cppFlags "-std=c++17"
|
||||
cFlags "-DANDROID_PLATFORM=android-26"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
@@ -46,8 +54,8 @@ android {
|
||||
applicationIdSuffix ".debug"
|
||||
}
|
||||
release {
|
||||
// Uncomment the following line for singing a test release build.
|
||||
//signingConfig signingConfigs.debug
|
||||
// Uncomment the following line for signing a test release build.
|
||||
// signingConfig signingConfigs.debug
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-release.pro'
|
||||
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${googleServicesEnabled}"
|
||||
@@ -102,8 +110,6 @@ dependencies {
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
// Dropbox integration
|
||||
//
|
||||
|
||||
def dropboxAppKey
|
||||
if (project.file('dropbox.key').exists()) {
|
||||
dropboxAppKey = project.file('dropbox.key').text.trim() - 'db-'
|
||||
@@ -174,7 +180,6 @@ gradle.projectsEvaluated {
|
||||
|
||||
packageTask.dependsOn(currentRunPackagerTask)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (googleServicesEnabled) {
|
||||
|
||||
@@ -6,6 +6,5 @@
|
||||
-keep public class * extends java.lang.Exception
|
||||
|
||||
# R8 missing classes - suppress warnings
|
||||
-dontwarn com.facebook.fresco.ui.common.LoggingListener
|
||||
-dontwarn com.facebook.memory.config.MemorySpikeConfig
|
||||
-dontwarn kotlinx.parcelize.Parcelize
|
||||
|
||||
5
android/app/proguard-rules.pro
vendored
5
android/app/proguard-rules.pro
vendored
@@ -96,8 +96,3 @@
|
||||
|
||||
# Rule to avoid build errors related to SVGs.
|
||||
-keep public class com.horcrux.svg.** {*;}
|
||||
|
||||
# https://github.com/facebook/fresco/issues/2638
|
||||
-keep public class com.facebook.imageutils.** {
|
||||
public *;
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import org.gradle.util.VersionNumber
|
||||
buildscript {
|
||||
ext {
|
||||
kotlinVersion = "2.0.21"
|
||||
gradlePluginVersion = "8.4.2"
|
||||
buildToolsVersion = "34.0.0"
|
||||
compileSdkVersion = 34
|
||||
gradlePluginVersion = "8.6.0"
|
||||
buildToolsVersion = "35.0.0"
|
||||
compileSdkVersion = 35
|
||||
minSdkVersion = 26
|
||||
targetSdkVersion = 34
|
||||
targetSdkVersion = 35
|
||||
supportLibVersion = "28.0.0"
|
||||
ndkVersion = "27.1.12297006"
|
||||
|
||||
@@ -75,26 +75,6 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
// Due to a dependency conflict between React Native and the Fresco library used by GiphySDK,
|
||||
// GIFs appear as static images instead of animating
|
||||
// https://github.com/Giphy/giphy-react-native-sdk/commit/7fe466ed6fddfaec95f9cbc959d33bd75ad8f900
|
||||
|
||||
configurations.configureEach {
|
||||
resolutionStrategy {
|
||||
forcedModules = [
|
||||
'com.facebook.fresco:fresco:3.2.0',
|
||||
'com.facebook.fresco:animated-gif:3.2.0',
|
||||
'com.facebook.fresco:animated-base:3.2.0',
|
||||
'com.facebook.fresco:animated-drawable:3.2.0',
|
||||
'com.facebook.fresco:animated-webp:3.2.0',
|
||||
'com.facebook.fresco:webpsupport:3.2.0',
|
||||
'com.facebook.fresco:imagepipeline-okhttp3:3.2.0',
|
||||
'com.facebook.fresco:middleware:3.2.0',
|
||||
'com.facebook.fresco:nativeimagetranscoder:3.2.0'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Third-party react-native modules which Jitsi Meet SDK for Android depends
|
||||
// on and which are not available in third-party Maven repositories need to
|
||||
// be deployed in a Maven repository of ours.
|
||||
|
||||
113
android/scripts/check_elf_alignment.sh
Executable file
113
android/scripts/check_elf_alignment.sh
Executable file
@@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
progname="${0##*/}"
|
||||
progname="${progname%.sh}"
|
||||
|
||||
# usage: check_elf_alignment.sh [path to *.so files|path to *.apk]
|
||||
|
||||
cleanup_trap() {
|
||||
if [ -n "${tmp}" -a -d "${tmp}" ]; then
|
||||
rm -rf ${tmp}
|
||||
fi
|
||||
exit $1
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Host side script to check the ELF alignment of shared libraries."
|
||||
echo "Shared libraries are reported ALIGNED when their ELF regions are"
|
||||
echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED."
|
||||
echo
|
||||
echo "Usage: ${progname} [input-path|input-APK|input-APEX]"
|
||||
}
|
||||
|
||||
if [ ${#} -ne 1 ]; then
|
||||
usage
|
||||
exit
|
||||
fi
|
||||
|
||||
case ${1} in
|
||||
--help | -h | -\?)
|
||||
usage
|
||||
exit
|
||||
;;
|
||||
|
||||
*)
|
||||
dir="${1}"
|
||||
;;
|
||||
esac
|
||||
|
||||
if ! [ -f "${dir}" -o -d "${dir}" ]; then
|
||||
echo "Invalid file: ${dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${dir}" == *.apk ]]; then
|
||||
trap 'cleanup_trap' EXIT
|
||||
|
||||
echo
|
||||
echo "Recursively analyzing $dir"
|
||||
echo
|
||||
|
||||
if { zipalign --help 2>&1 | grep -q "\-P <pagesize_kb>"; }; then
|
||||
echo "=== APK zip-alignment ==="
|
||||
zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification'
|
||||
echo "========================="
|
||||
else
|
||||
echo "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher."
|
||||
echo " You can install the latest build-tools by running the below command"
|
||||
echo " and updating your \$PATH:"
|
||||
echo
|
||||
echo " sdkmanager \"build-tools;35.0.0-rc3\""
|
||||
fi
|
||||
|
||||
dir_filename=$(basename "${dir}")
|
||||
tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX")
|
||||
unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1
|
||||
dir="${tmp}"
|
||||
fi
|
||||
|
||||
if [[ "${dir}" == *.apex ]]; then
|
||||
trap 'cleanup_trap' EXIT
|
||||
|
||||
echo
|
||||
echo "Recursively analyzing $dir"
|
||||
echo
|
||||
|
||||
dir_filename=$(basename "${dir}")
|
||||
tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX")
|
||||
deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; }
|
||||
dir="${tmp}"
|
||||
fi
|
||||
|
||||
RED="\e[31m"
|
||||
GREEN="\e[32m"
|
||||
ENDCOLOR="\e[0m"
|
||||
|
||||
unaligned_libs=()
|
||||
|
||||
echo
|
||||
echo "=== ELF alignment ==="
|
||||
|
||||
matches="$(find "${dir}" -type f)"
|
||||
IFS=$'\n'
|
||||
for match in $matches; do
|
||||
# We could recursively call this script or rewrite it to though.
|
||||
[[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}"
|
||||
[[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}"
|
||||
|
||||
[[ $(file "${match}") == *"ELF"* ]] || continue
|
||||
|
||||
res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)"
|
||||
if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then
|
||||
echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
|
||||
else
|
||||
echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"
|
||||
unaligned_libs+=("${match}")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#unaligned_libs[@]} -gt 0 ]; then
|
||||
echo -e "${RED}Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}"
|
||||
elif [ -n "${dir_filename}" ]; then
|
||||
echo -e "ELF Verification Successful"
|
||||
fi
|
||||
echo "====================="
|
||||
@@ -44,7 +44,6 @@ dependencies {
|
||||
api "com.facebook.react:react-android:$rootProject.ext.rnVersion"
|
||||
api "com.facebook.react:hermes-android:$rootProject.ext.rnVersion"
|
||||
|
||||
implementation 'com.facebook.fresco:animated-gif:2.5.0'
|
||||
implementation 'com.dropbox.core:dropbox-core-sdk:4.0.1'
|
||||
implementation 'com.jakewharton.timber:timber:5.0.1'
|
||||
implementation 'com.squareup.duktape:duktape-android:1.3.0'
|
||||
|
||||
@@ -761,7 +761,7 @@ var config = {
|
||||
// hideDominantSpeakerBadge: false,
|
||||
|
||||
// Default language for the user interface. Cannot be overwritten.
|
||||
// DEPRECATED! Use the `lang` iframe option directly instead.
|
||||
// For iframe integrations, use the `lang` option directly instead.
|
||||
// defaultLanguage: 'en',
|
||||
|
||||
// Disables profile and the edit of all fields from the profile settings (display name and email)
|
||||
@@ -791,7 +791,6 @@ var config = {
|
||||
// Configs for prejoin page.
|
||||
// prejoinConfig: {
|
||||
// // When 'true', it shows an intermediate page before joining, where the user can configure their devices.
|
||||
// // This replaces `prejoinPageEnabled`. Defaults to true.
|
||||
// enabled: true,
|
||||
// // Hides the participant name editing field in the prejoin screen.
|
||||
// // If requireDisplayName is also set as true, a name should still be provided through
|
||||
@@ -1363,7 +1362,9 @@ var config = {
|
||||
// disableGrantModerator: true,
|
||||
// // If set to 'all' the 'Private chat' button will be disabled for all participants.
|
||||
// // If set to 'allow-moderator-chat' the 'Private chat' button will be available for chats with moderators.
|
||||
// disablePrivateChat: 'all' | 'allow-moderator-chat',
|
||||
// // If set to 'disable-visitor-chat' the 'Private chat' button will be disabled for visitor-main participant
|
||||
// // conversations.
|
||||
// disablePrivateChat: 'all' | 'allow-moderator-chat' | 'disable-visitor-chat',
|
||||
// },
|
||||
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ $welcomePageHeaderContainerMargin: $welcomePageHeaderContainerMarginTop auto 0;
|
||||
$welcomePageHeaderTextTitleMarginBottom: 0;
|
||||
$welcomePageHeaderTextTitleFontSize: 2.625rem;
|
||||
$welcomePageHeaderTextTitleFontWeight: normal;
|
||||
$welcomePageHeaderTextTitleLineHeight: 50px;
|
||||
$welcomePageHeaderTextTitleLineHeight: 3.125rem;
|
||||
$welcomePageHeaderTextTitleOpacity: 1;
|
||||
|
||||
$welcomePageEnterRoomDisplay: flex;
|
||||
|
||||
16
giphy-analytics-stub.js
Normal file
16
giphy-analytics-stub.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// Stub replacement for @giphy/js-analytics to prevent beforeunload handlers
|
||||
// This completely disables all Giphy analytics functionality
|
||||
|
||||
export const pingback = () => {
|
||||
// Completely disabled - do nothing
|
||||
|
||||
};
|
||||
|
||||
export const mergeAttributes = (attributes, newAttributes) => {
|
||||
// Return merged attributes without any analytics calls
|
||||
return { ...attributes,
|
||||
...newAttributes };
|
||||
};
|
||||
|
||||
// Ensure no beforeunload handlers are ever registered
|
||||
export default pingback;
|
||||
@@ -64,11 +64,11 @@ PODS:
|
||||
- GoogleUtilities/UserDefaults (~> 7.7)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- fmt (11.0.2)
|
||||
- Giphy (2.2.13):
|
||||
- Giphy (2.2.16):
|
||||
- libwebp
|
||||
- giphy-react-native-sdk (3.3.1):
|
||||
- giphy-react-native-sdk (4.1.0):
|
||||
- DoubleConversion
|
||||
- Giphy (= 2.2.13)
|
||||
- Giphy (= 2.2.16)
|
||||
- glog
|
||||
- hermes-engine
|
||||
- RCT-Folly (= 2024.11.18.00)
|
||||
@@ -1382,9 +1382,9 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-netinfo (11.1.0):
|
||||
- React-Core
|
||||
- react-native-orientation-locker (1.6.0):
|
||||
- react-native-orientation-locker (1.5.0):
|
||||
- React-Core
|
||||
- react-native-pager-view (6.4.1):
|
||||
- react-native-pager-view (6.8.1):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
@@ -1407,7 +1407,7 @@ PODS:
|
||||
- Yoga
|
||||
- react-native-performance (5.1.2):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (5.4.0):
|
||||
- react-native-safe-area-context (5.5.2):
|
||||
- React-Core
|
||||
- react-native-slider (4.5.6):
|
||||
- DoubleConversion
|
||||
@@ -1794,7 +1794,7 @@ PODS:
|
||||
- React-Core
|
||||
- RNDefaultPreference (1.4.4):
|
||||
- React-Core
|
||||
- RNDeviceInfo (10.9.0):
|
||||
- RNDeviceInfo (12.1.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.24.0):
|
||||
- DoubleConversion
|
||||
@@ -2201,8 +2201,8 @@ SPEC CHECKSUMS:
|
||||
FirebaseCrashlytics: feb07e4e9187be3c23c6a846cce4824e5ce2dd0b
|
||||
FirebaseInstallations: 40bd9054049b2eae9a2c38ef1c3dd213df3605cd
|
||||
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
|
||||
Giphy: a11dd02b51ac2ec37b881de1717ebf2cc8e9df62
|
||||
giphy-react-native-sdk: 678a115ea5a47a43d39d1b61703e0d08b1e48917
|
||||
Giphy: 55914215541027873875757f350530e6d8986fba
|
||||
giphy-react-native-sdk: 733177b2537b527cfa55979c396cc1f2046eb457
|
||||
glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8
|
||||
GoogleAppMeasurement: 4c19f031220c72464d460c9daa1fb5d1acce958e
|
||||
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
|
||||
@@ -2249,10 +2249,10 @@ SPEC CHECKSUMS:
|
||||
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
|
||||
react-native-keep-awake: 03b74eebe4f2bb5e8478fc8f420651a92463b6f8
|
||||
react-native-netinfo: 5364263f903da576bdef9c84a76fe243ab06812c
|
||||
react-native-orientation-locker: ee8bb2177365ca74f51dc1e11218fe544634d523
|
||||
react-native-pager-view: 68e8a65a607a6f91a1e25865002192c3c4f53fcf
|
||||
react-native-orientation-locker: dbd3f6ddbe9e62389cb0807dc2af63f6c36dec36
|
||||
react-native-pager-view: 11662c698c8f11d39e05891316d2a144fa00adc4
|
||||
react-native-performance: 125a96c145e29918b55b45ce25cbba54f1e24dcd
|
||||
react-native-safe-area-context: 9d72abf6d8473da73033b597090a80b709c0b2f1
|
||||
react-native-safe-area-context: 0f7bf11598f9a61b7ceac8dc3f59ef98697e99e1
|
||||
react-native-slider: 1205801a8d29b28cacc14eef08cb120015cdafcb
|
||||
react-native-video: eb861d67a71dfef1bbf6086a811af5f338b13781
|
||||
react-native-webrtc: 2261a482150195092246fe70b3aff976f2e11ec5
|
||||
@@ -2290,7 +2290,7 @@ SPEC CHECKSUMS:
|
||||
RNCAsyncStorage: aa75595c1aefa18f868452091fa0c411a516ce11
|
||||
RNCClipboard: 7c3e3b5f71d84ef61690ad377b6c50cf27864ff5
|
||||
RNDefaultPreference: ee13d69e6693d193cd223d10e15e5b3c012d31ba
|
||||
RNDeviceInfo: 8af23685571b7867d8dc15fb89e7fb5fa8607e1e
|
||||
RNDeviceInfo: 723e97dd98af9b7913477e7a40252c15517c258c
|
||||
RNGestureHandler: 9f3109e11ed88fe5bed280bf7762b25e4c52f396
|
||||
RNGoogleSignin: 30e1aee80140dc0706cd78a4951c411376c88329
|
||||
RNScreens: 9ef996b6041d0960a4794a845f7d0808b171b4ef
|
||||
|
||||
@@ -30,6 +30,14 @@
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>85F4.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
}
|
||||
},
|
||||
"chat": {
|
||||
"disabled": "Tērzēšanas ziņojumu sūtīšana ir atspējota.",
|
||||
"enter": "Ienākt istabā",
|
||||
"error": "Kļūda: Jūsu ziņa netika nosūtīta. Cēlonis: {{error}}",
|
||||
"fieldPlaceHolder": "Rakstiet ziņu šeit",
|
||||
@@ -124,7 +125,8 @@
|
||||
"title": "Ierakstiet vārdu, lai izmantotu tērzēšanā",
|
||||
"titleWithCC": "Ievadiet segvārdu, lai izmantotu tērzēšanā un slēptos subtitros",
|
||||
"titleWithPolls": "Ierakstiet segvārdu, lai izmantotu tērzēšanā un aptaujās",
|
||||
"titleWithPollsAndCC": "Ievadiet segvārdu, lai izmantotu tērzēšanā, aptaujās un slēptos subtitros"
|
||||
"titleWithPollsAndCC": "Ievadiet segvārdu, lai izmantotu tērzēšanā, aptaujās un slēptos subtitros",
|
||||
"titleWithPollsAndCCAndFileSharing": "Ievadiet segvārdu, lai izmantotu tērzēšanā, aptaujās, slēptos subtitros un failos"
|
||||
},
|
||||
"noMessagesMessage": "Sapulcē pagaidām nav nevienas ziņas. Uzsāciet saraksti!",
|
||||
"privateNotice": "Privāta ziņa adresātam {{recipient}}",
|
||||
@@ -134,12 +136,14 @@
|
||||
"tabs": {
|
||||
"chat": "Tērzēšana",
|
||||
"closedCaptions": "Slēptie subtitri",
|
||||
"fileSharing": "Faili",
|
||||
"polls": "Aptaujas"
|
||||
},
|
||||
"title": "Tērzēšana",
|
||||
"titleWithCC": "Tērzēšana un slēptie subtitri",
|
||||
"titleWithCC": "Tērzēšana un Slēptie subtitri",
|
||||
"titleWithFeatures": "Tērzēšana un",
|
||||
"titleWithFileSharing": "Faili",
|
||||
"titleWithPolls": "Tērzēšana un Aptaujas",
|
||||
"titleWithPollsAndCC": "Tērzēšana, Aptaujas un Slēptie subtitri",
|
||||
"you": "jūs"
|
||||
},
|
||||
"chromeExtensionBanner": {
|
||||
@@ -296,6 +300,12 @@
|
||||
"alreadySharedVideoTitle": "Atļauts tikai viens kopīgots videoklips",
|
||||
"applicationWindow": "Lietotnes logs",
|
||||
"authenticationRequired": "Nepieciešama autentifikācija",
|
||||
"cameraCaptureDialog": {
|
||||
"description": "Uzņemt un nosūtīt attēlu, izmantojot mobilā tālruņa kameru",
|
||||
"ok": "Atvērt kameru",
|
||||
"reject": "Ne tagad",
|
||||
"title": "Uzņemt attēlu"
|
||||
},
|
||||
"cameraConstraintFailedError": "Kamera neatbilst noteiktajām prasībām.",
|
||||
"cameraNotFoundError": "Kamera nav atrasta.",
|
||||
"cameraNotSendingData": "Nevar piekļūt jūsu kamerai. Lūdzu, pārbaudiet, vai šo ierīci neizmanto cita programma, iestatījumu izvēlnē atlasiet citu ierīci vai mēģiniet atkārtoti ielādēt programmu.",
|
||||
@@ -371,22 +381,34 @@
|
||||
"micTimeoutError": "Nevarēja palaist audio avotu. Iestājās noildze!",
|
||||
"micUnknownError": "Nevar izmantot mikrofonu nezināma iemesla dēļ.",
|
||||
"moderationAudioLabel": "Atļaut dalībniekiem ieslēgt savu mikrofonu",
|
||||
"moderationDesktopLabel": "Atļaut lietotājiem, kas nav moderatori, kopīgot savu ekrānu",
|
||||
"moderationVideoLabel": "Atļaut dalībniekiem ieslēgt savu kameru",
|
||||
"muteEveryoneDialog": "Dalībnieki paši var ieslēgt savu mikrofonu.",
|
||||
"muteEveryoneDialogModerationOn": "Dalībnieki var nosūtīt pieprasījumu ieslēgt savu mikrofonu.",
|
||||
"muteEveryoneElseDialog": "Kad skaņa būs izslēgta, jūs nevarēsiet to ieslēgt atpakaļ, taču dalībnieki to varēs izdarīt paši.",
|
||||
"muteEveryoneElseTitle": "Vai izslēgt skaņu visiem, izņemot {{whom}}?",
|
||||
"muteEveryoneElsesDesktopDialog": "Kad kopīgošana būs apturēta, jūs vairs nevarēsiet to ieslēgt atpakaļ, bet viņi to varēs izdarīt jebkurā laikā.",
|
||||
"muteEveryoneElsesDesktopTitle": "Apturēt ekrāna kopīgošanu visiem, izņemot {{kam}}?",
|
||||
"muteEveryoneElsesVideoDialog": "Kad video būs izslēgts, jūs nevarēsiet to ieslēgt atpakaļ, taču dalībnieki to varēs izdarīt paši.",
|
||||
"muteEveryoneElsesVideoTitle": "Vai izslēgt video visiem, izņemot {{whom}}?",
|
||||
"muteEveryoneSelf": "jūs",
|
||||
"muteEveryoneStartMuted": "No šī brīža visi jauni dalībnieki pieslēdzas ar izslēgt skaņu",
|
||||
"muteEveryoneTitle": "Vai izslēgt skaņu visiem?",
|
||||
"muteEveryonesDesktopDialog": "Dalībnieki var kopīgot savu ekrānu jebkurā laikā.",
|
||||
"muteEveryonesDesktopDialogModerationOn": "Dalībnieki jebkurā laikā var nosūtīt pieprasījumu kopīgot savu ekrānu.",
|
||||
"muteEveryonesDesktopTitle": "Vai pārtraukt ekrāna kopīgošanu visiem?",
|
||||
"muteEveryonesVideoDialog": "Dalībnieki var ieslēgt savu video.",
|
||||
"muteEveryonesVideoDialogModerationOn": "Dalībnieki var nosūtīt pieprasījumu ieslēgt viņu video.",
|
||||
"muteEveryonesVideoDialogOk": "Atspējot",
|
||||
"muteEveryonesVideoTitle": "Vai apturēt ikviena video?",
|
||||
"muteParticipantBody": "Jūs nevariet viņiem ieslēgt skaņu, bet viņi paši to var izdarīt jebkurā laikā.",
|
||||
"muteParticipantButton": "Izslēgt skaņu",
|
||||
"muteParticipantsDesktopBody": "Jūs nevarēsiet sākt viņu ekrāna kopīgošanu, bet viņi to varēs izdarīt jebkurā laikā.",
|
||||
"muteParticipantsDesktopBodyModerationOn": "Jūs nevarēsiet sākt viņu ekrāna kopīgošanu, un arī viņi to nevarēs izdarīt.",
|
||||
"muteParticipantsDesktopButton": "Pārtraukt ekrāna kopīgošanu",
|
||||
"muteParticipantsDesktopDialog": "Vai tiešām vēlaties izslēgt šī dalībnieka ekrāna kopīgošanu? Jūs vairs nevarēsiet ieslēgt to atpakaļ, bet viņš to varēs izdarīt jebkurā laikā.",
|
||||
"muteParticipantsDesktopDialogModerationOn": "Vai tiešām vēlaties izslēgt šī dalībnieka ekrāna kopīgošanu? Jūs vairs nevarēsiet ieslēgt to atpakaļ, un arī viņš to nevarēs izdarīt.",
|
||||
"muteParticipantsDesktopTitle": "Atspējot ekrāna kopīgošanu šim dalībniekam?",
|
||||
"muteParticipantsVideoBody": "Jūs nevarēsiet kameru ieslēgt atpakaļ, taču viņi paši to varēs izdarīt jebkurā laikā.",
|
||||
"muteParticipantsVideoBodyModerationOn": "Ne Jūs, ne dalībnieki nevarēsiet ieslēgt kameru atpakaļ.",
|
||||
"muteParticipantsVideoButton": "Pārtraukt video",
|
||||
@@ -539,6 +561,19 @@
|
||||
"veryBad": "Ļoti Slikta",
|
||||
"veryGood": "Ļoti Laba"
|
||||
},
|
||||
"fileSharing": {
|
||||
"downloadFailedDescription": "Lūdzu, mēģiniet vēlreiz.",
|
||||
"downloadFailedTitle": "Lejuplādes kļūda",
|
||||
"downloadFile": "Lejuplādēt",
|
||||
"dragAndDrop": "Velciet un palaidiet failus šeit, vai jebkurā ekrāna vietā",
|
||||
"fileAlreadyUploaded": "Fails jau ir augšupielādēts šajā sanāksmē.",
|
||||
"fileTooLargeDescription": "Lūdzu, pārliecinieties, vai faila lielums nepārsniedz {{ maxFileSize }}.",
|
||||
"fileTooLargeTitle": "Izvēlētais fails ir pārāk liels",
|
||||
"removeFile": "Noņemt",
|
||||
"uploadFailedDescription": "Lūdzu, mēģiniet vēlreiz.",
|
||||
"uploadFailedTitle": "Augšuplādes kļūda",
|
||||
"uploadFile": "Kopīgot failu"
|
||||
},
|
||||
"filmstrip": {
|
||||
"accessibilityLabel": {
|
||||
"heading": "Video sīktēli"
|
||||
@@ -750,8 +785,9 @@
|
||||
"me": "es",
|
||||
"notify": {
|
||||
"OldElectronAPPTitle": "Drošības ievainojamība!",
|
||||
"allowAll": "Atļaut visu",
|
||||
"allowAudio": "Atļaut audio",
|
||||
"allowBoth": "Abus",
|
||||
"allowDesktop": "Atļaut ekrāna kopīgošanu",
|
||||
"allowVideo": "Atļaut video",
|
||||
"allowedUnmute": "Varat ieslēgt mikrofona skaņu, ieslēgt kameru vai kopīgot ekrānu.",
|
||||
"audioUnmuteBlockedDescription": "Mikrofona ieslēgšanas darbība ir īslaicīgi bloķēta sistēmas ierobežojumu dēļ.",
|
||||
@@ -765,6 +801,7 @@
|
||||
"dataChannelClosedDescription": "Savienojuma kanāls nedarbojas, tāpēc video kvalitāte var būt ierobežota līdz zemākajam iestatījumam.",
|
||||
"dataChannelClosedDescriptionWithAudio": "Savienojuma kanāls nedarbojas, tāpēc var rasties audio un video traucējumi.",
|
||||
"dataChannelClosedWithAudio": "Audio un video kvalitāte var būt traucēta",
|
||||
"desktopMutedRemotelyTitle": "",
|
||||
"disabledIframe": "Iegulšana ir paredzēta tikai demonstrācijas nolūkiem, tāpēc šis zvans tiks atvienots pēc {{timeout}} minūtēm.",
|
||||
"disabledIframeSecondaryNative": "Domēna {{domain}} iegulšana ir paredzēta tikai demonstrācijas nolūkiem, tāpēc šis zvans tiks pārtraukts pēc {{timeout}} minūtēm.",
|
||||
"disabledIframeSecondaryWeb": "Domēna {{domain}} iegulšana ir paredzēta tikai demonstrācijas nolūkiem, tāpēc šis zvans tiks pārtraukts pēc {{timeout}} minūtēm. Lūdzu, produkcijas videi izmantojiet <a href='{{jaasDomain}}' rel='noopener noreferrer' target='_blank'>Jitsi as a Service</a>!",
|
||||
@@ -845,6 +882,7 @@
|
||||
"suggestRecordingDescription": "Vai vēlaties sākt ierakstīšanu?",
|
||||
"suggestRecordingTitle": "Ierakstīt sanāksmi",
|
||||
"unmute": "Ieslēgt mikrofonu",
|
||||
"unmuteScreen": "",
|
||||
"unmuteVideo": "Ieslēgt video",
|
||||
"videoMutedRemotelyDescription": "Jūs vienmēr varat to atkal ieslēgt.",
|
||||
"videoMutedRemotelyTitle": "{{participantDisplayName}} izslēdza jūsu video",
|
||||
@@ -864,11 +902,14 @@
|
||||
"admit": "Apstiprināt",
|
||||
"admitAll": "Apstiprināt visus",
|
||||
"allow": "Atļaut dalībniekiem:",
|
||||
"allowDesktop": "Atļaut ekrāna kopīgošanu",
|
||||
"allowVideo": "Atļaut video",
|
||||
"askDesktop": "Lūgt kopīgot ekrānu",
|
||||
"askUnmute": "Lūgt ieslēgt skaņu",
|
||||
"audioModeration": "Ieslēgt savu skaņu",
|
||||
"blockEveryoneMicCamera": "Bloķēt visiem mikrofonu un kameru",
|
||||
"breakoutRooms": "Grupu istabas",
|
||||
"desktopModeration": "Sākt ekrāna kopīgošanu",
|
||||
"goLive": "Sākt",
|
||||
"invite": "Uzaicināt",
|
||||
"lowerAllHands": "Nolaist visas paceltās rokas",
|
||||
@@ -880,6 +921,8 @@
|
||||
"muteAll": "Apklusināt visus",
|
||||
"muteEveryoneElse": "Apklusināt pārējos",
|
||||
"reject": "Noraidīt",
|
||||
"stopDesktop": "Pārtraukt ekrāna kopīgošanu",
|
||||
"stopEveryonesDesktop": "Pārtraukt visiem ekrāna kopīgošanu",
|
||||
"stopEveryonesVideo": "Izslēgt visiem video",
|
||||
"stopVideo": "Izslēgt video",
|
||||
"unblockEveryoneMicCamera": "Atbloķēt visiem mikrofonu un kameru",
|
||||
@@ -889,9 +932,11 @@
|
||||
"headings": {
|
||||
"lobby": "Vestibils ({{count}})",
|
||||
"participantsList": "Sapulces dalībnieki ({{count}})",
|
||||
"viewerRequests": "Apmeklētāju pieprasījumi {{count}}",
|
||||
"visitorInQueue": " (gaida {{count}})",
|
||||
"visitorRequests": " (pieprasījumi {{count}})",
|
||||
"visitors": "Apmeklētāji ({{count}})",
|
||||
"visitors": "Apmeklētāji {{count}}",
|
||||
"visitorsList": "Apmeklētāji ({{count}})",
|
||||
"waitingLobby": "Gaida vestibilā ({{count}})"
|
||||
},
|
||||
"search": "Meklēt dalībniekus",
|
||||
@@ -1484,6 +1529,8 @@
|
||||
"connectionInfo": "Informācija par savienojumu",
|
||||
"demote": "Pārveidot par apmeklētāju",
|
||||
"domute": "Izlsēgt skaņu",
|
||||
"domuteDesktop": "Pārtraukt ekrāna kopīgošanu",
|
||||
"domuteDesktopOfOthers": "Pārtraukt ekrāna kopīgošanu visiem pārējiem",
|
||||
"domuteOthers": "Izslēgt skaņu visiem pārējiem",
|
||||
"domuteVideo": "Izslēgt kameru",
|
||||
"domuteVideoOfOthers": "Izslēgt video visiem pārējiem",
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
"disabled": "Sending chat messages is disabled.",
|
||||
"enter": "Enter room",
|
||||
"error": "Error: your message was not sent. Reason: {{error}}",
|
||||
"everyone": "Everyone",
|
||||
"fieldPlaceHolder": "Aa",
|
||||
"lobbyChatMessageTo": "Lobby chat message to {{recipient}}",
|
||||
"message": "Message",
|
||||
@@ -380,7 +381,7 @@
|
||||
"micPermissionDeniedError": "You have not granted permission to use your microphone. You can still join the conference but others won't hear you. Use the camera button in the address bar to fix this.",
|
||||
"micTimeoutError": "Could not start audio source. Timeout occurred!",
|
||||
"micUnknownError": "Cannot use microphone for an unknown reason.",
|
||||
"moderationAudioLabel": "Allow attendees to unmute themselves",
|
||||
"moderationAudioLabel": "Allow non-moderators to unmute themselves",
|
||||
"moderationDesktopLabel": "Allow non-moderators to share their screen",
|
||||
"moderationVideoLabel": "Allow non-moderators to start their video",
|
||||
"muteEveryoneDialog": "The participants can unmute themselves at any time.",
|
||||
@@ -569,6 +570,8 @@
|
||||
"fileAlreadyUploaded": "File has already been uploaded to this meeting.",
|
||||
"fileTooLargeDescription": "Please make sure the file does not exceed {{ maxFileSize }}.",
|
||||
"fileTooLargeTitle": "The selected file is too large",
|
||||
"fileUploadProgress": "File upload progress",
|
||||
"fileUploadedSuccessfully": "File uploaded successfully",
|
||||
"removeFile": "Remove",
|
||||
"uploadFailedDescription": "Please try again.",
|
||||
"uploadFailedTitle": "Upload failed",
|
||||
|
||||
574
package-lock.json
generated
574
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@@ -23,7 +23,7 @@
|
||||
"@emotion/styled": "11.10.6",
|
||||
"@giphy/js-fetch-api": "4.9.3",
|
||||
"@giphy/react-components": "6.9.4",
|
||||
"@giphy/react-native-sdk": "3.3.1",
|
||||
"@giphy/react-native-sdk": "4.1.0",
|
||||
"@jitsi/excalidraw": "https://github.com/jitsi/excalidraw/releases/download/v0.0.19/jitsi-excalidraw-0.0.19.tgz",
|
||||
"@jitsi/js-utils": "2.2.1",
|
||||
"@jitsi/logger": "2.0.2",
|
||||
@@ -59,6 +59,7 @@
|
||||
"dayjs": "1.11.13",
|
||||
"dropbox": "10.7.0",
|
||||
"focus-visible": "5.1.0",
|
||||
"glob": "11.0.3",
|
||||
"grapheme-splitter": "1.0.4",
|
||||
"i18n-iso-countries": "6.8.0",
|
||||
"i18next": "17.0.6",
|
||||
@@ -70,7 +71,7 @@
|
||||
"js-md5": "0.6.1",
|
||||
"js-sha512": "0.8.0",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v2033.0.0+bf3e3a8e/lib-jitsi-meet.tgz",
|
||||
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v2051.0.0+ccc06e83/lib-jitsi-meet.tgz",
|
||||
"lodash-es": "4.17.21",
|
||||
"null-loader": "4.0.1",
|
||||
"optional-require": "1.0.3",
|
||||
@@ -87,16 +88,16 @@
|
||||
"react-native-background-timer": "https://github.com/jitsi/react-native-background-timer.git#d180dfaa4486ae3ee17d01242db92cb3195f4718",
|
||||
"react-native-calendar-events": "https://github.com/jitsi/react-native-calendar-events.git#47f068dedfed7c0f72042e093f688eb11624eb7b",
|
||||
"react-native-default-preference": "https://github.com/jitsi/react-native-default-preference.git#c9bf63bdc058e3fa2aa0b87b1ee1af240f44ed02",
|
||||
"react-native-device-info": "10.9.0",
|
||||
"react-native-device-info": "12.1.0",
|
||||
"react-native-dialog": "https://github.com/jitsi/react-native-dialog/releases/download/v9.2.2-jitsi.1/react-native-dialog-9.2.2.tgz",
|
||||
"react-native-gesture-handler": "2.24.0",
|
||||
"react-native-get-random-values": "1.11.0",
|
||||
"react-native-immersive-mode": "https://github.com/jitsi/react-native-immersive-mode.git#38cc9001db24618bc0c61800f81e889bcfb6ff2c",
|
||||
"react-native-orientation-locker": "1.6.0",
|
||||
"react-native-pager-view": "6.4.1",
|
||||
"react-native-orientation-locker": "https://github.com/jitsi/react-native-orientation-locker.git#fe095651d819cf134624f786b61fc8667862178a",
|
||||
"react-native-pager-view": "6.8.1",
|
||||
"react-native-paper": "5.10.3",
|
||||
"react-native-performance": "5.1.2",
|
||||
"react-native-safe-area-context": "5.4.0",
|
||||
"react-native-safe-area-context": "5.5.2",
|
||||
"react-native-screens": "4.11.1",
|
||||
"react-native-sound": "https://github.com/jitsi/react-native-sound.git#ea13c97b5c2a4ff5e0d9bacbd9ff5e4457fe2c3c",
|
||||
"react-native-splash-view": "0.0.18",
|
||||
@@ -111,7 +112,7 @@
|
||||
"react-native-youtube-iframe": "2.3.0",
|
||||
"react-redux": "7.2.9",
|
||||
"react-textarea-autosize": "8.3.0",
|
||||
"react-virtualized-auto-sizer": "^1.0.26",
|
||||
"react-virtualized-auto-sizer": "1.0.26",
|
||||
"react-window": "1.8.6",
|
||||
"react-youtube": "10.1.0",
|
||||
"redux": "4.0.4",
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
diff --git a/node_modules/@giphy/js-analytics/dist/send-pingback.js b/node_modules/@giphy/js-analytics/dist/send-pingback.js
|
||||
index 989f0ff..52471cb 100644
|
||||
--- a/node_modules/@giphy/js-analytics/dist/send-pingback.js
|
||||
+++ b/node_modules/@giphy/js-analytics/dist/send-pingback.js
|
||||
@@ -10,6 +10,9 @@ var global_1 = __importDefault(require("./global"));
|
||||
var environment = (global_1.default === null || global_1.default === void 0 ? void 0 : global_1.default.GIPHY_PINGBACK_URL) || 'https://pingback.giphy.com';
|
||||
var pingBackUrl = "".concat(environment, "/v2/pingback?apikey=l0HlIwPWyBBUDAUgM");
|
||||
var sendPingback = function (events) {
|
||||
+ // Disabled.
|
||||
+ return Promise.resolve();
|
||||
+
|
||||
var headers = (0, js_util_1.getGiphySDKRequestHeaders)();
|
||||
/* istanbul ignore next */
|
||||
headers === null || headers === void 0 ? void 0 : headers.set('Content-Type', 'application/json');
|
||||
@@ -2,7 +2,7 @@ import React, { useCallback } from 'react';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { pixelsToRem } from '../../../ui/functions.any';
|
||||
import { isIcon } from '../../functions';
|
||||
import { IAvatarProps } from '../../types';
|
||||
import { PRESENCE_AVAILABLE_COLOR, PRESENCE_AWAY_COLOR, PRESENCE_BUSY_COLOR, PRESENCE_IDLE_COLOR } from '../styles';
|
||||
@@ -50,9 +50,8 @@ const useStyles = makeStyles()(theme => {
|
||||
avatar: {
|
||||
backgroundColor: '#AAA',
|
||||
borderRadius: '50%',
|
||||
fontWeight: '600',
|
||||
color: theme.palette?.text01 || '#fff',
|
||||
...withPixelLineHeight(theme.typography?.heading1 ?? {}),
|
||||
...(theme.typography?.heading1 ?? {}),
|
||||
fontSize: 'inherit',
|
||||
objectFit: 'cover',
|
||||
textAlign: 'center',
|
||||
@@ -137,7 +136,7 @@ const StatelessAvatar = ({
|
||||
const _getAvatarStyle = (backgroundColor?: string) => {
|
||||
return {
|
||||
background: backgroundColor || undefined,
|
||||
fontSize: size ? size * 0.4 : '180%',
|
||||
fontSize: size ? pixelsToRem(size * 0.4) : '180%',
|
||||
height: size || '100%',
|
||||
width: size || '100%'
|
||||
};
|
||||
|
||||
@@ -4,13 +4,12 @@ import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import Icon from '../icons/components/Icon';
|
||||
import { IconCheck, IconCopy } from '../icons/svg';
|
||||
import { withPixelLineHeight } from '../styles/functions.web';
|
||||
import { copyText } from '../util/copyText.web';
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
copyButton: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortBold),
|
||||
...theme.typography.bodyShortBold,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-start',
|
||||
|
||||
@@ -521,7 +521,6 @@ export interface IConfig {
|
||||
preCallTestEnabled?: boolean;
|
||||
preCallTestICEUrl?: string;
|
||||
};
|
||||
prejoinPageEnabled?: boolean;
|
||||
raisedHands?: {
|
||||
disableLowerHandByModerator?: boolean;
|
||||
disableLowerHandNotification?: boolean;
|
||||
|
||||
@@ -202,7 +202,6 @@ export default [
|
||||
'prejoinConfig.enabled',
|
||||
'prejoinConfig.hideDisplayName',
|
||||
'prejoinConfig.hideExtraJoinButtons',
|
||||
'prejoinPageEnabled',
|
||||
'raisedHands',
|
||||
'recordingService',
|
||||
'requireDisplayName',
|
||||
|
||||
@@ -7,6 +7,7 @@ import { isEmpty, mergeWith, pick } from 'lodash-es';
|
||||
|
||||
import { IReduxState } from '../../app/types';
|
||||
import { getLocalParticipant } from '../participants/functions';
|
||||
import { isEmbedded } from '../util/embedUtils';
|
||||
import { parseURLParams } from '../util/parseURLParams';
|
||||
|
||||
import { IConfig } from './configType';
|
||||
@@ -335,7 +336,7 @@ export function setConfigFromURLParams(
|
||||
|
||||
overrideConfigJSON(config, interfaceConfig, json);
|
||||
|
||||
// Print warning about depricated URL params
|
||||
// Print warning about deprecated URL params
|
||||
if ('interfaceConfig.SUPPORT_URL' in params) {
|
||||
logger.warn('Using SUPPORT_URL interfaceConfig URL overwrite is deprecated.'
|
||||
+ ' Please use supportUrl from advanced branding!');
|
||||
@@ -371,6 +372,13 @@ export function setConfigFromURLParams(
|
||||
logger.warn('Using liveStreaming config URL overwrite and/or LIVE_STREAMING_HELP_LINK interfaceConfig URL'
|
||||
+ ' overwrite is deprecated. Please use liveStreaming from advanced branding!');
|
||||
}
|
||||
|
||||
// When not in an iframe, start without media if the pre-join page is not enabled.
|
||||
if (!isEmbedded()
|
||||
&& 'config.prejoinConfig.enabled' in params && config.prejoinConfig?.enabled === false) {
|
||||
logger.warn('Using prejoinConfig.enabled config URL overwrite implies starting without media.');
|
||||
config.disableInitialGUM = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable max-params */
|
||||
|
||||
@@ -405,13 +405,6 @@ function _translateLegacyConfig(oldValue: IConfig) {
|
||||
newValue.welcomePage.disabled = !oldValue.enableWelcomePage;
|
||||
}
|
||||
|
||||
newValue.prejoinConfig = oldValue.prejoinConfig || {};
|
||||
if (oldValue.hasOwnProperty('prejoinPageEnabled')
|
||||
&& !newValue.prejoinConfig.hasOwnProperty('enabled')
|
||||
) {
|
||||
newValue.prejoinConfig.enabled = oldValue.prejoinPageEnabled;
|
||||
}
|
||||
|
||||
newValue.disabledSounds = newValue.disabledSounds || [];
|
||||
|
||||
if (oldValue.disableJoinLeaveSounds) {
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, { useCallback } from 'react';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { COLORS } from '../../constants';
|
||||
|
||||
interface IProps {
|
||||
@@ -55,7 +54,7 @@ interface IProps {
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
label: {
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
alignItems: 'center',
|
||||
background: theme.palette.ui04,
|
||||
borderRadius: '4px',
|
||||
|
||||
@@ -3,7 +3,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { IconArrowDown } from '../../../icons/svg';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
interface IProps {
|
||||
|
||||
@@ -82,7 +81,7 @@ interface IProps {
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
actionButton: {
|
||||
...withPixelLineHeight(theme.typography.bodyLongBold),
|
||||
...theme.typography.bodyLongBold,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
boxSizing: 'border-box',
|
||||
color: theme.palette.text01,
|
||||
@@ -115,7 +114,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
'&.text': {
|
||||
width: 'auto',
|
||||
fontSize: '13px',
|
||||
fontSize: '0.875rem',
|
||||
margin: '0',
|
||||
padding: '0'
|
||||
},
|
||||
@@ -135,7 +134,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
|
||||
[theme.breakpoints.down(400)]: {
|
||||
fontSize: 16,
|
||||
fontSize: '1rem',
|
||||
marginBottom: 8,
|
||||
padding: '11px 16px'
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { IconArrowDown, IconCloseCircle, IconWifi1Bar, IconWifi2Bars, IconWifi3Bars } from '../../../icons/svg';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { PREJOIN_DEFAULT_CONTENT_WIDTH } from '../../../ui/components/variables';
|
||||
import Spinner from '../../../ui/components/web/Spinner';
|
||||
import { runPreCallTest } from '../../actions.web';
|
||||
@@ -16,7 +15,7 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
connectionStatus: {
|
||||
color: '#fff',
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import Toolbox from '../../../../toolbox/components/web/Toolbox';
|
||||
import { isButtonEnabled } from '../../../../toolbox/functions.web';
|
||||
import { getConferenceName } from '../../../conference/functions';
|
||||
import { PREMEETING_BUTTONS, THIRD_PARTY_PREJOIN_BUTTONS } from '../../../config/constants';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import Tooltip from '../../../tooltip/components/Tooltip';
|
||||
import { isPreCallTestEnabled } from '../../functions';
|
||||
|
||||
@@ -152,7 +151,7 @@ const useStyles = makeStyles()(theme => {
|
||||
width: '100%'
|
||||
},
|
||||
title: {
|
||||
...withPixelLineHeight(theme.typography.heading4),
|
||||
...theme.typography.heading4,
|
||||
color: `${theme.palette.text01}!important`,
|
||||
marginBottom: theme.spacing(3),
|
||||
textAlign: 'center',
|
||||
@@ -168,7 +167,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
roomName: {
|
||||
...withPixelLineHeight(theme.typography.heading5),
|
||||
...theme.typography.heading5,
|
||||
color: theme.palette.text01,
|
||||
display: 'inline-block',
|
||||
overflow: 'hidden',
|
||||
|
||||
@@ -2,8 +2,6 @@ import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
warning: {
|
||||
@@ -11,7 +9,7 @@ const useStyles = makeStyles()(theme => {
|
||||
color: theme.palette.text03,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginBottom: theme.spacing(3),
|
||||
marginTop: theme.spacing(2),
|
||||
paddingLeft: theme.spacing(3),
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import Checkbox from '../../../ui/components/web/Checkbox';
|
||||
import getUnsafeRoomText from '../../../util/getUnsafeRoomText.web';
|
||||
import { setUnsafeRoomConsent } from '../../actions.web';
|
||||
@@ -14,7 +13,7 @@ const useStyles = makeStyles()(theme => {
|
||||
warning: {
|
||||
backgroundColor: theme.palette.warning01,
|
||||
color: theme.palette.text04,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
padding: theme.spacing(3),
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
marginBottom: theme.spacing(3)
|
||||
|
||||
@@ -6,6 +6,7 @@ import { translate } from '../../../i18n/functions';
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import Tooltip from '../../../tooltip/components/Tooltip';
|
||||
import { TOOLTIP_POSITION } from '../../../ui/constants.any';
|
||||
import { pixelsToRem } from '../../../ui/functions.any';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link BaseIndicator}.
|
||||
@@ -40,7 +41,7 @@ interface IProps extends WithTranslation {
|
||||
/**
|
||||
* The font size for the icon.
|
||||
*/
|
||||
iconSize: string | number;
|
||||
iconSize: number;
|
||||
|
||||
/**
|
||||
* The ID attribute to set on the root element of the component.
|
||||
@@ -88,10 +89,10 @@ const BaseIndicator = ({
|
||||
tooltipPosition = 'top'
|
||||
}: IProps) => {
|
||||
const { classes: styles } = useStyles();
|
||||
const style: { fontSize?: string | number; } = {};
|
||||
const style: { fontSize?: string; } = {};
|
||||
|
||||
if (iconSize) {
|
||||
style.fontSize = iconSize;
|
||||
style.fontSize = pixelsToRem(iconSize);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import Button from '../../../ui/components/web/Button';
|
||||
import { getSupportUrl } from '../../functions';
|
||||
|
||||
@@ -15,7 +14,7 @@ const useStyles = makeStyles()(theme => {
|
||||
borderRadius: `${Number(theme.shape.borderRadius)}px`,
|
||||
boxShadow: '0px 1px 2px rgba(41, 41, 41, 0.25)',
|
||||
color: theme.palette.text01,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
padding: `${theme.spacing(3)} 10`,
|
||||
'& .retry-button': {
|
||||
margin: '16px auto 0 auto'
|
||||
|
||||
@@ -22,17 +22,3 @@ export function getFixedPlatformStyle(style?: StyleType | StyleType[]) {
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the line height of a CSS Object group in pixels.
|
||||
* By default lineHeight is unitless in CSS, but not in RN.
|
||||
*
|
||||
* @param {Object} base - The base object containing the `lineHeight` property.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function withPixelLineHeight(base: any) {
|
||||
return {
|
||||
...base,
|
||||
lineHeight: `${base.lineHeight}px`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { isMobileBrowser } from '../../environment/utils';
|
||||
import Popover from '../../popover/components/Popover.web';
|
||||
import { withPixelLineHeight } from '../../styles/functions.web';
|
||||
import { TOOLTIP_POSITION } from '../../ui/constants.any';
|
||||
import { hideTooltip, showTooltip } from '../actions';
|
||||
|
||||
@@ -26,7 +25,7 @@ const useStyles = makeStyles()(theme => {
|
||||
backgroundColor: theme.palette.uiBackground,
|
||||
borderRadius: '3px',
|
||||
padding: theme.spacing(2),
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text01,
|
||||
position: 'relative',
|
||||
|
||||
|
||||
@@ -118,8 +118,8 @@ export const colorMap = {
|
||||
|
||||
|
||||
export const font = {
|
||||
weightRegular: '400',
|
||||
weightSemiBold: '600'
|
||||
weightRegular: 400,
|
||||
weightSemiBold: 600
|
||||
};
|
||||
|
||||
export const shape = {
|
||||
@@ -136,64 +136,64 @@ export const typography = {
|
||||
labelBold: 'labelBold01',
|
||||
|
||||
bodyShortRegularSmall: {
|
||||
fontSize: 10,
|
||||
lineHeight: 16,
|
||||
fontSize: '0.625rem',
|
||||
lineHeight: '1rem',
|
||||
fontWeight: font.weightRegular,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
bodyShortRegular: {
|
||||
fontSize: 14,
|
||||
lineHeight: 20,
|
||||
fontSize: '0.875rem',
|
||||
lineHeight: '1.25rem',
|
||||
fontWeight: font.weightRegular,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
bodyShortBold: {
|
||||
fontSize: 14,
|
||||
lineHeight: 20,
|
||||
fontSize: '0.875rem',
|
||||
lineHeight: '1.25rem',
|
||||
fontWeight: font.weightSemiBold,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
bodyShortRegularLarge: {
|
||||
fontSize: 16,
|
||||
lineHeight: 22,
|
||||
fontSize: '1rem',
|
||||
lineHeight: '1.375rem',
|
||||
fontWeight: font.weightRegular,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
bodyShortBoldLarge: {
|
||||
fontSize: 16,
|
||||
lineHeight: 22,
|
||||
fontSize: '1rem',
|
||||
lineHeight: '1.375rem',
|
||||
fontWeight: font.weightSemiBold,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
bodyLongRegular: {
|
||||
fontSize: 14,
|
||||
lineHeight: 24,
|
||||
fontSize: '0.875rem',
|
||||
lineHeight: '1.5rem',
|
||||
fontWeight: font.weightRegular,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
bodyLongRegularLarge: {
|
||||
fontSize: 16,
|
||||
lineHeight: 26,
|
||||
fontSize: '1rem',
|
||||
lineHeight: '1.625rem',
|
||||
fontWeight: font.weightRegular,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
bodyLongBold: {
|
||||
fontSize: 14,
|
||||
lineHeight: 24,
|
||||
fontSize: '0.875rem',
|
||||
lineHeight: '1.5rem',
|
||||
fontWeight: font.weightSemiBold,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
bodyLongBoldLarge: {
|
||||
fontSize: 16,
|
||||
lineHeight: 26,
|
||||
fontSize: '1rem',
|
||||
lineHeight: '1.625rem',
|
||||
fontWeight: font.weightSemiBold,
|
||||
letterSpacing: 0
|
||||
},
|
||||
@@ -203,29 +203,29 @@ export const typography = {
|
||||
heading2: 'heading02',
|
||||
|
||||
heading3: {
|
||||
fontSize: 32,
|
||||
lineHeight: 40,
|
||||
fontSize: '2rem',
|
||||
lineHeight: '2.5rem',
|
||||
fontWeight: font.weightSemiBold,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
heading4: {
|
||||
fontSize: 28,
|
||||
lineHeight: 36,
|
||||
fontSize: '1.75rem',
|
||||
lineHeight: '2.25rem',
|
||||
fontWeight: font.weightSemiBold,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
heading5: {
|
||||
fontSize: 20,
|
||||
lineHeight: 28,
|
||||
fontSize: '1.25rem',
|
||||
lineHeight: '1.75rem',
|
||||
fontWeight: font.weightSemiBold,
|
||||
letterSpacing: 0
|
||||
},
|
||||
|
||||
heading6: {
|
||||
fontSize: 16,
|
||||
lineHeight: 26,
|
||||
fontSize: '1rem',
|
||||
lineHeight: '1.625rem',
|
||||
fontWeight: font.weightSemiBold,
|
||||
letterSpacing: 0
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useTranslation } from 'react-i18next';
|
||||
import { keyframes } from 'tss-react';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { isElementInTheViewport } from '../../functions.web';
|
||||
|
||||
import { DialogTransitionContext } from './DialogTransition';
|
||||
@@ -16,7 +15,7 @@ const useStyles = makeStyles()(theme => {
|
||||
height: '100%',
|
||||
position: 'fixed',
|
||||
color: theme.palette.text01,
|
||||
...withPixelLineHeight(theme.typography.bodyLongRegular),
|
||||
...theme.typography.bodyLongRegular,
|
||||
top: 0,
|
||||
left: 0,
|
||||
display: 'flex',
|
||||
|
||||
@@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { BUTTON_TYPES } from '../../constants.web';
|
||||
import { IButtonProps } from '../types';
|
||||
|
||||
@@ -57,7 +56,7 @@ const useStyles = makeStyles()(theme => {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: 0,
|
||||
...withPixelLineHeight(theme.typography.bodyShortBold),
|
||||
...theme.typography.bodyShortBold,
|
||||
transition: 'background .2s',
|
||||
cursor: 'pointer',
|
||||
|
||||
@@ -151,7 +150,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
small: {
|
||||
padding: '8px 16px',
|
||||
...withPixelLineHeight(theme.typography.labelBold),
|
||||
...theme.typography.labelBold,
|
||||
|
||||
'&.iconButton': {
|
||||
padding: theme.spacing(1)
|
||||
@@ -162,7 +161,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
large: {
|
||||
padding: '13px 16px',
|
||||
...withPixelLineHeight(theme.typography.bodyShortBoldLarge),
|
||||
...theme.typography.bodyShortBoldLarge,
|
||||
|
||||
'&.iconButton': {
|
||||
padding: '12px'
|
||||
|
||||
@@ -4,7 +4,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
import { isMobileBrowser } from '../../../environment/utils';
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { IconCheck } from '../../../icons/svg';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
interface ICheckboxProps {
|
||||
|
||||
@@ -42,13 +41,13 @@ interface ICheckboxProps {
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
formControl: {
|
||||
...withPixelLineHeight(theme.typography.bodyLongRegular),
|
||||
...theme.typography.bodyLongRegular,
|
||||
color: theme.palette.text01,
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
|
||||
'&.is-mobile': {
|
||||
...withPixelLineHeight(theme.typography.bodyLongRegularLarge)
|
||||
...theme.typography.bodyLongRegularLarge
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
@@ -8,7 +8,6 @@ import Drawer from '../../../../toolbox/components/web/Drawer';
|
||||
import JitsiPortal from '../../../../toolbox/components/web/JitsiPortal';
|
||||
import { showOverflowDrawer } from '../../../../toolbox/functions.web';
|
||||
import participantsPaneTheme from '../../../components/themes/participantsPaneTheme.json';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { spacing } from '../../Tokens';
|
||||
|
||||
|
||||
@@ -139,7 +138,7 @@ const useStyles = makeStyles()(theme => {
|
||||
borderRadius: `${Number(theme.shape.borderRadius)}px`,
|
||||
boxShadow: '0px 1px 2px rgba(41, 41, 41, 0.25)',
|
||||
color: theme.palette.text01,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginTop: '48px',
|
||||
position: 'absolute',
|
||||
right: `${participantsPaneTheme.panePadding}px`,
|
||||
@@ -159,7 +158,7 @@ const useStyles = makeStyles()(theme => {
|
||||
paddingTop: '16px',
|
||||
|
||||
'& > div': {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge),
|
||||
...theme.typography.bodyShortRegularLarge,
|
||||
|
||||
'& svg': {
|
||||
fill: theme.palette.icon01
|
||||
|
||||
@@ -4,7 +4,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { showOverflowDrawer } from '../../../../toolbox/functions.web';
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { TEXT_OVERFLOW_TYPES } from '../../constants.any';
|
||||
|
||||
import TextWithOverflow from './TextWithOverflow';
|
||||
@@ -174,12 +173,12 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
text: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01
|
||||
},
|
||||
|
||||
drawerText: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
|
||||
...theme.typography.bodyShortRegularLarge
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -5,7 +5,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { hideDialog } from '../../../dialog/actions';
|
||||
import { IconCloseLarge } from '../../../icons/svg';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { operatesWithEnterKey } from '../../functions.web';
|
||||
|
||||
import BaseDialog, { IProps as IBaseDialogProps } from './BaseDialog';
|
||||
@@ -26,7 +25,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
title: {
|
||||
color: theme.palette.text01,
|
||||
...withPixelLineHeight(theme.typography.heading5),
|
||||
...theme.typography.heading5,
|
||||
margin: 0,
|
||||
padding: 0
|
||||
},
|
||||
|
||||
@@ -6,7 +6,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import { hideDialog } from '../../../dialog/actions';
|
||||
import { IconArrowBack, IconCloseLarge } from '../../../icons/svg';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
import BaseDialog, { IProps as IBaseProps } from './BaseDialog';
|
||||
import Button from './Button';
|
||||
@@ -70,7 +69,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
title: {
|
||||
...withPixelLineHeight(theme.typography.heading5),
|
||||
...theme.typography.heading5,
|
||||
color: `${theme.palette.text01} !important`,
|
||||
margin: 0,
|
||||
padding: 0
|
||||
|
||||
@@ -5,7 +5,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
import { isMobileBrowser } from '../../../environment/utils';
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { IconCloseCircle } from '../../../icons/svg';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { IInputProps } from '../types';
|
||||
|
||||
import { HiddenDescription } from './HiddenDescription';
|
||||
@@ -51,11 +50,11 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
label: {
|
||||
color: theme.palette.text01,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginBottom: theme.spacing(2),
|
||||
|
||||
'&.is-mobile': {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
|
||||
...theme.typography.bodyShortRegularLarge
|
||||
}
|
||||
},
|
||||
|
||||
@@ -68,7 +67,7 @@ const useStyles = makeStyles()(theme => {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
background: theme.palette.ui03,
|
||||
color: theme.palette.text01,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
padding: '10px 16px',
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
border: 0,
|
||||
@@ -92,7 +91,7 @@ const useStyles = makeStyles()(theme => {
|
||||
'&.is-mobile': {
|
||||
height: '48px',
|
||||
padding: '13px 16px',
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
|
||||
...theme.typography.bodyShortRegularLarge
|
||||
},
|
||||
|
||||
'&.icon-input': {
|
||||
@@ -139,11 +138,11 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
bottomLabel: {
|
||||
marginTop: theme.spacing(2),
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
|
||||
'&.is-mobile': {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular)
|
||||
...theme.typography.bodyShortRegular
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
|
||||
@@ -4,7 +4,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
import { ACTION_TRIGGER } from '../../../../participants-pane/constants';
|
||||
import participantsPaneTheme from '../../../components/themes/participantsPaneTheme.json';
|
||||
import { isMobileBrowser } from '../../../environment/utils';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
interface IProps {
|
||||
|
||||
@@ -86,7 +85,7 @@ const useStyles = makeStyles()(theme => {
|
||||
alignItems: 'center',
|
||||
color: theme.palette.text01,
|
||||
display: 'flex',
|
||||
...withPixelLineHeight(theme.typography.bodyShortBold),
|
||||
...theme.typography.bodyShortBold,
|
||||
margin: `0 -${participantsPaneTheme.panePadding}px`,
|
||||
padding: `${theme.spacing(2)} ${participantsPaneTheme.panePadding}px`,
|
||||
position: 'relative',
|
||||
@@ -110,7 +109,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
[`@media(max-width: ${participantsPaneTheme.MD_BREAKPOINT})`]: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortBoldLarge),
|
||||
...theme.typography.bodyShortBoldLarge,
|
||||
padding: `${theme.spacing(3)} ${participantsPaneTheme.panePadding}px`
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, { useCallback, useMemo, useRef } from 'react';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IconCloseLarge } from '../../../icons/svg';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
import { MultiSelectItem } from '../types';
|
||||
|
||||
import ClickableIcon from './ClickableIcon';
|
||||
@@ -42,7 +41,7 @@ const useStyles = makeStyles()(theme => {
|
||||
backgroundColor: theme.palette.ui01,
|
||||
border: `1px solid ${theme.palette.ui04}`,
|
||||
borderRadius: `${Number(theme.shape.borderRadius)}px`,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
zIndex: 2,
|
||||
maxHeight: `${MULTI_SELECT_HEIGHT}px`,
|
||||
overflowY: 'auto',
|
||||
|
||||
@@ -4,7 +4,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
import { isMobileBrowser } from '../../../environment/utils';
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { IconArrowDown } from '../../../icons/svg';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
interface ISelectProps {
|
||||
|
||||
@@ -18,6 +17,11 @@ interface ISelectProps {
|
||||
*/
|
||||
className?: string;
|
||||
|
||||
/**
|
||||
* Class name for additional styles for container.
|
||||
*/
|
||||
containerClassName?: string;
|
||||
|
||||
/**
|
||||
* Whether or not the select is disabled.
|
||||
*/
|
||||
@@ -67,11 +71,11 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
label: {
|
||||
color: theme.palette.text01,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
marginBottom: theme.spacing(2),
|
||||
|
||||
'&.is-mobile': {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
|
||||
...theme.typography.bodyShortRegularLarge
|
||||
}
|
||||
},
|
||||
|
||||
@@ -83,7 +87,7 @@ const useStyles = makeStyles()(theme => {
|
||||
backgroundColor: theme.palette.ui03,
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
width: '100%',
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01,
|
||||
padding: '10px 16px',
|
||||
paddingRight: '42px',
|
||||
@@ -103,7 +107,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge),
|
||||
...theme.typography.bodyShortRegularLarge,
|
||||
padding: '12px 16px',
|
||||
paddingRight: '46px'
|
||||
},
|
||||
@@ -127,11 +131,11 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
bottomLabel: {
|
||||
marginTop: theme.spacing(2),
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
|
||||
'&.is-mobile': {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular)
|
||||
...theme.typography.bodyShortRegular
|
||||
},
|
||||
|
||||
'&.error': {
|
||||
@@ -143,6 +147,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
const Select = ({
|
||||
bottomLabel,
|
||||
containerClassName,
|
||||
className,
|
||||
disabled,
|
||||
error,
|
||||
@@ -155,7 +160,7 @@ const Select = ({
|
||||
const isMobile = isMobileBrowser();
|
||||
|
||||
return (
|
||||
<div className = { classes.container }>
|
||||
<div className = { cx(classes.container, containerClassName) }>
|
||||
{label && <label
|
||||
className = { cx(classes.label, isMobile && 'is-mobile') }
|
||||
htmlFor = { id } >
|
||||
|
||||
@@ -3,7 +3,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { isMobileBrowser } from '../../../environment/utils';
|
||||
import Icon from '../../../icons/components/Icon';
|
||||
import { withPixelLineHeight } from '../../../styles/functions.web';
|
||||
|
||||
interface ITabProps {
|
||||
accessibilityLabel: string;
|
||||
@@ -18,6 +17,7 @@ interface ITabProps {
|
||||
icon?: Function;
|
||||
id: string;
|
||||
label?: string;
|
||||
title?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
tab: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortBold),
|
||||
...theme.typography.bodyShortBold,
|
||||
color: theme.palette.text02,
|
||||
flex: 1,
|
||||
padding: '14px',
|
||||
@@ -65,12 +65,12 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
'&.is-mobile': {
|
||||
...withPixelLineHeight(theme.typography.bodyShortBoldLarge)
|
||||
...theme.typography.bodyShortBoldLarge
|
||||
}
|
||||
},
|
||||
|
||||
badge: {
|
||||
...withPixelLineHeight(theme.typography.labelBold),
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.text04,
|
||||
padding: `0 ${theme.spacing(1)}`,
|
||||
borderRadius: '100%',
|
||||
@@ -127,26 +127,34 @@ const Tabs = ({
|
||||
aria-label = { accessibilityLabel }
|
||||
className = { cx(classes.container, className) }
|
||||
role = 'tablist'>
|
||||
{tabs.map((tab, index) => (
|
||||
<button
|
||||
aria-controls = { tab.controlsId }
|
||||
aria-label = { tab.accessibilityLabel }
|
||||
aria-selected = { selected === tab.id }
|
||||
className = { cx(classes.tab, selected === tab.id && 'selected', isMobile && 'is-mobile') }
|
||||
disabled = { tab.disabled }
|
||||
id = { tab.id }
|
||||
key = { tab.id }
|
||||
onClick = { onClick(tab.id) }
|
||||
onKeyDown = { onKeyDown(index) }
|
||||
role = 'tab'
|
||||
tabIndex = { selected === tab.id ? undefined : -1 }>
|
||||
{tab.icon && <Icon
|
||||
className = { classes.icon }
|
||||
src = { tab.icon } />}
|
||||
{tab.label}
|
||||
{tab.countBadge && <span className = { classes.badge }>{tab.countBadge}</span>}
|
||||
</button>
|
||||
))}
|
||||
{
|
||||
tabs.map((tab, index) => (
|
||||
<button
|
||||
aria-controls = { tab.controlsId }
|
||||
aria-label = { tab.accessibilityLabel }
|
||||
aria-selected = { selected === tab.id }
|
||||
className = { cx(classes.tab, selected === tab.id && 'selected', isMobile && 'is-mobile') }
|
||||
disabled = { tab.disabled }
|
||||
id = { tab.id }
|
||||
key = { tab.id }
|
||||
onClick = { onClick(tab.id) }
|
||||
onKeyDown = { onKeyDown(index) }
|
||||
role = 'tab'
|
||||
tabIndex = { selected === tab.id ? undefined : -1 }
|
||||
title = { tab.title }>
|
||||
{
|
||||
tab.icon && <Icon
|
||||
className = { classes.icon }
|
||||
src = { tab.icon } />
|
||||
}
|
||||
{ tab.label }
|
||||
{
|
||||
tab.countBadge && <span className = { classes.badge }>
|
||||
{ tab.countBadge }
|
||||
</span>
|
||||
}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
marginTop: theme.spacing(3),
|
||||
|
||||
'& label': {
|
||||
fontSize: '14px'
|
||||
fontSize: '0.875rem'
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -42,10 +42,10 @@ export const commonStyles = (theme: Theme) => {
|
||||
color: theme.palette.text01,
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
fontSize: 14,
|
||||
fontSize: '0.875rem',
|
||||
fontWeight: 400,
|
||||
height: 40,
|
||||
lineHeight: '24px',
|
||||
lineHeight: '1.5rem',
|
||||
padding: '8px 16px',
|
||||
boxSizing: 'border-box' as const,
|
||||
'& > div': {
|
||||
@@ -85,7 +85,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
|
||||
'& i': {
|
||||
display: 'inline',
|
||||
fontSize: 24
|
||||
fontSize: '1.5rem'
|
||||
},
|
||||
|
||||
'@media (hover: hover) and (pointer: fine)': {
|
||||
@@ -120,8 +120,8 @@ export const commonStyles = (theme: Theme) => {
|
||||
},
|
||||
|
||||
'.prejoin-dialog-label': {
|
||||
fontSize: '15px',
|
||||
lineHeight: '24px'
|
||||
fontSize: '1rem',
|
||||
lineHeight: '1.5rem'
|
||||
},
|
||||
|
||||
'.prejoin-dialog-label-num': {
|
||||
@@ -156,8 +156,8 @@ export const commonStyles = (theme: Theme) => {
|
||||
|
||||
'.prejoin-dialog-title': {
|
||||
display: 'inline-block',
|
||||
fontSize: '24px',
|
||||
lineHeight: '32px'
|
||||
fontSize: '1.5rem',
|
||||
lineHeight: '2rem'
|
||||
},
|
||||
|
||||
'.prejoin-dialog-icon': {
|
||||
@@ -196,7 +196,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
'.prejoin-dialog-delimiter-txt': {
|
||||
background: theme.palette.uiBackground,
|
||||
color: theme.palette.text01,
|
||||
fontSize: '11px',
|
||||
fontSize: '0.75rem',
|
||||
textTransform: 'uppercase' as const,
|
||||
padding: `0 ${theme.spacing(2)}`
|
||||
}
|
||||
@@ -212,7 +212,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
display: 'flex',
|
||||
borderRadius: 3,
|
||||
flexDirection: 'column' as const,
|
||||
fontSize: 24,
|
||||
fontSize: '1.5rem',
|
||||
height: 48,
|
||||
justifyContent: 'center',
|
||||
width: 48,
|
||||
@@ -249,7 +249,7 @@ export const commonStyles = (theme: Theme) => {
|
||||
color: theme.palette.text01,
|
||||
cursor: 'pointer',
|
||||
display: 'inline-block',
|
||||
lineHeight: '48px',
|
||||
lineHeight: '3rem',
|
||||
textAlign: 'center' as const
|
||||
},
|
||||
|
||||
|
||||
25
react/features/base/ui/functions.any.ts
Normal file
25
react/features/base/ui/functions.any.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// Base font size in pixels (standard is 16px = 1rem)
|
||||
const BASE_FONT_SIZE = 16;
|
||||
|
||||
/**
|
||||
* Converts rem to pixels.
|
||||
*
|
||||
* @param {string} remValue - The value in rem units (e.g. '0.875rem').
|
||||
* @returns {number}
|
||||
*/
|
||||
export function remToPixels(remValue: string): number {
|
||||
const numericValue = parseFloat(remValue.replace('rem', ''));
|
||||
|
||||
return Math.round(numericValue * BASE_FONT_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts pixels to rem.
|
||||
*
|
||||
* @param {number} pixels - The value in pixels.
|
||||
* @returns {string}
|
||||
* */
|
||||
export function pixelsToRem(pixels: number): string {
|
||||
return `${(pixels / BASE_FONT_SIZE).toFixed(3)}rem`;
|
||||
}
|
||||
@@ -1,7 +1,36 @@
|
||||
import { DefaultTheme } from 'react-native-paper';
|
||||
|
||||
import { remToPixels } from './functions.any';
|
||||
import { createColorTokens } from './utils';
|
||||
|
||||
export * from './functions.any';
|
||||
|
||||
/**
|
||||
* Converts all rem to pixels in an object.
|
||||
*
|
||||
* @param {Object} obj - The object to convert rem values in.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function convertRemValues(obj: any): any {
|
||||
const converted: { [key: string]: any; } = {};
|
||||
|
||||
if (typeof obj !== 'object' || obj === null) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
Object.entries(obj).forEach(([ key, value ]) => {
|
||||
if (typeof value === 'string' && value.includes('rem')) {
|
||||
converted[key] = remToPixels(value);
|
||||
} else if (typeof value === 'object' && value !== null) {
|
||||
converted[key] = convertRemValues(value);
|
||||
} else {
|
||||
converted[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a React Native Paper theme based on local UI tokens.
|
||||
*
|
||||
@@ -16,7 +45,7 @@ export function createNativeTheme({ font, colorMap, shape, spacing, typography }
|
||||
spacing,
|
||||
typography: {
|
||||
font,
|
||||
...typography
|
||||
...convertRemValues(typography)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import { ITypography, IPalette as Palette1 } from '../ui/types';
|
||||
|
||||
import { createColorTokens, createTypographyTokens } from './utils';
|
||||
|
||||
export * from './functions.any';
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
interface Palette extends Palette1 {}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
interface ITypographyType {
|
||||
fontSize: number;
|
||||
fontWeight: number; // TODO: revisit this.
|
||||
fontSize: string;
|
||||
fontWeight: 'normal' | 'bold' | 'bolder' | 'lighter' | number;
|
||||
letterSpacing: number;
|
||||
lineHeight: number;
|
||||
lineHeight: string;
|
||||
}
|
||||
|
||||
export interface IPalette {
|
||||
|
||||
@@ -130,7 +130,7 @@ export default createStyleSheet({
|
||||
*/
|
||||
notificationIcon: {
|
||||
color: 'white',
|
||||
fontSize: 25
|
||||
fontSize: '1.5rem'
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -148,7 +148,7 @@ export default createStyleSheet({
|
||||
*/
|
||||
notificationText: {
|
||||
color: 'white',
|
||||
fontSize: 13
|
||||
fontSize: '0.875rem'
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -163,3 +163,12 @@ export const SET_USER_CHAT_WIDTH = 'SET_USER_CHAT_WIDTH';
|
||||
* }
|
||||
*/
|
||||
export const SET_CHAT_IS_RESIZING = 'SET_CHAT_IS_RESIZING';
|
||||
|
||||
/**
|
||||
* The type of action sets the timestamp of the last private chat recipients list changed.
|
||||
*
|
||||
* {
|
||||
* type: NOTIFY_PRIVATE_RECIPIENTS_CHANGED
|
||||
* }
|
||||
*/
|
||||
export const NOTIFY_PRIVATE_RECIPIENTS_CHANGED = 'NOTIFY_PRIVATE_RECIPIENTS_CHANGED';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IStore } from '../app/types';
|
||||
import { getCurrentConference } from '../base/conference/functions';
|
||||
import { getLocalParticipant } from '../base/participants/functions';
|
||||
import { getLocalParticipant, getParticipantById } from '../base/participants/functions';
|
||||
import { IParticipant } from '../base/participants/types';
|
||||
import { LOBBY_CHAT_INITIALIZED } from '../lobby/constants';
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
CLEAR_MESSAGES,
|
||||
CLOSE_CHAT,
|
||||
EDIT_MESSAGE,
|
||||
NOTIFY_PRIVATE_RECIPIENTS_CHANGED,
|
||||
OPEN_CHAT,
|
||||
REMOVE_LOBBY_CHAT_PARTICIPANT,
|
||||
SEND_MESSAGE,
|
||||
@@ -170,6 +171,25 @@ export function setPrivateMessageRecipient(participant?: Object) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the sending of a private message to the supplied participantId.
|
||||
*
|
||||
* @param {string} participantId - The participant id to set the recipient to.
|
||||
* @returns {{
|
||||
* participant: IParticipant,
|
||||
* type: SET_PRIVATE_MESSAGE_RECIPIENT
|
||||
* }}
|
||||
*/
|
||||
export function setPrivateMessageRecipientById(participantId: string) {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const participant = getParticipantById(getState(), participantId);
|
||||
|
||||
if (participant) {
|
||||
dispatch(setPrivateMessageRecipient(participant));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the currently focused tab.
|
||||
*
|
||||
@@ -252,6 +272,22 @@ export function setLobbyChatActiveState(value: boolean) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the private chat recipients list changed.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function notifyPrivateRecipientsChanged() {
|
||||
return (dispatch: IStore['dispatch']) => {
|
||||
const timestamp = Date.now();
|
||||
|
||||
return dispatch({
|
||||
type: NOTIFY_PRIVATE_RECIPIENTS_CHANGED,
|
||||
payload: timestamp
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes lobby type messages.
|
||||
*
|
||||
|
||||
@@ -1,20 +1,29 @@
|
||||
import { throttle } from 'lodash-es';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { connect, useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { IconInfo, IconMessage, IconShareDoc, IconSubtitles } from '../../../base/icons/svg';
|
||||
import { getLocalParticipant } from '../../../base/participants/functions';
|
||||
import { getLocalParticipant, getRemoteParticipants } from '../../../base/participants/functions';
|
||||
import Select from '../../../base/ui/components/web/Select';
|
||||
import Tabs from '../../../base/ui/components/web/Tabs';
|
||||
import { arePollsDisabled } from '../../../conference/functions.any';
|
||||
import FileSharing from '../../../file-sharing/components/web/FileSharing';
|
||||
import { isFileSharingEnabled } from '../../../file-sharing/functions.any';
|
||||
import PollsPane from '../../../polls/components/web/PollsPane';
|
||||
import { isCCTabEnabled } from '../../../subtitles/functions.any';
|
||||
import { sendMessage, setChatIsResizing, setFocusedTab, setUserChatWidth, toggleChat } from '../../actions.web';
|
||||
import { CHAT_SIZE, ChatTabs, SMALL_WIDTH_THRESHOLD } from '../../constants';
|
||||
import {
|
||||
sendMessage,
|
||||
setChatIsResizing,
|
||||
setFocusedTab,
|
||||
setPrivateMessageRecipient,
|
||||
setPrivateMessageRecipientById,
|
||||
setUserChatWidth,
|
||||
toggleChat
|
||||
} from '../../actions.web';
|
||||
import { CHAT_SIZE, ChatTabs, OPTION_GROUPCHAT, SMALL_WIDTH_THRESHOLD } from '../../constants';
|
||||
import { getChatMaxSize } from '../../functions';
|
||||
import { IChatProps as AbstractProps } from '../../types';
|
||||
|
||||
@@ -216,6 +225,10 @@ const useStyles = makeStyles<{ _isResizing: boolean; width: number; }>()((theme,
|
||||
height: '100px',
|
||||
width: '3px',
|
||||
borderRadius: '1px'
|
||||
},
|
||||
|
||||
privateMessageRecipientsList: {
|
||||
padding: '0 16px 5px'
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -245,6 +258,34 @@ const Chat = ({
|
||||
const [ mousePosition, setMousePosition ] = useState<number | null>(null);
|
||||
const [ dragChatWidth, setDragChatWidth ] = useState<number | null>(null);
|
||||
const maxChatWidth = useSelector(getChatMaxSize);
|
||||
const notifyTimestamp = useSelector((state: IReduxState) =>
|
||||
state['features/chat'].notifyPrivateRecipientsChangedTimestamp
|
||||
);
|
||||
const {
|
||||
defaultRemoteDisplayName = 'Fellow Jitster'
|
||||
} = useSelector((state: IReduxState) => state['features/base/config']);
|
||||
const privateMessageRecipient = useSelector((state: IReduxState) => state['features/chat'].privateMessageRecipient);
|
||||
const participants = useSelector(getRemoteParticipants);
|
||||
|
||||
const options = useMemo(() => {
|
||||
const o = Array.from(participants?.values() || [])
|
||||
.filter(p => !p.fakeParticipant)
|
||||
.map(p => {
|
||||
return {
|
||||
value: p.id,
|
||||
label: p.name ?? defaultRemoteDisplayName
|
||||
};
|
||||
});
|
||||
|
||||
o.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
o.unshift({
|
||||
label: t('chat.everyone'),
|
||||
value: OPTION_GROUPCHAT
|
||||
});
|
||||
|
||||
return o;
|
||||
}, [ participants, defaultRemoteDisplayName, t, notifyTimestamp ]);
|
||||
|
||||
/**
|
||||
* Handles mouse down on the drag handle.
|
||||
@@ -376,6 +417,17 @@ const Chat = ({
|
||||
dispatch(setFocusedTab(id as ChatTabs));
|
||||
}, [ dispatch ]);
|
||||
|
||||
|
||||
const onSelectedRecipientChange = useCallback((e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const selected = e.target.value;
|
||||
|
||||
if (selected === OPTION_GROUPCHAT) {
|
||||
dispatch(setPrivateMessageRecipient());
|
||||
} else {
|
||||
dispatch(setPrivateMessageRecipientById(selected));
|
||||
}
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Returns a React Element for showing chat messages and a form to send new
|
||||
* chat messages.
|
||||
@@ -403,6 +455,12 @@ const Chat = ({
|
||||
<MessageContainer
|
||||
messages = { _messages } />
|
||||
<MessageRecipient />
|
||||
<Select
|
||||
containerClassName = { cx(classes.privateMessageRecipientsList) }
|
||||
id = 'select-chat-recipient'
|
||||
onChange = { onSelectedRecipientChange }
|
||||
options = { options }
|
||||
value = { privateMessageRecipient?.id || OPTION_GROUPCHAT } />
|
||||
<ChatInput
|
||||
onSend = { onSendMessage } />
|
||||
</div>
|
||||
@@ -454,7 +512,8 @@ const Chat = ({
|
||||
_focusedTab !== ChatTabs.CHAT && _nbUnreadMessages > 0 ? _nbUnreadMessages : undefined,
|
||||
id: ChatTabs.CHAT,
|
||||
controlsId: `${ChatTabs.CHAT}-panel`,
|
||||
icon: IconMessage
|
||||
icon: IconMessage,
|
||||
title: t('chat.tabs.chat')
|
||||
}
|
||||
];
|
||||
|
||||
@@ -464,7 +523,8 @@ const Chat = ({
|
||||
countBadge: _focusedTab !== ChatTabs.POLLS && _nbUnreadPolls > 0 ? _nbUnreadPolls : undefined,
|
||||
id: ChatTabs.POLLS,
|
||||
controlsId: `${ChatTabs.POLLS}-panel`,
|
||||
icon: IconInfo
|
||||
icon: IconInfo,
|
||||
title: t('chat.tabs.polls')
|
||||
});
|
||||
}
|
||||
|
||||
@@ -474,7 +534,8 @@ const Chat = ({
|
||||
countBadge: undefined,
|
||||
id: ChatTabs.CLOSED_CAPTIONS,
|
||||
controlsId: `${ChatTabs.CLOSED_CAPTIONS}-panel`,
|
||||
icon: IconSubtitles
|
||||
icon: IconSubtitles,
|
||||
title: t('chat.tabs.closedCaptions')
|
||||
});
|
||||
}
|
||||
|
||||
@@ -484,7 +545,8 @@ const Chat = ({
|
||||
countBadge: undefined,
|
||||
id: ChatTabs.FILE_SHARING,
|
||||
controlsId: `${ChatTabs.FILE_SHARING}-panel`,
|
||||
icon: IconShareDoc
|
||||
icon: IconShareDoc,
|
||||
title: t('chat.tabs.fileSharing')
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { translate } from '../../../base/i18n/functions';
|
||||
import { getParticipantById, getParticipantDisplayName, isPrivateChatEnabled } from '../../../base/participants/functions';
|
||||
import Popover from '../../../base/popover/components/Popover.web';
|
||||
import Message from '../../../base/react/components/web/Message';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import { MESSAGE_TYPE_LOCAL } from '../../constants';
|
||||
import { getFormattedTimestamp, getMessageText, getPrivateNoticeMessage } from '../../functions';
|
||||
import { IChatMessageProps } from '../../types';
|
||||
|
||||
@@ -16,9 +16,10 @@ import MessageMenu from './MessageMenu';
|
||||
import ReactButton from './ReactButton';
|
||||
|
||||
interface IProps extends IChatMessageProps {
|
||||
shouldDisplayChatMessageMenu: boolean;
|
||||
className?: string;
|
||||
enablePrivateChat?: boolean;
|
||||
shouldDisplayMenuOnRight?: boolean;
|
||||
state?: IReduxState;
|
||||
type: string;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles()((theme: Theme) => {
|
||||
@@ -128,7 +129,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
minHeight: '32px'
|
||||
},
|
||||
displayName: {
|
||||
...withPixelLineHeight(theme.typography.labelBold),
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.text02,
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
@@ -137,18 +138,18 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
maxWidth: '130px'
|
||||
},
|
||||
userMessage: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word'
|
||||
},
|
||||
privateMessageNotice: {
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
marginTop: theme.spacing(1)
|
||||
},
|
||||
timestamp: {
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text03,
|
||||
marginTop: theme.spacing(1),
|
||||
marginLeft: theme.spacing(1),
|
||||
@@ -190,11 +191,12 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
});
|
||||
|
||||
const ChatMessage = ({
|
||||
className = '',
|
||||
message,
|
||||
state,
|
||||
showDisplayName,
|
||||
type,
|
||||
shouldDisplayChatMessageMenu,
|
||||
shouldDisplayMenuOnRight,
|
||||
enablePrivateChat,
|
||||
knocking,
|
||||
t
|
||||
}: IProps) => {
|
||||
@@ -331,28 +333,28 @@ const ChatMessage = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className = { cx(classes.chatMessageWrapper, type) }
|
||||
className = { cx(classes.chatMessageWrapper, className) }
|
||||
id = { message.messageId }
|
||||
onMouseEnter = { handleMouseEnter }
|
||||
onMouseLeave = { handleMouseLeave }
|
||||
tabIndex = { -1 }>
|
||||
<div className = { classes.sideBySideContainer }>
|
||||
{!shouldDisplayChatMessageMenu && (
|
||||
{!shouldDisplayMenuOnRight && (
|
||||
<div className = { classes.optionsButtonContainer }>
|
||||
{isHovered && <MessageMenu
|
||||
displayName = { message.displayName }
|
||||
enablePrivateChat = { Boolean(enablePrivateChat) }
|
||||
isFromVisitor = { message.isFromVisitor }
|
||||
isLobbyMessage = { message.lobbyChat }
|
||||
message = { message.message }
|
||||
participantId = { message.participantId }
|
||||
shouldDisplayChatMessageMenu = { shouldDisplayChatMessageMenu } />}
|
||||
participantId = { message.participantId } />}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className = { cx(
|
||||
'chatmessage',
|
||||
classes.chatMessage,
|
||||
type,
|
||||
className,
|
||||
message.privateMessage && 'privatemessage',
|
||||
message.lobbyChat && !knocking && 'lobbymessage'
|
||||
) }>
|
||||
@@ -383,7 +385,7 @@ const ChatMessage = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{shouldDisplayChatMessageMenu && (
|
||||
{shouldDisplayMenuOnRight && (
|
||||
<div className = { classes.sideBySideContainer }>
|
||||
{!message.privateMessage && !message.lobbyChat && <div>
|
||||
<div className = { classes.optionsButtonContainer }>
|
||||
@@ -396,11 +398,11 @@ const ChatMessage = ({
|
||||
<div className = { classes.optionsButtonContainer }>
|
||||
{isHovered && <MessageMenu
|
||||
displayName = { message.displayName }
|
||||
enablePrivateChat = { Boolean(enablePrivateChat) }
|
||||
isFromVisitor = { message.isFromVisitor }
|
||||
isLobbyMessage = { message.lobbyChat }
|
||||
message = { message.message }
|
||||
participantId = { message.participantId }
|
||||
shouldDisplayChatMessageMenu = { shouldDisplayChatMessageMenu } />}
|
||||
participantId = { message.participantId } />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -430,8 +432,13 @@ function _mapStateToProps(state: IReduxState, { message }: IProps) {
|
||||
const enablePrivateChat = (!message.isFromVisitor || message.privateMessage)
|
||||
&& isPrivateChatEnabled(participantForCheck, state);
|
||||
|
||||
// Only the local messages appear on the right side of the chat therefore only for them the menu has to be on the
|
||||
// left side.
|
||||
const shouldDisplayMenuOnRight = message.messageType !== MESSAGE_TYPE_LOCAL;
|
||||
|
||||
return {
|
||||
shouldDisplayChatMessageMenu: enablePrivateChat,
|
||||
shouldDisplayMenuOnRight,
|
||||
enablePrivateChat,
|
||||
knocking,
|
||||
state
|
||||
};
|
||||
|
||||
@@ -71,12 +71,11 @@ const ChatMessageGroup = ({ className = '', messages }: IProps) => {
|
||||
<div className = { `${classes.messageGroup} chat-message-group ${className}` }>
|
||||
{messages.map((message, i) => (
|
||||
<ChatMessage
|
||||
className = { className }
|
||||
key = { i }
|
||||
message = { message }
|
||||
shouldDisplayChatMessageMenu = { false }
|
||||
showDisplayName = { i === 0 }
|
||||
showTimestamp = { i === messages.length - 1 }
|
||||
type = { className } />
|
||||
showTimestamp = { i === messages.length - 1 } />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconSubtitles } from '../../../base/icons/svg';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import Button from '../../../base/ui/components/web/Button';
|
||||
import { groupMessagesBySender } from '../../../base/util/messageGrouping';
|
||||
import { setRequestingSubtitles } from '../../../subtitles/actions.any';
|
||||
@@ -67,7 +66,7 @@ const useStyles = makeStyles()(theme => {
|
||||
}
|
||||
},
|
||||
emptyState: {
|
||||
...withPixelLineHeight(theme.typography.bodyLongBold),
|
||||
...theme.typography.bodyLongBold,
|
||||
color: theme.palette.text02
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,11 +16,11 @@ import { handleLobbyChatInitialized, openChat } from '../../actions.web';
|
||||
export interface IProps {
|
||||
className?: string;
|
||||
displayName?: string;
|
||||
enablePrivateChat: boolean;
|
||||
isFromVisitor?: boolean;
|
||||
isLobbyMessage: boolean;
|
||||
message: string;
|
||||
participantId: string;
|
||||
shouldDisplayChatMessageMenu: boolean;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
@@ -48,7 +48,7 @@ const useStyles = makeStyles()(theme => {
|
||||
color: 'white',
|
||||
padding: '4px 8px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '12px',
|
||||
fontSize: '0.75rem',
|
||||
zIndex: 1000,
|
||||
opacity: 0,
|
||||
transition: 'opacity 0.3s ease-in-out',
|
||||
@@ -60,7 +60,7 @@ const useStyles = makeStyles()(theme => {
|
||||
};
|
||||
});
|
||||
|
||||
const MessageMenu = ({ message, participantId, isFromVisitor, isLobbyMessage, shouldDisplayChatMessageMenu, displayName }: IProps) => {
|
||||
const MessageMenu = ({ message, participantId, isFromVisitor, isLobbyMessage, enablePrivateChat, displayName }: IProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const { classes, cx } = useStyles();
|
||||
const { t } = useTranslation();
|
||||
@@ -130,7 +130,7 @@ const MessageMenu = ({ message, participantId, isFromVisitor, isLobbyMessage, sh
|
||||
|
||||
const popoverContent = (
|
||||
<div className = { classes.menuPanel }>
|
||||
{shouldDisplayChatMessageMenu && (
|
||||
{enablePrivateChat && (
|
||||
<div
|
||||
className = { classes.menuItem }
|
||||
onClick = { handlePrivateClick }>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { connect } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IconCloseLarge } from '../../../base/icons/svg';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import Button from '../../../base/ui/components/web/Button';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants.any';
|
||||
import {
|
||||
@@ -24,7 +23,7 @@ const useStyles = makeStyles()(theme => {
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.support05,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01
|
||||
},
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconArrowDown } from '../../../base/icons/svg';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.web';
|
||||
|
||||
export interface INewMessagesButtonProps extends WithTranslation {
|
||||
@@ -53,7 +52,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
textContainer: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text04,
|
||||
paddingLeft: '8px'
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { getParticipantDisplayName } from '../../../base/participants/functions';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import { ISubtitle } from '../../../subtitles/types';
|
||||
|
||||
/**
|
||||
@@ -39,7 +38,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
messageHeader: {
|
||||
...withPixelLineHeight(theme.typography.labelBold),
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.text02,
|
||||
whiteSpace: 'nowrap',
|
||||
textOverflow: 'ellipsis',
|
||||
@@ -49,14 +48,14 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
messageText: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word'
|
||||
},
|
||||
|
||||
timestamp: {
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text03,
|
||||
marginTop: theme.spacing(1)
|
||||
},
|
||||
|
||||
@@ -55,3 +55,5 @@ export const TIMESTAMP_FORMAT = 'H:mm';
|
||||
* The namespace for system messages.
|
||||
*/
|
||||
export const MESSAGE_TYPE_SYSTEM = 'system_chat_message';
|
||||
|
||||
export const OPTION_GROUPCHAT = 'groupchat';
|
||||
|
||||
@@ -15,11 +15,13 @@ import {
|
||||
JitsiConferenceErrors,
|
||||
JitsiConferenceEvents
|
||||
} from '../base/lib-jitsi-meet';
|
||||
import { PARTICIPANT_JOINED, PARTICIPANT_LEFT, PARTICIPANT_UPDATED } from '../base/participants/actionTypes';
|
||||
import {
|
||||
getLocalParticipant,
|
||||
getParticipantById,
|
||||
getParticipantDisplayName
|
||||
} from '../base/participants/functions';
|
||||
import { IParticipant } from '../base/participants/types';
|
||||
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
|
||||
import StateListenerRegistry from '../base/redux/StateListenerRegistry';
|
||||
import { playSound, registerSound, unregisterSound } from '../base/sounds/actions';
|
||||
@@ -43,7 +45,14 @@ import {
|
||||
SEND_REACTION,
|
||||
SET_FOCUSED_TAB
|
||||
} from './actionTypes';
|
||||
import { addMessage, addMessageReaction, clearMessages, closeChat, setPrivateMessageRecipient } from './actions.any';
|
||||
import {
|
||||
addMessage,
|
||||
addMessageReaction,
|
||||
clearMessages,
|
||||
closeChat,
|
||||
notifyPrivateRecipientsChanged,
|
||||
setPrivateMessageRecipient
|
||||
} from './actions.any';
|
||||
import { ChatPrivacyDialog } from './components';
|
||||
import {
|
||||
ChatTabs,
|
||||
@@ -198,6 +207,19 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
break;
|
||||
}
|
||||
|
||||
case PARTICIPANT_JOINED:
|
||||
case PARTICIPANT_LEFT:
|
||||
case PARTICIPANT_UPDATED: {
|
||||
if (_shouldNotifyPrivateRecipientsChanged(store, action)) {
|
||||
const result = next(action);
|
||||
|
||||
dispatch(notifyPrivateRecipientsChanged());
|
||||
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SEND_MESSAGE: {
|
||||
const state = store.getState();
|
||||
const conference = getCurrentConference(state);
|
||||
@@ -303,6 +325,27 @@ StateListenerRegistry.register(
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Checks whether a notification for private chat recipients is needed.
|
||||
*
|
||||
* @param {IStore} store - The redux store.
|
||||
* @param {{ participant: IParticipant, type: string }} action - The action.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function _shouldNotifyPrivateRecipientsChanged(
|
||||
store: IStore, action: { participant: IParticipant; type: string; }
|
||||
) {
|
||||
const { type, participant } = action;
|
||||
|
||||
if ([ PARTICIPANT_LEFT, PARTICIPANT_JOINED ].includes(type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const { id, name } = participant;
|
||||
|
||||
return name !== getParticipantDisplayName(store, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers listener for {@link JitsiConferenceEvents.MESSAGE_RECEIVED} that
|
||||
* will perform various chat related activities.
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
CLEAR_MESSAGES,
|
||||
CLOSE_CHAT,
|
||||
EDIT_MESSAGE,
|
||||
NOTIFY_PRIVATE_RECIPIENTS_CHANGED,
|
||||
OPEN_CHAT,
|
||||
REMOVE_LOBBY_CHAT_PARTICIPANT,
|
||||
SET_CHAT_IS_RESIZING,
|
||||
@@ -26,6 +27,7 @@ const DEFAULT_STATE = {
|
||||
groupChatWithPermissions: false,
|
||||
isOpen: false,
|
||||
messages: [],
|
||||
notifyPrivateRecipientsChangedTimestamp: undefined,
|
||||
reactions: {},
|
||||
nbUnreadMessages: 0,
|
||||
privateMessageRecipient: undefined,
|
||||
@@ -52,6 +54,7 @@ export interface IChatState {
|
||||
} | ILocalParticipant;
|
||||
messages: IMessage[];
|
||||
nbUnreadMessages: number;
|
||||
notifyPrivateRecipientsChangedTimestamp?: number;
|
||||
privateMessageRecipient?: IParticipant | IVisitorChatParticipant;
|
||||
width: {
|
||||
current: number;
|
||||
@@ -262,6 +265,11 @@ ReducerRegistry.register<IChatState>('features/chat', (state = DEFAULT_STATE, ac
|
||||
isResizing: action.resizing
|
||||
};
|
||||
}
|
||||
case NOTIFY_PRIVATE_RECIPIENTS_CHANGED:
|
||||
return {
|
||||
...state,
|
||||
notifyPrivateRecipientsChangedTimestamp: action.payload
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
|
||||
@@ -62,11 +62,6 @@ export interface IChatMessageProps extends WithTranslation {
|
||||
*/
|
||||
message: IMessage;
|
||||
|
||||
/**
|
||||
* Whether the chat message menu is visible or not.
|
||||
*/
|
||||
shouldDisplayChatMessageMenu?: boolean;
|
||||
|
||||
/**
|
||||
* Whether or not the avatar image of the participant which sent the message
|
||||
* should be displayed.
|
||||
|
||||
@@ -579,7 +579,7 @@ function _mapStateToProps(state: IReduxState, _ownProps: any) {
|
||||
const { startCarMode } = state['features/base/settings'];
|
||||
const { enabled: audioOnlyEnabled } = state['features/base/audio-only'];
|
||||
const brandingStyles = backgroundColor ? {
|
||||
backgroundColor
|
||||
background: backgroundColor
|
||||
} : undefined;
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import { IDisplayProps } from '../ConferenceTimer';
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
timer: {
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text01,
|
||||
padding: '6px 8px',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||
|
||||
@@ -11,7 +11,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
text: {
|
||||
fontSize: '20px'
|
||||
fontSize: '1.25rem'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -4,13 +4,12 @@ import { useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { getConferenceName } from '../../../base/conference/functions';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import Tooltip from '../../../base/tooltip/components/Tooltip';
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
...withPixelLineHeight(theme.typography.bodyLongRegular),
|
||||
...theme.typography.bodyLongRegular,
|
||||
color: theme.palette.text01,
|
||||
padding: '2px 16px',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.6)',
|
||||
|
||||
@@ -8,7 +8,6 @@ import { MIN_ASSUMED_BANDWIDTH_BPS } from '../../../../../modules/API/constants'
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { setAssumedBandwidthBps as saveAssumedBandwidthBps } from '../../../base/conference/actions';
|
||||
import { IconInfoCircle } from '../../../base/icons/svg';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import Dialog from '../../../base/ui/components/web/Dialog';
|
||||
import Input from '../../../base/ui/components/web/Input';
|
||||
|
||||
@@ -20,7 +19,7 @@ const useStyles = makeStyles()(theme => {
|
||||
|
||||
info: {
|
||||
background: theme.palette.ui01,
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
marginTop: theme.spacing(2)
|
||||
},
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
getVirtualScreenshareParticipantTrack
|
||||
} from '../../../base/tracks/functions';
|
||||
import { ITrack } from '../../../base/tracks/types';
|
||||
import { pixelsToRem } from '../../../base/ui/functions.any';
|
||||
import {
|
||||
isTrackStreamingStatusInactive,
|
||||
isTrackStreamingStatusInterrupted
|
||||
@@ -355,7 +356,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<IProps, IState> {
|
||||
|
||||
return (
|
||||
<div
|
||||
style = {{ fontSize: iconSize }}>
|
||||
style = {{ fontSize: pixelsToRem(iconSize) }}>
|
||||
<span className = 'sr-only'>{ t('videothumbnail.connectionInfo') }</span>
|
||||
<ConnectionIndicatorIcon
|
||||
classes = { classes }
|
||||
|
||||
@@ -222,7 +222,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
connectionStatsTable: {
|
||||
'&, & > table': {
|
||||
fontSize: '12px',
|
||||
fontSize: '0.75rem',
|
||||
fontWeight: 400,
|
||||
|
||||
'& td': {
|
||||
|
||||
@@ -12,7 +12,6 @@ import { getLegalUrls } from '../../base/config/functions.any';
|
||||
import { isSupportedBrowser } from '../../base/environment/environment';
|
||||
import { translate, translateToHTML } from '../../base/i18n/functions';
|
||||
import Platform from '../../base/react/Platform.web';
|
||||
import { withPixelLineHeight } from '../../base/styles/functions.web';
|
||||
import Button from '../../base/ui/components/web/Button';
|
||||
import { BUTTON_TYPES } from '../../base/ui/constants.any';
|
||||
import {
|
||||
@@ -46,15 +45,15 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
launchingMeetingLabel: {
|
||||
marginBottom: 16,
|
||||
...withPixelLineHeight(theme.typography.heading4)
|
||||
...theme.typography.heading4
|
||||
},
|
||||
roomName: {
|
||||
marginBottom: 32,
|
||||
...withPixelLineHeight(theme.typography.heading5)
|
||||
...theme.typography.heading5
|
||||
},
|
||||
descriptionLabel: {
|
||||
marginBottom: 32,
|
||||
...withPixelLineHeight(theme.typography.bodyLongRegular)
|
||||
...theme.typography.bodyLongRegular
|
||||
},
|
||||
buttonsContainer: {
|
||||
display: 'flex',
|
||||
@@ -71,7 +70,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
label: {
|
||||
marginTop: 40,
|
||||
...withPixelLineHeight(theme.typography.labelRegular),
|
||||
...theme.typography.labelRegular,
|
||||
color: theme.palette.text02,
|
||||
'& a': {
|
||||
color: theme.palette.link01
|
||||
|
||||
@@ -12,7 +12,6 @@ import { IDeeplinkingConfig, IDeeplinkingMobileConfig } from '../../base/config/
|
||||
import { isSupportedMobileBrowser } from '../../base/environment/environment';
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
import Platform from '../../base/react/Platform.web';
|
||||
import { withPixelLineHeight } from '../../base/styles/functions.web';
|
||||
import Button from '../../base/ui/components/web/Button';
|
||||
import DialInSummary from '../../invite/components/dial-in-summary/web/DialInSummary';
|
||||
import { openWebApp } from '../actions';
|
||||
@@ -51,10 +50,10 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
marginTop: 24,
|
||||
textAlign: 'center',
|
||||
marginBottom: 32,
|
||||
...withPixelLineHeight(theme.typography.heading5)
|
||||
...theme.typography.heading5
|
||||
},
|
||||
roomNameLabel: {
|
||||
...withPixelLineHeight(theme.typography.bodyLongRegularLarge)
|
||||
...theme.typography.bodyLongRegularLarge
|
||||
},
|
||||
joinMeetWrapper: {
|
||||
marginTop: 24,
|
||||
@@ -63,7 +62,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
labelDescription: {
|
||||
textAlign: 'center',
|
||||
marginTop: 16,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
|
||||
...theme.typography.bodyShortRegularLarge
|
||||
},
|
||||
linkWrapper: {
|
||||
display: 'flex',
|
||||
@@ -74,7 +73,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
linkLabel: {
|
||||
color: theme.palette.link01,
|
||||
...withPixelLineHeight(theme.typography.bodyLongBoldLarge)
|
||||
...theme.typography.bodyLongBoldLarge
|
||||
},
|
||||
supportedBrowserContent: {
|
||||
marginTop: 16,
|
||||
@@ -84,7 +83,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
justifyContent: 'center'
|
||||
},
|
||||
labelOr: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
|
||||
...theme.typography.bodyShortRegularLarge
|
||||
},
|
||||
separator: {
|
||||
marginTop: '32px',
|
||||
|
||||
@@ -5,7 +5,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import Icon from '../../base/icons/components/Icon';
|
||||
import { IconTrash } from '../../base/icons/svg';
|
||||
import { withPixelLineHeight } from '../../base/styles/functions.web';
|
||||
import Button from '../../base/ui/components/web/Button';
|
||||
import { BUTTON_TYPES } from '../../base/ui/constants.any';
|
||||
import { closeHidDevice, requestHidDevice } from '../../web-hid/actions';
|
||||
@@ -20,7 +19,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
label: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text01,
|
||||
marginBottom: theme.spacing(2)
|
||||
},
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { withPixelLineHeight } from '../../base/styles/functions.web';
|
||||
import Select from '../../base/ui/components/web/Select';
|
||||
|
||||
/**
|
||||
@@ -60,7 +59,7 @@ const useStyles = makeStyles()(theme => {
|
||||
backgroundColor: theme.palette.uiBackground,
|
||||
padding: '10px 16px',
|
||||
textAlign: 'center',
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
border: `1px solid ${theme.palette.ui03}`
|
||||
}
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
getParticipantDisplayName
|
||||
} from '../../../base/participants/functions';
|
||||
import { updateSettings } from '../../../base/settings/actions';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import Tooltip from '../../../base/tooltip/components/Tooltip';
|
||||
import { getIndicatorsTooltipPosition } from '../../../filmstrip/functions.web';
|
||||
import { appendSuffix } from '../../functions';
|
||||
@@ -49,7 +48,7 @@ interface IProps {
|
||||
const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
displayName: {
|
||||
...withPixelLineHeight(theme.typography.labelBold),
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.text01,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
@@ -62,7 +61,7 @@ const useStyles = makeStyles()(theme => {
|
||||
background: 'none',
|
||||
boxShadow: 'none',
|
||||
padding: 0,
|
||||
...withPixelLineHeight(theme.typography.labelBold),
|
||||
...theme.typography.labelBold,
|
||||
color: theme.palette.text01
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { remToPixels } from '../../../base/ui/functions.any';
|
||||
|
||||
import { DISPLAY_NAME_VERTICAL_PADDING } from './styles';
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
@@ -13,7 +15,7 @@ const useStyles = makeStyles()(theme => {
|
||||
color: text01,
|
||||
maxWidth: '50%',
|
||||
overflow: 'hidden',
|
||||
padding: `${DISPLAY_NAME_VERTICAL_PADDING / 2}px 16px`,
|
||||
padding: `${remToPixels(`${DISPLAY_NAME_VERTICAL_PADDING}rem`) / 2}px 16px`,
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap'
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { getParticipantDisplayName, isScreenShareParticipant } from '../../../base/participants/functions';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import { getVideospaceFloatingElementsBottomSpacing } from '../../../base/ui/functions.web';
|
||||
import { getLargeVideoParticipant } from '../../../large-video/functions';
|
||||
import {
|
||||
@@ -38,8 +37,8 @@ const useStyles = makeStyles<IOptions, 'screenSharing'>()((theme, options: IOpti
|
||||
// the clientHeight will be 960px if there are some titlebars, toolbars, addressbars, etc visible.For any other
|
||||
// screen size we will decrease/increase the font size based on the screen size.
|
||||
|
||||
typography.fontSize = scaleFontProperty(clientHeight, getStageParticipantFontSizeRange(theme));
|
||||
typography.lineHeight = getStageParticipantNameLabelLineHeight(theme, clientHeight);
|
||||
typography.fontSize = `${scaleFontProperty(clientHeight, getStageParticipantFontSizeRange(theme))}rem`;
|
||||
typography.lineHeight = `${getStageParticipantNameLabelLineHeight(theme, clientHeight)}rem`;
|
||||
}
|
||||
|
||||
const toolbarVisibleTransitionProps = getTransitionParamsForElementsAboveToolbox(true);
|
||||
@@ -53,7 +52,7 @@ const useStyles = makeStyles<IOptions, 'screenSharing'>()((theme, options: IOpti
|
||||
|
||||
return {
|
||||
badgeContainer: {
|
||||
...withPixelLineHeight(typography),
|
||||
...typography,
|
||||
alignItems: 'center',
|
||||
display: 'inline-flex',
|
||||
justifyContent: 'center',
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Theme } from '@mui/material';
|
||||
/**
|
||||
* The vertical padding for the display name.
|
||||
*/
|
||||
export const DISPLAY_NAME_VERTICAL_PADDING = 4;
|
||||
export const DISPLAY_NAME_VERTICAL_PADDING = 0.25;
|
||||
|
||||
/**
|
||||
* Returns the typography for stage participant display name badge.
|
||||
@@ -46,12 +46,12 @@ export function getStageParticipantLineHeightRange(theme: Theme) {
|
||||
*
|
||||
* @param {Theme} theme - The current theme.
|
||||
* @param {number} clientHeight - The height of the visible area.
|
||||
* @returns {number}
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getStageParticipantNameLabelHeight(theme: Theme, clientHeight?: number) {
|
||||
export function getStageParticipantNameLabelHeight(theme: Theme, clientHeight?: number): string {
|
||||
const lineHeight = getStageParticipantNameLabelLineHeight(theme, clientHeight);
|
||||
|
||||
return lineHeight + DISPLAY_NAME_VERTICAL_PADDING;
|
||||
return `${lineHeight + DISPLAY_NAME_VERTICAL_PADDING}rem`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,13 +59,18 @@ export function getStageParticipantNameLabelHeight(theme: Theme, clientHeight?:
|
||||
*
|
||||
* @param {Theme} theme - The current theme.
|
||||
* @param {number} clientHeight - The height of the visible area.
|
||||
* @returns {number}
|
||||
* @returns {number} - Value in rem units.
|
||||
*/
|
||||
export function getStageParticipantNameLabelLineHeight(theme: Theme, clientHeight?: number) {
|
||||
export function getStageParticipantNameLabelLineHeight(theme: Theme, clientHeight?: number): number {
|
||||
return scaleFontProperty(clientHeight, getStageParticipantLineHeightRange(theme));
|
||||
}
|
||||
|
||||
interface ILimits {
|
||||
max: string;
|
||||
min: string;
|
||||
}
|
||||
|
||||
interface INumberLimits {
|
||||
max: number;
|
||||
min: number;
|
||||
}
|
||||
@@ -85,22 +90,34 @@ const DEFAULT_CLIENT_HEIGHT_LIMITS = {
|
||||
*
|
||||
* @param {number|undefined} screenHeight - The current screen height.
|
||||
* @param {ILimits} propValuesLimits - The max and min value for the font property that we are scaling.
|
||||
* @param {ILimits} screenHeightLimits - The max and min value for screen height.
|
||||
* @returns {number} - The scaled prop value.
|
||||
* @param {INumberLimits} screenHeightLimits - The max and min value for screen height.
|
||||
* @returns {number} - The scaled prop value in rem units.
|
||||
*/
|
||||
export function scaleFontProperty(
|
||||
screenHeight: number | undefined,
|
||||
propValuesLimits: ILimits,
|
||||
screenHeightLimits: ILimits = DEFAULT_CLIENT_HEIGHT_LIMITS) {
|
||||
if (typeof screenHeight !== 'number') {
|
||||
return propValuesLimits.max;
|
||||
}
|
||||
|
||||
screenHeightLimits: INumberLimits = DEFAULT_CLIENT_HEIGHT_LIMITS): number {
|
||||
const { max: maxPropSize, min: minPropSize } = propValuesLimits;
|
||||
const { max: maxHeight, min: minHeight } = screenHeightLimits;
|
||||
const propSizePerPxHeight = (maxPropSize - minPropSize) / (maxHeight - minHeight);
|
||||
const numericalMinRem = parseFloat(minPropSize);
|
||||
const numericalMaxRem = parseFloat(maxPropSize);
|
||||
|
||||
return Math.round(
|
||||
(Math.max(Math.min(screenHeight, maxHeight), minHeight) - minHeight) * propSizePerPxHeight
|
||||
) + minPropSize;
|
||||
if (typeof screenHeight !== 'number') {
|
||||
return numericalMaxRem;
|
||||
}
|
||||
|
||||
// Calculate how much the 'rem' value changes per pixel of screen height.
|
||||
// (max 'rem' - min 'rem') / (max screen height in px - min screen height in px)
|
||||
const propSizeRemPerPxHeight = (numericalMaxRem - numericalMinRem) / (maxHeight - minHeight);
|
||||
|
||||
// Clamp the screenHeight to be within the defined minHeight and maxHeight.
|
||||
const clampedScreenHeightPx = Math.max(Math.min(screenHeight, maxHeight), minHeight);
|
||||
|
||||
// Calculate the scaled 'rem' value:
|
||||
// Start with the base min 'rem' value.
|
||||
// Add the scaled portion: (how far the current screen height is from the min height) * (rem change per pixel).
|
||||
// (clampedScreenHeightPx - minHeigh) gives the effective height within the range.
|
||||
const calculatedRemValue = (clampedScreenHeightPx - minHeight) * propSizeRemPerPxHeight + numericalMinRem;
|
||||
|
||||
return parseFloat(calculatedRemValue.toFixed(3));
|
||||
}
|
||||
|
||||
@@ -4,6 +4,29 @@ import { adaptV4Theme, createTheme } from '@mui/material/styles';
|
||||
import { breakpoints, colorMap, font, shape, spacing, typography } from '../base/ui/Tokens';
|
||||
import { createColorTokens } from '../base/ui/utils';
|
||||
|
||||
const DEFAULT_FONT_SIZE = 16;
|
||||
|
||||
/**
|
||||
* Converts unitless fontSize and lineHeight values in a typography style object to rem units.
|
||||
* Backward compatibility: This conversion supports custom themes that may still override
|
||||
* typography values with numeric (pixel-based) values instead of rem strings.
|
||||
*
|
||||
* @param {Object} style - The typography style object to convert.
|
||||
* @returns {void}
|
||||
*/
|
||||
function convertTypographyToRem(style: any): void {
|
||||
if (style) {
|
||||
// Support for backward compatibility with numeric font size overrides
|
||||
if (typeof style.fontSize === 'number') {
|
||||
style.fontSize = `${style.fontSize / DEFAULT_FONT_SIZE}rem`;
|
||||
}
|
||||
// Support for backward compatibility with numeric line height overrides
|
||||
if (typeof style.lineHeight === 'number') {
|
||||
style.lineHeight = `${style.lineHeight / DEFAULT_FONT_SIZE}rem`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates MUI branding theme based on the custom theme json.
|
||||
*
|
||||
@@ -38,6 +61,12 @@ export function createMuiBrandingTheme(customTheme: Theme) {
|
||||
|
||||
if (customTypography) {
|
||||
overwriteRecurrsive(newTypography, customTypography);
|
||||
|
||||
// Convert typography values to rem units in case some of the overrides are using the legacy unitless format.
|
||||
// Note: We do the conversion onlt when we do have custom typography overrides. All other values are already in rem.
|
||||
for (const variant of Object.keys(newTypography)) {
|
||||
convertTypographyToRem((newTypography as Record<string, any>)[variant]);
|
||||
}
|
||||
}
|
||||
|
||||
const newBreakpoints = { ...breakpoints };
|
||||
|
||||
@@ -52,7 +52,7 @@ const useStyles = makeStyles()(() => {
|
||||
},
|
||||
|
||||
description: {
|
||||
fontSize: '13px',
|
||||
fontSize: '0.875rem',
|
||||
margin: '15px 0'
|
||||
},
|
||||
|
||||
@@ -62,7 +62,7 @@ const useStyles = makeStyles()(() => {
|
||||
marginTop: '15px',
|
||||
|
||||
'& label': {
|
||||
fontSize: '14px',
|
||||
fontSize: '0.875rem',
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ const useStyles = makeStyles()(() => {
|
||||
margin: '16px'
|
||||
},
|
||||
emoji: {
|
||||
fontSize: '40px',
|
||||
fontSize: '2.5rem',
|
||||
margin: '12px'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,7 +10,6 @@ import { IJitsiConference } from '../../base/conference/reducer';
|
||||
import { isMobileBrowser } from '../../base/environment/utils';
|
||||
import Icon from '../../base/icons/components/Icon';
|
||||
import { IconFavorite, IconFavoriteSolid } from '../../base/icons/svg';
|
||||
import { withPixelLineHeight } from '../../base/styles/functions.web';
|
||||
import Dialog from '../../base/ui/components/web/Dialog';
|
||||
import Input from '../../base/ui/components/web/Input';
|
||||
import { cancelFeedback, submitFeedback } from '../actions.web';
|
||||
@@ -31,7 +30,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
ratingLabel: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortBold),
|
||||
...theme.typography.bodyShortBold,
|
||||
color: theme.palette.text01,
|
||||
marginBottom: theme.spacing(2),
|
||||
height: '20px'
|
||||
@@ -61,7 +60,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
title: {
|
||||
fontSize: '16px'
|
||||
fontSize: '1rem'
|
||||
},
|
||||
|
||||
details: {
|
||||
|
||||
@@ -7,7 +7,6 @@ import { IReduxState } from '../../../app/types';
|
||||
import Avatar from '../../../base/avatar/components/Avatar';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconCloudUpload, IconDownload, IconTrash } from '../../../base/icons/svg';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.web';
|
||||
import Button from '../../../base/ui/components/web/Button';
|
||||
import { BUTTON_TYPES } from '../../../base/ui/constants.web';
|
||||
@@ -110,8 +109,11 @@ const useStyles = makeStyles()(theme => {
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(2),
|
||||
gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))',
|
||||
listStyleType: 'none',
|
||||
marginBottom: theme.spacing(8),
|
||||
marginTop: 0,
|
||||
overflowY: 'auto',
|
||||
padding: 0,
|
||||
zIndex: 1
|
||||
},
|
||||
|
||||
@@ -161,7 +163,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
noFilesText: {
|
||||
...withPixelLineHeight(theme.typography.bodyLongBold),
|
||||
...theme.typography.bodyLongBold,
|
||||
color: theme.palette.text02,
|
||||
padding: '0 24px',
|
||||
textAlign: 'center'
|
||||
@@ -207,6 +209,7 @@ const FileSharing = () => {
|
||||
const { classes } = useStyles();
|
||||
const [ isDragging, setIsDragging ] = useState(false);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const uploadButtonRef = useRef<HTMLButtonElement>(null);
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const store = useStore();
|
||||
@@ -235,6 +238,7 @@ const FileSharing = () => {
|
||||
if (e.target.files) {
|
||||
processFiles(e.target.files as FileList, store);
|
||||
e.target.value = ''; // Reset the input value to allow re-uploading the same file
|
||||
uploadButtonRef.current?.focus();
|
||||
}
|
||||
}, [ processFiles ]);
|
||||
|
||||
@@ -253,6 +257,8 @@ const FileSharing = () => {
|
||||
}, []);
|
||||
|
||||
const handleKeyPress = useCallback((e: React.KeyboardEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
fileInputRef.current?.click();
|
||||
}
|
||||
@@ -270,19 +276,15 @@ const FileSharing = () => {
|
||||
onDragEnter = { handleDragEnter }
|
||||
onDragLeave = { handleDragLeave }
|
||||
onDragOver = { handleDragOver }
|
||||
onDrop = { handleDrop }
|
||||
role = 'button'
|
||||
tabIndex = { 0 }>
|
||||
<input
|
||||
className = { classes.hiddenInput }
|
||||
multiple = { true }
|
||||
onChange = { handleFileSelect }
|
||||
ref = { fileInputRef }
|
||||
type = 'file' />
|
||||
</div>
|
||||
onDrop = { handleDrop } />
|
||||
{
|
||||
sortedFiles.length === 0 && (
|
||||
<div className = { classes.noFilesContainer }>
|
||||
<div
|
||||
className = { classes.noFilesContainer }
|
||||
onClick = { handleClick }
|
||||
onKeyUp = { handleKeyPress }
|
||||
role = 'button'
|
||||
tabIndex = { 0 }>
|
||||
<Icon
|
||||
className = { classes.uploadIcon }
|
||||
color = { BaseTheme.palette.icon03 }
|
||||
@@ -294,15 +296,22 @@ const FileSharing = () => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<input
|
||||
className = { classes.hiddenInput }
|
||||
multiple = { true }
|
||||
onChange = { handleFileSelect }
|
||||
ref = { fileInputRef }
|
||||
tabIndex = { -1 }
|
||||
type = 'file' />
|
||||
</>
|
||||
)
|
||||
}
|
||||
{
|
||||
sortedFiles.length > 0 && (
|
||||
<div className = { classes.fileList }>
|
||||
<ul className = { classes.fileList }>
|
||||
{
|
||||
sortedFiles.map(file => (
|
||||
<div
|
||||
<li
|
||||
className = { classes.fileItem }
|
||||
key = { file.fileId }
|
||||
title = { file.fileName }>
|
||||
@@ -364,17 +373,25 @@ const FileSharing = () => {
|
||||
}
|
||||
{
|
||||
(file.progress ?? 100) < 100 && (
|
||||
<div className = { classes.progressBar }>
|
||||
<>
|
||||
<div
|
||||
className = { classes.progressFill }
|
||||
style = {{ width: `${file.progress}%` }} />
|
||||
</div>
|
||||
aria-label = { t('fileSharing.fileUploadProgress') }
|
||||
aria-valuemax = { 100 }
|
||||
aria-valuemin = { 0 }
|
||||
aria-valuenow = { file.progress }
|
||||
className = { classes.progressBar }
|
||||
role = 'progressbar'>
|
||||
<div
|
||||
className = { classes.progressFill }
|
||||
style = {{ width: `${file.progress}%` }} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
{
|
||||
@@ -385,6 +402,7 @@ const FileSharing = () => {
|
||||
labelKey = { 'fileSharing.uploadFile' }
|
||||
onClick = { handleClick }
|
||||
onKeyPress = { handleKeyPress }
|
||||
ref = { uploadButtonRef }
|
||||
type = { BUTTON_TYPES.PRIMARY } />
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
|
||||
import { getLocalParticipant, getParticipantDisplayName } from '../base/participants/functions';
|
||||
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
|
||||
import StateListenerRegistry from '../base/redux/StateListenerRegistry';
|
||||
import { showErrorNotification } from '../notifications/actions';
|
||||
import { showErrorNotification, showSuccessNotification } from '../notifications/actions';
|
||||
import { NOTIFICATION_TIMEOUT_TYPE, NOTIFICATION_TYPE } from '../notifications/constants';
|
||||
|
||||
import { DOWNLOAD_FILE, REMOVE_FILE, UPLOAD_FILES, _FILE_LIST_RECEIVED, _FILE_REMOVED } from './actionTypes';
|
||||
@@ -229,6 +229,9 @@ function uploadFile(file: File, store: IStore, token: string): void {
|
||||
const fileSharingHandler = conference?.getFileSharing();
|
||||
|
||||
fileSharingHandler.addFile(fileMetadata);
|
||||
store.dispatch(showSuccessNotification({
|
||||
titleKey: 'fileSharing.fileUploadedSuccessfully'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.SHORT));
|
||||
} else {
|
||||
handleError();
|
||||
}
|
||||
|
||||
@@ -253,9 +253,13 @@ class Filmstrip extends PureComponent<IProps> {
|
||||
const filmstripStyle = isNarrowAspectRatio ? styles.filmstripNarrow : styles.filmstripWide;
|
||||
const { height, width } = this._getDimensions();
|
||||
const { height: thumbnailHeight, width: thumbnailWidth, margin } = styles.thumbnail;
|
||||
const initialNumToRender = Math.ceil(isNarrowAspectRatio
|
||||
? width / (thumbnailWidth + (2 * margin))
|
||||
: height / (thumbnailHeight + (2 * margin))
|
||||
const initialNumToRender = Math.max(
|
||||
0,
|
||||
Math.ceil(
|
||||
isNarrowAspectRatio
|
||||
? width / (thumbnailWidth + (2 * margin))
|
||||
: height / (thumbnailHeight + (2 * margin))
|
||||
)
|
||||
);
|
||||
let participants;
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ function styles(theme: Theme, props: IProps) {
|
||||
},
|
||||
|
||||
toggleFilmstripButton: {
|
||||
fontSize: '14px',
|
||||
fontSize: '0.875rem',
|
||||
lineHeight: 1.2,
|
||||
textAlign: 'center' as const,
|
||||
background: 'transparent',
|
||||
|
||||
@@ -71,7 +71,7 @@ const PinnedIndicator = ({
|
||||
id = { `pin-indicator-${participantId}` }>
|
||||
<BaseIndicator
|
||||
icon = { IconPin }
|
||||
iconSize = { `${iconSize}px` }
|
||||
iconSize = { iconSize }
|
||||
tooltipKey = 'pinnedParticipant'
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,7 @@ const RaisedHandIndicator = ({
|
||||
<BaseIndicator
|
||||
icon = { IconRaiseHand }
|
||||
iconColor = { theme.palette.uiBackground }
|
||||
iconSize = { `${iconSize}px` }
|
||||
iconSize = { iconSize }
|
||||
tooltipKey = 'raisedHand'
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { WithTranslation } from 'react-i18next';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { translate } from '../../../../base/i18n/functions';
|
||||
import { withPixelLineHeight } from '../../../../base/styles/functions.web';
|
||||
import { UPGRADE_OPTIONS_LINK, UPGRADE_OPTIONS_TEXT } from '../../../constants';
|
||||
|
||||
const useStyles = makeStyles()(theme => {
|
||||
@@ -15,7 +14,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
limitInfo: {
|
||||
color: theme.palette.text.primary,
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular)
|
||||
...theme.typography.bodyShortRegular
|
||||
},
|
||||
link: {
|
||||
color: `${theme.palette.text.primary} !important`,
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useSelector } from 'react-redux';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { IReduxState } from '../../../../app/types';
|
||||
import { withPixelLineHeight } from '../../../../base/styles/functions.web';
|
||||
import { getDialInfoPageURL, hasMultipleNumbers } from '../../../functions';
|
||||
|
||||
import DialInNumber from './DialInNumber';
|
||||
@@ -22,12 +21,12 @@ const useStyles = makeStyles()(theme => {
|
||||
return {
|
||||
container: {
|
||||
'& .info-label': {
|
||||
...withPixelLineHeight(theme.typography.bodyLongBold)
|
||||
...theme.typography.bodyLongBold
|
||||
}
|
||||
},
|
||||
|
||||
link: {
|
||||
...withPixelLineHeight(theme.typography.bodyLongRegular),
|
||||
...theme.typography.bodyLongRegular,
|
||||
color: theme.palette.link01,
|
||||
|
||||
'&:hover': {
|
||||
|
||||
@@ -4,7 +4,6 @@ import { WithTranslation } from 'react-i18next';
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
import { translate } from '../../../../base/i18n/functions';
|
||||
import { withPixelLineHeight } from '../../../../base/styles/functions.web';
|
||||
import { _formatConferenceIDPin } from '../../../_utils';
|
||||
|
||||
|
||||
@@ -38,14 +37,14 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
}
|
||||
},
|
||||
confNameLabel: {
|
||||
...withPixelLineHeight(theme.typography.heading6),
|
||||
...theme.typography.heading6,
|
||||
marginBottom: 18,
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis'
|
||||
},
|
||||
descriptionLabel: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegularLarge),
|
||||
...theme.typography.bodyShortRegularLarge,
|
||||
marginBottom: 18
|
||||
},
|
||||
separator: {
|
||||
@@ -55,7 +54,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
marginBottom: 18
|
||||
},
|
||||
pinLabel: {
|
||||
...withPixelLineHeight(theme.typography.heading6)
|
||||
...theme.typography.heading6
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -5,7 +5,6 @@ import { WithTranslation } from 'react-i18next';
|
||||
import { withStyles } from 'tss-react/mui';
|
||||
|
||||
import { translate } from '../../../../base/i18n/functions';
|
||||
import { withPixelLineHeight } from '../../../../base/styles/functions.web';
|
||||
import { getDialInConferenceID, getDialInNumbers } from '../../../_utils';
|
||||
|
||||
import ConferenceID from './ConferenceID';
|
||||
@@ -103,7 +102,7 @@ const styles = (theme: Theme) => {
|
||||
},
|
||||
roomName: {
|
||||
margin: '40px auto 8px',
|
||||
...withPixelLineHeight(theme.typography.heading5)
|
||||
...theme.typography.heading5
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -317,12 +317,12 @@ class LargeVideo extends Component<IProps> {
|
||||
_visibleFilmstrip
|
||||
} = this.props;
|
||||
|
||||
styles.backgroundColor = _customBackgroundColor || interfaceConfig.DEFAULT_BACKGROUND;
|
||||
styles.background = _customBackgroundColor || interfaceConfig.DEFAULT_BACKGROUND;
|
||||
|
||||
if (this.props._backgroundAlpha !== undefined) {
|
||||
const alphaColor = setColorAlpha(styles.backgroundColor, this.props._backgroundAlpha);
|
||||
|
||||
styles.backgroundColor = alphaColor;
|
||||
styles.background = alphaColor;
|
||||
}
|
||||
|
||||
if (_customBackgroundImageUrl) {
|
||||
|
||||
@@ -45,8 +45,8 @@ const useStyles = makeStyles()(theme => {
|
||||
sharingMessage: {
|
||||
fontStyle: 'normal',
|
||||
fontWeight: 600,
|
||||
fontSize: '20px',
|
||||
lineHeight: '28px',
|
||||
fontSize: '1.25rem',
|
||||
lineHeight: '1.75rem',
|
||||
marginTop: '24px',
|
||||
letterSpacing: '-0.012em',
|
||||
color: theme.palette.text01
|
||||
@@ -54,8 +54,8 @@ const useStyles = makeStyles()(theme => {
|
||||
showSharing: {
|
||||
fontStyle: 'normal',
|
||||
fontWeight: 600,
|
||||
fontSize: '14px',
|
||||
lineHeight: '20px',
|
||||
fontSize: '0.875rem',
|
||||
lineHeight: '1.25rem',
|
||||
height: '20px',
|
||||
marginTop: '16px',
|
||||
color: theme.palette.link01,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Theme } from '@mui/material';
|
||||
import React, { isValidElement, useCallback, useContext } from 'react';
|
||||
import React, { isValidElement, useCallback, useContext, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { keyframes } from 'tss-react';
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
} from '../../../base/icons/svg';
|
||||
import Message from '../../../base/react/components/web/Message';
|
||||
import { getSupportUrl } from '../../../base/react/functions';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import { NOTIFICATION_ICON, NOTIFICATION_TYPE } from '../../constants';
|
||||
import { INotificationProps } from '../../types';
|
||||
import { NotificationsTransitionContext } from '../NotificationsTransition';
|
||||
@@ -124,11 +123,11 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
},
|
||||
|
||||
title: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortBold)
|
||||
...theme.typography.bodyShortBold
|
||||
},
|
||||
|
||||
description: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
overflow: 'auto',
|
||||
overflowWrap: 'break-word',
|
||||
userSelect: 'all',
|
||||
@@ -152,7 +151,7 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
outline: 0,
|
||||
backgroundColor: 'transparent',
|
||||
color: theme.palette.action01,
|
||||
...withPixelLineHeight(theme.typography.bodyShortBold),
|
||||
...theme.typography.bodyShortBold,
|
||||
marginRight: theme.spacing(3),
|
||||
padding: 0,
|
||||
cursor: 'pointer',
|
||||
@@ -163,6 +162,11 @@ const useStyles = makeStyles()((theme: Theme) => {
|
||||
|
||||
'&.destructive': {
|
||||
color: theme.palette.textError
|
||||
},
|
||||
|
||||
'&:focus-visible': {
|
||||
outline: `2px solid ${theme.palette.action01}`,
|
||||
outlineOffset: 2
|
||||
}
|
||||
},
|
||||
|
||||
@@ -193,6 +197,10 @@ const Notification = ({
|
||||
const { t } = useTranslation();
|
||||
const { unmounting } = useContext(NotificationsTransitionContext);
|
||||
const supportUrl = useSelector(getSupportUrl);
|
||||
const isErrorOrWarning = useMemo(
|
||||
() => appearance === NOTIFICATION_TYPE.ERROR || appearance === NOTIFICATION_TYPE.WARNING,
|
||||
[ appearance ]
|
||||
);
|
||||
|
||||
const ICON_COLOR = {
|
||||
error: theme.palette.iconError,
|
||||
@@ -314,11 +322,12 @@ const Notification = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
aria-atomic = 'false'
|
||||
aria-live = 'polite'
|
||||
aria-atomic = { true }
|
||||
aria-live = { isErrorOrWarning ? 'assertive' : 'polite' }
|
||||
className = { cx(classes.container, (unmounting.get(uid ?? '') && 'unmount') as string | undefined) }
|
||||
data-testid = { titleKey || descriptionKey }
|
||||
id = { uid }>
|
||||
id = { uid }
|
||||
role = { isErrorOrWarning ? 'alert' : 'status' }>
|
||||
<div className = { cx(classes.ribbon, appearance) } />
|
||||
<div className = { classes.content }>
|
||||
<div className = { icon }>
|
||||
@@ -333,10 +342,12 @@ const Notification = ({
|
||||
<div className = { classes.actionsContainer }>
|
||||
{mapAppearanceToButtons().map(({ content, onClick, type, testId }) => (
|
||||
<button
|
||||
aria-label = { content }
|
||||
className = { cx(classes.action, type) }
|
||||
data-testid = { testId }
|
||||
key = { content }
|
||||
onClick = { onClick }>
|
||||
onClick = { onClick }
|
||||
type = 'button'>
|
||||
{content}
|
||||
</button>
|
||||
))}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { IReduxState } from '../../../../../app/types';
|
||||
import Icon from '../../../../../base/icons/components/Icon';
|
||||
import { IconArrowDown, IconArrowUp } from '../../../../../base/icons/svg';
|
||||
import { isLocalParticipantModerator } from '../../../../../base/participants/functions';
|
||||
import { withPixelLineHeight } from '../../../../../base/styles/functions.web';
|
||||
import ListItem from '../../../../../base/ui/components/web/ListItem';
|
||||
import { IRoom } from '../../../../../breakout-rooms/types';
|
||||
import { showOverflowDrawer } from '../../../../../toolbox/functions.web';
|
||||
@@ -92,7 +91,7 @@ const useStyles = makeStyles()(theme => {
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
...withPixelLineHeight(theme.typography.bodyLongBold)
|
||||
...theme.typography.bodyLongBold
|
||||
},
|
||||
|
||||
arrowContainer: {
|
||||
|
||||
@@ -9,7 +9,6 @@ import { makeStyles } from 'tss-react/mui';
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import Icon from '../../../base/icons/components/Icon';
|
||||
import { IconArrowDown, IconArrowUp } from '../../../base/icons/svg';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import { normalizeAccents } from '../../../base/util/strings.web';
|
||||
import { subscribeVisitorsList } from '../../../visitors/actions';
|
||||
import {
|
||||
@@ -45,7 +44,7 @@ const useStyles = makeStyles()(theme => {
|
||||
justifyContent: 'space-between',
|
||||
cursor: 'pointer',
|
||||
padding: `${theme.spacing(1)} 0`,
|
||||
...withPixelLineHeight(theme.typography.bodyShortBold),
|
||||
...theme.typography.bodyShortBold,
|
||||
color: theme.palette.text02,
|
||||
flexShrink: 0
|
||||
},
|
||||
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
IconVideoOff
|
||||
} from '../../../base/icons/svg';
|
||||
import { getRaiseHandsQueue } from '../../../base/participants/functions';
|
||||
import { withPixelLineHeight } from '../../../base/styles/functions.web';
|
||||
import ContextMenu from '../../../base/ui/components/web/ContextMenu';
|
||||
import ContextMenuItemGroup from '../../../base/ui/components/web/ContextMenuItemGroup';
|
||||
import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
|
||||
@@ -49,7 +48,7 @@ const useStyles = makeStyles()(theme => {
|
||||
},
|
||||
|
||||
text: {
|
||||
...withPixelLineHeight(theme.typography.bodyShortRegular),
|
||||
...theme.typography.bodyShortRegular,
|
||||
color: theme.palette.text02,
|
||||
padding: '10px 16px',
|
||||
height: '40px',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user