From db76929d0f41675cfb5f001753e21fb6dc283296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 9 May 2024 18:33:51 +0200 Subject: [PATCH 01/37] Adding support for transcripts, recording and AI summarization --- server/webhook.go | 176 +- server/zoom/webhook.go | 28 +- webapp/package-lock.json | 3359 +++++++++-------- webapp/package.json | 3 +- .../post_type_zoom/post_type_zoom.jsx | 3 + webapp/src/index.js | 2 + webapp/webpack.config.js | 6 + 7 files changed, 1917 insertions(+), 1660 deletions(-) diff --git a/server/webhook.go b/server/webhook.go index f22b0a29..42916369 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -10,6 +10,7 @@ import ( "io" "math" "net/http" + "strconv" "strings" "time" @@ -56,11 +57,16 @@ func (p *Plugin) handleWebhook(w http.ResponseWriter, r *http.Request) { } } + p.API.LogWarn("New event received", "even_type", webhook.Event, "payload", string(b)) switch webhook.Event { case zoom.EventTypeMeetingEnded: p.handleMeetingEnded(w, r, b) case zoom.EventTypeValidateWebhook: p.handleValidateZoomWebhook(w, r, b) + case zoom.EventTypeRecordingCompleted: + p.handleRecordingCompleted(w, r, b) + case zoom.EventTypeTranscriptCompleted: + p.handleTranscriptCompleted(w, r, b) default: w.WriteHeader(http.StatusOK) } @@ -123,11 +129,177 @@ func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body return } - if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { - p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) + // TODO: Delete the meeting post if is no longer needed + // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { + // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) + // return + // } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(post); err != nil { + p.API.LogWarn("failed to write response", "error", err.Error()) + } +} + +func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Request, body []byte) { + p.API.LogError("RUNNING THE UPDATE MEETING TRANSCRIPT") + var webhook zoom.RecordingWebhook + if err := json.Unmarshal(body, &webhook); err != nil { + p.API.LogError("Error unmarshaling meeting webhook", "err", err.Error()) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + meetingPostID := webhook.Payload.Object.ID + postID, appErr := p.fetchMeetingPostID(strconv.Itoa(meetingPostID)) + if appErr != nil { + http.Error(w, appErr.Error(), appErr.StatusCode) return } + post, appErr := p.API.GetPost(postID) + if appErr != nil { + p.API.LogWarn("Could not get meeting post by id", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + _, appErr = p.API.UpdatePost(post) + if appErr != nil { + p.API.LogWarn("Could not update the post", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + newPost := &model.Post{ + UserId: p.botUserID, + ChannelId: post.ChannelId, + RootId: post.Id, + Message: "Here's the zoom meeting transcription", + FileIds: []string{}, + Type: "custom_zoom_transcript", + } + + p.API.LogError("UPDATING MEETING TRANSCRIPT") + for _, recording := range webhook.Payload.Object.RecordingFiles { + if recording.RecordingType == zoom.RecordingTypeAudioTranscript { + p.API.LogError("MEETING TRANSCRIPT UPDATED") + post.Props["meeting_transcript"] = recording.PlayURL + if webhook.Payload.Object.Password != "" { + post.Props["meeting_password"] = webhook.Payload.Object.Password + } + request, err := http.NewRequest(http.MethodGet, recording.DownloadURL, nil) + if err != nil { + p.API.LogWarn("Unable to get the transcription", "err", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + request.Header.Set("Authorization", "Bearer "+webhook.DownloadToken) + response, err := http.DefaultClient.Do(request) + if err != nil { + p.API.LogWarn("Unable to get the transcription", "err", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + defer response.Body.Close() + transcription, err := io.ReadAll(response.Body) + if err != nil { + p.API.LogWarn("Unable to get the transcription", "err", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + fileInfo, appErr := p.API.UploadFile(transcription, post.ChannelId, "transcription.txt") + if appErr != nil { + p.API.LogWarn("Unable to get the transcription", "err", appErr) + http.Error(w, appErr.Error(), http.StatusBadRequest) + return + } + newPost.FileIds = append(newPost.FileIds, fileInfo.Id) + post.Props["captions"] = []map[string]string{{"file_id": fileInfo.Id}} + } + } + + _, appErr = p.API.UpdatePost(post) + if appErr != nil { + p.API.LogWarn("Could not update the post", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + _, appErr = p.API.CreatePost(newPost) + + if appErr != nil { + p.API.LogWarn("Could not create the transcription post", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + // TODO: Delete the meeting post if is no longer needed + // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { + // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) + // return + // } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(post); err != nil { + p.API.LogWarn("failed to write response", "error", err.Error()) + } +} + +func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request, body []byte) { + p.API.LogError("RUNNING THE UPDATE MEETING RECORDING") + var webhook zoom.RecordingWebhook + if err := json.Unmarshal(body, &webhook); err != nil { + p.API.LogError("Error unmarshaling meeting webhook", "err", err.Error()) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + meetingPostID := webhook.Payload.Object.ID + postID, appErr := p.fetchMeetingPostID(strconv.Itoa(meetingPostID)) + if appErr != nil { + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + post, appErr := p.API.GetPost(postID) + if appErr != nil { + p.API.LogWarn("Could not get meeting post by id", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + p.API.LogError("UPDATING MEETING RECORDING") + for _, recording := range webhook.Payload.Object.RecordingFiles { + if recording.RecordingType == zoom.RecordingTypeVideo { + p.API.LogError("MEETING RECORDING UPDATED") + post.Props["meeting_recording"] = recording.PlayURL + if webhook.Payload.Object.Password != "" { + post.Props["meeting_password"] = webhook.Payload.Object.Password + } + } + } + + _, appErr = p.API.UpdatePost(post) + if appErr != nil { + p.API.LogWarn("Could not update the post", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + _, appErr = p.API.CreatePost(&model.Post{ + UserId: p.botUserID, + ChannelId: post.ChannelId, + RootId: post.Id, + Message: "Here's the zoom meeting recording:\n**Link:** [Meeting Recording](" + post.Props["meeting_recording"].(string) + ")\n**Password:** " + post.Props["meeting_password"].(string), + }) + + // TODO: Delete the meeting post if is no longer needed + // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { + // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) + // return + // } + w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(post); err != nil { p.API.LogWarn("failed to write response", "error", err.Error()) diff --git a/server/zoom/webhook.go b/server/zoom/webhook.go index 307c4c29..1b70d1b7 100644 --- a/server/zoom/webhook.go +++ b/server/zoom/webhook.go @@ -15,9 +15,14 @@ const ( RecordingWebhookTypeComplete = "RECORDING_MEETING_COMPLETED" RecentlyCreated = "RECENTLY_CREATED" - EventTypeMeetingStarted EventType = "meeting.started" - EventTypeMeetingEnded EventType = "meeting.ended" - EventTypeValidateWebhook EventType = "endpoint.url_validation" + EventTypeMeetingStarted EventType = "meeting.started" + EventTypeMeetingEnded EventType = "meeting.ended" + EventTypeTranscriptCompleted EventType = "recording.transcript_completed" + EventTypeRecordingCompleted EventType = "recording.completed" + EventTypeValidateWebhook EventType = "endpoint.url_validation" + + RecordingTypeAudioTranscript = "audio_transcript" + RecordingTypeVideo = "shared_screen_with_speaker_view" ) type MeetingWebhookObject struct { @@ -63,13 +68,20 @@ type Webhook struct { } type RecordingWebhook struct { - Type string `schema:"type"` - Content string `schema:"content"` + Type string `schema:"type"` + DownloadToken string `json:"download_token"` + Payload RecordingWebhookPayload `schema:"content"` } -type RecordingWebhookContent struct { +type RecordingWebhookPayload struct { + AccountID string `json:"account_id"` + Object RecordingWebhookObject `json:"object"` +} + +type RecordingWebhookObject struct { UUID string `json:"uuid"` MeetingNumber int `json:"meeting_number"` + ID int `json:"id"` AccountID string `json:"account_id"` HostID string `json:"host_id"` Topic string `json:"topic"` @@ -79,6 +91,7 @@ type RecordingWebhookContent struct { Duration int `json:"duration"` TotalSize int `json:"total_size"` RecordingCount int `json:"recording_count"` + Password string `json:"password"` RecordingFiles []struct { ID string `json:"id"` MeetingID string `json:"meeting_id"` @@ -88,6 +101,9 @@ type RecordingWebhookContent struct { FileSize int `json:"file_size"` FilePath string `json:"file_path"` Status string `json:"status"` + DownloadURL string `json:"download_url"` + PlayURL string `json:"play_url"` + RecordingType string `json:"recording_type"` } `json:"recording_files"` } diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 4efd1d85..ee7755d4 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -12,10 +12,11 @@ "core-js": "3.7.0", "mattermost-redux": "5.33.1", "prop-types": "15.7.2", - "react": "17.0.1", + "react": "18.3.1", "react-intl": "4.7.6", "react-redux": "7.2.2", "redux": "4.0.5", + "styled-components": "6.1.10", "typescript": "4.6.4" }, "devDependencies": { @@ -165,11 +166,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", - "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", "dependencies": { - "@babel/types": "^7.24.0", + "@babel/types": "^7.24.5", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -224,18 +225,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz", - "integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz", + "integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.24.5", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-split-export-declaration": "^7.24.5", "semver": "^6.3.1" }, "engines": { @@ -354,11 +355,11 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz", + "integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==", "dependencies": { - "@babel/types": "^7.23.0" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -376,15 +377,15 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", + "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-simple-access": "^7.24.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -405,9 +406,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", "engines": { "node": ">=6.9.0" } @@ -445,11 +446,11 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", + "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -467,28 +468,28 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", "engines": { "node": ">=6.9.0" } @@ -515,13 +516,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", - "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", + "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", "dependencies": { "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -542,9 +543,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", - "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1449,14 +1450,14 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", - "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.5.tgz", + "integrity": "sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==", "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-create-class-features-plugin": "^7.24.5", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1528,12 +1529,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz", - "integrity": "sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.5.tgz", + "integrity": "sha512-RtCJoUO2oYrYwFPtR1/jkoBEcFuI1ae9a9IMxeyAVa3a1Ap4AnxmyIKG2b2FaJKqkidw/0cxRbWN+HOs6ZWd1w==", "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" }, "engines": { "node": ">=6.9.0" @@ -1623,9 +1624,9 @@ } }, "node_modules/@babel/plugin-transform-runtime/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", - "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", @@ -1639,13 +1640,13 @@ } }, "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", - "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "peer": true, "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.1", + "@babel/helper-define-polyfill-provider": "^0.6.2", "semver": "^6.3.1" }, "peerDependencies": { @@ -1666,12 +1667,12 @@ } }, "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", - "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "peer": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1" + "@babel/helper-define-polyfill-provider": "^0.6.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -2043,18 +2044,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2084,12 +2085,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2191,11 +2192,18 @@ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==", "dev": true }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, "node_modules/@emotion/memoize": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", - "dev": true + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/react": { "version": "11.11.0", @@ -2261,8 +2269,7 @@ "node_modules/@emotion/unitless": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", - "dev": true + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.1", @@ -2660,7 +2667,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -2673,7 +2679,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "engines": { "node": ">= 8" } @@ -2682,7 +2687,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -2692,20 +2696,19 @@ } }, "node_modules/@react-native-community/cli": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.6.tgz", - "integrity": "sha512-647OSi6xBb8FbwFqX9zsJxOzu685AWtrOUWHfOkbKD+5LOpGORw+GQo0F9rWZnB68rLQyfKUZWJeaD00pGv5fw==", - "peer": true, - "dependencies": { - "@react-native-community/cli-clean": "12.3.6", - "@react-native-community/cli-config": "12.3.6", - "@react-native-community/cli-debugger-ui": "12.3.6", - "@react-native-community/cli-doctor": "12.3.6", - "@react-native-community/cli-hermes": "12.3.6", - "@react-native-community/cli-plugin-metro": "12.3.6", - "@react-native-community/cli-server-api": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", - "@react-native-community/cli-types": "12.3.6", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-13.6.6.tgz", + "integrity": "sha512-IqclB7VQ84ye8Fcs89HOpOscY4284VZg2pojHNl8H0Lzd4DadXJWQoxC7zWm8v2f8eyeX2kdhxp2ETD5tceIgA==", + "peer": true, + "dependencies": { + "@react-native-community/cli-clean": "13.6.6", + "@react-native-community/cli-config": "13.6.6", + "@react-native-community/cli-debugger-ui": "13.6.6", + "@react-native-community/cli-doctor": "13.6.6", + "@react-native-community/cli-hermes": "13.6.6", + "@react-native-community/cli-server-api": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", + "@react-native-community/cli-types": "13.6.6", "chalk": "^4.1.2", "commander": "^9.4.1", "deepmerge": "^4.3.0", @@ -2724,14 +2727,15 @@ } }, "node_modules/@react-native-community/cli-clean": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-12.3.6.tgz", - "integrity": "sha512-gUU29ep8xM0BbnZjwz9MyID74KKwutq9x5iv4BCr2im6nly4UMf1B1D+V225wR7VcDGzbgWjaezsJShLLhC5ig==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-13.6.6.tgz", + "integrity": "sha512-cBwJTwl0NyeA4nyMxbhkWZhxtILYkbU3TW3k8AXLg+iGphe0zikYMGB3T+haTvTc6alTyEFwPbimk9bGIqkjAQ==", "peer": true, "dependencies": { - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", - "execa": "^5.0.0" + "execa": "^5.0.0", + "fast-glob": "^3.3.2" } }, "node_modules/@react-native-community/cli-clean/node_modules/ansi-styles": { @@ -2836,18 +2840,6 @@ "node": ">=10.17.0" } }, - "node_modules/@react-native-community/cli-clean/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@react-native-community/cli-clean/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2861,16 +2853,16 @@ } }, "node_modules/@react-native-community/cli-config": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-12.3.6.tgz", - "integrity": "sha512-JGWSYQ9EAK6m2v0abXwFLEfsqJ1zkhzZ4CV261QZF9MoUNB6h57a274h1MLQR9mG6Tsh38wBUuNfEPUvS1vYew==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-13.6.6.tgz", + "integrity": "sha512-mbG425zCKr8JZhv/j11382arezwS/70juWMsn8j2lmrGTrP1cUdW0MF15CCIFtJsqyK3Qs+FTmqttRpq81QfSg==", "peer": true, "dependencies": { - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "cosmiconfig": "^5.1.0", "deepmerge": "^4.3.0", - "glob": "^7.1.3", + "fast-glob": "^3.3.2", "joi": "^17.2.1" } }, @@ -2995,24 +2987,25 @@ } }, "node_modules/@react-native-community/cli-debugger-ui": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.6.tgz", - "integrity": "sha512-SjUKKsx5FmcK9G6Pb6UBFT0s9JexVStK5WInmANw75Hm7YokVvHEgtprQDz2Uvy5znX5g2ujzrkIU//T15KQzA==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-13.6.6.tgz", + "integrity": "sha512-Vv9u6eS4vKSDAvdhA0OiQHoA7y39fiPIgJ6biT32tN4avHDtxlc6TWZGiqv7g98SBvDWvoVAmdPLcRf3kU+c8g==", "peer": true, "dependencies": { "serve-static": "^1.13.1" } }, "node_modules/@react-native-community/cli-doctor": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-12.3.6.tgz", - "integrity": "sha512-fvBDv2lTthfw4WOQKkdTop2PlE9GtfrlNnpjB818MhcdEnPjfQw5YaTUcnNEGsvGomdCs1MVRMgYXXwPSN6OvQ==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-13.6.6.tgz", + "integrity": "sha512-TWZb5g6EmQe2Ua2TEWNmyaEayvlWH4GmdD9ZC+p8EpKFpB1NpDGMK6sXbpb42TDvwZg5s4TDRplK0PBEA/SVDg==", "peer": true, "dependencies": { - "@react-native-community/cli-config": "12.3.6", - "@react-native-community/cli-platform-android": "12.3.6", - "@react-native-community/cli-platform-ios": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-config": "13.6.6", + "@react-native-community/cli-platform-android": "13.6.6", + "@react-native-community/cli-platform-apple": "13.6.6", + "@react-native-community/cli-platform-ios": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "command-exists": "^1.2.8", "deepmerge": "^4.3.0", @@ -3138,38 +3131,11 @@ "node": ">=10.17.0" } }, - "node_modules/@react-native-community/cli-doctor/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@react-native-community/cli-doctor/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@react-native-community/cli-doctor/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.1.tgz", + "integrity": "sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==", "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -3201,16 +3167,10 @@ "node": ">=8" } }, - "node_modules/@react-native-community/cli-doctor/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "peer": true - }, "node_modules/@react-native-community/cli-doctor/node_modules/yaml": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", - "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", + "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==", "peer": true, "bin": { "yaml": "bin.mjs" @@ -3220,13 +3180,13 @@ } }, "node_modules/@react-native-community/cli-hermes": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-12.3.6.tgz", - "integrity": "sha512-sNGwfOCl8OAIjWCkwuLpP8NZbuO0dhDI/2W7NeOGDzIBsf4/c4MptTrULWtGIH9okVPLSPX0NnRyGQ+mSwWyuQ==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-13.6.6.tgz", + "integrity": "sha512-La5Ie+NGaRl3klei6WxKoOxmCUSGGxpOk6vU5pEGf0/O7ky+Ay0io+zXYUZqlNMi/cGpO7ZUijakBYOB/uyuFg==", "peer": true, "dependencies": { - "@react-native-community/cli-platform-android": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-platform-android": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "hermes-profile-transformer": "^0.0.6" } @@ -3302,16 +3262,16 @@ } }, "node_modules/@react-native-community/cli-platform-android": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.6.tgz", - "integrity": "sha512-DeDDAB8lHpuGIAPXeeD9Qu2+/wDTFPo99c8uSW49L0hkmZJixzvvvffbGQAYk32H0TmaI7rzvzH+qzu7z3891g==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-13.6.6.tgz", + "integrity": "sha512-/tMwkBeNxh84syiSwNlYtmUz/Ppc+HfKtdopL/5RB+fd3SV1/5/NPNjMlyLNgFKnpxvKCInQ7dnl6jGHJjeHjg==", "peer": true, "dependencies": { - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "execa": "^5.0.0", + "fast-glob": "^3.3.2", "fast-xml-parser": "^4.2.4", - "glob": "^7.1.3", "logkitty": "^0.7.1" } }, @@ -3417,18 +3377,6 @@ "node": ">=10.17.0" } }, - "node_modules/@react-native-community/cli-platform-android/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@react-native-community/cli-platform-android/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3441,21 +3389,21 @@ "node": ">=8" } }, - "node_modules/@react-native-community/cli-platform-ios": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.6.tgz", - "integrity": "sha512-3eZ0jMCkKUO58wzPWlvAPRqezVKm9EPZyaPyHbRPWU8qw7JqkvnRlWIaYDGpjCJgVW4k2hKsEursLtYKb188tg==", + "node_modules/@react-native-community/cli-platform-apple": { + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-13.6.6.tgz", + "integrity": "sha512-bOmSSwoqNNT3AmCRZXEMYKz1Jf1l2F86Nhs7qBcXdY/sGiJ+Flng564LOqvdAlVLTbkgz47KjNKCS2pP4Jg0Mg==", "peer": true, "dependencies": { - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "execa": "^5.0.0", + "fast-glob": "^3.3.2", "fast-xml-parser": "^4.0.12", - "glob": "^7.1.3", "ora": "^5.4.1" } }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/ansi-styles": { + "node_modules/@react-native-community/cli-platform-apple/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -3470,7 +3418,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/chalk": { + "node_modules/@react-native-community/cli-platform-apple/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -3486,7 +3434,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/color-convert": { + "node_modules/@react-native-community/cli-platform-apple/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -3498,13 +3446,13 @@ "node": ">=7.0.0" } }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/color-name": { + "node_modules/@react-native-community/cli-platform-apple/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "peer": true }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/execa": { + "node_modules/@react-native-community/cli-platform-apple/node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", @@ -3527,7 +3475,7 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/get-stream": { + "node_modules/@react-native-community/cli-platform-apple/node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", @@ -3539,7 +3487,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/has-flag": { + "node_modules/@react-native-community/cli-platform-apple/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -3548,7 +3496,7 @@ "node": ">=8" } }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/human-signals": { + "node_modules/@react-native-community/cli-platform-apple/node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", @@ -3557,19 +3505,7 @@ "node": ">=10.17.0" } }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@react-native-community/cli-platform-ios/node_modules/supports-color": { + "node_modules/@react-native-community/cli-platform-apple/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -3581,37 +3517,50 @@ "node": ">=8" } }, - "node_modules/@react-native-community/cli-plugin-metro": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.6.tgz", - "integrity": "sha512-3jxSBQt4fkS+KtHCPSyB5auIT+KKIrPCv9Dk14FbvOaEh9erUWEm/5PZWmtboW1z7CYeNbFMeXm9fM2xwtVOpg==", - "peer": true + "node_modules/@react-native-community/cli-platform-ios": { + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-13.6.6.tgz", + "integrity": "sha512-vjDnRwhlSN5ryqKTas6/DPkxuouuyFBAqAROH4FR1cspTbn6v78JTZKDmtQy9JMMo7N5vZj1kASU5vbFep9IOQ==", + "peer": true, + "dependencies": { + "@react-native-community/cli-platform-apple": "13.6.6" + } }, "node_modules/@react-native-community/cli-server-api": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-12.3.6.tgz", - "integrity": "sha512-80NIMzo8b2W+PL0Jd7NjiJW9mgaT8Y8wsIT/lh6mAvYH7mK0ecDJUYUTAAv79Tbo1iCGPAr3T295DlVtS8s4yQ==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-13.6.6.tgz", + "integrity": "sha512-ZtCXxoFlM7oDv3iZ3wsrT3SamhtUJuIkX2WePLPlN5bcbq7zimbPm2lHyicNJtpcGQ5ymsgpUWPCNZsWQhXBqQ==", "peer": true, "dependencies": { - "@react-native-community/cli-debugger-ui": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-debugger-ui": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", "compression": "^1.7.1", "connect": "^3.6.5", "errorhandler": "^1.5.1", "nocache": "^3.0.1", "pretty-format": "^26.6.2", "serve-static": "^1.13.1", - "ws": "^7.5.1" + "ws": "^6.2.2" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "peer": true, + "dependencies": { + "async-limiter": "~1.0.0" } }, "node_modules/@react-native-community/cli-tools": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-12.3.6.tgz", - "integrity": "sha512-FPEvZn19UTMMXUp/piwKZSh8cMEfO8G3KDtOwo53O347GTcwNrKjgZGtLSPELBX2gr+YlzEft3CoRv2Qmo83fQ==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-13.6.6.tgz", + "integrity": "sha512-ptOnn4AJczY5njvbdK91k4hcYazDnGtEPrqIwEI+k/CTBHNdb27Rsm2OZ7ye6f7otLBqF8gj/hK6QzJs8CEMgw==", "peer": true, "dependencies": { "appdirsjs": "^1.2.4", "chalk": "^4.1.2", + "execa": "^5.0.0", "find-up": "^5.0.0", "mime": "^2.4.1", "node-fetch": "^2.6.0", @@ -3671,6 +3620,29 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "peer": true }, + "node_modules/@react-native-community/cli-tools/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/@react-native-community/cli-tools/node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3687,6 +3659,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@react-native-community/cli-tools/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@react-native-community/cli-tools/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3696,6 +3680,15 @@ "node": ">=8" } }, + "node_modules/@react-native-community/cli-tools/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "peer": true, + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/@react-native-community/cli-tools/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3711,38 +3704,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@react-native-community/cli-tools/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@react-native-community/cli-tools/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "peer": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/@react-native-community/cli-tools/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -3783,13 +3744,10 @@ } }, "node_modules/@react-native-community/cli-tools/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.1.tgz", + "integrity": "sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==", "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -3809,16 +3767,10 @@ "node": ">=8" } }, - "node_modules/@react-native-community/cli-tools/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "peer": true - }, "node_modules/@react-native-community/cli-types": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-12.3.6.tgz", - "integrity": "sha512-xPqTgcUtZowQ8WKOkI9TLGBwH2bGggOC4d2FFaIRST3gTcjrEeGRNeR5aXCzJFIgItIft8sd7p2oKEdy90+01Q==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-13.6.6.tgz", + "integrity": "sha512-733iaYzlmvNK7XYbnWlMjdE+2k0hlTBJW071af/xb6Bs+hbJqBP9c03FZuYH2hFFwDDntwj05bkri/P7VgSxug==", "peer": true, "dependencies": { "joi": "^17.2.1" @@ -3948,18 +3900,6 @@ "node": ">=10.17.0" } }, - "node_modules/@react-native-community/cli/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@react-native-community/cli/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -3972,18 +3912,6 @@ "node": ">=8" } }, - "node_modules/@react-native-community/cli/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@react-native-community/cli/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -4030,13 +3958,10 @@ } }, "node_modules/@react-native-community/cli/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.1.tgz", + "integrity": "sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==", "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -4056,51 +3981,38 @@ "node": ">=8" } }, - "node_modules/@react-native-community/cli/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "peer": true - }, - "node_modules/@react-native-community/netinfo": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-4.7.0.tgz", - "integrity": "sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA==", - "peerDependencies": { - "react-native": ">=0.59" - } - }, "node_modules/@react-native/assets-registry": { - "version": "0.73.1", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.73.1.tgz", - "integrity": "sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.74.83.tgz", + "integrity": "sha512-2vkLMVnp+YTZYTNSDIBZojSsjz8sl5PscP3j4GcV6idD8V978SZfwFlk8K0ti0BzRs11mzL0Pj17km597S/eTQ==", "peer": true, "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz", - "integrity": "sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.74.83.tgz", + "integrity": "sha512-+S0st3t4Ro00bi9gjT1jnK8qTFOU+CwmziA7U9odKyWrCoRJrgmrvogq/Dr1YXlpFxexiGIupGut1VHxr+fxJA==", "peer": true, "dependencies": { - "@react-native/codegen": "0.73.3" + "@react-native/codegen": "0.74.83" }, "engines": { "node": ">=18" } }, "node_modules/@react-native/babel-preset": { - "version": "0.73.21", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.21.tgz", - "integrity": "sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.74.83.tgz", + "integrity": "sha512-KJuu3XyVh3qgyUer+rEqh9a/JoUxsDOzkJNfRpDyXiAyjDRoVch60X/Xa/NcEQ93iCVHAWs0yQ+XGNGIBCYE6g==", "peer": true, "dependencies": { "@babel/core": "^7.20.0", "@babel/plugin-proposal-async-generator-functions": "^7.0.0", "@babel/plugin-proposal-class-properties": "^7.18.0", "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", "@babel/plugin-proposal-numeric-separator": "^7.0.0", "@babel/plugin-proposal-object-rest-spread": "^7.20.0", @@ -4136,7 +4048,7 @@ "@babel/plugin-transform-typescript": "^7.5.0", "@babel/plugin-transform-unicode-regex": "^7.0.0", "@babel/template": "^7.0.0", - "@react-native/babel-plugin-codegen": "0.73.4", + "@react-native/babel-plugin-codegen": "0.74.83", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" }, @@ -4148,21 +4060,21 @@ } }, "node_modules/@react-native/babel-preset/node_modules/@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -4271,14 +4183,14 @@ } }, "node_modules/@react-native/codegen": { - "version": "0.73.3", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.73.3.tgz", - "integrity": "sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.74.83.tgz", + "integrity": "sha512-GgvgHS3Aa2J8/mp1uC/zU8HuTh8ZT5jz7a4mVMWPw7+rGyv70Ba8uOVBq6UH2Q08o617IATYc+0HfyzAfm4n0w==", "peer": true, "dependencies": { "@babel/parser": "^7.20.0", - "flow-parser": "^0.206.0", "glob": "^7.1.1", + "hermes-parser": "0.19.1", "invariant": "^2.2.4", "jscodeshift": "^0.14.0", "mkdirp": "^0.5.1", @@ -4292,21 +4204,22 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.73.17", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.17.tgz", - "integrity": "sha512-F3PXZkcHg+1ARIr6FRQCQiB7ZAA+MQXGmq051metRscoLvgYJwj7dgC8pvgy0kexzUkHu5BNKrZeySzUft3xuQ==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.74.83.tgz", + "integrity": "sha512-7GAFjFOg1mFSj8bnFNQS4u8u7+QtrEeflUIDVZGEfBZQ3wMNI5ycBzbBGycsZYiq00Xvoc6eKFC7kvIaqeJpUQ==", "peer": true, "dependencies": { - "@react-native-community/cli-server-api": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", - "@react-native/dev-middleware": "0.73.8", - "@react-native/metro-babel-transformer": "0.73.15", + "@react-native-community/cli-server-api": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", + "@react-native/dev-middleware": "0.74.83", + "@react-native/metro-babel-transformer": "0.74.83", "chalk": "^4.0.0", "execa": "^5.1.1", "metro": "^0.80.3", "metro-config": "^0.80.3", "metro-core": "^0.80.3", "node-fetch": "^2.2.0", + "querystring": "^0.2.1", "readline": "^1.3.0" }, "engines": { @@ -4415,36 +4328,14 @@ "node": ">=10.17.0" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/@react-native/community-cli-plugin/node_modules/querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", "peer": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@react-native/community-cli-plugin/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "peer": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">=0.4.x" } }, "node_modules/@react-native/community-cli-plugin/node_modules/supports-color": { @@ -4460,28 +4351,30 @@ } }, "node_modules/@react-native/debugger-frontend": { - "version": "0.73.3", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz", - "integrity": "sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.74.83.tgz", + "integrity": "sha512-RGQlVUegBRxAUF9c1ss1ssaHZh6CO+7awgtI9sDeU0PzDZY/40ImoPD5m0o0SI6nXoVzbPtcMGzU+VO590pRfA==", "peer": true, "engines": { "node": ">=18" } }, "node_modules/@react-native/dev-middleware": { - "version": "0.73.8", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz", - "integrity": "sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.74.83.tgz", + "integrity": "sha512-UH8iriqnf7N4Hpi20D7M2FdvSANwTVStwFCSD7VMU9agJX88Yk0D1T6Meh2RMhUu4kY2bv8sTkNRm7LmxvZqgA==", "peer": true, "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.73.3", + "@react-native/debugger-frontend": "0.74.83", + "@rnx-kit/chromium-edge-launcher": "^1.0.0", "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^1.0.0", "connect": "^3.6.5", "debug": "^2.2.0", "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", "open": "^7.0.3", + "selfsigned": "^2.4.1", "serve-static": "^1.13.1", "temp-dir": "^2.0.0", "ws": "^6.2.2" @@ -4490,26 +4383,6 @@ "node": ">=18" } }, - "node_modules/@react-native/dev-middleware/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "peer": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/@react-native/dev-middleware/node_modules/open": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", @@ -4536,32 +4409,32 @@ } }, "node_modules/@react-native/gradle-plugin": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz", - "integrity": "sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.74.83.tgz", + "integrity": "sha512-Pw2BWVyOHoBuJVKxGVYF6/GSZRf6+v1Ygc+ULGz5t20N8qzRWPa2fRZWqoxsN7TkNLPsECYY8gooOl7okOcPAQ==", "peer": true, "engines": { "node": ">=18" } }, "node_modules/@react-native/js-polyfills": { - "version": "0.73.1", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", - "integrity": "sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.74.83.tgz", + "integrity": "sha512-/t74n8r6wFhw4JEoOj3bN71N1NDLqaawB75uKAsSjeCwIR9AfCxlzZG0etsXtOexkY9KMeZIQ7YwRPqUdNXuqw==", "peer": true, "engines": { "node": ">=18" } }, "node_modules/@react-native/metro-babel-transformer": { - "version": "0.73.15", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz", - "integrity": "sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.74.83.tgz", + "integrity": "sha512-hGdx5N8diu8y+GW/ED39vTZa9Jx1di2ZZ0aapbhH4egN1agIAusj5jXTccfNBwwWF93aJ5oVbRzfteZgjbutKg==", "peer": true, "dependencies": { "@babel/core": "^7.20.0", - "@react-native/babel-preset": "0.73.21", - "hermes-parser": "0.15.0", + "@react-native/babel-preset": "0.74.83", + "hermes-parser": "0.19.1", "nullthrows": "^1.1.1" }, "engines": { @@ -4572,21 +4445,21 @@ } }, "node_modules/@react-native/metro-babel-transformer/node_modules/@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -4640,11 +4513,76 @@ } }, "node_modules/@react-native/normalize-colors": { - "version": "0.73.2", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz", - "integrity": "sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.83.tgz", + "integrity": "sha512-jhCY95gRDE44qYawWVvhTjTplW1g+JtKTKM3f8xYT1dJtJ8QWv+gqEtKcfmOHfDkSDaMKG0AGBaDTSK8GXLH8Q==", "peer": true }, + "node_modules/@rnx-kit/chromium-edge-launcher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", + "integrity": "sha512-lzD84av1ZQhYUS+jsGqJiCMaJO2dn9u+RTT9n9q6D3SaKVwWqv+7AoRKqBu19bkwyE+iFRl1ymr40QS90jVFYg==", + "peer": true, + "dependencies": { + "@types/node": "^18.0.0", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=14.15" + } + }, + "node_modules/@rnx-kit/chromium-edge-launcher/node_modules/@types/node": { + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@rnx-kit/chromium-edge-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@rnx-kit/chromium-edge-launcher/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@rnx-kit/chromium-edge-launcher/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -4774,6 +4712,15 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -4786,9 +4733,9 @@ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "node_modules/@types/react": { - "version": "16.9.56", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.56.tgz", - "integrity": "sha512-gIkl4J44G/qxbuC6r2Xh+D3CGZpJ+NdWTItAPmZbR5mUS+JQ8Zvzpl0ea5qT/ZT3ZNTUcDKUVqV3xBE8wv/DyQ==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz", + "integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -4800,6 +4747,11 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "peer": true }, + "node_modules/@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==" + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -6248,6 +6200,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001587", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", @@ -6347,59 +6307,6 @@ "node": ">=6.0" } }, - "node_modules/chromium-edge-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", - "integrity": "sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==", - "peer": true, - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0", - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chromium-edge-launcher/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "peer": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/chromium-edge-launcher/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -6816,15 +6723,33 @@ "node": "*" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/csstype": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.4.tgz", - "integrity": "sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==", "peer": true }, "node_modules/debug": { @@ -6924,31 +6849,6 @@ "node": ">= 0.8" } }, - "node_modules/deprecated-react-native-prop-types": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz", - "integrity": "sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==", - "peer": true, - "dependencies": { - "@react-native/normalize-colors": "^0.73.0", - "invariant": "^2.2.4", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/deprecated-react-native-prop-types/node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "peer": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, "node_modules/des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -7084,16 +6984,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "peer": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -7770,18 +7660,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/execa/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -7792,7 +7670,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -7842,7 +7719,6 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "dependencies": { "reusify": "^1.0.4" } @@ -7955,9 +7831,9 @@ "peer": true }, "node_modules/flow-parser": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", - "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", + "version": "0.235.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.235.1.tgz", + "integrity": "sha512-s04193L4JE+ntEcQXbD6jxRRlyj9QXcgEl2W6xSjH4l9x4b0eHoCHfbYHjqf9LdZFUiM5LhgpiqsvLj/AyOyYQ==", "peer": true, "engines": { "node": ">=0.4.0" @@ -8119,7 +7995,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -8286,18 +8161,18 @@ } }, "node_modules/hermes-estree": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.15.0.tgz", - "integrity": "sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.19.1.tgz", + "integrity": "sha512-daLGV3Q2MKk8w4evNMKwS8zBE/rcpA800nu1Q5kM08IKijoSnPe9Uo1iIxzPKRkn95IxxsgBMPeYHt3VG4ej2g==", "peer": true }, "node_modules/hermes-parser": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.15.0.tgz", - "integrity": "sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.19.1.tgz", + "integrity": "sha512-Vp+bXzxYJWrpEuJ/vXxUsLnt0+y4q9zyi4zUlkLqD8FKv4LjIfOvP69R/9Lty3dCyKh0E2BU7Eypqr63/rKT/A==", "peer": true, "dependencies": { - "hermes-estree": "0.15.0" + "hermes-estree": "0.19.1" } }, "node_modules/hermes-profile-transformer": { @@ -8386,19 +8261,6 @@ "node": ">=8.12.0" } }, - "node_modules/iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "optional": true, - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -8728,7 +8590,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -8745,7 +8606,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -8806,6 +8666,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", @@ -9007,9 +8878,9 @@ } }, "node_modules/jest-message-util/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "peer": true }, "node_modules/jest-message-util/node_modules/slash": { @@ -9236,9 +9107,9 @@ } }, "node_modules/jest-validate/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "peer": true }, "node_modules/jest-validate/node_modules/supports-color": { @@ -9292,9 +9163,9 @@ } }, "node_modules/joi": { - "version": "17.12.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.3.tgz", - "integrity": "sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==", + "version": "17.13.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.1.tgz", + "integrity": "sha512-vaBlIKCyo4FCUtCm7Eu4QZd/q02bWcxfUO6YSXAZOWF6gzcLBeba8kwotUdYJjDLW8Cz8RywsSOqiNJZW0mNvg==", "peer": true, "dependencies": { "@hapi/hoek": "^9.3.0", @@ -10096,15 +9967,14 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } }, "node_modules/metro": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.8.tgz", - "integrity": "sha512-in7S0W11mg+RNmcXw+2d9S3zBGmCARDxIwoXJAmLUQOQoYsRP3cpGzyJtc7WOw8+FXfpgXvceD0u+PZIHXEL7g==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.9.tgz", + "integrity": "sha512-Bc57Xf3GO2Xe4UWQsBj/oW6YfLPABEu8jfDVDiNmJvoQW4CO34oDPuYKe4KlXzXhcuNsqOtSxpbjCRRVjhhREg==", "peer": true, "dependencies": { "@babel/code-frame": "^7.0.0", @@ -10128,18 +9998,18 @@ "jest-worker": "^29.6.3", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.80.8", - "metro-cache": "0.80.8", - "metro-cache-key": "0.80.8", - "metro-config": "0.80.8", - "metro-core": "0.80.8", - "metro-file-map": "0.80.8", - "metro-resolver": "0.80.8", - "metro-runtime": "0.80.8", - "metro-source-map": "0.80.8", - "metro-symbolicate": "0.80.8", - "metro-transform-plugins": "0.80.8", - "metro-transform-worker": "0.80.8", + "metro-babel-transformer": "0.80.9", + "metro-cache": "0.80.9", + "metro-cache-key": "0.80.9", + "metro-config": "0.80.9", + "metro-core": "0.80.9", + "metro-file-map": "0.80.9", + "metro-resolver": "0.80.9", + "metro-runtime": "0.80.9", + "metro-source-map": "0.80.9", + "metro-symbolicate": "0.80.9", + "metro-transform-plugins": "0.80.9", + "metro-transform-worker": "0.80.9", "mime-types": "^2.1.27", "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", @@ -10159,9 +10029,9 @@ } }, "node_modules/metro-babel-transformer": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.8.tgz", - "integrity": "sha512-TTzNwRZb2xxyv4J/+yqgtDAP2qVqH3sahsnFu6Xv4SkLqzrivtlnyUbaeTdJ9JjtADJUEjCbgbFgUVafrXdR9Q==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.9.tgz", + "integrity": "sha512-d76BSm64KZam1nifRZlNJmtwIgAeZhZG3fi3K+EmPOlrR8rDtBxQHDSN3fSGeNB9CirdTyabTMQCkCup6BXFSQ==", "peer": true, "dependencies": { "@babel/core": "^7.20.0", @@ -10173,21 +10043,21 @@ } }, "node_modules/metro-babel-transformer/node_modules/@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -10256,12 +10126,12 @@ } }, "node_modules/metro-cache": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.8.tgz", - "integrity": "sha512-5svz+89wSyLo7BxdiPDlwDTgcB9kwhNMfNhiBZPNQQs1vLFXxOkILwQiV5F2EwYT9DEr6OPZ0hnJkZfRQ8lDYQ==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.9.tgz", + "integrity": "sha512-ujEdSI43QwI+Dj2xuNax8LMo8UgKuXJEdxJkzGPU6iIx42nYa1byQ+aADv/iPh5sh5a//h5FopraW5voXSgm2w==", "peer": true, "dependencies": { - "metro-core": "0.80.8", + "metro-core": "0.80.9", "rimraf": "^3.0.2" }, "engines": { @@ -10269,9 +10139,9 @@ } }, "node_modules/metro-cache-key": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.8.tgz", - "integrity": "sha512-qWKzxrLsRQK5m3oH8ePecqCc+7PEhR03cJE6Z6AxAj0idi99dHOSitTmY0dclXVB9vP2tQIAE8uTd8xkYGk8fA==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.9.tgz", + "integrity": "sha512-hRcYGhEiWIdM87hU0fBlcGr+tHDEAT+7LYNCW89p5JhErFt/QaAkVx4fb5bW3YtXGv5BTV7AspWPERoIb99CXg==", "peer": true, "engines": { "node": ">=18" @@ -10293,18 +10163,18 @@ } }, "node_modules/metro-config": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.8.tgz", - "integrity": "sha512-VGQJpfJawtwRzGzGXVUoohpIkB0iPom4DmSbAppKfumdhtLA8uVeEPp2GM61kL9hRvdbMhdWA7T+hZFDlo4mJA==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.9.tgz", + "integrity": "sha512-28wW7CqS3eJrunRGnsibWldqgwRP9ywBEf7kg+uzUHkSFJNKPM1K3UNSngHmH0EZjomizqQA2Zi6/y6VdZMolg==", "peer": true, "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "jest-validate": "^29.6.3", - "metro": "0.80.8", - "metro-cache": "0.80.8", - "metro-core": "0.80.8", - "metro-runtime": "0.80.8" + "metro": "0.80.9", + "metro-cache": "0.80.9", + "metro-core": "0.80.9", + "metro-runtime": "0.80.9" }, "engines": { "node": ">=18" @@ -10361,22 +10231,22 @@ } }, "node_modules/metro-core": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.8.tgz", - "integrity": "sha512-g6lud55TXeISRTleW6SHuPFZHtYrpwNqbyFIVd9j9Ofrb5IReiHp9Zl8xkAfZQp8v6ZVgyXD7c130QTsCz+vBw==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.9.tgz", + "integrity": "sha512-tbltWQn+XTdULkGdzHIxlxk4SdnKxttvQQV3wpqqFbHDteR4gwCyTR2RyYJvxgU7HELfHtrVbqgqAdlPByUSbg==", "peer": true, "dependencies": { "lodash.throttle": "^4.1.1", - "metro-resolver": "0.80.8" + "metro-resolver": "0.80.9" }, "engines": { "node": ">=18" } }, "node_modules/metro-file-map": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.8.tgz", - "integrity": "sha512-eQXMFM9ogTfDs2POq7DT2dnG7rayZcoEgRbHPXvhUWkVwiKkro2ngcBE++ck/7A36Cj5Ljo79SOkYwHaWUDYDw==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.9.tgz", + "integrity": "sha512-sBUjVtQMHagItJH/wGU9sn3k2u0nrCl0CdR4SFMO1tksXLKbkigyQx4cbpcyPVOAmGTVuy3jyvBlELaGCAhplQ==", "peer": true, "dependencies": { "anymatch": "^3.0.3", @@ -10437,9 +10307,9 @@ } }, "node_modules/metro-minify-terser": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.8.tgz", - "integrity": "sha512-y8sUFjVvdeUIINDuW1sejnIjkZfEF+7SmQo0EIpYbWmwh+kq/WMj74yVaBWuqNjirmUp1YNfi3alT67wlbBWBQ==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.9.tgz", + "integrity": "sha512-FEeCeFbkvvPuhjixZ1FYrXtO0araTpV6UbcnGgDUpH7s7eR5FG/PiJz3TsuuPP/HwCK19cZtQydcA2QrCw446A==", "peer": true, "dependencies": { "terser": "^5.15.0" @@ -10449,18 +10319,18 @@ } }, "node_modules/metro-resolver": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.8.tgz", - "integrity": "sha512-JdtoJkP27GGoZ2HJlEsxs+zO7jnDUCRrmwXJozTlIuzLHMRrxgIRRby9fTCbMhaxq+iA9c+wzm3iFb4NhPmLbQ==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.9.tgz", + "integrity": "sha512-wAPIjkN59BQN6gocVsAvvpZ1+LQkkqUaswlT++cJafE/e54GoVkMNCmrR4BsgQHr9DknZ5Um/nKueeN7kaEz9w==", "peer": true, "engines": { "node": ">=18" } }, "node_modules/metro-runtime": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.8.tgz", - "integrity": "sha512-2oScjfv6Yb79PelU1+p8SVrCMW9ZjgEiipxq7jMRn8mbbtWzyv3g8Mkwr+KwOoDFI/61hYPUbY8cUnu278+x1g==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.9.tgz", + "integrity": "sha512-8PTVIgrVcyU+X/rVCy/9yxNlvXsBCk5JwwkbAm/Dm+Abo6NBGtNjWF0M1Xo/NWCb4phamNWcD7cHdR91HhbJvg==", "peer": true, "dependencies": { "@babel/runtime": "^7.0.0" @@ -10470,17 +10340,17 @@ } }, "node_modules/metro-source-map": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.8.tgz", - "integrity": "sha512-+OVISBkPNxjD4eEKhblRpBf463nTMk3KMEeYS8Z4xM/z3qujGJGSsWUGRtH27+c6zElaSGtZFiDMshEb8mMKQg==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.9.tgz", + "integrity": "sha512-RMn+XS4VTJIwMPOUSj61xlxgBvPeY4G6s5uIn6kt6HB6A/k9ekhr65UkkDD7WzHYs3a9o869qU8tvOZvqeQzgw==", "peer": true, "dependencies": { "@babel/traverse": "^7.20.0", "@babel/types": "^7.20.0", "invariant": "^2.2.4", - "metro-symbolicate": "0.80.8", + "metro-symbolicate": "0.80.9", "nullthrows": "^1.1.1", - "ob1": "0.80.8", + "ob1": "0.80.9", "source-map": "^0.5.6", "vlq": "^1.0.0" }, @@ -10489,13 +10359,13 @@ } }, "node_modules/metro-symbolicate": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.8.tgz", - "integrity": "sha512-nwhYySk79jQhwjL9QmOUo4wS+/0Au9joEryDWw7uj4kz2yvw1uBjwmlql3BprQCBzRdB3fcqOP8kO8Es+vE31g==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.9.tgz", + "integrity": "sha512-Ykae12rdqSs98hg41RKEToojuIW85wNdmSe/eHUgMkzbvCFNVgcC0w3dKZEhSsqQOXapXRlLtHkaHLil0UD/EA==", "peer": true, "dependencies": { "invariant": "^2.2.4", - "metro-source-map": "0.80.8", + "metro-source-map": "0.80.9", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "through2": "^2.0.1", @@ -10509,9 +10379,9 @@ } }, "node_modules/metro-transform-plugins": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.8.tgz", - "integrity": "sha512-sSu8VPL9Od7w98MftCOkQ1UDeySWbsIAS5I54rW22BVpPnI3fQ42srvqMLaJUQPjLehUanq8St6OMBCBgH/UWw==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.9.tgz", + "integrity": "sha512-UlDk/uc8UdfLNJhPbF3tvwajyuuygBcyp+yBuS/q0z3QSuN/EbLllY3rK8OTD9n4h00qZ/qgxGv/lMFJkwP4vg==", "peer": true, "dependencies": { "@babel/core": "^7.20.0", @@ -10525,21 +10395,21 @@ } }, "node_modules/metro-transform-plugins/node_modules/@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -10593,22 +10463,22 @@ } }, "node_modules/metro-transform-worker": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.8.tgz", - "integrity": "sha512-+4FG3TQk3BTbNqGkFb2uCaxYTfsbuFOCKMMURbwu0ehCP8ZJuTUramkaNZoATS49NSAkRgUltgmBa4YaKZ5mqw==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.9.tgz", + "integrity": "sha512-c/IrzMUVnI0hSVVit4TXzt3A1GiUltGVlzCmLJWxNrBGHGrJhvgePj38+GXl1Xf4Fd4vx6qLUkKMQ3ux73bFLQ==", "peer": true, "dependencies": { "@babel/core": "^7.20.0", "@babel/generator": "^7.20.0", "@babel/parser": "^7.20.0", "@babel/types": "^7.20.0", - "metro": "0.80.8", - "metro-babel-transformer": "0.80.8", - "metro-cache": "0.80.8", - "metro-cache-key": "0.80.8", - "metro-minify-terser": "0.80.8", - "metro-source-map": "0.80.8", - "metro-transform-plugins": "0.80.8", + "metro": "0.80.9", + "metro-babel-transformer": "0.80.9", + "metro-cache": "0.80.9", + "metro-cache-key": "0.80.9", + "metro-minify-terser": "0.80.9", + "metro-source-map": "0.80.9", + "metro-transform-plugins": "0.80.9", "nullthrows": "^1.1.1" }, "engines": { @@ -10616,21 +10486,21 @@ } }, "node_modules/metro-transform-worker/node_modules/@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -10684,21 +10554,21 @@ } }, "node_modules/metro/node_modules/@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -10851,26 +10721,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "peer": true }, - "node_modules/metro/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "peer": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/metro/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -11104,16 +10954,45 @@ "node": ">= 0.10.5" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "peer": true - }, - "node_modules/node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "peer": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "peer": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "peer": true + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", "dev": true, "dependencies": { "assert": "^1.1.1", @@ -11225,9 +11104,9 @@ "peer": true }, "node_modules/ob1": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.8.tgz", - "integrity": "sha512-QHJQk/lXMmAW8I7AIM3in1MSlwe1umR72Chhi8B7Xnq6mzjhBKkA6Fy/zAhQnGkA4S912EPCEvTij5yh+EQTAA==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.9.tgz", + "integrity": "sha512-v9yOxowkZbxWhKOaaTyLjIm1aLy4ebMNcSn4NYJKOAI/Qv+SkfEfszpLr2GIxsccmb2Y2HA9qtsqiIJ80ucpVA==", "peer": true, "engines": { "node": ">=18" @@ -11801,6 +11680,55 @@ "node": ">=6" } }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -12051,7 +11979,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -12096,27 +12023,39 @@ } }, "node_modules/react": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz", - "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-devtools-core": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", - "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.2.0.tgz", + "integrity": "sha512-vZK+/gvxxsieAoAyYaiRIVFxlajb7KXhgBDV7OsoMzaAE+IqGpoxusBjIgq5ibqA2IloKu0p9n7tE68z1xs18A==", "peer": true, "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, "node_modules/react-intl": { "version": "4.7.6", "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-4.7.6.tgz", @@ -12145,162 +12084,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/react-native": { - "version": "0.73.6", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.6.tgz", - "integrity": "sha512-oqmZe8D2/VolIzSPZw+oUd6j/bEmeRHwsLn1xLA5wllEYsZ5zNuMsDus235ONOnCRwexqof/J3aztyQswSmiaA==", - "peer": true, - "dependencies": { - "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "12.3.6", - "@react-native-community/cli-platform-android": "12.3.6", - "@react-native-community/cli-platform-ios": "12.3.6", - "@react-native/assets-registry": "0.73.1", - "@react-native/codegen": "0.73.3", - "@react-native/community-cli-plugin": "0.73.17", - "@react-native/gradle-plugin": "0.73.4", - "@react-native/js-polyfills": "0.73.1", - "@react-native/normalize-colors": "0.73.2", - "@react-native/virtualized-lists": "0.73.4", - "abort-controller": "^3.0.0", - "anser": "^1.4.9", - "ansi-regex": "^5.0.0", - "base64-js": "^1.5.1", - "chalk": "^4.0.0", - "deprecated-react-native-prop-types": "^5.0.0", - "event-target-shim": "^5.0.1", - "flow-enums-runtime": "^0.0.6", - "invariant": "^2.2.4", - "jest-environment-node": "^29.6.3", - "jsc-android": "^250231.0.0", - "memoize-one": "^5.0.0", - "metro-runtime": "^0.80.3", - "metro-source-map": "^0.80.3", - "mkdirp": "^0.5.1", - "nullthrows": "^1.1.1", - "pretty-format": "^26.5.2", - "promise": "^8.3.0", - "react-devtools-core": "^4.27.7", - "react-refresh": "^0.14.0", - "react-shallow-renderer": "^16.15.0", - "regenerator-runtime": "^0.13.2", - "scheduler": "0.24.0-canary-efb381bbf-20230505", - "stacktrace-parser": "^0.1.10", - "whatwg-fetch": "^3.0.0", - "ws": "^6.2.2", - "yargs": "^17.6.2" - }, - "bin": { - "react-native": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "react": "18.2.0" - } - }, - "node_modules/react-native/node_modules/@react-native/virtualized-lists": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz", - "integrity": "sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog==", - "peer": true, - "dependencies": { - "invariant": "^2.2.4", - "nullthrows": "^1.1.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "react-native": "*" - } - }, - "node_modules/react-native/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/react-native/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/react-native/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "peer": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/react-native/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "peer": true - }, - "node_modules/react-native/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "peer": true - }, - "node_modules/react-native/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native/node_modules/ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", - "peer": true, - "dependencies": { - "async-limiter": "~1.0.0" - } - }, "node_modules/react-redux": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.2.tgz", @@ -12342,9 +12125,9 @@ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "peer": true, "engines": { "node": ">=0.10.0" @@ -12527,6 +12310,203 @@ "redux": ">=3" } }, + "node_modules/redux-offline/node_modules/@react-native-community/netinfo": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-4.7.0.tgz", + "integrity": "sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA==", + "peerDependencies": { + "react-native": ">=0.59" + } + }, + "node_modules/redux-offline/node_modules/@react-native/virtualized-lists": { + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.74.83.tgz", + "integrity": "sha512-rmaLeE34rj7py4FxTod7iMTC7BAsm+HrGA8WxYmEJeyTV7WSaxAkosKoYBz8038mOiwnG9VwA/7FrB6bEQvn1A==", + "peer": true, + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.2.6", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/redux-offline/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/redux-offline/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/redux-offline/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/redux-offline/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "peer": true + }, + "node_modules/redux-offline/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/redux-offline/node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/redux-offline/node_modules/react-native": { + "version": "0.74.1", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.74.1.tgz", + "integrity": "sha512-0H2XpmghwOtfPpM2LKqHIN7gxy+7G/r1hwJHKLV6uoyXGC/gCojRtoo5NqyKrWpFC8cqyT6wTYCLuG7CxEKilg==", + "peer": true, + "dependencies": { + "@jest/create-cache-key-function": "^29.6.3", + "@react-native-community/cli": "13.6.6", + "@react-native-community/cli-platform-android": "13.6.6", + "@react-native-community/cli-platform-ios": "13.6.6", + "@react-native/assets-registry": "0.74.83", + "@react-native/codegen": "0.74.83", + "@react-native/community-cli-plugin": "0.74.83", + "@react-native/gradle-plugin": "0.74.83", + "@react-native/js-polyfills": "0.74.83", + "@react-native/normalize-colors": "0.74.83", + "@react-native/virtualized-lists": "0.74.83", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", + "jsc-android": "^250231.0.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.80.3", + "metro-source-map": "^0.80.3", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.3.0", + "react-devtools-core": "^5.0.0", + "react-refresh": "^0.14.0", + "react-shallow-renderer": "^16.15.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.24.0-canary-efb381bbf-20230505", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.2", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.2.6", + "react": "18.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/redux-offline/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "peer": true + }, + "node_modules/redux-offline/node_modules/scheduler": { + "version": "0.24.0-canary-efb381bbf-20230505", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", + "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/redux-offline/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redux-offline/node_modules/ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "peer": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, "node_modules/redux-persist": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-4.9.1.tgz", @@ -12747,7 +12727,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -12789,7 +12768,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -12813,13 +12791,6 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "optional": true, - "peer": true - }, "node_modules/sc-channel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/sc-channel/-/sc-channel-1.2.0.tgz", @@ -12839,9 +12810,9 @@ "integrity": "sha512-9PbqYBpCq+OoEeRQ3QfFIGE6qwjjBcd2j7UjgDlhnZbtSnuGgHdcRklPKYGuYFH82V/dwd+AIpu8XvA1zqTd+A==" }, "node_modules/scheduler": { - "version": "0.24.0-canary-efb381bbf-20230505", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", - "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "peer": true, "dependencies": { "loose-envify": "^1.1.0" @@ -12865,6 +12836,19 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "peer": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", @@ -13027,6 +13011,11 @@ "resolved": "https://registry.npmjs.org/shallow-equals/-/shallow-equals-1.0.0.tgz", "integrity": "sha1-JLdL8cY0wR7Uxxgqbfb7MA3OQ5A=" }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -13160,6 +13149,14 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -13478,6 +13475,43 @@ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", "peer": true }, + "node_modules/styled-components": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.10.tgz", + "integrity": "sha512-4K8IKcn7iOt76riGLjvBhRyNPTkUKTvmnwoRFBOtJLswVvzy2VsoE2KOrfl9FJLQUYbITLJY2wfIZ3tjbkA/Zw==", + "dependencies": { + "@emotion/is-prop-valid": "1.2.2", + "@emotion/unitless": "0.8.1", + "@types/stylis": "4.2.5", + "css-to-react-native": "3.2.0", + "csstype": "3.1.3", + "postcss": "8.4.38", + "shallowequal": "1.1.0", + "stylis": "4.3.2", + "tslib": "2.6.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" + }, + "node_modules/styled-components/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -14269,9 +14303,9 @@ } }, "node_modules/whatwg-fetch": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz", - "integrity": "sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A==", + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", "peer": true }, "node_modules/whatwg-url": { @@ -14637,11 +14671,11 @@ } }, "@babel/generator": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", - "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", "requires": { - "@babel/types": "^7.24.0", + "@babel/types": "^7.24.5", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -14683,18 +14717,18 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz", - "integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz", + "integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==", "requires": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.24.5", "@babel/helper-optimise-call-expression": "^7.22.5", "@babel/helper-replace-supers": "^7.24.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-split-export-declaration": "^7.24.5", "semver": "^6.3.1" }, "dependencies": { @@ -14778,11 +14812,11 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz", + "integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==", "requires": { - "@babel/types": "^7.23.0" + "@babel/types": "^7.24.5" } }, "@babel/helper-module-imports": { @@ -14794,15 +14828,15 @@ } }, "@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", + "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", "requires": { "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-simple-access": "^7.24.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.5" } }, "@babel/helper-optimise-call-expression": { @@ -14814,9 +14848,9 @@ } }, "@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==" + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==" }, "@babel/helper-remap-async-to-generator": { "version": "7.22.20", @@ -14839,11 +14873,11 @@ } }, "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", + "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" } }, "@babel/helper-skip-transparent-expression-wrappers": { @@ -14855,22 +14889,22 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.5" } }, "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==" }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==" }, "@babel/helper-validator-option": { "version": "7.23.5", @@ -14888,13 +14922,13 @@ } }, "@babel/helpers": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", - "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", + "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", "requires": { "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5" } }, "@babel/highlight": { @@ -14909,9 +14943,9 @@ } }, "@babel/parser": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", - "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==" + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.23.3", @@ -15462,14 +15496,14 @@ } }, "@babel/plugin-transform-private-property-in-object": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", - "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.5.tgz", + "integrity": "sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==", "peer": true, "requires": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-create-class-features-plugin": "^7.24.5", + "@babel/helper-plugin-utils": "^7.24.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, @@ -15511,12 +15545,12 @@ } }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.1.tgz", - "integrity": "sha512-kDJgnPujTmAZ/9q2CN4m2/lRsUUPDvsG3+tSHWUJIzMGTt5U/b/fwWd3RO3n+5mjLrsBrVa5eKFRVSQbi3dF1w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.5.tgz", + "integrity": "sha512-RtCJoUO2oYrYwFPtR1/jkoBEcFuI1ae9a9IMxeyAVa3a1Ap4AnxmyIKG2b2FaJKqkidw/0cxRbWN+HOs6ZWd1w==", "peer": true, "requires": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.5" } }, "@babel/plugin-transform-react-jsx-source": { @@ -15570,9 +15604,9 @@ }, "dependencies": { "@babel/helper-define-polyfill-provider": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", - "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", "peer": true, "requires": { "@babel/helper-compilation-targets": "^7.22.6", @@ -15583,13 +15617,13 @@ } }, "babel-plugin-polyfill-corejs2": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", - "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", "peer": true, "requires": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.1", + "@babel/helper-define-polyfill-provider": "^0.6.2", "semver": "^6.3.1" } }, @@ -15604,12 +15638,12 @@ } }, "babel-plugin-polyfill-regenerator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", - "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", "peer": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.6.1" + "@babel/helper-define-polyfill-provider": "^0.6.2" } }, "debug": { @@ -15883,18 +15917,18 @@ } }, "@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", "requires": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -15915,12 +15949,12 @@ } }, "@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", "to-fast-properties": "^2.0.0" } }, @@ -16006,11 +16040,18 @@ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==", "dev": true }, + "@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "requires": { + "@emotion/memoize": "^0.8.1" + } + }, "@emotion/memoize": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", - "dev": true + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "@emotion/react": { "version": "11.11.0", @@ -16067,8 +16108,7 @@ "@emotion/unitless": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", - "dev": true + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" }, "@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.1", @@ -16403,7 +16443,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -16412,34 +16451,31 @@ "@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" }, "@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "@react-native-community/cli": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.6.tgz", - "integrity": "sha512-647OSi6xBb8FbwFqX9zsJxOzu685AWtrOUWHfOkbKD+5LOpGORw+GQo0F9rWZnB68rLQyfKUZWJeaD00pGv5fw==", - "peer": true, - "requires": { - "@react-native-community/cli-clean": "12.3.6", - "@react-native-community/cli-config": "12.3.6", - "@react-native-community/cli-debugger-ui": "12.3.6", - "@react-native-community/cli-doctor": "12.3.6", - "@react-native-community/cli-hermes": "12.3.6", - "@react-native-community/cli-plugin-metro": "12.3.6", - "@react-native-community/cli-server-api": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", - "@react-native-community/cli-types": "12.3.6", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-13.6.6.tgz", + "integrity": "sha512-IqclB7VQ84ye8Fcs89HOpOscY4284VZg2pojHNl8H0Lzd4DadXJWQoxC7zWm8v2f8eyeX2kdhxp2ETD5tceIgA==", + "peer": true, + "requires": { + "@react-native-community/cli-clean": "13.6.6", + "@react-native-community/cli-config": "13.6.6", + "@react-native-community/cli-debugger-ui": "13.6.6", + "@react-native-community/cli-doctor": "13.6.6", + "@react-native-community/cli-hermes": "13.6.6", + "@react-native-community/cli-server-api": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", + "@react-native-community/cli-types": "13.6.6", "chalk": "^4.1.2", "commander": "^9.4.1", "deepmerge": "^4.3.0", @@ -16536,12 +16572,6 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "peer": true }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true - }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -16551,15 +16581,6 @@ "p-locate": "^4.1.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "peer": true, - "requires": { - "yallist": "^4.0.0" - } - }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -16591,13 +16612,10 @@ "peer": true }, "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "peer": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.1.tgz", + "integrity": "sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==", + "peer": true }, "supports-color": { "version": "7.2.0", @@ -16605,26 +16623,21 @@ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "peer": true, "requires": { - "has-flag": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "peer": true + "has-flag": "^4.0.0" + } } } }, "@react-native-community/cli-clean": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-12.3.6.tgz", - "integrity": "sha512-gUU29ep8xM0BbnZjwz9MyID74KKwutq9x5iv4BCr2im6nly4UMf1B1D+V225wR7VcDGzbgWjaezsJShLLhC5ig==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-13.6.6.tgz", + "integrity": "sha512-cBwJTwl0NyeA4nyMxbhkWZhxtILYkbU3TW3k8AXLg+iGphe0zikYMGB3T+haTvTc6alTyEFwPbimk9bGIqkjAQ==", "peer": true, "requires": { - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", - "execa": "^5.0.0" + "execa": "^5.0.0", + "fast-glob": "^3.3.2" }, "dependencies": { "ansi-styles": { @@ -16696,12 +16709,6 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "peer": true }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -16714,16 +16721,16 @@ } }, "@react-native-community/cli-config": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-12.3.6.tgz", - "integrity": "sha512-JGWSYQ9EAK6m2v0abXwFLEfsqJ1zkhzZ4CV261QZF9MoUNB6h57a274h1MLQR9mG6Tsh38wBUuNfEPUvS1vYew==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-13.6.6.tgz", + "integrity": "sha512-mbG425zCKr8JZhv/j11382arezwS/70juWMsn8j2lmrGTrP1cUdW0MF15CCIFtJsqyK3Qs+FTmqttRpq81QfSg==", "peer": true, "requires": { - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "cosmiconfig": "^5.1.0", "deepmerge": "^4.3.0", - "glob": "^7.1.3", + "fast-glob": "^3.3.2", "joi": "^17.2.1" }, "dependencies": { @@ -16817,24 +16824,25 @@ } }, "@react-native-community/cli-debugger-ui": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.6.tgz", - "integrity": "sha512-SjUKKsx5FmcK9G6Pb6UBFT0s9JexVStK5WInmANw75Hm7YokVvHEgtprQDz2Uvy5znX5g2ujzrkIU//T15KQzA==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-13.6.6.tgz", + "integrity": "sha512-Vv9u6eS4vKSDAvdhA0OiQHoA7y39fiPIgJ6biT32tN4avHDtxlc6TWZGiqv7g98SBvDWvoVAmdPLcRf3kU+c8g==", "peer": true, "requires": { "serve-static": "^1.13.1" } }, "@react-native-community/cli-doctor": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-12.3.6.tgz", - "integrity": "sha512-fvBDv2lTthfw4WOQKkdTop2PlE9GtfrlNnpjB818MhcdEnPjfQw5YaTUcnNEGsvGomdCs1MVRMgYXXwPSN6OvQ==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-13.6.6.tgz", + "integrity": "sha512-TWZb5g6EmQe2Ua2TEWNmyaEayvlWH4GmdD9ZC+p8EpKFpB1NpDGMK6sXbpb42TDvwZg5s4TDRplK0PBEA/SVDg==", "peer": true, "requires": { - "@react-native-community/cli-config": "12.3.6", - "@react-native-community/cli-platform-android": "12.3.6", - "@react-native-community/cli-platform-ios": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-config": "13.6.6", + "@react-native-community/cli-platform-android": "13.6.6", + "@react-native-community/cli-platform-apple": "13.6.6", + "@react-native-community/cli-platform-ios": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "command-exists": "^1.2.8", "deepmerge": "^4.3.0", @@ -16924,29 +16932,11 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "peer": true }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "peer": true, - "requires": { - "yallist": "^4.0.0" - } - }, "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "peer": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.1.tgz", + "integrity": "sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==", + "peer": true }, "strip-ansi": { "version": "5.2.0", @@ -16966,28 +16956,22 @@ "has-flag": "^4.0.0" } }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "peer": true - }, "yaml": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", - "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz", + "integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==", "peer": true } } }, "@react-native-community/cli-hermes": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-12.3.6.tgz", - "integrity": "sha512-sNGwfOCl8OAIjWCkwuLpP8NZbuO0dhDI/2W7NeOGDzIBsf4/c4MptTrULWtGIH9okVPLSPX0NnRyGQ+mSwWyuQ==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-13.6.6.tgz", + "integrity": "sha512-La5Ie+NGaRl3klei6WxKoOxmCUSGGxpOk6vU5pEGf0/O7ky+Ay0io+zXYUZqlNMi/cGpO7ZUijakBYOB/uyuFg==", "peer": true, "requires": { - "@react-native-community/cli-platform-android": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-platform-android": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "hermes-profile-transformer": "^0.0.6" }, @@ -17044,16 +17028,16 @@ } }, "@react-native-community/cli-platform-android": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.6.tgz", - "integrity": "sha512-DeDDAB8lHpuGIAPXeeD9Qu2+/wDTFPo99c8uSW49L0hkmZJixzvvvffbGQAYk32H0TmaI7rzvzH+qzu7z3891g==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-13.6.6.tgz", + "integrity": "sha512-/tMwkBeNxh84syiSwNlYtmUz/Ppc+HfKtdopL/5RB+fd3SV1/5/NPNjMlyLNgFKnpxvKCInQ7dnl6jGHJjeHjg==", "peer": true, "requires": { - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "execa": "^5.0.0", + "fast-glob": "^3.3.2", "fast-xml-parser": "^4.2.4", - "glob": "^7.1.3", "logkitty": "^0.7.1" }, "dependencies": { @@ -17126,12 +17110,6 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "peer": true }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -17143,17 +17121,17 @@ } } }, - "@react-native-community/cli-platform-ios": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.6.tgz", - "integrity": "sha512-3eZ0jMCkKUO58wzPWlvAPRqezVKm9EPZyaPyHbRPWU8qw7JqkvnRlWIaYDGpjCJgVW4k2hKsEursLtYKb188tg==", + "@react-native-community/cli-platform-apple": { + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-apple/-/cli-platform-apple-13.6.6.tgz", + "integrity": "sha512-bOmSSwoqNNT3AmCRZXEMYKz1Jf1l2F86Nhs7qBcXdY/sGiJ+Flng564LOqvdAlVLTbkgz47KjNKCS2pP4Jg0Mg==", "peer": true, "requires": { - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-tools": "13.6.6", "chalk": "^4.1.2", "execa": "^5.0.0", + "fast-glob": "^3.3.2", "fast-xml-parser": "^4.0.12", - "glob": "^7.1.3", "ora": "^5.4.1" }, "dependencies": { @@ -17226,12 +17204,6 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "peer": true }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "peer": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -17243,37 +17215,52 @@ } } }, - "@react-native-community/cli-plugin-metro": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.6.tgz", - "integrity": "sha512-3jxSBQt4fkS+KtHCPSyB5auIT+KKIrPCv9Dk14FbvOaEh9erUWEm/5PZWmtboW1z7CYeNbFMeXm9fM2xwtVOpg==", - "peer": true + "@react-native-community/cli-platform-ios": { + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-13.6.6.tgz", + "integrity": "sha512-vjDnRwhlSN5ryqKTas6/DPkxuouuyFBAqAROH4FR1cspTbn6v78JTZKDmtQy9JMMo7N5vZj1kASU5vbFep9IOQ==", + "peer": true, + "requires": { + "@react-native-community/cli-platform-apple": "13.6.6" + } }, "@react-native-community/cli-server-api": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-12.3.6.tgz", - "integrity": "sha512-80NIMzo8b2W+PL0Jd7NjiJW9mgaT8Y8wsIT/lh6mAvYH7mK0ecDJUYUTAAv79Tbo1iCGPAr3T295DlVtS8s4yQ==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-13.6.6.tgz", + "integrity": "sha512-ZtCXxoFlM7oDv3iZ3wsrT3SamhtUJuIkX2WePLPlN5bcbq7zimbPm2lHyicNJtpcGQ5ymsgpUWPCNZsWQhXBqQ==", "peer": true, "requires": { - "@react-native-community/cli-debugger-ui": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", + "@react-native-community/cli-debugger-ui": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", "compression": "^1.7.1", "connect": "^3.6.5", "errorhandler": "^1.5.1", "nocache": "^3.0.1", "pretty-format": "^26.6.2", "serve-static": "^1.13.1", - "ws": "^7.5.1" + "ws": "^6.2.2" + }, + "dependencies": { + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "peer": true, + "requires": { + "async-limiter": "~1.0.0" + } + } } }, "@react-native-community/cli-tools": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-12.3.6.tgz", - "integrity": "sha512-FPEvZn19UTMMXUp/piwKZSh8cMEfO8G3KDtOwo53O347GTcwNrKjgZGtLSPELBX2gr+YlzEft3CoRv2Qmo83fQ==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-13.6.6.tgz", + "integrity": "sha512-ptOnn4AJczY5njvbdK91k4hcYazDnGtEPrqIwEI+k/CTBHNdb27Rsm2OZ7ye6f7otLBqF8gj/hK6QzJs8CEMgw==", "peer": true, "requires": { "appdirsjs": "^1.2.4", "chalk": "^4.1.2", + "execa": "^5.0.0", "find-up": "^5.0.0", "mime": "^2.4.1", "node-fetch": "^2.6.0", @@ -17318,6 +17305,23 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "peer": true }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "peer": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -17328,12 +17332,24 @@ "path-exists": "^4.0.0" } }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "peer": true + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "peer": true }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "peer": true + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -17343,24 +17359,6 @@ "p-locate": "^5.0.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "peer": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "peer": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -17386,13 +17384,10 @@ "peer": true }, "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "peer": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.1.tgz", + "integrity": "sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==", + "peer": true }, "supports-color": { "version": "7.2.0", @@ -17402,55 +17397,44 @@ "requires": { "has-flag": "^4.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "peer": true } } }, "@react-native-community/cli-types": { - "version": "12.3.6", - "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-12.3.6.tgz", - "integrity": "sha512-xPqTgcUtZowQ8WKOkI9TLGBwH2bGggOC4d2FFaIRST3gTcjrEeGRNeR5aXCzJFIgItIft8sd7p2oKEdy90+01Q==", + "version": "13.6.6", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-13.6.6.tgz", + "integrity": "sha512-733iaYzlmvNK7XYbnWlMjdE+2k0hlTBJW071af/xb6Bs+hbJqBP9c03FZuYH2hFFwDDntwj05bkri/P7VgSxug==", "peer": true, "requires": { "joi": "^17.2.1" } }, - "@react-native-community/netinfo": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-4.7.0.tgz", - "integrity": "sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA==", - "requires": {} - }, "@react-native/assets-registry": { - "version": "0.73.1", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.73.1.tgz", - "integrity": "sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.74.83.tgz", + "integrity": "sha512-2vkLMVnp+YTZYTNSDIBZojSsjz8sl5PscP3j4GcV6idD8V978SZfwFlk8K0ti0BzRs11mzL0Pj17km597S/eTQ==", "peer": true }, "@react-native/babel-plugin-codegen": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz", - "integrity": "sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.74.83.tgz", + "integrity": "sha512-+S0st3t4Ro00bi9gjT1jnK8qTFOU+CwmziA7U9odKyWrCoRJrgmrvogq/Dr1YXlpFxexiGIupGut1VHxr+fxJA==", "peer": true, "requires": { - "@react-native/codegen": "0.73.3" + "@react-native/codegen": "0.74.83" } }, "@react-native/babel-preset": { - "version": "0.73.21", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.21.tgz", - "integrity": "sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.74.83.tgz", + "integrity": "sha512-KJuu3XyVh3qgyUer+rEqh9a/JoUxsDOzkJNfRpDyXiAyjDRoVch60X/Xa/NcEQ93iCVHAWs0yQ+XGNGIBCYE6g==", "peer": true, "requires": { "@babel/core": "^7.20.0", "@babel/plugin-proposal-async-generator-functions": "^7.0.0", "@babel/plugin-proposal-class-properties": "^7.18.0", "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", "@babel/plugin-proposal-numeric-separator": "^7.0.0", "@babel/plugin-proposal-object-rest-spread": "^7.20.0", @@ -17486,27 +17470,27 @@ "@babel/plugin-transform-typescript": "^7.5.0", "@babel/plugin-transform-unicode-regex": "^7.0.0", "@babel/template": "^7.0.0", - "@react-native/babel-plugin-codegen": "0.73.4", + "@react-native/babel-plugin-codegen": "0.74.83", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" }, "dependencies": { "@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -17578,14 +17562,14 @@ } }, "@react-native/codegen": { - "version": "0.73.3", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.73.3.tgz", - "integrity": "sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.74.83.tgz", + "integrity": "sha512-GgvgHS3Aa2J8/mp1uC/zU8HuTh8ZT5jz7a4mVMWPw7+rGyv70Ba8uOVBq6UH2Q08o617IATYc+0HfyzAfm4n0w==", "peer": true, "requires": { "@babel/parser": "^7.20.0", - "flow-parser": "^0.206.0", "glob": "^7.1.1", + "hermes-parser": "0.19.1", "invariant": "^2.2.4", "jscodeshift": "^0.14.0", "mkdirp": "^0.5.1", @@ -17593,21 +17577,22 @@ } }, "@react-native/community-cli-plugin": { - "version": "0.73.17", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.17.tgz", - "integrity": "sha512-F3PXZkcHg+1ARIr6FRQCQiB7ZAA+MQXGmq051metRscoLvgYJwj7dgC8pvgy0kexzUkHu5BNKrZeySzUft3xuQ==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.74.83.tgz", + "integrity": "sha512-7GAFjFOg1mFSj8bnFNQS4u8u7+QtrEeflUIDVZGEfBZQ3wMNI5ycBzbBGycsZYiq00Xvoc6eKFC7kvIaqeJpUQ==", "peer": true, "requires": { - "@react-native-community/cli-server-api": "12.3.6", - "@react-native-community/cli-tools": "12.3.6", - "@react-native/dev-middleware": "0.73.8", - "@react-native/metro-babel-transformer": "0.73.15", + "@react-native-community/cli-server-api": "13.6.6", + "@react-native-community/cli-tools": "13.6.6", + "@react-native/dev-middleware": "0.74.83", + "@react-native/metro-babel-transformer": "0.74.83", "chalk": "^4.0.0", "execa": "^5.1.1", "metro": "^0.80.3", "metro-config": "^0.80.3", "metro-core": "^0.80.3", "node-fetch": "^2.2.0", + "querystring": "^0.2.1", "readline": "^1.3.0" }, "dependencies": { @@ -17680,21 +17665,12 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "peer": true }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", "peer": true }, - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "peer": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -17707,39 +17683,32 @@ } }, "@react-native/debugger-frontend": { - "version": "0.73.3", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz", - "integrity": "sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.74.83.tgz", + "integrity": "sha512-RGQlVUegBRxAUF9c1ss1ssaHZh6CO+7awgtI9sDeU0PzDZY/40ImoPD5m0o0SI6nXoVzbPtcMGzU+VO590pRfA==", "peer": true }, "@react-native/dev-middleware": { - "version": "0.73.8", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz", - "integrity": "sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.74.83.tgz", + "integrity": "sha512-UH8iriqnf7N4Hpi20D7M2FdvSANwTVStwFCSD7VMU9agJX88Yk0D1T6Meh2RMhUu4kY2bv8sTkNRm7LmxvZqgA==", "peer": true, "requires": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.73.3", + "@react-native/debugger-frontend": "0.74.83", + "@rnx-kit/chromium-edge-launcher": "^1.0.0", "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^1.0.0", "connect": "^3.6.5", "debug": "^2.2.0", "node-fetch": "^2.2.0", + "nullthrows": "^1.1.1", "open": "^7.0.3", + "selfsigned": "^2.4.1", "serve-static": "^1.13.1", "temp-dir": "^2.0.0", "ws": "^6.2.2" }, "dependencies": { - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "peer": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, "open": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", @@ -17762,45 +17731,45 @@ } }, "@react-native/gradle-plugin": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.4.tgz", - "integrity": "sha512-PMDnbsZa+tD55Ug+W8CfqXiGoGneSSyrBZCMb5JfiB3AFST3Uj5e6lw8SgI/B6SKZF7lG0BhZ6YHZsRZ5MlXmg==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.74.83.tgz", + "integrity": "sha512-Pw2BWVyOHoBuJVKxGVYF6/GSZRf6+v1Ygc+ULGz5t20N8qzRWPa2fRZWqoxsN7TkNLPsECYY8gooOl7okOcPAQ==", "peer": true }, "@react-native/js-polyfills": { - "version": "0.73.1", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", - "integrity": "sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.74.83.tgz", + "integrity": "sha512-/t74n8r6wFhw4JEoOj3bN71N1NDLqaawB75uKAsSjeCwIR9AfCxlzZG0etsXtOexkY9KMeZIQ7YwRPqUdNXuqw==", "peer": true }, "@react-native/metro-babel-transformer": { - "version": "0.73.15", - "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz", - "integrity": "sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.74.83.tgz", + "integrity": "sha512-hGdx5N8diu8y+GW/ED39vTZa9Jx1di2ZZ0aapbhH4egN1agIAusj5jXTccfNBwwWF93aJ5oVbRzfteZgjbutKg==", "peer": true, "requires": { "@babel/core": "^7.20.0", - "@react-native/babel-preset": "0.73.21", - "hermes-parser": "0.15.0", + "@react-native/babel-preset": "0.74.83", + "hermes-parser": "0.19.1", "nullthrows": "^1.1.1" }, "dependencies": { "@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -17838,11 +17807,57 @@ } }, "@react-native/normalize-colors": { - "version": "0.73.2", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz", - "integrity": "sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==", + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.83.tgz", + "integrity": "sha512-jhCY95gRDE44qYawWVvhTjTplW1g+JtKTKM3f8xYT1dJtJ8QWv+gqEtKcfmOHfDkSDaMKG0AGBaDTSK8GXLH8Q==", "peer": true }, + "@rnx-kit/chromium-edge-launcher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rnx-kit/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", + "integrity": "sha512-lzD84av1ZQhYUS+jsGqJiCMaJO2dn9u+RTT9n9q6D3SaKVwWqv+7AoRKqBu19bkwyE+iFRl1ymr40QS90jVFYg==", + "peer": true, + "requires": { + "@types/node": "^18.0.0", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "@types/node": { + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", + "peer": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "peer": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "peer": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "peer": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -17972,6 +17987,15 @@ "undici-types": "~5.26.4" } }, + "@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "peer": true, + "requires": { + "@types/node": "*" + } + }, "@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -17984,9 +18008,9 @@ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/react": { - "version": "16.9.56", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.56.tgz", - "integrity": "sha512-gIkl4J44G/qxbuC6r2Xh+D3CGZpJ+NdWTItAPmZbR5mUS+JQ8Zvzpl0ea5qT/ZT3ZNTUcDKUVqV3xBE8wv/DyQ==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz", + "integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==", "requires": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -17998,6 +18022,11 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "peer": true }, + "@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==" + }, "@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -19091,6 +19120,11 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "peer": true }, + "camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" + }, "caniuse-lite": { "version": "1.0.30001587", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", @@ -19152,43 +19186,6 @@ "tslib": "^1.9.0" } }, - "chromium-edge-launcher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", - "integrity": "sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==", - "peer": true, - "requires": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0", - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "dependencies": { - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "peer": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "peer": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "peer": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -19529,15 +19526,30 @@ "randomfill": "^1.0.3" } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==" + }, + "css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "csstype": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.4.tgz", - "integrity": "sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==", "peer": true }, "debug": { @@ -19615,30 +19627,6 @@ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "peer": true }, - "deprecated-react-native-prop-types": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz", - "integrity": "sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==", - "peer": true, - "requires": { - "@react-native/normalize-colors": "^0.73.0", - "invariant": "^2.2.4", - "prop-types": "^15.8.1" - }, - "dependencies": { - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "peer": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - } - } - }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -19757,16 +19745,6 @@ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "peer": true }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "peer": true, - "requires": { - "iconv-lite": "^0.6.2" - } - }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -20277,14 +20255,6 @@ "onetime": "^5.1.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" - }, - "dependencies": { - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - } } }, "fast-deep-equal": { @@ -20297,7 +20267,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -20331,7 +20300,6 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, "requires": { "reusify": "^1.0.4" } @@ -20426,9 +20394,9 @@ "peer": true }, "flow-parser": { - "version": "0.206.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", - "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", + "version": "0.235.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.235.1.tgz", + "integrity": "sha512-s04193L4JE+ntEcQXbD6jxRRlyj9QXcgEl2W6xSjH4l9x4b0eHoCHfbYHjqf9LdZFUiM5LhgpiqsvLj/AyOyYQ==", "peer": true }, "form-data": { @@ -20547,7 +20515,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -20665,18 +20632,18 @@ } }, "hermes-estree": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.15.0.tgz", - "integrity": "sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.19.1.tgz", + "integrity": "sha512-daLGV3Q2MKk8w4evNMKwS8zBE/rcpA800nu1Q5kM08IKijoSnPe9Uo1iIxzPKRkn95IxxsgBMPeYHt3VG4ej2g==", "peer": true }, "hermes-parser": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.15.0.tgz", - "integrity": "sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.19.1.tgz", + "integrity": "sha512-Vp+bXzxYJWrpEuJ/vXxUsLnt0+y4q9zyi4zUlkLqD8FKv4LjIfOvP69R/9Lty3dCyKh0E2BU7Eypqr63/rKT/A==", "peer": true, "requires": { - "hermes-estree": "0.15.0" + "hermes-estree": "0.19.1" } }, "hermes-profile-transformer": { @@ -20754,16 +20721,6 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, - "iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "optional": true, - "peer": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -20997,8 +20954,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -21009,7 +20965,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -21049,6 +21004,11 @@ "has-symbols": "^1.0.1" } }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, "is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", @@ -21192,9 +21152,9 @@ } }, "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "peer": true }, "slash": { @@ -21364,9 +21324,9 @@ } }, "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "peer": true }, "supports-color": { @@ -21409,9 +21369,9 @@ } }, "joi": { - "version": "17.12.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.3.tgz", - "integrity": "sha512-2RRziagf555owrm9IRVtdKynOBeITiDpuZqIpgwqXShPncPKNiRQoiGsl/T8SQdq+8ugRzH2LqY67irr2y/d+g==", + "version": "17.13.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.1.tgz", + "integrity": "sha512-vaBlIKCyo4FCUtCm7Eu4QZd/q02bWcxfUO6YSXAZOWF6gzcLBeba8kwotUdYJjDLW8Cz8RywsSOqiNJZW0mNvg==", "peer": true, "requires": { "@hapi/hoek": "^9.3.0", @@ -22059,13 +22019,12 @@ "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "metro": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.8.tgz", - "integrity": "sha512-in7S0W11mg+RNmcXw+2d9S3zBGmCARDxIwoXJAmLUQOQoYsRP3cpGzyJtc7WOw8+FXfpgXvceD0u+PZIHXEL7g==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.9.tgz", + "integrity": "sha512-Bc57Xf3GO2Xe4UWQsBj/oW6YfLPABEu8jfDVDiNmJvoQW4CO34oDPuYKe4KlXzXhcuNsqOtSxpbjCRRVjhhREg==", "peer": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -22089,18 +22048,18 @@ "jest-worker": "^29.6.3", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.80.8", - "metro-cache": "0.80.8", - "metro-cache-key": "0.80.8", - "metro-config": "0.80.8", - "metro-core": "0.80.8", - "metro-file-map": "0.80.8", - "metro-resolver": "0.80.8", - "metro-runtime": "0.80.8", - "metro-source-map": "0.80.8", - "metro-symbolicate": "0.80.8", - "metro-transform-plugins": "0.80.8", - "metro-transform-worker": "0.80.8", + "metro-babel-transformer": "0.80.9", + "metro-cache": "0.80.9", + "metro-cache-key": "0.80.9", + "metro-config": "0.80.9", + "metro-core": "0.80.9", + "metro-file-map": "0.80.9", + "metro-resolver": "0.80.9", + "metro-runtime": "0.80.9", + "metro-source-map": "0.80.9", + "metro-symbolicate": "0.80.9", + "metro-transform-plugins": "0.80.9", + "metro-transform-worker": "0.80.9", "mime-types": "^2.1.27", "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", @@ -22114,21 +22073,21 @@ }, "dependencies": { "@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -22243,15 +22202,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "peer": true }, - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "peer": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -22285,9 +22235,9 @@ } }, "metro-babel-transformer": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.8.tgz", - "integrity": "sha512-TTzNwRZb2xxyv4J/+yqgtDAP2qVqH3sahsnFu6Xv4SkLqzrivtlnyUbaeTdJ9JjtADJUEjCbgbFgUVafrXdR9Q==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.9.tgz", + "integrity": "sha512-d76BSm64KZam1nifRZlNJmtwIgAeZhZG3fi3K+EmPOlrR8rDtBxQHDSN3fSGeNB9CirdTyabTMQCkCup6BXFSQ==", "peer": true, "requires": { "@babel/core": "^7.20.0", @@ -22296,21 +22246,21 @@ }, "dependencies": { "@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -22363,12 +22313,12 @@ } }, "metro-cache": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.8.tgz", - "integrity": "sha512-5svz+89wSyLo7BxdiPDlwDTgcB9kwhNMfNhiBZPNQQs1vLFXxOkILwQiV5F2EwYT9DEr6OPZ0hnJkZfRQ8lDYQ==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.9.tgz", + "integrity": "sha512-ujEdSI43QwI+Dj2xuNax8LMo8UgKuXJEdxJkzGPU6iIx42nYa1byQ+aADv/iPh5sh5a//h5FopraW5voXSgm2w==", "peer": true, "requires": { - "metro-core": "0.80.8", + "metro-core": "0.80.9", "rimraf": "^3.0.2" }, "dependencies": { @@ -22384,24 +22334,24 @@ } }, "metro-cache-key": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.8.tgz", - "integrity": "sha512-qWKzxrLsRQK5m3oH8ePecqCc+7PEhR03cJE6Z6AxAj0idi99dHOSitTmY0dclXVB9vP2tQIAE8uTd8xkYGk8fA==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.9.tgz", + "integrity": "sha512-hRcYGhEiWIdM87hU0fBlcGr+tHDEAT+7LYNCW89p5JhErFt/QaAkVx4fb5bW3YtXGv5BTV7AspWPERoIb99CXg==", "peer": true }, "metro-config": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.8.tgz", - "integrity": "sha512-VGQJpfJawtwRzGzGXVUoohpIkB0iPom4DmSbAppKfumdhtLA8uVeEPp2GM61kL9hRvdbMhdWA7T+hZFDlo4mJA==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.9.tgz", + "integrity": "sha512-28wW7CqS3eJrunRGnsibWldqgwRP9ywBEf7kg+uzUHkSFJNKPM1K3UNSngHmH0EZjomizqQA2Zi6/y6VdZMolg==", "peer": true, "requires": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "jest-validate": "^29.6.3", - "metro": "0.80.8", - "metro-cache": "0.80.8", - "metro-core": "0.80.8", - "metro-runtime": "0.80.8" + "metro": "0.80.9", + "metro-cache": "0.80.9", + "metro-core": "0.80.9", + "metro-runtime": "0.80.9" }, "dependencies": { "cosmiconfig": { @@ -22445,19 +22395,19 @@ } }, "metro-core": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.8.tgz", - "integrity": "sha512-g6lud55TXeISRTleW6SHuPFZHtYrpwNqbyFIVd9j9Ofrb5IReiHp9Zl8xkAfZQp8v6ZVgyXD7c130QTsCz+vBw==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.9.tgz", + "integrity": "sha512-tbltWQn+XTdULkGdzHIxlxk4SdnKxttvQQV3wpqqFbHDteR4gwCyTR2RyYJvxgU7HELfHtrVbqgqAdlPByUSbg==", "peer": true, "requires": { "lodash.throttle": "^4.1.1", - "metro-resolver": "0.80.8" + "metro-resolver": "0.80.9" } }, "metro-file-map": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.8.tgz", - "integrity": "sha512-eQXMFM9ogTfDs2POq7DT2dnG7rayZcoEgRbHPXvhUWkVwiKkro2ngcBE++ck/7A36Cj5Ljo79SOkYwHaWUDYDw==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.9.tgz", + "integrity": "sha512-sBUjVtQMHagItJH/wGU9sn3k2u0nrCl0CdR4SFMO1tksXLKbkigyQx4cbpcyPVOAmGTVuy3jyvBlELaGCAhplQ==", "peer": true, "requires": { "anymatch": "^3.0.3", @@ -22503,53 +22453,53 @@ } }, "metro-minify-terser": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.8.tgz", - "integrity": "sha512-y8sUFjVvdeUIINDuW1sejnIjkZfEF+7SmQo0EIpYbWmwh+kq/WMj74yVaBWuqNjirmUp1YNfi3alT67wlbBWBQ==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.9.tgz", + "integrity": "sha512-FEeCeFbkvvPuhjixZ1FYrXtO0araTpV6UbcnGgDUpH7s7eR5FG/PiJz3TsuuPP/HwCK19cZtQydcA2QrCw446A==", "peer": true, "requires": { "terser": "^5.15.0" } }, "metro-resolver": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.8.tgz", - "integrity": "sha512-JdtoJkP27GGoZ2HJlEsxs+zO7jnDUCRrmwXJozTlIuzLHMRrxgIRRby9fTCbMhaxq+iA9c+wzm3iFb4NhPmLbQ==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.9.tgz", + "integrity": "sha512-wAPIjkN59BQN6gocVsAvvpZ1+LQkkqUaswlT++cJafE/e54GoVkMNCmrR4BsgQHr9DknZ5Um/nKueeN7kaEz9w==", "peer": true }, "metro-runtime": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.8.tgz", - "integrity": "sha512-2oScjfv6Yb79PelU1+p8SVrCMW9ZjgEiipxq7jMRn8mbbtWzyv3g8Mkwr+KwOoDFI/61hYPUbY8cUnu278+x1g==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.9.tgz", + "integrity": "sha512-8PTVIgrVcyU+X/rVCy/9yxNlvXsBCk5JwwkbAm/Dm+Abo6NBGtNjWF0M1Xo/NWCb4phamNWcD7cHdR91HhbJvg==", "peer": true, "requires": { "@babel/runtime": "^7.0.0" } }, "metro-source-map": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.8.tgz", - "integrity": "sha512-+OVISBkPNxjD4eEKhblRpBf463nTMk3KMEeYS8Z4xM/z3qujGJGSsWUGRtH27+c6zElaSGtZFiDMshEb8mMKQg==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.9.tgz", + "integrity": "sha512-RMn+XS4VTJIwMPOUSj61xlxgBvPeY4G6s5uIn6kt6HB6A/k9ekhr65UkkDD7WzHYs3a9o869qU8tvOZvqeQzgw==", "peer": true, "requires": { "@babel/traverse": "^7.20.0", "@babel/types": "^7.20.0", "invariant": "^2.2.4", - "metro-symbolicate": "0.80.8", + "metro-symbolicate": "0.80.9", "nullthrows": "^1.1.1", - "ob1": "0.80.8", + "ob1": "0.80.9", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "metro-symbolicate": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.8.tgz", - "integrity": "sha512-nwhYySk79jQhwjL9QmOUo4wS+/0Au9joEryDWw7uj4kz2yvw1uBjwmlql3BprQCBzRdB3fcqOP8kO8Es+vE31g==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.9.tgz", + "integrity": "sha512-Ykae12rdqSs98hg41RKEToojuIW85wNdmSe/eHUgMkzbvCFNVgcC0w3dKZEhSsqQOXapXRlLtHkaHLil0UD/EA==", "peer": true, "requires": { "invariant": "^2.2.4", - "metro-source-map": "0.80.8", + "metro-source-map": "0.80.9", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "through2": "^2.0.1", @@ -22557,9 +22507,9 @@ } }, "metro-transform-plugins": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.8.tgz", - "integrity": "sha512-sSu8VPL9Od7w98MftCOkQ1UDeySWbsIAS5I54rW22BVpPnI3fQ42srvqMLaJUQPjLehUanq8St6OMBCBgH/UWw==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.9.tgz", + "integrity": "sha512-UlDk/uc8UdfLNJhPbF3tvwajyuuygBcyp+yBuS/q0z3QSuN/EbLllY3rK8OTD9n4h00qZ/qgxGv/lMFJkwP4vg==", "peer": true, "requires": { "@babel/core": "^7.20.0", @@ -22570,21 +22520,21 @@ }, "dependencies": { "@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -22622,41 +22572,41 @@ } }, "metro-transform-worker": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.8.tgz", - "integrity": "sha512-+4FG3TQk3BTbNqGkFb2uCaxYTfsbuFOCKMMURbwu0ehCP8ZJuTUramkaNZoATS49NSAkRgUltgmBa4YaKZ5mqw==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.9.tgz", + "integrity": "sha512-c/IrzMUVnI0hSVVit4TXzt3A1GiUltGVlzCmLJWxNrBGHGrJhvgePj38+GXl1Xf4Fd4vx6qLUkKMQ3ux73bFLQ==", "peer": true, "requires": { "@babel/core": "^7.20.0", "@babel/generator": "^7.20.0", "@babel/parser": "^7.20.0", "@babel/types": "^7.20.0", - "metro": "0.80.8", - "metro-babel-transformer": "0.80.8", - "metro-cache": "0.80.8", - "metro-cache-key": "0.80.8", - "metro-minify-terser": "0.80.8", - "metro-source-map": "0.80.8", - "metro-transform-plugins": "0.80.8", + "metro": "0.80.9", + "metro-babel-transformer": "0.80.9", + "metro-cache": "0.80.9", + "metro-cache-key": "0.80.9", + "metro-minify-terser": "0.80.9", + "metro-source-map": "0.80.9", + "metro-transform-plugins": "0.80.9", "nullthrows": "^1.1.1" }, "dependencies": { "@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", + "@babel/generator": "^7.24.5", "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -22838,6 +22788,21 @@ "minimatch": "^3.0.2" } }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "peer": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "peer": true + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -22945,9 +22910,9 @@ "peer": true }, "ob1": { - "version": "0.80.8", - "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.8.tgz", - "integrity": "sha512-QHJQk/lXMmAW8I7AIM3in1MSlwe1umR72Chhi8B7Xnq6mzjhBKkA6Fy/zAhQnGkA4S912EPCEvTij5yh+EQTAA==", + "version": "0.80.9", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.9.tgz", + "integrity": "sha512-v9yOxowkZbxWhKOaaTyLjIm1aLy4ebMNcSn4NYJKOAI/Qv+SkfEfszpLr2GIxsccmb2Y2HA9qtsqiIJ80ucpVA==", "peer": true }, "object-assign": { @@ -23361,6 +23326,28 @@ } } }, + "postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "dependencies": { + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" + } + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -23565,8 +23552,7 @@ "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, "randombytes": { "version": "2.1.0", @@ -23594,24 +23580,33 @@ "peer": true }, "react": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz", - "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "react-devtools-core": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", - "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-5.2.0.tgz", + "integrity": "sha512-vZK+/gvxxsieAoAyYaiRIVFxlajb7KXhgBDV7OsoMzaAE+IqGpoxusBjIgq5ibqA2IloKu0p9n7tE68z1xs18A==", "peer": true, "requires": { "shell-quote": "^1.6.1", "ws": "^7" } }, + "react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + } + }, "react-intl": { "version": "4.7.6", "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-4.7.6.tgz", @@ -23637,128 +23632,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "react-native": { - "version": "0.73.6", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.6.tgz", - "integrity": "sha512-oqmZe8D2/VolIzSPZw+oUd6j/bEmeRHwsLn1xLA5wllEYsZ5zNuMsDus235ONOnCRwexqof/J3aztyQswSmiaA==", - "peer": true, - "requires": { - "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "12.3.6", - "@react-native-community/cli-platform-android": "12.3.6", - "@react-native-community/cli-platform-ios": "12.3.6", - "@react-native/assets-registry": "0.73.1", - "@react-native/codegen": "0.73.3", - "@react-native/community-cli-plugin": "0.73.17", - "@react-native/gradle-plugin": "0.73.4", - "@react-native/js-polyfills": "0.73.1", - "@react-native/normalize-colors": "0.73.2", - "@react-native/virtualized-lists": "0.73.4", - "abort-controller": "^3.0.0", - "anser": "^1.4.9", - "ansi-regex": "^5.0.0", - "base64-js": "^1.5.1", - "chalk": "^4.0.0", - "deprecated-react-native-prop-types": "^5.0.0", - "event-target-shim": "^5.0.1", - "flow-enums-runtime": "^0.0.6", - "invariant": "^2.2.4", - "jest-environment-node": "^29.6.3", - "jsc-android": "^250231.0.0", - "memoize-one": "^5.0.0", - "metro-runtime": "^0.80.3", - "metro-source-map": "^0.80.3", - "mkdirp": "^0.5.1", - "nullthrows": "^1.1.1", - "pretty-format": "^26.5.2", - "promise": "^8.3.0", - "react-devtools-core": "^4.27.7", - "react-refresh": "^0.14.0", - "react-shallow-renderer": "^16.15.0", - "regenerator-runtime": "^0.13.2", - "scheduler": "0.24.0-canary-efb381bbf-20230505", - "stacktrace-parser": "^0.1.10", - "whatwg-fetch": "^3.0.0", - "ws": "^6.2.2", - "yargs": "^17.6.2" - }, - "dependencies": { - "@react-native/virtualized-lists": { - "version": "0.73.4", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz", - "integrity": "sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog==", - "peer": true, - "requires": { - "invariant": "^2.2.4", - "nullthrows": "^1.1.1" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "peer": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "peer": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "peer": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "peer": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "peer": true - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "peer": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "peer": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "ws": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", - "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", - "peer": true, - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, "react-redux": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.2.tgz", @@ -23787,9 +23660,9 @@ } }, "react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "peer": true }, "react-shallow-renderer": { @@ -23936,6 +23809,151 @@ "requires": { "@react-native-community/netinfo": "^4.1.3", "redux-persist": "^4.5.0" + }, + "dependencies": { + "@react-native-community/netinfo": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-4.7.0.tgz", + "integrity": "sha512-a/sDB+AsLEUNmhAUlAaTYeXKyQdFGBUfatqKkX5jluBo2CB3OAuTHfm7rSjcaLB9EmG5iSq3fOTpync2E7EYTA==", + "requires": {} + }, + "@react-native/virtualized-lists": { + "version": "0.74.83", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.74.83.tgz", + "integrity": "sha512-rmaLeE34rj7py4FxTod7iMTC7BAsm+HrGA8WxYmEJeyTV7WSaxAkosKoYBz8038mOiwnG9VwA/7FrB6bEQvn1A==", + "peer": true, + "requires": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "peer": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "peer": true + }, + "react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, + "react-native": { + "version": "0.74.1", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.74.1.tgz", + "integrity": "sha512-0H2XpmghwOtfPpM2LKqHIN7gxy+7G/r1hwJHKLV6uoyXGC/gCojRtoo5NqyKrWpFC8cqyT6wTYCLuG7CxEKilg==", + "peer": true, + "requires": { + "@jest/create-cache-key-function": "^29.6.3", + "@react-native-community/cli": "13.6.6", + "@react-native-community/cli-platform-android": "13.6.6", + "@react-native-community/cli-platform-ios": "13.6.6", + "@react-native/assets-registry": "0.74.83", + "@react-native/codegen": "0.74.83", + "@react-native/community-cli-plugin": "0.74.83", + "@react-native/gradle-plugin": "0.74.83", + "@react-native/js-polyfills": "0.74.83", + "@react-native/normalize-colors": "0.74.83", + "@react-native/virtualized-lists": "0.74.83", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", + "jsc-android": "^250231.0.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.80.3", + "metro-source-map": "^0.80.3", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.3.0", + "react-devtools-core": "^5.0.0", + "react-refresh": "^0.14.0", + "react-shallow-renderer": "^16.15.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.24.0-canary-efb381bbf-20230505", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.2", + "yargs": "^17.6.2" + } + }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "peer": true + }, + "scheduler": { + "version": "0.24.0-canary-efb381bbf-20230505", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", + "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "peer": true, + "requires": { + "async-limiter": "~1.0.0" + } + } } }, "redux-persist": { @@ -24115,8 +24133,7 @@ "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, "rimraf": { "version": "2.6.3", @@ -24150,7 +24167,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "requires": { "queue-microtask": "^1.2.2" } @@ -24160,13 +24176,6 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "optional": true, - "peer": true - }, "sc-channel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/sc-channel/-/sc-channel-1.2.0.tgz", @@ -24186,9 +24195,9 @@ "integrity": "sha512-9PbqYBpCq+OoEeRQ3QfFIGE6qwjjBcd2j7UjgDlhnZbtSnuGgHdcRklPKYGuYFH82V/dwd+AIpu8XvA1zqTd+A==" }, "scheduler": { - "version": "0.24.0-canary-efb381bbf-20230505", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", - "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "peer": true, "requires": { "loose-envify": "^1.1.0" @@ -24205,6 +24214,16 @@ "ajv-keywords": "^3.4.1" } }, + "selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "peer": true, + "requires": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + } + }, "semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", @@ -24336,6 +24355,11 @@ "resolved": "https://registry.npmjs.org/shallow-equals/-/shallow-equals-1.0.0.tgz", "integrity": "sha1-JLdL8cY0wR7Uxxgqbfb7MA3OQ5A=" }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -24441,6 +24465,11 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, + "source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==" + }, "source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -24708,6 +24737,34 @@ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", "peer": true }, + "styled-components": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.10.tgz", + "integrity": "sha512-4K8IKcn7iOt76riGLjvBhRyNPTkUKTvmnwoRFBOtJLswVvzy2VsoE2KOrfl9FJLQUYbITLJY2wfIZ3tjbkA/Zw==", + "requires": { + "@emotion/is-prop-valid": "1.2.2", + "@emotion/unitless": "0.8.1", + "@types/stylis": "4.2.5", + "css-to-react-native": "3.2.0", + "csstype": "3.1.3", + "postcss": "8.4.38", + "shallowequal": "1.1.0", + "stylis": "4.3.2", + "tslib": "2.6.2" + }, + "dependencies": { + "stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + } + } + }, "stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -25278,9 +25335,9 @@ "dev": true }, "whatwg-fetch": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz", - "integrity": "sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A==", + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", "peer": true }, "whatwg-url": { diff --git a/webapp/package.json b/webapp/package.json index b395e86e..2a5f7131 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -22,10 +22,11 @@ "core-js": "3.7.0", "mattermost-redux": "5.33.1", "prop-types": "15.7.2", - "react": "17.0.1", + "react": "18.3.1", "react-intl": "4.7.6", "react-redux": "7.2.2", "redux": "4.0.5", + "styled-components": "6.1.10", "typescript": "4.6.4" }, "devDependencies": { diff --git a/webapp/src/components/post_type_zoom/post_type_zoom.jsx b/webapp/src/components/post_type_zoom/post_type_zoom.jsx index 4850f205..a418ed3b 100644 --- a/webapp/src/components/post_type_zoom/post_type_zoom.jsx +++ b/webapp/src/components/post_type_zoom/post_type_zoom.jsx @@ -162,6 +162,9 @@ export default class PostTypeZoom extends React.PureComponent { {'Date: ' + start}
{'Meeting Length: ' + length + ' minute(s)'} + {props.meeting_recording && (
{'View Meeting Recording'}
)} + {props.meeting_transcript && (
{'View Meeting Transcript'}
)} + {props.meeting_password && (
{'Meeting Password: ' + props.meeting_password}
)} ); } else if (props.meeting_status === 'RECENTLY_CREATED') { diff --git a/webapp/src/index.js b/webapp/src/index.js index e9c4f138..e93a610b 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -7,6 +7,7 @@ import manifest from './manifest'; import ChannelHeaderIcon from './components/channel-header-icon'; import PostTypeZoom from './components/post_type_zoom'; +import {PostTypeTranscription} from './components/post_type_transcription'; import {startMeeting} from './actions'; import Client from './client'; import {getPluginURL, getServerRoute} from './selectors'; @@ -50,6 +51,7 @@ class Plugin { ); registry.registerPostTypeComponent('custom_zoom', PostTypeZoom); + registry.registerPostTypeComponent('custom_zoom_transcript', PostTypeTranscription); Client.setServerRoute(getServerRoute(store.getState())); } } diff --git a/webapp/webpack.config.js b/webapp/webpack.config.js index 9de57c95..de72ca1a 100644 --- a/webapp/webpack.config.js +++ b/webapp/webpack.config.js @@ -1,4 +1,5 @@ var path = require('path'); +var webpack = require('webpack'); module.exports = { entry: [ @@ -28,6 +29,11 @@ module.exports = { }, ], }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), + }) + ], externals: { react: 'React', 'react-dom': 'ReactDOM', From a305b43c76553c675e5973de834c287ddc445d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 10 May 2024 10:50:17 +0200 Subject: [PATCH 02/37] WIP --- server/webhook.go | 2 +- webapp/src/components/ai_icon.jsx | 33 +++++++++ .../components/post_type_transcription.jsx | 72 +++++++++++++++++++ webapp/src/components/svg.jsx | 13 ++++ 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 webapp/src/components/ai_icon.jsx create mode 100644 webapp/src/components/post_type_transcription.jsx create mode 100644 webapp/src/components/svg.jsx diff --git a/server/webhook.go b/server/webhook.go index 42916369..21ecd6be 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -215,7 +215,7 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques return } newPost.FileIds = append(newPost.FileIds, fileInfo.Id) - post.Props["captions"] = []map[string]string{{"file_id": fileInfo.Id}} + newPost.AddProp("captions", []any{map[string]any{"file_id": fileInfo.Id}}) } } diff --git a/webapp/src/components/ai_icon.jsx b/webapp/src/components/ai_icon.jsx new file mode 100644 index 00000000..abca38a5 --- /dev/null +++ b/webapp/src/components/ai_icon.jsx @@ -0,0 +1,33 @@ +import React from 'react'; + +import Svg from './svg'; + +const IconAI = () => ( + + + + + + +); + +export default IconAI; diff --git a/webapp/src/components/post_type_transcription.jsx b/webapp/src/components/post_type_transcription.jsx new file mode 100644 index 00000000..9223354c --- /dev/null +++ b/webapp/src/components/post_type_transcription.jsx @@ -0,0 +1,72 @@ +import React from 'react'; +import {FormattedMessage} from 'react-intl'; +import {useSelector} from 'react-redux'; +import IconAI from 'src/components/ai_icon'; +import styled from 'styled-components'; + +const useAIAvailable = () => { + //@ts-ignore plugins state is a thing + return useSelector((state) => Boolean(state.plugins?.plugins?.[aiPluginID])); +}; + +const aiPluginID = 'mattermost-ai'; + +const useCallsPostButtonClicked = () => { + return useSelector((state) => { + //@ts-ignore plugins state is a thing + return state['plugins-' + aiPluginID]?.callsPostButtonClickedTranscription; + }); +}; + +const CreateMeetingSummaryButton = styled.button` + display: flex; + border: none; + height: 24px; + padding: 4px 10px; + margin-top: 8px; + margin-bottom: 8px; + align-items: center; + justify-content: center; + gap: 6px; + border-radius: 4px; + background: rgba(var(--center-channel-color-rgb), 0.08); + color: rgba(var(--center-channel-color-rgb), 0.64); + font-size: 12px; + font-weight: 600; + line-height: 16px; + + &:hover { + background: rgba(var(--center-channel-color-rgb), 0.12); + color: rgba(var(--center-channel-color-rgb), 0.72); + } + + &:active { + background: rgba(var(--button-bg-rgb), 0.08); + color: var(--button-bg); + } +`; + +export const PostTypeTranscription = (props) => { + const aiAvailable = useAIAvailable(); + const callsPostButtonClicked = useCallsPostButtonClicked(); + + const createMeetingSummary = () => { + callsPostButtonClicked?.(props.post); + }; + + const msg = props.post.message; + + return ( +
+ {msg} + {aiAvailable && callsPostButtonClicked && + + + + + } +
+ ); +}; diff --git a/webapp/src/components/svg.jsx b/webapp/src/components/svg.jsx new file mode 100644 index 00000000..8430fb0b --- /dev/null +++ b/webapp/src/components/svg.jsx @@ -0,0 +1,13 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import styled from 'styled-components'; + +// Hat-tip: https://www.pinkdroids.com/blog/svg-react-styled-components/ +const Svg = styled.svg.attrs({ + version: '1.1', + xmlns: 'http://www.w3.org/2000/svg', + xmlnsXlink: 'http://www.w3.org/1999/xlink', +})``; + +export default Svg; From dd47bbf74e60c81b3a0b5f61bfb10129c416b8c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 10 May 2024 15:48:20 +0200 Subject: [PATCH 03/37] Adding chat support --- server/webhook.go | 154 ++++++++++++++---- server/zoom/webhook.go | 1 + .../post_type_zoom/post_type_zoom.jsx | 1 + webapp/src/index.js | 1 + 4 files changed, 123 insertions(+), 34 deletions(-) diff --git a/server/webhook.go b/server/webhook.go index 21ecd6be..60004047 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -171,23 +171,11 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques return } - newPost := &model.Post{ - UserId: p.botUserID, - ChannelId: post.ChannelId, - RootId: post.Id, - Message: "Here's the zoom meeting transcription", - FileIds: []string{}, - Type: "custom_zoom_transcript", - } - p.API.LogError("UPDATING MEETING TRANSCRIPT") for _, recording := range webhook.Payload.Object.RecordingFiles { if recording.RecordingType == zoom.RecordingTypeAudioTranscript { p.API.LogError("MEETING TRANSCRIPT UPDATED") - post.Props["meeting_transcript"] = recording.PlayURL - if webhook.Payload.Object.Password != "" { - post.Props["meeting_password"] = webhook.Payload.Object.Password - } + request, err := http.NewRequest(http.MethodGet, recording.DownloadURL, nil) if err != nil { p.API.LogWarn("Unable to get the transcription", "err", err) @@ -195,12 +183,39 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques return } request.Header.Set("Authorization", "Bearer "+webhook.DownloadToken) - response, err := http.DefaultClient.Do(request) - if err != nil { - p.API.LogWarn("Unable to get the transcription", "err", err) + + retries := 3 + var response *http.Response + for retries > 0 { + var err error + response, err = http.DefaultClient.Do(request) + if err != nil { + p.API.LogWarn("Unable to get the transcription", "err", err) + time.Sleep(1 * time.Second) + retries -= 1 + continue + } + if response.StatusCode != http.StatusOK { + p.API.LogWarn("Unable to get the transcription", "err", "bad status code "+strconv.Itoa(response.StatusCode)) + time.Sleep(1 * time.Second) + retries -= 1 + continue + } + break + } + + if response == nil { + p.API.LogWarn("Unable to get the transcription", "err", "response is nil") http.Error(w, err.Error(), http.StatusBadRequest) return } + + post, appErr := p.API.GetPost(postID) + if appErr != nil { + p.API.LogWarn("Could not get meeting post by id", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } defer response.Body.Close() transcription, err := io.ReadAll(response.Body) if err != nil { @@ -214,8 +229,29 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques http.Error(w, appErr.Error(), http.StatusBadRequest) return } + newPost := &model.Post{ + UserId: p.botUserID, + ChannelId: post.ChannelId, + RootId: post.Id, + Message: "Here's the zoom meeting transcription", + FileIds: []string{}, + Type: "custom_zoom_transcript", + } + newPost.FileIds = append(newPost.FileIds, fileInfo.Id) newPost.AddProp("captions", []any{map[string]any{"file_id": fileInfo.Id}}) + + _, appErr = p.API.CreatePost(newPost) + if appErr != nil { + p.API.LogWarn("Could not update the post", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + post.Props["meeting_transcript"] = recording.PlayURL + if post.Props["meeting_password"] == "" && webhook.Payload.Object.Password != "" { + post.Props["meeting_password"] = webhook.Payload.Object.Password + } } } @@ -226,14 +262,6 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques return } - _, appErr = p.API.CreatePost(newPost) - - if appErr != nil { - p.API.LogWarn("Could not create the transcription post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) - return - } - // TODO: Delete the meeting post if is no longer needed // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) @@ -269,13 +297,78 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request return } - p.API.LogError("UPDATING MEETING RECORDING") + p.API.LogError("UPDATING MEETING RECORDING AND CHAT") for _, recording := range webhook.Payload.Object.RecordingFiles { + if post.Props["meeting_password"] == "" && webhook.Payload.Object.Password != "" { + post.Props["meeting_password"] = webhook.Payload.Object.Password + } + if recording.RecordingType == zoom.RecordingTypeVideo { p.API.LogError("MEETING RECORDING UPDATED") post.Props["meeting_recording"] = recording.PlayURL - if webhook.Payload.Object.Password != "" { - post.Props["meeting_password"] = webhook.Payload.Object.Password + _, appErr = p.API.CreatePost(&model.Post{ + UserId: p.botUserID, + ChannelId: post.ChannelId, + RootId: post.Id, + Message: "Here's the zoom meeting recording:\n**Link:** [Meeting Recording](" + recording.PlayURL + ")\n**Password:** " + webhook.Payload.Object.Password, + }) + if appErr != nil { + p.API.LogWarn("Could not update the post", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + } + + if recording.RecordingType == zoom.RecordingTypeChat { + p.API.LogError("MEETING CHAT UPDATED") + post.Props["meeting_chat"] = recording.PlayURL + request, err := http.NewRequest(http.MethodGet, recording.DownloadURL, nil) + if err != nil { + p.API.LogWarn("Unable to get the chat", "err", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + request.Header.Set("Authorization", "Bearer "+webhook.DownloadToken) + response, err := http.DefaultClient.Do(request) + if err != nil { + p.API.LogWarn("Unable to get the chat", "err", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + defer response.Body.Close() + chat, err := io.ReadAll(response.Body) + if err != nil { + p.API.LogWarn("Unable to get the chat", "err", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + fileInfo, appErr := p.API.UploadFile(chat, post.ChannelId, "chat.txt") + if appErr != nil { + p.API.LogWarn("Unable to get the chat", "err", appErr) + http.Error(w, appErr.Error(), http.StatusBadRequest) + return + } + + newPost := &model.Post{ + UserId: p.botUserID, + ChannelId: post.ChannelId, + RootId: post.Id, + Message: "Here's the zoom meeting chat history", + FileIds: []string{}, + Type: "custom_zoom_chat", + } + + newPost.FileIds = append(newPost.FileIds, fileInfo.Id) + newPost.AddProp("captions", []any{map[string]any{"file_id": fileInfo.Id}}) + + p.API.LogError("SENDING THE NEW POST FOR THE CHAT HISTORY") + + _, appErr = p.API.CreatePost(newPost) + if appErr != nil { + p.API.LogWarn("Could not update the post", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return } } } @@ -287,13 +380,6 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request return } - _, appErr = p.API.CreatePost(&model.Post{ - UserId: p.botUserID, - ChannelId: post.ChannelId, - RootId: post.Id, - Message: "Here's the zoom meeting recording:\n**Link:** [Meeting Recording](" + post.Props["meeting_recording"].(string) + ")\n**Password:** " + post.Props["meeting_password"].(string), - }) - // TODO: Delete the meeting post if is no longer needed // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) diff --git a/server/zoom/webhook.go b/server/zoom/webhook.go index 1b70d1b7..95541d96 100644 --- a/server/zoom/webhook.go +++ b/server/zoom/webhook.go @@ -22,6 +22,7 @@ const ( EventTypeValidateWebhook EventType = "endpoint.url_validation" RecordingTypeAudioTranscript = "audio_transcript" + RecordingTypeChat = "chat_file" RecordingTypeVideo = "shared_screen_with_speaker_view" ) diff --git a/webapp/src/components/post_type_zoom/post_type_zoom.jsx b/webapp/src/components/post_type_zoom/post_type_zoom.jsx index a418ed3b..4b53a69c 100644 --- a/webapp/src/components/post_type_zoom/post_type_zoom.jsx +++ b/webapp/src/components/post_type_zoom/post_type_zoom.jsx @@ -164,6 +164,7 @@ export default class PostTypeZoom extends React.PureComponent { {'Meeting Length: ' + length + ' minute(s)'} {props.meeting_recording && (
{'View Meeting Recording'}
)} {props.meeting_transcript && (
{'View Meeting Transcript'}
)} + {props.meeting_chat && (
{'View Meeting Chat History'}
)} {props.meeting_password && (
{'Meeting Password: ' + props.meeting_password}
)} ); diff --git a/webapp/src/index.js b/webapp/src/index.js index e93a610b..cab935c3 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -52,6 +52,7 @@ class Plugin { registry.registerPostTypeComponent('custom_zoom', PostTypeZoom); registry.registerPostTypeComponent('custom_zoom_transcript', PostTypeTranscription); + registry.registerPostTypeComponent('custom_zoom_chat', PostTypeTranscription); Client.setServerRoute(getServerRoute(store.getState())); } } From 12815afeb05e09cbf6c849adeceab19c21e7736e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 10 May 2024 18:27:50 +0200 Subject: [PATCH 04/37] WIP --- server/webhook.go | 222 +++++++----------- server/zoom/webhook.go | 54 +++-- webapp/src/components/post_type_chat.jsx | 81 +++++++ .../post_type_zoom/post_type_zoom.jsx | 4 - webapp/src/index.js | 3 +- 5 files changed, 200 insertions(+), 164 deletions(-) create mode 100644 webapp/src/components/post_type_chat.jsx diff --git a/server/webhook.go b/server/webhook.go index 60004047..bd3120dc 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -141,6 +141,71 @@ func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body } } +func (p *Plugin) handleTranscript(recording zoom.RecordingFile, postID, channelID, downloadToken string) error { + request, err := http.NewRequest(http.MethodGet, recording.DownloadURL, nil) + if err != nil { + p.API.LogWarn("Unable to get the transcription", "err", err) + return err + } + request.Header.Set("Authorization", "Bearer "+downloadToken) + + retries := 5 + var response *http.Response + for retries > 0 { + var err error + response, err = http.DefaultClient.Do(request) + if err != nil { + p.API.LogWarn("Unable to get the transcription", "err", err) + time.Sleep(1 * time.Second) + retries -= 1 + continue + } + if response.StatusCode != http.StatusOK { + p.API.LogWarn("Unable to get the transcription", "err", "bad status code "+strconv.Itoa(response.StatusCode)) + time.Sleep(1 * time.Second) + retries -= 1 + continue + } + break + } + + if response == nil { + p.API.LogWarn("Unable to get the transcription", "err", "response is nil") + return err + } + + defer response.Body.Close() + transcription, err := io.ReadAll(response.Body) + if err != nil { + p.API.LogWarn("Unable to get the transcription", "err", err) + return err + } + fileInfo, appErr := p.API.UploadFile(transcription, channelID, "transcription.txt") + if appErr != nil { + p.API.LogWarn("Unable to get the transcription", "err", appErr) + return appErr + } + newPost := &model.Post{ + UserId: p.botUserID, + ChannelId: channelID, + RootId: postID, + Message: "Here's the zoom meeting transcription", + FileIds: []string{}, + Type: "custom_zoom_transcript", + } + + newPost.FileIds = append(newPost.FileIds, fileInfo.Id) + newPost.AddProp("captions", []any{map[string]any{"file_id": fileInfo.Id}}) + + _, appErr = p.API.CreatePost(newPost) + if appErr != nil { + p.API.LogWarn("Could not update the post", "err", appErr) + return appErr + } + + return nil +} + func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Request, body []byte) { p.API.LogError("RUNNING THE UPDATE MEETING TRANSCRIPT") var webhook zoom.RecordingWebhook @@ -164,104 +229,18 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques return } - _, appErr = p.API.UpdatePost(post) - if appErr != nil { - p.API.LogWarn("Could not update the post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) - return - } - p.API.LogError("UPDATING MEETING TRANSCRIPT") for _, recording := range webhook.Payload.Object.RecordingFiles { if recording.RecordingType == zoom.RecordingTypeAudioTranscript { p.API.LogError("MEETING TRANSCRIPT UPDATED") - - request, err := http.NewRequest(http.MethodGet, recording.DownloadURL, nil) + err := p.handleTranscript(recording, post.Id, post.ChannelId, webhook.DownloadToken) if err != nil { - p.API.LogWarn("Unable to get the transcription", "err", err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - request.Header.Set("Authorization", "Bearer "+webhook.DownloadToken) - - retries := 3 - var response *http.Response - for retries > 0 { - var err error - response, err = http.DefaultClient.Do(request) - if err != nil { - p.API.LogWarn("Unable to get the transcription", "err", err) - time.Sleep(1 * time.Second) - retries -= 1 - continue - } - if response.StatusCode != http.StatusOK { - p.API.LogWarn("Unable to get the transcription", "err", "bad status code "+strconv.Itoa(response.StatusCode)) - time.Sleep(1 * time.Second) - retries -= 1 - continue - } - break - } - - if response == nil { - p.API.LogWarn("Unable to get the transcription", "err", "response is nil") - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - post, appErr := p.API.GetPost(postID) - if appErr != nil { - p.API.LogWarn("Could not get meeting post by id", "err", appErr) http.Error(w, appErr.Error(), appErr.StatusCode) - return - } - defer response.Body.Close() - transcription, err := io.ReadAll(response.Body) - if err != nil { - p.API.LogWarn("Unable to get the transcription", "err", err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - fileInfo, appErr := p.API.UploadFile(transcription, post.ChannelId, "transcription.txt") - if appErr != nil { - p.API.LogWarn("Unable to get the transcription", "err", appErr) - http.Error(w, appErr.Error(), http.StatusBadRequest) - return - } - newPost := &model.Post{ - UserId: p.botUserID, - ChannelId: post.ChannelId, - RootId: post.Id, - Message: "Here's the zoom meeting transcription", - FileIds: []string{}, - Type: "custom_zoom_transcript", - } - - newPost.FileIds = append(newPost.FileIds, fileInfo.Id) - newPost.AddProp("captions", []any{map[string]any{"file_id": fileInfo.Id}}) - - _, appErr = p.API.CreatePost(newPost) - if appErr != nil { - p.API.LogWarn("Could not update the post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) - return - } - - post.Props["meeting_transcript"] = recording.PlayURL - if post.Props["meeting_password"] == "" && webhook.Payload.Object.Password != "" { - post.Props["meeting_password"] = webhook.Payload.Object.Password + continue } } } - _, appErr = p.API.UpdatePost(post) - if appErr != nil { - p.API.LogWarn("Could not update the post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) - return - } - // TODO: Delete the meeting post if is no longer needed // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) @@ -298,31 +277,17 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request } p.API.LogError("UPDATING MEETING RECORDING AND CHAT") + newPost := &model.Post{ + UserId: p.botUserID, + ChannelId: post.ChannelId, + RootId: post.Id, + Message: "", + FileIds: []string{}, + } for _, recording := range webhook.Payload.Object.RecordingFiles { - if post.Props["meeting_password"] == "" && webhook.Payload.Object.Password != "" { - post.Props["meeting_password"] = webhook.Payload.Object.Password - } - - if recording.RecordingType == zoom.RecordingTypeVideo { - p.API.LogError("MEETING RECORDING UPDATED") - post.Props["meeting_recording"] = recording.PlayURL - _, appErr = p.API.CreatePost(&model.Post{ - UserId: p.botUserID, - ChannelId: post.ChannelId, - RootId: post.Id, - Message: "Here's the zoom meeting recording:\n**Link:** [Meeting Recording](" + recording.PlayURL + ")\n**Password:** " + webhook.Payload.Object.Password, - }) - if appErr != nil { - p.API.LogWarn("Could not update the post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) - return - } - - } - + p.API.LogError("RECORDING COMPLETE RECORDING", "recording", recording) if recording.RecordingType == zoom.RecordingTypeChat { p.API.LogError("MEETING CHAT UPDATED") - post.Props["meeting_chat"] = recording.PlayURL request, err := http.NewRequest(http.MethodGet, recording.DownloadURL, nil) if err != nil { p.API.LogWarn("Unable to get the chat", "err", err) @@ -350,36 +315,27 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request return } - newPost := &model.Post{ - UserId: p.botUserID, - ChannelId: post.ChannelId, - RootId: post.Id, - Message: "Here's the zoom meeting chat history", - FileIds: []string{}, - Type: "custom_zoom_chat", - } - newPost.FileIds = append(newPost.FileIds, fileInfo.Id) newPost.AddProp("captions", []any{map[string]any{"file_id": fileInfo.Id}}) - - p.API.LogError("SENDING THE NEW POST FOR THE CHAT HISTORY") - - _, appErr = p.API.CreatePost(newPost) - if appErr != nil { - p.API.LogWarn("Could not update the post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) - return + newPost.Type = "custom_zoom_chat" + if newPost.Message == "" { + newPost.Message = " " } } - } - _, appErr = p.API.UpdatePost(post) - if appErr != nil { - p.API.LogWarn("Could not update the post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) - return + if recording.RecordingType == zoom.RecordingTypeVideo { + newPost.Message = "Here's the zoom meeting recording:\n**Link:** [Meeting Recording](" + recording.PlayURL + ")\n**Password:** " + webhook.Payload.Object.Password + } } + if newPost.Message != "" { + _, appErr = p.API.CreatePost(newPost) + if appErr != nil { + p.API.LogWarn("Could not update the post", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + } // TODO: Delete the meeting post if is no longer needed // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) diff --git a/server/zoom/webhook.go b/server/zoom/webhook.go index 95541d96..cd43ee71 100644 --- a/server/zoom/webhook.go +++ b/server/zoom/webhook.go @@ -79,33 +79,35 @@ type RecordingWebhookPayload struct { Object RecordingWebhookObject `json:"object"` } +type RecordingFile struct { + ID string `json:"id"` + MeetingID string `json:"meeting_id"` + RecordingStart time.Time `json:"recording_start"` + RecordingEnd time.Time `json:"recording_end"` + FileType string `json:"file_type"` + FileSize int `json:"file_size"` + FilePath string `json:"file_path"` + Status string `json:"status"` + DownloadURL string `json:"download_url"` + PlayURL string `json:"play_url"` + RecordingType string `json:"recording_type"` +} + type RecordingWebhookObject struct { - UUID string `json:"uuid"` - MeetingNumber int `json:"meeting_number"` - ID int `json:"id"` - AccountID string `json:"account_id"` - HostID string `json:"host_id"` - Topic string `json:"topic"` - StartTime time.Time `json:"start_time"` - Timezone string `json:"timezone"` - HostEmail string `json:"host_email"` - Duration int `json:"duration"` - TotalSize int `json:"total_size"` - RecordingCount int `json:"recording_count"` - Password string `json:"password"` - RecordingFiles []struct { - ID string `json:"id"` - MeetingID string `json:"meeting_id"` - RecordingStart time.Time `json:"recording_start"` - RecordingEnd time.Time `json:"recording_end"` - FileType string `json:"file_type"` - FileSize int `json:"file_size"` - FilePath string `json:"file_path"` - Status string `json:"status"` - DownloadURL string `json:"download_url"` - PlayURL string `json:"play_url"` - RecordingType string `json:"recording_type"` - } `json:"recording_files"` + UUID string `json:"uuid"` + MeetingNumber int `json:"meeting_number"` + ID int `json:"id"` + AccountID string `json:"account_id"` + HostID string `json:"host_id"` + Topic string `json:"topic"` + StartTime time.Time `json:"start_time"` + Timezone string `json:"timezone"` + HostEmail string `json:"host_email"` + Duration int `json:"duration"` + TotalSize int `json:"total_size"` + RecordingCount int `json:"recording_count"` + Password string `json:"password"` + RecordingFiles []RecordingFile `json:"recording_files"` } type DeauthorizationEvent struct { diff --git a/webapp/src/components/post_type_chat.jsx b/webapp/src/components/post_type_chat.jsx new file mode 100644 index 00000000..e616ff7f --- /dev/null +++ b/webapp/src/components/post_type_chat.jsx @@ -0,0 +1,81 @@ +import React from 'react'; +import {FormattedMessage} from 'react-intl'; +import {useSelector} from 'react-redux'; +import IconAI from 'src/components/ai_icon'; +import styled from 'styled-components'; + +const useAIAvailable = () => { + //@ts-ignore plugins state is a thing + return useSelector((state) => Boolean(state.plugins?.plugins?.[aiPluginID])); +}; + +const aiPluginID = 'mattermost-ai'; + +const useCallsPostButtonClicked = () => { + return useSelector((state) => { + //@ts-ignore plugins state is a thing + return state['plugins-' + aiPluginID]?.callsPostButtonClickedTranscription; + }); +}; + +const CreateMeetingSummaryButton = styled.button` + display: flex; + border: none; + height: 24px; + padding: 4px 10px; + margin-top: 8px; + margin-bottom: 8px; + align-items: center; + justify-content: center; + gap: 6px; + border-radius: 4px; + background: rgba(var(--center-channel-color-rgb), 0.08); + color: rgba(var(--center-channel-color-rgb), 0.64); + font-size: 12px; + font-weight: 600; + line-height: 16px; + + &:hover { + background: rgba(var(--center-channel-color-rgb), 0.12); + color: rgba(var(--center-channel-color-rgb), 0.72); + } + + &:active { + background: rgba(var(--button-bg-rgb), 0.08); + color: var(--button-bg); + } +`; + +export const PostTypeChat = (props) => { + const aiAvailable = useAIAvailable(); + const callsPostButtonClicked = useCallsPostButtonClicked(); + + const createMeetingSummary = () => { + callsPostButtonClicked?.(props.post); + }; + + const msg = props.post.message; + + const renderPostWithMarkdown = (msg) => { + const {formatText, messageHtmlToComponent} = window.PostUtils; + + return messageHtmlToComponent( + formatText(msg, {}), + false, + ); + } + + return ( +
+ {renderPostWithMarkdown(msg)} + {aiAvailable && callsPostButtonClicked && + + + + + } +
+ ); +}; diff --git a/webapp/src/components/post_type_zoom/post_type_zoom.jsx b/webapp/src/components/post_type_zoom/post_type_zoom.jsx index 4b53a69c..4850f205 100644 --- a/webapp/src/components/post_type_zoom/post_type_zoom.jsx +++ b/webapp/src/components/post_type_zoom/post_type_zoom.jsx @@ -162,10 +162,6 @@ export default class PostTypeZoom extends React.PureComponent { {'Date: ' + start}
{'Meeting Length: ' + length + ' minute(s)'} - {props.meeting_recording && (
{'View Meeting Recording'}
)} - {props.meeting_transcript && (
{'View Meeting Transcript'}
)} - {props.meeting_chat && (
{'View Meeting Chat History'}
)} - {props.meeting_password && (
{'Meeting Password: ' + props.meeting_password}
)} ); } else if (props.meeting_status === 'RECENTLY_CREATED') { diff --git a/webapp/src/index.js b/webapp/src/index.js index cab935c3..33d610ef 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -8,6 +8,7 @@ import manifest from './manifest'; import ChannelHeaderIcon from './components/channel-header-icon'; import PostTypeZoom from './components/post_type_zoom'; import {PostTypeTranscription} from './components/post_type_transcription'; +import {PostTypeChat} from './components/post_type_chat'; import {startMeeting} from './actions'; import Client from './client'; import {getPluginURL, getServerRoute} from './selectors'; @@ -52,7 +53,7 @@ class Plugin { registry.registerPostTypeComponent('custom_zoom', PostTypeZoom); registry.registerPostTypeComponent('custom_zoom_transcript', PostTypeTranscription); - registry.registerPostTypeComponent('custom_zoom_chat', PostTypeTranscription); + registry.registerPostTypeComponent('custom_zoom_chat', PostTypeChat); Client.setServerRoute(getServerRoute(store.getState())); } } From 161b66044d8947b00e2c930b1d517ad605723182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Wed, 15 May 2024 19:51:18 +0200 Subject: [PATCH 05/37] Adding support for subscription of meetings to channels --- server/command.go | 60 ++++++++++++--- server/http.go | 43 +++++++++-- server/store.go | 36 ++++++++- server/webhook.go | 190 ++++++++++++++++++++++++++++++---------------- 4 files changed, 244 insertions(+), 85 deletions(-) diff --git a/server/command.go b/server/command.go index 2d6cdd60..3b331dc6 100644 --- a/server/command.go +++ b/server/command.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "strconv" "strings" "github.com/mattermost/mattermost-plugin-zoom/server/zoom" @@ -25,11 +26,13 @@ const ( ) const ( - actionConnect = "connect" - actionStart = "start" - actionDisconnect = "disconnect" - actionHelp = "help" - settings = "settings" + actionConnect = "connect" + actionSubscribe = "subscribe" + actionUnsubscribe = "unsubscribe" + actionStart = "start" + actionDisconnect = "disconnect" + actionHelp = "help" + settings = "settings" ) func (p *Plugin) getCommand() (*model.Command, error) { @@ -64,7 +67,7 @@ func (p *Plugin) postCommandResponse(args *model.CommandArgs, text string) { _ = p.API.SendEphemeralPost(args.UserId, post) } -func (p *Plugin) parseCommand(rawCommand string) (cmd, action, topic string) { +func (p *Plugin) parseCommand(rawCommand string) (cmd, action, topic string, meetingID int) { split := strings.Fields(rawCommand) cmd = split[0] if len(split) > 1 { @@ -73,11 +76,14 @@ func (p *Plugin) parseCommand(rawCommand string) (cmd, action, topic string) { if action == actionStart { topic = strings.Join(split[2:], " ") } - return cmd, action, topic + if len(split) > 2 && (action == actionSubscribe || action == actionUnsubscribe) { + meetingID, _ = strconv.Atoi(split[2]) + } + return cmd, action, topic, meetingID } func (p *Plugin) executeCommand(c *plugin.Context, args *model.CommandArgs) (string, error) { - command, action, topic := p.parseCommand(args.Command) + command, action, topic, meetingID := p.parseCommand(args.Command) if command != "/zoom" { return fmt.Sprintf("Command '%s' is not /zoom. Please try again.", command), nil @@ -96,6 +102,10 @@ func (p *Plugin) executeCommand(c *plugin.Context, args *model.CommandArgs) (str switch action { case actionConnect: return p.runConnectCommand(user, args) + case actionSubscribe: + return p.runSubscribeCommand(user, args, meetingID) + case actionUnsubscribe: + return p.runUnsubscribeCommand(user, args, meetingID) case actionStart: return p.runStartCommand(args, user, topic) case actionDisconnect: @@ -180,7 +190,12 @@ func (p *Plugin) runStartCommand(args *model.CommandArgs, user *model.User, topi } } - if postMeetingErr := p.postMeeting(user, meetingID, args.ChannelId, args.RootId, topic); postMeetingErr != nil { + meeting, err := p.getMeeting(user, meetingID) + if err != nil { + return "", errors.Wrap(err, "failed to get the meeting") + } + + if postMeetingErr := p.postMeeting(user, meetingID, meeting.UUID, args.ChannelId, args.RootId, topic); postMeetingErr != nil { return "", postMeetingErr } @@ -225,6 +240,23 @@ func (p *Plugin) runConnectCommand(user *model.User, extra *model.CommandArgs) ( return oauthMsg, nil } +func (p *Plugin) runSubscribeCommand(user *model.User, extra *model.CommandArgs, meetingID int) (string, error) { + if appErr := p.storeChannelForMeeting(meetingID, extra.ChannelId); appErr != nil { + return "", errors.Wrap(appErr, "cannot subscribing to meeting") + } + return "Channel subscribed to meeting", nil +} + +func (p *Plugin) runUnsubscribeCommand(user *model.User, extra *model.CommandArgs, meetingID int) (string, error) { + if channelID, appErr := p.fetchChannelForMeeting(meetingID); appErr != nil || channelID == "" { + return "Can not unsubscribe from meeting: meeting not found", errors.New("meeting not found") + } + if appErr := p.deleteChannelForMeeting(meetingID); appErr != nil { + return "Can not unsubscribe from meeting: unable to delete the meeting subscription", errors.Wrap(appErr, "cannot unsubscribing from meeting") + } + return "Channel unsubscribed from meeting", nil +} + // runDisconnectCommand runs command to disconnect from Zoom. Will fail if user cannot connect. func (p *Plugin) runDisconnectCommand(user *model.User) (string, error) { if !p.canConnect(user) { @@ -285,9 +317,9 @@ func (p *Plugin) updateUserPersonalSettings(usePMIValue, userID string) *model.A func (p *Plugin) getAutocompleteData() *model.AutocompleteData { canConnect := !p.configuration.AccountLevelApp - available := "start, help, settings" + available := "start, help, settings, subscribe, unsubscribe" if canConnect { - available = "start, connect, disconnect, help, settings" + available = "start, connect, disconnect, help, settings, subscribe, unsubscribe" } zoom := model.NewAutocompleteData("zoom", "[command]", fmt.Sprintf("Available commands: %s", available)) @@ -306,6 +338,12 @@ func (p *Plugin) getAutocompleteData() *model.AutocompleteData { setting := model.NewAutocompleteData("settings", "", "Update your meeting ID preferences") zoom.AddCommand(setting) + subscribe := model.NewAutocompleteData("subscribe", "[meeting id]", "Subscribe this channel to a Zoom meeting") + zoom.AddCommand(subscribe) + + unsubscribe := model.NewAutocompleteData("unsubscribe", "[meeting id]", "Unsubscribe this channel from a Zoom meeting") + zoom.AddCommand(unsubscribe) + help := model.NewAutocompleteData("help", "", "Display usage") zoom.AddCommand(help) diff --git a/server/http.go b/server/http.go index bc4bd35f..56d17820 100644 --- a/server/http.go +++ b/server/http.go @@ -180,7 +180,13 @@ func (p *Plugin) startMeeting(action, userID, channelID, rootID string) { } } - if postMeetingErr := p.postMeeting(user, meetingID, channelID, rootID, defaultMeetingTopic); postMeetingErr != nil { + meeting, err := p.getMeeting(user, meetingID) + if err != nil { + p.API.LogWarn("failed to get the meeting", "Error", err.Error()) + return + } + + if postMeetingErr := p.postMeeting(user, meetingID, meeting.UUID, channelID, rootID, defaultMeetingTopic); postMeetingErr != nil { p.API.LogWarn("failed to post the meeting", "Error", postMeetingErr.Error()) return } @@ -365,7 +371,8 @@ func (p *Plugin) completeUserOAuthToZoom(w http.ResponseWriter, r *http.Request) } meetingID := meeting.ID - if err = p.postMeeting(user, meetingID, channelID, "", ""); err != nil { + meetingUUID := meeting.UUID + if err = p.postMeeting(user, meetingID, meetingUUID, channelID, "", ""); err != nil { p.API.LogWarn("Failed to post the meeting", "error", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -392,14 +399,14 @@ func (p *Plugin) completeUserOAuthToZoom(w http.ResponseWriter, r *http.Request) } } -func (p *Plugin) postMeeting(creator *model.User, meetingID int, channelID string, rootID string, topic string) error { +func (p *Plugin) postMeeting(creator *model.User, meetingID int, meetingUUID string, channelID string, rootID string, topic string) error { meetingURL := p.getMeetingURL(creator, meetingID) if topic == "" { topic = defaultMeetingTopic } - if !p.API.HasPermissionToChannel(creator.Id, channelID, model.PermissionCreatePost) { + if p.botUserID != creator.Id && !p.API.HasPermissionToChannel(creator.Id, channelID, model.PermissionCreatePost) { return errors.New("this channel is not accessible, you might not have permissions to write in this channel. Contact the administrator of this channel to find out if you have access permissions") } @@ -418,6 +425,7 @@ func (p *Plugin) postMeeting(creator *model.User, meetingID int, channelID strin Props: map[string]interface{}{ "attachments": []*model.SlackAttachment{&slackAttachment}, "meeting_id": meetingID, + "meeting_uuid": meetingUUID, "meeting_link": meetingURL, "meeting_status": zoom.WebhookStatusStarted, "meeting_personal": false, @@ -432,7 +440,8 @@ func (p *Plugin) postMeeting(creator *model.User, meetingID int, channelID strin return appErr } - if appErr = p.storeMeetingPostID(meetingID, createdPost.Id); appErr != nil { + p.API.LogWarn("MEETING UUID ID", "uuid", meetingUUID) + if appErr = p.storeMeetingPostID(meetingUUID, createdPost.Id); appErr != nil { p.API.LogDebug("failed to store post id", "error", appErr) } @@ -621,7 +630,14 @@ func (p *Plugin) handleStartMeeting(w http.ResponseWriter, r *http.Request) { } } - if err = p.postMeeting(user, meetingID, req.ChannelID, req.RootID, topic); err != nil { + meeting, err := p.getMeeting(user, meetingID) + if err != nil { + p.API.LogWarn("failed to get the meeting", "Error", err.Error()) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if err = p.postMeeting(user, meetingID, meeting.UUID, req.ChannelID, req.RootID, topic); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -655,6 +671,21 @@ func (p *Plugin) createMeetingWithoutPMI(user *model.User, zoomUser *zoom.User, return meeting.ID, nil } +func (p *Plugin) getMeeting(user *model.User, meetingID int) (*zoom.Meeting, error) { + client, _, err := p.getActiveClient(user) + if err != nil { + p.API.LogWarn("could not get the active zoom client", "error", err.Error()) + return nil, err + } + + meeting, err := client.GetMeeting(meetingID) + if err != nil { + p.API.LogDebug("failed to get meeting") + return nil, err + } + return meeting, nil +} + func (p *Plugin) getMeetingURL(user *model.User, meetingID int) string { defaultURL := fmt.Sprintf("%s/j/%v", p.getZoomURL(), meetingID) client, _, err := p.getActiveClient(user) diff --git a/server/store.go b/server/store.go index f06b8ed1..aeb09361 100644 --- a/server/store.go +++ b/server/store.go @@ -16,6 +16,7 @@ import ( const ( postMeetingKey = "post_meeting_" + meetingChannelKey = "meeting_channel_" zoomStateKeyPrefix = "zoomuserstate" zoomUserByMMID = "zoomtoken_" zoomUserByZoomID = "zoomtokenbyzoomid_" @@ -134,14 +135,14 @@ func (p *Plugin) deleteUserState(userID string) *model.AppError { return p.API.KVDelete(key) } -func (p *Plugin) storeMeetingPostID(meetingID int, postID string) *model.AppError { - key := fmt.Sprintf("%v%v", postMeetingKey, meetingID) +func (p *Plugin) storeMeetingPostID(meetingUUID string, postID string) *model.AppError { + key := fmt.Sprintf("%v%v", postMeetingKey, meetingUUID) bytes := []byte(postID) return p.API.KVSetWithExpiry(key, bytes, meetingPostIDTTL) } -func (p *Plugin) fetchMeetingPostID(meetingID string) (string, *model.AppError) { - key := fmt.Sprintf("%v%v", postMeetingKey, meetingID) +func (p *Plugin) fetchMeetingPostID(meetingUUID string) (string, *model.AppError) { + key := fmt.Sprintf("%v%v", postMeetingKey, meetingUUID) postID, appErr := p.API.KVGet(key) if appErr != nil { p.API.LogDebug("Could not get meeting post from KVStore", "error", appErr.Error()) @@ -161,6 +162,33 @@ func (p *Plugin) deleteMeetingPostID(postID string) *model.AppError { return p.API.KVDelete(key) } +func (p *Plugin) storeChannelForMeeting(meetingID int, channelID string) *model.AppError { + key := fmt.Sprintf("%v%v", meetingChannelKey, meetingID) + bytes := []byte(channelID) + return p.API.KVSet(key, bytes) +} + +func (p *Plugin) fetchChannelForMeeting(meetingID int) (string, *model.AppError) { + key := fmt.Sprintf("%v%v", meetingChannelKey, meetingID) + channelID, appErr := p.API.KVGet(key) + if appErr != nil { + p.API.LogDebug("Could not get channel meeting from KVStore", "error", appErr.Error()) + return "", appErr + } + + if channelID == nil { + p.API.LogWarn("Stored channel meeting not found") + return "", appErr + } + + return string(channelID), nil +} + +func (p *Plugin) deleteChannelForMeeting(meetingID int) *model.AppError { + key := fmt.Sprintf("%v%v", meetingChannelKey, meetingID) + return p.API.KVDelete(key) +} + // getOAuthUserStateKey generates and returns the key for storing the OAuth user state in the KV store. func getOAuthUserStateKey(userID string) string { return fmt.Sprintf("%s_%s", zoomStateKeyPrefix, userID) diff --git a/server/webhook.go b/server/webhook.go index bd3120dc..cc718202 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -59,6 +59,8 @@ func (p *Plugin) handleWebhook(w http.ResponseWriter, r *http.Request) { p.API.LogWarn("New event received", "even_type", webhook.Event, "payload", string(b)) switch webhook.Event { + case zoom.EventTypeMeetingStarted: + p.handleMeetingStarted(w, r, b) case zoom.EventTypeMeetingEnded: p.handleMeetingEnded(w, r, b) case zoom.EventTypeValidateWebhook: @@ -72,6 +74,54 @@ func (p *Plugin) handleWebhook(w http.ResponseWriter, r *http.Request) { } } +func (p *Plugin) handleMeetingStarted(w http.ResponseWriter, r *http.Request, body []byte) { + var webhook zoom.MeetingWebhook + if err := json.Unmarshal(body, &webhook); err != nil { + p.API.LogError("Error unmarshaling meeting webhook", "err", err.Error()) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + meetingID, err := strconv.Atoi(webhook.Payload.Object.ID) + if err != nil { + p.API.LogError("Failed to get meeting ID", "err", err.Error()) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + channelID, appErr := p.fetchChannelForMeeting(meetingID) + if appErr != nil { + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } + + if channelID == "" { + return + } + + p.API.LogError("RUNNING THIS ON CHANNEL", "channel", channelID) + + botUser, appErr := p.API.GetUser(p.botUserID) + if appErr != nil { + p.API.LogError("Failed to get bot user", "err", appErr.Error()) + http.Error(w, appErr.Error(), http.StatusBadRequest) + return + } + + p.API.LogError("POSTING MEETING TO CHANNEL", "channel", channelID, "meetingID", meetingID) + + if postMeetingErr := p.postMeeting(botUser, meetingID, webhook.Payload.Object.UUID, channelID, "", webhook.Payload.Object.ID); postMeetingErr != nil { + p.API.LogError("Failed to post the zoom message in the channel", "err", postMeetingErr.Error()) + http.Error(w, postMeetingErr.Error(), http.StatusBadRequest) + return + } + + p.API.LogError("POSTED MEETING TO CHANNEL", "channel", channelID, "meetingID", meetingID) + + p.trackMeetingStart(p.botUserID, telemetryStartSourceCommand) + p.trackMeetingType(p.botUserID, false) +} + func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body []byte) { var webhook zoom.MeetingWebhook if err := json.Unmarshal(body, &webhook); err != nil { @@ -80,7 +130,8 @@ func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body return } - meetingPostID := webhook.Payload.Object.ID + meetingPostID := webhook.Payload.Object.UUID + p.API.LogWarn("MEETING ID", "uuid", meetingPostID) postID, appErr := p.fetchMeetingPostID(meetingPostID) if appErr != nil { http.Error(w, appErr.Error(), appErr.StatusCode) @@ -207,7 +258,6 @@ func (p *Plugin) handleTranscript(recording zoom.RecordingFile, postID, channelI } func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Request, body []byte) { - p.API.LogError("RUNNING THE UPDATE MEETING TRANSCRIPT") var webhook zoom.RecordingWebhook if err := json.Unmarshal(body, &webhook); err != nil { p.API.LogError("Error unmarshaling meeting webhook", "err", err.Error()) @@ -215,8 +265,8 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques return } - meetingPostID := webhook.Payload.Object.ID - postID, appErr := p.fetchMeetingPostID(strconv.Itoa(meetingPostID)) + meetingPostID := webhook.Payload.Object.UUID + postID, appErr := p.fetchMeetingPostID(meetingPostID) if appErr != nil { http.Error(w, appErr.Error(), appErr.StatusCode) return @@ -229,15 +279,18 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques return } - p.API.LogError("UPDATING MEETING TRANSCRIPT") + var lastTranscription *zoom.RecordingFile for _, recording := range webhook.Payload.Object.RecordingFiles { if recording.RecordingType == zoom.RecordingTypeAudioTranscript { - p.API.LogError("MEETING TRANSCRIPT UPDATED") - err := p.handleTranscript(recording, post.Id, post.ChannelId, webhook.DownloadToken) - if err != nil { - http.Error(w, appErr.Error(), appErr.StatusCode) - continue - } + lastTranscription = &recording + } + } + + if lastTranscription != nil { + err := p.handleTranscript(*lastTranscription, post.Id, post.ChannelId, webhook.DownloadToken) + if err != nil { + http.Error(w, appErr.Error(), appErr.StatusCode) + return } } @@ -254,7 +307,6 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques } func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request, body []byte) { - p.API.LogError("RUNNING THE UPDATE MEETING RECORDING") var webhook zoom.RecordingWebhook if err := json.Unmarshal(body, &webhook); err != nil { p.API.LogError("Error unmarshaling meeting webhook", "err", err.Error()) @@ -262,8 +314,8 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request return } - meetingPostID := webhook.Payload.Object.ID - postID, appErr := p.fetchMeetingPostID(strconv.Itoa(meetingPostID)) + meetingPostID := webhook.Payload.Object.UUID + postID, appErr := p.fetchMeetingPostID(meetingPostID) if appErr != nil { http.Error(w, appErr.Error(), appErr.StatusCode) return @@ -276,66 +328,76 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request return } - p.API.LogError("UPDATING MEETING RECORDING AND CHAT") - newPost := &model.Post{ - UserId: p.botUserID, - ChannelId: post.ChannelId, - RootId: post.Id, - Message: "", - FileIds: []string{}, - } + recordings := make(map[time.Time][]zoom.RecordingFile) + for _, recording := range webhook.Payload.Object.RecordingFiles { - p.API.LogError("RECORDING COMPLETE RECORDING", "recording", recording) if recording.RecordingType == zoom.RecordingTypeChat { - p.API.LogError("MEETING CHAT UPDATED") - request, err := http.NewRequest(http.MethodGet, recording.DownloadURL, nil) - if err != nil { - p.API.LogWarn("Unable to get the chat", "err", err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - request.Header.Set("Authorization", "Bearer "+webhook.DownloadToken) - response, err := http.DefaultClient.Do(request) - if err != nil { - p.API.LogWarn("Unable to get the chat", "err", err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - defer response.Body.Close() - chat, err := io.ReadAll(response.Body) - if err != nil { - p.API.LogWarn("Unable to get the chat", "err", err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - fileInfo, appErr := p.API.UploadFile(chat, post.ChannelId, "chat.txt") - if appErr != nil { - p.API.LogWarn("Unable to get the chat", "err", appErr) - http.Error(w, appErr.Error(), http.StatusBadRequest) - return - } - - newPost.FileIds = append(newPost.FileIds, fileInfo.Id) - newPost.AddProp("captions", []any{map[string]any{"file_id": fileInfo.Id}}) - newPost.Type = "custom_zoom_chat" - if newPost.Message == "" { - newPost.Message = " " - } + recordings[recording.RecordingStart] = append(recordings[recording.RecordingStart], recording) } if recording.RecordingType == zoom.RecordingTypeVideo { - newPost.Message = "Here's the zoom meeting recording:\n**Link:** [Meeting Recording](" + recording.PlayURL + ")\n**Password:** " + webhook.Payload.Object.Password + recordings[recording.RecordingStart] = append(recordings[recording.RecordingStart], recording) } } - if newPost.Message != "" { - _, appErr = p.API.CreatePost(newPost) - if appErr != nil { - p.API.LogWarn("Could not update the post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) - return + for _, recordingGroup := range recordings { + newPost := &model.Post{ + UserId: p.botUserID, + ChannelId: post.ChannelId, + RootId: post.Id, + Message: "", + FileIds: []string{}, + } + for _, recording := range recordingGroup { + if recording.RecordingType == zoom.RecordingTypeChat { + request, err := http.NewRequest(http.MethodGet, recording.DownloadURL, nil) + if err != nil { + p.API.LogWarn("Unable to get the chat", "err", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + request.Header.Set("Authorization", "Bearer "+webhook.DownloadToken) + response, err := http.DefaultClient.Do(request) + if err != nil { + p.API.LogWarn("Unable to get the chat", "err", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + defer response.Body.Close() + chat, err := io.ReadAll(response.Body) + if err != nil { + p.API.LogWarn("Unable to get the chat", "err", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + fileInfo, appErr := p.API.UploadFile(chat, post.ChannelId, "Chat-history.txt") + if appErr != nil { + p.API.LogWarn("Unable to get the chat", "err", appErr) + http.Error(w, appErr.Error(), http.StatusBadRequest) + return + } + + newPost.FileIds = append(newPost.FileIds, fileInfo.Id) + newPost.AddProp("captions", []any{map[string]any{"file_id": fileInfo.Id}}) + newPost.Type = "custom_zoom_chat" + if newPost.Message == "" { + newPost.Message = " " + } + } + if recording.RecordingType == zoom.RecordingTypeVideo { + newPost.Message = "Here's the zoom meeting recording:\n**Link:** [Meeting Recording](" + recording.PlayURL + ")\n**Password:** " + webhook.Payload.Object.Password + } + } + if newPost.Message != "" { + _, appErr = p.API.CreatePost(newPost) + if appErr != nil { + p.API.LogWarn("Could not update the post", "err", appErr) + http.Error(w, appErr.Error(), appErr.StatusCode) + return + } } } + // TODO: Delete the meeting post if is no longer needed // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) From 467399e39bbd2018edfb06498ad483eabb4102b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Wed, 15 May 2024 19:54:08 +0200 Subject: [PATCH 06/37] Removing debug log messages --- server/http.go | 1 - server/webhook.go | 26 -------------------------- 2 files changed, 27 deletions(-) diff --git a/server/http.go b/server/http.go index 56d17820..7bf8a923 100644 --- a/server/http.go +++ b/server/http.go @@ -440,7 +440,6 @@ func (p *Plugin) postMeeting(creator *model.User, meetingID int, meetingUUID str return appErr } - p.API.LogWarn("MEETING UUID ID", "uuid", meetingUUID) if appErr = p.storeMeetingPostID(meetingUUID, createdPost.Id); appErr != nil { p.API.LogDebug("failed to store post id", "error", appErr) } diff --git a/server/webhook.go b/server/webhook.go index cc718202..5729c2b8 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -57,7 +57,6 @@ func (p *Plugin) handleWebhook(w http.ResponseWriter, r *http.Request) { } } - p.API.LogWarn("New event received", "even_type", webhook.Event, "payload", string(b)) switch webhook.Event { case zoom.EventTypeMeetingStarted: p.handleMeetingStarted(w, r, b) @@ -99,8 +98,6 @@ func (p *Plugin) handleMeetingStarted(w http.ResponseWriter, r *http.Request, bo return } - p.API.LogError("RUNNING THIS ON CHANNEL", "channel", channelID) - botUser, appErr := p.API.GetUser(p.botUserID) if appErr != nil { p.API.LogError("Failed to get bot user", "err", appErr.Error()) @@ -108,16 +105,12 @@ func (p *Plugin) handleMeetingStarted(w http.ResponseWriter, r *http.Request, bo return } - p.API.LogError("POSTING MEETING TO CHANNEL", "channel", channelID, "meetingID", meetingID) - if postMeetingErr := p.postMeeting(botUser, meetingID, webhook.Payload.Object.UUID, channelID, "", webhook.Payload.Object.ID); postMeetingErr != nil { p.API.LogError("Failed to post the zoom message in the channel", "err", postMeetingErr.Error()) http.Error(w, postMeetingErr.Error(), http.StatusBadRequest) return } - p.API.LogError("POSTED MEETING TO CHANNEL", "channel", channelID, "meetingID", meetingID) - p.trackMeetingStart(p.botUserID, telemetryStartSourceCommand) p.trackMeetingType(p.botUserID, false) } @@ -131,7 +124,6 @@ func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body } meetingPostID := webhook.Payload.Object.UUID - p.API.LogWarn("MEETING ID", "uuid", meetingPostID) postID, appErr := p.fetchMeetingPostID(meetingPostID) if appErr != nil { http.Error(w, appErr.Error(), appErr.StatusCode) @@ -180,12 +172,6 @@ func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body return } - // TODO: Delete the meeting post if is no longer needed - // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { - // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) - // return - // } - w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(post); err != nil { p.API.LogWarn("failed to write response", "error", err.Error()) @@ -294,12 +280,6 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques } } - // TODO: Delete the meeting post if is no longer needed - // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { - // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) - // return - // } - w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(post); err != nil { p.API.LogWarn("failed to write response", "error", err.Error()) @@ -398,12 +378,6 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request } } - // TODO: Delete the meeting post if is no longer needed - // if appErr = p.deleteMeetingPostID(meetingPostID); appErr != nil { - // p.API.LogWarn("failed to delete db entry", "error", appErr.Error()) - // return - // } - w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(post); err != nil { p.API.LogWarn("failed to write response", "error", err.Error()) From e4485896ff2b289de721df25d566f8a78e7be1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Wed, 15 May 2024 20:15:54 +0200 Subject: [PATCH 07/37] Fixing tests --- server/plugin_test.go | 5 +++-- server/webhook_test.go | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/server/plugin_test.go b/server/plugin_test.go index 230ea133..73fa7877 100644 --- a/server/plugin_test.go +++ b/server/plugin_test.go @@ -61,10 +61,10 @@ func TestPlugin(t *testing.T) { meetingRequest := httptest.NewRequest("POST", "/api/v1/meetings", strings.NewReader("{\"channel_id\": \"thechannelid\"}")) meetingRequest.Header.Add("Mattermost-User-Id", "theuserid") - endedPayload := `{"event": "meeting.ended", "payload": {"object": {"id": "234"}}}` + endedPayload := `{"event": "meeting.ended", "payload": {"object": {"id": "234", "uuid": "234"}}}` validStoppedWebhookRequest := httptest.NewRequest("POST", "/webhook?secret=thewebhooksecret", strings.NewReader(endedPayload)) - validStartedWebhookRequest := httptest.NewRequest("POST", "/webhook?secret=thewebhooksecret", strings.NewReader(`{"event": "meeting.started"}`)) + validStartedWebhookRequest := httptest.NewRequest("POST", "/webhook?secret=thewebhooksecret", strings.NewReader(`{"event": "meeting.started", "payload": {"object": {"id": "234"}}}`)) noSecretWebhookRequest := httptest.NewRequest("POST", "/webhook", strings.NewReader(endedPayload)) @@ -153,6 +153,7 @@ func TestPlugin(t *testing.T) { api.On("KVGet", fmt.Sprintf("%v%v", postMeetingKey, 234)).Return([]byte("thepostid"), nil) api.On("KVGet", fmt.Sprintf("%v%v", postMeetingKey, 123)).Return([]byte("thepostid"), nil) + api.On("KVGet", fmt.Sprintf("%v%v", meetingChannelKey, 234)).Return([]byte(""), nil) api.On("KVDelete", fmt.Sprintf("%v%v", postMeetingKey, 234)).Return(nil) diff --git a/server/webhook_test.go b/server/webhook_test.go index 70755e23..dbd92510 100644 --- a/server/webhook_test.go +++ b/server/webhook_test.go @@ -2,6 +2,9 @@ package main import ( "bytes" + "crypto/hmac" + "crypto/sha256" + "encoding/hex" "encoding/json" "io" "net/http/httptest" @@ -63,10 +66,12 @@ func TestWebhookVerifySignature(t *testing.T) { api.On("LogDebug", "Could not get meeting post from KVStore", "error", "") p.SetAPI(api) - requestBody := `{"payload":{"object": {"id": "123"}},"event":"meeting.ended"}` + requestBody := `{"payload":{"object": {"id": "123", "uuid": "123"}},"event":"meeting.ended"}` ts := "1660149894817" - signature := "v0=7fe2f9e66d133961eff4746eda161096cebe8d677319d66546281d88ea147189" + h := hmac.New(sha256.New, []byte(testConfig.ZoomWebhookSecret)) + _, _ = h.Write([]byte("v0:" + ts + ":" + requestBody)) + signature := "v0=" + hex.EncodeToString(h.Sum(nil)) w := httptest.NewRecorder() reqBody := io.NopCloser(bytes.NewBufferString(requestBody)) From df60c28872203d1d655148bf2d5c0b841ba4d8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Wed, 15 May 2024 20:21:35 +0200 Subject: [PATCH 08/37] fixing linter errors --- webapp/src/components/post_type_chat.jsx | 20 ++++++++++++++----- .../components/post_type_transcription.jsx | 14 +++++++++++-- webapp/webpack.config.js | 5 +++-- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/webapp/src/components/post_type_chat.jsx b/webapp/src/components/post_type_chat.jsx index e616ff7f..e942d31d 100644 --- a/webapp/src/components/post_type_chat.jsx +++ b/webapp/src/components/post_type_chat.jsx @@ -1,9 +1,12 @@ import React from 'react'; +import PropTypes from 'prop-types'; import {FormattedMessage} from 'react-intl'; import {useSelector} from 'react-redux'; -import IconAI from 'src/components/ai_icon'; + import styled from 'styled-components'; +import IconAI from 'src/components/ai_icon'; + const useAIAvailable = () => { //@ts-ignore plugins state is a thing return useSelector((state) => Boolean(state.plugins?.plugins?.[aiPluginID])); @@ -54,7 +57,7 @@ export const PostTypeChat = (props) => { callsPostButtonClicked?.(props.post); }; - const msg = props.post.message; + const markdownMessage = props.post.message; const renderPostWithMarkdown = (msg) => { const {formatText, messageHtmlToComponent} = window.PostUtils; @@ -63,19 +66,26 @@ export const PostTypeChat = (props) => { formatText(msg, {}), false, ); - } + }; return (
- {renderPostWithMarkdown(msg)} + {renderPostWithMarkdown(markdownMessage)} {aiAvailable && callsPostButtonClicked && - + }
); }; + +PostTypeChat.propTypes = { + post: PropTypes.object.isRequired, +}; diff --git a/webapp/src/components/post_type_transcription.jsx b/webapp/src/components/post_type_transcription.jsx index 9223354c..5903f3b3 100644 --- a/webapp/src/components/post_type_transcription.jsx +++ b/webapp/src/components/post_type_transcription.jsx @@ -1,9 +1,12 @@ import React from 'react'; +import PropTypes from 'prop-types'; import {FormattedMessage} from 'react-intl'; import {useSelector} from 'react-redux'; -import IconAI from 'src/components/ai_icon'; + import styled from 'styled-components'; +import IconAI from 'src/components/ai_icon'; + const useAIAvailable = () => { //@ts-ignore plugins state is a thing return useSelector((state) => Boolean(state.plugins?.plugins?.[aiPluginID])); @@ -64,9 +67,16 @@ export const PostTypeTranscription = (props) => { onClick={createMeetingSummary} > - + } ); }; + +PostTypeTranscription.propTypes = { + post: PropTypes.object.isRequired, +}; diff --git a/webapp/webpack.config.js b/webapp/webpack.config.js index de72ca1a..1d91a1a2 100644 --- a/webapp/webpack.config.js +++ b/webapp/webpack.config.js @@ -31,8 +31,9 @@ module.exports = { }, plugins: [ new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), - }) + // eslint-disable-next-line no-process-env + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), + }), ], externals: { react: 'React', From bc696fdb386ed447650a036701c2b14dd53941d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Wed, 15 May 2024 20:35:19 +0200 Subject: [PATCH 09/37] Fixing linter errors --- server/store.go | 5 ----- server/webhook.go | 27 ++++++++++++++------------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/server/store.go b/server/store.go index aeb09361..4e3862bb 100644 --- a/server/store.go +++ b/server/store.go @@ -157,11 +157,6 @@ func (p *Plugin) fetchMeetingPostID(meetingUUID string) (string, *model.AppError return string(postID), nil } -func (p *Plugin) deleteMeetingPostID(postID string) *model.AppError { - key := fmt.Sprintf("%v%v", postMeetingKey, postID) - return p.API.KVDelete(key) -} - func (p *Plugin) storeChannelForMeeting(meetingID int, channelID string) *model.AppError { key := fmt.Sprintf("%v%v", meetingChannelKey, meetingID) bytes := []byte(channelID) diff --git a/server/webhook.go b/server/webhook.go index 5729c2b8..79194f37 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -189,18 +189,19 @@ func (p *Plugin) handleTranscript(recording zoom.RecordingFile, postID, channelI retries := 5 var response *http.Response for retries > 0 { - var err error response, err = http.DefaultClient.Do(request) if err != nil { p.API.LogWarn("Unable to get the transcription", "err", err) time.Sleep(1 * time.Second) - retries -= 1 + retries-- continue } + if response.StatusCode != http.StatusOK { + response.Body.Close() p.API.LogWarn("Unable to get the transcription", "err", "bad status code "+strconv.Itoa(response.StatusCode)) time.Sleep(1 * time.Second) - retries -= 1 + retries-- continue } break @@ -265,17 +266,17 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques return } - var lastTranscription *zoom.RecordingFile - for _, recording := range webhook.Payload.Object.RecordingFiles { + lastTranscriptionIdx := -1 + for idx, recording := range webhook.Payload.Object.RecordingFiles { if recording.RecordingType == zoom.RecordingTypeAudioTranscript { - lastTranscription = &recording + lastTranscriptionIdx = idx } } - if lastTranscription != nil { - err := p.handleTranscript(*lastTranscription, post.Id, post.ChannelId, webhook.DownloadToken) + if lastTranscriptionIdx != -1 { + err := p.handleTranscript(webhook.Payload.Object.RecordingFiles[lastTranscriptionIdx], post.Id, post.ChannelId, webhook.DownloadToken) if err != nil { - http.Error(w, appErr.Error(), appErr.StatusCode) + http.Error(w, err.Error(), http.StatusBadRequest) return } } @@ -350,10 +351,10 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request http.Error(w, err.Error(), http.StatusBadRequest) return } - fileInfo, appErr := p.API.UploadFile(chat, post.ChannelId, "Chat-history.txt") - if appErr != nil { - p.API.LogWarn("Unable to get the chat", "err", appErr) - http.Error(w, appErr.Error(), http.StatusBadRequest) + fileInfo, appErr2 := p.API.UploadFile(chat, post.ChannelId, "Chat-history.txt") + if appErr2 != nil { + p.API.LogWarn("Unable to get the chat", "err", appErr2) + http.Error(w, appErr2.Error(), http.StatusBadRequest) return } From 513006a9f3e948084c90165265f0434b91cffd7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 16 May 2024 10:39:42 +0200 Subject: [PATCH 10/37] Addressing PR review comments --- server/command.go | 22 ++++++++++++++++++++-- server/webhook.go | 25 +++---------------------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/server/command.go b/server/command.go index 3b331dc6..9d95a15f 100644 --- a/server/command.go +++ b/server/command.go @@ -241,18 +241,36 @@ func (p *Plugin) runConnectCommand(user *model.User, extra *model.CommandArgs) ( } func (p *Plugin) runSubscribeCommand(user *model.User, extra *model.CommandArgs, meetingID int) (string, error) { + if !p.API.HasPermissionToChannel(user.Id, extra.ChannelId, model.PermissionCreatePost) { + return "You do not have permission to subscribe to this channel", nil + } + + _, err := p.getMeeting(user, meetingID) + if err != nil { + return "Can not subscribe to meeting: meeting not found", errors.Wrap(err, "meeting not found") + } + if appErr := p.storeChannelForMeeting(meetingID, extra.ChannelId); appErr != nil { - return "", errors.Wrap(appErr, "cannot subscribing to meeting") + return "", errors.Wrap(appErr, "cannot subscribe to meeting") } return "Channel subscribed to meeting", nil } func (p *Plugin) runUnsubscribeCommand(user *model.User, extra *model.CommandArgs, meetingID int) (string, error) { + if !p.API.HasPermissionToChannel(user.Id, extra.ChannelId, model.PermissionCreatePost) { + return "You do not have permission to unsubscribe from this channel", nil + } + + _, err := p.getMeeting(user, meetingID) + if err != nil { + return "Can not unsubscribe from meeting: meeting not found", errors.Wrap(err, "meeting not found") + } + if channelID, appErr := p.fetchChannelForMeeting(meetingID); appErr != nil || channelID == "" { return "Can not unsubscribe from meeting: meeting not found", errors.New("meeting not found") } if appErr := p.deleteChannelForMeeting(meetingID); appErr != nil { - return "Can not unsubscribe from meeting: unable to delete the meeting subscription", errors.Wrap(appErr, "cannot unsubscribing from meeting") + return "Can not unsubscribe from meeting: unable to delete the meeting subscription", errors.Wrap(appErr, "cannot unsubscribe from meeting") } return "Channel unsubscribed from meeting", nil } diff --git a/server/webhook.go b/server/webhook.go index 79194f37..19da6365 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -90,7 +90,6 @@ func (p *Plugin) handleMeetingStarted(w http.ResponseWriter, r *http.Request, bo channelID, appErr := p.fetchChannelForMeeting(meetingID) if appErr != nil { - http.Error(w, appErr.Error(), appErr.StatusCode) return } @@ -101,13 +100,11 @@ func (p *Plugin) handleMeetingStarted(w http.ResponseWriter, r *http.Request, bo botUser, appErr := p.API.GetUser(p.botUserID) if appErr != nil { p.API.LogError("Failed to get bot user", "err", appErr.Error()) - http.Error(w, appErr.Error(), http.StatusBadRequest) return } if postMeetingErr := p.postMeeting(botUser, meetingID, webhook.Payload.Object.UUID, channelID, "", webhook.Payload.Object.ID); postMeetingErr != nil { p.API.LogError("Failed to post the zoom message in the channel", "err", postMeetingErr.Error()) - http.Error(w, postMeetingErr.Error(), http.StatusBadRequest) return } @@ -126,14 +123,12 @@ func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body meetingPostID := webhook.Payload.Object.UUID postID, appErr := p.fetchMeetingPostID(meetingPostID) if appErr != nil { - http.Error(w, appErr.Error(), appErr.StatusCode) return } post, appErr := p.API.GetPost(postID) if appErr != nil { p.API.LogWarn("Could not get meeting post by id", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) return } @@ -168,7 +163,6 @@ func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body _, appErr = p.API.UpdatePost(post) if appErr != nil { p.API.LogWarn("Could not update the post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) return } @@ -213,14 +207,14 @@ func (p *Plugin) handleTranscript(recording zoom.RecordingFile, postID, channelI } defer response.Body.Close() - transcription, err := io.ReadAll(response.Body) + transcriptionBytes, err := io.ReadAll(response.Body) if err != nil { p.API.LogWarn("Unable to get the transcription", "err", err) return err } - fileInfo, appErr := p.API.UploadFile(transcription, channelID, "transcription.txt") + fileInfo, appErr := p.API.UploadFile(transcriptionBytes, channelID, "transcription.txt") if appErr != nil { - p.API.LogWarn("Unable to get the transcription", "err", appErr) + p.API.LogWarn("Unable to save transcription file to the channel", "err", appErr) return appErr } newPost := &model.Post{ @@ -255,14 +249,12 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques meetingPostID := webhook.Payload.Object.UUID postID, appErr := p.fetchMeetingPostID(meetingPostID) if appErr != nil { - http.Error(w, appErr.Error(), appErr.StatusCode) return } post, appErr := p.API.GetPost(postID) if appErr != nil { p.API.LogWarn("Could not get meeting post by id", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) return } @@ -276,7 +268,6 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques if lastTranscriptionIdx != -1 { err := p.handleTranscript(webhook.Payload.Object.RecordingFiles[lastTranscriptionIdx], post.Id, post.ChannelId, webhook.DownloadToken) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) return } } @@ -298,14 +289,12 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request meetingPostID := webhook.Payload.Object.UUID postID, appErr := p.fetchMeetingPostID(meetingPostID) if appErr != nil { - http.Error(w, appErr.Error(), appErr.StatusCode) return } post, appErr := p.API.GetPost(postID) if appErr != nil { p.API.LogWarn("Could not get meeting post by id", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) return } @@ -334,36 +323,29 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request request, err := http.NewRequest(http.MethodGet, recording.DownloadURL, nil) if err != nil { p.API.LogWarn("Unable to get the chat", "err", err) - http.Error(w, err.Error(), http.StatusBadRequest) return } request.Header.Set("Authorization", "Bearer "+webhook.DownloadToken) response, err := http.DefaultClient.Do(request) if err != nil { p.API.LogWarn("Unable to get the chat", "err", err) - http.Error(w, err.Error(), http.StatusBadRequest) return } defer response.Body.Close() chat, err := io.ReadAll(response.Body) if err != nil { p.API.LogWarn("Unable to get the chat", "err", err) - http.Error(w, err.Error(), http.StatusBadRequest) return } fileInfo, appErr2 := p.API.UploadFile(chat, post.ChannelId, "Chat-history.txt") if appErr2 != nil { p.API.LogWarn("Unable to get the chat", "err", appErr2) - http.Error(w, appErr2.Error(), http.StatusBadRequest) return } newPost.FileIds = append(newPost.FileIds, fileInfo.Id) newPost.AddProp("captions", []any{map[string]any{"file_id": fileInfo.Id}}) newPost.Type = "custom_zoom_chat" - if newPost.Message == "" { - newPost.Message = " " - } } if recording.RecordingType == zoom.RecordingTypeVideo { newPost.Message = "Here's the zoom meeting recording:\n**Link:** [Meeting Recording](" + recording.PlayURL + ")\n**Password:** " + webhook.Payload.Object.Password @@ -373,7 +355,6 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request _, appErr = p.API.CreatePost(newPost) if appErr != nil { p.API.LogWarn("Could not update the post", "err", appErr) - http.Error(w, appErr.Error(), appErr.StatusCode) return } } From 8b30a5d79d228eef9b20cf9e0c80c0c1ea6e07e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 16 May 2024 10:42:49 +0200 Subject: [PATCH 11/37] Updating webhooks subscriptions needed in the documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 211aa8ab..3ad8a627 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ When a Zoom meeting ends, the original link shared in the channel can be changed ![mattermost_webhook_secret](https://github.com/mattermost/mattermost-plugin-zoom/assets/74422101/58b9ac74-ecf9-4e3e-986e-94fd4c39bfb0) -Select **Add events** and select the **End Meeting** event. +Select **Add events** and select the **Start Meeting**, **End Meeting**, **All Recordings have completed** and **Recording Transcript files have completed** events. ![event_types](https://github.com/mattermost/mattermost-plugin-zoom/assets/74422101/a2f04fe9-e4fa-4e78-b198-1f493e53cf93) From a8100649a7385cd1cf1cb7ae23307502e64e36fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 16 May 2024 10:48:20 +0200 Subject: [PATCH 12/37] Addressing PR review comments --- webapp/src/components/post_type_chat.jsx | 22 +++++++++---------- .../components/post_type_transcription.jsx | 22 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/webapp/src/components/post_type_chat.jsx b/webapp/src/components/post_type_chat.jsx index e942d31d..629be5ab 100644 --- a/webapp/src/components/post_type_chat.jsx +++ b/webapp/src/components/post_type_chat.jsx @@ -71,17 +71,17 @@ export const PostTypeChat = (props) => { return (
{renderPostWithMarkdown(markdownMessage)} - {aiAvailable && callsPostButtonClicked && - - - - - } + {aiAvailable && callsPostButtonClicked && ( + + + + + )}
); }; diff --git a/webapp/src/components/post_type_transcription.jsx b/webapp/src/components/post_type_transcription.jsx index 5903f3b3..6e89292f 100644 --- a/webapp/src/components/post_type_transcription.jsx +++ b/webapp/src/components/post_type_transcription.jsx @@ -62,17 +62,17 @@ export const PostTypeTranscription = (props) => { return (
{msg} - {aiAvailable && callsPostButtonClicked && - - - - - } + {aiAvailable && callsPostButtonClicked && ( + + + + + )}
); }; From 9ae260c6adfb62dc3d123104823d517cbf1afd40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 16 May 2024 10:49:45 +0200 Subject: [PATCH 13/37] Addressing PR review comments --- webapp/package-lock.json | 20 +++++++++++--------- webapp/package.json | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/webapp/package-lock.json b/webapp/package-lock.json index ee7755d4..c4f52b15 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -12,7 +12,7 @@ "core-js": "3.7.0", "mattermost-redux": "5.33.1", "prop-types": "15.7.2", - "react": "18.3.1", + "react": "17.0.2", "react-intl": "4.7.6", "react-redux": "7.2.2", "redux": "4.0.5", @@ -12023,11 +12023,12 @@ } }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", "dependencies": { - "loose-envify": "^1.1.0" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" }, "engines": { "node": ">=0.10.0" @@ -23580,11 +23581,12 @@ "peer": true }, "react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", "requires": { - "loose-envify": "^1.1.0" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" } }, "react-devtools-core": { diff --git a/webapp/package.json b/webapp/package.json index 2a5f7131..41e9fda0 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -22,7 +22,7 @@ "core-js": "3.7.0", "mattermost-redux": "5.33.1", "prop-types": "15.7.2", - "react": "18.3.1", + "react": "17.0.2", "react-intl": "4.7.6", "react-redux": "7.2.2", "redux": "4.0.5", From 42bfc3adcdf3a4dc6fb95a6233f3a7228e615e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 16 May 2024 11:00:58 +0200 Subject: [PATCH 14/37] Avoid subscriptions to personal meetings --- server/command.go | 6 +++++- server/zoom/meeting.go | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/server/command.go b/server/command.go index 9d95a15f..1685d41b 100644 --- a/server/command.go +++ b/server/command.go @@ -245,11 +245,15 @@ func (p *Plugin) runSubscribeCommand(user *model.User, extra *model.CommandArgs, return "You do not have permission to subscribe to this channel", nil } - _, err := p.getMeeting(user, meetingID) + meeting, err := p.getMeeting(user, meetingID) if err != nil { return "Can not subscribe to meeting: meeting not found", errors.Wrap(err, "meeting not found") } + if meeting.Type == zoom.MeetingTypePersonal { + return "Can not subscribe to personal meeting", nil + } + if appErr := p.storeChannelForMeeting(meetingID, extra.ChannelId); appErr != nil { return "", errors.Wrap(appErr, "cannot subscribe to meeting") } diff --git a/server/zoom/meeting.go b/server/zoom/meeting.go index 040408c5..9b440620 100644 --- a/server/zoom/meeting.go +++ b/server/zoom/meeting.go @@ -13,6 +13,8 @@ const ( MeetingTypeScheduled MeetingType = 2 // MeetingTypeRecurringWithNoFixedTime meeting MeetingTypeRecurringWithNoFixedTime MeetingType = 3 + // MeetingTypePersonal + MeetingTypePersonal MeetingType = 4 // MeetingTypeRecurringWithFixedTime meeting MeetingTypeRecurringWithFixedTime MeetingType = 8 ) From 4f6233f3282b963b950ac9d423b3cf4a713dd932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 16 May 2024 22:04:31 +0200 Subject: [PATCH 15/37] Migrating to typescript --- webapp/package-lock.json | 25 +++++++++++++ webapp/package.json | 1 + .../components/{ai_icon.jsx => ai_icon.tsx} | 0 ...{post_type_chat.jsx => post_type_chat.tsx} | 36 +++++++++++-------- ...iption.jsx => post_type_transcription.tsx} | 31 +++++++++------- webapp/src/components/{svg.jsx => svg.tsx} | 0 webapp/tsconfig.json | 1 + 7 files changed, 66 insertions(+), 28 deletions(-) rename webapp/src/components/{ai_icon.jsx => ai_icon.tsx} (100%) rename webapp/src/components/{post_type_chat.jsx => post_type_chat.tsx} (68%) rename webapp/src/components/{post_type_transcription.jsx => post_type_transcription.tsx} (71%) rename webapp/src/components/{svg.jsx => svg.tsx} (100%) diff --git a/webapp/package-lock.json b/webapp/package-lock.json index c4f52b15..1d4b7417 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -32,6 +32,7 @@ "@babel/runtime": "7.16.7", "@emotion/babel-preset-css-prop": "11.2.0", "@emotion/react": "11.11.0", + "@types/react-redux": "7.1.33", "@typescript-eslint/eslint-plugin": "5.10.1", "@typescript-eslint/parser": "5.10.1", "babel-eslint": "10.1.0", @@ -4741,6 +4742,18 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-redux": { + "version": "7.1.33", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.33.tgz", + "integrity": "sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg==", + "dev": true, + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -18017,6 +18030,18 @@ "csstype": "^3.0.2" } }, + "@types/react-redux": { + "version": "7.1.33", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.33.tgz", + "integrity": "sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg==", + "dev": true, + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", diff --git a/webapp/package.json b/webapp/package.json index 41e9fda0..b21bedff 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -42,6 +42,7 @@ "@babel/runtime": "7.16.7", "@emotion/babel-preset-css-prop": "11.2.0", "@emotion/react": "11.11.0", + "@types/react-redux": "7.1.33", "@typescript-eslint/eslint-plugin": "5.10.1", "@typescript-eslint/parser": "5.10.1", "babel-eslint": "10.1.0", diff --git a/webapp/src/components/ai_icon.jsx b/webapp/src/components/ai_icon.tsx similarity index 100% rename from webapp/src/components/ai_icon.jsx rename to webapp/src/components/ai_icon.tsx diff --git a/webapp/src/components/post_type_chat.jsx b/webapp/src/components/post_type_chat.tsx similarity index 68% rename from webapp/src/components/post_type_chat.jsx rename to webapp/src/components/post_type_chat.tsx index 629be5ab..979d4088 100644 --- a/webapp/src/components/post_type_chat.jsx +++ b/webapp/src/components/post_type_chat.tsx @@ -1,23 +1,28 @@ import React from 'react'; -import PropTypes from 'prop-types'; import {FormattedMessage} from 'react-intl'; import {useSelector} from 'react-redux'; +import type {Post} from 'mattermost-redux/types/posts'; +import type {GlobalState} from 'mattermost-redux/types/store'; + import styled from 'styled-components'; import IconAI from 'src/components/ai_icon'; +const aiPluginID = 'mattermost-ai'; + const useAIAvailable = () => { - //@ts-ignore plugins state is a thing - return useSelector((state) => Boolean(state.plugins?.plugins?.[aiPluginID])); + return useSelector((state: any) => Boolean(state.plugins?.plugins?.[aiPluginID])); }; -const aiPluginID = 'mattermost-ai'; - const useCallsPostButtonClicked = () => { - return useSelector((state) => { - //@ts-ignore plugins state is a thing - return state['plugins-' + aiPluginID]?.callsPostButtonClickedTranscription; + return useSelector((state: GlobalState) => { + type StateWithAiPluginState = { + 'plugins-mattermost-ai'?: {callsPostButtonClickedTranscription: (post: Post) => void}; + } + const stateTyped: StateWithAiPluginState = state as StateWithAiPluginState; + const aiPluginState = stateTyped['plugins-mattermost-ai']; + return aiPluginState?.callsPostButtonClickedTranscription; }); }; @@ -49,7 +54,11 @@ const CreateMeetingSummaryButton = styled.button` } `; -export const PostTypeChat = (props) => { +type Props = { + post: Post; +}; + +export const PostTypeChat = (props: Props) => { const aiAvailable = useAIAvailable(); const callsPostButtonClicked = useCallsPostButtonClicked(); @@ -59,8 +68,9 @@ export const PostTypeChat = (props) => { const markdownMessage = props.post.message; - const renderPostWithMarkdown = (msg) => { - const {formatText, messageHtmlToComponent} = window.PostUtils; + const renderPostWithMarkdown = (msg: string) => { + const windowAny: any = window; + const {formatText, messageHtmlToComponent} = windowAny.PostUtils; return messageHtmlToComponent( formatText(msg, {}), @@ -85,7 +95,3 @@ export const PostTypeChat = (props) => { ); }; - -PostTypeChat.propTypes = { - post: PropTypes.object.isRequired, -}; diff --git a/webapp/src/components/post_type_transcription.jsx b/webapp/src/components/post_type_transcription.tsx similarity index 71% rename from webapp/src/components/post_type_transcription.jsx rename to webapp/src/components/post_type_transcription.tsx index 6e89292f..b8316419 100644 --- a/webapp/src/components/post_type_transcription.jsx +++ b/webapp/src/components/post_type_transcription.tsx @@ -1,23 +1,28 @@ import React from 'react'; -import PropTypes from 'prop-types'; import {FormattedMessage} from 'react-intl'; import {useSelector} from 'react-redux'; +import type {Post} from 'mattermost-redux/types/posts'; +import type {GlobalState} from 'mattermost-redux/types/store'; + import styled from 'styled-components'; import IconAI from 'src/components/ai_icon'; +const aiPluginID = 'mattermost-ai'; + const useAIAvailable = () => { - //@ts-ignore plugins state is a thing - return useSelector((state) => Boolean(state.plugins?.plugins?.[aiPluginID])); + return useSelector((state: any) => Boolean(state.plugins?.plugins?.[aiPluginID])); }; -const aiPluginID = 'mattermost-ai'; - const useCallsPostButtonClicked = () => { - return useSelector((state) => { - //@ts-ignore plugins state is a thing - return state['plugins-' + aiPluginID]?.callsPostButtonClickedTranscription; + return useSelector((state: GlobalState) => { + type StateWithAiPluginState = { + 'plugins-mattermost-ai'?: {callsPostButtonClickedTranscription: (post: Post) => void}; + } + const stateTyped: StateWithAiPluginState = state as StateWithAiPluginState; + const aiPluginState = stateTyped['plugins-mattermost-ai']; + return aiPluginState?.callsPostButtonClickedTranscription; }); }; @@ -49,7 +54,11 @@ const CreateMeetingSummaryButton = styled.button` } `; -export const PostTypeTranscription = (props) => { +type Props = { + post: Post; +}; + +export const PostTypeTranscription = (props: Props) => { const aiAvailable = useAIAvailable(); const callsPostButtonClicked = useCallsPostButtonClicked(); @@ -76,7 +85,3 @@ export const PostTypeTranscription = (props) => { ); }; - -PostTypeTranscription.propTypes = { - post: PropTypes.object.isRequired, -}; diff --git a/webapp/src/components/svg.jsx b/webapp/src/components/svg.tsx similarity index 100% rename from webapp/src/components/svg.jsx rename to webapp/src/components/svg.tsx diff --git a/webapp/tsconfig.json b/webapp/tsconfig.json index 76616e9f..2a66c7eb 100644 --- a/webapp/tsconfig.json +++ b/webapp/tsconfig.json @@ -6,6 +6,7 @@ "dom.iterable", "esnext" ], + "jsx": "react", "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, From 0cc74d99de3159feebb7c1cfc6487e70084b05ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 16 May 2024 22:06:40 +0200 Subject: [PATCH 16/37] Migrating to typescript --- webapp/src/components/post_type_chat.tsx | 9 ++------- webapp/src/components/post_type_transcription.tsx | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/webapp/src/components/post_type_chat.tsx b/webapp/src/components/post_type_chat.tsx index 979d4088..54040227 100644 --- a/webapp/src/components/post_type_chat.tsx +++ b/webapp/src/components/post_type_chat.tsx @@ -3,7 +3,6 @@ import {FormattedMessage} from 'react-intl'; import {useSelector} from 'react-redux'; import type {Post} from 'mattermost-redux/types/posts'; -import type {GlobalState} from 'mattermost-redux/types/store'; import styled from 'styled-components'; @@ -16,12 +15,8 @@ const useAIAvailable = () => { }; const useCallsPostButtonClicked = () => { - return useSelector((state: GlobalState) => { - type StateWithAiPluginState = { - 'plugins-mattermost-ai'?: {callsPostButtonClickedTranscription: (post: Post) => void}; - } - const stateTyped: StateWithAiPluginState = state as StateWithAiPluginState; - const aiPluginState = stateTyped['plugins-mattermost-ai']; + return useSelector((state: any) => { + const aiPluginState = state['plugins-'+aiPluginID]; return aiPluginState?.callsPostButtonClickedTranscription; }); }; diff --git a/webapp/src/components/post_type_transcription.tsx b/webapp/src/components/post_type_transcription.tsx index b8316419..e2bc7630 100644 --- a/webapp/src/components/post_type_transcription.tsx +++ b/webapp/src/components/post_type_transcription.tsx @@ -3,7 +3,6 @@ import {FormattedMessage} from 'react-intl'; import {useSelector} from 'react-redux'; import type {Post} from 'mattermost-redux/types/posts'; -import type {GlobalState} from 'mattermost-redux/types/store'; import styled from 'styled-components'; @@ -16,12 +15,8 @@ const useAIAvailable = () => { }; const useCallsPostButtonClicked = () => { - return useSelector((state: GlobalState) => { - type StateWithAiPluginState = { - 'plugins-mattermost-ai'?: {callsPostButtonClickedTranscription: (post: Post) => void}; - } - const stateTyped: StateWithAiPluginState = state as StateWithAiPluginState; - const aiPluginState = stateTyped['plugins-mattermost-ai']; + return useSelector((state: any) => { + const aiPluginState = state['plugins-'+aiPluginID]; return aiPluginState?.callsPostButtonClickedTranscription; }); }; From bf0599dc69db85be9bf5c7cbddfd96f339453042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 17 May 2024 09:32:57 +0200 Subject: [PATCH 17/37] Fixing linter --- webapp/src/components/post_type_chat.tsx | 2 +- webapp/src/components/post_type_transcription.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/post_type_chat.tsx b/webapp/src/components/post_type_chat.tsx index 54040227..086064ba 100644 --- a/webapp/src/components/post_type_chat.tsx +++ b/webapp/src/components/post_type_chat.tsx @@ -16,7 +16,7 @@ const useAIAvailable = () => { const useCallsPostButtonClicked = () => { return useSelector((state: any) => { - const aiPluginState = state['plugins-'+aiPluginID]; + const aiPluginState = state['plugins-' + aiPluginID]; return aiPluginState?.callsPostButtonClickedTranscription; }); }; diff --git a/webapp/src/components/post_type_transcription.tsx b/webapp/src/components/post_type_transcription.tsx index e2bc7630..39ebbb94 100644 --- a/webapp/src/components/post_type_transcription.tsx +++ b/webapp/src/components/post_type_transcription.tsx @@ -16,7 +16,7 @@ const useAIAvailable = () => { const useCallsPostButtonClicked = () => { return useSelector((state: any) => { - const aiPluginState = state['plugins-'+aiPluginID]; + const aiPluginState = state['plugins-' + aiPluginID]; return aiPluginState?.callsPostButtonClickedTranscription; }); }; From 777767074239ede978de063d8b4d580ce58d1ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 17 May 2024 10:12:22 +0200 Subject: [PATCH 18/37] Adding tests for transcript and chat handlers --- server/webhook_test.go | 169 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/server/webhook_test.go b/server/webhook_test.go index dbd92510..7303f858 100644 --- a/server/webhook_test.go +++ b/server/webhook_test.go @@ -7,8 +7,10 @@ import ( "encoding/hex" "encoding/json" "io" + "net/http" "net/http/httptest" "testing" + "time" "github.com/stretchr/testify/require" @@ -112,3 +114,170 @@ func TestWebhookVerifySignatureInvalid(t *testing.T) { body, _ := io.ReadAll(w.Result().Body) t.Log(string(body)) } + +func TestWebhookHandleTranscriptCompleted(t *testing.T) { + api := &plugintest.API{} + p := Plugin{} + p.setConfiguration(testConfig) + + httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Write([]byte(r.URL.Path)) + })) + defer httpServer.Close() + + oldDefaultClient := http.DefaultClient + http.DefaultClient = httpServer.Client() + defer func() { + http.DefaultClient = oldDefaultClient + }() + + api.On("GetLicense").Return(nil) + api.On("GetPost", "post-id").Return(&model.Post{Id: "post-id", ChannelId: "channel-id"}, nil) + api.On("KVGet", "post_meeting_321").Return([]byte("post-id"), nil) + api.On("UploadFile", []byte("/test"), "channel-id", "transcription.txt").Return(&model.FileInfo{Id: "file-id"}, nil) + api.On("CreatePost", &model.Post{ + ChannelId: "channel-id", + RootId: "post-id", + Message: "Here's the zoom meeting transcription", + Type: "custom_zoom_transcript", + Props: model.StringInterface{ + "captions": []any{map[string]any{"file_id": "file-id"}}, + }, + FileIds: []string{"file-id"}, + }).Return(&model.Post{ + ChannelId: "channel-id", + RootId: "post-id", + Message: "Here's the zoom meeting transcription", + Type: "custom_zoom_transcript", + Props: model.StringInterface{ + "captions": []any{map[string]any{"file_id": "file-id"}}, + }, + FileIds: []string{"file-id"}, + }, nil) + p.SetAPI(api) + + requestBodyBytes, _ := json.Marshal(map[string]any{ + "payload": map[string]any{ + "object": map[string]any{ + "id": 123, + "uuid": "321", + "recording_files": []map[string]any{ + { + "recording_type": "audio_transcript", + "download_url": httpServer.URL + "/test", + }, + }, + }, + }, + "event": "recording.transcript_completed", + "download_token": "test-token", + }) + requestBody := string(requestBodyBytes) + + ts := "1660149894817" + h := hmac.New(sha256.New, []byte(testConfig.ZoomWebhookSecret)) + _, _ = h.Write([]byte("v0:" + ts + ":" + requestBody)) + signature := "v0=" + hex.EncodeToString(h.Sum(nil)) + + w := httptest.NewRecorder() + reqBody := io.NopCloser(bytes.NewBufferString(requestBody)) + request := httptest.NewRequest("POST", "/webhook?secret=webhooksecret", reqBody) + request.Header.Add("Content-Type", "application/json") + request.Header.Add("x-zm-signature", signature) + request.Header.Add("x-zm-request-timestamp", ts) + + p.ServeHTTP(&plugin.Context{}, w, request) + body, _ := io.ReadAll(w.Result().Body) + t.Log(string(body)) + + api.AssertExpectations(t) +} + +func TestWebhookHandleRecordingCompleted(t *testing.T) { + api := &plugintest.API{} + p := Plugin{} + p.setConfiguration(testConfig) + + httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Write([]byte(r.URL.Path)) + })) + defer httpServer.Close() + + oldDefaultClient := http.DefaultClient + http.DefaultClient = httpServer.Client() + defer func() { + http.DefaultClient = oldDefaultClient + }() + + api.On("GetLicense").Return(nil) + api.On("GetPost", "post-id").Return(&model.Post{Id: "post-id", ChannelId: "channel-id"}, nil) + api.On("KVGet", "post_meeting_321").Return([]byte("post-id"), nil) + api.On("UploadFile", []byte("/chat_file"), "channel-id", "Chat-history.txt").Return(&model.FileInfo{Id: "file-id"}, nil) + api.On("CreatePost", &model.Post{ + ChannelId: "channel-id", + RootId: "post-id", + Message: "Here's the zoom meeting recording:\n**Link:** [Meeting Recording]()\n**Password:** test-password", + Type: "custom_zoom_chat", + Props: model.StringInterface{ + "captions": []any{map[string]any{"file_id": "file-id"}}, + }, + FileIds: []string{"file-id"}, + }).Return(&model.Post{ + ChannelId: "channel-id", + RootId: "post-id", + Message: "Here's the zoom meeting recording:\n**Link:** [Meeting Recording]()\n**Password:** test-password", + Type: "custom_zoom_chat", + Props: model.StringInterface{ + "captions": []any{map[string]any{"file_id": "file-id"}}, + }, + FileIds: []string{"file-id"}, + }, nil) + p.SetAPI(api) + + now := time.Now() + requestBodyBytes, _ := json.Marshal(map[string]any{ + "payload": map[string]any{ + "object": map[string]any{ + "id": 123, + "uuid": "321", + "password": "test-password", + "recording_files": []map[string]any{ + { + "recording_start": now, + "recording_type": "chat_file", + "download_url": httpServer.URL + "/chat_file", + }, + { + "recording_start": now, + "recording_type": "shared_screen_with_speaker_view", + "download_url": httpServer.URL + "/recording_file", + "playURL": httpServer.URL + "/recording_url", + }, + }, + }, + }, + "event": "recording.completed", + "download_token": "test-token", + }) + requestBody := string(requestBodyBytes) + + ts := "1660149894817" + h := hmac.New(sha256.New, []byte(testConfig.ZoomWebhookSecret)) + _, _ = h.Write([]byte("v0:" + ts + ":" + requestBody)) + signature := "v0=" + hex.EncodeToString(h.Sum(nil)) + + w := httptest.NewRecorder() + reqBody := io.NopCloser(bytes.NewBufferString(requestBody)) + request := httptest.NewRequest("POST", "/webhook?secret=webhooksecret", reqBody) + request.Header.Add("Content-Type", "application/json") + request.Header.Add("x-zm-signature", signature) + request.Header.Add("x-zm-request-timestamp", ts) + + p.ServeHTTP(&plugin.Context{}, w, request) + body, _ := io.ReadAll(w.Result().Body) + t.Log(string(body)) + + api.AssertExpectations(t) +} From b67ed8249fb32db185e4a4dee3789816a4db3266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 17 May 2024 10:15:39 +0200 Subject: [PATCH 19/37] Fixing some linter errors --- server/command.go | 2 +- server/webhook_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/command.go b/server/command.go index 1685d41b..669d5afa 100644 --- a/server/command.go +++ b/server/command.go @@ -267,7 +267,7 @@ func (p *Plugin) runUnsubscribeCommand(user *model.User, extra *model.CommandArg _, err := p.getMeeting(user, meetingID) if err != nil { - return "Can not unsubscribe from meeting: meeting not found", errors.Wrap(err, "meeting not found") + return "Can not unsubscribe from meeting: meeting not accesible in zoom", errors.Wrap(err, "meeting not accesible in zoom") } if channelID, appErr := p.fetchChannelForMeeting(meetingID); appErr != nil || channelID == "" { diff --git a/server/webhook_test.go b/server/webhook_test.go index 7303f858..1f763167 100644 --- a/server/webhook_test.go +++ b/server/webhook_test.go @@ -122,7 +122,7 @@ func TestWebhookHandleTranscriptCompleted(t *testing.T) { httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) - w.Write([]byte(r.URL.Path)) + _, _ = w.Write([]byte(r.URL.Path)) })) defer httpServer.Close() @@ -201,7 +201,7 @@ func TestWebhookHandleRecordingCompleted(t *testing.T) { httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) - w.Write([]byte(r.URL.Path)) + _, _ = w.Write([]byte(r.URL.Path)) })) defer httpServer.Close() From 3b4d73dc07381e188ef4c9062ee93458cb1ae4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Thu, 23 May 2024 09:34:30 +0200 Subject: [PATCH 20/37] Addressing some PR review comments --- server/telemetry.go | 5 +++-- server/webhook.go | 2 +- webapp/src/components/post_type_transcription.tsx | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/server/telemetry.go b/server/telemetry.go index ca8013d5..40f0d5e5 100644 --- a/server/telemetry.go +++ b/server/telemetry.go @@ -4,8 +4,9 @@ const ( telemetryOauthModeOauth = "Oauth" telemetryOauthModeOauthAccountLevel = "Oauth Account Level" - telemetryStartSourceWebapp = "webapp" - telemetryStartSourceCommand = "command" + telemetryStartSourceWebapp = "webapp" + telemetryStartSourceCommand = "command" + telemetryStartSourceSubscribeWebhook = "subscribe-webhook" ) func (p *Plugin) TrackEvent(event string, properties map[string]interface{}) { diff --git a/server/webhook.go b/server/webhook.go index 19da6365..8c6623b6 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -108,7 +108,7 @@ func (p *Plugin) handleMeetingStarted(w http.ResponseWriter, r *http.Request, bo return } - p.trackMeetingStart(p.botUserID, telemetryStartSourceCommand) + p.trackMeetingStart(p.botUserID, telemetryStartSourceSubscribeWebhook) p.trackMeetingType(p.botUserID, false) } diff --git a/webapp/src/components/post_type_transcription.tsx b/webapp/src/components/post_type_transcription.tsx index 39ebbb94..0add0206 100644 --- a/webapp/src/components/post_type_transcription.tsx +++ b/webapp/src/components/post_type_transcription.tsx @@ -17,7 +17,7 @@ const useAIAvailable = () => { const useCallsPostButtonClicked = () => { return useSelector((state: any) => { const aiPluginState = state['plugins-' + aiPluginID]; - return aiPluginState?.callsPostButtonClickedTranscription; + return aiPluginState?.callsPostButtonClickedTranscription as ((post: Post) => void) | undefined; }); }; @@ -73,7 +73,7 @@ export const PostTypeTranscription = (props: Props) => { )} From 5efacfd8d30af6cc711921e16444268ab6af9c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 24 May 2024 15:16:16 +0200 Subject: [PATCH 21/37] Fixing types --- webapp/src/components/post_type_transcription.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/components/post_type_transcription.tsx b/webapp/src/components/post_type_transcription.tsx index 0add0206..91d7b93e 100644 --- a/webapp/src/components/post_type_transcription.tsx +++ b/webapp/src/components/post_type_transcription.tsx @@ -17,7 +17,7 @@ const useAIAvailable = () => { const useCallsPostButtonClicked = () => { return useSelector((state: any) => { const aiPluginState = state['plugins-' + aiPluginID]; - return aiPluginState?.callsPostButtonClickedTranscription as ((post: Post) => void) | undefined; + return aiPluginState?.callsPostButtonClickedTranscription; }); }; From dd108cf862f3baacb4de2e52f27f150aeeaa7c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 12 Jul 2024 18:33:26 +0200 Subject: [PATCH 22/37] Adding the meeting UUID --- server/command.go | 12 ++++-------- server/http.go | 35 ++++++++++++----------------------- 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/server/command.go b/server/command.go index 729f8db7..ad145c9c 100644 --- a/server/command.go +++ b/server/command.go @@ -160,6 +160,7 @@ func (p *Plugin) runStartCommand(args *model.CommandArgs, user *model.User, topi } var meetingID int + var meetingUUID string var createMeetingErr error userPMISettingPref, err := p.getPMISettingData(user.Id) @@ -177,25 +178,20 @@ func (p *Plugin) runStartCommand(args *model.CommandArgs, user *model.User, topi meetingID = zoomUser.Pmi if meetingID <= 0 { - meetingID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, args.ChannelId, topic) + meetingID, meetingUUID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, args.ChannelId, topic) if createMeetingErr != nil { return "", errors.Wrap(createMeetingErr, "failed to create the meeting") } p.sendEnableZoomPMISettingMessage(user.Id, args.ChannelId, args.RootId) } default: - meetingID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, args.ChannelId, topic) + meetingID, meetingUUID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, args.ChannelId, topic) if createMeetingErr != nil { return "", errors.Wrap(createMeetingErr, "failed to create the meeting") } } - meeting, err := p.getMeeting(user, meetingID) - if err != nil { - return "", errors.Wrap(err, "failed to get the meeting") - } - - if postMeetingErr := p.postMeeting(user, meetingID, meeting.UUID, args.ChannelId, args.RootId, topic); postMeetingErr != nil { + if postMeetingErr := p.postMeeting(user, meetingID, meetingUUID, args.ChannelId, args.RootId, topic); postMeetingErr != nil { return "", postMeetingErr } diff --git a/server/http.go b/server/http.go index 91da05ff..fb295776 100644 --- a/server/http.go +++ b/server/http.go @@ -158,6 +158,7 @@ func (p *Plugin) startMeeting(action, userID, channelID, rootID string) { } var meetingID int + var meetingUUID string var createMeetingErr error createMeetingWithPMI := false if action == usePersonalMeetingID { @@ -165,7 +166,7 @@ func (p *Plugin) startMeeting(action, userID, channelID, rootID string) { meetingID = zoomUser.Pmi if meetingID <= 0 { - meetingID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, channelID, defaultMeetingTopic) + meetingID, meetingUUID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, channelID, defaultMeetingTopic) if createMeetingErr != nil { p.API.LogWarn("failed to create the meeting", "Error", createMeetingErr.Error()) return @@ -173,20 +174,14 @@ func (p *Plugin) startMeeting(action, userID, channelID, rootID string) { p.sendEnableZoomPMISettingMessage(userID, channelID, rootID) } } else { - meetingID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, channelID, defaultMeetingTopic) + meetingID, meetingUUID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, channelID, defaultMeetingTopic) if createMeetingErr != nil { p.API.LogWarn("failed to create the meeting", "Error", createMeetingErr.Error()) return } } - meeting, err := p.getMeeting(user, meetingID) - if err != nil { - p.API.LogWarn("failed to get the meeting", "Error", err.Error()) - return - } - - if postMeetingErr := p.postMeeting(user, meetingID, meeting.UUID, channelID, rootID, defaultMeetingTopic); postMeetingErr != nil { + if postMeetingErr := p.postMeeting(user, meetingID, meetingUUID, channelID, rootID, defaultMeetingTopic); postMeetingErr != nil { p.API.LogWarn("failed to post the meeting", "Error", postMeetingErr.Error()) return } @@ -594,20 +589,20 @@ func (p *Plugin) handleStartMeeting(w http.ResponseWriter, r *http.Request) { } } -func (p *Plugin) createMeetingWithoutPMI(user *model.User, zoomUser *zoom.User, channelID, topic string) (int, error) { +func (p *Plugin) createMeetingWithoutPMI(user *model.User, zoomUser *zoom.User, channelID, topic string) (int, string, error) { client, _, err := p.getActiveClient(user) if err != nil { p.API.LogWarn("Error getting the client", "Error", err.Error()) - return -1, err + return -1, "", err } meeting, err := client.CreateMeeting(zoomUser, topic) if err != nil { p.API.LogWarn("Error creating the meeting", "Error", err.Error()) - return -1, err + return -1, "", err } - return meeting.ID, nil + return meeting.ID, meeting.UUID, nil } func (p *Plugin) getMeeting(user *model.User, meetingID int) (*zoom.Meeting, error) { @@ -888,6 +883,7 @@ func (p *Plugin) slackAttachmentToUpdatePMI(currentValue, channelID string) *mod func (p *Plugin) handleMeetingCreation(channelID, rootID, topic string, user *model.User, zoomUser *zoom.User) (string, error) { var meetingID int + var meetingUUID string var createMeetingErr error userPMISettingPref, err := p.getPMISettingData(user.Id) if err != nil { @@ -904,27 +900,20 @@ func (p *Plugin) handleMeetingCreation(channelID, rootID, topic string, user *mo meetingID = zoomUser.Pmi if meetingID <= 0 { - meetingID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, channelID, topic) + meetingID, meetingUUID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, channelID, topic) if createMeetingErr != nil { return "", createMeetingErr } p.sendEnableZoomPMISettingMessage(user.Id, channelID, rootID) } default: - meetingID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, channelID, topic) + meetingID, meetingUUID, createMeetingErr = p.createMeetingWithoutPMI(user, zoomUser, channelID, topic) if createMeetingErr != nil { return "", createMeetingErr } } - meeting, err := p.getMeeting(user, meetingID) - if err != nil { - p.API.LogWarn("failed to get the meeting", "Error", err.Error()) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - if postMeetingErr := p.postMeeting(user, meetingID, meeting.UUID, channelID, rootID, topic); postMeetingErr != nil { + if postMeetingErr := p.postMeeting(user, meetingID, meetingUUID, channelID, rootID, topic); postMeetingErr != nil { return "", createMeetingErr } From e6b0a5059b8d2f4bbc4272a4ab6d3e8faf300076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 12 Jul 2024 18:52:14 +0200 Subject: [PATCH 23/37] Merging master and fixed problems related to the merge --- server/store.go | 6 +++--- server/webhook.go | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/server/store.go b/server/store.go index 77d1cc1f..c0301d9c 100644 --- a/server/store.go +++ b/server/store.go @@ -143,17 +143,17 @@ func (p *Plugin) storeMeetingPostID(meetingUUID string, postID string) *model.Ap func (p *Plugin) fetchMeetingPostID(meetingUUID string) (string, error) { key := fmt.Sprintf("%v%v", postMeetingKey, meetingUUID) - var postID string + var postID []byte if err := p.client.KV.Get(key, &postID); err != nil { p.client.Log.Debug("Could not get meeting post from KVStore", "error", err.Error()) return "", err } - if postID == "" { + if string(postID) == "" { return "", errors.New("stored meeting post ID not found") } - return postID, nil + return string(postID), nil } func (p *Plugin) storeChannelForMeeting(meetingID int, channelID string) error { diff --git a/server/webhook.go b/server/webhook.go index a760e214..6c0bd6ee 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -248,14 +248,14 @@ func (p *Plugin) handleTranscriptCompleted(w http.ResponseWriter, r *http.Reques } meetingPostID := webhook.Payload.Object.UUID - postID, appErr := p.fetchMeetingPostID(meetingPostID) - if appErr != nil { + postID, err := p.fetchMeetingPostID(meetingPostID) + if err != nil { return } - post, appErr := p.API.GetPost(postID) - if appErr != nil { - p.API.LogWarn("Could not get meeting post by id", "err", appErr) + post, err := p.client.Post.GetPost(postID) + if err != nil { + p.API.LogWarn("Could not get meeting post by id", "err", err) return } @@ -288,14 +288,14 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request } meetingPostID := webhook.Payload.Object.UUID - postID, appErr := p.fetchMeetingPostID(meetingPostID) - if appErr != nil { + postID, err := p.fetchMeetingPostID(meetingPostID) + if err != nil { return } - post, appErr := p.API.GetPost(postID) - if appErr != nil { - p.API.LogWarn("Could not get meeting post by id", "err", appErr) + post, err := p.client.Post.GetPost(postID) + if err != nil { + p.API.LogWarn("Could not get meeting post by id", "err", err) return } @@ -353,7 +353,7 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request } } if newPost.Message != "" { - _, appErr = p.API.CreatePost(newPost) + _, appErr := p.API.CreatePost(newPost) if appErr != nil { p.API.LogWarn("Could not update the post", "err", appErr) return From d75b8a573bf8244a21c242bf9b01e966264f05cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 12 Jul 2024 20:29:46 +0200 Subject: [PATCH 24/37] Fixing a crash on subscription --- server/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/store.go b/server/store.go index c0301d9c..28f3831a 100644 --- a/server/store.go +++ b/server/store.go @@ -159,7 +159,7 @@ func (p *Plugin) fetchMeetingPostID(meetingUUID string) (string, error) { func (p *Plugin) storeChannelForMeeting(meetingID int, channelID string) error { key := fmt.Sprintf("%v%v", meetingChannelKey, meetingID) bytes := []byte(channelID) - _, err := p.client.KV.Set(key, bytes, nil) + _, err := p.client.KV.Set(key, bytes) return err } From 5c9a13a20a6bebaf57234a91187a9af67aa45198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 12 Jul 2024 20:53:05 +0200 Subject: [PATCH 25/37] Fixing the alteration on the length after receiving transcriptions/recordings --- server/webhook.go | 2 ++ webapp/src/components/post_type_zoom/post_type_zoom.jsx | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/server/webhook.go b/server/webhook.go index 6c0bd6ee..23f8de7c 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -134,6 +134,7 @@ func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body } start := time.Unix(0, post.CreateAt*int64(time.Millisecond)) + end := model.GetMillis() length := int(math.Ceil(float64((model.GetMillis()-post.CreateAt)/1000) / 60)) startText := start.Format("Mon Jan 2 15:04:05 -0700 MST 2006") topic, ok := post.Props["meeting_topic"].(string) @@ -159,6 +160,7 @@ func (p *Plugin) handleMeetingEnded(w http.ResponseWriter, r *http.Request, body post.Message = "The meeting has ended." post.Props["meeting_status"] = zoom.WebhookStatusEnded + post.Props["meeting_end_time"] = end post.Props["attachments"] = []*model.SlackAttachment{&slackAttachment} if err = p.client.Post.UpdatePost(post); err != nil { diff --git a/webapp/src/components/post_type_zoom/post_type_zoom.jsx b/webapp/src/components/post_type_zoom/post_type_zoom.jsx index 4850f205..b7d5ad14 100644 --- a/webapp/src/components/post_type_zoom/post_type_zoom.jsx +++ b/webapp/src/components/post_type_zoom/post_type_zoom.jsx @@ -152,7 +152,8 @@ export default class PostTypeZoom extends React.PureComponent { const startDate = new Date(post.create_at); const start = formatDate(startDate); - const length = Math.ceil((new Date(post.update_at) - startDate) / 1000 / 60); + const end = props.meeting_end_time || post.update_at + const length = Math.ceil((new Date(end) - startDate) / 1000 / 60); content = (
From d3067af2d957382de91daabcf5681d8ff326cabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Sat, 11 Jan 2025 07:35:55 +0100 Subject: [PATCH 26/37] Fixing linter error --- webapp/src/components/post_type_zoom/post_type_zoom.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/components/post_type_zoom/post_type_zoom.jsx b/webapp/src/components/post_type_zoom/post_type_zoom.jsx index b7d5ad14..679c3ce9 100644 --- a/webapp/src/components/post_type_zoom/post_type_zoom.jsx +++ b/webapp/src/components/post_type_zoom/post_type_zoom.jsx @@ -152,7 +152,7 @@ export default class PostTypeZoom extends React.PureComponent { const startDate = new Date(post.create_at); const start = formatDate(startDate); - const end = props.meeting_end_time || post.update_at + const end = props.meeting_end_time || post.update_at; const length = Math.ceil((new Date(end) - startDate) / 1000 / 60); content = ( From fc9d542647247a7495e29753fb926f0987ad77de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino=20=28aider=29?= Date: Sat, 11 Jan 2025 07:41:06 +0100 Subject: [PATCH 27/37] fix: Add missing mock expectation for KVGet in test case --- server/plugin_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/plugin_test.go b/server/plugin_test.go index 83a5e429..b8fb43c2 100644 --- a/server/plugin_test.go +++ b/server/plugin_test.go @@ -131,6 +131,7 @@ func TestPlugin(t *testing.T) { api.On("KVGet", "mmi_botid").Return([]byte(botUserID), nil) api.On("KVGet", "zoomtoken_theuserid").Return(userInfo, nil) + api.On("KVGet", "meeting_channel_234").Return([]byte("thechannelid"), nil) api.On("SendEphemeralPost", "theuserid", mock.AnythingOfType("*model.Post")).Return(nil) From 191ef217b97075773e047b7586399c7f4f1f65a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino=20=28aider=29?= Date: Sat, 11 Jan 2025 07:41:40 +0100 Subject: [PATCH 28/37] fix: Add missing mock expectation for GetUser in webhook test --- server/plugin_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/plugin_test.go b/server/plugin_test.go index b8fb43c2..b95422a2 100644 --- a/server/plugin_test.go +++ b/server/plugin_test.go @@ -132,6 +132,9 @@ func TestPlugin(t *testing.T) { api.On("KVGet", "mmi_botid").Return([]byte(botUserID), nil) api.On("KVGet", "zoomtoken_theuserid").Return(userInfo, nil) api.On("KVGet", "meeting_channel_234").Return([]byte("thechannelid"), nil) + api.On("GetUser", botUserID).Return(&model.User{ + Id: botUserID, + }, nil) api.On("SendEphemeralPost", "theuserid", mock.AnythingOfType("*model.Post")).Return(nil) From 0af0204f77912214a528105baa0455a00a8b7371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino=20=28aider=29?= Date: Sat, 11 Jan 2025 07:42:12 +0100 Subject: [PATCH 29/37] fix: Add missing mock expectation for bot user's Zoom token --- server/plugin_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/plugin_test.go b/server/plugin_test.go index b95422a2..007013c0 100644 --- a/server/plugin_test.go +++ b/server/plugin_test.go @@ -132,6 +132,7 @@ func TestPlugin(t *testing.T) { api.On("KVGet", "mmi_botid").Return([]byte(botUserID), nil) api.On("KVGet", "zoomtoken_theuserid").Return(userInfo, nil) api.On("KVGet", "meeting_channel_234").Return([]byte("thechannelid"), nil) + api.On("KVGet", "zoomtoken_"+botUserID).Return(userInfo, nil) api.On("GetUser", botUserID).Return(&model.User{ Id: botUserID, }, nil) From d3f70c413834da3b72bae58e4e4c69f999592420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino=20=28aider=29?= Date: Sat, 11 Jan 2025 07:42:44 +0100 Subject: [PATCH 30/37] fix: Add missing KVSetWithExpiry mock for meeting post ID test --- server/plugin_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/plugin_test.go b/server/plugin_test.go index 007013c0..7a2e82ec 100644 --- a/server/plugin_test.go +++ b/server/plugin_test.go @@ -136,6 +136,7 @@ func TestPlugin(t *testing.T) { api.On("GetUser", botUserID).Return(&model.User{ Id: botUserID, }, nil) + api.On("KVSetWithExpiry", "post_meeting_234", mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil) api.On("SendEphemeralPost", "theuserid", mock.AnythingOfType("*model.Post")).Return(nil) From 70f1af5874f96d977019b0cdd6815973fffef339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino=20=28aider=29?= Date: Sat, 11 Jan 2025 07:43:15 +0100 Subject: [PATCH 31/37] fix: Add missing mock expectation for KVSetWithExpiry in test --- server/plugin_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/plugin_test.go b/server/plugin_test.go index 7a2e82ec..7035e2d8 100644 --- a/server/plugin_test.go +++ b/server/plugin_test.go @@ -137,6 +137,7 @@ func TestPlugin(t *testing.T) { Id: botUserID, }, nil) api.On("KVSetWithExpiry", "post_meeting_234", mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil) + api.On("KVSetWithExpiry", "post_meeting_", mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil) api.On("SendEphemeralPost", "theuserid", mock.AnythingOfType("*model.Post")).Return(nil) From 5fe64f00a48ad3db8e369df656ee514eb17b20ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino=20=28aider=29?= Date: Sat, 11 Jan 2025 07:43:46 +0100 Subject: [PATCH 32/37] test: Add mock expectation for PublishWebSocketEvent in test case --- server/plugin_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/plugin_test.go b/server/plugin_test.go index 7035e2d8..d03bb410 100644 --- a/server/plugin_test.go +++ b/server/plugin_test.go @@ -138,6 +138,7 @@ func TestPlugin(t *testing.T) { }, nil) api.On("KVSetWithExpiry", "post_meeting_234", mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil) api.On("KVSetWithExpiry", "post_meeting_", mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil) + api.On("PublishWebSocketEvent", "meeting_started", map[string]interface{}{"meeting_url": "https://zoom.us/j/234"}, &model.WebsocketBroadcast{UserId: botUserID}).Return() api.On("SendEphemeralPost", "theuserid", mock.AnythingOfType("*model.Post")).Return(nil) From 9dc2a3c11c3be25a678f6e516780849d49fdcb58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino=20=28aider=29?= Date: Sat, 11 Jan 2025 07:44:32 +0100 Subject: [PATCH 33/37] fix: Initialize plugin client in webhook test to resolve nil pointer dereference --- server/webhook_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/webhook_test.go b/server/webhook_test.go index 6e5e311a..4cf3ecec 100644 --- a/server/webhook_test.go +++ b/server/webhook_test.go @@ -138,6 +138,7 @@ func TestWebhookHandleTranscriptCompleted(t *testing.T) { api.On("GetPost", "post-id").Return(&model.Post{Id: "post-id", ChannelId: "channel-id"}, nil) api.On("KVGet", "post_meeting_321").Return([]byte("post-id"), nil) api.On("UploadFile", []byte("/test"), "channel-id", "transcription.txt").Return(&model.FileInfo{Id: "file-id"}, nil) + p.client = pluginapi.NewClient(api, nil) api.On("CreatePost", &model.Post{ ChannelId: "channel-id", RootId: "post-id", From c90d235bedd1e29c0f8d2796a2f9c6585f8a77b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino=20=28aider=29?= Date: Sat, 11 Jan 2025 07:45:08 +0100 Subject: [PATCH 34/37] fix: Initialize plugin client in TestWebhookHandleRecordingCompleted test --- server/webhook_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/webhook_test.go b/server/webhook_test.go index 4cf3ecec..134b8504 100644 --- a/server/webhook_test.go +++ b/server/webhook_test.go @@ -218,6 +218,7 @@ func TestWebhookHandleRecordingCompleted(t *testing.T) { api.On("GetPost", "post-id").Return(&model.Post{Id: "post-id", ChannelId: "channel-id"}, nil) api.On("KVGet", "post_meeting_321").Return([]byte("post-id"), nil) api.On("UploadFile", []byte("/chat_file"), "channel-id", "Chat-history.txt").Return(&model.FileInfo{Id: "file-id"}, nil) + p.client = pluginapi.NewClient(api, nil) api.On("CreatePost", &model.Post{ ChannelId: "channel-id", RootId: "post-id", From fb6ae2ff78e2004c23353a2b07c1ca92594731e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Sat, 11 Jan 2025 07:56:09 +0100 Subject: [PATCH 35/37] Fixing tests --- server/plugin_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/plugin_test.go b/server/plugin_test.go index d03bb410..b0ed872c 100644 --- a/server/plugin_test.go +++ b/server/plugin_test.go @@ -68,7 +68,7 @@ func TestPlugin(t *testing.T) { endedPayload := `{"event": "meeting.ended", "payload": {"object": {"id": "234", "uuid": "234"}}}` validStoppedWebhookRequest := httptest.NewRequest("POST", "/webhook?secret=thewebhooksecret", strings.NewReader(endedPayload)) - validStartedWebhookRequest := httptest.NewRequest("POST", "/webhook?secret=thewebhooksecret", strings.NewReader(`{"event": "meeting.started", "payload": {"object": {"id": "234"}}}`)) + validStartedWebhookRequest := httptest.NewRequest("POST", "/webhook?secret=thewebhooksecret", strings.NewReader(`{"event": "meeting.started", "payload": {"object": {"id": "234", "uuid": "234"}}}`)) noSecretWebhookRequest := httptest.NewRequest("POST", "/webhook", strings.NewReader(endedPayload)) @@ -136,8 +136,6 @@ func TestPlugin(t *testing.T) { api.On("GetUser", botUserID).Return(&model.User{ Id: botUserID, }, nil) - api.On("KVSetWithExpiry", "post_meeting_234", mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil) - api.On("KVSetWithExpiry", "post_meeting_", mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil) api.On("PublishWebSocketEvent", "meeting_started", map[string]interface{}{"meeting_url": "https://zoom.us/j/234"}, &model.WebsocketBroadcast{UserId: botUserID}).Return() api.On("SendEphemeralPost", "theuserid", mock.AnythingOfType("*model.Post")).Return(nil) From e9ea52a8a64a290be2b71f22b54c4551dd9613d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Sat, 11 Jan 2025 08:03:04 +0100 Subject: [PATCH 36/37] Fixing linter error --- server/webhook.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/webhook.go b/server/webhook.go index 23f8de7c..f942c352 100644 --- a/server/webhook.go +++ b/server/webhook.go @@ -20,6 +20,8 @@ import ( "github.com/mattermost/mattermost-plugin-zoom/server/zoom" ) +const bearerString = "Bearer " + func (p *Plugin) handleWebhook(w http.ResponseWriter, r *http.Request) { if !p.verifyMattermostWebhookSecret(r) { p.API.LogWarn("Could not verify Mattermost webhook secret") @@ -181,7 +183,7 @@ func (p *Plugin) handleTranscript(recording zoom.RecordingFile, postID, channelI p.API.LogWarn("Unable to get the transcription", "err", err) return err } - request.Header.Set("Authorization", "Bearer "+downloadToken) + request.Header.Set("Authorization", bearerString+downloadToken) retries := 5 var response *http.Response @@ -328,7 +330,7 @@ func (p *Plugin) handleRecordingCompleted(w http.ResponseWriter, r *http.Request p.API.LogWarn("Unable to get the chat", "err", err) return } - request.Header.Set("Authorization", "Bearer "+webhook.DownloadToken) + request.Header.Set("Authorization", bearerString+webhook.DownloadToken) response, err := http.DefaultClient.Do(request) if err != nil { p.API.LogWarn("Unable to get the chat", "err", err) From a35591eb8eeabdaee86d5b8cf90b9dbce3c8b5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino=20=28aider=29?= Date: Sat, 11 Jan 2025 08:08:27 +0100 Subject: [PATCH 37/37] test: Add tests for `handleMeetingStarted` webhook functionality --- server/webhook_test.go | 91 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/server/webhook_test.go b/server/webhook_test.go index 134b8504..05e9b409 100644 --- a/server/webhook_test.go +++ b/server/webhook_test.go @@ -12,12 +12,14 @@ import ( "testing" "time" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/plugin" "github.com/mattermost/mattermost/server/public/plugin/plugintest" "github.com/mattermost/mattermost/server/public/pluginapi" + "github.com/mattermost/mattermost/server/public/pluginapi/experimental/telemetry" "github.com/mattermost/mattermost-plugin-zoom/server/zoom" ) @@ -59,6 +61,95 @@ func TestWebhookValidate(t *testing.T) { require.Equal(t, "2a41c3138d2187a756c51428f78d192e9b88dcf44dd62d1b081ace4ec2241e0a", out.EncryptedToken) } +func TestHandleMeetingStarted(t *testing.T) { + p := Plugin{} + p.setConfiguration(testConfig) + + t.Run("successful meeting start", func(t *testing.T) { + api := &plugintest.API{} + api.On("GetLicense").Return(nil) + api.On("KVGet", "meeting_channel_123").Return([]byte("channel-id"), nil) + api.On("GetUser", "").Return(&model.User{Id: "user-id"}, nil) + api.On("KVGet", "zoomtoken_user-id").Return(nil, &model.AppError{}) + api.On("LogWarn", "could not get the active Zoom client", "error", "could not fetch Zoom OAuth info: must connect user account to Zoom first").Return() + api.On("HasPermissionToChannel", "user-id", "channel-id", mock.AnythingOfType("*model.Permission")).Return(true) + api.On("KVSetWithExpiry", "post_meeting_abc", []byte{}, int64(86400)).Return(nil) + api.On("PublishWebSocketEvent", "meeting_started", map[string]interface{}{"meeting_url": "https://zoom.us/j/123"}, mock.AnythingOfType("*model.WebsocketBroadcast")).Return() + api.On("CreatePost", mock.AnythingOfType("*model.Post")).Return(&model.Post{}, nil) + p.SetAPI(api) + p.client = pluginapi.NewClient(api, nil) + p.botUserID = "" + p.tracker = telemetry.NewTracker(nil, "", "", "", "", "", telemetry.NewTrackerConfig(nil), nil) + + requestBody := `{"payload":{"object": {"id": "123", "uuid": "abc", "topic": "test meeting"}},"event":"meeting.started"}` + w := httptest.NewRecorder() + reqBody := io.NopCloser(bytes.NewBufferString(requestBody)) + request := httptest.NewRequest("POST", "/webhook?secret=webhooksecret", reqBody) + request.Header.Add("Content-Type", "application/json") + + ts := "1660149894817" + h := hmac.New(sha256.New, []byte(testConfig.ZoomWebhookSecret)) + _, _ = h.Write([]byte("v0:" + ts + ":" + requestBody)) + signature := "v0=" + hex.EncodeToString(h.Sum(nil)) + + request.Header.Add("x-zm-signature", signature) + request.Header.Add("x-zm-request-timestamp", ts) + + p.ServeHTTP(&plugin.Context{}, w, request) + require.Equal(t, http.StatusOK, w.Result().StatusCode) + }) + + t.Run("invalid meeting ID", func(t *testing.T) { + api := &plugintest.API{} + api.On("GetLicense").Return(nil) + api.On("LogError", "Failed to get meeting ID", "err", "strconv.Atoi: parsing \"invalid\": invalid syntax").Return() + p.SetAPI(api) + + requestBody := `{"payload":{"object": {"id": "invalid", "uuid": "123-abc"}},"event":"meeting.started"}` + w := httptest.NewRecorder() + reqBody := io.NopCloser(bytes.NewBufferString(requestBody)) + request := httptest.NewRequest("POST", "/webhook?secret=webhooksecret", reqBody) + request.Header.Add("Content-Type", "application/json") + + ts := "1660149894817" + h := hmac.New(sha256.New, []byte(testConfig.ZoomWebhookSecret)) + _, _ = h.Write([]byte("v0:" + ts + ":" + requestBody)) + signature := "v0=" + hex.EncodeToString(h.Sum(nil)) + + request.Header.Add("x-zm-signature", signature) + request.Header.Add("x-zm-request-timestamp", ts) + + p.ServeHTTP(&plugin.Context{}, w, request) + require.Equal(t, http.StatusBadRequest, w.Result().StatusCode) + }) + + t.Run("channel not found", func(t *testing.T) { + api := &plugintest.API{} + api.On("GetLicense").Return(nil) + api.On("KVGet", "meeting_channel_123").Return(nil, &model.AppError{}) + api.On("LogDebug", "Could not get channel meeting from KVStore", "error", "").Return() + api.On("KVSetWithExpiry", "post_meeting_123-abc", []byte{}, int64(86400)).Return(nil) + p.SetAPI(api) + + requestBody := `{"payload":{"object": {"id": "123", "uuid": "123-abc"}},"event":"meeting.started"}` + w := httptest.NewRecorder() + reqBody := io.NopCloser(bytes.NewBufferString(requestBody)) + request := httptest.NewRequest("POST", "/webhook?secret=webhooksecret", reqBody) + request.Header.Add("Content-Type", "application/json") + + ts := "1660149894817" + h := hmac.New(sha256.New, []byte(testConfig.ZoomWebhookSecret)) + _, _ = h.Write([]byte("v0:" + ts + ":" + requestBody)) + signature := "v0=" + hex.EncodeToString(h.Sum(nil)) + + request.Header.Add("x-zm-signature", signature) + request.Header.Add("x-zm-request-timestamp", ts) + + p.ServeHTTP(&plugin.Context{}, w, request) + require.Equal(t, http.StatusOK, w.Result().StatusCode) + }) +} + func TestWebhookVerifySignature(t *testing.T) { api := &plugintest.API{} p := Plugin{}