Merge remote-tracking branch 'upstream/v3.0.x-release' into avoid-unrelated-notifications

This commit is contained in:
Gabriel Porfirio 2024-03-19 15:08:07 -03:00
commit cecfb71483
135 changed files with 754 additions and 961 deletions

View File

@ -17,7 +17,7 @@ As such, we recommend that all administrators deploy 2.7 going forward. You'll
## Reporting a Vulnerability
If you believe you have found a security vunerability in BigBlueButton please let us know directly by
If you believe you have found a security vulnerability in BigBlueButton please let us know directly by
- using GitHub's "Report a vulnerability" functionality on https://github.com/bigbluebutton/bigbluebutton/security/advisories
- or e-mailing security@bigbluebutton.org with as much detail as possible.

View File

@ -16,7 +16,7 @@ object Dependencies {
val pekkoHttpVersion = "1.0.0"
val gson = "2.8.9"
val jackson = "2.13.5"
val logback = "1.2.11"
val logback = "1.2.13"
val quicklens = "1.7.5"
val spray = "1.3.6"

View File

@ -13,6 +13,7 @@ trait SystemConfiguration {
lazy val bbbWebPort = Try(config.getInt("services.bbbWebPort")).getOrElse(8888)
lazy val bbbWebAPI = Try(config.getString("services.bbbWebAPI")).getOrElse("localhost")
lazy val bbbWebSharedSecret = Try(config.getString("services.sharedSecret")).getOrElse("changeme")
lazy val checkSumAlgorithmForBreakouts = Try(config.getString("services.checkSumAlgorithmForBreakouts")).getOrElse("sha256")
lazy val bbbWebModeratorPassword = Try(config.getString("services.moderatorPassword")).getOrElse("changeme")
lazy val bbbWebViewerPassword = Try(config.getString("services.viewerPassword")).getOrElse("changeme")
lazy val keysExpiresInSec = Try(config.getInt("redis.keyExpiry")).getOrElse(14 * 86400) // 14 days

View File

@ -4,6 +4,7 @@ import org.bigbluebutton.core.running.MeetingActor
import java.net.URLEncoder
import scala.collection.SortedSet
import org.apache.commons.codec.digest.DigestUtils
import org.bigbluebutton.SystemConfiguration
trait BreakoutApp2x extends BreakoutRoomCreatedMsgHdlr
with BreakoutRoomsListMsgHdlr
@ -26,7 +27,7 @@ trait BreakoutApp2x extends BreakoutRoomCreatedMsgHdlr
}
object BreakoutRoomsUtil {
object BreakoutRoomsUtil extends SystemConfiguration {
def createMeetingIds(id: String, index: Int): (String, String) = {
val timeStamp = System.currentTimeMillis()
val externalHash = DigestUtils.sha1Hex(id.concat("-").concat(timeStamp.toString()).concat("-").concat(index.toString()))
@ -48,7 +49,13 @@ object BreakoutRoomsUtil {
//checksum() -- Return a checksum based on SHA-1 digest
//
def checksum(s: String): String = {
DigestUtils.sha256Hex(s);
checkSumAlgorithmForBreakouts match {
case "sha1" => DigestUtils.sha1Hex(s);
case "sha256" => DigestUtils.sha256Hex(s);
case "sha384" => DigestUtils.sha384Hex(s);
case "sha512" => DigestUtils.sha512Hex(s);
case _ => DigestUtils.sha256Hex(s); // default
}
}
def calculateChecksum(apiCall: String, baseString: String, sharedSecret: String): String = {

View File

@ -15,7 +15,7 @@ trait SetPresenterInDefaultPodInternalMsgHdlr {
msg: SetPresenterInDefaultPodInternalMsg, state: MeetingState2x,
liveMeeting: LiveMeeting, bus: MessageBus
): MeetingState2x = {
// Swith presenter as default presenter pod has changed.
// Switch presenter as default presenter pod has changed.
log.info("Presenter pod change will trigger a presenter change")
SetPresenterInPodActionHandler.handleAction(state, liveMeeting, bus.outGW, "", PresentationPod.DEFAULT_PRESENTATION_POD, msg.presenterId)
}

View File

@ -367,7 +367,7 @@ public class Bezier {
* @param first Indice of first point in d.
* @param last Indice of last point in d.
* @param tHat1 Unit tangent vectors at start point.
* @param tHat2 Unit tanget vector at end point.
* @param tHat2 Unit tangent vector at end point.
* @param errorSquared User-defined errorSquared squared.
* @param bezierPath Path to which the bezier curve segments are added.
*/
@ -580,7 +580,7 @@ public class Bezier {
*
* @param Q Current fitted bezier curve.
* @param P Digitized point.
* @param u Parameter value vor P.
* @param u Parameter value for P.
*/
private static double newtonRaphsonRootFind(Point2D.Double[] Q, Point2D.Double P, double u) {
double numerator, denominator;
@ -661,7 +661,7 @@ public class Bezier {
* @param last Indice of last point in d.
* @param uPrime Parameter values for region .
* @param tHat1 Unit tangent vectors at start point.
* @param tHat2 Unit tanget vector at end point.
* @param tHat2 Unit tangent vector at end point.
* @return A cubic bezier curve consisting of 4 control points.
*/
private static Point2D.Double[] generateBezier(ArrayList<Point2D.Double> d, int first, int last, double[] uPrime, Point2D.Double tHat1, Point2D.Double tHat2) {

View File

@ -40,7 +40,7 @@ public class BezierPath extends ArrayList<BezierPath.Node>
private static final long serialVersionUID=1L;
/** Constant for having only control point C0 in effect. C0 is the point
* through whitch the curve passes. */
* through which the curve passes. */
public static final int C0_MASK = 0;
/** Constant for having control point C1 in effect (in addition
* to C0). C1 controls the curve going towards C0.

View File

@ -115,7 +115,7 @@ class RedisRecorderActor(
//case m: DeskShareNotifyViewersRTMP => handleDeskShareNotifyViewersRTMP(m)
// AudioCaptions
case m: TranscriptUpdatedEvtMsg => handleTranscriptUpdatedEvtMsg(m)
//case m: TranscriptUpdatedEvtMsg => handleTranscriptUpdatedEvtMsg(m) // temporarily disabling due to issue https://github.com/bigbluebutton/bigbluebutton/issues/19701
// Meeting
case m: RecordingStatusChangedEvtMsg => handleRecordingStatusChangedEvtMsg(m)
@ -284,7 +284,7 @@ class RedisRecorderActor(
}
private def getPresentationId(whiteboardId: String): String = {
// Need to split the whiteboard id into presenation id and page num as the old
// Need to split the whiteboard id into presentation id and page num as the old
// recording expects them
val strId = new StringOps(whiteboardId)
val ids = strId.split('/')
@ -536,6 +536,7 @@ class RedisRecorderActor(
}
*/
/* temporarily disabling due to issue https://github.com/bigbluebutton/bigbluebutton/issues/19701
private def handleTranscriptUpdatedEvtMsg(msg: TranscriptUpdatedEvtMsg) {
val ev = new TranscriptUpdatedRecordEvent()
ev.setMeetingId(msg.header.meetingId)
@ -544,6 +545,7 @@ class RedisRecorderActor(
record(msg.header.meetingId, ev.toMap.asJava)
}
*/
private def handleStartExternalVideoEvtMsg(msg: StartExternalVideoEvtMsg) {
val ev = new StartExternalVideoRecordEvent()

View File

@ -65,6 +65,7 @@ expire {
services {
bbbWebAPI = "https://192.168.23.33/bigbluebutton/api"
sharedSecret = "changeme"
checkSumAlgorithmForBreakouts = "sha256"
}
eventBus {

View File

@ -14,7 +14,7 @@ object Dependencies {
// Libraries
val pekkoVersion = "1.0.1"
val pekkoHttpVersion = "1.0.0"
val logback = "1.2.10"
val logback = "1.2.13"
// Apache Commons
val lang = "3.12.0"

View File

@ -143,7 +143,7 @@ case class SetRecordingStatusCmdMsg(header: BbbClientMsgHeader, body: SetRecordi
case class SetRecordingStatusCmdMsgBody(recording: Boolean, setBy: String)
/**
* Sent by user to start recording mark and ignore previsous marks
* Sent by user to start recording mark and ignore previous marks
*/
object RecordAndClearPreviousMarkersCmdMsg { val NAME = "RecordAndClearPreviousMarkersCmdMsg" }
case class RecordAndClearPreviousMarkersCmdMsg(header: BbbClientMsgHeader, body: RecordAndClearPreviousMarkersCmdMsgBody) extends StandardMsg

View File

@ -111,7 +111,7 @@ public class ApiParams {
public static final String RECORD_FULL_DURATION_MEDIA = "recordFullDurationMedia";
private ApiParams() {
throw new IllegalStateException("ApiParams is a utility class. Instanciation is forbidden.");
throw new IllegalStateException("ApiParams is a utility class. Instantiation is forbidden.");
}
}

View File

@ -124,7 +124,7 @@ public class RecordingServiceFileImpl implements RecordingService {
if (!doneFile.exists())
log.error("Failed to create {} file.", done);
} catch (IOException e) {
log.error("Exception occured when trying to create {} file", done);
log.error("Exception occurred when trying to create {} file", done);
}
} else {
log.error("{} file already exists.", done);
@ -141,7 +141,7 @@ public class RecordingServiceFileImpl implements RecordingService {
if (!doneFile.exists())
log.error("Failed to create {} file.", done);
} catch (IOException e) {
log.error("Exception occured when trying to create {} file.", done);
log.error("Exception occurred when trying to create {} file.", done);
}
} else {
log.error("{} file already exists.", done);
@ -158,7 +158,7 @@ public class RecordingServiceFileImpl implements RecordingService {
if (!doneFile.exists())
log.error("Failed to create " + done + " file.");
} catch (IOException e) {
log.error("Exception occured when trying to create {} file.", done);
log.error("Exception occurred when trying to create {} file.", done);
}
} else {
log.error(done + " file already exists.");

View File

@ -37,7 +37,7 @@ public class ResponseBuilder {
try {
cfg.setDirectoryForTemplateLoading(templatesLoc);
} catch (IOException e) {
log.error("Exception occured creating ResponseBuilder", e);
log.error("Exception occurred creating ResponseBuilder", e);
}
setUpConfiguration();
}
@ -97,12 +97,12 @@ public class ResponseBuilder {
return xmlText.toString();
}
public String buildErrors(ArrayList erros, String returnCode) {
public String buildErrors(ArrayList errors, String returnCode) {
StringWriter xmlText = new StringWriter();
Map<String, Object> data = new HashMap<String, Object>();
data.put("returnCode", returnCode);
data.put("errorsList", erros);
data.put("errorsList", errors);
processData(getTemplate("api-errors.ftlx"), data, xmlText);

View File

@ -41,6 +41,6 @@ public class ConversionMessageConstants {
public static final String CONVERSION_TIMEOUT_KEY = "CONVERSION_TIMEOUT";
private ConversionMessageConstants() {
throw new IllegalStateException("ConversionMessageConstants is a utility class. Instanciation is forbidden.");
throw new IllegalStateException("ConversionMessageConstants is a utility class. Instantiation is forbidden.");
}
}

View File

@ -81,7 +81,7 @@ public class ExternalProcessExecutor {
try {
if (!proc.waitFor(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
log.warn("TIMEDOUT excuting: {}", String.join(" ", cmd));
log.warn("TIMEDOUT executing: {}", String.join(" ", cmd));
proc.destroy();
}
return !proc.isAlive() && proc.exitValue() == 0;

View File

@ -11,7 +11,7 @@ object Dependencies {
// Libraries
val netty = "3.2.10.Final"
val logback = "1.2.10"
val logback = "1.2.13"
// Test
val junit = "4.12"

View File

@ -157,7 +157,7 @@ public class Client
* Sends a FreeSWITCH API command to the server and blocks, waiting for an immediate response from the
* server.
* <p/>
* The outcome of the command from the server is retured in an {@link EslMessage} object.
* The outcome of the command from the server is returned in an {@link EslMessage} object.
*
* @param command API command to send
* @param arg command arguments
@ -454,7 +454,7 @@ public class Client
public void run() {
try {
/**
* Custom extra parsing to get conference Events for BigBlueButton / FreeSwitch intergration
* Custom extra parsing to get conference Events for BigBlueButton / FreeSwitch integration
*/
//FIXME: make the conference headers constants
if (event.getEventSubclass().equals("conference::maintenance")) {
@ -495,7 +495,7 @@ public class Client
listener.conferenceEventPlayFile(uniqueId, confName, confSize, event);
return;
} else if (eventFunc.equals("conf_api_sub_transfer") || eventFunc.equals("conference_api_sub_transfer")) {
//Member transfered to another conf...
//Member transferred to another conf...
listener.conferenceEventTransfer(uniqueId, confName, confSize, event);
return;
} else if (eventFunc.equals("conference_add_member") || eventFunc.equals("conference_member_add")) {

View File

@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory;
/**
* a {@link Runnable} which sends the specified {@link ChannelEvent} upstream.
* Most users will not see this type at all because it is used by
* {@link Executor} implementors only
* {@link Executor} implementers only
*
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com)

View File

@ -26,7 +26,7 @@ import org.slf4j.LoggerFactory;
* the following:
* <pre>
&lt;extension&gt;
&lt;condition field="destination_number" expresssion="444"&gt;
&lt;condition field="destination_number" expression="444"&gt;
&lt;action application="socket" data="192.168.100.88:8084 async full"/&gt;
&lt;/condition&gt;
&lt;/extension&gt;

View File

@ -21,7 +21,7 @@ export default function buildRedisMessage(sessionVariables: Record<string, unkno
recording: input.recording
};
//TODO check if backend velidate it
//TODO check if backend validates it
// const recordObject = await RecordMeetings.findOneAsync({ meetingId });
//

View File

@ -0,0 +1,24 @@
import { RedisMessage } from '../types';
export default function buildRedisMessage(sessionVariables: Record<string, unknown>, input: Record<string, unknown>): RedisMessage {
const eventName = `SendCursorPositionPubMsg`;
const routing = {
meetingId: sessionVariables['x-hasura-meetingid'] as String,
userId: sessionVariables['x-hasura-userid'] as String
};
const header = {
name: eventName,
meetingId: routing.meetingId,
userId: routing.userId
};
const body = {
whiteboardId: input.whiteboardId,
xPercent: input.xPercent,
yPercent: input.yPercent,
};
return { eventName, routing, header, body };
}

View File

@ -3,7 +3,7 @@ BBB_GRAPHQL_MIDDLEWARE_LISTEN_PORT=8378
BBB_GRAPHQL_MIDDLEWARE_REDIS_ADDRESS=127.0.0.1:6379
BBB_GRAPHQL_MIDDLEWARE_REDIS_PASSWORD=
BBB_GRAPHQL_MIDDLEWARE_HASURA_WS=ws://127.0.0.1:8080/v1/graphql
BBB_GRAPHQL_MIDDLEWARE_RATE_LIMIT_IN_MS=50
BBB_GRAPHQL_MIDDLEWARE_MAX_CONN_PER_SECOND=10
# If you are running a cluster proxy setup, you need to configure the Origin of
# the frontend. See https://docs.bigbluebutton.org/administration/cluster-proxy

View File

@ -2,12 +2,12 @@ package main
import (
"context"
"errors"
"fmt"
"github.com/iMDT/bbb-graphql-middleware/internal/common"
"github.com/iMDT/bbb-graphql-middleware/internal/msgpatch"
"github.com/iMDT/bbb-graphql-middleware/internal/websrv"
log "github.com/sirupsen/logrus"
"golang.org/x/time/rate"
"net/http"
"os"
"strconv"
@ -53,20 +53,23 @@ func main() {
}
//Define new Connections Rate Limit
rateLimitInMs := 50
if envRateLimitInMs := os.Getenv("BBB_GRAPHQL_MIDDLEWARE_RATE_LIMIT_IN_MS"); envRateLimitInMs != "" {
if envRateLimitInMsAsInt, err := strconv.Atoi(envRateLimitInMs); err == nil {
rateLimitInMs = envRateLimitInMsAsInt
maxConnPerSecond := 10
if envMaxConnPerSecond := os.Getenv("BBB_GRAPHQL_MIDDLEWARE_MAX_CONN_PER_SECOND"); envMaxConnPerSecond != "" {
if envMaxConnPerSecondAsInt, err := strconv.Atoi(envMaxConnPerSecond); err == nil {
maxConnPerSecond = envMaxConnPerSecondAsInt
}
}
limiterInterval := rate.NewLimiter(rate.Every(time.Duration(rateLimitInMs)*time.Millisecond), 1)
rateLimiter := common.NewCustomRateLimiter(maxConnPerSecond)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
ctx, cancel := context.WithTimeout(r.Context(), 120*time.Second)
defer cancel()
if err := limiterInterval.Wait(ctx); err != nil {
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
if err := rateLimiter.Wait(ctx); err != nil {
if !errors.Is(err, context.Canceled) {
http.Error(w, "Request cancelled or rate limit exceeded", http.StatusTooManyRequests)
}
return
}

View File

@ -0,0 +1,64 @@
package common
import (
"context"
"time"
)
type CustomRateLimiter struct {
tokens chan struct{}
requestQueue chan context.Context
}
func NewCustomRateLimiter(requestsPerSecond int) *CustomRateLimiter {
rl := &CustomRateLimiter{
tokens: make(chan struct{}, requestsPerSecond),
requestQueue: make(chan context.Context, 20000), // Adjust the size accordingly
}
go rl.refillTokens(requestsPerSecond)
go rl.processQueue()
return rl
}
func (rl *CustomRateLimiter) refillTokens(requestsPerSecond int) {
ticker := time.NewTicker(time.Second / time.Duration(requestsPerSecond))
for {
select {
case <-ticker.C:
// Try to add a token, skip if full
select {
case rl.tokens <- struct{}{}:
default:
}
}
}
}
func (rl *CustomRateLimiter) processQueue() {
for ctx := range rl.requestQueue {
select {
case <-rl.tokens:
if ctx.Err() == nil {
// Token acquired and context not cancelled, proceed
// Simulate processing by calling a dummy function
// processRequest() or similar
}
case <-ctx.Done():
// Context cancelled, skip
}
}
}
func (rl *CustomRateLimiter) Wait(ctx context.Context) error {
rl.requestQueue <- ctx
select {
case <-ctx.Done():
// Request cancelled
return ctx.Err()
case <-rl.tokens:
// Acquired token, proceed
return nil
}
}

View File

@ -54,7 +54,7 @@ func handleMessageReceivedFromHasura(hc *common.HasuraConnection, fromHasuraToBr
subscription, ok := hc.BrowserConn.ActiveSubscriptions[queryId]
hc.BrowserConn.ActiveSubscriptionsMutex.RUnlock()
if !ok {
log.Debugf("Subscription with Id %s doesn't exist anymore, skiping response.", queryId)
log.Debugf("Subscription with Id %s doesn't exist anymore, skipping response.", queryId)
return
}

View File

@ -67,10 +67,13 @@ func ConnectionHandler(w http.ResponseWriter, r *http.Request) {
defer func() {
msgpatch.RemoveConnCacheDir(browserConnectionId)
BrowserConnectionsMutex.Lock()
sessionTokenRemoved := BrowserConnections[browserConnectionId].SessionToken
delete(BrowserConnections, browserConnectionId)
_, bcExists := BrowserConnections[browserConnectionId]
if bcExists {
sessionTokenRemoved := BrowserConnections[browserConnectionId].SessionToken
delete(BrowserConnections, browserConnectionId)
go SendUserGraphqlConnectionClosedSysMsg(sessionTokenRemoved, browserConnectionId)
}
BrowserConnectionsMutex.Unlock()
go SendUserGraphqlConnectionClosedSysMsg(sessionTokenRemoved, browserConnectionId)
log.Infof("connection removed")
}()
@ -135,7 +138,71 @@ func ConnectionHandler(w http.ResponseWriter, r *http.Request) {
func InvalidateSessionTokenConnections(sessionTokenToInvalidate string) {
BrowserConnectionsMutex.RLock()
connectionsToProcess := make([]*common.BrowserConnection, 0)
for _, browserConnection := range BrowserConnections {
if browserConnection.SessionToken == sessionTokenToInvalidate {
connectionsToProcess = append(connectionsToProcess, browserConnection)
}
}
BrowserConnectionsMutex.RUnlock()
var wg sync.WaitGroup
for _, browserConnection := range connectionsToProcess {
wg.Add(1)
go func(bc *common.BrowserConnection) {
defer wg.Done()
invalidateBrowserConnection(bc, sessionTokenToInvalidate)
}(browserConnection)
}
wg.Wait()
}
func invalidateBrowserConnection(bc *common.BrowserConnection, sessionToken string) {
if bc.HasuraConnection == nil {
return // If there's no Hasura connection, there's nothing to invalidate.
}
hasuraConnectionId := bc.HasuraConnection.Id
// Send message to stop receiving new messages from the browser.
bc.HasuraConnection.FreezeMsgFromBrowserChan.Send(true)
// Wait until there are no active mutations.
for iterationCount := 0; iterationCount < 20; iterationCount++ {
activeMutationFound := false
bc.ActiveSubscriptionsMutex.RLock()
for _, subscription := range bc.ActiveSubscriptions {
if subscription.Type == common.Mutation {
activeMutationFound = true
break
}
}
bc.ActiveSubscriptionsMutex.RUnlock()
if !activeMutationFound {
break // Exit the loop if no active mutations are found.
}
time.Sleep(100 * time.Millisecond) // Wait a bit before checking again.
}
log.Debugf("Processing invalidate request for sessionToken %v (hasura connection %v)", sessionToken, hasuraConnectionId)
// Cancel the Hasura connection context to clean up resources.
if bc.HasuraConnection != nil && bc.HasuraConnection.ContextCancelFunc != nil {
bc.HasuraConnection.ContextCancelFunc()
}
log.Debugf("Processed invalidate request for sessionToken %v (hasura connection %v)", sessionToken, hasuraConnectionId)
// Send a reconnection confirmation message
go SendUserGraphqlReconnectionForcedEvtMsg(sessionToken)
}
func InvalidateSessionTokenConnectionsB(sessionTokenToInvalidate string) {
BrowserConnectionsMutex.RLock()
for _, browserConnection := range BrowserConnections {
hasuraConnectionId := browserConnection.HasuraConnection.Id
if browserConnection.SessionToken == sessionTokenToInvalidate {
if browserConnection.HasuraConnection != nil {
//Send message to force stop receiving new messages from the browser
@ -159,9 +226,10 @@ func InvalidateSessionTokenConnections(sessionTokenToInvalidate string) {
time.Sleep(100 * time.Millisecond)
}
hasuraConnectionId := browserConnection.HasuraConnection.Id
log.Debugf("Processing invalidate request for sessionToken %v (hasura connection %v)", sessionTokenToInvalidate, hasuraConnectionId)
browserConnection.HasuraConnection.ContextCancelFunc()
if browserConnection.HasuraConnection != nil {
browserConnection.HasuraConnection.ContextCancelFunc()
}
log.Debugf("Processed invalidate request for sessionToken %v (hasura connection %v)", sessionTokenToInvalidate, hasuraConnectionId)
go SendUserGraphqlReconnectionForcedEvtMsg(browserConnection.SessionToken)

View File

@ -39,7 +39,7 @@ func BrowserConnectionReader(browserConnectionId string, ctx context.Context, ct
if errors.Is(err, context.Canceled) {
log.Debugf("Closing Browser ws connection as Context was cancelled!")
} else {
log.Debugf("Hasura is disconnected, skiping reading of ws message: %v", err)
log.Debugf("Hasura is disconnected, skipping reading of ws message: %v", err)
}
return
}

View File

@ -35,7 +35,7 @@ RangeLoop:
log.Tracef("sending to browser: %v", toBrowserMessage)
err := wsjson.Write(ctx, browserWsConn, toBrowserMessage)
if err != nil {
log.Debugf("Browser is disconnected, skiping writing of ws message: %v", err)
log.Debugf("Browser is disconnected, skipping writing of ws message: %v", err)
return
}

View File

@ -250,7 +250,7 @@ CREATE TABLE "user" (
"registeredOn" bigint,
"excludeFromDashboard" bool,
"enforceLayout" varchar(50),
--columns of user state bellow
--columns of user state below
"raiseHand" bool default false,
"raiseHandTime" timestamp with time zone,
"away" bool default false,

View File

@ -287,6 +287,14 @@ type Mutation {
): Boolean
}
type Mutation {
presentationPublishCursor(
whiteboardId: String!
xPercent: Float!
yPercent: Float!
): Boolean
}
type Mutation {
presentationRemove(
presentationId: String!

View File

@ -252,6 +252,12 @@ actions:
permissions:
- role: bbb_client
comment: presentationExport
- name: presentationPublishCursor
definition:
kind: synchronous
handler: '{{HASURA_BBB_GRAPHQL_ACTIONS_ADAPTER_URL}}'
permissions:
- role: bbb_client
- name: presentationRemove
definition:
kind: synchronous

View File

@ -16,7 +16,7 @@ HOST=127.0.0.1
# Set this to "-k" to allow it to work in a test environment, ie with a self signed
# certificate
UNSECURE=
INSECURE=
# This script receives three params
# Param 1: Input office file path (e.g. "/tmp/test.odt")
@ -46,6 +46,6 @@ timeoutSecs="${timeoutSecs:0:3}"
# The timeout is important.
timeout $(printf %03d $timeoutSecs)s curl $UNSECURE -F "data=@${source}" https://$HOST:9980/cool/convert-to/$convertTo > "${dest}"
timeout $(printf %03d $timeoutSecs)s curl $INSECURE -F "data=@${source}" https://$HOST:9980/cool/convert-to/$convertTo > "${dest}"
exit 0

View File

@ -18,7 +18,7 @@ conf.orig dir is what was installed by freeswitch by default
NOTE: you must double check this config if you intend to have
the freeswitch server on a public facing interface.
It defaults to localhost for the event socket inteface.
It defaults to localhost for the event socket interface.
I run my server in a test environment with
/usr/local/freeswitch/bin/freeswitch -hp -nc

View File

@ -3,7 +3,7 @@
NOTICE:
This context is usually accessed via authenticated callers on the sip profile on port 5060
or transfered callers from the public context which arrived via the sip profile on port 5080.
or transferred callers from the public context which arrived via the sip profile on port 5080.
Authenticated users will use the user_context variable on the user to determine what context
they can access. You can also add a user in the directory with the cidr= attribute acl.conf.xml

View File

@ -7,7 +7,7 @@
<params>
<!-- omit password for authless registration -->
<param name="password" value="secret"/>
<!-- What this user is allowed to acces -->
<!-- What this user is allowed to access -->
<!--<param name="http-allowed-api" value="jsapi,voicemail,status"/> -->
</params>
<variables>

View File

@ -327,7 +327,7 @@
<!--<param name="rtcp-audio-interval-msec" value="5000"/>-->
<!--<param name="rtcp-video-interval-msec" value="5000"/>-->
<!--force suscription expires to a lower value than requested-->
<!--force subscription expires to a lower value than requested-->
<!--<param name="force-subscription-expires" value="60"/>-->
<!-- add a random deviation to the expires value of the 202 Accepted -->

View File

@ -166,7 +166,7 @@
rtp_secure_media_suites
____________________________________________________________________________
Optionaly you can use rtp_secure_media_suites to dictate the suite list
Optionally you can use rtp_secure_media_suites to dictate the suite list
and only use rtp_secure_media=[optional|mandatory|false|true] without having
to dictate the suite list with the rtp_secure_media* variables.
-->
@ -175,7 +175,7 @@
codecname[@8000h|16000h|32000h[@XXi]]
XX is the frame size must be multples allowed for the codec
XX is the frame size must be multiples allowed for the codec
FreeSWITCH can support 10-120ms on some codecs.
We do not support exceeding the MTU of the RTP packet.
@ -414,7 +414,7 @@
openssl ciphers -v 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH'
Will show you what is available in your verion of openssl.
Will show you what is available in your version of openssl.
-->
<X-PRE-PROCESS cmd="set" data="sip_tls_ciphers=ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"/>
@ -431,7 +431,7 @@
<X-PRE-PROCESS cmd="set" data="external_ssl_enable=false"/>
<!-- Video Settings -->
<!-- Setting the max bandwdith -->
<!-- Setting the max bandwidth -->
<X-PRE-PROCESS cmd="set" data="rtp_video_max_bandwidth_in=1mb"/>
<X-PRE-PROCESS cmd="set" data="rtp_video_max_bandwidth_out=1mb"/>

View File

@ -1 +1 @@
git clone --branch v2.13.2 --depth 1 https://github.com/bigbluebutton/bbb-webrtc-sfu bbb-webrtc-sfu
git clone --branch v2.13.3 --depth 1 https://github.com/bigbluebutton/bbb-webrtc-sfu bbb-webrtc-sfu

View File

@ -308,7 +308,7 @@ check_and_backup () {
fi
}
# 3 paramenter: the file, the variable name, the new value
# 3 parameter: the file, the variable name, the new value
change_var_value () {
check_and_backup $1
sed -i "s<^[[:blank:]#]*\(${2}\).*<\1=${3}<" $1
@ -1489,7 +1489,7 @@ if [ -n "$HOST" ]; then
echo "bigbluebutton.web.serverURL=$PROTOCOL://$HOST" >> "$BBB_WEB_ETC_CONFIG"
fi
# Populate /etc/bigbluebutton/bbb-web.properites with the shared secret
# Populate /etc/bigbluebutton/bbb-web.properties with the shared secret
if ! grep -q "^securitySalt" "$BBB_WEB_ETC_CONFIG"; then
echo "securitySalt=$(get_bbb_web_config_value securitySalt)" >> "$BBB_WEB_ETC_CONFIG"
fi

View File

@ -23,7 +23,7 @@
# Daniel Petri Rocha <danielpetrirocha@gmail.com>
#
# Changelog:
# 2011-08-18 FFD Inital Version
# 2011-08-18 FFD Initial Version
# 2011-11-20 FFD Added more checks for processing of recording
# 2012-01-04 GUG Add option to check for errors
# 2012-02-27 GUG Add option to delete one meeting and recording

View File

@ -122,7 +122,7 @@ remove_raw_of_published_recordings(){
remove_raw_of_published_recordings
#
# Remove untagged and unamed docker images, cleanning /var/lib/docker/overlay2
# Remove untagged and unnamed docker images, cleaning /var/lib/docker/overlay2
#
docker image prune -f

View File

@ -97,7 +97,7 @@ const doGUM = async (constraints, retryOnFailure = false) => {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
return stream;
} catch (error) {
// This is probably a deviceId mistmatch. Retry with base constraints
// This is probably a deviceId mismatch. Retry with base constraints
// without an exact deviceId.
if (error.name === 'OverconstrainedError' && retryOnFailure) {
logger.warn({

View File

@ -225,7 +225,7 @@ export default class SFUAudioBridge extends BaseAudioBridge {
}
}
// Already tried reconnecting once OR the user handn't succesfully
// Already tried reconnecting once OR the user handn't successfully
// connected firsthand and retrying isn't an option. Finish the session
// and reject with the error
logger.error({

View File

@ -272,7 +272,7 @@ class SIPSession {
*
* sessionSupportRTPPayloadDtmf
* tells if browser support RFC4733 DTMF.
* Safari 13 doens't support it yet
* Safari 13 doesn't support it yet
*/
sessionSupportRTPPayloadDtmf(session) {
try {
@ -383,7 +383,7 @@ class SIPSession {
if (this.preloadedInputStream && this.preloadedInputStream.active) {
return Promise.resolve(this.preloadedInputStream);
}
// The rest of this mimicks the default factory behavior.
// The rest of this mimics the default factory behavior.
if (!constraints.audio && !constraints.video) {
return Promise.resolve(new MediaStream());
}
@ -498,7 +498,7 @@ class SIPSession {
extraInfo: {
callerIdName: this.user.callerIdName,
},
}, 'User agent succesfully reconnected');
}, 'User agent successfully reconnected');
}).catch(() => {
if (userAgentConnected) {
error = 1001;
@ -531,7 +531,7 @@ class SIPSession {
extraInfo: {
callerIdName: this.user.callerIdName,
},
}, 'User agent succesfully connected');
}, 'User agent successfully connected');
window.addEventListener('beforeunload', this.onBeforeUnload.bind(this));
@ -567,7 +567,7 @@ class SIPSession {
extraInfo: {
callerIdName: this.user.callerIdName,
},
}, 'User agent succesfully reconnected');
}, 'User agent successfully reconnected');
resolve();
}).catch(() => {
@ -579,7 +579,7 @@ class SIPSession {
callerIdName: this.user.callerIdName,
},
}, 'User agent failed to reconnect after'
+ ` ${USER_AGENT_RECONNECTION_ATTEMPTS} attemps`);
+ ` ${USER_AGENT_RECONNECTION_ATTEMPTS} attempts`);
this.callback({
status: this.baseCallStates.failed,
@ -1013,7 +1013,7 @@ class SIPSession {
}
// if session hasn't even started, we let audio-modal to handle
// any possile errors
// any possible errors
if (!this._currentSessionState) return false;

View File

@ -1 +0,0 @@
import './methods';

View File

@ -1,6 +0,0 @@
import { Meteor } from 'meteor/meteor';
import publishCursorUpdate from './methods/publishCursorUpdate';
Meteor.methods({
publishCursorUpdate,
});

View File

@ -1,10 +0,0 @@
import RedisPubSub from '/imports/startup/server/redis';
import { Meteor } from 'meteor/meteor';
export default function publishCursorUpdate(meetingId, requesterUserId, payload) {
const REDIS_CONFIG = Meteor.settings.private.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'SendCursorPositionPubMsg';
return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
}

View File

@ -8,7 +8,7 @@ const SELECT_RANDOM_USER_COUNTDOWN = Meteor.settings.public.selectRandomUser.cou
// for iteration in animation.
const intervals = [0, 200, 450, 750, 1100, 1500];
// Used to togle to the first value of intervals to
// Used to toggle to the first value of intervals to
// differenciare whether this function has been called
let updateIndicator = true;
@ -30,7 +30,7 @@ function getFiveRandom(userList, userIds) {
IDs = userIds.slice(); // start over
let userId = IDs.splice(0, 1);
if (userList[userList.length] === [userId, intervals[i]]) {
// If we start over with the one we finnished, change it
// If we start over with the one we finished, change it
IDs.push(userId);
userId = IDs.splice(0, 1);
}

View File

@ -118,7 +118,7 @@ const intlMessages = defineMessages({
},
defaultViewLabel: {
id: 'app.title.defaultViewLabel',
description: 'view name apended to document title',
description: 'view name appended to document title',
},
promotedLabel: {
id: 'app.toast.promotedLabel',

View File

@ -626,7 +626,7 @@ class AudioModal extends Component {
<Styled.BrowserWarning>
<FormattedMessage
id="app.audioModal.unsupportedBrowserLabel"
description="Warning when someone joins with a browser that isnt supported"
description="Warning when someone joins with a browser that isn't supported"
values={{
0: <a href="https://www.google.com/chrome/">Chrome</a>,
1: <a href="https://getfirefox.com">Firefox</a>,

View File

@ -208,7 +208,7 @@ class AudioSettings extends React.Component {
const { outputDeviceId: currentOutputDeviceId } = this.state;
// withEcho usage (isLive arg): if local echo is enabled we need the device
// change to be performed seamlessly (which is what the isLive parameter guarantes)
// change to be performed seamlessly (which is what the isLive parameter guarantees)
changeOutputDevice(deviceId, withEcho)
.then(() => {
this.setState({

View File

@ -67,11 +67,11 @@ const intlMessages = defineMessages({
},
BrowserNotSupported: {
id: 'app.audioNotification.audioFailedError1003',
description: 'browser not supported error messsage',
description: 'browser not supported error message',
},
reconectingAsListener: {
id: 'app.audioNotificaion.reconnectingAsListenOnly',
description: 'ice negociation error messsage',
description: 'ice negotiation error message',
},
});

View File

@ -29,7 +29,7 @@ const intlMessages = defineMessages({
},
dictationStop: {
id: 'app.captions.dictationStop',
description: 'Label for stoping speech recognition',
description: 'Label for stopping speech recognition',
},
dictationOnDesc: {
id: 'app.captions.dictationOnDesc',

View File

@ -29,7 +29,7 @@ const isBoolean = (v: unknown): boolean => {
} if (v === 'false') {
return false;
}
// if v is not difined it shouldn't be considered on comparation, so it returns true
// if v is not defined it shouldn't be considered on comparison, so it returns true
return true;
};

View File

@ -46,7 +46,7 @@ const RandomUserSelectContainer = (props) => {
try {
if (!currentUser.presenter // this functionality does not bother presenter
&& (!keepModalOpen) // we only ween a change if modal has been closed before
&& (randomlySelectedUser[0][1] !== updateIndicator)// if tey are different, a user was generated
&& (randomlySelectedUser[0][1] !== updateIndicator)// if they are different, a user was generated
) { keepModalOpen = true; } // reopen modal
if (!currentUser.presenter) { updateIndicator = randomlySelectedUser[0][1]; } // keep indicator up to date
} catch (err) {

View File

@ -56,6 +56,7 @@ const ConnectionManager: React.FC<ConnectionManagerProps> = ({ children }): Reac
const subscription = new SubscriptionClient(graphqlUrl, {
reconnect: true,
timeout: 30000,
minTimeout: 30000,
connectionParams: {
headers: {
'X-Session-Token': sessionToken,

View File

@ -1,4 +1,5 @@
import React, { useEffect } from 'react';
import { Session } from 'meteor/session';
import { ErrorScreen } from '../../error-screen/component';
import LoadingScreen from '../../common/loading-screen/component';
@ -69,6 +70,10 @@ const StartupDataFetch: React.FC<StartupDataFetchProps> = ({
setSettingsFetched(true);
clearTimeout(timeoutRef.current);
setLoading(false);
}).catch(() => {
Session.set('errorMessageDescription', 'meeting_ended');
setError('Error fetching startup data');
setLoading(false);
});
}, []);
@ -79,6 +84,7 @@ const StartupDataFetch: React.FC<StartupDataFetchProps> = ({
? (
<ErrorScreen
endedReason={error}
code={403}
/>
)
: null}

View File

@ -30,7 +30,7 @@ const intlMessages = defineMessages({
},
more: {
id: 'app.connection-status.more',
description: 'More about conectivity issues',
description: 'More about connectivity issues',
},
audioLabel: {
id: 'app.settings.audioTab.label',
@ -386,7 +386,7 @@ class ConnectionStatusComponent extends PureComponent {
}
/**
* Render network data , containing information abount current upload and
* Render network data , containing information about current upload and
* download rates
* @return {Object} The component to be renderized.
*/

View File

@ -263,7 +263,7 @@ const getNetworkData = async () => {
};
/**
* Calculates both upload and download rates using data retreived from getStats
* Calculates both upload and download rates using data retrieved from getStats
* API. For upload (outbound-rtp) we use both bytesSent and timestamp fields.
* byteSent field contains the number of octets sent at the given timestamp,
* more information can be found in:

View File

@ -94,7 +94,7 @@ const reducer = (state, action) => {
}
// LAYOUT TYPE
// using to load a diferent layout manager
// using to load a different layout manager
case ACTIONS.SET_LAYOUT_TYPE: {
const { layoutType } = state.input;
if (layoutType === action.value) return state;

View File

@ -22,7 +22,7 @@ const LayoutModalComponent = (props) => {
const [selectedLayout, setSelectedLayout] = useState(application.selectedLayout);
const BASE_NAME = window.meetingClientSettings.public.app.basename;
const BASE_NAME = window.meetingClientSettings.public.app.cdn + window.meetingClientSettings.public.app.basename;
const LAYOUTS_PATH = `${BASE_NAME}/resources/images/layouts/`;
const isKeepPushingLayoutEnabled = SettingsService.isKeepPushingLayoutEnabled();

View File

@ -23,7 +23,7 @@ export {
isMobile, isTablet, isTabletPortrait, isTabletLandscape, isDesktop,
};
// Array for select component to select diferent layout
// Array for select component to select different layout
const suportedLayouts = [
{
layoutKey: LAYOUT_TYPE.SMART_LAYOUT,

View File

@ -167,7 +167,7 @@ export default class Legacy extends Component {
<p className="browserWarning">
<FormattedMessage
id={messageId}
description="Warning when someone joins with a browser that isnt supported"
description="Warning when someone joins with a browser that isn't supported"
values={{
0: <a href="https://www.google.com/chrome/">Chrome</a>,
1: <a href="https://getfirefox.com">Firefox</a>,

View File

@ -68,7 +68,7 @@ const intlMessage = defineMessages({
},
confirmDesc: {
id: 'app.leaveConfirmation.confirmDesc',
description: 'adds context to confim option',
description: 'adds context to confirm option',
},
sendLabel: {
id: 'app.feedback.sendFeedback',

View File

@ -9,7 +9,7 @@ export interface IsBreakoutSubscriptionData {
meeting: Array<IsBreakoutData>;
}
// TODO: rework when useMeeting hook be avaible
// TODO: rework when useMeeting hook be available
export const MEETING_ISBREAKOUT_SUBSCRIPTION = gql`
subscription getIsBreakout {
meeting {

View File

@ -62,7 +62,7 @@ const intlMessages = defineMessages({
},
customInputToggleLabel: {
id: 'app.poll.customInput.label',
description: 'poll custom input toogle button label',
description: 'poll custom input toggle button label',
},
customInputInstructionsLabel: {
id: 'app.poll.customInputInstructions.label',

View File

@ -11,7 +11,7 @@ import { POLL_PUBLISH_RESULT, POLL_CANCEL, POLL_CREATE } from './mutations';
import { ACTIONS, PANELS } from '../layout/enums';
const CHAT_CONFIG = window.meetingClientSettings.public.chat;
const PUBLIC_CHAT_KEY = CHAT_CONFIG.public_id;
const PUBLIC_CHAT_KEY = CHAT_CONFIG.public_group_id;
const PollContainer = (props) => {
const layoutContextDispatch = layoutDispatch();

View File

@ -90,6 +90,16 @@ export const PRES_ANNOTATION_SUBMIT = gql`
}
`;
export const PRESENTATION_PUBLISH_CURSOR = gql`
mutation PresentationPublishCursor($whiteboardId: String!, $xPercent: Float!, $yPercent: Float!) {
presentationPublishCursor(
whiteboardId: $whiteboardId,
xPercent: $xPercent,
yPercent: $yPercent,
)
}
`;
export default {
PRESENTATION_SET_ZOOM,
PRESENTATION_SET_WRITERS,
@ -100,4 +110,5 @@ export default {
PRESENTATION_REMOVE,
PRES_ANNOTATION_DELETE,
PRES_ANNOTATION_SUBMIT,
PRESENTATION_PUBLISH_CURSOR,
};

View File

@ -565,6 +565,7 @@ class PresentationUploader extends Component {
commands[newCurrentIndex] = {
$apply: (presentation) => {
if (!presentation) return;
const p = presentation;
if (p) {
p.current = true;

View File

@ -20,7 +20,7 @@ const intlMessages = defineMessages({
},
pushAlertLabel: {
id: 'app.submenu.notification.pushAlertLabel',
description: 'push notifiation label',
description: 'push notification label',
},
messagesLabel: {
id: 'app.submenu.notification.messagesLabel',

View File

@ -123,7 +123,7 @@ interface RenderModalProps {
isOpen: boolean;
priority: string;
/* Use 'any' if you don't have specific props;
As this props varies in types usage of any is most apropriate */
As this props varies in types usage of any is most appropriate */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Component: React.ComponentType<any>;
otherOptions: object;

View File

@ -309,7 +309,7 @@ class VideoPreview extends Component {
const newDevices = await navigator.mediaDevices.enumerateDevices();
webcams = PreviewService.digestVideoDevices(newDevices, webcamDeviceId).webcams;
} catch (error) {
// Not a critical error beucase it should only affect UI; log it
// Not a critical error because it should only affect UI; log it
// and go ahead
logger.error({
logCode: 'video_preview_enumerate_relabel_failure',
@ -1059,7 +1059,7 @@ class VideoPreview extends Component {
<Styled.BrowserWarning>
<FormattedMessage
id="app.audioModal.unsupportedBrowserLabel"
description="Warning when someone joins with a browser that isnt supported"
description="Warning when someone joins with a browser that isn't supported"
values={{
0: <a href="https://www.google.com/chrome/">Chrome</a>,
1: <a href="https://getfirefox.com">Firefox</a>,

View File

@ -200,7 +200,7 @@ const doGUM = (deviceId, profile) => {
// Chrome/Edge sometimes bork gUM calls when switching camera
// profiles. This looks like a browser bug. Track release not
// being done synchronously -> quick subsequent gUM calls for the same
// device (profile switching) -> device becoming unavaible while previous
// device (profile switching) -> device becoming unavailable while previous
// tracks aren't finished - prlanzarin
if (browserInfo.isChrome || browserInfo.isEdge) {
const opts = {

View File

@ -205,7 +205,7 @@ class VideoProvider extends Component {
} = this.props;
const { socketOpen } = this.state;
// Only debounce when page changes to avoid unecessary debouncing
// Only debounce when page changes to avoid unnecessary debouncing
const shouldDebounce = VideoService.isPaginationEnabled()
&& prevProps.currentVideoPageIndex !== currentVideoPageIndex;
@ -1174,7 +1174,7 @@ class VideoProvider extends Component {
peer.started = true;
// Clear camera shared timeout when camera succesfully starts
// Clear camera shared timeout when camera successfully starts
this.clearRestartTimers(stream);
this.attachVideoStream(stream);

View File

@ -468,7 +468,7 @@ class VideoService {
const connectingStream = this.getConnectingStream(streams);
if (connectingStream) streams.push(connectingStream);
// Pagination is either explictly disabled or pagination is set to 0 (which
// Pagination is either explicitly disabled or pagination is set to 0 (which
// is equivalent to disabling it), so return the mapped streams as they are
// which produces the original non paginated behaviour
if (isPaginationDisabled) {
@ -900,7 +900,7 @@ class VideoService {
parameters.encodings = [{}];
}
// Only reset bitrate if it changed in some way to avoid enconder fluctuations
// Only reset bitrate if it changed in some way to avoid encoder fluctuations
if (parameters.encodings[0].maxBitrate !== normalizedBitrate) {
parameters.encodings[0].maxBitrate = normalizedBitrate;
sender.setParameters(parameters)

View File

@ -200,7 +200,7 @@ class VideoList extends Component {
canvasWidth, canvasHeight, gridGutter,
ASPECT_RATIO, numItems, col,
);
// We need a minimun of 2 rows and columns for the focused
// We need a minimum of 2 rows and columns for the focused
const focusedConstraint = hasFocusedItem ? testGrid.rows > 1 && testGrid.columns > 1 : true;
const betterThanCurrent = testGrid.filledArea > currentGrid.filledArea;
return focusedConstraint && betterThanCurrent ? testGrid : currentGrid;

View File

@ -1,14 +1,20 @@
import React, { useEffect, useRef, useState } from 'react';
import React, {
useEffect,
useRef,
useState,
useMemo,
} from 'react';
import { useSubscription, useMutation } from '@apollo/client';
import {
AssetRecordType,
} from '@tldraw/tldraw';
import { throttle } from 'radash';
import {
CURRENT_PRESENTATION_PAGE_SUBSCRIPTION,
CURRENT_PAGE_ANNOTATIONS_STREAM,
CURRENT_PAGE_WRITERS_SUBSCRIPTION,
CURSOR_SUBSCRIPTION,
} from './queries';
import { CURSOR_SUBSCRIPTION } from './cursors/queries';
import {
initDefaultPages,
persistShape,
@ -17,7 +23,6 @@ import {
toggleToolsAnimations,
formatAnnotations,
} from './service';
import CursorService from './cursors/service';
import SettingsService from '/imports/ui/services/settings';
import Auth from '/imports/ui/services/auth';
import {
@ -35,6 +40,7 @@ import {
PRES_ANNOTATION_DELETE,
PRES_ANNOTATION_SUBMIT,
PRESENTATION_SET_PAGE,
PRESENTATION_PUBLISH_CURSOR,
} from '../presentation/mutations';
const WHITEBOARD_CONFIG = window.meetingClientSettings.public.whiteboard;
@ -76,6 +82,7 @@ const WhiteboardContainer = (props) => {
const [presentationSetPage] = useMutation(PRESENTATION_SET_PAGE);
const [presentationDeleteAnnotations] = useMutation(PRES_ANNOTATION_DELETE);
const [presentationSubmitAnnotations] = useMutation(PRES_ANNOTATION_SUBMIT);
const [presentationPublishCursor] = useMutation(PRESENTATION_PUBLISH_CURSOR);
const setPresentationPage = (pageId) => {
presentationSetPage({
@ -131,6 +138,23 @@ const WhiteboardContainer = (props) => {
persistShape(shape, whiteboardId, isModerator, submitAnnotations);
};
const publishCursorUpdate = (payload) => {
const { whiteboardId, xPercent, yPercent } = payload;
presentationPublishCursor({
variables: {
whiteboardId,
xPercent,
yPercent,
},
});
};
const throttledPublishCursorUpdate = useMemo(() => throttle(
{ interval: WHITEBOARD_CONFIG.cursorInterval },
publishCursorUpdate,
), []);
const isMultiUserActive = whiteboardWriters?.length > 0;
const { data: currentUser } = useCurrentUser((user) => ({
@ -282,7 +306,7 @@ const WhiteboardContainer = (props) => {
}}
{...props}
meetingId={Auth.meetingID}
publishCursorUpdate={CursorService.publishCursorUpdate}
publishCursorUpdate={throttledPublishCursorUpdate}
otherCursors={cursorArray}
hideViewersCursor={meeting?.data?.lockSettings?.hideViewersCursor}
/>

View File

@ -1,337 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { Meteor } from 'meteor/meteor';
import Cursor from './cursor/component';
import PositionLabel from './position-label/component';
const XS_OFFSET = 8;
const SMALL_OFFSET = 18;
const XL_OFFSET = 85;
const BOTTOM_CAM_HANDLE_HEIGHT = 10;
const PRES_TOOLBAR_HEIGHT = 35;
const baseName = window.meetingClientSettings.public.app.cdn + window.meetingClientSettings.public.app.basename;
const makeCursorUrl = (filename) => `${baseName}/resources/images/whiteboard-cursor/${filename}`;
const TOOL_CURSORS = {
select: 'default',
erase: 'crosshair',
arrow: 'crosshair',
draw: `url('${makeCursorUrl('pencil.png')}') 2 22, default`,
rectangle: `url('${makeCursorUrl('square.png')}'), default`,
ellipse: `url('${makeCursorUrl('ellipse.png')}'), default`,
triangle: `url('${makeCursorUrl('triangle.png')}'), default`,
line: `url('${makeCursorUrl('line.png')}'), default`,
text: `url('${makeCursorUrl('text.png')}'), default`,
sticky: `url('${makeCursorUrl('square.png')}'), default`,
pan: 'grab',
grabbing: 'grabbing',
moving: 'move',
};
const Cursors = (props) => {
const cursorWrapper = React.useRef();
const [active, setActive] = React.useState(false);
const [pos, setPos] = React.useState({ x: 0, y: 0 });
const {
whiteboardId,
otherCursors,
currentUser,
currentPoint,
tldrawCamera,
publishCursorUpdate,
children,
hasWBAccess,
isMultiUserActive,
isPanning,
isMoving,
currentTool,
toggleToolsAnimations,
whiteboardToolbarAutoHide,
application,
whiteboardWriters,
} = props;
const [panGrabbing, setPanGrabbing] = React.useState(false);
const start = (event) => {
const targetElement = event?.target;
const className = targetElement instanceof SVGElement
? targetElement?.className?.baseVal
: targetElement?.className;
const hasTlPartial = className?.includes('tl-');
if (hasTlPartial) {
event?.preventDefault();
}
if (whiteboardToolbarAutoHide) toggleToolsAnimations('fade-out', 'fade-in', application?.animations ? '.3s' : '0s');
setActive(true);
};
const handleGrabbing = () => setPanGrabbing(true);
const handleReleaseGrab = () => setPanGrabbing(false);
const end = () => {
if (whiteboardId && (hasWBAccess || currentUser?.presenter)) {
publishCursorUpdate({
xPercent: -1.0,
yPercent: -1.0,
whiteboardId,
});
}
if (whiteboardToolbarAutoHide) toggleToolsAnimations('fade-in', 'fade-out', application?.animations ? '3s' : '0s');
setActive(false);
};
const moved = (event) => {
const { type, x, y } = event;
const nav = document.getElementById('Navbar');
const getSibling = (el) => {
if (el?.previousSibling && !el?.previousSibling?.hasAttribute('data-test')) {
return el?.previousSibling;
}
return null;
};
const panel = getSibling(nav);
const webcams = document.getElementById('cameraDock');
const subPanel = panel && getSibling(panel);
const camPosition = document.getElementById('layout')?.getAttribute('data-cam-position') || null;
const sl = document.getElementById('layout')?.getAttribute('data-layout');
const presentationContainer = document.querySelector('[data-test="presentationContainer"]');
const presentation = document.getElementById('currentSlideText')?.parentElement;
const banners = document.querySelectorAll('[data-test="notificationBannerBar"]');
let yOffset = 0;
let xOffset = 0;
const calcPresOffset = () => {
yOffset
+= (parseFloat(presentationContainer?.style?.height)
- (parseFloat(presentation?.style?.height)
+ (currentUser.presenter ? PRES_TOOLBAR_HEIGHT : 0))
) / 2;
xOffset
+= (parseFloat(presentationContainer?.style?.width)
- parseFloat(presentation?.style?.width)
) / 2;
};
// If the presentation container is the full screen element we don't
// need any offsets
const { webkitFullscreenElement, fullscreenElement } = document;
const fsEl = webkitFullscreenElement || fullscreenElement;
if (fsEl?.getAttribute('data-test') === 'presentationContainer') {
calcPresOffset();
return setPos({ x: x - xOffset, y: y - yOffset });
}
if (nav) yOffset += parseFloat(nav?.style?.height);
if (panel) xOffset += parseFloat(panel?.style?.width);
if (subPanel) xOffset += parseFloat(subPanel?.style?.width);
// offset native tldraw eraser animation container
const overlay = document.getElementsByClassName('tl-overlay')[0];
if (overlay) overlay.style.left = '0px';
if (type === 'touchmove') {
calcPresOffset();
if (!active) {
setActive(true);
}
const newX = event?.changedTouches[0]?.clientX - xOffset;
const newY = event?.changedTouches[0]?.clientY - yOffset;
return setPos({ x: newX, y: newY });
}
if (document?.documentElement?.dir === 'rtl') {
xOffset = 0;
if (presentationContainer && presentation) {
calcPresOffset();
}
if (sl.includes('custom')) {
if (webcams) {
if (camPosition === 'contentTop' || !camPosition) {
yOffset += (parseFloat(webcams?.style?.height || 0) + BOTTOM_CAM_HANDLE_HEIGHT);
}
if (camPosition === 'contentBottom') {
yOffset -= BOTTOM_CAM_HANDLE_HEIGHT;
}
if (camPosition === 'contentRight') {
xOffset += (parseFloat(webcams?.style?.width || 0) + SMALL_OFFSET);
}
}
}
if (sl?.includes('smart')) {
if (panel || subPanel) {
const dockPos = webcams?.getAttribute('data-position');
if (dockPos === 'contentTop') {
yOffset += (parseFloat(webcams?.style?.height || 0) + SMALL_OFFSET);
}
}
}
if (webcams && sl?.includes('videoFocus')) {
xOffset += parseFloat(nav?.style?.width);
yOffset += (parseFloat(panel?.style?.height || 0) - XL_OFFSET);
}
} else {
if (sl.includes('custom')) {
if (webcams) {
if (camPosition === 'contentTop' || !camPosition) {
yOffset += (parseFloat(webcams?.style?.height) || 0) + XS_OFFSET;
}
if (camPosition === 'contentBottom') {
yOffset -= BOTTOM_CAM_HANDLE_HEIGHT;
}
if (camPosition === 'contentLeft') {
xOffset += (parseFloat(webcams?.style?.width) || 0) + SMALL_OFFSET;
}
}
}
if (sl.includes('smart')) {
if (panel || subPanel) {
const dockPos = webcams?.getAttribute('data-position');
if (dockPos === 'contentLeft') {
xOffset += (parseFloat(webcams?.style?.width || 0) + SMALL_OFFSET);
}
if (dockPos === 'contentTop') {
yOffset += (parseFloat(webcams?.style?.height || 0) + SMALL_OFFSET);
}
}
if (!panel && !subPanel) {
if (webcams) {
xOffset = parseFloat(webcams?.style?.width || 0) + SMALL_OFFSET;
}
}
}
if (sl?.includes('videoFocus')) {
if (webcams) {
xOffset = parseFloat(subPanel?.style?.width);
yOffset = parseFloat(panel?.style?.height);
}
}
if (presentationContainer && presentation) {
calcPresOffset();
}
}
if (banners) {
banners.forEach((el) => {
yOffset += parseFloat(window.getComputedStyle(el).height);
});
}
return setPos({ x: event.x - xOffset, y: event.y - yOffset });
};
React.useEffect(() => {
const currentCursor = cursorWrapper?.current;
currentCursor?.addEventListener('mouseenter', start);
currentCursor?.addEventListener('touchstart', start);
currentCursor?.addEventListener('mouseleave', end);
currentCursor?.addEventListener('mousedown', handleGrabbing);
currentCursor?.addEventListener('mouseup', handleReleaseGrab);
currentCursor?.addEventListener('touchend', end);
currentCursor?.addEventListener('mousemove', moved);
currentCursor?.addEventListener('touchmove', moved);
return () => {
currentCursor?.removeEventListener('mouseenter', start);
currentCursor?.addEventListener('touchstart', start);
currentCursor?.removeEventListener('mouseleave', end);
currentCursor?.removeEventListener('mousedown', handleGrabbing);
currentCursor?.removeEventListener('mouseup', handleReleaseGrab);
currentCursor?.removeEventListener('touchend', end);
currentCursor?.removeEventListener('mousemove', moved);
currentCursor?.removeEventListener('touchmove', moved);
};
}, [cursorWrapper, whiteboardId, currentUser?.presenter, whiteboardToolbarAutoHide]);
let cursorType = hasWBAccess || currentUser?.presenter ? TOOL_CURSORS[currentTool] : 'default';
if (isPanning) {
if (panGrabbing) {
cursorType = TOOL_CURSORS.grabbing;
} else {
cursorType = TOOL_CURSORS.pan;
}
}
if (isMoving) cursorType = TOOL_CURSORS.moving;
return (
<span key={`cursor-wrapper-${whiteboardId}`} ref={cursorWrapper}>
<div style={{ height: '100%', cursor: cursorType }}>
{((active && hasWBAccess) || (active && currentUser?.presenter)) && (
<PositionLabel
pos={pos}
otherCursors={otherCursors}
currentUser={currentUser}
currentPoint={currentPoint}
tldrawCamera={tldrawCamera}
publishCursorUpdate={publishCursorUpdate}
whiteboardId={whiteboardId}
isMultiUserActive={isMultiUserActive}
/>
)}
{children}
</div>
{otherCursors
.filter((c) => c?.xPercent && c.xPercent !== -1.0 && c?.yPercent && c.yPercent !== -1.0)
.map((c) => {
if (c && currentUser?.userId !== c?.userId) {
if (c.user.presenter) {
return (
<Cursor
key={`${c?.userId}`}
name={c?.user.name}
color="#C70039"
x={c?.xPercent}
y={c?.yPercent}
tldrawCamera={tldrawCamera}
isMultiUserActive={isMultiUserActive}
owner
/>
);
}
return whiteboardWriters?.some((writer) => writer.userId === c?.userId)
&& (
<Cursor
key={`${c?.userId}`}
name={c?.user.name}
color="#AFE1AF"
x={c?.xPercent}
y={c?.yPercent}
tldrawCamera={tldrawCamera}
isMultiUserActive={isMultiUserActive}
owner
/>
);
}
return null;
})}
</span>
);
};
Cursors.propTypes = {
whiteboardId: PropTypes.string,
otherCursors: PropTypes.arrayOf(PropTypes.shape).isRequired,
currentUser: PropTypes.shape({
userId: PropTypes.string.isRequired,
presenter: PropTypes.bool.isRequired,
}).isRequired,
currentPoint: PropTypes.arrayOf(PropTypes.number),
tldrawCamera: PropTypes.shape({
point: PropTypes.arrayOf(PropTypes.number).isRequired,
zoom: PropTypes.number.isRequired,
}),
publishCursorUpdate: PropTypes.func.isRequired,
children: PropTypes.arrayOf(PropTypes.element).isRequired,
isMultiUserActive: PropTypes.bool.isRequired,
isPanning: PropTypes.bool.isRequired,
isMoving: PropTypes.bool.isRequired,
currentTool: PropTypes.string,
toggleToolsAnimations: PropTypes.func.isRequired,
};
Cursors.defaultProps = {
whiteboardId: undefined,
currentPoint: undefined,
tldrawCamera: undefined,
currentTool: null,
};
export default Cursors;

View File

@ -1,29 +0,0 @@
import React from 'react';
import { useSubscription } from '@apollo/client';
import SettingsService from '/imports/ui/services/settings';
import Cursors from './component';
import Service from './service';
import { CURSOR_SUBSCRIPTION } from './queries';
import { omit } from 'radash';
const CursorsContainer = (props) => {
const { data: cursorData } = useSubscription(CURSOR_SUBSCRIPTION);
const { pres_page_cursor: cursorArray } = (cursorData || []);
if (!cursorData) return null;
return (
<Cursors
{...{
application: SettingsService?.application,
publishCursorUpdate: Service.publishCursorUpdate,
otherCursors: cursorArray,
currentPoint: props.tldrawAPI?.currentPoint,
tldrawCamera: props.tldrawAPI?.getPageState().camera,
}}
{...omit(props, ['tldrawAPI'])}
/>
)
};
export default CursorsContainer;

View File

@ -1,93 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Meteor } from 'meteor/meteor';
const { pointerDiameter } = window.meetingClientSettings.public.whiteboard;
const Cursor = (props) => {
const {
name,
color,
x,
y,
currentPoint,
tldrawCamera,
isMultiUserActive,
owner = false,
} = props;
const z = !owner ? 2 : 1;
let _x = null;
let _y = null;
if (!currentPoint) {
_x = (x + tldrawCamera?.point[0]) * tldrawCamera?.zoom;
_y = (y + tldrawCamera?.point[1]) * tldrawCamera?.zoom;
}
const transitionStyle = owner ? { transition: 'left 0.3s ease-out, top 0.3s ease-out' } : {};
return (
<>
<div
style={{
zIndex: z,
position: 'absolute',
left: (_x || x) - pointerDiameter / 2,
top: (_y || y) - pointerDiameter / 2,
width: pointerDiameter,
height: pointerDiameter,
borderRadius: '50%',
background: `${color}`,
pointerEvents: 'none',
...transitionStyle,
}}
/>
{isMultiUserActive && (
<div
style={{
zIndex: z,
position: 'absolute',
pointerEvents: 'none',
left: (_x || x) + 3.75,
top: (_y || y) + 3,
paddingLeft: '.25rem',
paddingRight: '.25rem',
paddingBottom: '.1rem',
lineHeight: '1rem',
borderRadius: '2px',
color: '#FFF',
backgroundColor: color,
border: `1px solid ${color}`,
...transitionStyle,
}}
data-test="whiteboardCursorIndicator"
>
{name}
</div>
)}
</>
);
};
Cursor.propTypes = {
name: PropTypes.string.isRequired,
color: PropTypes.string.isRequired,
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired,
currentPoint: PropTypes.arrayOf(PropTypes.number),
tldrawCamera: PropTypes.shape({
point: PropTypes.arrayOf(PropTypes.number).isRequired,
zoom: PropTypes.number.isRequired,
}),
isMultiUserActive: PropTypes.bool.isRequired,
owner: PropTypes.bool,
};
Cursor.defaultProps = {
owner: false,
currentPoint: undefined,
tldrawCamera: undefined,
};
export default Cursor;

View File

@ -1,93 +0,0 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import logger from '/imports/startup/client/logger';
import Cursor from '../cursor/component';
const PositionLabel = (props) => {
const {
currentUser,
currentPoint,
tldrawCamera,
publishCursorUpdate,
whiteboardId,
pos,
isMultiUserActive,
} = props;
const { name, color, userId } = currentUser;
const { x, y } = pos;
const { zoom, point: tldrawPoint } = tldrawCamera;
React.useEffect(() => {
try {
const point = [x, y];
publishCursorUpdate({
xPercent:
point[0] / zoom - tldrawPoint[0],
yPercent:
point[1] / zoom - tldrawPoint[1],
whiteboardId,
});
} catch (error) {
logger.error({
logCode: 'cursor_update__error',
extraInfo: { error },
}, 'Whiteboard catch error on cursor update');
}
}, [x, y, zoom, tldrawPoint]);
// eslint-disable-next-line arrow-body-style
React.useEffect(() => {
return () => {
// Disable cursor on unmount
publishCursorUpdate({
xPercent: -1.0,
yPercent: -1.0,
whiteboardId,
});
};
}, []);
return (
<>
<div style={{ position: 'absolute', height: '100%', width: '100%' }}>
<Cursor
key={`${userId}-label`}
name={name}
color={color}
x={x}
y={y}
currentPoint={currentPoint}
tldrawCamera={tldrawCamera}
isMultiUserActive={isMultiUserActive}
/>
</div>
</>
);
};
PositionLabel.propTypes = {
currentUser: PropTypes.shape({
name: PropTypes.string.isRequired,
color: PropTypes.string.isRequired,
userId: PropTypes.string.isRequired,
}).isRequired,
currentPoint: PropTypes.arrayOf(PropTypes.number).isRequired,
tldrawCamera: PropTypes.shape({
point: PropTypes.arrayOf(PropTypes.number).isRequired,
zoom: PropTypes.number.isRequired,
}).isRequired,
publishCursorUpdate: PropTypes.func.isRequired,
whiteboardId: PropTypes.string,
pos: PropTypes.shape({
x: PropTypes.number.isRequired,
y: PropTypes.number.isRequired,
}).isRequired,
isMultiUserActive: PropTypes.bool.isRequired,
};
PositionLabel.defaultProps = {
whiteboardId: undefined,
};
export default PositionLabel;

View File

@ -1,20 +0,0 @@
import { gql } from '@apollo/client';
export const CURSOR_SUBSCRIPTION = gql`subscription CursorSubscription {
pres_page_cursor {
isCurrentPage
lastUpdatedAt
pageId
presentationId
userId
xPercent
yPercent
user {
name
presenter
role
}
}
}`;
export default CURSOR_SUBSCRIPTION;

View File

@ -1,14 +0,0 @@
import Auth from '/imports/ui/services/auth';
import { throttle } from '/imports/utils/throttle';
import { makeCall } from '/imports/ui/services/api';
const { cursorInterval: CURSOR_INTERVAL } = window.meetingClientSettings.public.whiteboard;
const publishCursorUpdate = throttle(
(payload) => makeCall('publishCursorUpdate', Auth.meetingID, Auth.userID, payload),
CURSOR_INTERVAL,
);
export default {
publishCursorUpdate,
};

View File

@ -13,9 +13,9 @@ const useCursor = (publishCursorUpdate, whiteboardId) => {
useEffect(() => {
publishCursorUpdate({
whiteboardId,
xPercent: cursorPosition?.x,
yPercent: cursorPosition?.y,
whiteboardId,
});
}, [cursorPosition, publishCursorUpdate, whiteboardId]);

View File

@ -112,4 +112,21 @@ export const CURRENT_PAGE_WRITERS_QUERY = gql`query currentPageWritersQuery {
}
}`;
export const CURSOR_SUBSCRIPTION = gql`subscription CursorSubscription {
pres_page_cursor {
isCurrentPage
lastUpdatedAt
pageId
presentationId
userId
xPercent
yPercent
user {
name
presenter
role
}
}
}`;
export default CURRENT_PAGE_ANNOTATIONS_QUERY;

View File

@ -287,4 +287,4 @@ export {
notifyShapeNumberExceeded,
toggleToolsAnimations,
formatAnnotations,
};
};

View File

@ -62,7 +62,7 @@ const TldrawV2GlobalStyle = createGlobalStyle`
.tlui-navigation-zone,
.tlui-help-menu,
.tlui-debug-panel {
display: none;
display: none !important;
}
.tlui-style-panel__wrapper {
@ -93,8 +93,8 @@ const TldrawV2GlobalStyle = createGlobalStyle`
[data-testid="main.menu"],
[data-testid="tools.laser"],
[data-testid="tools.asset"],
.tlui-menu-zone__controls > :nth-child(1),
.tlui-menu-zone__controls > :nth-child(2) {
.tlui-buttons__horizontal > :nth-child(1),
.tlui-buttons__horizontal > :nth-child(2) {
display: none;
}

View File

@ -108,7 +108,7 @@ class LocalCollectionSynchronizer {
const subscription = SubscriptionRegistry.getSubscription(this.serverCollection._name);
// If the subscriptionId changes means the subscriptions was redone
// or theres more than one subscription per collection
// or there's more than one subscription per collection
if (subscription && (this.lastSubscriptionId !== subscription.subscriptionId)) {
const wasEmpty = this.lastSubscriptionId === '';
this.lastSubscriptionId = subscription.subscriptionId;

View File

@ -18,7 +18,7 @@ export function makeCall(name, ...args) {
return new Promise(async (resolve, reject) => {
if (Meteor.status().connected) {
const result = await Meteor.callAsync(name, ...args);
// all tested cases it returnd 0, empty array or undefined
// all tested cases it returned 0, empty array or undefined
resolve(result);
} else {
const failureString = `Call to ${name} failed because Meteor is not connected`;

View File

@ -3,7 +3,7 @@ import { createIntl } from 'react-intl';
const FALLBACK_ON_EMPTY_STRING = window.meetingClientSettings.public.app.fallbackOnEmptyLocaleString;
/**
* Use this if you need any translation outside of React lifecyle.
* Use this if you need any translation outside of React lifecycle.
*/
class BBBIntl {
_intl = {

View File

@ -7,7 +7,7 @@ import { isObject, isArray, isString } from 'radash';
export default class StorageTracker {
constructor(storage, prefix = '') {
if (!(storage instanceof Storage)) {
throw `Expecting a instanceof Storage recieve a '${storage.constructor.name}' instance`;
throw `Expecting a instanceof Storage receive a '${storage.constructor.name}' instance`;
}
this._trackers = {};

View File

@ -185,7 +185,7 @@ export default class WebRtcPeer extends EventEmitter2 {
return this.peerConnection.setLocalDescription(rtcSessionDescription);
}
// Public method can be overriden via options
// Public method can be overridden via options
mediaStreamFactory() {
if (this.videoStream || this.audioStream) {
return Promise.resolve();

View File

@ -92,7 +92,7 @@ export default new RegExp(
// IP address dotted notation octets
// excludes loopback network 0.0.0.0
// excludes reserved space >= 224.0.0.0
// excludes network & broacast addresses
// excludes network & broadcast addresses
// (first & last IP address of each class)
'(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])' +
'(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}' +

View File

@ -4,7 +4,7 @@ export const MYSTERY_NUM = 2;
export const STEP = 25;
export default class SlideCalcUtil {
// After lots of trial and error on why synching doesn't work properly, I found I had to
// After lots of trial and error on why syncing doesn't work properly, I found I had to
// multiply the coordinates by 2. There's something I don't understand probably on the
// canvas coordinate system. (ralam feb 22, 2012)

View File

@ -1,7 +1,7 @@
{
"name": "bbb-html5-client",
"requires": true,
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@aashutoshrathi/word-wrap": {
"version": "1.2.6",
@ -4066,13 +4066,13 @@
}
},
"dom-serializer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
}
},
"domelementtype": {
@ -4081,21 +4081,21 @@
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
},
"domhandler": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"requires": {
"domelementtype": "^2.2.0"
"domelementtype": "^2.3.0"
}
},
"domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
}
},
"electron-to-chromium": {
@ -4139,9 +4139,9 @@
}
},
"entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
},
"error-ex": {
"version": "1.3.2",
@ -5231,14 +5231,14 @@
"integrity": "sha512-9gux8QhvjRO/erSnDPv28noDZcPZmYE7e1vFsBLKLlRlKDSqNJYebj6Qz1TGd5lsRV+X+xYyjCKjuZdABinWjA=="
},
"htmlparser2": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0",
"domutils": "^2.5.2",
"entities": "^2.0.0"
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"entities": "^4.4.0"
}
},
"human-signals": {
@ -6143,6 +6143,7 @@
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
"integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
"bundled": true,
"requires": {
"bn.js": "^4.0.0",
"inherits": "^2.0.1",
@ -6153,7 +6154,8 @@
"bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
"bundled": true
}
}
},
@ -6161,6 +6163,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz",
"integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==",
"bundled": true,
"requires": {
"es6-object-assign": "^1.1.0",
"is-nan": "^1.2.1",
@ -6171,27 +6174,32 @@
"available-typed-arrays": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz",
"integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA=="
"integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==",
"bundled": true
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"bundled": true
},
"bn.js": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==",
"bundled": true
},
"brorand": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
"integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
"bundled": true
},
"browserify-aes": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
"bundled": true,
"requires": {
"buffer-xor": "^1.0.3",
"cipher-base": "^1.0.0",
@ -6205,6 +6213,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
"integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
"bundled": true,
"requires": {
"browserify-aes": "^1.0.4",
"browserify-des": "^1.0.0",
@ -6215,6 +6224,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
"integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
"bundled": true,
"requires": {
"cipher-base": "^1.0.1",
"des.js": "^1.0.0",
@ -6226,6 +6236,7 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
"integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
"bundled": true,
"requires": {
"bn.js": "^5.0.0",
"randombytes": "^2.0.1"
@ -6235,6 +6246,7 @@
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
"integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
"bundled": true,
"requires": {
"bn.js": "^5.1.1",
"browserify-rsa": "^4.0.1",
@ -6251,6 +6263,7 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
"integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
"bundled": true,
"requires": {
"pako": "~1.0.5"
}
@ -6259,6 +6272,7 @@
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"bundled": true,
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
@ -6267,17 +6281,20 @@
"buffer-xor": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
"bundled": true
},
"builtin-status-codes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
"integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
"integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
"bundled": true
},
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"bundled": true,
"requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
@ -6287,6 +6304,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
"integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
"bundled": true,
"requires": {
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
@ -6295,17 +6313,20 @@
"console-browserify": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
"integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA=="
"integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==",
"bundled": true
},
"constants-browserify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
"integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
"integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
"bundled": true
},
"create-ecdh": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
"integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
"bundled": true,
"requires": {
"bn.js": "^4.1.0",
"elliptic": "^6.5.3"
@ -6314,7 +6335,8 @@
"bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
"bundled": true
}
}
},
@ -6322,6 +6344,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
"bundled": true,
"requires": {
"cipher-base": "^1.0.1",
"inherits": "^2.0.1",
@ -6334,6 +6357,7 @@
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
"bundled": true,
"requires": {
"cipher-base": "^1.0.3",
"create-hash": "^1.1.0",
@ -6347,6 +6371,7 @@
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
"integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
"bundled": true,
"requires": {
"browserify-cipher": "^1.0.0",
"browserify-sign": "^4.0.0",
@ -6365,6 +6390,7 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"bundled": true,
"requires": {
"object-keys": "^1.0.12"
}
@ -6373,6 +6399,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
"integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
"bundled": true,
"requires": {
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0"
@ -6382,6 +6409,7 @@
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
"bundled": true,
"requires": {
"bn.js": "^4.1.0",
"miller-rabin": "^4.0.0",
@ -6391,19 +6419,22 @@
"bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
"bundled": true
}
}
},
"domain-browser": {
"version": "4.22.0",
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz",
"integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw=="
"integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==",
"bundled": true
},
"elliptic": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
"integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
"bundled": true,
"requires": {
"bn.js": "^4.11.9",
"brorand": "^1.1.0",
@ -6417,7 +6448,8 @@
"bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
"bundled": true
}
}
},
@ -6425,6 +6457,7 @@
"version": "1.18.3",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz",
"integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==",
"bundled": true,
"requires": {
"call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1",
@ -6448,6 +6481,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"bundled": true,
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
@ -6457,17 +6491,20 @@
"es6-object-assign": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
"integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw="
"integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=",
"bundled": true
},
"events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
"bundled": true
},
"evp_bytestokey": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
"integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
"bundled": true,
"requires": {
"md5.js": "^1.3.4",
"safe-buffer": "^5.1.1"
@ -6476,17 +6513,20 @@
"foreach": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
"integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
"bundled": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"bundled": true
},
"get-intrinsic": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"bundled": true,
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
@ -6497,6 +6537,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"bundled": true,
"requires": {
"function-bind": "^1.1.1"
}
@ -6504,17 +6545,20 @@
"has-bigints": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
"bundled": true
},
"has-symbols": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
"bundled": true
},
"hash-base": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
"integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
"bundled": true,
"requires": {
"inherits": "^2.0.4",
"readable-stream": "^3.6.0",
@ -6525,6 +6569,7 @@
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
"integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
"bundled": true,
"requires": {
"inherits": "^2.0.3",
"minimalistic-assert": "^1.0.1"
@ -6534,6 +6579,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
"integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
"bundled": true,
"requires": {
"hash.js": "^1.0.3",
"minimalistic-assert": "^1.0.0",
@ -6543,22 +6589,26 @@
"https-browserify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
"bundled": true
},
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"bundled": true
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"bundled": true
},
"is-arguments": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz",
"integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==",
"bundled": true,
"requires": {
"call-bind": "^1.0.0"
}
@ -6566,12 +6616,14 @@
"is-bigint": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz",
"integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA=="
"integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==",
"bundled": true
},
"is-boolean-object": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz",
"integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==",
"bundled": true,
"requires": {
"call-bind": "^1.0.2"
}
@ -6579,22 +6631,26 @@
"is-callable": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz",
"integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ=="
"integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==",
"bundled": true
},
"is-date-object": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz",
"integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A=="
"integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==",
"bundled": true
},
"is-generator-function": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz",
"integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A=="
"integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==",
"bundled": true
},
"is-nan": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
"integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
"bundled": true,
"requires": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3"
@ -6603,17 +6659,20 @@
"is-negative-zero": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
"integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w=="
"integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
"bundled": true
},
"is-number-object": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz",
"integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw=="
"integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
"bundled": true
},
"is-regex": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz",
"integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==",
"bundled": true,
"requires": {
"call-bind": "^1.0.2",
"has-symbols": "^1.0.2"
@ -6622,12 +6681,14 @@
"is-string": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz",
"integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w=="
"integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==",
"bundled": true
},
"is-symbol": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
"bundled": true,
"requires": {
"has-symbols": "^1.0.2"
}
@ -6636,6 +6697,7 @@
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz",
"integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==",
"bundled": true,
"requires": {
"available-typed-arrays": "^1.0.2",
"call-bind": "^1.0.2",
@ -6648,6 +6710,7 @@
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
"integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
"bundled": true,
"requires": {
"hash-base": "^3.0.0",
"inherits": "^2.0.1",
@ -6658,6 +6721,7 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
"integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
"bundled": true,
"requires": {
"bn.js": "^4.0.0",
"brorand": "^1.0.1"
@ -6666,29 +6730,34 @@
"bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
"bundled": true
}
}
},
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
"bundled": true
},
"minimalistic-crypto-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
"integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
"bundled": true
},
"object-inspect": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz",
"integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw=="
"integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==",
"bundled": true
},
"object-is": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
"integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
"bundled": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@ -6697,12 +6766,14 @@
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"bundled": true
},
"object.assign": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
"integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
"bundled": true,
"requires": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3",
@ -6713,17 +6784,20 @@
"os-browserify": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
"integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
"integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
"bundled": true
},
"pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
"bundled": true
},
"parse-asn1": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
"integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
"bundled": true,
"requires": {
"asn1.js": "^5.2.0",
"browserify-aes": "^1.0.0",
@ -6735,12 +6809,14 @@
"path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
"bundled": true
},
"pbkdf2": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
"integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
"bundled": true,
"requires": {
"create-hash": "^1.1.2",
"create-hmac": "^1.1.4",
@ -6752,12 +6828,14 @@
"process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
"integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
"bundled": true
},
"public-encrypt": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
"integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
"bundled": true,
"requires": {
"bn.js": "^4.1.0",
"browserify-rsa": "^4.0.0",
@ -6770,29 +6848,34 @@
"bn.js": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
"bundled": true
}
}
},
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
"bundled": true
},
"querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
"bundled": true
},
"querystring-es3": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
"bundled": true
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"bundled": true,
"requires": {
"safe-buffer": "^5.1.0"
}
@ -6801,6 +6884,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
"integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
"bundled": true,
"requires": {
"randombytes": "^2.0.5",
"safe-buffer": "^5.1.0"
@ -6810,6 +6894,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"bundled": true,
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
@ -6820,6 +6905,7 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
"integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
"bundled": true,
"requires": {
"hash-base": "^3.0.0",
"inherits": "^2.0.1"
@ -6828,22 +6914,26 @@
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"bundled": true
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"bundled": true
},
"setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
"integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
"bundled": true
},
"sha.js": {
"version": "2.4.11",
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
"bundled": true,
"requires": {
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
@ -6853,6 +6943,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
"integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
"bundled": true,
"requires": {
"inherits": "~2.0.4",
"readable-stream": "^3.5.0"
@ -6862,6 +6953,7 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz",
"integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==",
"bundled": true,
"requires": {
"builtin-status-codes": "^3.0.0",
"inherits": "^2.0.4",
@ -6869,10 +6961,20 @@
"xtend": "^4.0.2"
}
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"bundled": true,
"requires": {
"safe-buffer": "~5.2.0"
}
},
"string.prototype.trimend": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
"integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
"bundled": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
@ -6882,23 +6984,17 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
"integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
"bundled": true,
"requires": {
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
}
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
}
},
"timers-browserify": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz",
"integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==",
"bundled": true,
"requires": {
"setimmediate": "^1.0.4"
}
@ -6906,12 +7002,14 @@
"tty-browserify": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
"integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw=="
"integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==",
"bundled": true
},
"unbox-primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
"integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
"bundled": true,
"requires": {
"function-bind": "^1.1.1",
"has-bigints": "^1.0.1",
@ -6923,6 +7021,7 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
"integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
"bundled": true,
"requires": {
"punycode": "1.3.2",
"querystring": "0.2.0"
@ -6931,7 +7030,8 @@
"punycode": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
"bundled": true
}
}
},
@ -6939,6 +7039,7 @@
"version": "0.12.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz",
"integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==",
"bundled": true,
"requires": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
@ -6951,17 +7052,20 @@
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"bundled": true
},
"vm-browserify": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
"bundled": true
},
"which-boxed-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"bundled": true,
"requires": {
"is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0",
@ -6974,6 +7078,7 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz",
"integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==",
"bundled": true,
"requires": {
"available-typed-arrays": "^1.0.2",
"call-bind": "^1.0.0",
@ -6987,7 +7092,8 @@
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"bundled": true
}
}
},
@ -8437,13 +8543,13 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sanitize-html": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.7.1.tgz",
"integrity": "sha512-oOpe8l4J8CaBk++2haoN5yNI5beekjuHv3JRPKUx/7h40Rdr85pemn4NkvUB3TcBP7yjat574sPlcMAyv4UQig==",
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.12.1.tgz",
"integrity": "sha512-Plh+JAn0UVDpBRP/xEjsk+xDCoOvMBwQUf/K+/cBAVuTbtX8bj2VB7S1sL1dssVpykqp0/KPSesHrqXtokVBpA==",
"requires": {
"deepmerge": "^4.2.2",
"escape-string-regexp": "^4.0.0",
"htmlparser2": "^6.0.0",
"htmlparser2": "^8.0.0",
"is-plain-object": "^5.0.0",
"parse-srcset": "^1.0.2",
"postcss": "^8.3.11"
@ -8738,6 +8844,14 @@
"resolved": "https://registry.npmjs.org/strictdom/-/strictdom-1.0.1.tgz",
"integrity": "sha512-cEmp9QeXXRmjj/rVp9oyiqcvyocWab/HaoN4+bwFeZ7QzykJD6L3yD4v12K1x0tHpqRqVpJevN3gW7kyM39Bqg=="
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
}
},
"string-argv": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
@ -8810,14 +8924,6 @@
"es-abstract": "^1.22.1"
}
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
}
},
"stringify-object": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",

View File

@ -96,7 +96,7 @@
"recharts": "^2.7.2",
"reconnecting-websocket": "~v4.4.0",
"redis": "^3.1.2",
"sanitize-html": "2.7.1",
"sanitize-html": "2.12.1",
"scheduler": "^0.20.2",
"sdp-transform": "2.7.0",
"smile2emoji": "^3.8.3",

View File

@ -162,11 +162,11 @@ public:
# emojiSize: size of the emoji in 'em' units
emojiSize: 2
# If enabled, before joining microphone the client will perform a trickle
# ICE against Kurento and use the information about successfull
# ICE against Kurento and use the information about successful
# candidate-pairs to filter out local candidates in SIP.js's SDP.
# Try enabling this setting in scenarios where the listenonly mode works,
# but microphone doesn't (for example, when using VPN).
# For compatibility check "Browser compatbility" section in:
# For compatibility check "Browser compatibility" section in:
# https://developer.mozilla.org/en-US/docs/Web/API/RTCDtlsTransport/iceTransport
# This is an EXPERIMENTAL setting and the default value is false
# experimentalUseKmsTrickleIceForMicrophone: false
@ -216,7 +216,7 @@ public:
overrideLocale: null
#Audio constraints for microphone. Use this to control browser's
#filters, such as AGC (Auto Gain Control) , Echo Cancellation,
#Noise Supression, etc.
#Noise Suppression, etc.
#For more deails, see:
# https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints
#Currently, google chrome sets {ideal: true} for autoGainControl,

View File

@ -5422,7 +5422,7 @@ class SessionDialog extends _dialog__WEBPACK_IMPORTED_MODULE_18__["Dialog"] {
msg += " but the following tip is provided for avoiding race conditions of";
msg += " this type. The caller can delay sending re-INVITE F6 for some period";
msg += " of time (2 seconds, perhaps), after which the caller can reasonably";
msg += " assume that its ACK has been received. Implementors can decouple the";
msg += " assume that its ACK has been received. Implementers can decouple the";
msg += " actions of the user (e.g., pressing the hold button) from the actions";
msg += " of the protocol (the sending of re-INVITE F6), so that the UA can";
msg += " behave like this. In this case, it is the implementor's choice as to";
@ -5430,7 +5430,7 @@ class SessionDialog extends _dialog__WEBPACK_IMPORTED_MODULE_18__["Dialog"] {
msg += " useful to prevent the type of race condition shown in this section.";
msg += " This document expresses no preference about whether or not they";
msg += " should wait for an ACK to be delivered. After considering the impact";
msg += " on user experience, implementors should decide whether or not to wait";
msg += " on user experience, implementers should decide whether or not to wait";
msg += " for a while, because the user experience depends on the";
msg += " implementation and has no direct bearing on protocol behavior.";
this.logger.warn(msg);
@ -11684,7 +11684,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5);
/**
* An exception indicating a session description handler error occured.
* An exception indicating a session description handler error occurred.
* @public
*/
class SessionDescriptionHandlerError extends _core__WEBPACK_IMPORTED_MODULE_0__["Exception"] {
@ -11724,7 +11724,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5);
/**
* An exception indicating an invalid state transition error occured.
* An exception indicating an invalid state transition error occurred.
* @public
*/
class StateTransitionError extends _core__WEBPACK_IMPORTED_MODULE_0__["Exception"] {
@ -12297,7 +12297,7 @@ class Invitation extends _session__WEBPACK_IMPORTED_MODULE_3__["Session"] {
// State should never be reached as first reliable provisional response must have answer/offer.
throw new Error(`Invalid signaling state ${this.dialog.signalingState}.`);
case _core__WEBPACK_IMPORTED_MODULE_0__["SignalingState"].Stable:
// Receved answer.
// Received answer.
return this.setAnswer(body, options).then(() => undefined);
case _core__WEBPACK_IMPORTED_MODULE_0__["SignalingState"].HaveLocalOffer:
// State should never be reached as local offer would be answered by this PRACK
@ -14937,7 +14937,7 @@ class Inviter extends _session__WEBPACK_IMPORTED_MODULE_2__["Session"] {
if (this.earlyMediaDialog !== session) {
if (this.earlyMedia) {
const message = "You have set the 'earlyMedia' option to 'true' which requires that your INVITE requests " +
"do not fork and yet this INVITE request did in fact fork. Consequentially and not surprisingly " +
"do not fork and yet this INVITE request did in fact fork. Consequently and not surprisingly " +
"the end point which accepted the INVITE (confirmed dialog) does not match the end point with " +
"which early media has been setup (early dialog) and thus this session is unable to proceed. " +
"In accordance with the SIP specifications, the SIP servers your end point is connected to " +
@ -17817,7 +17817,7 @@ class UserAgent {
},
onRefer: (incomingReferRequest) => {
this.logger.warn("Received an out of dialog REFER request");
// TOOD: this.delegate.onRefer(...)
// TODO: this.delegate.onRefer(...)
if (this.delegate && this.delegate.onReferRequest) {
this.delegate.onReferRequest(incomingReferRequest);
}
@ -17827,7 +17827,7 @@ class UserAgent {
},
onRegister: (incomingRegisterRequest) => {
this.logger.warn("Received an out of dialog REGISTER request");
// TOOD: this.delegate.onRegister(...)
// TODO: this.delegate.onRegister(...)
if (this.delegate && this.delegate.onRegisterRequest) {
this.delegate.onRegisterRequest(incomingRegisterRequest);
}
@ -17837,7 +17837,7 @@ class UserAgent {
},
onSubscribe: (incomingSubscribeRequest) => {
this.logger.warn("Received an out of dialog SUBSCRIBE request");
// TOOD: this.delegate.onSubscribe(...)
// TODO: this.delegate.onSubscribe(...)
if (this.delegate && this.delegate.onSubscribeRequest) {
this.delegate.onSubscribeRequest(incomingSubscribeRequest);
}
@ -19501,7 +19501,7 @@ class Transport {
return this.send("\r\n\r\n");
}
/**
* Start sending keep-alives.
* Start sending keep-alive.
*/
startSendingKeepAlives() {
// Compute an amount of time in seconds to wait before sending another keep-alive.
@ -19517,7 +19517,7 @@ class Transport {
}
}
/**
* Stop sending keep-alives.
* Stop sending keep-alive.
*/
stopSendingKeepAlives() {
if (this.keepAliveInterval) {
@ -20637,7 +20637,7 @@ class SimpleUser {
if (mediaElement) {
const localStream = this.localMediaStream;
if (!localStream) {
throw new Error("Local media stream undefiend.");
throw new Error("Local media stream undefined.");
}
mediaElement.srcObject = localStream;
mediaElement.volume = 0;
@ -20657,7 +20657,7 @@ class SimpleUser {
if (mediaElement) {
const remoteStream = this.remoteMediaStream;
if (!remoteStream) {
throw new Error("Remote media stream undefiend.");
throw new Error("Remote media stream undefined.");
}
mediaElement.autoplay = true; // Safari hack, because you cannot call .play() from a non user action
mediaElement.srcObject = remoteStream;
@ -20667,7 +20667,7 @@ class SimpleUser {
});
remoteStream.onaddtrack = () => {
this.logger.log(`[${this.id}] Remote media onaddtrack`);
mediaElement.load(); // Safari hack, as it doesn't work otheriwse
mediaElement.load(); // Safari hack, as it doesn't work otherwise
mediaElement.play().catch((error) => {
this.logger.error(`[${this.id}] Failed to play remote media`);
this.logger.error(error.message);

Some files were not shown because too many files have changed in this diff Show More