From 4702ee7237dc1c233a3a0e04681a15dd3db973fa Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Mon, 12 Jan 2026 14:37:46 -0300 Subject: [PATCH 01/61] merge feat.voip-lib --- android/app/src/main/AndroidManifest.xml | 24 + app/definitions/Voip.ts | 5 + app/lib/constants/defaultSettings.ts | 6 + app/lib/services/voip/MediaCallLogger.ts | 21 + app/lib/services/voip/MediaSessionInstance.ts | 159 +++++ app/lib/services/voip/MediaSessionStore.ts | 105 ++++ .../services/voip/parseStringToIceServers.ts | 24 + app/lib/store/index.ts | 4 +- app/sagas/login.js | 69 ++- ios/Podfile.lock | 16 + ios/RocketChatRN.xcodeproj/project.pbxproj | 264 ++++----- package.json | 3 + patches/@rocket.chat+sdk+1.3.3-mobile.patch | 15 + patches/react-native-callkeep+4.3.16.patch | 544 ++++++++++++++++++ yarn.lock | 110 ++-- 15 files changed, 1195 insertions(+), 174 deletions(-) create mode 100644 app/definitions/Voip.ts create mode 100644 app/lib/services/voip/MediaCallLogger.ts create mode 100644 app/lib/services/voip/MediaSessionInstance.ts create mode 100644 app/lib/services/voip/MediaSessionStore.ts create mode 100644 app/lib/services/voip/parseStringToIceServers.ts create mode 100644 patches/@rocket.chat+sdk+1.3.3-mobile.patch create mode 100644 patches/react-native-callkeep+4.3.16.patch diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 4fb70ab1a89..acb0a58bde9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -13,6 +13,17 @@ + + + + + + + + + + + @@ -104,6 +115,19 @@ + + + + + + + + diff --git a/app/definitions/Voip.ts b/app/definitions/Voip.ts new file mode 100644 index 00000000000..1f13d16e56f --- /dev/null +++ b/app/definitions/Voip.ts @@ -0,0 +1,5 @@ +export type IceServer = { + urls: string; + username?: string; + credential?: string; +}; diff --git a/app/lib/constants/defaultSettings.ts b/app/lib/constants/defaultSettings.ts index aac112fd0f2..be63b56c559 100644 --- a/app/lib/constants/defaultSettings.ts +++ b/app/lib/constants/defaultSettings.ts @@ -306,5 +306,11 @@ export const defaultSettings = { Federation_Matrix_enabled: { type: 'valueAsBoolean' }, + VoIP_TeamCollab_Ice_Servers: { + type: 'valueAsString' + }, + VoIP_TeamCollab_Ice_Gathering_Timeout: { + type: 'valueAsNumber' + }, ...deprecatedSettings } as const; diff --git a/app/lib/services/voip/MediaCallLogger.ts b/app/lib/services/voip/MediaCallLogger.ts new file mode 100644 index 00000000000..0d9444d7f7a --- /dev/null +++ b/app/lib/services/voip/MediaCallLogger.ts @@ -0,0 +1,21 @@ +import type { IMediaSignalLogger } from '@rocket.chat/media-signaling'; + +export class MediaCallLogger implements IMediaSignalLogger { + log(...args: unknown[]): void { + console.log(`[Media Call] ${JSON.stringify(args)}`); + } + + debug(...args: unknown[]): void { + if (__DEV__) { + console.log(`[Media Call Debug] ${JSON.stringify(args)}`); + } + } + + error(...args: unknown[]): void { + console.log(`[Media Call Error] ${JSON.stringify(args)}`); + } + + warn(...args: unknown[]): void { + console.log(`[Media Call Warning] ${JSON.stringify(args)}`); + } +} diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts new file mode 100644 index 00000000000..d4406da20ba --- /dev/null +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -0,0 +1,159 @@ +import { + MediaCallWebRTCProcessor, + type ClientMediaSignal, + type IClientMediaCall, + type MediaSignalingSession, + type WebRTCProcessorConfig +} from '@rocket.chat/media-signaling'; +import RNCallKeep from 'react-native-callkeep'; +import { registerGlobals } from 'react-native-webrtc'; + +import { mediaSessionStore } from './MediaSessionStore'; +import { store } from '../../store/auxStore'; +import sdk from '../sdk'; +import { parseStringToIceServers } from './parseStringToIceServers'; +import type { IceServer } from '../../../definitions/Voip'; +import type { IDDPMessage } from '../../../definitions/IDDPMessage'; + +class MediaSessionInstance { + private iceServers: IceServer[] = []; + private iceGatheringTimeout: number = 5000; + private mediaSignalListener: { stop: () => void } | null = null; + private mediaSignalsListener: { stop: () => void } | null = null; + private instance: MediaSignalingSession | null = null; + private storeTimeoutUnsubscribe: (() => void) | null = null; + private storeIceServersUnsubscribe: (() => void) | null = null; + + public init(userId: string): void { + this.stop(); + registerGlobals(); + this.configureRNCallKeep(); + this.configureIceServers(); + + mediaSessionStore.setWebRTCProcessorFactory( + (config: WebRTCProcessorConfig) => + new MediaCallWebRTCProcessor({ + ...config, + rtc: { ...config.rtc, iceServers: this.iceServers }, + iceGatheringTimeout: this.iceGatheringTimeout + }) + ); + mediaSessionStore.setSendSignalFn((signal: ClientMediaSignal) => { + sdk.methodCall('stream-notify-user', `${userId}/media-calls`, JSON.stringify(signal)); + }); + this.instance = mediaSessionStore.getInstance(userId); + mediaSessionStore.onChange(() => (this.instance = mediaSessionStore.getInstance(userId))); + + this.mediaSignalListener = sdk.onStreamData('stream-notify-user', (ddpMessage: IDDPMessage) => { + if (!this.instance) { + return; + } + const [, ev] = ddpMessage.fields.eventName.split('/'); + if (ev !== 'media-signal') { + return; + } + const signal = ddpMessage.fields.args[0]; + this.instance.processSignal(signal); + }); + + this.instance?.on('newCall', ({ call }: { call: IClientMediaCall }) => { + if (call && !call.hidden) { + call.emitter.on('stateChange', oldState => { + console.log(`📊 ${oldState} → ${call.state}`); + }); + + const displayName = call.contact.displayName || call.contact.username || 'Unknown'; + RNCallKeep.displayIncomingCall(call.callId, displayName, displayName, 'generic', false); + + call.emitter.on('ended', () => RNCallKeep.endCall(call.callId)); + } + }); + } + + private configureRNCallKeep() { + RNCallKeep.addEventListener('answerCall', async ({ callUUID }) => { + const mainCall = this.instance?.getMainCall(); + if (mainCall && mainCall.callId === callUUID) { + await mainCall.accept(); + RNCallKeep.setCurrentCallActive(mainCall.callId); + } else { + RNCallKeep.endCall(callUUID); + } + }); + + RNCallKeep.addEventListener('endCall', ({ callUUID }) => { + const mainCall = this.instance?.getMainCall(); + if (mainCall && mainCall.callId === callUUID) { + if (mainCall.state === 'ringing') { + mainCall.reject(); + } else { + mainCall.hangup(); + } + } + }); + + RNCallKeep.addEventListener('didPerformSetMutedCallAction', ({ muted, callUUID }) => { + const mainCall = this.instance?.getMainCall(); + if (mainCall && mainCall.callId === callUUID) { + mainCall.setMuted(muted); + } + }); + + RNCallKeep.addEventListener('didPerformDTMFAction', ({ digits }) => { + const mainCall = this.instance?.getMainCall(); + if (mainCall) { + mainCall.sendDTMF(digits); + } + }); + } + + private getIceServers() { + const iceServers = store.getState().settings.VoIP_TeamCollab_Ice_Servers as any; + return parseStringToIceServers(iceServers); + } + + private configureIceServers() { + this.iceServers = this.getIceServers(); + this.iceGatheringTimeout = store.getState().settings.VoIP_TeamCollab_Ice_Gathering_Timeout as number; + + this.storeTimeoutUnsubscribe = store.subscribe(() => { + const currentTimeout = store.getState().settings.VoIP_TeamCollab_Ice_Gathering_Timeout as number; + if (currentTimeout !== this.iceGatheringTimeout) { + this.iceGatheringTimeout = currentTimeout; + this.instance?.setIceGatheringTimeout(this.iceGatheringTimeout); + } + }); + + this.storeIceServersUnsubscribe = store.subscribe(() => { + const currentIceServers = this.getIceServers(); + if (currentIceServers !== this.iceServers) { + this.iceServers = currentIceServers; + // this.instance?.setIceServers(this.iceServers); + } + }); + } + + private stop() { + if (this.mediaSignalListener) { + this.mediaSignalListener.stop(); + } + if (this.mediaSignalsListener) { + this.mediaSignalsListener.stop(); + } + RNCallKeep.removeEventListener('answerCall'); + RNCallKeep.removeEventListener('endCall'); + RNCallKeep.removeEventListener('didPerformSetMutedCallAction'); + RNCallKeep.removeEventListener('didPerformDTMFAction'); + if (this.storeTimeoutUnsubscribe) { + this.storeTimeoutUnsubscribe(); + } + if (this.storeIceServersUnsubscribe) { + this.storeIceServersUnsubscribe(); + } + if (this.instance) { + this.instance.endSession(); + } + } +} + +export const mediaSessionInstance = new MediaSessionInstance(); diff --git a/app/lib/services/voip/MediaSessionStore.ts b/app/lib/services/voip/MediaSessionStore.ts new file mode 100644 index 00000000000..6f09cde2216 --- /dev/null +++ b/app/lib/services/voip/MediaSessionStore.ts @@ -0,0 +1,105 @@ +import { Emitter } from '@rocket.chat/emitter'; +import { MediaSignalingSession } from '@rocket.chat/media-signaling'; +import type { + MediaSignalTransport, + ClientMediaSignal, + WebRTCProcessorConfig, + MediaCallWebRTCProcessor +} from '@rocket.chat/media-signaling'; +import { mediaDevices } from 'react-native-webrtc'; +import BackgroundTimer from 'react-native-background-timer'; + +import { MediaCallLogger } from './MediaCallLogger'; + +type SignalTransport = MediaSignalTransport; + +const randomStringFactory = (): string => + Date.now().toString(36) + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); + +class MediaSessionStore extends Emitter<{ change: void }> { + private sessionInstance: MediaSignalingSession | null = null; + private sendSignalFn: SignalTransport | null = null; + private _webrtcProcessorFactory: ((config: WebRTCProcessorConfig) => MediaCallWebRTCProcessor) | null = null; + + private change() { + this.emit('change'); + } + + public onChange(callback: () => void) { + return this.on('change', callback); + } + + private webrtcProcessorFactory(config: WebRTCProcessorConfig): MediaCallWebRTCProcessor { + if (!this._webrtcProcessorFactory) { + throw new Error('WebRTC processor factory not set'); + } + return this._webrtcProcessorFactory(config); + } + + private sendSignal(signal: ClientMediaSignal) { + if (!this.sendSignalFn) { + throw new Error('Send signal function not set'); + } + return this.sendSignalFn(signal); + } + + private makeInstance(userId: string): MediaSignalingSession | null { + if (this.sessionInstance !== null) { + this.sessionInstance.endSession(); + this.sessionInstance = null; + } + + if (!this._webrtcProcessorFactory || !this.sendSignalFn) { + throw new Error('WebRTC processor factory and send signal function must be set'); + } + + this.sessionInstance = new MediaSignalingSession({ + userId, + transport: (signal: ClientMediaSignal) => this.sendSignal(signal), + processorFactories: { + webrtc: (config: WebRTCProcessorConfig) => this.webrtcProcessorFactory(config) + }, + mediaStreamFactory: (constraints: any) => mediaDevices.getUserMedia(constraints) as unknown as Promise, + randomStringFactory, + logger: new MediaCallLogger(), + timerProcessor: { + setInterval: (callback: () => void, interval: number) => BackgroundTimer.setInterval(callback, interval), + clearInterval: (interval: number) => BackgroundTimer.clearInterval(interval), + setTimeout: (callback: () => void, timeout: number) => BackgroundTimer.setTimeout(callback, timeout), + clearTimeout: (timeout: number) => BackgroundTimer.clearTimeout(timeout) + } + }); + + this.change(); + return this.sessionInstance; + } + + public getInstance(userId?: string): MediaSignalingSession | null { + if (!userId) { + throw new Error('User Id is required'); + } + + if (this.sessionInstance?.userId === userId) { + return this.sessionInstance; + } + + return this.makeInstance(userId); + } + + public setSendSignalFn(sendSignalFn: SignalTransport) { + this.sendSignalFn = sendSignalFn; + this.change(); + } + + public setWebRTCProcessorFactory(factory: (config: WebRTCProcessorConfig) => MediaCallWebRTCProcessor): void { + this._webrtcProcessorFactory = factory; + this.change(); + } + + public getCurrentInstance(): MediaSignalingSession | null { + return this.sessionInstance; + } +} + +// TODO: change name +export const mediaSessionStore = new MediaSessionStore(); diff --git a/app/lib/services/voip/parseStringToIceServers.ts b/app/lib/services/voip/parseStringToIceServers.ts new file mode 100644 index 00000000000..0a339d4a84d --- /dev/null +++ b/app/lib/services/voip/parseStringToIceServers.ts @@ -0,0 +1,24 @@ +import type { IceServer } from '../../../definitions/Voip'; + +export const parseStringToIceServer = (server: string): IceServer => { + const credentials = server.trim().split('@'); + const urls = credentials.pop() as string; + const [username, credential] = credentials.length === 1 ? credentials[0].split(':') : []; + + return { + urls, + ...(username && + credential && { + username: decodeURIComponent(username), + credential: decodeURIComponent(credential) + }) + }; +}; + +export const parseStringToIceServers = (string: string): IceServer[] => { + if (!string) { + return []; + } + const lines = string.trim() ? string.split(',') : []; + return lines.map(line => parseStringToIceServer(line)); +}; diff --git a/app/lib/store/index.ts b/app/lib/store/index.ts index 3ae917484ac..25011f0f648 100644 --- a/app/lib/store/index.ts +++ b/app/lib/store/index.ts @@ -18,8 +18,8 @@ if (__DEV__) { applyAppStateMiddleware(), applyInternetStateMiddleware(), applyMiddleware(reduxImmutableStateInvariant), - applyMiddleware(sagaMiddleware), - applyMiddleware(logger) + applyMiddleware(sagaMiddleware) + // applyMiddleware(logger) ); } else { sagaMiddleware = createSagaMiddleware(); diff --git a/app/sagas/login.js b/app/sagas/login.js index 00b79a37c3d..17eeae96473 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -2,6 +2,10 @@ import React from 'react'; import { call, cancel, delay, fork, put, race, select, take, takeLatest } from 'redux-saga/effects'; import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import { Q } from '@nozbe/watermelondb'; +import RNCallKeep from 'react-native-callkeep'; +import { PermissionsAndroid } from 'react-native'; +import BackgroundTimer from 'react-native-background-timer'; + import dayjs from '../lib/dayjs'; import * as types from '../actions/actionsTypes'; import { appStart } from '../actions/app'; @@ -31,14 +35,14 @@ import { getSlashCommands } from '../lib/methods/getSlashCommands'; import { getUserPresence, subscribeUsersPresence } from '../lib/methods/getUsersPresence'; import { logout, removeServerData, removeServerDatabase } from '../lib/methods/logout'; import { subscribeSettings } from '../lib/methods/getSettings'; -import { connect, loginWithPassword, login } from '../lib/services/connect'; +import { loginWithPassword, login } from '../lib/services/connect'; import { saveUserProfile, registerPushToken, getUsersRoles } from '../lib/services/restApi'; import { setUsersRoles } from '../actions/usersRoles'; import { getServerById } from '../lib/database/services/Server'; import appNavigation from '../lib/navigation/appNavigation'; import { showActionSheetRef } from '../containers/ActionSheet'; import { SupportedVersionsWarning } from '../containers/SupportedVersions'; -import { isIOS } from '../lib/methods/helpers'; +import { mediaSessionInstance } from '../lib/services/voip/MediaSessionInstance'; const getServer = state => state.server.server; const loginWithPasswordCall = args => loginWithPassword(args); @@ -58,7 +62,7 @@ const showSupportedVersionsWarning = function* showSupportedVersionsWarning(serv const serversDB = database.servers; yield serversDB.write(async () => { - await serverRecord.update((r) => { + await serverRecord.update(r => { r.supportedVersionsWarningAt = new Date(); }); }); @@ -105,7 +109,7 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE } // this is updating on every login just to save `updated_at` // keeping this server as the most recent on autocomplete order - await serverHistoryRecord.update((s) => { + await serverHistoryRecord.update(s => { s.username = result.username; if (iconURL) { s.iconURL = iconURL; @@ -223,6 +227,55 @@ const fetchUsersRoles = function* fetchRoomsFork() { } }; +function* initCallKeep() { + try { + const options = { + ios: { + appName: 'Rocket.Chat', + includesCallsInRecents: false + }, + android: { + alertTitle: 'Permissions required', + alertDescription: 'This application needs to access your phone accounts', + cancelButton: 'Cancel', + okButton: 'Ok', + imageName: 'phone_account_icon', + additionalPermissions: [ + PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE, + PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, + PermissionsAndroid.PERMISSIONS.CALL_PHONE + ], + // Required to get audio in background when using Android 11 + foregroundService: { + channelId: 'chat.rocket.reactnative', + channelName: 'Rocket.Chat', + notificationTitle: 'Voice call is running on background' + } + } + }; + + RNCallKeep.setup(options); + RNCallKeep.canMakeMultipleCalls(false); + + const start = Date.now(); + setInterval(() => { + console.log('Timer fired after', Date.now() - start, 'ms'); + }, 1000); + } catch (e) { + log(e); + } +} + +const startVoipFork = function* startVoipFork() { + try { + yield call(initCallKeep); + const userId = yield select(state => state.login.user.id); + mediaSessionInstance.init(userId); + } catch (e) { + log(e); + } +}; + const handleLoginSuccess = function* handleLoginSuccess({ user }) { try { getUserPresence(user.id); @@ -239,6 +292,8 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) { yield fork(fetchEnterpriseModulesFork, { user }); yield fork(subscribeSettingsFork); yield fork(fetchUsersRoles); + yield delay(1000); + yield fork(startVoipFork); setLanguage(user?.language); @@ -261,12 +316,12 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) { yield serversDB.write(async () => { try { const userRecord = await usersCollection.find(user.id); - await userRecord.update((record) => { + await userRecord.update(record => { record._raw = sanitizedRaw({ id: user.id, ...record._raw }, usersCollection.schema); Object.assign(record, u); }); } catch (e) { - await usersCollection.create((record) => { + await usersCollection.create(record => { record._raw = sanitizedRaw({ id: user.id }, usersCollection.schema); Object.assign(record, u); }); @@ -344,7 +399,7 @@ const handleSetUser = function* handleSetUser({ user }) { yield serversDB.write(async () => { try { const record = await userCollections.find(userId); - await record.update((userRecord) => { + await record.update(userRecord => { if ('avatarETag' in user) { userRecord.avatarETag = user.avatarETag; } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 99a6053f60c..848e26d5b2d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -215,6 +215,7 @@ PODS: - hermes-engine (0.79.4): - hermes-engine/Pre-built (= 0.79.4) - hermes-engine/Pre-built (0.79.4) + - JitsiWebRTC (124.0.2) - libavif/core (0.11.1) - libavif/libdav1d (0.11.1): - libavif/core @@ -1816,6 +1817,9 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - react-native-webrtc (124.0.7): + - JitsiWebRTC (~> 124.0.0) + - React-Core - react-native-webview (13.15.0): - DoubleConversion - glog @@ -2186,6 +2190,8 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - RNCallKeep (4.3.16): + - React - RNCAsyncStorage (1.22.3): - DoubleConversion - glog @@ -2704,6 +2710,7 @@ DEPENDENCIES: - react-native-restart (from `../node_modules/react-native-restart`) - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - "react-native-slider (from `../node_modules/@react-native-community/slider`)" + - react-native-webrtc (from `../node_modules/react-native-webrtc`) - react-native-webview (from `../node_modules/react-native-webview`) - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - React-oscompat (from `../node_modules/react-native/ReactCommon/oscompat`) @@ -2737,6 +2744,7 @@ DEPENDENCIES: - ReactCodegen (from `build/generated/ios`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - RNBootSplash (from `../node_modules/react-native-bootsplash`) + - RNCallKeep (from `../node_modules/react-native-callkeep`) - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" - "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)" @@ -2772,6 +2780,7 @@ SPEC REPOS: - GoogleAppMeasurement - GoogleDataTransport - GoogleUtilities + - JitsiWebRTC - libavif - libdav1d - libwebp @@ -2930,6 +2939,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-safe-area-context" react-native-slider: :path: "../node_modules/@react-native-community/slider" + react-native-webrtc: + :path: "../node_modules/react-native-webrtc" react-native-webview: :path: "../node_modules/react-native-webview" React-NativeModulesApple: @@ -2996,6 +3007,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon" RNBootSplash: :path: "../node_modules/react-native-bootsplash" + RNCallKeep: + :path: "../node_modules/react-native-callkeep" RNCAsyncStorage: :path: "../node_modules/@react-native-async-storage/async-storage" RNCClipboard: @@ -3079,6 +3092,7 @@ SPEC CHECKSUMS: GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d hermes-engine: 8b5a5eb386b990287d072fd7b6f6ebd9544dd251 + JitsiWebRTC: b47805ab5668be38e7ee60e2258f49badfe8e1d0 libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7 libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 @@ -3127,6 +3141,7 @@ SPEC CHECKSUMS: react-native-restart: f6f591aeb40194c41b9b5013901f00e6cf7d0f29 react-native-safe-area-context: 5928d84c879db2f9eb6969ca70e68f58623dbf25 react-native-slider: 605e731593322c4bb2eb48d7d64e2e4dbf7cbd77 + react-native-webrtc: e8f0ce746353adc2744a2b933645e1aeb41eaa74 react-native-webview: 69c118d283fccfbc4fca0cd680e036ff3bf188fa React-NativeModulesApple: 5b234860053d0dd11f3442f38b99688ff1c9733b React-oscompat: 472a446c740e39ee39cd57cd7bfd32177c763a2b @@ -3160,6 +3175,7 @@ SPEC CHECKSUMS: ReactCodegen: 2f22969ab54e1aace69c9b5d3085e0a3b405a9a6 ReactCommon: 177fca841e97b2c0e288e86097b8be04c6e7ae36 RNBootSplash: 1280eeb18d887de0a45bb4923d4fc56f25c8b99c + RNCallKeep: 1930a01d8caf48f018be4f2db0c9f03405c2f977 RNCAsyncStorage: edb872909c88d8541c0bfade3f86cd7784a7c6b3 RNCClipboard: 4fd4b093bd9d0be5ad62ea73884eda7745ad23d0 RNCMaskedView: de80352547bd4f0d607bf6bab363d826822bd126 diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index 29cc9563241..6dacd17fe10 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -7,8 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 020BAAEF21339D1538B55D15 /* Pods_defaults_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 537F37501C643FE86F92916E /* Pods_defaults_NotificationService.framework */; }; - 05F9D701BF644C25192B8E79 /* Pods_defaults_RocketChatRN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A46AABC73B7E9703E69AF850 /* Pods_defaults_RocketChatRN.framework */; }; 0C6E2DE448364EA896869ADF /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B37C79D9BD0742CE936B6982 /* libc++.tbd */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 1E01C81C2511208400FEF824 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E01C81B2511208400FEF824 /* URL+Extensions.swift */; }; @@ -279,6 +277,7 @@ 3F56D232A9EBA1C9C749F15E /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; 3F56D232A9EBA1C9C749F15F /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; 3F56D232A9EBA1C9C749F160 /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; + 426FF478D77293099212881F /* Pods_defaults_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB9F534F3E8CBF9FEFFC4866 /* Pods_defaults_Rocket_Chat.framework */; }; 4C4C8603EF082F0A33A95522 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D5C142B655F8EFD006792C /* ExpoModulesProvider.swift */; }; 65AD38372BFBDF4A00271B39 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */; }; 65AD38392BFBDF4A00271B39 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */; }; @@ -364,9 +363,10 @@ A2C6E2DD38F8BEE19BFB2E1D /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A42CFB843397273C7EA /* SecureStorage.m */; }; A48B46D92D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; A48B46DA2D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; - ACCF5C382F186B5D43B2C952 /* Pods_defaults_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 85094D3182EA9331CC444733 /* Pods_defaults_Rocket_Chat.framework */; }; BC404914E86821389EEB543D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */; }; + D220BA967F2E1E70183F9145 /* Pods_defaults_RocketChatRN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 595D750F5B210F6E68883689 /* Pods_defaults_RocketChatRN.framework */; }; DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA7E862283664608B3894E34 /* libWatermelonDB.a */; }; + EE97DFD0E0BEC72B1240C322 /* Pods_defaults_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB05EB8B2044518903038699 /* Pods_defaults_NotificationService.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -613,10 +613,12 @@ 1EFEB5992493B6640072EDC0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1EFEB5A12493B67D0072EDC0 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = ""; }; 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-Rocket.Chat/ExpoModulesProvider.swift"; sourceTree = ""; }; - 44A0BDC6158008BF9FF04F0A /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = ""; }; 45D5C142B655F8EFD006792C /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-RocketChatRN/ExpoModulesProvider.swift"; sourceTree = ""; }; - 482E711ACFA5E2C4281835BF /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = ""; }; - 537F37501C643FE86F92916E /* Pods_defaults_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 493A01BC9ACB23394D12AFDF /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = ""; }; + 4E0E229CA6934B9EAF0B9493 /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = ""; }; + 59533A56A22734482A5210FD /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = ""; }; + 595D750F5B210F6E68883689 /* Pods_defaults_RocketChatRN.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_RocketChatRN.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5999665FA1FBE0F403918D2A /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = ""; }; 60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = RocketChatRN.entitlements; path = RocketChatRN/RocketChatRN.entitlements; sourceTree = ""; }; 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; 65B9A7192AFC24190088956F /* ringtone.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ringtone.mp3; sourceTree = ""; }; @@ -624,7 +626,6 @@ 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MMKVKeyManager.mm; sourceTree = ""; }; 66C2701E2EBBCB780062725F /* SecureStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecureStorage.h; sourceTree = ""; }; 66C2701F2EBBCB780062725F /* SecureStorage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecureStorage.m; sourceTree = ""; }; - 6CE8C7A54627937DB698E839 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = ""; }; 7A006F13229C83B600803143 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 7A0129D22C6E8B5900F84A97 /* ShareRocketChatRN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareRocketChatRN.swift; sourceTree = ""; }; 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; @@ -640,18 +641,17 @@ 7ACD4853222860DE00442C55 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 7ACFE7D82DDE48760090D9BC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AE10C0528A59530003593CB /* Inter.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Inter.ttf; sourceTree = ""; }; - 85094D3182EA9331CC444733 /* Pods_defaults_Rocket_Chat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_Rocket_Chat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 92B416D2ADF070E0E0C782A0 /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = ""; }; 9B215A42CFB843397273C7EA /* SecureStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = SecureStorage.m; sourceTree = ""; }; 9B215A44CFB843397273C7EC /* MMKVBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MMKVBridge.mm; path = Shared/RocketChat/MMKVBridge.mm; sourceTree = ""; }; - A46AABC73B7E9703E69AF850 /* Pods_defaults_RocketChatRN.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_RocketChatRN.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A48B46D72D3FFBD200945489 /* A11yFlowModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = A11yFlowModule.h; sourceTree = ""; }; A48B46D82D3FFBD200945489 /* A11yFlowModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = A11yFlowModule.m; sourceTree = ""; }; + A8AB3C26BAEA809C12CB9A87 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = ""; }; B179038FDD7AAF285047814B /* SecureStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = SecureStorage.h; sourceTree = ""; }; B37C79D9BD0742CE936B6982 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; BA7E862283664608B3894E34 /* libWatermelonDB.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libWatermelonDB.a; sourceTree = ""; }; - CD1F8BBE6FE382D33AB37935 /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = ""; }; - F6BFACDCE2AB06F4936B3E03 /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = ""; }; + CB05EB8B2044518903038699 /* Pods_defaults_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E48D2153CA15F36CA164CFDC /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = ""; }; + EB9F534F3E8CBF9FEFFC4866 /* Pods_defaults_Rocket_Chat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_Rocket_Chat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -672,7 +672,7 @@ 7ACD4897222860DE00442C55 /* JavaScriptCore.framework in Frameworks */, 24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */, DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */, - 05F9D701BF644C25192B8E79 /* Pods_defaults_RocketChatRN.framework in Frameworks */, + D220BA967F2E1E70183F9145 /* Pods_defaults_RocketChatRN.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -694,7 +694,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 020BAAEF21339D1538B55D15 /* Pods_defaults_NotificationService.framework in Frameworks */, + EE97DFD0E0BEC72B1240C322 /* Pods_defaults_NotificationService.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -715,7 +715,7 @@ 7AAB3E3D257E6A6E00707CF6 /* JavaScriptCore.framework in Frameworks */, 7AAB3E3E257E6A6E00707CF6 /* libz.tbd in Frameworks */, 7AAB3E3F257E6A6E00707CF6 /* libWatermelonDB.a in Frameworks */, - ACCF5C382F186B5D43B2C952 /* Pods_defaults_Rocket_Chat.framework in Frameworks */, + 426FF478D77293099212881F /* Pods_defaults_Rocket_Chat.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1143,12 +1143,12 @@ 7AC2B09613AA7C3FEBAC9F57 /* Pods */ = { isa = PBXGroup; children = ( - 6CE8C7A54627937DB698E839 /* Pods-defaults-NotificationService.debug.xcconfig */, - 44A0BDC6158008BF9FF04F0A /* Pods-defaults-NotificationService.release.xcconfig */, - 92B416D2ADF070E0E0C782A0 /* Pods-defaults-Rocket.Chat.debug.xcconfig */, - CD1F8BBE6FE382D33AB37935 /* Pods-defaults-Rocket.Chat.release.xcconfig */, - 482E711ACFA5E2C4281835BF /* Pods-defaults-RocketChatRN.debug.xcconfig */, - F6BFACDCE2AB06F4936B3E03 /* Pods-defaults-RocketChatRN.release.xcconfig */, + A8AB3C26BAEA809C12CB9A87 /* Pods-defaults-NotificationService.debug.xcconfig */, + 493A01BC9ACB23394D12AFDF /* Pods-defaults-NotificationService.release.xcconfig */, + 4E0E229CA6934B9EAF0B9493 /* Pods-defaults-Rocket.Chat.debug.xcconfig */, + E48D2153CA15F36CA164CFDC /* Pods-defaults-Rocket.Chat.release.xcconfig */, + 59533A56A22734482A5210FD /* Pods-defaults-RocketChatRN.debug.xcconfig */, + 5999665FA1FBE0F403918D2A /* Pods-defaults-RocketChatRN.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -1247,9 +1247,9 @@ 7ACD4853222860DE00442C55 /* JavaScriptCore.framework */, B37C79D9BD0742CE936B6982 /* libc++.tbd */, 06BB44DD4855498082A744AD /* libz.tbd */, - 537F37501C643FE86F92916E /* Pods_defaults_NotificationService.framework */, - 85094D3182EA9331CC444733 /* Pods_defaults_Rocket_Chat.framework */, - A46AABC73B7E9703E69AF850 /* Pods_defaults_RocketChatRN.framework */, + CB05EB8B2044518903038699 /* Pods_defaults_NotificationService.framework */, + EB9F534F3E8CBF9FEFFC4866 /* Pods_defaults_Rocket_Chat.framework */, + 595D750F5B210F6E68883689 /* Pods_defaults_RocketChatRN.framework */, ); name = Frameworks; sourceTree = ""; @@ -1269,7 +1269,7 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RocketChatRN" */; buildPhases = ( - 8A4915EBB9B9EA919C35752B /* [CP] Check Pods Manifest.lock */, + 962B748359DA9B9705179CCD /* [CP] Check Pods Manifest.lock */, 06C10D4F29CD7532492AD29E /* [Expo] Configure project */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, @@ -1279,8 +1279,8 @@ 1E1EA8082326CCE300E22452 /* ShellScript */, 1ED0389C2B507B4F00C007D4 /* Embed Watch Content */, 7AAE9EB32891A0D20024F559 /* Upload source maps to Bugsnag */, - BCA373A96A91C30B09231381 /* [CP] Embed Pods Frameworks */, - E57DE3ACCEF8E313DFF4D411 /* [CP] Copy Pods Resources */, + BE3FE00123CFEC10E0345AF4 /* [CP] Embed Pods Frameworks */, + 95401EE136E44874208F1354 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1348,12 +1348,12 @@ isa = PBXNativeTarget; buildConfigurationList = 1EFEB5A02493B6640072EDC0 /* Build configuration list for PBXNativeTarget "NotificationService" */; buildPhases = ( - 664B079CA244E1ABB144A1C9 /* [CP] Check Pods Manifest.lock */, + 33BF8EE785F0FACE91B45419 /* [CP] Check Pods Manifest.lock */, 86A998705576AFA7CE938617 /* [Expo] Configure project */, 1EFEB5912493B6640072EDC0 /* Sources */, 1EFEB5922493B6640072EDC0 /* Frameworks */, 1EFEB5932493B6640072EDC0 /* Resources */, - 6BC31F4F1CF6E74A7683D2D4 /* [CP] Copy Pods Resources */, + 38768FD2CC9FB4795F119569 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1368,7 +1368,7 @@ isa = PBXNativeTarget; buildConfigurationList = 7AAB3E4F257E6A6E00707CF6 /* Build configuration list for PBXNativeTarget "Rocket.Chat" */; buildPhases = ( - 7E2F5D729E377A4A5D1E96B4 /* [CP] Check Pods Manifest.lock */, + 960C1CE9E3B9DBC185AC91D8 /* [CP] Check Pods Manifest.lock */, 6319FBDD06EF0030B48AD389 /* [Expo] Configure project */, 7AAB3E14257E6A6E00707CF6 /* Sources */, 7AAB3E32257E6A6E00707CF6 /* Frameworks */, @@ -1378,8 +1378,8 @@ 7A55BE3C2F1131C000D8744D /* ShellScript */, 1ED1ECE32B8699DD00F6620C /* Embed Watch Content */, 7A55BE3D2F11320C00D8744D /* Upload source maps to Bugsnag */, - F1B660D44BA706C4AA9FC60C /* [CP] Embed Pods Frameworks */, - 441DA981C582EB474E37526F /* [CP] Copy Pods Resources */, + D5D0EF64F1A7388CD16A9F46 /* [CP] Embed Pods Frameworks */, + 7639A7AEAB5CF1DC7E845A3A /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1589,13 +1589,35 @@ shellPath = /bin/sh; shellScript = "echo \"Target architectures: $ARCHS\"\n\nAPP_PATH=\"${TARGET_BUILD_DIR}/${WRAPPER_NAME}\"\n\nfind \"$APP_PATH\" -name '*.framework' -type d | while read -r FRAMEWORK\ndo\nFRAMEWORK_EXECUTABLE_NAME=$(defaults read \"$FRAMEWORK/Info.plist\" CFBundleExecutable)\nFRAMEWORK_EXECUTABLE_PATH=\"$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME\"\necho \"Executable is $FRAMEWORK_EXECUTABLE_PATH\"\necho $(lipo -info \"$FRAMEWORK_EXECUTABLE_PATH\")\n\nFRAMEWORK_TMP_PATH=\"$FRAMEWORK_EXECUTABLE_PATH-tmp\"\n\n# remove simulator's archs if location is not simulator's directory\ncase \"${TARGET_BUILD_DIR}\" in\n*\"iphonesimulator\")\necho \"No need to remove archs\"\n;;\n*)\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"i386\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"i386\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"i386 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"x86_64\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"x86_64\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"x86_64 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\n;;\nesac\n\necho \"Completed for executable $FRAMEWORK_EXECUTABLE_PATH\"\necho $\n\ndone\n"; }; - 441DA981C582EB474E37526F /* [CP] Copy Pods Resources */ = { + 33BF8EE785F0FACE91B45419 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 38768FD2CC9FB4795F119569 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/BugsnagReactNative/Bugsnag.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", @@ -1662,7 +1684,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh\"\n"; showEnvVarsInLog = 0; }; 6319FBDD06EF0030B48AD389 /* [Expo] Configure project */ = { @@ -1684,35 +1706,13 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-Rocket.Chat/expo-configure-project.sh\"\n"; }; - 664B079CA244E1ABB144A1C9 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 6BC31F4F1CF6E74A7683D2D4 /* [CP] Copy Pods Resources */ = { + 7639A7AEAB5CF1DC7E845A3A /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh", + "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/BugsnagReactNative/Bugsnag.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", @@ -1779,7 +1779,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh\"\n"; showEnvVarsInLog = 0; }; 7A55BE3B2F11316900D8744D /* Bundle React Native code and images */ = { @@ -1857,28 +1857,6 @@ shellScript = "SOURCE_MAP=\"$TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh\n"; showEnvVarsInLog = 0; }; - 7E2F5D729E377A4A5D1E96B4 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-Rocket.Chat-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; 86A998705576AFA7CE938617 /* [Expo] Configure project */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -1898,47 +1876,7 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-NotificationService/expo-configure-project.sh\"\n"; }; - 8A4915EBB9B9EA919C35752B /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-RocketChatRN-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - BCA373A96A91C30B09231381 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - E57DE3ACCEF8E313DFF4D411 /* [CP] Copy Pods Resources */ = { + 95401EE136E44874208F1354 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2014,17 +1952,83 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh\"\n"; showEnvVarsInLog = 0; }; - F1B660D44BA706C4AA9FC60C /* [CP] Embed Pods Frameworks */ = { + 960C1CE9E3B9DBC185AC91D8 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-defaults-Rocket.Chat-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 962B748359DA9B9705179CCD /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-defaults-RocketChatRN-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + BE3FE00123CFEC10E0345AF4 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + D5D0EF64F1A7388CD16A9F46 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", ); runOnlyForDeploymentPostprocessing = 0; @@ -2421,7 +2425,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 482E711ACFA5E2C4281835BF /* Pods-defaults-RocketChatRN.debug.xcconfig */; + baseConfigurationReference = 59533A56A22734482A5210FD /* Pods-defaults-RocketChatRN.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2486,7 +2490,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F6BFACDCE2AB06F4936B3E03 /* Pods-defaults-RocketChatRN.release.xcconfig */; + baseConfigurationReference = 5999665FA1FBE0F403918D2A /* Pods-defaults-RocketChatRN.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2901,7 +2905,7 @@ }; 1EFEB59D2493B6640072EDC0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6CE8C7A54627937DB698E839 /* Pods-defaults-NotificationService.debug.xcconfig */; + baseConfigurationReference = A8AB3C26BAEA809C12CB9A87 /* Pods-defaults-NotificationService.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(EMBEDDED_CONTENT_CONTAINS_SWIFT)"; CLANG_ANALYZER_NONNULL = YES; @@ -2953,7 +2957,7 @@ }; 1EFEB59E2493B6640072EDC0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 44A0BDC6158008BF9FF04F0A /* Pods-defaults-NotificationService.release.xcconfig */; + baseConfigurationReference = 493A01BC9ACB23394D12AFDF /* Pods-defaults-NotificationService.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(EMBEDDED_CONTENT_CONTAINS_SWIFT)"; CLANG_ANALYZER_NONNULL = YES; @@ -3004,7 +3008,7 @@ }; 7AAB3E50257E6A6E00707CF6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 92B416D2ADF070E0E0C782A0 /* Pods-defaults-Rocket.Chat.debug.xcconfig */; + baseConfigurationReference = 4E0E229CA6934B9EAF0B9493 /* Pods-defaults-Rocket.Chat.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -3069,7 +3073,7 @@ }; 7AAB3E51257E6A6E00707CF6 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CD1F8BBE6FE382D33AB37935 /* Pods-defaults-Rocket.Chat.release.xcconfig */; + baseConfigurationReference = E48D2153CA15F36CA164CFDC /* Pods-defaults-Rocket.Chat.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; diff --git a/package.json b/package.json index 45c7b5e50e1..821b4b6208a 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "@react-navigation/elements": "^2.6.1", "@react-navigation/native": "^7.1.16", "@react-navigation/native-stack": "^7.3.23", + "@rocket.chat/media-signaling": "/Users/diegomello/Development/Work/Rocket.Chat/packages/media-signaling", "@rocket.chat/message-parser": "^0.31.31", "@rocket.chat/mobile-crypto": "RocketChat/rocket.chat-mobile-crypto", "@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#mobile", @@ -91,6 +92,7 @@ "react-native-animatable": "1.3.3", "react-native-background-timer": "2.4.1", "react-native-bootsplash": "^6.3.8", + "react-native-callkeep": "^4.3.16", "react-native-config-reader": "4.1.1", "react-native-console-time-polyfill": "1.2.3", "react-native-device-info": "11.1.0", @@ -120,6 +122,7 @@ "react-native-slowlog": "1.0.2", "react-native-svg": "^15.12.1", "react-native-url-polyfill": "2.0.0", + "react-native-webrtc": "^124.0.7", "react-native-webview": "^13.15.0", "react-redux": "8.0.5", "reanimated-tab-view": "^0.3.0", diff --git a/patches/@rocket.chat+sdk+1.3.3-mobile.patch b/patches/@rocket.chat+sdk+1.3.3-mobile.patch new file mode 100644 index 00000000000..ab0a55a87d2 --- /dev/null +++ b/patches/@rocket.chat+sdk+1.3.3-mobile.patch @@ -0,0 +1,15 @@ +diff --git a/node_modules/@rocket.chat/sdk/lib/drivers/ddp.ts b/node_modules/@rocket.chat/sdk/lib/drivers/ddp.ts +index 19d31ae..d5295b5 100644 +--- a/node_modules/@rocket.chat/sdk/lib/drivers/ddp.ts ++++ b/node_modules/@rocket.chat/sdk/lib/drivers/ddp.ts +@@ -549,7 +549,9 @@ export class DDPDriver extends EventEmitter implements ISocket, IDriver { + 'uiInteraction', + 'e2ekeyRequest', + 'userData', +- 'video-conference' ++ 'video-conference', ++ 'media-signal', ++ 'media-calls' + ].map(event => this.subscribe(topic, `${this.userId}/${event}`, false))) + } + diff --git a/patches/react-native-callkeep+4.3.16.patch b/patches/react-native-callkeep+4.3.16.patch new file mode 100644 index 00000000000..41f76ed042f --- /dev/null +++ b/patches/react-native-callkeep+4.3.16.patch @@ -0,0 +1,544 @@ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/results.bin b/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/results.bin +new file mode 100644 +index 0000000..0d259dd +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/results.bin +@@ -0,0 +1 @@ ++o/classes +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/transformed/classes/classes_dex/classes.dex b/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/transformed/classes/classes_dex/classes.dex +new file mode 100644 +index 0000000..4119e43 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/transformed/classes/classes_dex/classes.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/results.bin b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/results.bin +new file mode 100644 +index 0000000..7ed749e +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/results.bin +@@ -0,0 +1 @@ ++o/bundleLibRuntimeToDirDebug +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/BuildConfig.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/BuildConfig.dex +new file mode 100644 +index 0000000..778c715 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/BuildConfig.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/Constants.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/Constants.dex +new file mode 100644 +index 0000000..b455781 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/Constants.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils$1.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils$1.dex +new file mode 100644 +index 0000000..4d67548 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils$1.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils.dex +new file mode 100644 +index 0000000..cff89d7 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.dex +new file mode 100644 +index 0000000..915774b +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$1.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$1.dex +new file mode 100644 +index 0000000..f6b4e96 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$1.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$CallStateListener.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$CallStateListener.dex +new file mode 100644 +index 0000000..adb3630 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$CallStateListener.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.dex +new file mode 100644 +index 0000000..60293f2 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.dex +new file mode 100644 +index 0000000..2534446 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule.dex +new file mode 100644 +index 0000000..b430d90 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepPackage.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepPackage.dex +new file mode 100644 +index 0000000..8ec634e +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepPackage.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConference.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConference.dex +new file mode 100644 +index 0000000..6c2a20d +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConference.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection$1.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection$1.dex +new file mode 100644 +index 0000000..12f4957 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection$1.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection.dex +new file mode 100644 +index 0000000..91730a7 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$1.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$1.dex +new file mode 100644 +index 0000000..9b64aa6 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$1.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$2.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$2.dex +new file mode 100644 +index 0000000..6b69b72 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$2.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$3.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$3.dex +new file mode 100644 +index 0000000..eadb3df +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$3.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$4.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$4.dex +new file mode 100644 +index 0000000..b330051 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$4.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService.dex +new file mode 100644 +index 0000000..d5dff5c +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService.dex differ +diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +new file mode 100644 +index 0000000..dbb49bb +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin differ +diff --git a/node_modules/react-native-callkeep/android/build/generated/source/buildConfig/debug/io/wazo/callkeep/BuildConfig.java b/node_modules/react-native-callkeep/android/build/generated/source/buildConfig/debug/io/wazo/callkeep/BuildConfig.java +new file mode 100644 +index 0000000..af36621 +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/generated/source/buildConfig/debug/io/wazo/callkeep/BuildConfig.java +@@ -0,0 +1,10 @@ ++/** ++ * Automatically generated file. DO NOT MODIFY ++ */ ++package io.wazo.callkeep; ++ ++public final class BuildConfig { ++ public static final boolean DEBUG = Boolean.parseBoolean("true"); ++ public static final String LIBRARY_PACKAGE_NAME = "io.wazo.callkeep"; ++ public static final String BUILD_TYPE = "debug"; ++} +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml b/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +new file mode 100644 +index 0000000..4889152 +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +@@ -0,0 +1,14 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json b/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +new file mode 100644 +index 0000000..a663f08 +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +@@ -0,0 +1,18 @@ ++{ ++ "version": 3, ++ "artifactType": { ++ "type": "AAPT_FRIENDLY_MERGED_MANIFESTS", ++ "kind": "Directory" ++ }, ++ "applicationId": "io.wazo.callkeep", ++ "variantName": "debug", ++ "elements": [ ++ { ++ "type": "SINGLE", ++ "filters": [], ++ "attributes": [], ++ "outputFile": "AndroidManifest.xml" ++ } ++ ], ++ "elementType": "File" ++} +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties b/node_modules/react-native-callkeep/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +new file mode 100644 +index 0000000..1211b1e +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +@@ -0,0 +1,6 @@ ++aarFormatVersion=1.0 ++aarMetadataVersion=1.0 ++minCompileSdk=1 ++minCompileSdkExtension=0 ++minAndroidGradlePluginVersion=1.0.0 ++coreLibraryDesugaringEnabled=false +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json b/node_modules/react-native-callkeep/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +new file mode 100644 +index 0000000..9e26dfe +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +@@ -0,0 +1 @@ ++{} +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar b/node_modules/react-native-callkeep/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +new file mode 100644 +index 0000000..8c54db9 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar b/node_modules/react-native-callkeep/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +new file mode 100644 +index 0000000..169bdf6 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt b/node_modules/react-native-callkeep/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +new file mode 100644 +index 0000000..e69de29 +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties b/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +new file mode 100644 +index 0000000..342121f +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +@@ -0,0 +1 @@ ++#Mon Jan 12 14:06:26 BRT 2026 +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml b/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +new file mode 100644 +index 0000000..7344b1b +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +@@ -0,0 +1,2 @@ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml b/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +new file mode 100644 +index 0000000..e436a6a +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +@@ -0,0 +1,2 @@ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugShaders/merger.xml b/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +new file mode 100644 +index 0000000..7572f77 +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +@@ -0,0 +1,2 @@ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/packageDebugAssets/merger.xml b/node_modules/react-native-callkeep/android/build/intermediates/incremental/packageDebugAssets/merger.xml +new file mode 100644 +index 0000000..2713406 +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/packageDebugAssets/merger.xml +@@ -0,0 +1,2 @@ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/BuildConfig.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/BuildConfig.class +new file mode 100644 +index 0000000..eea56ab +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/BuildConfig.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/Constants.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/Constants.class +new file mode 100644 +index 0000000..1431c43 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/Constants.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils$1.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils$1.class +new file mode 100644 +index 0000000..2edfdd4 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils$1.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils.class +new file mode 100644 +index 0000000..41dc2a1 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class +new file mode 100644 +index 0000000..135262e +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$1.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$1.class +new file mode 100644 +index 0000000..5d16482 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$1.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class +new file mode 100644 +index 0000000..fac5f49 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class +new file mode 100644 +index 0000000..f96d7ff +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class +new file mode 100644 +index 0000000..7508b23 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule.class +new file mode 100644 +index 0000000..8161c41 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepPackage.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepPackage.class +new file mode 100644 +index 0000000..a53c172 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepPackage.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConference.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConference.class +new file mode 100644 +index 0000000..be38a83 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConference.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection$1.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection$1.class +new file mode 100644 +index 0000000..de9749e +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection$1.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection.class +new file mode 100644 +index 0000000..bf89219 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$1.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$1.class +new file mode 100644 +index 0000000..3af0dbe +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$1.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$2.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$2.class +new file mode 100644 +index 0000000..f0c485d +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$2.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$3.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$3.class +new file mode 100644 +index 0000000..d27d5cf +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$3.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$4.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$4.class +new file mode 100644 +index 0000000..87119b1 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$4.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService.class +new file mode 100644 +index 0000000..104d3e9 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt b/node_modules/react-native-callkeep/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +new file mode 100644 +index 0000000..78ac5b8 +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +@@ -0,0 +1,2 @@ ++R_DEF: Internal format may change without notice ++local +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt b/node_modules/react-native-callkeep/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +new file mode 100644 +index 0000000..999890d +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +@@ -0,0 +1,23 @@ ++1 ++2 ++4 ++5 ++6 ++7 ++7-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:4:5-69 ++7-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:4:22-66 ++8 /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:5:5-6:51 ++9 android:name="android.permission.READ_PHONE_STATE" ++9-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:5:22-72 ++10 android:maxSdkVersion="29" /> ++10-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:6:22-48 ++11 ++11-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:7:5-77 ++11-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:7:22-74 ++12 ++12-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:8:5-75 ++12-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:8:22-72 ++13 ++14 +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml b/node_modules/react-native-callkeep/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +new file mode 100644 +index 0000000..4889152 +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +@@ -0,0 +1,14 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json b/node_modules/react-native-callkeep/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +new file mode 100644 +index 0000000..0637a08 +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +@@ -0,0 +1 @@ ++[] +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt b/node_modules/react-native-callkeep/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +new file mode 100644 +index 0000000..08f4ebe +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +@@ -0,0 +1 @@ ++0 Warning/Error +\ No newline at end of file +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/BuildConfig.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/BuildConfig.class +new file mode 100644 +index 0000000..eea56ab +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/BuildConfig.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/Constants.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/Constants.class +new file mode 100644 +index 0000000..1431c43 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/Constants.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils$1.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils$1.class +new file mode 100644 +index 0000000..2edfdd4 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils$1.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils.class +new file mode 100644 +index 0000000..41dc2a1 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class +new file mode 100644 +index 0000000..135262e +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$1.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$1.class +new file mode 100644 +index 0000000..5d16482 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$1.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class +new file mode 100644 +index 0000000..fac5f49 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class +new file mode 100644 +index 0000000..f96d7ff +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class +new file mode 100644 +index 0000000..7508b23 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule.class +new file mode 100644 +index 0000000..8161c41 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepPackage.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepPackage.class +new file mode 100644 +index 0000000..a53c172 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepPackage.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConference.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConference.class +new file mode 100644 +index 0000000..be38a83 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConference.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection$1.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection$1.class +new file mode 100644 +index 0000000..de9749e +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection$1.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection.class +new file mode 100644 +index 0000000..bf89219 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$1.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$1.class +new file mode 100644 +index 0000000..3af0dbe +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$1.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$2.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$2.class +new file mode 100644 +index 0000000..f0c485d +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$2.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$3.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$3.class +new file mode 100644 +index 0000000..d27d5cf +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$3.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$4.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$4.class +new file mode 100644 +index 0000000..87119b1 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$4.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService.class +new file mode 100644 +index 0000000..104d3e9 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService.class differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +new file mode 100644 +index 0000000..1c837d1 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar differ +diff --git a/node_modules/react-native-callkeep/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt b/node_modules/react-native-callkeep/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +new file mode 100644 +index 0000000..7612bfd +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +@@ -0,0 +1 @@ ++io.wazo.callkeep +diff --git a/node_modules/react-native-callkeep/android/build/outputs/logs/manifest-merger-debug-report.txt b/node_modules/react-native-callkeep/android/build/outputs/logs/manifest-merger-debug-report.txt +new file mode 100644 +index 0000000..d3fde62 +--- /dev/null ++++ b/node_modules/react-native-callkeep/android/build/outputs/logs/manifest-merger-debug-report.txt +@@ -0,0 +1,35 @@ ++-- Merging decision tree log --- ++manifest ++ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:2:1-9:12 ++INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:2:1-9:12 ++ package ++ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:2:70-96 ++ INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml ++ xmlns:android ++ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:2:11-69 ++uses-permission#android.permission.CALL_PHONE ++ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:4:5-69 ++ android:name ++ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:4:22-66 ++uses-permission#android.permission.READ_PHONE_STATE ++ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:5:5-6:51 ++ android:maxSdkVersion ++ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:6:22-48 ++ android:name ++ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:5:22-72 ++uses-permission#android.permission.READ_PHONE_NUMBERS ++ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:7:5-77 ++ android:name ++ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:7:22-74 ++uses-permission#android.permission.MANAGE_OWN_CALLS ++ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:8:5-75 ++ android:name ++ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:8:22-72 ++uses-sdk ++INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml reason: use-sdk injection requested ++INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml ++INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml ++ android:targetSdkVersion ++ INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml ++ android:minSdkVersion ++ INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml +diff --git a/node_modules/react-native-callkeep/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin b/node_modules/react-native-callkeep/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +new file mode 100644 +index 0000000..b44a073 +Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin differ +diff --git a/node_modules/react-native-callkeep/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java b/node_modules/react-native-callkeep/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java +index 025480a..70a1305 100644 +--- a/node_modules/react-native-callkeep/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java ++++ b/node_modules/react-native-callkeep/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java +@@ -434,11 +434,6 @@ public class RNCallKeepModule extends ReactContextBaseJavaModule implements Life + this.hasListeners = false; + } + +- @ReactMethod +- public void displayIncomingCall(String uuid, String number, String callerName) { +- this.displayIncomingCall(uuid, number, callerName, false, null); +- } +- + @ReactMethod + public void displayIncomingCall(String uuid, String number, String callerName, boolean hasVideo) { + this.displayIncomingCall(uuid, number, callerName, hasVideo, null); +@@ -483,11 +478,6 @@ public class RNCallKeepModule extends ReactContextBaseJavaModule implements Life + conn.onAnswer(); + } + +- @ReactMethod +- public void startCall(String uuid, String number, String callerName) { +- this.startCall(uuid, number, callerName, false, null); +- } +- + @ReactMethod + public void startCall(String uuid, String number, String callerName, boolean hasVideo) { + this.startCall(uuid, number, callerName, hasVideo, null); diff --git a/yarn.lock b/yarn.lock index 5f334cbad37..036a80005f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2750,14 +2750,14 @@ xcode "^3.0.1" xml2js "0.6.0" -"@expo/config-plugins@~54.0.3": - version "54.0.3" - resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-54.0.3.tgz#2b9ffd68a48e3b51299cdbe3ee777b9f5163fc03" - integrity sha512-tBIUZIxLQfCu5jmqTO+UOeeDUGIB0BbK6xTMkPRObAXRQeTLPPfokZRCo818d2owd+Bcmq1wBaDz0VY3g+glfw== - dependencies: - "@expo/config-types" "^54.0.9" - "@expo/json-file" "~10.0.7" - "@expo/plist" "^0.4.7" +"@expo/config-plugins@~54.0.4": + version "54.0.4" + resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-54.0.4.tgz#b31cb16f6651342abcdafba600118245ecd9fb00" + integrity sha512-g2yXGICdoOw5i3LkQSDxl2Q5AlQCrG7oniu0pCPPO+UxGb7He4AFqSvPSy8HpRUj55io17hT62FTjYRD+d6j3Q== + dependencies: + "@expo/config-types" "^54.0.10" + "@expo/json-file" "~10.0.8" + "@expo/plist" "^0.4.8" "@expo/sdk-runtime-versions" "^1.0.0" chalk "^4.1.2" debug "^4.3.5" @@ -2785,11 +2785,6 @@ resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-54.0.10.tgz#688f4338255d2fdea970f44e2dfd8e8d37dec292" integrity sha512-/J16SC2an1LdtCZ67xhSkGXpALYUVUNyZws7v+PVsFZxClYehDSoKLqyRaGkpHlYrCc08bS0RF5E0JV6g50psA== -"@expo/config-types@^54.0.9": - version "54.0.9" - resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-54.0.9.tgz#b9279c47fe249b774fbd3358b6abddea08f1bcec" - integrity sha512-Llf4jwcrAnrxgE5WCdAOxtMf8FGwS4Sk0SSgI0NnIaSyCnmOCAm80GPFvsK778Oj19Ub4tSyzdqufPyeQPksWw== - "@expo/config@~11.0.7", "@expo/config@~11.0.8": version "11.0.8" resolved "https://registry.yarnpkg.com/@expo/config/-/config-11.0.8.tgz#658538d4321cf6edf6741f8b8506fda0046d5e94" @@ -2828,13 +2823,13 @@ slugify "^1.3.4" sucrase "3.35.0" -"@expo/config@~12.0.12": - version "12.0.12" - resolved "https://registry.yarnpkg.com/@expo/config/-/config-12.0.12.tgz#5e26390ec209ee56432e980451c08b361e0f07dd" - integrity sha512-X2MW86+ulLpMGvdgfvpl2EOBAKUlwvnvoPwdaZeeyWufGopn1nTUeh4C9gMsplDaP1kXv9sLXVhOoUoX6g9PvQ== +"@expo/config@~12.0.13": + version "12.0.13" + resolved "https://registry.yarnpkg.com/@expo/config/-/config-12.0.13.tgz#8e696e6121c3c364e1dd527f595cf0a1d9386828" + integrity sha512-Cu52arBa4vSaupIWsF0h7F/Cg//N374nYb7HAxV0I4KceKA7x2UXpYaHOL7EEYYvp7tZdThBjvGpVmr8ScIvaQ== dependencies: "@babel/code-frame" "~7.10.4" - "@expo/config-plugins" "~54.0.3" + "@expo/config-plugins" "~54.0.4" "@expo/config-types" "^54.0.10" "@expo/json-file" "^10.0.8" deepmerge "^4.3.1" @@ -2934,7 +2929,7 @@ temp-dir "~2.0.0" unique-string "~2.0.0" -"@expo/json-file@^10.0.8", "@expo/json-file@~10.0.7": +"@expo/json-file@^10.0.8", "@expo/json-file@~10.0.8": version "10.0.8" resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-10.0.8.tgz#05e524d1ecc0011db0a6d66b525ea2f58cfe6d43" integrity sha512-9LOTh1PgKizD1VXfGQ88LtDH0lRwq9lsTb4aichWTWSWqy3Ugfkhfm3BhzBIkJJfQQ5iJu3m/BoRlEIjoCGcnQ== @@ -3004,7 +2999,7 @@ base64-js "^1.2.3" xmlbuilder "^15.1.1" -"@expo/plist@^0.4.7": +"@expo/plist@^0.4.8": version "0.4.8" resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.4.8.tgz#e014511a4a5008cf2b832b91caa8e9f2704127cc" integrity sha512-pfNtErGGzzRwHP+5+RqswzPDKkZrx+Cli0mzjQaus1ZWFsog5ibL+nVT3NcporW51o8ggnt7x813vtRbPiyOrQ== @@ -5009,6 +5004,11 @@ resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.2.1.tgz#9403f51c17cae37edf870c6bc0c81c1ece5ccef8" integrity sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA== +"@rocket.chat/emitter@~0.31.25": + version "0.31.25" + resolved "https://registry.yarnpkg.com/@rocket.chat/emitter/-/emitter-0.31.25.tgz#17dd7838dc988ebc5fcd96343c4431d5cef45845" + integrity sha512-hw5BpDlNwpYSb+K5X3DNMNUVEVXxmXugUPetGZGCWvntSVFsOjYuVEypoKW6vBBXSfqCBb0kN1npYcKEb4NFBw== + "@rocket.chat/eslint-config@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@rocket.chat/eslint-config/-/eslint-config-0.4.0.tgz#d648decd02ae739eac17a32e1630332a75318ea1" @@ -5016,6 +5016,12 @@ dependencies: eslint-plugin-import "^2.17.2" +"@rocket.chat/media-signaling@file:../Rocket.Chat/packages/media-signaling": + version "0.1.0" + dependencies: + "@rocket.chat/emitter" "~0.31.25" + ajv "^8.17.1" + "@rocket.chat/message-parser@^0.31.31": version "0.31.31" resolved "https://registry.yarnpkg.com/@rocket.chat/message-parser/-/message-parser-0.31.31.tgz#9a3eea7602ac37387c6384577623865c8d536003" @@ -5984,6 +5990,16 @@ ajv@^8.0.0, ajv@^8.9.0: require-from-string "^2.0.2" uri-js "^4.2.2" +ajv@^8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + anser@^1.4.9: version "1.4.10" resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b" @@ -6554,7 +6570,7 @@ bare-path@^2.0.0, bare-path@^2.1.0: dependencies: bare-os "^2.1.0" -base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1: +base64-js@1.5.1, base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -7363,9 +7379,9 @@ data-view-byte-offset@^1.0.0: is-data-view "^1.0.1" dayjs@^1.11.18: - version "1.11.18" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.18.tgz#835fa712aac52ab9dec8b1494098774ed7070a11" - integrity sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA== + version "1.11.19" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.19.tgz#15dc98e854bb43917f12021806af897c58ae2938" + integrity sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw== dayjs@^1.8.15: version "1.11.10" @@ -7386,6 +7402,13 @@ debug@4, debug@^4.1.0, debug@^4.1.1: dependencies: ms "^2.1.1" +debug@4.3.4, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -7400,13 +7423,6 @@ debug@^4.3.1: dependencies: ms "2.1.2" -debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - debug@^4.3.5, debug@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" @@ -8387,6 +8403,11 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +event-target-shim@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-6.0.2.tgz#ea5348c3618ee8b62ff1d344f01908ee2b8a2b71" + integrity sha512-8q3LsZjRezbFZ2PN+uP+Q7pnHUMmAOziU2vA2OwoFaKIXxlxl38IylhSSgUorWu/rf4er67w0ikBqjBFk/pomA== + event-target-shim@^5.0.0, event-target-shim@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" @@ -8472,11 +8493,11 @@ expo-constants@~17.1.5: "@expo/env" "~1.0.5" expo-constants@~18.0.8: - version "18.0.12" - resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-18.0.12.tgz#3e67f7109ffd03eaa5514c19875a767c39f5a2ca" - integrity sha512-WzcKYMVNRRu4NcSzfIVRD5aUQFnSpTZgXFrlWmm19xJoDa4S3/PQNi6PNTBRc49xz9h8FT7HMxRKaC8lr0gflA== + version "18.0.13" + resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-18.0.13.tgz#0117f1f3d43be7b645192c0f4f431fb4efc4803d" + integrity sha512-FnZn12E1dRYKDHlAdIyNFhBurKTS3F9CrfrBDJI5m3D7U17KBHMQ6JEfYlSj7LG7t+Ulr+IKaj58L1k5gBwTcQ== dependencies: - "@expo/config" "~12.0.12" + "@expo/config" "~12.0.13" "@expo/env" "~2.0.8" expo-device@^8.0.10: @@ -8674,6 +8695,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-uri@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" + integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== + fast-xml-parser@^4.0.12, fast-xml-parser@^4.2.4: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" @@ -12635,6 +12661,11 @@ react-native-bootsplash@^6.3.8: ts-dedent "^2.2.0" xml-formatter "^3.6.5" +react-native-callkeep@^4.3.16: + version "4.3.16" + resolved "https://registry.yarnpkg.com/react-native-callkeep/-/react-native-callkeep-4.3.16.tgz#56291796984b896113ef00f8b67ae3fe177baf70" + integrity sha512-aIxn02T5zW4jNPyzRdFGTWv6xD3Vy/1AkBMB6iYvWZEHWnfmgNGF0hELqg03Vbc2BNUhfqpu17aIydos+5Hurg== + react-native-config-reader@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/react-native-config-reader/-/react-native-config-reader-4.1.1.tgz#478b69e32adcc2e9a14f6ef5fa2cbbe012b9a27e" @@ -12861,6 +12892,15 @@ react-native-url-polyfill@2.0.0, react-native-url-polyfill@^2.0.0: dependencies: whatwg-url-without-unicode "8.0.0-3" +react-native-webrtc@^124.0.7: + version "124.0.7" + resolved "https://registry.yarnpkg.com/react-native-webrtc/-/react-native-webrtc-124.0.7.tgz#f50647a8eb3fae0ef29843eb1b5fe2c4ff75a56e" + integrity sha512-gnXPdbUS8IkKHq9WNaWptW/yy5s6nMyI6cNn90LXdobPVCgYSk6NA2uUGdT4c4J14BRgaFA95F+cR28tUPkMVA== + dependencies: + base64-js "1.5.1" + debug "4.3.4" + event-target-shim "6.0.2" + react-native-webview@^13.15.0: version "13.15.0" resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-13.15.0.tgz#b6d2f8d8dd65897db76659ddd8198d2c74ec5a79" From e532171c71c4d2d5a6f6c0fb372bd4940b98bcf6 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Mon, 12 Jan 2026 16:52:19 -0300 Subject: [PATCH 02/61] feat(voip): enhance call handling with UUID mapping and event listeners --- app/lib/services/voip/MediaSessionInstance.ts | 65 ++++++++++++------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index d4406da20ba..711721d06d5 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -5,8 +5,9 @@ import { type MediaSignalingSession, type WebRTCProcessorConfig } from '@rocket.chat/media-signaling'; -import RNCallKeep from 'react-native-callkeep'; +import RNCallKeep, { type EventListener } from 'react-native-callkeep'; import { registerGlobals } from 'react-native-webrtc'; +import { randomUuid } from '@rocket.chat/mobile-crypto'; import { mediaSessionStore } from './MediaSessionStore'; import { store } from '../../store/auxStore'; @@ -15,6 +16,8 @@ import { parseStringToIceServers } from './parseStringToIceServers'; import type { IceServer } from '../../../definitions/Voip'; import type { IDDPMessage } from '../../../definitions/IDDPMessage'; +const localCallIdMap: Record = {}; + class MediaSessionInstance { private iceServers: IceServer[] = []; private iceGatheringTimeout: number = 5000; @@ -23,6 +26,12 @@ class MediaSessionInstance { private instance: MediaSignalingSession | null = null; private storeTimeoutUnsubscribe: (() => void) | null = null; private storeIceServersUnsubscribe: (() => void) | null = null; + private callKeepListeners: { + answerCall?: EventListener; + endCall?: EventListener; + didPerformSetMutedCallAction?: EventListener; + didPerformDTMFAction?: EventListener; + } = {}; public init(userId: string): void { this.stop(); @@ -56,56 +65,68 @@ class MediaSessionInstance { this.instance.processSignal(signal); }); - this.instance?.on('newCall', ({ call }: { call: IClientMediaCall }) => { + this.instance?.on('newCall', async ({ call }: { call: IClientMediaCall }) => { if (call && !call.hidden) { call.emitter.on('stateChange', oldState => { console.log(`📊 ${oldState} → ${call.state}`); }); - + const callUUID = (await randomUuid()).toLowerCase(); + localCallIdMap[callUUID] = call.callId; const displayName = call.contact.displayName || call.contact.username || 'Unknown'; - RNCallKeep.displayIncomingCall(call.callId, displayName, displayName, 'generic', false); + RNCallKeep.displayIncomingCall(callUUID, displayName, displayName, 'generic', false); - call.emitter.on('ended', () => RNCallKeep.endCall(call.callId)); + call.emitter.on('ended', () => { + RNCallKeep.endCall(callUUID); + delete localCallIdMap[callUUID]; + }); } }); } - private configureRNCallKeep() { - RNCallKeep.addEventListener('answerCall', async ({ callUUID }) => { + private configureRNCallKeep = () => { + this.callKeepListeners.answerCall = RNCallKeep.addEventListener('answerCall', async ({ callUUID }) => { + const callId = localCallIdMap[callUUID]; const mainCall = this.instance?.getMainCall(); - if (mainCall && mainCall.callId === callUUID) { + if (mainCall && mainCall.callId === callId) { await mainCall.accept(); - RNCallKeep.setCurrentCallActive(mainCall.callId); + RNCallKeep.setCurrentCallActive(callUUID); } else { RNCallKeep.endCall(callUUID); } }); - RNCallKeep.addEventListener('endCall', ({ callUUID }) => { + this.callKeepListeners.endCall = RNCallKeep.addEventListener('endCall', ({ callUUID }) => { + const callId = localCallIdMap[callUUID]; const mainCall = this.instance?.getMainCall(); - if (mainCall && mainCall.callId === callUUID) { + if (mainCall && mainCall.callId === callId) { if (mainCall.state === 'ringing') { mainCall.reject(); } else { mainCall.hangup(); } } + delete localCallIdMap[callUUID]; }); - RNCallKeep.addEventListener('didPerformSetMutedCallAction', ({ muted, callUUID }) => { - const mainCall = this.instance?.getMainCall(); - if (mainCall && mainCall.callId === callUUID) { - mainCall.setMuted(muted); + this.callKeepListeners.didPerformSetMutedCallAction = RNCallKeep.addEventListener( + 'didPerformSetMutedCallAction', + ({ muted, callUUID }) => { + const callId = localCallIdMap[callUUID]; + const mainCall = this.instance?.getMainCall(); + if (mainCall && mainCall.callId === callId) { + mainCall.setMuted(muted); + } } - }); + ); - RNCallKeep.addEventListener('didPerformDTMFAction', ({ digits }) => { + this.callKeepListeners.didPerformDTMFAction = RNCallKeep.addEventListener('didPerformDTMFAction', ({ digits, callUUID }) => { + const callId = localCallIdMap[callUUID]; const mainCall = this.instance?.getMainCall(); - if (mainCall) { + if (mainCall && mainCall.callId === callId) { mainCall.sendDTMF(digits); } }); - } + }; private getIceServers() { const iceServers = store.getState().settings.VoIP_TeamCollab_Ice_Servers as any; @@ -140,10 +161,6 @@ class MediaSessionInstance { if (this.mediaSignalsListener) { this.mediaSignalsListener.stop(); } - RNCallKeep.removeEventListener('answerCall'); - RNCallKeep.removeEventListener('endCall'); - RNCallKeep.removeEventListener('didPerformSetMutedCallAction'); - RNCallKeep.removeEventListener('didPerformDTMFAction'); if (this.storeTimeoutUnsubscribe) { this.storeTimeoutUnsubscribe(); } @@ -153,6 +170,8 @@ class MediaSessionInstance { if (this.instance) { this.instance.endSession(); } + Object.values(this.callKeepListeners).forEach(listener => listener?.remove()); + Object.keys(localCallIdMap).forEach(key => delete localCallIdMap[key]); } } From 1299b0e0123de2e726f61d81834787b091574d33 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Mon, 12 Jan 2026 17:56:03 -0300 Subject: [PATCH 03/61] Base call UI --- app/i18n/locales/en.json | 6 + app/lib/services/voip/MediaSessionInstance.ts | 3 + app/stacks/InsideStack.tsx | 2 + app/stacks/types.ts | 3 + .../CallView/components/CallActionButton.tsx | 65 +++++ .../CallView/components/CallStatusText.tsx | 38 +++ app/views/CallView/components/CallTimer.tsx | 31 +++ app/views/CallView/components/CallerInfo.tsx | 32 +++ app/views/CallView/index.tsx | 242 ++++++++++++++++++ app/views/CallView/styles.ts | 124 +++++++++ 10 files changed, 546 insertions(+) create mode 100644 app/views/CallView/components/CallActionButton.tsx create mode 100644 app/views/CallView/components/CallStatusText.tsx create mode 100644 app/views/CallView/components/CallTimer.tsx create mode 100644 app/views/CallView/components/CallerInfo.tsx create mode 100644 app/views/CallView/index.tsx create mode 100644 app/views/CallView/styles.ts diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index 20adc12eb90..c422c088149 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -322,6 +322,7 @@ "Encryption_error_title": "Incorrect password", "Encryption_keys_reset": "Encryption keys reset", "Encryption_keys_reset_failed": "Encryption keys reset failed", + "End": "End", "End_to_end_encrypted_room": "End to end encrypted room", "Enter_E2EE_Password": "Enter E2EE password", "Enter_E2EE_Password_description": "Enter your E2EE password to view and send encrypted messages.\n\nPassword need to be entered on each device.", @@ -399,6 +400,7 @@ "Hide_room": "Hide", "Hide_System_Messages": "Hide system messages", "Hide_type_messages": "Hide \"{{type}}\" messages", + "Hold": "Hold", "How_It_Works": "How it works", "I_Saved_My_E2E_Password": "I saved my E2E password", "Ignore": "Ignore", @@ -559,6 +561,7 @@ "Move_to_Team_Warning": "After reading the previous instructions about this behavior, do you still want to move this channel to the selected team?", "moving_channel_to_team": "moving channel to team", "Mute": "Mute", + "Muted": "Muted", "Mute_someone_in_room": "Mute someone in the room", "muted": "muted", "N_channels": "{{n}} channels", @@ -618,6 +621,7 @@ "Omnichannel_on_hold_chat_resumed": "On hold chat resumed: {{comment}}", "Omnichannel_placed_chat_on_hold": "Chat on hold: {{comment}}", "Omnichannel_queue": "Omnichannel queue", + "On_hold": "On hold", "On_hold_Livechats": "Omnichannel chats on hold", "Onboarding_agree_terms": "By continuing, you agree to Rocket.Chat", "Onboarding_less_options": "Less options", @@ -842,6 +846,7 @@ "Smileys_and_people": "Smileys and people", "Sort_by": "Sort by", "Sound": "Sound", + "Speaker": "Speaker", "Star": "Star", "Starred": "Starred", "Start_a_call": "Start a call", @@ -919,6 +924,7 @@ "Unfollowed_thread": "Unfollowed thread", "Unhide": "Unhide", "Unignore": "Unignore", + "Unhold": "Unhold", "Unmute": "Unmute", "Unmute_someone_in_room": "Unmute someone in the room", "unmuted": "unmuted", diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 711721d06d5..05e4f99cb81 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -12,6 +12,7 @@ import { randomUuid } from '@rocket.chat/mobile-crypto'; import { mediaSessionStore } from './MediaSessionStore'; import { store } from '../../store/auxStore'; import sdk from '../sdk'; +import Navigation from '../../navigation/appNavigation'; import { parseStringToIceServers } from './parseStringToIceServers'; import type { IceServer } from '../../../definitions/Voip'; import type { IDDPMessage } from '../../../definitions/IDDPMessage'; @@ -90,6 +91,8 @@ class MediaSessionInstance { if (mainCall && mainCall.callId === callId) { await mainCall.accept(); RNCallKeep.setCurrentCallActive(callUUID); + // Navigate to CallView - call data fetched from mediaSessionStore + Navigation.navigate('CallView', { callUUID }); } else { RNCallKeep.endCall(callUUID); } diff --git a/app/stacks/InsideStack.tsx b/app/stacks/InsideStack.tsx index a314c801885..26001ec28d2 100644 --- a/app/stacks/InsideStack.tsx +++ b/app/stacks/InsideStack.tsx @@ -66,6 +66,7 @@ import ModalBlockView from '../views/ModalBlockView'; import JitsiMeetView from '../views/JitsiMeetView'; import StatusView from '../views/StatusView'; import ShareView from '../views/ShareView'; +import CallView from '../views/CallView'; import CreateDiscussionView from '../views/CreateDiscussionView'; import ForwardMessageView from '../views/ForwardMessageView'; import QueueListView from '../ee/omnichannel/views/QueueListView'; @@ -339,6 +340,7 @@ const InsideStackNavigator = () => { {/* @ts-ignore */} + ); }; diff --git a/app/stacks/types.ts b/app/stacks/types.ts index c8afff63863..02d606a5833 100644 --- a/app/stacks/types.ts +++ b/app/stacks/types.ts @@ -296,6 +296,9 @@ export type InsideStackParamList = { ModalBlockView: { data: any; // TODO: Change; }; + CallView: { + callUUID: string; + }; }; export type OutsideParamList = { diff --git a/app/views/CallView/components/CallActionButton.tsx b/app/views/CallView/components/CallActionButton.tsx new file mode 100644 index 00000000000..de6122c29b9 --- /dev/null +++ b/app/views/CallView/components/CallActionButton.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { Text, View } from 'react-native'; +import Touchable from 'react-native-platform-touchable'; + +import { CustomIcon, type TIconsName } from '../../../containers/CustomIcon'; +import { styles } from '../styles'; + +type TCallActionButtonVariant = 'default' | 'active' | 'danger'; + +interface ICallActionButton { + icon: TIconsName; + label: string; + onPress: () => void; + variant?: TCallActionButtonVariant; + disabled?: boolean; + testID?: string; +} + +const CallActionButton = ({ + icon, + label, + onPress, + variant = 'default', + disabled = false, + testID +}: ICallActionButton): React.ReactElement => { + const getIconStyle = () => { + switch (variant) { + case 'active': + return styles.actionButtonIconActive; + case 'danger': + return styles.actionButtonIconDanger; + default: + return styles.actionButtonIconDefault; + } + }; + + const getIconColor = () => { + switch (variant) { + case 'active': + return '#1F2329'; + case 'danger': + return '#FFFFFF'; + default: + return '#FFFFFF'; + } + }; + + return ( + + + + + {label} + + ); +}; + +export default CallActionButton; diff --git a/app/views/CallView/components/CallStatusText.tsx b/app/views/CallView/components/CallStatusText.tsx new file mode 100644 index 00000000000..bbc4fa76cc8 --- /dev/null +++ b/app/views/CallView/components/CallStatusText.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { Text, View } from 'react-native'; + +import I18n from '../../../i18n'; +import { styles } from '../styles'; + +interface ICallStatusText { + isOnHold?: boolean; + isMuted?: boolean; +} + +const CallStatusText = ({ isOnHold = false, isMuted = false }: ICallStatusText): React.ReactElement | null => { + if (!isOnHold && !isMuted) { + return null; + } + + const getStatusText = (): React.ReactNode => { + if (isOnHold && isMuted) { + return ( + <> + {I18n.t('On_hold')}, + {I18n.t('Muted')} + + ); + } + if (isOnHold) { + return {I18n.t('On_hold')}; + } + if (isMuted) { + return {I18n.t('Muted')}; + } + return null; + }; + + return {getStatusText()}; +}; + +export default CallStatusText; diff --git a/app/views/CallView/components/CallTimer.tsx b/app/views/CallView/components/CallTimer.tsx new file mode 100644 index 00000000000..cd00758fc73 --- /dev/null +++ b/app/views/CallView/components/CallTimer.tsx @@ -0,0 +1,31 @@ +import React, { useEffect, useState } from 'react'; + +interface ICallTimer { + startTime: number; +} + +const formatDuration = (seconds: number): string => { + const mins = Math.floor(seconds / 60); + const secs = seconds % 60; + return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; +}; + +const CallTimer = ({ startTime }: ICallTimer): string => { + const [elapsed, setElapsed] = useState(0); + + useEffect(() => { + const updateElapsed = () => { + const now = Date.now(); + setElapsed(Math.floor((now - startTime) / 1000)); + }; + + updateElapsed(); + const interval = setInterval(updateElapsed, 1000); + + return () => clearInterval(interval); + }, [startTime]); + + return formatDuration(elapsed); +}; + +export default CallTimer; diff --git a/app/views/CallView/components/CallerInfo.tsx b/app/views/CallView/components/CallerInfo.tsx new file mode 100644 index 00000000000..94cd74e2bc1 --- /dev/null +++ b/app/views/CallView/components/CallerInfo.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Text, View } from 'react-native'; + +import AvatarContainer from '../../../containers/Avatar'; +import { CustomIcon } from '../../../containers/CustomIcon'; +import { styles } from '../styles'; + +interface ICallerInfo { + name: string; + extension?: string; + avatarText?: string; + isMuted?: boolean; + showOnlineStatus?: boolean; +} + +const CallerInfo = ({ name, extension, avatarText, isMuted = false, showOnlineStatus = false }: ICallerInfo): React.ReactElement => ( + + + + {showOnlineStatus && } + + + + {name} + + {isMuted && } + + {extension ? {extension} : null} + +); + +export default CallerInfo; diff --git a/app/views/CallView/index.tsx b/app/views/CallView/index.tsx new file mode 100644 index 00000000000..f55d945faaa --- /dev/null +++ b/app/views/CallView/index.tsx @@ -0,0 +1,242 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { Text, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import { type RouteProp, useNavigation, useRoute } from '@react-navigation/native'; +import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake'; +import RNCallKeep from 'react-native-callkeep'; +import Touchable from 'react-native-platform-touchable'; +import type { IClientMediaCall } from '@rocket.chat/media-signaling'; + +import I18n from '../../i18n'; +import { CustomIcon } from '../../containers/CustomIcon'; +import { mediaSessionStore } from '../../lib/services/voip/MediaSessionStore'; +import { type InsideStackParamList } from '../../stacks/types'; +import CallerInfo from './components/CallerInfo'; +import CallActionButton from './components/CallActionButton'; +import CallStatusText from './components/CallStatusText'; +import CallTimer from './components/CallTimer'; +import { styles } from './styles'; + +const CallView = (): React.ReactElement | null => { + const { + params: { callUUID } + } = useRoute>(); + const { goBack } = useNavigation(); + + const [call, setCall] = useState(null); + const [callState, setCallState] = useState('connecting'); + const [isMuted, setIsMuted] = useState(false); + const [isOnHold, setIsOnHold] = useState(false); + const [isSpeakerOn, setIsSpeakerOn] = useState(false); + const [callStartTime, setCallStartTime] = useState(null); + + // Get call from mediaSessionStore + useEffect(() => { + const session = mediaSessionStore.getCurrentInstance(); + const mainCall = session?.getMainCall(); + + if (mainCall) { + setCall(mainCall); + setCallState(mainCall.state); + setIsMuted(mainCall.muted); + setIsOnHold(mainCall.held); + + // Set call start time when call is active + if (mainCall.state === 'active') { + setCallStartTime(Date.now()); + } + } + + return () => { + // Cleanup + }; + }, []); + + // Subscribe to call state changes + useEffect(() => { + if (!call) { + return; + } + + const handleStateChange = () => { + setCallState(call.state); + + // Set start time when call becomes active + if (call.state === 'active' && !callStartTime) { + setCallStartTime(Date.now()); + } + }; + + const handleTrackStateChange = () => { + setIsMuted(call.muted); + setIsOnHold(call.held); + }; + + const handleEnded = () => { + goBack(); + }; + + call.emitter.on('stateChange', handleStateChange); + call.emitter.on('trackStateChange', handleTrackStateChange); + call.emitter.on('ended', handleEnded); + + return () => { + call.emitter.off('stateChange', handleStateChange); + call.emitter.off('trackStateChange', handleTrackStateChange); + call.emitter.off('ended', handleEnded); + }; + }, [call, callStartTime, goBack]); + + // Keep screen awake during call + useEffect(() => { + activateKeepAwake(); + return () => { + deactivateKeepAwake(); + }; + }, []); + + const handleToggleSpeaker = useCallback(() => { + // TODO: Implement speaker toggle via RNCallKeep or WebRTC audio routing + setIsSpeakerOn(prev => !prev); + }, []); + + const handleToggleHold = useCallback(() => { + if (!call) { + return; + } + call.setHeld(!isOnHold); + }, [call, isOnHold]); + + const handleToggleMute = useCallback(() => { + if (!call) { + return; + } + call.setMuted(!isMuted); + }, [call, isMuted]); + + const handleMessage = useCallback(() => { + // TODO: Navigate to chat with caller + // Navigation.navigate('RoomView', { rid, t: 'd' }); + }, []); + + const handleEndCall = useCallback(() => { + if (!call) { + RNCallKeep.endCall(callUUID); + goBack(); + return; + } + + if (callState === 'ringing') { + call.reject(); + } else { + call.hangup(); + } + RNCallKeep.endCall(callUUID); + }, [call, callState, callUUID, goBack]); + + const handleMore = useCallback(() => { + // TODO: Show action sheet with more options (DTMF, transfer, etc.) + }, []); + + const handleMinimize = useCallback(() => { + goBack(); + }, [goBack]); + + if (!call) { + return null; + } + + const callerName = call.contact.displayName || call.contact.username || I18n.t('Unknown'); + const callerExtension = call.contact.sipExtension; + const isConnecting = callState === 'connecting' || callState === 'ringing'; + const isConnected = callState === 'active'; + + const getHeaderTitle = () => { + if (isConnecting) { + return I18n.t('Connecting'); + } + if (isConnected && callStartTime) { + return `${callerName} – ${CallTimer({ startTime: callStartTime })}`; + } + return callerName; + }; + + return ( + + + {/* Header */} + + + + + {getHeaderTitle()} + + + + + + {/* Caller Info */} + + + {/* Status Text */} + {isConnected && } + + {/* Action Buttons */} + + {/* First row of buttons */} + + + + + + + {/* Second row of buttons */} + + + + + + + + + ); +}; + +export default CallView; diff --git a/app/views/CallView/styles.ts b/app/views/CallView/styles.ts new file mode 100644 index 00000000000..39487a74346 --- /dev/null +++ b/app/views/CallView/styles.ts @@ -0,0 +1,124 @@ +import { StyleSheet } from 'react-native'; + +import sharedStyles from '../Styles'; + +// Dark background color matching the mockups +export const CALL_BACKGROUND_COLOR = '#1F2329'; + +export const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: CALL_BACKGROUND_COLOR + }, + contentContainer: { + flex: 1, + justifyContent: 'space-between', + paddingBottom: 32 + }, + header: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 16, + paddingVertical: 12 + }, + headerTitle: { + ...sharedStyles.textSemibold, + fontSize: 16, + color: '#FFFFFF' + }, + headerButton: { + padding: 8 + }, + callerInfoContainer: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + paddingHorizontal: 24 + }, + avatarContainer: { + marginBottom: 16, + position: 'relative' + }, + statusIndicator: { + position: 'absolute', + bottom: 4, + right: 4, + width: 16, + height: 16, + borderRadius: 8, + backgroundColor: '#158D65', + borderWidth: 2, + borderColor: CALL_BACKGROUND_COLOR + }, + callerName: { + ...sharedStyles.textBold, + fontSize: 24, + color: '#FFFFFF', + textAlign: 'center', + marginBottom: 4 + }, + callerNameRow: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center' + }, + mutedIndicator: { + marginLeft: 8 + }, + callerExtension: { + ...sharedStyles.textRegular, + fontSize: 16, + color: '#9EA2A8', + textAlign: 'center', + marginBottom: 8 + }, + statusTextContainer: { + marginTop: 24 + }, + statusText: { + ...sharedStyles.textRegular, + fontSize: 16, + color: '#9EA2A8', + textAlign: 'center' + }, + statusTextHighlight: { + color: '#F5455C' + }, + buttonsContainer: { + paddingHorizontal: 24 + }, + buttonsRow: { + flexDirection: 'row', + justifyContent: 'space-around', + marginBottom: 24 + }, + actionButton: { + alignItems: 'center', + justifyContent: 'center', + width: 72 + }, + actionButtonIcon: { + width: 56, + height: 56, + borderRadius: 16, + alignItems: 'center', + justifyContent: 'center', + marginBottom: 8 + }, + actionButtonIconDefault: { + backgroundColor: '#2F343D' + }, + actionButtonIconActive: { + backgroundColor: '#FFFFFF' + }, + actionButtonIconDanger: { + backgroundColor: '#F5455C' + }, + actionButtonLabel: { + ...sharedStyles.textRegular, + fontSize: 12, + color: '#FFFFFF', + textAlign: 'center' + } +}); From d2cef3d235fdc27b6de3ce07f8a0a96e1b4e2330 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Tue, 13 Jan 2026 16:38:59 -0300 Subject: [PATCH 04/61] feat(voip): integrate Zustand for call state management and enhance CallView UI --- app/lib/services/voip/MediaSessionInstance.ts | 8 +- app/lib/services/voip/useCallStore.ts | 185 +++++++++++++++ app/views/CallView/CallView.stories.tsx | 126 +++++++++++ .../components/CallActionButton.stories.tsx | 63 ++++++ .../components/CallActionButton.test.tsx | 60 +++++ .../CallView/components/CallActionButton.tsx | 39 ++-- .../CallView/components/CallStatusText.tsx | 50 ++--- app/views/CallView/components/CallTimer.tsx | 15 +- .../components/CallerInfo.stories.tsx | 62 +++++ .../CallView/components/CallerInfo.test.tsx | 112 ++++++++++ app/views/CallView/components/CallerInfo.tsx | 61 +++-- app/views/CallView/index.tsx | 211 +++++------------- app/views/CallView/styles.ts | 64 ++---- package.json | 3 +- yarn.lock | 5 + 15 files changed, 788 insertions(+), 276 deletions(-) create mode 100644 app/lib/services/voip/useCallStore.ts create mode 100644 app/views/CallView/CallView.stories.tsx create mode 100644 app/views/CallView/components/CallActionButton.stories.tsx create mode 100644 app/views/CallView/components/CallActionButton.test.tsx create mode 100644 app/views/CallView/components/CallerInfo.stories.tsx create mode 100644 app/views/CallView/components/CallerInfo.test.tsx diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 05e4f99cb81..a54a4855d36 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -10,6 +10,7 @@ import { registerGlobals } from 'react-native-webrtc'; import { randomUuid } from '@rocket.chat/mobile-crypto'; import { mediaSessionStore } from './MediaSessionStore'; +import { useCallStore } from './useCallStore'; import { store } from '../../store/auxStore'; import sdk from '../sdk'; import Navigation from '../../navigation/appNavigation'; @@ -91,7 +92,8 @@ class MediaSessionInstance { if (mainCall && mainCall.callId === callId) { await mainCall.accept(); RNCallKeep.setCurrentCallActive(callUUID); - // Navigate to CallView - call data fetched from mediaSessionStore + // Set call in Zustand store and navigate to CallView + useCallStore.getState().setCall(mainCall, callUUID); Navigation.navigate('CallView', { callUUID }); } else { RNCallKeep.endCall(callUUID); @@ -108,6 +110,8 @@ class MediaSessionInstance { mainCall.hangup(); } } + // Reset Zustand store + useCallStore.getState().reset(); delete localCallIdMap[callUUID]; }); @@ -118,6 +122,8 @@ class MediaSessionInstance { const mainCall = this.instance?.getMainCall(); if (mainCall && mainCall.callId === callId) { mainCall.setMuted(muted); + // Sync with Zustand store + useCallStore.getState().updateFromCall(); } } ); diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts new file mode 100644 index 00000000000..373eca56091 --- /dev/null +++ b/app/lib/services/voip/useCallStore.ts @@ -0,0 +1,185 @@ +import { create } from 'zustand'; +import { useShallow } from 'zustand/react/shallow'; +import type { CallState, IClientMediaCall } from '@rocket.chat/media-signaling'; +import RNCallKeep from 'react-native-callkeep'; + +import Navigation from '../../navigation/appNavigation'; + +interface CallContact { + displayName?: string; + username?: string; + sipExtension?: string; +} + +interface CallStoreState { + // Call reference + call: IClientMediaCall | null; + callUUID: string | null; + + // Call state + callState: CallState; + isMuted: boolean; + isOnHold: boolean; + isSpeakerOn: boolean; + callStartTime: number | null; + + // Contact info + contact: CallContact; +} + +interface CallStoreActions { + setCall: (call: IClientMediaCall, callUUID: string) => void; + updateFromCall: () => void; + toggleMute: () => void; + toggleHold: () => void; + toggleSpeaker: () => void; + endCall: () => void; + reset: () => void; +} + +export type CallStore = CallStoreState & CallStoreActions; + +const initialState: CallStoreState = { + call: null, + callUUID: null, + callState: 'none', + isMuted: false, + isOnHold: false, + isSpeakerOn: false, + callStartTime: null, + contact: {} +}; + +export const useCallStore = create((set, get) => ({ + ...initialState, + + setCall: (call: IClientMediaCall, callUUID: string) => { + // Update state with call info + set({ + call, + callUUID, + callState: call.state, + isMuted: call.muted, + isOnHold: call.held, + // isSpeakerOn: call. + contact: { + displayName: call.contact.displayName, + username: call.contact.username, + sipExtension: call.contact.sipExtension + }, + callStartTime: call.state === 'active' ? Date.now() : null + }); + + // Subscribe to call events + const handleStateChange = () => { + const currentCall = get().call; + if (!currentCall) return; + + const newState = currentCall.state; + set({ callState: newState }); + + // Set start time when call becomes active + if (newState === 'active' && !get().callStartTime) { + set({ callStartTime: Date.now() }); + } + }; + + const handleTrackStateChange = () => { + const currentCall = get().call; + if (!currentCall) return; + + set({ + isMuted: currentCall.muted, + isOnHold: currentCall.held + }); + }; + + const handleEnded = () => { + get().reset(); + Navigation.back(); + }; + + call.emitter.on('stateChange', handleStateChange); + call.emitter.on('trackStateChange', handleTrackStateChange); + call.emitter.on('ended', handleEnded); + }, + + updateFromCall: () => { + const { call } = get(); + if (!call) return; + + set({ + callState: call.state, + isMuted: call.muted, + isOnHold: call.held, + contact: { + displayName: call.contact.displayName, + username: call.contact.username, + sipExtension: call.contact.sipExtension + } + }); + }, + + toggleMute: () => { + const { call, isMuted } = get(); + if (!call) return; + + call.setMuted(!isMuted); + set({ isMuted: !isMuted }); + }, + + toggleHold: () => { + const { call, isOnHold } = get(); + if (!call) return; + + call.setHeld(!isOnHold); + set({ isOnHold: !isOnHold }); + }, + + toggleSpeaker: () => { + const { isSpeakerOn } = get(); + // TODO: Implement actual speaker toggle via RNCallKeep or WebRTC audio routing + set({ isSpeakerOn: !isSpeakerOn }); + }, + + endCall: () => { + const { call, callState, callUUID } = get(); + + if (call) { + if (callState === 'ringing') { + call.reject(); + } else { + call.hangup(); + } + } + + if (callUUID) { + RNCallKeep.endCall(callUUID); + } + + get().reset(); + }, + + reset: () => { + set(initialState); + } +})); + +// Selector hooks for better performance +export const useCallState = () => useCallStore(state => state.callState); +export const useCallContact = () => useCallStore(state => state.contact); +export const useCallControls = () => + useCallStore( + useShallow(state => ({ + isMuted: state.isMuted, + isOnHold: state.isOnHold, + isSpeakerOn: state.isSpeakerOn + })) + ); +export const useCallActions = () => + useCallStore(state => ({ + toggleMute: state.toggleMute, + toggleHold: state.toggleHold, + toggleSpeaker: state.toggleSpeaker, + endCall: state.endCall + })); diff --git a/app/views/CallView/CallView.stories.tsx b/app/views/CallView/CallView.stories.tsx new file mode 100644 index 00000000000..a57029eb652 --- /dev/null +++ b/app/views/CallView/CallView.stories.tsx @@ -0,0 +1,126 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; +import { NavigationContainer } from '@react-navigation/native'; + +import CallView from '.'; +import { useCallStore } from '../../lib/services/voip/useCallStore'; +import { CALL_BACKGROUND_COLOR } from './styles'; +import { + BASE_ROW_HEIGHT, + BASE_ROW_HEIGHT_CONDENSED, + ResponsiveLayoutContext +} from '../../lib/hooks/useResponsiveLayout/useResponsiveLayout'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: CALL_BACKGROUND_COLOR + } +}); + +// Mock navigation +// jest.mock('@react-navigation/native', () => ({ +// ...jest.requireActual('@react-navigation/native'), +// useNavigation: () => ({ +// goBack: () => {} +// }), +// useRoute: () => ({ +// params: { callUUID: 'test-uuid' } +// }) +// })); + +// Helper to set store state for stories +const setStoreState = (overrides: Partial> = {}) => { + const mockCall = { + state: 'active', + muted: false, + held: false, + contact: { + displayName: 'Bob Burnquist', + username: 'bob.burnquist', + sipExtension: '2244' + }, + setMuted: () => {}, + setHeld: () => {}, + hangup: () => {}, + reject: () => {}, + emitter: { + on: () => {}, + off: () => {} + } + } as any; + + useCallStore.setState({ + call: mockCall, + callUUID: 'test-uuid', + callState: 'active', + isMuted: false, + isOnHold: false, + isSpeakerOn: false, + callStartTime: Date.now(), + contact: { + displayName: 'Bob Burnquist', + username: 'bob.burnquist', + sipExtension: '2244' + }, + ...overrides + }); +}; + +const responsiveLayoutProviderLargeFontValue = (fontScale: number) => ({ + fontScale, + fontScaleLimited: fontScale, + isLargeFontScale: fontScale > 1, + rowHeight: BASE_ROW_HEIGHT * fontScale, + rowHeightCondensed: BASE_ROW_HEIGHT_CONDENSED * fontScale, + width: 350, + height: 800 +}); + +const Wrapper = ({ children }: { children: React.ReactNode }) => {children}; + +export default { + title: 'CallView', + component: CallView, + decorators: [ + (Story: React.ComponentType) => ( + + + + + + + + ) + ] +}; + +export const ConnectedCall = () => { + setStoreState({ callState: 'active', callStartTime: Date.now() - 61000 }); + return ; +}; + +export const ConnectingCall = () => { + setStoreState({ callState: 'accepted', callStartTime: null }); + return ; +}; + +export const MutedCall = () => { + setStoreState({ callState: 'active', isMuted: true }); + return ; +}; + +export const OnHoldCall = () => { + setStoreState({ callState: 'active', isOnHold: true }); + return ; +}; + +export const MutedAndOnHold = () => { + setStoreState({ callState: 'active', isMuted: true, isOnHold: true }); + return ; +}; + +export const SpeakerOn = () => { + setStoreState({ callState: 'active', isSpeakerOn: true }); + return ; +}; diff --git a/app/views/CallView/components/CallActionButton.stories.tsx b/app/views/CallView/components/CallActionButton.stories.tsx new file mode 100644 index 00000000000..1e475a189eb --- /dev/null +++ b/app/views/CallView/components/CallActionButton.stories.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; + +import CallActionButton from './CallActionButton'; +import { CALL_BACKGROUND_COLOR } from '../styles'; + +const styles = StyleSheet.create({ + container: { + backgroundColor: CALL_BACKGROUND_COLOR, + padding: 24, + alignItems: 'center' + }, + row: { + flexDirection: 'row', + gap: 16 + } +}); + +const Wrapper = ({ children }: { children: React.ReactNode }) => {children}; + +export default { + title: 'CallActionButton', + component: CallActionButton +}; + +export const DefaultButton = () => ( + + {}} testID='call-action-button' /> + +); + +export const ActiveButton = () => ( + + {}} variant='active' testID='call-action-button' /> + +); + +export const DangerButton = () => ( + + {}} variant='danger' testID='call-action-button' /> + +); + +export const DisabledButton = () => ( + + {}} disabled testID='call-action-button' /> + +); + +export const AllVariants = () => ( + + + {}} testID='speaker' /> + {}} testID='hold' /> + {}} testID='mute' /> + + + {}} testID='message' /> + {}} variant='danger' testID='end' /> + {}} testID='more' /> + + +); diff --git a/app/views/CallView/components/CallActionButton.test.tsx b/app/views/CallView/components/CallActionButton.test.tsx new file mode 100644 index 00000000000..ac8791834cc --- /dev/null +++ b/app/views/CallView/components/CallActionButton.test.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; + +import CallActionButton from './CallActionButton'; +import * as stories from './CallActionButton.stories'; +import { generateSnapshots } from '../../../../.rnstorybook/generateSnapshots'; + +const onPressMock = jest.fn(); + +describe('CallActionButton', () => { + beforeEach(() => { + onPressMock.mockClear(); + }); + + it('should render correctly', () => { + const { getByTestId } = render( + + ); + expect(getByTestId('call-action-button')).toBeTruthy(); + }); + + it('should display the correct label', () => { + const { getByText } = render( + + ); + expect(getByText('Mute')).toBeTruthy(); + }); + + it('should call onPress when pressed', () => { + const { getByTestId } = render( + + ); + fireEvent.press(getByTestId('call-action-button')); + expect(onPressMock).toHaveBeenCalledTimes(1); + }); + + it('should not call onPress when disabled', () => { + const { getByTestId } = render( + + ); + fireEvent.press(getByTestId('call-action-button')); + expect(onPressMock).not.toHaveBeenCalled(); + }); + + it('should render with active variant', () => { + const { getByTestId } = render( + + ); + expect(getByTestId('call-action-button')).toBeTruthy(); + }); + + it('should render with danger variant', () => { + const { getByTestId } = render( + + ); + expect(getByTestId('call-action-button')).toBeTruthy(); + }); +}); + +generateSnapshots(stories); diff --git a/app/views/CallView/components/CallActionButton.tsx b/app/views/CallView/components/CallActionButton.tsx index de6122c29b9..bd8454b9e17 100644 --- a/app/views/CallView/components/CallActionButton.tsx +++ b/app/views/CallView/components/CallActionButton.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import { Text, View } from 'react-native'; -import Touchable from 'react-native-platform-touchable'; +import { Text, View, Pressable } from 'react-native'; import { CustomIcon, type TIconsName } from '../../../containers/CustomIcon'; import { styles } from '../styles'; +import { useTheme } from '../../../theme'; type TCallActionButtonVariant = 'default' | 'active' | 'danger'; @@ -24,41 +24,38 @@ const CallActionButton = ({ disabled = false, testID }: ICallActionButton): React.ReactElement => { - const getIconStyle = () => { - switch (variant) { - case 'active': - return styles.actionButtonIconActive; - case 'danger': - return styles.actionButtonIconDanger; - default: - return styles.actionButtonIconDefault; - } - }; + const { colors } = useTheme(); const getIconColor = () => { switch (variant) { case 'active': - return '#1F2329'; + return colors.buttonFontSecondaryDanger; case 'danger': - return '#FFFFFF'; + return colors.buttonFontDanger; default: - return '#FFFFFF'; + return colors.buttonFontSecondary; } }; return ( - - - + + - {label} - + {label} + ); }; diff --git a/app/views/CallView/components/CallStatusText.tsx b/app/views/CallView/components/CallStatusText.tsx index bbc4fa76cc8..305c4b66ea1 100644 --- a/app/views/CallView/components/CallStatusText.tsx +++ b/app/views/CallView/components/CallStatusText.tsx @@ -1,38 +1,34 @@ import React from 'react'; -import { Text, View } from 'react-native'; +import { Text } from 'react-native'; import I18n from '../../../i18n'; import { styles } from '../styles'; +import { useCallControls } from '../../../lib/services/voip/useCallStore'; +import { useTheme } from '../../../theme'; -interface ICallStatusText { - isOnHold?: boolean; - isMuted?: boolean; -} +const CallStatusText = (): React.ReactElement => { + 'use memo'; -const CallStatusText = ({ isOnHold = false, isMuted = false }: ICallStatusText): React.ReactElement | null => { - if (!isOnHold && !isMuted) { - return null; - } + const { isMuted, isOnHold } = useCallControls(); + const { colors } = useTheme(); - const getStatusText = (): React.ReactNode => { - if (isOnHold && isMuted) { - return ( - <> - {I18n.t('On_hold')}, - {I18n.t('Muted')} - - ); - } - if (isOnHold) { - return {I18n.t('On_hold')}; - } - if (isMuted) { - return {I18n.t('Muted')}; - } - return null; - }; + if (isOnHold && isMuted) { + return ( + <> + + {I18n.t('On_hold')}, {I18n.t('Muted')} + + + ); + } + if (isOnHold) { + return {I18n.t('On_hold')}; + } + if (isMuted) { + return {I18n.t('Muted')}; + } - return {getStatusText()}; + return  ; }; export default CallStatusText; diff --git a/app/views/CallView/components/CallTimer.tsx b/app/views/CallView/components/CallTimer.tsx index cd00758fc73..0b36993f60d 100644 --- a/app/views/CallView/components/CallTimer.tsx +++ b/app/views/CallView/components/CallTimer.tsx @@ -1,8 +1,4 @@ -import React, { useEffect, useState } from 'react'; - -interface ICallTimer { - startTime: number; -} +import { useEffect, useState } from 'react'; const formatDuration = (seconds: number): string => { const mins = Math.floor(seconds / 60); @@ -10,10 +6,15 @@ const formatDuration = (seconds: number): string => { return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; }; -const CallTimer = ({ startTime }: ICallTimer): string => { +export const useCallTimer = (startTime: number | null): string => { const [elapsed, setElapsed] = useState(0); useEffect(() => { + if (!startTime) { + setElapsed(0); + return; + } + const updateElapsed = () => { const now = Date.now(); setElapsed(Math.floor((now - startTime) / 1000)); @@ -27,5 +28,3 @@ const CallTimer = ({ startTime }: ICallTimer): string => { return formatDuration(elapsed); }; - -export default CallTimer; diff --git a/app/views/CallView/components/CallerInfo.stories.tsx b/app/views/CallView/components/CallerInfo.stories.tsx new file mode 100644 index 00000000000..db9afd358e0 --- /dev/null +++ b/app/views/CallView/components/CallerInfo.stories.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; + +import CallerInfo from './CallerInfo'; +import { CALL_BACKGROUND_COLOR } from '../styles'; +import { useCallStore } from '../../../lib/services/voip/useCallStore'; + +const styles = StyleSheet.create({ + container: { + backgroundColor: CALL_BACKGROUND_COLOR, + padding: 24, + flex: 1, + minHeight: 300 + } +}); + +const Wrapper = ({ children }: { children: React.ReactNode }) => {children}; + +// Helper to set store state for stories +const setStoreState = (contact: { displayName?: string; username?: string; sipExtension?: string }) => { + useCallStore.setState({ + contact, + call: {} as any, + callUUID: 'test-uuid', + callState: 'active', + isMuted: false, + isOnHold: false, + isSpeakerOn: false, + callStartTime: Date.now() + }); +}; + +export default { + title: 'CallerInfo', + component: CallerInfo, + decorators: [ + (Story: React.ComponentType) => { + setStoreState({ displayName: 'Bob Burnquist', username: 'bob.burnquist', sipExtension: '2244' }); + return ( + + + + ); + } + ] +}; + +export const Default = () => ; + +export const WithOnlineStatus = () => ; + +export const WithMutedIndicator = () => ; + +export const NoExtension = () => { + setStoreState({ displayName: 'Alice Attali', username: 'alice.attali' }); + return ; +}; + +export const UsernameOnly = () => { + setStoreState({ username: 'john.doe' }); + return ; +}; diff --git a/app/views/CallView/components/CallerInfo.test.tsx b/app/views/CallView/components/CallerInfo.test.tsx new file mode 100644 index 00000000000..752cf6b0236 --- /dev/null +++ b/app/views/CallView/components/CallerInfo.test.tsx @@ -0,0 +1,112 @@ +import React from 'react'; +import { render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import CallerInfo from './CallerInfo'; +import { useCallStore } from '../../../lib/services/voip/useCallStore'; +import { mockedStore } from '../../../reducers/mockedStore'; +import * as stories from './CallerInfo.stories'; +import { generateSnapshots } from '../../../../.rnstorybook/generateSnapshots'; + +// Helper to set store state for tests +const setStoreState = (contact: { displayName?: string; username?: string; sipExtension?: string }) => { + useCallStore.setState({ + contact, + call: {} as any, + callUUID: 'test-uuid', + callState: 'active', + isMuted: false, + isOnHold: false, + isSpeakerOn: false, + callStartTime: Date.now() + }); +}; + +const Wrapper = ({ children }: { children: React.ReactNode }) => {children}; + +describe('CallerInfo', () => { + beforeEach(() => { + useCallStore.getState().reset(); + }); + + it('should render with display name', () => { + setStoreState({ displayName: 'Bob Burnquist', username: 'bob.burnquist', sipExtension: '2244' }); + const { getByTestId, getByText } = render( + + + + ); + + expect(getByTestId('caller-info')).toBeTruthy(); + expect(getByText('Bob Burnquist')).toBeTruthy(); + expect(getByText('2244')).toBeTruthy(); + }); + + it('should render with username when no display name', () => { + setStoreState({ username: 'john.doe' }); + const { getByText } = render( + + + + ); + + expect(getByText('john.doe')).toBeTruthy(); + }); + + it('should show online status indicator when showOnlineStatus is true', () => { + setStoreState({ displayName: 'Test User' }); + const { getByTestId } = render( + + + + ); + + expect(getByTestId('caller-info-status')).toBeTruthy(); + }); + + it('should not show online status indicator when showOnlineStatus is false', () => { + setStoreState({ displayName: 'Test User' }); + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('caller-info-status')).toBeNull(); + }); + + it('should show muted indicator when isMuted is true', () => { + setStoreState({ displayName: 'Test User' }); + const { getByTestId } = render( + + + + ); + + expect(getByTestId('caller-info-muted')).toBeTruthy(); + }); + + it('should not show muted indicator when isMuted is false', () => { + setStoreState({ displayName: 'Test User' }); + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('caller-info-muted')).toBeNull(); + }); + + it('should not show extension when not provided', () => { + setStoreState({ displayName: 'Test User' }); + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('caller-info-extension')).toBeNull(); + }); +}); + +generateSnapshots(stories); diff --git a/app/views/CallView/components/CallerInfo.tsx b/app/views/CallView/components/CallerInfo.tsx index 94cd74e2bc1..cb9231ad0bc 100644 --- a/app/views/CallView/components/CallerInfo.tsx +++ b/app/views/CallView/components/CallerInfo.tsx @@ -3,30 +3,55 @@ import { Text, View } from 'react-native'; import AvatarContainer from '../../../containers/Avatar'; import { CustomIcon } from '../../../containers/CustomIcon'; +import I18n from '../../../i18n'; +import { useCallContact } from '../../../lib/services/voip/useCallStore'; import { styles } from '../styles'; +import { useTheme } from '../../../theme'; +// import Status from '../../../containers/Status'; +import sharedStyles from '../../Styles'; interface ICallerInfo { - name: string; - extension?: string; - avatarText?: string; isMuted?: boolean; - showOnlineStatus?: boolean; } -const CallerInfo = ({ name, extension, avatarText, isMuted = false, showOnlineStatus = false }: ICallerInfo): React.ReactElement => ( - - - - {showOnlineStatus && } - - - - {name} - - {isMuted && } +const CallerInfo = ({ isMuted = false }: ICallerInfo): React.ReactElement => { + const { colors } = useTheme(); + const contact = useCallContact(); + + const name = contact.displayName || contact.username || I18n.t('Unknown'); + const extension = contact.sipExtension; + const avatarText = contact.username || name; + + return ( + + + + + {/* */} + + + + + + {name} + + {isMuted && ( + + )} + + {extension ? ( + + {extension} + + ) : null} - {extension ? {extension} : null} - -); + ); +}; export default CallerInfo; diff --git a/app/views/CallView/index.tsx b/app/views/CallView/index.tsx index f55d945faaa..f9b316883e4 100644 --- a/app/views/CallView/index.tsx +++ b/app/views/CallView/index.tsx @@ -1,154 +1,74 @@ -import React, { useCallback, useEffect, useState } from 'react'; -import { Text, View } from 'react-native'; +import React, { useEffect } from 'react'; +import { Text, View, Pressable } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; -import { type RouteProp, useNavigation, useRoute } from '@react-navigation/native'; -import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake'; -import RNCallKeep from 'react-native-callkeep'; -import Touchable from 'react-native-platform-touchable'; -import type { IClientMediaCall } from '@rocket.chat/media-signaling'; +import { useNavigation } from '@react-navigation/native'; +import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake'; import I18n from '../../i18n'; import { CustomIcon } from '../../containers/CustomIcon'; -import { mediaSessionStore } from '../../lib/services/voip/MediaSessionStore'; -import { type InsideStackParamList } from '../../stacks/types'; +import { useCallStore } from '../../lib/services/voip/useCallStore'; import CallerInfo from './components/CallerInfo'; import CallActionButton from './components/CallActionButton'; import CallStatusText from './components/CallStatusText'; -import CallTimer from './components/CallTimer'; +// import { useCallTimer } from './components/CallTimer'; import { styles } from './styles'; +import { useTheme } from '../../theme'; const CallView = (): React.ReactElement | null => { - const { - params: { callUUID } - } = useRoute>(); const { goBack } = useNavigation(); - - const [call, setCall] = useState(null); - const [callState, setCallState] = useState('connecting'); - const [isMuted, setIsMuted] = useState(false); - const [isOnHold, setIsOnHold] = useState(false); - const [isSpeakerOn, setIsSpeakerOn] = useState(false); - const [callStartTime, setCallStartTime] = useState(null); - - // Get call from mediaSessionStore - useEffect(() => { - const session = mediaSessionStore.getCurrentInstance(); - const mainCall = session?.getMainCall(); - - if (mainCall) { - setCall(mainCall); - setCallState(mainCall.state); - setIsMuted(mainCall.muted); - setIsOnHold(mainCall.held); - - // Set call start time when call is active - if (mainCall.state === 'active') { - setCallStartTime(Date.now()); - } - } - - return () => { - // Cleanup - }; - }, []); - - // Subscribe to call state changes - useEffect(() => { - if (!call) { - return; - } - - const handleStateChange = () => { - setCallState(call.state); - - // Set start time when call becomes active - if (call.state === 'active' && !callStartTime) { - setCallStartTime(Date.now()); - } - }; - - const handleTrackStateChange = () => { - setIsMuted(call.muted); - setIsOnHold(call.held); - }; - - const handleEnded = () => { - goBack(); - }; - - call.emitter.on('stateChange', handleStateChange); - call.emitter.on('trackStateChange', handleTrackStateChange); - call.emitter.on('ended', handleEnded); - - return () => { - call.emitter.off('stateChange', handleStateChange); - call.emitter.off('trackStateChange', handleTrackStateChange); - call.emitter.off('ended', handleEnded); - }; - }, [call, callStartTime, goBack]); + const { colors } = useTheme(); + + // Get state from store + const call = useCallStore(state => state.call); + const callState = useCallStore(state => state.callState); + const isMuted = useCallStore(state => state.isMuted); + const isOnHold = useCallStore(state => state.isOnHold); + const isSpeakerOn = useCallStore(state => state.isSpeakerOn); + const callStartTime = useCallStore(state => state.callStartTime); + const contact = useCallStore(state => state.contact); + + // Get actions from store + const toggleMute = useCallStore(state => state.toggleMute); + const toggleHold = useCallStore(state => state.toggleHold); + const toggleSpeaker = useCallStore(state => state.toggleSpeaker); + const endCall = useCallStore(state => state.endCall); + + // Get formatted call duration + // const callDuration = useCallTimer(callStartTime); + const callDuration = '00:00'; // Keep screen awake during call useEffect(() => { - activateKeepAwake(); + activateKeepAwakeAsync(); return () => { deactivateKeepAwake(); }; }, []); - const handleToggleSpeaker = useCallback(() => { - // TODO: Implement speaker toggle via RNCallKeep or WebRTC audio routing - setIsSpeakerOn(prev => !prev); - }, []); - - const handleToggleHold = useCallback(() => { - if (!call) { - return; - } - call.setHeld(!isOnHold); - }, [call, isOnHold]); - - const handleToggleMute = useCallback(() => { - if (!call) { - return; - } - call.setMuted(!isMuted); - }, [call, isMuted]); - - const handleMessage = useCallback(() => { + const handleMessage = () => { // TODO: Navigate to chat with caller // Navigation.navigate('RoomView', { rid, t: 'd' }); - }, []); - - const handleEndCall = useCallback(() => { - if (!call) { - RNCallKeep.endCall(callUUID); - goBack(); - return; - } - - if (callState === 'ringing') { - call.reject(); - } else { - call.hangup(); - } - RNCallKeep.endCall(callUUID); - }, [call, callState, callUUID, goBack]); + }; - const handleMore = useCallback(() => { + const handleMore = () => { // TODO: Show action sheet with more options (DTMF, transfer, etc.) - }, []); + }; + + const handleMinimize = () => { + goBack(); + }; - const handleMinimize = useCallback(() => { + const handleEndCall = () => { + endCall(); goBack(); - }, [goBack]); + }; if (!call) { return null; } - const callerName = call.contact.displayName || call.contact.username || I18n.t('Unknown'); - const callerExtension = call.contact.sipExtension; - const isConnecting = callState === 'connecting' || callState === 'ringing'; + const callerName = contact.displayName || contact.username || I18n.t('Unknown'); + const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; const isConnected = callState === 'active'; const getHeaderTitle = () => { @@ -156,36 +76,32 @@ const CallView = (): React.ReactElement | null => { return I18n.t('Connecting'); } if (isConnected && callStartTime) { - return `${callerName} – ${CallTimer({ startTime: callStartTime })}`; + return `${callerName} – ${callDuration}`; } return callerName; }; return ( - - + + {/* Header */} - - - - - {getHeaderTitle()} - - - + + + + + + {getHeaderTitle()} + + + + {/* Caller Info */} - + {/* Status Text */} - {isConnected && } + {isConnected && } {/* Action Buttons */} @@ -194,14 +110,14 @@ const CallView = (): React.ReactElement | null => { { { {/* Second row of buttons */} - + Date: Tue, 13 Jan 2026 16:46:29 -0300 Subject: [PATCH 05/61] feat(voip): add simulateCall function for mock call handling in UI development --- app/lib/services/voip/simulateCall.ts | 106 ++++++++++++++++++ .../RoomView/components/HeaderCallButton.tsx | 34 ++++-- 2 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 app/lib/services/voip/simulateCall.ts diff --git a/app/lib/services/voip/simulateCall.ts b/app/lib/services/voip/simulateCall.ts new file mode 100644 index 00000000000..1777563288d --- /dev/null +++ b/app/lib/services/voip/simulateCall.ts @@ -0,0 +1,106 @@ +import type { CallState, IClientMediaCall } from '@rocket.chat/media-signaling'; +import { randomUuid } from '@rocket.chat/mobile-crypto'; + +import Navigation from '../../navigation/appNavigation'; +import { useCallStore } from './useCallStore'; + +interface SimulateCallOptions { + callState?: CallState; + contact?: { + displayName?: string; + username?: string; + sipExtension?: string; + }; + isMuted?: boolean; + isOnHold?: boolean; +} + +const defaultContact = { + displayName: 'Bob Burnquist', + username: 'bob.burnquist', + sipExtension: '2244' +}; + +/** + * Simulates a call for UI development purposes. + * Creates a mock IClientMediaCall object, sets it in the call store, and navigates to CallView. + */ +export const simulateCall = async (options: SimulateCallOptions = {}): Promise => { + const { callState = 'active', contact = defaultContact, isMuted = false, isOnHold = false } = options; + + // Create a simple event emitter for the mock call + const listeners: Record void>> = {}; + + const emitter = { + on: (event: string, callback: (...args: unknown[]) => void) => { + if (!listeners[event]) { + listeners[event] = new Set(); + } + listeners[event].add(callback); + }, + off: (event: string, callback: (...args: unknown[]) => void) => { + listeners[event]?.delete(callback); + }, + emit: (event: string, ...args: unknown[]) => { + listeners[event]?.forEach(cb => cb(...args)); + } + }; + + // Track mutable state for the mock + let currentMuted = isMuted; + let currentHeld = isOnHold; + let currentState: CallState = callState; + + const mockCall = { + callId: `mock-call-${Date.now()}`, + state: currentState, + get muted() { + return currentMuted; + }, + get held() { + return currentHeld; + }, + contact: { + displayName: contact.displayName, + username: contact.username, + sipExtension: contact.sipExtension + }, + setMuted: (muted: boolean) => { + currentMuted = muted; + emitter.emit('trackStateChange'); + }, + setHeld: (held: boolean) => { + currentHeld = held; + emitter.emit('trackStateChange'); + }, + hangup: () => { + currentState = 'ended' as CallState; + emitter.emit('ended'); + }, + reject: () => { + currentState = 'ended' as CallState; + emitter.emit('ended'); + }, + sendDTMF: (_digits: string) => { + // No-op for simulation + }, + emitter + } as unknown as IClientMediaCall; + + // Generate a unique callUUID + const callUUID = (await randomUuid()).toLowerCase(); + + // Set up the call store + useCallStore.getState().setCall(mockCall, callUUID); + + // If simulating a specific initial state, update the store + if (isMuted || isOnHold) { + useCallStore.setState({ + isMuted, + isOnHold + }); + } + + // Navigate to CallView + Navigation.navigate('CallView', { callUUID }); +}; diff --git a/app/views/RoomView/components/HeaderCallButton.tsx b/app/views/RoomView/components/HeaderCallButton.tsx index f763903a47f..f62e9bca798 100644 --- a/app/views/RoomView/components/HeaderCallButton.tsx +++ b/app/views/RoomView/components/HeaderCallButton.tsx @@ -2,6 +2,7 @@ import React from 'react'; import * as HeaderButton from '../../../containers/Header/components/HeaderButton'; import { useVideoConf } from '../../../lib/hooks/useVideoConf'; +import { simulateCall } from '../../../lib/services/voip/simulateCall'; export const HeaderCallButton = ({ rid, @@ -12,17 +13,26 @@ export const HeaderCallButton = ({ disabled: boolean; accessibilityLabel: string; }): React.ReactElement | null => { - const { showInitCallActionSheet, callEnabled, disabledTooltip } = useVideoConf(rid); + // const { showInitCallActionSheet, callEnabled, disabledTooltip } = useVideoConf(rid); - if (callEnabled) - return ( - - ); - return null; + // if (callEnabled) + // return ( + // + // ); + // return null; + return ( + simulateCall()} + testID='room-view-header-call' + /> + ); }; From 0d183142971130d14be1eeafd4884af0e98861e9 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Tue, 13 Jan 2026 17:08:36 -0300 Subject: [PATCH 06/61] refactor(CallView): update button handlers and improve UI responsiveness --- .../CallView/components/CallActionButton.tsx | 42 ++++++++++++------- app/views/CallView/index.tsx | 11 +++-- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/app/views/CallView/components/CallActionButton.tsx b/app/views/CallView/components/CallActionButton.tsx index bd8454b9e17..b67d6ee725d 100644 --- a/app/views/CallView/components/CallActionButton.tsx +++ b/app/views/CallView/components/CallActionButton.tsx @@ -37,25 +37,37 @@ const CallActionButton = ({ } }; + const getBackgroundColor = (pressed: boolean) => { + if (pressed) { + switch (variant) { + case 'active': + return colors.buttonBackgroundSecondaryDangerPress; + case 'danger': + return colors.buttonBackgroundDangerPress; + default: + return colors.buttonBackgroundSecondaryPress; + } + } + return variant === 'danger' ? colors.buttonBackgroundDangerDefault : colors.buttonBackgroundSecondaryDefault; + }; + return ( - - + [ styles.actionButton, - { - backgroundColor: variant === 'danger' ? colors.buttonBackgroundDangerDefault : colors.buttonBackgroundSecondaryDefault - } - ]}> + disabled && { opacity: 0.5 }, + { backgroundColor: getBackgroundColor(pressed) } + ]} + accessibilityLabel={label} + accessibilityRole='button' + testID={testID}> - + {label} - + ); }; diff --git a/app/views/CallView/index.tsx b/app/views/CallView/index.tsx index f9b316883e4..d9480a58cb2 100644 --- a/app/views/CallView/index.tsx +++ b/app/views/CallView/index.tsx @@ -48,14 +48,17 @@ const CallView = (): React.ReactElement | null => { const handleMessage = () => { // TODO: Navigate to chat with caller // Navigation.navigate('RoomView', { rid, t: 'd' }); + alert('Message'); }; const handleMore = () => { // TODO: Show action sheet with more options (DTMF, transfer, etc.) + alert('More'); }; - const handleMinimize = () => { - goBack(); + const handleCollapse = () => { + // goBack(); + alert('Collapse call'); }; const handleEndCall = () => { @@ -86,10 +89,10 @@ const CallView = (): React.ReactElement | null => { {/* Header */} - + - + {getHeaderTitle()} From 4b33a79374a75ac009a27eeb661b40f1f4bce019 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Tue, 13 Jan 2026 17:50:30 -0300 Subject: [PATCH 07/61] Add pause-shape-unfilled icon --- android/app/src/main/assets/fonts/custom.ttf | Bin 60564 -> 60696 bytes app/containers/CustomIcon/mappedIcons.js | 1 + app/containers/CustomIcon/selection.json | 2 +- ios/custom.ttf | Bin 60564 -> 60696 bytes 4 files changed, 2 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/assets/fonts/custom.ttf b/android/app/src/main/assets/fonts/custom.ttf index b0758f2fa60ec7d33ab136418ed1aa939022731b..3151388990e26173f1f0b9471ecf479503da664c 100644 GIT binary patch delta 403 zcmbPolX=E1=6VK31_lOhh6V;^1_S?KeItG$c5$G{9w1Ig&P^;354)Vlz`!U2UIGOfZ{#Lc6fpc?RApdzbpt4%ke8U7 zdi9^hS|A^2AY)ZQesKxVp+NAaWa18Y#%Gfly&0cv_F-K6SQ+FGAnwcBzB!)X<|_j? z3rHQ%W`3Z1A@t-KPt6%$Z@%z!4fE!Pmp2#%z@C52sLa3vQo_JAnenag=K9w&83FoE BQMCX7 diff --git a/app/containers/CustomIcon/mappedIcons.js b/app/containers/CustomIcon/mappedIcons.js index 1bf3d4d5429..8d2ba432a98 100644 --- a/app/containers/CustomIcon/mappedIcons.js +++ b/app/containers/CustomIcon/mappedIcons.js @@ -157,6 +157,7 @@ export const mappedIcons = { 'pause': 59803, 'pause-filled': 59802, 'pause-shape-filled': 59843, + 'pause-shape-unfilled': 59879, 'percentage': 59777, 'phone': 59806, 'phone-disabled': 59804, diff --git a/app/containers/CustomIcon/selection.json b/app/containers/CustomIcon/selection.json index ee13b9c0d91..4638607a1bb 100644 --- a/app/containers/CustomIcon/selection.json +++ b/app/containers/CustomIcon/selection.json @@ -1 +1 @@ -{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M727.050 406.195c12.259-12.73 11.878-32.986-0.854-45.245-12.73-12.259-32.986-11.878-45.245 0.854l-254.285 264.061-115.615-120.061c-12.259-12.733-32.516-13.114-45.247-0.854s-13.113 32.515-0.854 45.245l138.666 144c6.032 6.266 14.355 9.805 23.050 9.805 8.698 0 17.021-3.539 23.053-9.805l277.331-288z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["check-single"],"grid":0},"attrs":[{}],"properties":{"order":1151,"id":0,"name":"check-single","prevSize":32,"code":59876},"setIdx":0,"setId":6,"iconIdx":0},{"icon":{"paths":["M599.050 406.195c12.259-12.73 11.878-32.986-0.854-45.245-12.73-12.259-32.986-11.878-45.245 0.854l-254.284 264.061-115.616-120.061c-12.259-12.733-32.516-13.114-45.247-0.854s-13.113 32.515-0.854 45.245l138.667 144c6.032 6.266 14.354 9.805 23.050 9.805s17.018-3.539 23.052-9.805l277.331-288z","M887.021 406.227c12.275-12.714 11.92-32.973-0.794-45.248s-32.973-11.92-45.248 0.794l-255.040 264.157-50.918-52.739c-12.275-12.714-32.534-13.069-45.248-0.794s-13.069 32.534-0.794 45.248l73.939 76.582c6.029 6.246 14.339 9.773 23.021 9.773s16.992-3.526 23.021-9.773l278.061-288z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["check-double"],"grid":0},"attrs":[{},{}],"properties":{"order":1150,"id":1,"name":"check-double","prevSize":32,"code":59875},"setIdx":0,"setId":6,"iconIdx":1},{"icon":{"paths":["M511.997 256c35.347 0 64-28.654 64-64s-28.653-64-64-64c-35.344 0-64 28.654-64 64s28.656 64 64 64zM639.997 192c0 70.692-57.306 128-128 128-70.691 0-128-57.308-128-128s57.309-128 128-128c70.694 0 128 57.308 128 128z","M192.859 431.645c0.669 1.446 2.097 3.488 5.957 5.232 18.33 8.272 67.426 22.054 115.377 34.39 23.244 5.981 45.187 11.366 61.327 15.261 8.067 1.946 14.672 3.517 19.258 4.598l7.078 1.664c0 0 0.026 0.003-0.218 1.046l0.218-1.046c8.33 1.933 15.562 7.123 20.042 14.406 4.48 7.28 5.859 16.054 3.834 24.358l-83.856 343.437c-0.483 1.984-1.155 3.914-2.006 5.77-1.155 2.509-1.242 5.302-0.272 7.853 0.982 2.573 3.053 4.893 6.006 6.237 2.976 1.357 6.438 1.523 9.568 0.435 3.114-1.082 5.44-3.238 6.688-5.754 0.362-0.73 0.749-1.443 1.165-2.144l121.434-204.461c5.766-9.706 16.224-15.658 27.514-15.658 11.293 0 21.747 5.952 27.514 15.658l121.437 204.461c0.413 0.701 0.803 1.414 1.165 2.144 1.245 2.515 3.571 4.672 6.685 5.754 3.13 1.088 6.592 0.922 9.568-0.435 2.957-1.344 5.027-3.664 6.006-6.237 0.97-2.55 0.883-5.344-0.269-7.853-0.854-1.856-1.526-3.786-2.010-5.77l-83.853-343.437c-2.029-8.304-0.65-17.075 3.83-24.358 4.48-7.28 11.686-12.467 20.013-14.4l0.266 1.139c-0.262-1.139-0.266-1.139-0.266-1.139l1.821-0.426 5.283-1.245c4.582-1.082 11.184-2.653 19.248-4.598 16.138-3.894 38.074-9.28 61.312-15.261 47.936-12.333 97.046-26.118 115.424-34.4 3.888-1.75 5.322-3.802 5.994-5.248 0.813-1.763 1.155-4.179 0.557-6.861-0.602-2.678-1.974-4.858-3.629-6.259-1.402-1.187-3.76-2.499-8.109-2.499h-615.975c-4.316 0-6.656 1.302-8.052 2.486-1.647 1.402-3.026 3.581-3.628 6.272s-0.26 5.12 0.556 6.886zM172.486 495.21c-75.805-34.218-48.392-143.21 31.498-143.21h615.975c79.907 0 107.44 108.989 31.478 143.216-24.554 11.066-79.939 26.24-125.766 38.032-21.494 5.533-41.85 10.554-57.651 14.384l75.597 309.616c6.986 17.306 7.216 36.614 0.538 54.147-7.085 18.598-21.283 33.501-39.283 41.699-17.978 8.189-38.474 9.126-57.123 2.64-18.234-6.342-33.469-19.36-42.39-36.566l-93.386-157.232-93.386 157.232c-8.918 17.206-24.157 30.224-42.387 36.566-18.653 6.486-39.146 5.549-57.126-2.64-18-8.198-32.198-23.101-39.282-41.699-6.678-17.533-6.449-36.842 0.539-54.147l75.595-309.613c-15.808-3.83-36.172-8.854-57.676-14.387-45.829-11.789-101.229-26.966-125.761-38.038z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["accessibility"],"grid":0},"attrs":[{},{}],"properties":{"order":1147,"id":2,"name":"accessibility","prevSize":32,"code":59874},"setIdx":0,"setId":6,"iconIdx":2},{"icon":{"paths":["M512 928c-229.75 0-416-186.246-416-416 0-229.75 186.25-416 416-416 229.754 0 416 186.25 416 416 0 229.754-186.246 416-416 416zM678.176 433.884c12.742-12.247 13.139-32.504 0.896-45.246-12.25-12.742-32.506-13.143-45.247-0.896l-207.030 198.991-68.644-65.834c-12.755-12.232-33.012-11.809-45.245 0.946s-11.809 33.012 0.946 45.245l90.819 87.1c12.39 11.885 31.948 11.872 44.324-0.026l229.183-220.28z"],"attrs":[{"fill":"rgb(20, 134, 96)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":0}]},"tags":["success-circle"],"grid":0},"attrs":[{"fill":"rgb(20, 134, 96)"}],"properties":{"order":1143,"id":3,"name":"success-circle","prevSize":32,"code":59869},"setIdx":0,"setId":6,"iconIdx":3},{"icon":{"paths":["M928 512c0-229.75-186.246-416-416-416-229.75 0-416 186.25-416 416 0 229.754 186.25 416 416 416 229.754 0 416-186.246 416-416zM662.63 361.373c12.493 12.497 12.493 32.758 0 45.254l-105.375 105.373 105.375 105.373c12.493 12.497 12.493 32.758 0 45.258-12.499 12.493-32.761 12.493-45.258 0l-105.373-105.375-105.373 105.375c-12.497 12.493-32.758 12.493-45.254 0-12.497-12.499-12.497-32.761 0-45.258l105.372-105.373-105.372-105.373c-12.497-12.497-12.497-32.758 0-45.254s32.758-12.497 45.254 0l105.373 105.372 105.373-105.372c12.497-12.497 32.758-12.497 45.258 0z"],"attrs":[{"fill":"rgb(212, 12, 38)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":1}]},"tags":["error-circle"],"grid":0},"attrs":[{"fill":"rgb(212, 12, 38)"}],"properties":{"order":1144,"id":4,"name":"error-circle","prevSize":32,"code":59873},"setIdx":0,"setId":6,"iconIdx":4},{"icon":{"paths":["M512 819.2c169.661 0 307.2-137.539 307.2-307.2s-137.539-307.2-307.2-307.2c-169.662 0-307.2 137.538-307.2 307.2s137.538 307.2 307.2 307.2z","M1024 512c0-282.77-229.228-512-512-512-282.77 0-512 229.23-512 512 0 282.772 229.23 512 512 512 282.772 0 512-229.228 512-512zM921.6 512c0 226.217-183.383 409.6-409.6 409.6-226.216 0-409.6-183.383-409.6-409.6 0-226.215 183.384-409.6 409.6-409.6 226.217 0 409.6 183.385 409.6 409.6z"],"attrs":[{"fill":"rgb(21, 111, 245)"},{"fill":"rgb(21, 111, 245)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912111124512431405712431908124569921291162451452241651":[{"f":2},{"f":2}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":4},{"f":4}]},"tags":["radio-checked"],"grid":0},"attrs":[{"fill":"rgb(21, 111, 245)"},{"fill":"rgb(21, 111, 245)"}],"properties":{"order":5,"id":5,"name":"radio-checked","prevSize":32,"code":59855},"setIdx":0,"setId":6,"iconIdx":5},{"icon":{"paths":["M512 0c282.767 0 512 229.23 512 512 0 282.767-229.233 512-512 512-282.77 0-512-229.233-512-512 0-282.77 229.23-512 512-512zM512 921.6c226.217 0 409.6-183.383 409.6-409.6 0-226.216-183.383-409.6-409.6-409.6-226.216 0-409.6 183.384-409.6 409.6 0 226.217 183.384 409.6 409.6 409.6z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912111124512431405712431908124569921291162451452241651":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["radio-unchecked"],"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":4,"id":6,"name":"radio-unchecked","prevSize":32,"code":59867},"setIdx":0,"setId":6,"iconIdx":6},{"icon":{"paths":["M678.736 135.922c7.414-5.157 16.23-7.922 25.264-7.922s17.85 2.764 25.264 7.922c7.414 5.157 13.075 12.46 16.218 20.928l0.074 0.2 32.371 89.024 89.226 32.445c8.467 3.143 15.77 8.803 20.928 16.219 5.155 7.415 7.92 16.231 7.92 25.264 0 9.034-2.765 17.85-7.92 25.264-5.158 7.414-12.461 13.075-20.931 16.218l-0.198 0.074-89.024 32.371-32.445 89.226c-3.142 8.467-8.803 15.77-16.218 20.928-7.414 5.155-16.23 7.92-25.264 7.92s-17.85-2.765-25.264-7.92c-7.414-5.158-13.075-12.461-16.218-20.931l-0.074-0.198-32.371-89.024-89.226-32.445c-8.467-3.142-15.77-8.803-20.928-16.218-5.155-7.414-7.92-16.23-7.92-25.264 0-9.032 2.765-17.848 7.92-25.264 5.158-7.415 12.461-13.075 20.931-16.218l0.198-0.074 89.024-32.372 32.445-89.224c3.142-8.468 8.803-15.771 16.218-20.928zM713.437 384l7.533-20.717c2.224-6.029 5.725-11.504 10.269-16.045 4.541-4.544 10.016-8.045 16.045-10.269l0.128-0.045 46.541-16.925-46.669-16.971c-6.029-2.221-11.504-5.724-16.045-10.267-4.544-4.542-8.045-10.017-10.269-16.044l-0.045-0.128-16.925-46.541-16.97 46.669c-2.221 6.028-5.725 11.502-10.269 16.044-4.541 4.543-10.016 8.045-16.045 10.267l-0.128 0.047-46.541 16.924 46.669 16.97c6.029 2.221 11.504 5.725 16.045 10.269 4.544 4.541 8.045 10.016 10.269 16.045l0.045 0.128 16.925 46.541 9.437-25.952z","M323.091 265.629c8.256-6.153 18.346-9.629 28.909-9.629s20.653 3.477 28.909 9.629c8.224 6.127 14.17 14.542 17.402 23.873l0.067 0.191 47.674 140.467 130.595 50.883c9.696 3.856 17.67 10.64 23.126 19.046 5.44 8.381 8.227 18.118 8.227 27.91s-2.787 19.53-8.227 27.91c-5.456 8.406-13.434 15.19-23.126 19.046l-0.208 0.083-130.387 50.8-47.741 140.659c-3.232 9.328-9.178 17.744-17.402 23.872-8.256 6.15-18.346 9.629-28.909 9.629s-20.653-3.478-28.909-9.629c-8.223-6.128-14.17-14.544-17.402-23.875l-0.066-0.189-47.673-140.467-130.596-50.883c-9.694-3.856-17.669-10.64-23.125-19.046-5.442-8.381-8.228-18.118-8.228-27.91s2.787-19.53 8.228-27.91c5.456-8.406 13.431-15.19 23.125-19.046l0.208-0.083 130.388-50.8 47.739-140.658c3.233-9.331 9.18-17.746 17.403-23.873zM381.222 617.712l6.314-18.602c2.291-6.659 5.958-12.874 10.88-18.147 4.928-5.28 11.014-9.507 17.917-12.23l0.134-0.054 104.41-40.678-104.544-40.733c-6.902-2.723-12.989-6.95-17.917-12.23-4.922-5.274-8.589-11.488-10.88-18.147l-0.042-0.125-35.494-104.579-35.536 104.704c-2.291 6.659-5.959 12.874-10.881 18.147-4.929 5.28-11.015 9.507-17.916 12.23l-0.133 0.054-104.411 40.678 104.544 40.733c6.901 2.723 12.988 6.95 17.916 12.23 4.923 5.274 8.59 11.488 10.881 18.147l0.042 0.125 35.494 104.579 29.222-86.102z","M704 544c-9.034 0-17.85 2.765-25.264 7.92-7.414 5.158-13.075 12.461-16.218 20.928l-32.445 89.226-89.222 32.445c-8.47 3.142-15.773 8.803-20.931 16.218-5.155 7.414-7.92 16.23-7.92 25.264s2.765 17.85 7.92 25.264c5.158 7.414 12.461 13.075 20.928 16.218l89.226 32.445 32.445 89.222c3.142 8.47 8.803 15.773 16.218 20.931 7.414 5.155 16.23 7.92 25.264 7.92s17.85-2.765 25.264-7.92c7.414-5.158 13.075-12.461 16.218-20.928l32.445-89.226 89.222-32.445c8.47-3.142 15.773-8.803 20.931-16.218 5.155-7.414 7.92-16.23 7.92-25.264s-2.765-17.85-7.92-25.264c-5.158-7.414-12.461-13.075-20.928-16.218l-89.226-32.445-32.445-89.222c-3.142-8.47-8.803-15.773-16.218-20.931-7.414-5.155-16.23-7.92-25.264-7.92zM720.97 779.283l-6.829 18.784-10.141 27.885-16.97-46.669c-2.224-6.029-5.725-11.504-10.269-16.045-4.541-4.544-10.016-8.048-16.045-10.269l-46.669-16.97 46.669-16.97c6.029-2.221 11.504-5.725 16.045-10.269 4.544-4.541 8.048-10.016 10.269-16.045l16.97-46.669 16.97 46.669c2.224 6.029 5.725 11.504 10.269 16.045 4.541 4.544 10.016 8.048 16.045 10.269l46.669 16.97-46.669 16.97c-6.029 2.224-11.504 5.725-16.045 10.269-4.544 4.541-8.045 10.016-10.269 16.045z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{},{}]},"tags":["stars"],"grid":0},"attrs":[{},{},{}],"properties":{"order":1139,"id":7,"name":"stars","prevSize":32,"code":59845},"setIdx":0,"setId":6,"iconIdx":7},{"icon":{"paths":["M810.666 512c0.022 8.358-2.173 16.579-6.371 23.862-4.195 7.283-10.253 13.382-17.581 17.706l-454.067 271.187c-7.658 4.576-16.425 7.075-25.4 7.235-8.975 0.163-17.832-2.016-25.656-6.314-7.749-4.23-14.205-10.397-18.702-17.872-4.498-7.472-6.875-15.981-6.888-24.65v-542.311c0.013-8.668 2.39-17.176 6.888-24.649s10.953-13.642 18.702-17.872c7.824-4.297 16.681-6.477 25.656-6.315s17.743 2.661 25.4 7.237l454.067 271.186c7.328 4.323 13.386 10.422 17.581 17.706 4.198 7.283 6.394 15.504 6.371 23.862z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["play-shape-filled"],"grid":0},"attrs":[{}],"properties":{"order":4,"id":8,"name":"play-shape-filled","prevSize":32,"code":59842},"setIdx":0,"setId":6,"iconIdx":8},{"icon":{"paths":["M832 245.333v533.332c0 14.147-5.693 27.712-15.824 37.712-10.131 10.003-23.872 15.622-38.202 15.622h-135.066c-14.33 0-28.070-5.619-38.202-15.622-10.131-10-15.824-23.565-15.824-37.712v-533.332c0-14.145 5.693-27.71 15.824-37.712s23.872-15.621 38.202-15.621h135.066c14.33 0 28.070 5.619 38.202 15.621s15.824 23.567 15.824 37.712zM381.091 192h-135.065c-14.329 0-28.070 5.619-38.202 15.621s-15.824 23.567-15.824 37.712v533.332c0 14.147 5.692 27.712 15.824 37.712 10.132 10.003 23.874 15.622 38.202 15.622h135.065c14.33 0 28.070-5.619 38.202-15.622 10.131-10 15.824-23.565 15.824-37.712v-533.332c0-14.145-5.693-27.71-15.824-37.712s-23.872-15.621-38.202-15.621z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["pause-shape-filled"],"grid":0},"attrs":[{}],"properties":{"order":3,"id":9,"name":"pause-shape-filled","prevSize":32,"code":59843},"setIdx":0,"setId":6,"iconIdx":9},{"icon":{"paths":["M593.158 920.006c-80.698 16.051-164.342 7.814-240.355-23.674-76.014-31.485-140.984-84.806-186.695-153.216s-70.108-148.842-70.108-231.117h64c0 69.619 20.644 137.674 59.323 195.562 38.678 57.885 93.653 103.002 157.973 129.645 64.32 26.64 135.094 33.613 203.376 20.029 68.282-13.581 131.002-47.107 180.23-96.333 49.226-49.229 82.752-111.949 96.333-180.23 13.584-68.282 6.611-139.056-20.029-203.376-26.643-64.32-71.76-119.295-129.645-157.973-57.888-38.678-125.942-59.323-195.562-59.323v-64c82.278 0 162.707 24.398 231.117 70.109s121.731 110.681 153.216 186.695v0c31.488 76.013 39.725 159.658 23.674 240.355-16.051 80.694-55.67 154.819-113.85 212.998s-132.304 97.798-212.998 113.85z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["loading"],"grid":0},"attrs":[{}],"properties":{"order":2,"id":10,"name":"loading","prevSize":32,"code":59844},"setIdx":0,"setId":6,"iconIdx":10},{"icon":{"paths":["M544 208c0-17.673-14.326-32-32-32s-32 14.327-32 32v271.997h-271.998c-17.673 0-32 14.326-32 32s14.327 32 32 32h271.998v272.003c0 17.674 14.326 32 32 32s32-14.326 32-32v-272.003l272-0.003c17.674 0 32-14.326 32-32s-14.326-32-32-32l-272 0.003v-271.997z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["add"],"defaultCode":59872,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":923,"name":"add","prevSize":32,"id":11,"code":59872},"setIdx":0,"setId":6,"iconIdx":11},{"icon":{"paths":["M512 928c-14.218 0-28.275-0.714-42.144-2.112-16.694-1.68-30.557-12.528-36.688-27.395l-40.538-98.304-98.162 40.838c-14.837 6.173-32.3 4.048-45.292-6.554-21.838-17.818-41.831-37.811-59.65-59.648-10.601-12.992-12.726-30.454-6.553-45.293l40.839-98.16-98.307-40.541c-14.864-6.131-25.714-19.994-27.395-36.688-1.396-13.869-2.111-27.926-2.111-42.144 0-14.214 0.714-28.275 2.11-42.141 1.681-16.694 12.531-30.557 27.395-36.688l98.308-40.541-40.84-98.163c-6.173-14.837-4.047-32.3 6.553-45.292 17.818-21.838 37.81-41.83 59.648-59.648 12.992-10.6 30.455-12.726 45.292-6.553l98.165 40.84 40.541-98.309c6.128-14.865 19.994-25.714 36.688-27.395 13.866-1.396 27.926-2.11 42.141-2.11s28.275 0.714 42.141 2.11c16.694 1.681 30.56 12.531 36.688 27.395l40.541 98.309 98.163-40.84c14.838-6.173 32.301-4.047 45.293 6.553 21.837 17.818 41.83 37.81 59.648 59.648 10.602 12.992 12.726 30.455 6.554 45.292l-40.842 98.163 98.31 40.541c14.864 6.131 25.712 19.994 27.392 36.688 1.398 13.866 2.112 27.926 2.112 42.141 0 14.218-0.714 28.275-2.112 42.144-1.68 16.694-12.528 30.557-27.395 36.688l-98.307 40.541 40.842 98.16c6.173 14.838 4.045 32.301-6.554 45.293-17.821 21.837-37.811 41.83-59.651 59.648-12.992 10.602-30.454 12.726-45.29 6.554l-98.163-40.838-40.538 98.304c-6.131 14.867-19.994 25.715-36.688 27.395-13.869 1.398-27.93 2.112-42.144 2.112zM444.451 757.984l43.386 105.2c7.981 0.541 16.038 0.816 24.163 0.816s16.182-0.275 24.163-0.816l43.382-105.2c9.456-22.925 35.731-33.808 58.627-24.285l105.056 43.709c12.157-10.602 23.578-22.022 34.179-34.179l-43.709-105.056c-9.526-22.893 1.36-49.171 24.282-58.624l105.203-43.386c0.541-7.978 0.816-16.038 0.816-24.163s-0.275-16.182-0.816-24.16l-105.203-43.386c-22.922-9.453-33.808-35.731-24.282-58.624l43.709-105.060c-10.602-12.156-22.022-23.577-34.176-34.177l-105.059 43.708c-22.896 9.525-49.171-1.359-58.627-24.283l-43.382-105.204c-7.981-0.54-16.038-0.815-24.163-0.815s-16.182 0.275-24.163 0.815l-43.386 105.204c-9.453 22.924-35.728 33.808-58.624 24.283l-105.058-43.708c-12.156 10.6-23.577 22.021-34.177 34.177l43.708 105.059c9.525 22.893-1.359 49.171-24.284 58.624l-105.203 43.386c-0.54 7.978-0.815 16.035-0.815 24.16 0 8.128 0.275 16.186 0.815 24.163l105.203 43.386c22.924 9.453 33.809 35.731 24.284 58.624l-43.708 105.056c10.601 12.157 22.022 23.578 34.178 34.179l105.056-43.709c22.896-9.523 49.171 1.36 58.624 24.285zM416 512c0-53.021 42.979-96 96-96s96 42.979 96 96c0 53.021-42.979 96-96 96s-96-42.979-96-96zM512 352c-88.365 0-160 71.635-160 160s71.635 160 160 160c88.365 0 160-71.635 160-160s-71.635-160-160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["administration"],"defaultCode":59662,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":924,"name":"administration","prevSize":32,"id":12,"code":59662},"setIdx":0,"setId":6,"iconIdx":12},{"icon":{"paths":["M878.739 567.622c-41.853-41.136-161.235-29.824-220.925-22.282-59.005-35.997-98.458-85.706-126.243-158.73 13.379-55.194 34.646-139.185 18.525-191.98-14.41-89.82-129.674-80.907-146.141-20.227-15.094 55.195-1.373 131.988 24.013 230.034-34.304 81.936-85.421 191.984-121.441 255.062-68.611 35.312-161.235 89.821-174.957 158.384-11.321 54.166 89.194 189.238 261.063-106.96 76.845-25.37 160.547-56.566 234.65-68.909 64.835 34.97 140.65 58.282 191.421 58.282 87.478 0 96.054-96.678 60.035-132.675zM199.152 834.342c17.496-46.97 84.048-101.133 104.288-119.99-65.18 103.875-104.288 122.39-104.288 119.99zM479.082 180.918c25.386 0 22.986 110.047 6.176 139.873-15.094-47.653-14.752-139.873-6.176-139.873zM395.379 649.216c33.274-57.936 61.747-126.845 84.733-187.526 28.474 51.766 64.838 93.251 103.258 121.706-71.354 14.739-133.446 44.909-187.99 65.821zM846.835 632.074c0 0-17.152 20.57-127.958-26.739 120.413-8.912 140.307 18.512 127.958 26.739z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["adobe-reader-monochromatic"],"defaultCode":59663,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":925,"name":"adobe-reader-monochromatic","prevSize":32,"id":13,"code":59663},"setIdx":0,"setId":6,"iconIdx":13},{"icon":{"paths":["M512 192c-13.056 0-25.578 5.187-34.813 14.419-9.232 9.233-14.419 21.755-14.419 34.812v162.462c0 12.122-6.848 23.2-17.686 28.621l-253.082 126.541v49.498l232.493-46.499c9.402-1.882 19.149 0.554 26.563 6.63 7.414 6.080 11.712 15.162 11.712 24.749v108.307c0 8.486-3.37 16.624-9.373 22.627l-44.781 44.781v47.789l91.501-36.602c7.629-3.050 16.141-3.050 23.77 0l91.501 36.602v-47.789l-44.781-44.781c-6.003-6.003-9.373-14.141-9.373-22.627v-108.307c0-9.587 4.298-18.669 11.712-24.749 7.414-6.077 17.162-8.512 26.563-6.63l232.493 46.499v-49.498l-253.082-126.541c-10.838-5.421-17.686-16.499-17.686-28.621v-162.462c0-13.057-5.187-25.579-14.419-34.812-9.235-9.232-21.757-14.419-34.813-14.419zM431.933 161.164c21.235-21.235 50.035-33.164 80.067-33.164s58.832 11.93 80.067 33.164c21.235 21.235 33.165 50.036 33.165 80.066v142.686l253.078 126.538c10.842 5.421 17.69 16.502 17.69 28.624v108.307c0 9.587-4.298 18.669-11.712 24.746s-17.162 8.512-26.563 6.63l-232.493-46.496v56.019l44.781 44.781c6 6 9.373 14.141 9.373 22.627v108.307c0 10.618-5.267 20.544-14.061 26.499-8.794 5.952-19.965 7.155-29.824 3.213l-123.501-49.402-123.501 49.402c-9.859 3.942-21.030 2.739-29.824-3.213-8.794-5.955-14.061-15.882-14.061-26.499v-108.307c0-8.486 3.373-16.627 9.373-22.627l44.781-44.781v-56.019l-232.492 46.496c-9.401 1.882-19.149-0.554-26.564-6.63s-11.712-15.158-11.712-24.746v-108.307c0-12.122 6.848-23.203 17.689-28.624l253.079-126.538v-142.686c0-30.031 11.93-58.831 33.165-80.066z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["airplane"],"defaultCode":59815,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":926,"id":14,"name":"airplane","prevSize":32,"code":59815},"setIdx":0,"setId":6,"iconIdx":14},{"icon":{"paths":["M448 188.865c0 33.615 27.251 60.865 60.864 60.865 33.616 0 60.867-27.25 60.867-60.865s-27.251-60.865-60.867-60.865c-33.613 0-60.864 27.25-60.864 60.865zM384 188.865c0 59.026 40.957 108.485 96 121.512v77.745c-44.314 11.69-78.986 47.13-89.578 91.878h-80.045c-13.027-55.043-62.486-96-121.512-96-68.961 0-124.865 55.904-124.865 124.864 0 68.963 55.904 124.867 124.865 124.867 56.762 0 104.678-37.875 119.854-89.731h83.361c12.227 41.773 45.696 74.47 87.92 85.61v77.744c-55.043 13.027-96 62.486-96 121.51 0 68.963 55.904 124.867 124.864 124.867 68.963 0 124.867-55.904 124.867-124.867 0-56.762-37.875-104.675-89.731-119.853v-79.437c42.163-11.171 75.578-43.846 87.789-85.574h77.222c15.178 51.856 63.091 89.731 119.853 89.731 68.963 0 124.867-55.904 124.867-124.867 0-68.96-55.904-124.864-124.867-124.864-59.024 0-108.483 40.957-121.51 96h-73.907c-10.579-44.707-45.194-80.122-89.446-91.843v-79.438c51.856-15.176 89.731-63.092 89.731-119.854 0-68.961-55.904-124.865-124.867-124.865-68.96 0-124.864 55.904-124.864 124.865zM828.864 569.731c-33.613 0-60.864-27.251-60.864-60.867 0-33.613 27.251-60.864 60.864-60.864 33.616 0 60.867 27.251 60.867 60.864 0 33.616-27.251 60.867-60.867 60.867zM188.865 569.731c-33.615 0-60.865-27.251-60.865-60.867 0-33.613 27.25-60.864 60.865-60.864s60.865 27.251 60.865 60.864c0 33.616-27.25 60.867-60.865 60.867zM451.069 508.864c0 33.616 27.251 60.867 60.867 60.867 33.613 0 60.864-27.251 60.864-60.867 0-33.613-27.251-60.864-60.864-60.864-33.616 0-60.867 27.251-60.867 60.864zM508.864 889.731c-33.613 0-60.864-27.251-60.864-60.867 0-33.613 27.251-60.864 60.864-60.864 33.616 0 60.867 27.251 60.867 60.864 0 33.616-27.251 60.867-60.867 60.867z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["all-contacts-in-channels"],"defaultCode":59664,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":927,"name":"all-contacts-in-channels","prevSize":32,"id":15,"code":59664},"setIdx":0,"setId":6,"iconIdx":15},{"icon":{"paths":["M861.437 160c17.67 0 32 14.327 32 32s-14.33 32-32 32h-384c-17.674 0-32-14.327-32-32s14.326-32 32-32h384zM334.717 442.397c-24.962 0-45.197-20.237-45.197-45.2 0-24.96 20.236-45.197 45.197-45.197 24.963 0 45.2 20.237 45.2 45.197 0 24.963-20.237 45.2-45.2 45.2zM334.717 506.397c-60.308 0-109.197-48.89-109.197-109.2 0-60.307 48.89-109.197 109.197-109.197 60.31 0 109.2 48.89 109.2 109.197 0 60.31-48.89 109.2-109.2 109.2zM456.278 535.504c-18.288-4.899-37.504-5.2-55.939-0.88l-45.005 10.547c-13.194 3.091-26.947 2.877-40.036-0.63l-31.676-8.483c-19.669-5.27-40.384-5.562-60.154-0.928-55.68 13.050-95.468 62.781-95.468 120.179v34.752c0 42.906 34.783 77.686 77.689 77.686h258.057c42.906 0 77.69-34.781 77.69-77.686v-43.587c0-52-34.928-97.514-85.158-110.97zM414.944 596.934c8.166-1.914 16.675-1.779 24.774 0.39 22.246 5.958 37.718 26.118 37.718 49.149v43.587c0 7.558-6.131 13.686-13.69 13.686h-258.057c-7.56 0-13.689-6.128-13.689-13.686v-34.752c0-27.469 19.123-51.552 46.072-57.869 9.556-2.24 19.564-2.086 28.99 0.438l31.676 8.483c23.277 6.237 47.738 6.621 71.2 1.12l45.005-10.547zM893.437 512c0-17.674-14.33-32-32-32h-224c-17.674 0-32 14.326-32 32s14.326 32 32 32h224c17.67 0 32-14.326 32-32zM861.437 640c17.67 0 32 14.326 32 32s-14.33 32-32 32h-192c-17.674 0-32-14.326-32-32s14.326-32 32-32h192zM893.437 352c0-17.674-14.33-32-32-32h-288c-17.674 0-32 14.326-32 32s14.326 32 32 32h288c17.67 0 32-14.326 32-32zM861.437 800c17.67 0 32 14.326 32 32s-14.33 32-32 32h-256c-17.674 0-32-14.326-32-32s14.326-32 32-32h256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["all-contacts-in-queue"],"defaultCode":59665,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":928,"name":"all-contacts-in-queue","prevSize":32,"id":16,"code":59665},"setIdx":0,"setId":6,"iconIdx":16},{"icon":{"paths":["M523.571 295.385c33.133 0 74.669-22.133 99.402-51.645 22.4-26.745 38.733-64.095 38.733-101.445 0-5.072-0.467-10.144-1.402-14.294-36.864 1.383-81.2 24.439-107.798 55.334-21.002 23.517-40.134 60.406-40.134 98.218 0 5.533 0.934 11.067 1.402 12.911 2.333 0.461 6.067 0.922 9.798 0.922zM406.906 853.334c45.267 0 65.334-29.974 121.798-29.974 57.402 0 70 29.050 120.4 29.050 49.469 0 82.602-45.187 113.869-89.456 34.998-50.72 49.466-100.522 50.4-102.829-3.267-0.922-98-39.194-98-146.634 0-93.146 74.666-135.107 78.867-138.333-49.469-70.090-124.602-71.935-145.136-71.935-55.533 0-100.8 33.199-129.264 33.199-30.8 0-71.402-31.354-119.469-31.354-91.466 0-184.333 74.701-184.333 215.802 0 87.61 34.533 180.294 77 240.24 36.402 50.723 68.133 92.224 113.867 92.224z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["apple-monochromatic"],"defaultCode":59666,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":929,"name":"apple-monochromatic","prevSize":32,"id":17,"code":59666},"setIdx":0,"setId":6,"iconIdx":17},{"icon":{"paths":["M498.694 141.561l-298.666 136.533c-11.39 5.207-18.696 16.58-18.696 29.103v386.844c0 11.818 6.513 22.675 16.941 28.237l298.667 159.286c9.411 5.021 20.707 5.021 30.118 0l298.666-159.286c10.429-5.562 16.941-16.419 16.941-28.237v-386.844c0-12.524-7.306-23.896-18.694-29.103l-298.666-136.533c-8.451-3.862-18.16-3.862-26.611 0zM245.333 357.011l234.667 107.277v335.709l-234.667-125.155v-317.83zM544 799.997l234.666-125.155v-317.83l-234.666 107.277v335.709zM512 408.544l-221.7-101.347 221.7-101.348 221.699 101.348-221.699 101.347z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["apps"],"defaultCode":59667,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":930,"name":"apps","prevSize":32,"id":18,"code":59667},"setIdx":0,"setId":6,"iconIdx":18},{"icon":{"paths":["M374.627 297.372c-12.496-12.497-32.758-12.497-45.254 0l-192 192c-12.497 12.496-12.497 32.758 0 45.254l192 192c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-137.372-137.373h578.745v128c0 17.674 14.326 32 32 32s32-14.326 32-32v-160c0-17.674-14.326-32-32-32h-610.745l137.372-137.373c12.496-12.496 12.496-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-back"],"defaultCode":59668,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":931,"name":"arrow-back","prevSize":32,"id":19,"code":59668},"setIdx":0,"setId":6,"iconIdx":19},{"icon":{"paths":["M551.392 242.502c0.189-17.672 14.669-31.845 32.339-31.656 17.674 0.189 31.846 14.668 31.658 32.34l-1.318 123.489 193.44-193.439c12.496-12.497 32.755-12.497 45.254 0 12.496 12.497 12.496 32.758 0 45.255l-193.44 193.439 123.488-1.318c17.674-0.189 32.154 13.984 32.339 31.654 0.189 17.674-13.984 32.154-31.654 32.342l-201.92 2.154c-8.605 0.093-16.886-3.283-22.97-9.37-6.086-6.083-9.462-14.365-9.373-22.97l2.157-201.92zM475.981 782.147c-0.189 17.674-14.669 31.846-32.339 31.658-17.674-0.189-31.846-14.669-31.658-32.342l1.318-123.488-193.438 193.44c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l193.438-193.44-123.488 1.318c-17.672 0.189-32.151-13.984-32.34-31.654-0.189-17.674 13.984-32.154 31.656-32.342l201.922-2.154c8.605-0.093 16.883 3.283 22.966 9.37 6.086 6.083 9.462 14.365 9.373 22.97l-2.157 201.92z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-collapse"],"defaultCode":59669,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":932,"name":"arrow-collapse","prevSize":32,"id":20,"code":59669},"setIdx":0,"setId":6,"iconIdx":20},{"icon":{"paths":["M576 672c-17.674 0-32 14.326-32 32s14.326 32 32 32h224c17.674 0 32-14.326 32-32v-208c0-17.674-14.326-32-32-32s-32 14.326-32 32v130.746l-233.373-233.373c-12.496-12.496-32.758-12.496-45.254 0l-73.373 73.373-169.372-169.373c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.759 0 45.255l192 192c12.496 12.496 32.758 12.496 45.254 0l73.373-73.373 210.746 210.746h-146.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-decrease"],"defaultCode":59670,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":933,"name":"arrow-decrease","prevSize":32,"id":21,"code":59670},"setIdx":0,"setId":6,"iconIdx":21},{"icon":{"paths":["M726.88 526.064c12.355 12.637 12.128 32.896-0.509 45.254l-191.968 187.715c-12.438 12.163-32.31 12.163-44.746 0l-191.97-187.715c-12.636-12.358-12.863-32.618-0.507-45.254 12.356-12.634 32.615-12.861 45.252-0.506l137.597 134.55v-372.109c0-17.673 14.33-32 32-32 17.674 0 32 14.327 32 32v372.109l137.6-134.55c12.634-12.355 32.896-12.128 45.251 0.506z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-down"],"defaultCode":59673,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":934,"name":"arrow-down","prevSize":32,"id":22,"code":59673},"setIdx":0,"setId":6,"iconIdx":22},{"icon":{"paths":["M329.373 550.627c-12.497-12.496-12.497-32.758 0-45.254s32.758-12.496 45.254 0l105.373 105.373v-418.746c0-17.673 14.326-32 32-32s32 14.327 32 32v418.746l105.373-105.373c12.496-12.496 32.758-12.496 45.254 0s12.496 32.758 0 45.254l-160 160c-12.496 12.496-32.758 12.496-45.254 0l-160-160zM112 864c0 17.674 14.327 32 32 32h768c17.674 0 32-14.326 32-32v-512c0-17.674-14.326-32-32-32h-96c-17.674 0-32 14.326-32 32s14.326 32 32 32h64v448h-704v-448h64c17.673 0 32-14.326 32-32s-14.327-32-32-32h-96c-17.673 0-32 14.326-32 32v512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-down-box"],"defaultCode":59671,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":935,"name":"arrow-down-box","prevSize":32,"id":23,"code":59671},"setIdx":0,"setId":6,"iconIdx":23},{"icon":{"paths":["M866.49 512c0-194.404-157.802-352-352.464-352-194.661 0-352.465 157.596-352.465 352s157.804 352 352.465 352c194.662 0 352.464-157.597 352.464-352zM930.576 512c0 229.75-186.496 416-416.55 416s-416.549-186.25-416.549-416c0-229.75 186.495-416 416.549-416s416.55 186.25 416.55 416zM696.525 571.37c12.682-12.33 12.957-32.589 0.611-45.251-12.342-12.666-32.63-12.938-45.309-0.611l-105.789 102.842v-276.349c0-17.674-14.346-32-32.045-32-17.696 0-32.042 14.326-32.042 32v276.349l-105.789-102.842c-12.678-12.326-32.966-12.054-45.309 0.611-12.344 12.662-12.071 32.922 0.608 45.251l160.182 155.715c12.438 12.093 32.259 12.093 44.701 0l160.179-155.715z"],"width":1056,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-down-circle"],"defaultCode":59672,"grid":0},"attrs":[{}],"properties":{"order":936,"name":"arrow-down-circle","prevSize":32,"id":24,"code":59672},"setIdx":0,"setId":6,"iconIdx":24},{"icon":{"paths":["M859.978 398.15c-0.189 17.67-14.666 31.843-32.339 31.654-17.67-0.189-31.846-14.666-31.658-32.339l1.318-123.488-193.437 193.437c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.755 0-45.254l193.437-193.437-123.488 1.318c-17.67 0.189-32.15-13.984-32.339-31.656s13.984-32.151 31.658-32.34l201.92-2.156c8.605-0.092 16.883 3.286 22.97 9.371 6.083 6.085 9.462 14.364 9.37 22.969l-2.157 201.922zM167.394 626.522c0.189-17.674 14.668-31.846 32.34-31.658s31.845 14.669 31.657 32.339l-1.319 123.488 193.438-193.437c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-193.438 193.437 123.489-1.318c17.67-0.189 32.15 13.984 32.339 31.658 0.189 17.67-13.984 32.15-31.658 32.339l-201.92 2.157c-8.605 0.093-16.884-3.286-22.969-9.37-6.085-6.086-9.463-14.365-9.371-22.97l2.156-201.92z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-expand"],"defaultCode":59674,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":937,"name":"arrow-expand","prevSize":32,"id":25,"code":59674},"setIdx":0,"setId":6,"iconIdx":25},{"icon":{"paths":["M623.488 420.944h-129.030c-146.778 0-279.962 128.675-298.822 309.533 98.511-81.834 219.072-127.946 345.446-127.946h82.406v123.408l188.595-214.202-188.595-214.2v123.406zM888.045 501.165c5.322 6.045 5.325 15.104 0 21.149l-300.547 341.354c-9.747 11.069-28.010 4.176-28.010-10.573v-186.563h-18.406c-15.286 0-30.496 0.774-45.594 2.298-112.397 11.35-218.514 64.397-302.132 150.954-2.078 2.15-4.142 4.32-6.191 6.512-7.238 7.741-14.299 15.738-21.173 23.984-2.611 3.133-5.195 6.301-7.751 9.504l-0.376 0.474c-9.438 11.834-28.508 5.158-28.508-9.978v-75.606c0-230.707 163.46-417.728 365.102-417.728h65.030v-186.56c0-14.749 18.262-21.643 28.010-10.573l300.547 341.354z"],"width":1056,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-forward"],"defaultCode":59841,"grid":0},"attrs":[{}],"properties":{"order":938,"id":26,"name":"arrow-forward","prevSize":32,"code":59841},"setIdx":0,"setId":6,"iconIdx":26},{"icon":{"paths":["M576 352c-17.674 0-32-14.326-32-32s14.326-32 32-32h224c17.674 0 32 14.327 32 32v208c0 17.674-14.326 32-32 32s-32-14.326-32-32v-130.746l-233.373 233.373c-12.496 12.496-32.758 12.496-45.254 0l-73.373-73.373-169.372 169.373c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l192-192c12.496-12.496 32.758-12.496 45.254 0l73.373 73.373 210.746-210.746h-146.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-increase"],"defaultCode":59675,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":939,"name":"arrow-increase","prevSize":32,"id":27,"code":59675},"setIdx":0,"setId":6,"iconIdx":27},{"icon":{"paths":["M297.766 105.372c12.513-12.497 32.801-12.497 45.316 0 12.512 12.497 12.512 32.758 0 45.255l-105.513 105.372h611.551c17.699 0 32.045 14.327 32.045 32v112c0 17.674-14.346 32-32.045 32-17.696 0-32.042-14.326-32.042-32v-80h-579.51l105.513 105.373c12.512 12.496 12.512 32.758 0 45.254-12.515 12.496-32.803 12.496-45.316 0l-160.212-160c-12.513-12.497-12.513-32.758 0-45.255l160.212-160zM711.568 918.627c-12.515 12.496-32.803 12.496-45.315 0-12.515-12.496-12.515-32.758 0-45.254l105.51-105.373h-611.552c-17.696 0-32.042-14.326-32.042-32v-112c0-17.674 14.346-32 32.042-32s32.042 14.326 32.042 32v80h579.509l-105.51-105.373c-12.515-12.496-12.515-32.758 0-45.254 12.512-12.496 32.8-12.496 45.315 0l160.211 160c12.512 12.496 12.512 32.758 0 45.254l-160.211 160z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-looping"],"defaultCode":59677,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":940,"name":"arrow-looping","prevSize":32,"id":28,"code":59677},"setIdx":0,"setId":6,"iconIdx":28},{"icon":{"paths":["M374.627 769.296c-12.496 12.496-32.758 12.496-45.254 0l-192-192c-12.497-12.496-12.497-32.758 0-45.254l192-192c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-137.372 137.373h578.745v-192h-192c-17.674 0-32-14.328-32-32.001s14.326-32 32-32h224c17.674 0 32 14.327 32 32v256.001c0 17.674-14.326 32-32 32h-610.745l137.372 137.373c12.496 12.496 12.496 32.758 0 45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-return"],"defaultCode":59678,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":941,"name":"arrow-return","prevSize":32,"id":29,"code":59678},"setIdx":0,"setId":6,"iconIdx":29},{"icon":{"paths":["M526.064 297.121c12.637-12.356 32.896-12.129 45.254 0.507l187.715 191.969c12.163 12.438 12.163 32.31 0 44.746l-187.715 191.971c-12.358 12.634-32.618 12.861-45.254 0.506-12.634-12.355-12.861-32.614-0.506-45.251l134.55-137.597h-372.109c-17.673 0-32-14.33-32-32 0-17.674 14.327-32 32-32h372.109l-134.55-137.6c-12.355-12.634-12.128-32.894 0.506-45.251z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-right"],"defaultCode":59838,"grid":0},"attrs":[{}],"properties":{"order":942,"id":30,"name":"arrow-right","prevSize":32,"code":59838},"setIdx":0,"setId":6,"iconIdx":30},{"icon":{"paths":["M297.181 498.090c-12.356-12.634-12.129-32.896 0.507-45.251l191.97-187.717c12.435-12.161 32.307-12.161 44.746 0l191.968 187.717c12.637 12.355 12.864 32.618 0.509 45.251-12.355 12.637-32.618 12.864-45.251 0.509l-137.6-134.55v372.109c0 17.674-14.326 32-32 32-17.67 0-32-14.326-32-32v-372.109l-137.597 134.55c-12.637 12.355-32.895 12.128-45.251-0.509z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-up"],"defaultCode":59680,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":943,"name":"arrow-up","prevSize":32,"id":31,"code":59680},"setIdx":0,"setId":6,"iconIdx":31},{"icon":{"paths":["M694.627 473.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-105.373-105.373v418.746c0 17.674-14.326 32-32 32s-32-14.326-32-32v-418.746l-105.373 105.373c-12.496 12.496-32.758 12.496-45.254 0s-12.497-32.758 0-45.254l160-160c12.496-12.497 32.758-12.497 45.254 0l160 160zM912 160c0-17.673-14.326-32-32-32h-768c-17.673 0-32 14.327-32 32v512c0 17.674 14.327 32 32 32h96c17.673 0 32-14.326 32-32s-14.327-32-32-32h-64v-448h704v448h-64c-17.674 0-32 14.326-32 32s14.326 32 32 32h96c17.674 0 32-14.326 32-32v-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-up-box"],"defaultCode":59679,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":944,"name":"arrow-up-box","prevSize":32,"id":32,"code":59679},"setIdx":0,"setId":6,"iconIdx":32},{"icon":{"paths":["M649.427 192c-26.454 0-52.016 10.804-71.005 30.343l-305.1 313.906c-31.48 32.387-49.322 76.506-49.322 122.694 0 46.186 17.842 90.304 49.322 122.694 31.451 32.355 73.91 50.362 117.984 50.362s86.531-18.006 117.981-50.362l305.101-313.907c12.317-12.672 32.576-12.96 45.248-0.643 12.675 12.317 12.963 32.576 0.646 45.251l-305.101 313.904c-43.302 44.554-102.23 69.757-163.875 69.757s-120.574-25.203-163.877-69.757c-43.273-44.522-67.428-104.717-67.428-167.299s24.155-122.781 67.428-167.302l305.1-313.905c30.845-31.735 72.874-49.737 116.899-49.737s86.054 18.002 116.899 49.737c30.816 31.704 47.971 74.514 47.971 118.968s-17.155 87.263-47.971 118.969l-305.43 313.904c-0.003 0.006 0.003-0.003 0 0-18.384 18.909-43.523 29.718-69.923 29.718-26.406 0-51.539-10.8-69.923-29.718-18.356-18.883-28.512-44.31-28.512-70.634 0-26.326 10.156-51.754 28.512-70.637l281.872-289.668c12.326-12.666 32.586-12.942 45.251-0.617s12.941 32.585 0.618 45.251l-281.846 289.638c-6.557 6.752-10.406 16.106-10.406 26.032 0 9.93 3.843 19.277 10.406 26.029 6.531 6.72 15.194 10.323 24.029 10.323s17.498-3.603 24.029-10.323l305.43-313.907c19.024-19.568 29.866-46.301 29.866-74.361 0-28.059-10.842-54.791-29.866-74.362-18.989-19.54-44.55-30.343-71.005-30.343z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["attach"],"defaultCode":59676,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":945,"name":"attach","prevSize":32,"id":33,"code":59676},"setIdx":0,"setId":6,"iconIdx":33},{"icon":{"paths":["M300.1 631.12h-113.433v-280.89h113.433l12.366-48.048c11.054-42.953 50.123-74.619 96.423-74.619h58.666v526.223h-58.666c-46.301 0-85.37-31.667-96.423-74.621l-12.366-48.045zM163.556 695.12h86.931c18.156 70.541 82.192 122.666 158.403 122.666h81.776c22.582 0 40.89-18.307 40.89-40.89v-572.444c0-22.582-18.307-40.889-40.89-40.889h-81.776c-76.211 0-140.247 52.124-158.403 122.667h-86.931c-22.582 0-40.889 18.306-40.889 40.89v327.11c0 22.582 18.307 40.89 40.889 40.89zM646.461 316.515c17.146-4.286 34.518 6.138 38.806 23.284l11.136 44.55c20.81 83.229 20.81 170.301 0 253.533l-11.136 44.55c-4.288 17.146-21.661 27.568-38.806 23.283-17.146-4.288-27.571-21.661-23.283-38.806l11.136-44.55c18.262-73.040 18.262-149.45 0.003-222.486l-11.139-44.55c-4.288-17.146 6.138-34.522 23.283-38.807zM807.472 235.936c-5.197-16.892-23.104-26.372-39.994-21.174-16.893 5.197-26.371 23.104-21.174 39.996l35.536 115.489c28.112 91.37 26.976 189.242-3.254 279.933l-32.054 96.16c-5.59 16.765 3.472 34.886 20.237 40.477 16.768 5.587 34.89-3.472 40.48-20.24l32.051-96.16c34.448-103.344 35.747-214.87 3.709-318.989l-35.536-115.491z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio"],"defaultCode":59683,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":946,"name":"audio","prevSize":32,"id":34,"code":59683},"setIdx":0,"setId":6,"iconIdx":34},{"icon":{"paths":["M866.128 153.127c-12.496-12.497-32.758-12.497-45.254 0l-668.246 668.245c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l668.246-668.245c12.496-12.497 12.496-32.758 0-45.255zM674.643 480.358l55.92-55.923c16.259 79.565 14.515 161.866-5.229 240.842l-11.622 46.49c-4.288 17.146-21.661 27.571-38.806 23.283-17.146-4.285-27.568-21.661-23.283-38.806l11.622-46.486c13.875-55.507 17.677-112.874 11.398-169.398zM817.162 385.923l-11.312-36.771 51.203-51.206 21.28 69.155c33.344 108.368 31.994 224.445-3.859 332.010l-33.45 100.342c-5.587 16.765-23.709 25.827-40.477 20.24-16.765-5.59-25.827-23.712-20.237-40.48l33.446-100.339c31.635-94.912 32.826-197.334 3.405-292.95zM490.666 664.333l64-64v210.346c0 23.562-19.101 42.666-42.666 42.666h-85.334c-35.459 0-68.394-10.816-95.683-29.325l46.611-46.611c14.701 7.629 31.395 11.936 49.072 11.936h64v-125.011zM128 682.678c0 19.738 13.403 36.346 31.604 41.216l62.552-62.55h-30.156v-298.666h118.99l12.367-48.049c11.843-46.020 53.696-79.953 103.309-79.953h64v158.155l64-64v-115.488c0-23.564-19.101-42.667-42.666-42.667h-85.334c-79.523 0-146.343 54.39-165.289 128h-90.71c-23.564 0-42.667 19.102-42.667 42.667v341.334z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio-disabled"],"defaultCode":59681,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":947,"name":"audio-disabled","prevSize":32,"id":35,"code":59681},"setIdx":0,"setId":6,"iconIdx":35},{"icon":{"paths":["M310.99 661.344h-118.99v-298.666h118.99l12.367-48.049c11.843-46.020 53.696-79.953 103.309-79.953h64v554.667h-64c-49.613 0-91.466-33.933-103.309-79.952l-12.367-48.048zM170.667 725.344h90.71c18.946 73.61 85.766 128 165.289 128h85.334c23.565 0 42.666-19.104 42.666-42.666v-597.335c0-23.564-19.101-42.667-42.666-42.667h-85.334c-79.523 0-146.343 54.39-165.289 128h-90.71c-23.564 0-42.667 19.102-42.667 42.667v341.334c0 23.562 19.103 42.666 42.667 42.666zM886.627 393.373c12.496 12.496 12.496 32.758 0 45.254l-73.373 73.373 73.373 73.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-73.373-73.373-73.373 73.373c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l73.373-73.373-73.373-73.373c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l73.373 73.373 73.373-73.373c12.496-12.496 32.758-12.496 45.254 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio-unavailable"],"defaultCode":59682,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":948,"name":"audio-unavailable","prevSize":32,"id":36,"code":59682},"setIdx":0,"setId":6,"iconIdx":36},{"icon":{"paths":["M418.704 128c-35.344 0-64 28.654-64 64v226.637c20.774-2.822 42.134-3.456 64-1.526v-225.11h176v180.707c0 35.344 28.656 64 64 64h176v331.293h-120.554c-17.155 22.179-36.323 43.869-57.312 64h177.866c35.347 0 64-28.653 64-64v-363.293c0-6.413-1.923-12.675-5.526-17.978l-156.63-230.681c-11.914-17.544-31.741-28.049-52.947-28.049h-264.896zM658.704 372.707v-180.707h24.896l122.698 180.707h-147.594zM167.939 668.547c120.524 156.138 218.24 174.586 285.133 158.739 73.293-17.36 139.232-81.648 183.466-151.763-115.155-155.869-211.581-174.589-279.149-158.915-74.362 17.251-142.707 81.683-189.45 151.939zM104.428 649.037c100.621-162.8 337.62-357.19 593.252 1.789 9.072 12.739 10.32 29.818 2.422 43.315-95.27 162.854-326.394 358.346-593.234-0.224-9.745-13.094-11.022-30.995-2.44-44.88zM401.664 735.994c31.514 0 60.269-26.858 60.269-64 0-37.146-28.755-64-60.269-64-31.51 0-60.266 26.854-60.266 64 0 37.142 28.755 64 60.266 64zM401.664 799.994c68.634 0 124.269-57.309 124.269-128 0-70.694-55.635-128-124.269-128-68.63 0-124.267 57.306-124.267 128 0 70.691 55.636 128 124.267 128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["auditing"],"defaultCode":59684,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":949,"name":"auditing","prevSize":32,"id":37,"code":59684},"setIdx":0,"setId":6,"iconIdx":37},{"icon":{"paths":["M224 224c-17.673 0-32 14.327-32 32v544c0 17.674 14.327 32 32 32h544c17.674 0 32-14.326 32-32v-544c0-17.673-14.326-32-32-32h-544zM128 256c0-53.019 42.981-96 96-96h544c53.021 0 96 42.981 96 96v544c0 53.021-42.979 96-96 96h-544c-53.019 0-96-42.979-96-96v-544zM608 460.813c0 41.798-26.714 77.357-64 90.538v133.462h-64v-133.462c-37.286-13.181-64-48.739-64-90.538 0-53.021 42.979-96 96-96s96 42.979 96 96zM608 588.826c38.861-29.19 64-75.667 64-128.013 0-88.365-71.635-160-160-160s-160 71.636-160 160c0 52.346 25.139 98.822 64 128.013v127.987c0 17.674 14.326 32 32 32h128c17.674 0 32-14.326 32-32v-127.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["auth"],"defaultCode":59685,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":950,"name":"auth","prevSize":32,"id":38,"code":59685},"setIdx":0,"setId":6,"iconIdx":38},{"icon":{"paths":["M513.35 554.019c66.467 0 120.349-52.493 120.349-117.242 0-64.752-53.882-117.243-120.349-117.243-66.464 0-120.346 52.491-120.346 117.243 0 64.749 53.882 117.242 120.346 117.242zM513.35 490.019c-32.704 0-56.346-25.405-56.346-53.242 0-27.84 23.642-53.242 56.346-53.242 32.707 0 56.349 25.402 56.349 53.242 0 27.837-23.642 53.242-56.349 53.242z","M365.478 894.144h-172.126c-17.673 0-32-14.33-32-32v-702.144c0-17.673 14.327-32 32-32h640.001c17.674 0 32 14.327 32 32v702.144c0 17.67-14.326 32-32 32h-172.128c-6.24 1.274-12.701 1.942-19.318 1.942h-257.11c-6.618 0-13.078-0.669-19.318-1.942zM225.353 830.144h68.244c-3.114-9.456-4.799-19.558-4.799-30.058v-93.446c0-56.109 37.881-105.142 92.172-119.309 19.171-5.002 39.264-5.312 58.579-0.902l42.778 9.766c20.051 4.579 40.909 4.259 60.81-0.934l28.070-7.325c20.694-5.398 42.384-5.734 63.232-0.973 60.534 13.821 103.469 67.664 103.469 129.754v83.37c0 10.499-1.686 20.602-4.8 30.058h68.246v-638.144h-576.001v638.144zM652.918 830.144c12.246-4.49 20.989-16.253 20.989-30.058v-83.37c0-32.234-22.288-60.186-53.715-67.36-10.822-2.47-22.083-2.298-32.826 0.506l-28.070 7.325c-29.853 7.789-61.139 8.272-91.216 1.405l-42.774-9.766c-9.293-2.122-18.957-1.974-28.176 0.432-26.112 6.813-44.333 30.397-44.333 57.382v93.446c0 13.805 8.742 25.568 20.989 30.058h279.133z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["avatar"],"defaultCode":59686,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":951,"name":"avatar","prevSize":32,"id":39,"code":59686},"setIdx":0,"setId":6,"iconIdx":39},{"icon":{"paths":["M737.779 361.376c12.499 12.496 12.499 32.758 0 45.254l-110.947 110.95 110.947 110.947c12.499 12.496 12.499 32.758 0 45.254-12.496 12.499-32.758 12.499-45.254 0l-110.947-110.947-110.95 110.947c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.758 0-45.254l110.95-110.947-110.95-110.95c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l110.95 110.95 110.947-110.95c12.496-12.496 32.758-12.496 45.254 0z","M312.246 218.073c12.061-16.393 31.2-26.073 51.552-26.073h468.202c35.347 0 64 28.654 64 64v512c0 35.347-28.653 64-64 64h-468.202c-20.352 0-39.491-9.68-51.552-26.074l-188.343-256c-16.598-22.56-16.598-53.293 0-75.853l188.343-256.001zM363.798 256l-188.343 256 188.343 256h468.202v-512h-468.202z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["backspace"],"defaultCode":59687,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":952,"name":"backspace","prevSize":32,"id":40,"code":59687},"setIdx":0,"setId":6,"iconIdx":40},{"icon":{"paths":["M896 512c0-212.077-171.923-384-384-384s-384 171.923-384 384c0 212.077 171.923 384 384 384s384-171.923 384-384zM480 544v286.419c-56.483-5.606-108.646-25.904-152.618-57.011 46.403-78.992 67.251-156.97 71.734-229.408h80.883zM334.8 544c-4.282 58.995-21.005 122.198-56.631 186.458-46.616-49.875-77.462-114.678-84.589-186.458h141.22zM398.954 480c-6.192-93.13-37.366-173.574-70.627-230.072 43.773-30.733 95.594-50.78 151.674-56.348v286.42h-81.046zM279.095 292.556c26.251 47.457 50.118 112.532 55.644 187.444h-141.159c7.174-72.253 38.381-137.437 85.515-187.444zM544 544h80.883c4.483 72.438 25.331 150.416 71.734 229.408-43.971 31.107-96.134 51.405-152.618 57.011v-286.419zM830.419 544c-7.126 71.779-37.971 136.582-84.589 186.458-35.626-64.259-52.349-127.462-56.63-186.458h141.219zM830.419 480h-141.158c5.526-74.912 29.395-139.987 55.645-187.444 47.133 50.008 78.339 115.192 85.514 187.444zM544 193.58c56.080 5.568 107.901 25.614 151.674 56.348-33.261 56.499-64.435 136.943-70.627 230.072h-81.046v-286.42z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["basketball"],"defaultCode":59776,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":953,"id":41,"name":"basketball","prevSize":32,"code":59776},"setIdx":0,"setId":6,"iconIdx":41},{"icon":{"paths":["M233.358 169.364c6.002-6.001 14.141-9.372 22.629-9.372l304.020 0.020c0 0 0.003 0 0 0 46.678 0 91.446 18.543 124.451 51.549 33.008 33.006 51.549 77.772 51.549 124.452s-18.541 91.443-51.549 124.451c-0.803 0.803-1.616 1.6-2.435 2.387 22.867 9.552 43.888 23.533 61.75 41.395 36.006 36.006 56.234 84.845 56.234 135.766s-20.227 99.757-56.234 135.763c-36.006 36.006-84.845 56.237-135.766 56.237l-352.024-0.019c-17.673-0.003-31.998-14.33-31.998-32v-608.001c0-8.487 3.372-16.627 9.373-22.628zM560.006 448.013c29.706 0 58.192-11.802 79.197-32.806 21.005-21.002 32.803-49.491 32.803-79.194 0-29.705-11.798-58.193-32.803-79.197s-49.491-32.804-79.197-32.804l-272.022-0.018v224.019h272.022zM287.984 512.013v255.981l320.022 0.019c0 0 0.003 0 0 0 33.949 0 66.506-13.488 90.512-37.491 24.003-24.006 37.488-56.563 37.488-90.509 0-33.949-13.485-66.506-37.488-90.512-24.006-24.003-56.563-37.488-90.512-37.488h-320.022z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["bold"],"defaultCode":59688,"grid":0},"attrs":[{}],"properties":{"order":954,"name":"bold","prevSize":32,"id":42,"code":59688},"setIdx":0,"setId":6,"iconIdx":42},{"icon":{"paths":["M352 445.437c0-17.67 14.326-32 32-32h256c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M352 322.557c0-17.672 14.326-31.999 32-31.999h256c17.674 0 32 14.327 32 31.999 0 17.674-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M864 679.68c0 17.674-14.326 32-32 32h-18.509c-8.218 40.547-8.218 82.333 0 122.88h19.789c16.966 0 30.72 13.754 30.72 30.72s-13.754 30.72-30.72 30.72h-545.28c-70.692 0-128-55.014-128-122.88v-453.12c0-106.038 85.961-192 192-192h480c17.674 0 32 14.327 32 32v519.68zM748.419 834.56c-6.787-40.678-6.787-82.202 0-122.88h-460.419c-35.346 0-64 27.507-64 61.44s28.654 61.44 64 61.44h460.419zM224 647.68h576v-455.68h-448c-70.692 0-128 57.308-128 128v327.68z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["book"],"defaultCode":59689,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":955,"name":"book","prevSize":32,"id":43,"code":59689},"setIdx":0,"setId":6,"iconIdx":43},{"icon":{"paths":["M193.603 416h-33.603c-17.673 0-32 14.326-32 32s14.327 32 32 32h704c17.674 0 32-14.326 32-32s-14.326-32-32-32h-33.603c-7.347-73.117-39.702-141.853-92.122-194.274-60.013-60.012-141.405-93.726-226.275-93.726s-166.262 33.714-226.274 93.726c-52.421 52.421-84.777 121.157-92.123 194.274zM330.979 266.981c48.010-48.010 113.126-74.981 181.021-74.981s133.011 26.971 181.021 74.981c40.403 40.404 65.907 92.923 72.973 149.019h-507.987c7.066-56.096 32.57-108.615 72.972-149.019z","M877.242 605.133c16.090-7.315 23.203-26.285 15.891-42.374-7.315-16.090-26.285-23.203-42.374-15.891l-127.558 57.981-127.558-57.981c-8.413-3.824-18.070-3.824-26.483 0l-127.558 57.981-127.558-57.981c-8.413-3.824-18.070-3.824-26.483 0l-140.8 64c-16.089 7.315-23.203 26.285-15.89 42.374s26.284 23.203 42.373 15.891l18.758-8.528v29.68c0 38.102 15.908 74.31 43.672 100.752 27.712 26.394 64.978 40.963 103.528 40.963h345.6c38.55 0 75.814-14.57 103.526-40.963 27.766-26.442 43.674-62.65 43.674-100.752v-64.589l45.242-20.563zM736.442 669.133l31.558-14.346v35.498c0 20.093-8.368 39.699-23.811 54.41-15.494 14.758-36.832 23.306-59.389 23.306h-345.6c-22.556 0-43.893-8.547-59.39-23.306-15.444-14.71-23.81-34.317-23.81-54.41v-58.771l44.8-20.362 127.558 57.981c8.413 3.824 18.070 3.824 26.483 0l127.558-57.981 127.558 57.981c8.413 3.824 18.070 3.824 26.483 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["burger"],"defaultCode":59813,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":956,"id":44,"name":"burger","prevSize":32,"code":59813},"setIdx":0,"setId":6,"iconIdx":44},{"icon":{"paths":["M224 224h320v576h-96v-112c0-8.835-7.165-16-16-16h-96c-8.835 0-16 7.165-16 16v112h-96v-576zM608 448h192v352h-192v-352zM832 384h-224v-192c0-17.673-14.326-32-32-32h-384c-17.673 0-32 14.327-32 32v640c0 17.674 14.327 32 32 32h640c17.674 0 32-14.326 32-32v-416c0-17.674-14.326-32-32-32zM304 288c-8.836 0-16 7.164-16 16v32c0 8.835 7.164 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.836-7.165-16-16-16h-32zM288 432c0-8.835 7.164-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.836 0-16-7.165-16-16v-32zM304 544c-8.836 0-16 7.165-16 16v32c0 8.835 7.164 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM416 304c0-8.836 7.165-16 16-16h32c8.835 0 16 7.164 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32zM432 416c-8.835 0-16 7.165-16 16v32c0 8.835 7.165 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM416 560c0-8.835 7.165-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32zM688 512c-8.835 0-16 7.165-16 16v32c0 8.835 7.165 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM672 656c0-8.835 7.165-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["business"],"defaultCode":59690,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":957,"name":"business","prevSize":32,"id":45,"code":59690},"setIdx":0,"setId":6,"iconIdx":45},{"icon":{"paths":["M277.831 157.44c0-16.259 13.181-29.44 29.44-29.44s29.439 13.181 29.439 29.44v58.876h353.28v-58.876c0-16.259 13.181-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.876h85.76c17.674 0 32 14.327 32 32v583.68c0 17.674-14.326 32-32 32h-642.559c-17.673 0-32-14.326-32-32v-583.68c0-1.105 0.056-2.196 0.165-3.272 1.639-16.136 15.266-28.728 31.835-28.728h85.76v-58.876zM802.63 392.957h-578.559v407.040h578.559v-407.040zM425.034 644.474c0-8.835 7.162-16 16-16h26.88c8.835 0 16 7.165 16 16v26.88c0 8.838-7.165 16-16 16h-26.88c-8.838 0-16-7.162-16-16v-26.88zM323.27 510.72c-8.836 0-15.999 7.162-15.999 16v26.88c0 8.835 7.163 16 15.999 16h26.88c8.838 0 16-7.165 16-16v-26.88c0-8.838-7.162-16-16-16h-26.88zM542.79 526.72c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.835-7.162 16-16 16h-26.88c-8.835 0-16-7.165-16-16v-26.88zM323.27 628.474c-8.835 0-15.999 7.165-15.999 16v26.88c0 8.838 7.164 16 15.999 16h26.88c8.838 0 16-7.162 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88zM542.79 644.474c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.838-7.162 16-16 16h-26.88c-8.835 0-16-7.162-16-16v-26.88zM441.030 510.72c-8.835 0-16 7.165-16 16v26.88c0 8.835 7.165 16 16 16h26.88c8.838 0 16-7.165 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88zM660.55 526.72c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.835-7.162 16-16 16h-26.88c-8.835 0-16-7.165-16-16v-26.88zM676.55 628.474c-8.835 0-16 7.165-16 16v26.88c0 8.838 7.165 16 16 16h26.88c8.838 0 16-7.162 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["calendar"],"defaultCode":59691,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":958,"name":"calendar","prevSize":32,"id":46,"code":59691},"setIdx":0,"setId":6,"iconIdx":46},{"icon":{"paths":["M256 202.672c0-17.673 19.102-32 42.667-32h255.999c23.565 0 42.669 14.327 42.669 32s-19.104 32-42.669 32h-255.999c-23.564 0-42.667-14.327-42.667-32zM160 383.994c0-5.891 4.776-10.666 10.667-10.666h511.999c5.891 0 10.669 4.774 10.669 10.666v85.334c0 11.376 6.038 21.894 15.859 27.632s21.949 5.83 31.856 0.243l97.83-55.165c2.531-1.427 4.858-3.19 6.912-5.248 6.72-6.717 18.208-1.958 18.208 7.546v263.318c0 9.504-11.488 14.262-18.208 7.542-2.054-2.054-4.381-3.818-6.912-5.245l-97.83-55.165c-9.907-5.587-22.035-5.494-31.856 0.243s-15.859 16.256-15.859 27.632v85.331c0 5.891-4.778 10.669-10.669 10.669h-511.999c-5.891 0-10.667-4.778-10.667-10.669v-384zM170.667 309.328c-41.237 0-74.667 33.43-74.667 74.666v384c0 41.238 33.429 74.669 74.667 74.669h511.999c41.238 0 74.669-33.43 74.669-74.669v-30.55l46.778 26.374c47.418 41.99 123.888 8.701 123.888-56.163v-263.318c0-64.864-76.47-98.157-123.888-56.166l-46.778 26.378v-30.554c0-41.235-33.43-74.666-74.669-74.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["camera"],"defaultCode":59696,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":959,"name":"camera","prevSize":32,"id":47,"code":59696},"setIdx":0,"setId":6,"iconIdx":47},{"icon":{"paths":["M866.128 153.126c-12.496-12.497-32.758-12.497-45.254 0l-668.246 668.246c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l668.246-668.246c12.496-12.497 12.496-32.758 0-45.255zM298.667 170.671c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h255.999c23.565 0 42.669-14.327 42.669-32s-19.104-32-42.669-32h-255.999zM574.173 309.327h-403.506c-41.237 0-74.667 33.428-74.667 74.667v384c0 6.010 0.71 11.856 2.051 17.453l61.949-61.949v-339.504c0-5.891 4.776-10.666 10.667-10.666h339.506l64-64.001zM376.339 778.659h306.326c5.891 0 10.669-4.774 10.669-10.666v-85.334c0-11.373 6.038-21.891 15.859-27.629s21.949-5.83 31.856-0.243l97.83 55.162c2.531 1.427 4.858 3.194 6.912 5.248 6.72 6.72 18.208 1.962 18.208-7.542v-263.322c0-9.501-11.488-14.262-18.208-7.542-2.054 2.054-4.381 3.821-6.912 5.248l-97.83 55.162c-9.907 5.587-22.035 5.494-31.856-0.243-9.821-5.734-15.859-16.256-15.859-27.629v-7.661l110.778-73.498c47.418-41.99 123.888-8.701 123.888 56.163v263.322c0 64.864-76.47 98.154-123.888 56.163l-46.778-26.378v30.554c0 41.238-33.43 74.666-74.669 74.666h-370.327l64.001-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["camera-disabled"],"defaultCode":59692,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":960,"name":"camera-disabled","prevSize":32,"id":48,"code":59692},"setIdx":0,"setId":6,"iconIdx":48},{"icon":{"paths":["M288 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h256c17.674 0 32-14.327 32-32s-14.326-32-32-32h-256z","M170.667 341.328c-23.564 0-42.667 19.104-42.667 42.666v384c0 23.565 19.102 42.669 42.667 42.669h511.999c23.565 0 42.669-19.104 42.669-42.669v-128l97.83 97.83c26.877 26.88 72.835 7.843 72.835-30.17v-263.318c0-38.013-45.958-57.050-72.835-30.173l-97.83 97.83v-128c0-23.562-19.104-42.666-42.669-42.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["camera-filled"],"defaultCode":59693,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":961,"name":"camera-filled","prevSize":32,"id":49,"code":59693},"setIdx":0,"setId":6,"iconIdx":49},{"icon":{"paths":["M196.731 191.997c0-15.807 12.814-28.622 28.622-28.622h128.001c15.805 0 28.621 12.814 28.621 28.622s-12.816 28.621-28.621 28.621h-128.001c-15.807 0-28.622-12.814-28.622-28.621z","M737.354 559.997c0 97.203-78.8 176-176 176-97.203 0-176-78.797-176-176s78.797-176 176-176c97.2 0 176 78.797 176 176zM673.354 559.997c0-61.856-50.144-112-112-112s-112 50.144-112 112c0 61.856 50.144 112 112 112s112-50.144 112-112z","M193.353 255.997c-35.346 0-64 28.654-64 64v448c0 35.347 28.654 64 64 64h640.001c35.344 0 64-28.653 64-64v-448c0-35.346-28.656-64-64-64h-640.001zM833.354 319.997v448h-640.001v-448h640.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["camera-photo"],"defaultCode":59694,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":962,"name":"camera-photo","prevSize":32,"id":50,"code":59694},"setIdx":0,"setId":6,"iconIdx":50},{"icon":{"paths":["M298.667 170.672c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h255.999c23.565 0 42.669-14.327 42.669-32s-19.104-32-42.669-32h-255.999z","M545.712 503.453c11.267-11.267 11.19-29.61-0.17-40.97s-29.706-11.437-40.973-0.17l-71.402 71.402-71.994-71.997c-11.363-11.36-29.706-11.437-40.973-0.17s-11.19 29.61 0.17 40.97l71.997 71.997-71.402 71.402c-11.266 11.267-11.19 29.61 0.17 40.97 11.363 11.36 29.706 11.437 40.973 0.17l71.402-71.402 71.997 71.997c11.36 11.36 29.702 11.437 40.97 0.17s11.19-29.61-0.17-40.97l-71.997-71.997 71.402-71.402z","M96 383.994c0-41.235 33.429-74.666 74.667-74.666h511.999c41.238 0 74.669 33.43 74.669 74.666v30.554l46.778-26.378c47.418-41.99 123.888-8.698 123.888 56.166v263.318c0 64.864-76.47 98.154-123.888 56.163l-46.778-26.374v30.55c0 41.238-33.43 74.669-74.669 74.669h-511.999c-41.237 0-74.667-33.43-74.667-74.669v-384zM170.667 373.328c-5.891 0-10.667 4.774-10.667 10.666v384c0 5.891 4.776 10.669 10.667 10.669h511.999c5.891 0 10.669-4.778 10.669-10.669v-85.331c0-11.376 6.038-21.894 15.859-27.632s21.949-5.83 31.856-0.243l97.83 55.165c2.531 1.427 4.858 3.19 6.912 5.245 6.72 6.72 18.208 1.962 18.208-7.542v-263.318c0-9.504-11.488-14.262-18.208-7.546-2.054 2.058-4.381 3.821-6.912 5.248l-97.83 55.165c-9.907 5.587-22.035 5.494-31.856-0.243s-15.859-16.256-15.859-27.632v-85.334c0-5.891-4.778-10.666-10.669-10.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["camera-unavailable"],"defaultCode":59695,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":963,"name":"camera-unavailable","prevSize":32,"id":51,"code":59695},"setIdx":0,"setId":6,"iconIdx":51},{"icon":{"paths":["M224.248 304.026c-49.642 68.947-66.502 152.646-66.502 207.968v1.453l-0.132 1.446c-9.702 106.717 28.59 181.93 90.135 234.006 62.938 53.254 152.152 83.731 244.197 93.958 91.965 10.218 193.27 1.446 273.306-15.482 40.022-8.461 73.616-18.733 97.443-29.075 9.245-4.013 16.438-7.786 21.734-11.126-2.464-1.565-5.446-3.306-9.002-5.197-9.222-4.912-19.779-9.578-30.733-14.368l-1.914-0.835c-9.667-4.221-20.47-8.941-28.656-13.517-14.835-8.298-29.389-17.734-40.006-27.776-5.222-4.941-11.165-11.571-15.146-19.827-4.208-8.742-7.226-21.792-1.306-35.597 31.978-74.621 47.178-115.494 54.538-142.483 6.874-25.2 6.874-37.888 6.874-58.064v-0.182c0-16.035-9.318-89.517-55.811-158.032-45.018-66.338-125.99-129.968-274.854-129.968-134.637 0-215.698 55.382-264.165 122.698zM172.309 266.63c60.333-83.796 160.606-149.302 316.103-149.302 171.136 0 271.494 75.037 327.811 158.032 54.842 80.819 66.854 167.338 66.854 193.968 0 22.384-0.022 41.696-9.126 75.088-8.131 29.805-23.485 70.928-51.946 137.923 5.261 4.166 13.072 9.306 23.36 15.062 5.315 2.97 13.485 6.55 24.963 11.568 10.653 4.659 23.437 10.266 35.174 16.515 11.258 5.994 24.416 14.029 34.202 24.538 10.234 10.992 20.973 29.846 13.299 52.864-5.056 15.168-16.794 25.939-26.576 33.094-10.63 7.776-23.818 14.762-38.253 21.030-29.008 12.589-67.030 23.962-109.683 32.982-85.309 18.038-193.581 27.587-293.616 16.474-99.955-11.107-202.74-44.634-278.468-108.71-76.833-65.011-123.811-159.994-112.66-287.222 0.286-65.549 19.841-162.349 78.561-243.904zM493.744 320c17.674 0 32 14.326 32 32v224c0 17.674-14.326 32-32 32s-32-14.326-32-32v-224c0-17.674 14.326-32 32-32zM525.744 672c0-17.674-14.326-32-32-32s-32 14.326-32 32c0 17.674 14.326 32 32 32s32-14.326 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["canned-response"],"defaultCode":59697,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":964,"name":"canned-response","prevSize":32,"id":52,"code":59697},"setIdx":0,"setId":6,"iconIdx":52},{"icon":{"paths":["M193.352 181.331c-53.020 0-96 42.981-96 96v469.335c0 53.018 42.98 96 96 96h639.999c53.021 0 96-42.982 96-96v-469.335c0-53.019-42.979-96-96-96h-639.999zM161.352 277.331c0-17.673 14.327-32 32-32h639.999c17.674 0 32 14.327 32 32v202.673h-703.999v-202.673zM161.352 544.003h703.999v202.662c0 17.67-14.326 32-32 32h-639.999c-17.673 0-32-14.33-32-32v-202.662zM812.016 661.331c0-35.347-28.653-64-64-64-35.344 0-64 28.653-64 64s28.656 64 64 64c35.347 0 64-28.653 64-64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["card"],"defaultCode":59698,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":965,"name":"card","prevSize":32,"id":53,"code":59698},"setIdx":0,"setId":6,"iconIdx":53},{"icon":{"paths":["M368 182.4c0-17.673-14.326-32-32-32s-32 14.327-32 32v144h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v288h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v144c0 17.674 14.327 32 32 32s32-14.326 32-32v-144h288v144c0 17.674 14.326 32 32 32s32-14.326 32-32v-144h144c17.674 0 32-14.326 32-32s-14.326-32-32-32h-144v-80h-64v80h-288v-288h80v-64h-80v-144z","M640.515 327.283c-15.328-3.59-31.306-3.338-46.512 0.733-41.763 11.187-70.803 49.030-70.803 92.269v35.539c0 36.003 29.187 65.194 65.194 65.194h210.413c36.006 0 65.194-29.19 65.194-65.194v-28.336c0-47.667-33.040-88.957-79.27-99.792-16.413-3.846-33.613-3.603-49.946 0.771l-25.827 6.918c-10.381 2.781-21.286 2.95-31.747 0.499l-36.694-8.602z","M782.637 217.037c0 49.174-39.862 89.037-89.037 89.037s-89.037-39.863-89.037-89.037c0-49.174 39.862-89.037 89.037-89.037s89.037 39.863 89.037 89.037z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["channel-auto-join"],"defaultCode":59746,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":966,"name":"channel-auto-join","prevSize":32,"id":54,"code":59746},"setIdx":0,"setId":6,"iconIdx":54},{"icon":{"paths":["M236.709 162.578c11.779-5.037 25.426-2.564 34.688 6.286l150.709 144c6.32 6.037 9.894 14.396 9.894 23.136s-3.574 17.101-9.894 23.136l-150.709 144c-9.262 8.851-22.909 11.325-34.688 6.288s-19.419-16.614-19.419-29.424v-112h-73.29c-17.673 0-32-14.326-32-32 0-17.672 14.327-31.999 32-31.999h73.29v-112c0-12.81 7.64-24.386 19.419-29.423zM320 368.179v-0.179h0.189l-0.189 0.179zM320.189 304.001h-0.189v-0.179l0.189 0.179z","M492.899 303.258c8.762-9.388 21.245-15.258 35.101-15.258 26.509 0 48 21.49 48 48s-21.491 48-48 48c-16.582 0-31.203-8.41-39.824-21.197l-43.098 48.483c20.49 22.554 50.051 36.714 82.922 36.714 61.856 0 112-50.144 112-112s-50.144-112-112-112c-25.549 0-49.098 8.554-67.942 22.955l32.842 56.303z","M145.615 483.229l32.174 64.349c-0.861 3.040-1.318 6.23-1.318 9.501v44.688c0 17.674 14.327 32 32 32h79.53v64h-79.53c-53.019 0-96-42.979-96-96v-44.688c0-28.848 12.515-55.488 33.144-73.85z","M625.267 640h-0.797c0.259 0.598 0.525 1.194 0.797 1.786v-1.786z","M424.714 640h-0.797v1.786c0.272-0.592 0.538-1.187 0.797-1.786z","M477.901 494.515c-28.56-10.957-60.291-10.211-88.307 2.067-42.282 18.534-69.594 60.326-69.594 106.49v132.928c0 53.021 42.979 96 96 96h224c53.021 0 96-42.979 96-96v-125.062c0-51.162-31.536-97.034-79.306-115.354-30.352-11.642-64.067-10.851-93.84 2.198l-2.070 0.909c-21.523 9.434-45.901 10.006-67.843 1.59l-15.040-5.766zM415.286 555.2c12.595-5.52 26.858-5.856 39.699-0.931l15.040 5.77c37.664 14.445 79.504 13.462 116.451-2.73l2.070-0.909c14.349-6.288 30.602-6.669 45.229-1.059 23.024 8.829 38.224 30.938 38.224 55.597v125.062c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32v-132.928c0-20.752 12.278-39.539 31.286-47.872z","M864 320c0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96s96-42.979 96-96zM800 320c0 17.674-14.326 32-32 32s-32-14.326-32-32c0-17.673 14.326-32 32-32s32 14.327 32 32z","M840.714 697.766h-72.714v-64h72.714c17.674 0 32-14.326 32-32v-44.688c0-15.050-9.664-28.394-23.958-33.091-7.536-2.474-15.69-2.304-23.114 0.483l-4.554 1.709c-19.77 7.421-40.89 9.978-61.619 7.632-12.438-31.683-37.722-57.549-70.774-70.227-1.754-0.672-3.52-1.302-5.296-1.894 18.058-5.312 37.36-5.040 55.344 0.867l14.182 4.659c14.886 4.893 30.998 4.554 45.667-0.954l4.554-1.709c21.069-7.91 44.205-8.394 65.581-1.37 40.566 13.325 67.987 51.197 67.987 93.894v44.688c0 53.021-42.982 96-96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["channel-move-to-team"],"defaultCode":59747,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":967,"name":"channel-move-to-team","prevSize":32,"id":55,"code":59747},"setIdx":0,"setId":6,"iconIdx":55},{"icon":{"paths":["M368 160c0-17.673-14.326-32-32-32s-32 14.327-32 32v144h-144c-17.673 0-32 14.327-32 32s14.327 32 32 32h144v288h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v144c0 17.674 14.327 32 32 32s32-14.326 32-32v-144h288v144c0 17.674 14.326 32 32 32s32-14.326 32-32v-144h144c17.674 0 32-14.326 32-32s-14.326-32-32-32h-144v-80h-58.666c-1.786 0-3.565-0.042-5.334-0.118v80.118h-288v-288h168.79c-0.522-5.264-0.79-10.602-0.79-16v-48h-168v-144z","M760 96c-57.437 0-104 46.562-104 104v56h-24c-17.674 0-32 14.327-32 32v192c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-192c0-17.673-14.326-32-32-32h-24v-56c0-57.438-46.563-104-104-104zM800 255.238h-80v-55.238c0-22.092 17.907-40 40-40s40 17.908 40 40v55.238z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["channel-private"],"defaultCode":59699,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":968,"name":"channel-private","prevSize":32,"id":56,"code":59699},"setIdx":0,"setId":6,"iconIdx":56},{"icon":{"paths":["M336 128c17.674 0 32 14.327 32 32v144h288v-144c0-17.673 14.326-32 32-32s32 14.327 32 32v144h144c17.674 0 32 14.327 32 32s-14.326 32-32 32h-144v288h144c17.674 0 32 14.326 32 32s-14.326 32-32 32h-144v144c0 17.674-14.326 32-32 32s-32-14.326-32-32v-144h-288v144c0 17.674-14.326 32-32 32s-32-14.326-32-32v-144h-144c-17.673 0-32-14.326-32-32s14.327-32 32-32h144v-288h-144c-17.673 0-32-14.326-32-32s14.327-32 32-32h144v-144c0-17.673 14.327-32 32-32zM368 368v288h288v-288h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["channel-public"],"defaultCode":59700,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":969,"name":"channel-public","prevSize":32,"id":57,"code":59700},"setIdx":0,"setId":6,"iconIdx":57},{"icon":{"paths":["M886.627 105.372c12.496 12.497 12.496 32.758 0 45.255l-89.373 89.372 89.373 89.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-89.373-89.372-89.373 89.372c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l89.373-89.373-89.373-89.372c-12.496-12.497-12.496-32.758 0-45.255s32.758-12.497 45.254 0l89.373 89.373 89.373-89.373c12.496-12.497 32.758-12.497 45.254 0zM226.501 304.042c-49.642 68.947-66.502 152.646-66.502 207.968v1.453l-0.132 1.446c-9.701 106.717 28.59 181.93 90.135 234.006 62.938 53.254 152.151 83.731 244.196 93.958 91.968 10.218 193.27 1.446 273.309-15.482 40.019-8.461 73.613-18.733 97.44-29.075 9.245-4.013 16.438-7.786 21.738-11.126-2.467-1.565-5.446-3.306-9.005-5.2-9.222-4.909-19.776-9.574-30.733-14.365l-1.917-0.838c-9.667-4.221-20.47-8.938-28.653-13.517-14.835-8.294-29.389-17.731-40.003-27.773-5.226-4.941-11.168-11.571-15.146-19.827-4.211-8.742-7.226-21.792-1.309-35.6 42.086-98.205 54.957-137.722 59.219-163.318 2.906-17.434 19.392-29.21 36.822-26.307 17.434 2.906 29.213 19.389 26.307 36.822-5.453 32.749-20.333 76.41-58.006 165.088 5.261 4.166 13.069 9.306 23.357 15.059 5.315 2.973 13.485 6.554 24.963 11.571 10.656 4.656 23.437 10.266 35.174 16.515 11.261 5.994 24.419 14.029 34.202 24.538 10.234 10.992 20.973 29.846 13.299 52.864-5.053 15.168-16.794 25.939-26.576 33.094-10.627 7.776-23.814 14.762-38.253 21.027-29.005 12.592-67.027 23.965-109.68 32.986-85.312 18.038-193.584 27.587-293.616 16.47-99.955-11.104-202.742-44.63-278.471-108.707-76.833-65.014-123.811-159.997-112.66-287.222 0.286-65.549 19.841-162.349 78.561-243.904 60.333-83.796 160.605-149.302 316.103-149.302 17.674 0 32 14.327 32 32s-14.326 32-32 32c-134.637 0-215.697 55.382-264.164 122.698z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chat-close"],"defaultCode":59701,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":970,"name":"chat-close","prevSize":32,"id":58,"code":59701},"setIdx":0,"setId":6,"iconIdx":58},{"icon":{"paths":["M778 93.833c-11.795-13.162-32.026-14.271-45.187-2.477s-14.272 32.025-2.477 45.187l81.222 90.645h-216.358c-17.674 0-32 14.327-32 32s14.326 32 32 32h216.358l-81.222 90.646c-11.795 13.162-10.685 33.392 2.477 45.187 13.162 11.792 33.392 10.685 45.187-2.477l129.030-144.001c10.893-12.154 10.893-30.556 0-42.71l-129.030-144zM159.999 512.010c0-55.322 16.86-139.021 66.502-207.968 48.467-67.316 129.527-122.698 264.164-122.698 17.674 0 32-14.327 32-32s-14.326-32-32-32c-155.498 0-255.77 65.507-316.102 149.302-58.72 81.555-78.275 178.355-78.561 243.904-11.151 127.229 35.827 222.211 112.66 287.222 75.729 64.077 178.516 97.603 278.471 108.707 100.032 11.117 208.304 1.568 293.616-16.47 42.653-9.021 80.675-20.394 109.68-32.982 14.438-6.269 27.626-13.254 38.253-21.030 9.782-7.155 21.523-17.926 26.579-33.094 7.67-23.018-3.069-41.872-13.302-52.864-9.782-10.509-22.941-18.544-34.202-24.538-11.738-6.25-24.518-11.859-35.171-16.515-11.482-5.018-19.651-8.598-24.966-11.571-10.288-5.754-18.096-10.89-23.357-15.059 37.674-88.678 52.554-132.339 58.010-165.088 2.902-17.43-8.877-33.917-26.31-36.822-17.43-2.902-33.917 8.877-36.822 26.307-4.262 25.597-17.133 65.114-59.219 163.318-5.917 13.808-2.902 26.858 1.309 35.6 3.978 8.256 9.92 14.886 15.146 19.827 10.614 10.042 25.171 19.478 40.003 27.776 8.186 4.576 18.989 9.296 28.656 13.517v0l1.914 0.835c10.957 4.79 21.51 9.456 30.733 14.368 3.558 1.891 6.541 3.632 9.005 5.197-5.299 3.341-12.493 7.114-21.738 11.126-23.827 10.342-57.421 20.614-97.44 29.075-80.038 16.928-181.341 25.699-273.309 15.482-92.045-10.227-181.258-40.704-244.196-93.958-61.545-52.077-99.836-127.29-90.135-234.006l0.132-1.446v-1.453z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chat-forward"],"defaultCode":59702,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":971,"name":"chat-forward","prevSize":32,"id":59,"code":59702},"setIdx":0,"setId":6,"iconIdx":59},{"icon":{"paths":["M854.506 233.252c12.563 12.429 12.672 32.691 0.243 45.254l-474.877 480c-6.013 6.077-14.208 9.498-22.755 9.494-8.55-0.003-16.742-3.427-22.752-9.507l-165.126-167.088c-12.423-12.57-12.303-32.832 0.268-45.254s32.831-12.304 45.254 0.269l142.375 144.067 452.115-456.992c12.429-12.564 32.691-12.672 45.254-0.243z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["check"],"defaultCode":59703,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":972,"name":"check","prevSize":32,"id":60,"code":59703},"setIdx":0,"setId":6,"iconIdx":60},{"icon":{"paths":["M204.8 128h614.4c42.416 0 76.8 34.385 76.8 76.8v614.4c0 42.416-34.384 76.8-76.8 76.8h-614.4c-42.415 0-76.8-34.384-76.8-76.8v-614.4c0-42.415 34.385-76.8 76.8-76.8zM769.062 336.88c9.322-9.424 9.238-24.619-0.182-33.941-9.424-9.322-24.621-9.241-33.942 0.182l-339.085 342.745-106.782-108.051c-9.317-9.43-24.513-9.52-33.94-0.202s-9.518 24.512-0.201 33.939l123.842 125.318c4.509 4.56 10.653 7.126 17.066 7.13s12.557-2.563 17.069-7.12l356.157-360z"],"attrs":[{"fill":"rgb(29, 116, 245)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":5}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":4}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":6}]},"tags":["checkbox-checked"],"defaultCode":59654,"grid":0},"attrs":[{"fill":"rgb(29, 116, 245)"}],"properties":{"order":973,"name":"checkbox-checked","prevSize":32,"id":61,"code":59654},"setIdx":0,"setId":6,"iconIdx":61},{"icon":{"paths":["M819.2 204.8v614.4h-614.4v-614.4h614.4zM204.8 128c-42.415 0-76.8 34.385-76.8 76.8v614.4c0 42.416 34.385 76.8 76.8 76.8h614.4c42.416 0 76.8-34.384 76.8-76.8v-614.4c0-42.415-34.384-76.8-76.8-76.8h-614.4z"],"attrs":[{"fill":"rgb(203, 206, 209)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":8}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":8}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":10}]},"tags":["checkbox-unchecked"],"defaultCode":59653,"grid":0},"attrs":[{"fill":"rgb(203, 206, 209)"}],"properties":{"order":974,"name":"checkbox-unchecked","prevSize":32,"id":62,"code":59653},"setIdx":0,"setId":6,"iconIdx":62},{"icon":{"paths":["M281.372 436.042c12.497-12.499 32.758-12.499 45.255 0l185.373 185.373 185.373-185.373c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-208 208c-12.496 12.496-32.758 12.496-45.254 0l-208-208c-12.497-12.496-12.497-32.758 0-45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-down"],"defaultCode":59704,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":975,"name":"chevron-down","prevSize":32,"id":63,"code":59704},"setIdx":0,"setId":6,"iconIdx":63},{"icon":{"paths":["M587.962 281.372c12.496 12.497 12.496 32.758 0 45.255l-185.373 185.373 185.373 185.373c12.496 12.496 12.496 32.758 0 45.254-12.499 12.496-32.758 12.496-45.258 0l-208-208c-12.496-12.496-12.496-32.758 0-45.254l208-208c12.499-12.497 32.758-12.497 45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-left"],"defaultCode":59706,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":976,"name":"chevron-left","prevSize":32,"id":64,"code":59706},"setIdx":0,"setId":6,"iconIdx":64},{"icon":{"paths":["M670.17 183.165c16.662 16.662 16.662 43.677 0 60.34l-268.496 268.495 268.496 268.499c16.662 16.662 16.662 43.677 0 60.339s-43.677 16.662-60.339 0l-298.668-298.669c-8.002-8-12.497-18.851-12.497-30.17 0-11.315 4.495-22.166 12.497-30.17l298.668-298.666c16.662-16.662 43.677-16.662 60.339 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-left-big"],"defaultCode":59705,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":977,"name":"chevron-left-big","prevSize":32,"id":65,"code":59705},"setIdx":0,"setId":6,"iconIdx":65},{"icon":{"paths":["M436.038 742.627c-12.496-12.496-12.496-32.758 0-45.254l185.373-185.373-185.373-185.373c-12.496-12.497-12.496-32.758 0-45.254 12.499-12.497 32.758-12.497 45.254 0l208 208c12.499 12.496 12.499 32.758 0 45.254l-207.997 208c-12.499 12.496-32.758 12.496-45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-right"],"defaultCode":59707,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":978,"name":"chevron-right","prevSize":32,"id":66,"code":59707},"setIdx":0,"setId":6,"iconIdx":66},{"icon":{"paths":["M742.627 587.958c-12.496 12.499-32.758 12.499-45.254 0l-185.373-185.373-185.373 185.373c-12.496 12.499-32.758 12.499-45.254 0-12.497-12.496-12.497-32.758 0-45.254l208-208c12.496-12.496 32.758-12.496 45.254 0l208 208c12.496 12.496 12.496 32.758 0 45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-up"],"defaultCode":59708,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":979,"name":"chevron-up","prevSize":32,"id":67,"code":59708},"setIdx":0,"setId":6,"iconIdx":67},{"icon":{"paths":["M512 864c194.403 0 352-157.597 352-352 0-46.522-9.024-90.931-25.418-131.581l48.518-48.518c26.211 54.496 40.899 115.581 40.899 180.099 0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416 95.376 0 183.254 32.096 253.424 86.076l-45.712 45.712c-58.221-42.623-130.029-67.788-207.712-67.788-194.404 0-352 157.596-352 352s157.596 352 352 352zM902.63 230.623c12.496-12.499 12.493-32.76-0.006-45.255s-32.762-12.491-45.254 0.008l-345.386 345.503-105.341-105.491c-12.486-12.506-32.749-12.522-45.254-0.032-12.506 12.486-12.522 32.749-0.032 45.254l127.971 128.157c6 6.006 14.144 9.386 22.634 9.389 8.493 0 16.637-3.373 22.64-9.376l368.029-368.157z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["circle-check"],"defaultCode":59709,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":980,"name":"circle-check","prevSize":32,"id":68,"code":59709},"setIdx":0,"setId":6,"iconIdx":68},{"icon":{"paths":["M608 192c0-53.019-42.979-96-96-96s-96 42.981-96 96h-192c-17.673 0-32 14.327-32 32v672c0 17.674 14.327 32 32 32h576c17.674 0 32-14.326 32-32v-672c0-17.673-14.326-32-32-32h-192zM256 864v-608h96v64c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-64h96v608h-512zM512 224c17.674 0 32-14.327 32-32s-14.326-32-32-32c-17.674 0-32 14.327-32 32s14.326 32 32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["clipboard"],"defaultCode":59710,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":981,"name":"clipboard","prevSize":32,"id":69,"code":59710},"setIdx":0,"setId":6,"iconIdx":69},{"icon":{"paths":["M864 512c0 194.403-157.597 352-352 352s-352-157.597-352-352c0-194.404 157.596-352 352-352s352 157.596 352 352zM928 512c0-229.75-186.25-416-416-416s-416 186.25-416 416c0 229.75 186.25 416 416 416s416-186.25 416-416zM544 288c0-17.673-14.326-32-32-32s-32 14.327-32 32v224c0 8.486 3.373 16.627 9.373 22.627l96 96c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-86.627-86.627v-210.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["clock"],"defaultCode":59711,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":982,"name":"clock","prevSize":32,"id":70,"code":59711},"setIdx":0,"setId":6,"iconIdx":70},{"icon":{"paths":["M806.627 262.628c12.496-12.497 12.496-32.758 0-45.255s-32.758-12.497-45.254 0l-249.373 249.373-249.372-249.373c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l249.373 249.372-249.373 249.373c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l249.372-249.373 249.373 249.373c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-249.373-249.373 249.373-249.372z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["close"],"defaultCode":59712,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":983,"name":"close","prevSize":32,"id":71,"code":59712},"setIdx":0,"setId":6,"iconIdx":71},{"icon":{"paths":["M273.129 356.678c6.747-28.298 25.696-52.004 51.21-67.152 25.6-15.2 56.323-20.858 84.698-14.53 27.642 6.163 55.117 24.12 74.874 60.339l22.541 41.325 30.134-36.16c27.238-32.689 85.126-39.713 134.714-14.064 23.562 12.186 42.208 30.618 52.064 53.488 9.654 22.406 12.112 51.898-1.434 89.149l-15.616 42.938h45.686c53.606 0 82.419 15.882 97.642 33.75 15.651 18.374 21.898 44.646 18.557 74.714-3.344 30.083-16.054 60.518-33.456 82.89-17.939 23.066-36.646 32.646-50.742 32.646h-543.998c-18.791 0-37.068-10.362-52.195-31.578-15.217-21.344-24.978-51.050-25.818-81.312-0.84-30.227 7.237-57.914 23.733-77.491 15.796-18.746 42.268-33.619 86.279-33.619h59.791l-33.165-49.75c-27.882-41.824-32.118-77.814-25.498-105.581zM518.218 272.084c-26.339-32.073-59.667-51.619-95.251-59.554-45.626-10.174-92.902-0.833-131.301 21.965-38.487 22.85-69.538 60.142-80.791 107.342-8.278 34.72-5.369 72.758 10.731 111.77-35.67 8.464-64.099 26.186-84.825 50.784-29.004 34.422-39.927 78.733-38.766 120.506 1.159 41.738 14.399 84.032 37.682 116.688 23.373 32.784 59.097 58.426 104.306 58.426h543.999c41.907 0 77.2-26.419 101.261-57.354 24.598-31.629 41.888-73.197 46.544-115.114 4.659-41.933-3.094-87.658-33.443-123.283-24.106-28.301-59.504-46.774-105.616-53.456 5.83-35.194 1.686-67.674-10.605-96.205-16.646-38.628-46.998-67.197-81.437-85.010-54.902-28.397-128.733-32.652-182.486 2.495zM512 437.331c17.674 0 32 14.33 32 32v53.328h53.334c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-53.334v53.341c0 17.674-14.326 32-32 32s-32-14.326-32-32v-53.341h-53.331c-17.674 0-32-14.326-32-32 0-17.67 14.326-32 32-32h53.331v-53.328c0-17.67 14.326-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["cloud-connectivity"],"defaultCode":59713,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":984,"name":"cloud-connectivity","prevSize":32,"id":72,"code":59713},"setIdx":0,"setId":6,"iconIdx":72},{"icon":{"paths":["M630.157 204.798c16.493 6.344 24.723 24.859 18.378 41.355l-213.331 554.667c-6.346 16.496-24.861 24.723-41.357 18.381-16.493-6.346-24.723-24.861-18.378-41.357l213.331-554.666c6.346-16.495 24.861-24.724 41.357-18.38zM321.296 361.37c12.496 12.499 12.496 32.758 0 45.258l-105.373 105.37 105.373 105.373c12.496 12.499 12.496 32.758 0 45.258-12.497 12.496-32.759 12.496-45.255 0l-128-128c-12.497-12.499-12.497-32.758 0-45.258l128-128c12.497-12.496 32.758-12.496 45.255 0zM702.707 361.37c12.496-12.496 32.758-12.496 45.254 0l128 128c12.496 12.499 12.496 32.758 0 45.258l-128 128c-12.496 12.496-32.758 12.496-45.254 0-12.496-12.499-12.496-32.758 0-45.258l105.373-105.373-105.373-105.37c-12.496-12.499-12.496-32.758 0-45.258z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["code"],"defaultCode":59714,"grid":0},"attrs":[{}],"properties":{"order":985,"name":"code","prevSize":32,"id":73,"code":59714},"setIdx":0,"setId":6,"iconIdx":73},{"icon":{"paths":["M507.488 130.134c16.496 6.344 24.723 24.859 18.378 41.354l-160 416c-6.342 16.496-24.858 24.723-41.354 18.381-16.494-6.346-24.723-24.861-18.379-41.357l160.002-415.998c6.342-16.495 24.858-24.724 41.354-18.38z","M278.628 249.373c12.497 12.497 12.497 32.758 0 45.255l-73.373 73.372 73.373 73.373c12.497 12.496 12.497 32.758 0 45.254-12.497 12.499-32.758 12.499-45.255 0l-96-96c-6.001-6-9.372-14.141-9.372-22.627s3.372-16.624 9.372-22.627l96-95.999c12.497-12.497 32.758-12.497 45.255 0z","M553.373 249.373c12.496-12.497 32.758-12.497 45.254 0l96 95.999c6 6.003 9.373 14.141 9.373 22.627s-3.373 16.627-9.373 22.627l-96 96c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.758 0-45.254l73.373-73.373-73.373-73.372c-12.496-12.497-12.496-32.758 0-45.255z","M672 160c0-17.673 14.326-32 32-32h96c53.021 0 96 42.981 96 96v576c0 53.021-42.979 96-96 96h-576c-53.020 0-96-42.979-96-96v-160c0-17.674 14.327-32 32-32s32 14.326 32 32v192h640v-640h-128c-17.674 0-32-14.327-32-32z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{},{},{},{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{},{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{},{},{}]},"tags":["code-block"],"defaultCode":59840,"grid":0},"attrs":[{},{},{},{}],"properties":{"order":986,"id":74,"name":"code-block","prevSize":32,"code":59840},"setIdx":0,"setId":6,"iconIdx":74},{"icon":{"paths":["M770.704 224c17.674 0 32 14.327 32 32v544c0 17.674-14.326 32-32 32h-543.999c-17.673 0-32-14.326-32-32v-128c17.673 0 32-14.326 32-32s-14.327-32-32-32v-192c17.673 0 32-14.326 32-32s-14.327-32-32-32v-96c0-17.673 14.327-32 32-32h543.999zM130.705 608c-17.673 0-32 14.326-32 32s14.327 32 32 32v128c0 53.021 42.981 96 96 96h543.999c53.021 0 96-42.979 96-96v-544c0-53.019-42.979-96-96-96h-543.999c-53.019 0-96 42.981-96 96v96c-17.673 0-32 14.326-32 32s14.327 32 32 32v192zM427.91 514.266c13.315-3.568 27.309-3.789 40.73-0.643l31.52 7.389c8.73 2.045 17.83 1.904 26.49-0.416l22.186-5.942c14.285-3.827 29.328-4.042 43.683-0.675 40.429 9.475 69.325 45.584 69.325 87.277v24.336c0 31.811-25.789 57.6-57.6 57.6h-180.739c-31.811 0-57.6-25.789-57.6-57.6v-30.525c0-37.862 25.434-71.005 62.006-80.8zM456.957 563.472c-5.206-1.219-10.634-1.133-15.798 0.25-14.189 3.798-24.054 16.656-24.054 31.344v30.525c0 3.536 2.867 6.4 6.4 6.4h180.739c3.533 0 6.4-2.864 6.4-6.4v-24.336c0-17.75-12.365-33.341-29.808-37.427-6.186-1.45-12.662-1.35-18.752 0.282l-22.186 5.942c-16.813 4.502-34.474 4.781-51.421 0.81l-31.52-7.389zM539.155 420.48c0-13.962-11.318-25.28-25.28-25.28s-25.283 11.318-25.283 25.28c0 13.962 11.322 25.28 25.283 25.28s25.28-11.318 25.28-25.28zM590.355 420.48c0 42.24-34.243 76.48-76.48 76.48-42.24 0-76.483-34.24-76.483-76.48s34.243-76.48 76.483-76.48c42.237 0 76.48 34.24 76.48 76.48z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["contacts"],"defaultCode":59715,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":987,"name":"contacts","prevSize":32,"id":75,"code":59715},"setIdx":0,"setId":6,"iconIdx":75},{"icon":{"paths":["M464 272c-35.347 0-64 28.654-64 64v480c0 35.347 28.653 64 64 64h352c35.347 0 64-28.653 64-64v-304c0-6.509-1.984-12.864-5.69-18.214l-134.458-194.215c-11.952-17.267-31.619-27.571-52.621-27.571h-223.232zM464 336h144v144c0 35.347 28.653 64 64 64h144v272h-352v-480zM672 480v-144h15.232l99.693 144h-114.925zM144 208c0-35.346 28.654-64 64-64h241.844c18.032 0 35.229 7.607 47.357 20.949l39.136 43.051h-328.336v480h128v64h-128c-35.346 0-64-28.653-64-64v-480z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["copy"],"defaultCode":59716,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":988,"name":"copy","prevSize":32,"id":76,"code":59716},"setIdx":0,"setId":6,"iconIdx":76},{"icon":{"paths":["M824.682 183.521c-37.19-37.986-98.202-38.583-136.131-1.333l-348.48 342.237c-12.739 12.512-21.733 28.32-25.976 45.654l-23.681 96.749c-6.94 28.355 16.754 54.845 45.747 51.142l90.691-11.578c20.224-2.582 39.104-11.52 53.907-25.52l360.486-340.922c38.986-36.868 40.173-98.482 2.637-136.82l-19.2-19.61zM733.485 227.821c12.643-12.417 32.979-12.218 45.376 0.444l19.2 19.61c12.512 12.78 12.115 33.317-0.88 45.607l-69.965 66.169-63.446-63.364 69.715-68.466zM618.074 341.162l62.592 62.512-243.971 230.73c-4.934 4.666-11.229 7.645-17.968 8.506l-58.307 7.443 15.926-65.075c1.414-5.779 4.413-11.046 8.659-15.219l233.069-228.896zM193.608 265.602c0-17.673 14.346-32 32.042-32h281.332c17.696 0 32.042-14.327 32.042-32s-14.346-32-32.042-32h-281.332c-53.089 0-96.127 42.981-96.127 96v534.402c0 53.018 43.037 95.997 96.127 95.997h529.764c53.091 0 96.128-42.979 96.128-96v-279.414c0-17.67-14.346-32-32.042-32s-32.042 14.33-32.042 32v279.414c0 17.674-14.346 32-32.045 32h-529.764c-17.696 0-32.042-14.326-32.042-31.997v-534.402z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["create"],"defaultCode":59717,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":989,"name":"create","prevSize":32,"id":77,"code":59717},"setIdx":0,"setId":6,"iconIdx":77},{"icon":{"paths":["M717.373 298.663c0-17.673-14.326-32-32-32s-32 14.327-32 32v426.665c0 17.674 14.326 32 32 32s32-14.326 32-32v-426.665z","M514.704 394.672c17.674 0 32 14.326 32 32v298.666c0 17.674-14.326 32-32 32s-32-14.326-32-32v-298.666c0-17.674 14.326-32 32-32z","M376.038 554.672c0-17.674-14.326-32-32-32s-32 14.326-32 32v170.669c0 17.67 14.327 32 32 32s32-14.33 32-32v-170.669z","M130.705 199.556v624.889c0 39.52 32.036 71.555 71.556 71.555h624.888c39.52 0 71.555-32.035 71.555-71.555v-624.889c0-39.519-32.035-71.556-71.555-71.556h-624.888c-39.519 0-71.556 32.036-71.556 71.556zM202.26 192h624.888c4.173 0 7.555 3.383 7.555 7.556v624.889c0 4.173-3.382 7.555-7.555 7.555h-624.888c-4.173 0-7.556-3.382-7.556-7.555v-624.889c0-4.173 3.383-7.556 7.556-7.556z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["dashboard"],"defaultCode":59718,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":990,"name":"dashboard","prevSize":32,"id":78,"code":59718},"setIdx":0,"setId":6,"iconIdx":78},{"icon":{"paths":["M739.68 864v-448h-448.593v448h448.593zM227.003 864v-448c-35.393 0-64.084-28.653-64.084-64v-128c0-35.346 28.692-64 64.084-64h224.297c0-35.346 28.691-64 64.083-64 35.395 0 64.086 28.654 64.086 64h224.294c35.395 0 64.086 28.654 64.086 64v128c0 35.347-28.691 64-64.086 64v448c0 35.347-28.691 64-64.083 64h-448.593c-35.393 0-64.085-28.653-64.085-64zM803.763 224h-576.761v128h576.761v-128zM419.258 544v192c0 17.674 14.346 32 32.042 32s32.042-14.326 32.042-32v-192c0-17.674-14.346-32-32.042-32s-32.042 14.326-32.042 32zM579.469 512c17.696 0 32.042 14.326 32.042 32v192c0 17.674-14.346 32-32.042 32s-32.042-14.326-32.042-32v-192c0-17.674 14.346-32 32.042-32z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["delete"],"defaultCode":59719,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":991,"name":"delete","prevSize":32,"id":79,"code":59719},"setIdx":0,"setId":6,"iconIdx":79},{"icon":{"paths":["M341.334 778.672c-17.674 0-32 14.326-32 32s14.327 32 32 32h341.334c17.67 0 32-14.326 32-32s-14.33-32-32-32h-341.334z","M85.334 298.672c0-70.692 57.308-128 128-128h597.335c70.691 0 128 57.308 128 128v298.666c0 70.694-57.309 128-128 128h-597.335c-70.692 0-128-57.306-128-128v-298.666zM213.334 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.347 28.654 64 64 64h597.335c35.344 0 64-28.653 64-64v-298.666c0-35.347-28.656-64-64-64h-597.335z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["desktop"],"defaultCode":59720,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":992,"name":"desktop","prevSize":32,"id":80,"code":59720},"setIdx":0,"setId":6,"iconIdx":80},{"icon":{"paths":["M325.837 160c0-17.673-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.327-32.042 32v64c0 17.673 14.346 32 32.042 32h64.085c17.696 0 32.043-14.327 32.043-32v-64zM325.837 586.666c0-17.674-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.085c17.696 0 32.043-14.326 32.043-32v-64zM454.006 160c0-17.673 14.346-32 32.042-32h64.083c17.696 0 32.042 14.327 32.042 32v64c0 17.673-14.346 32-32.042 32h-64.083c-17.696 0-32.042-14.327-32.042-32v-64zM582.173 373.334c0-17.674-14.346-32-32.042-32h-64.083c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM454.006 586.666c0-17.674 14.346-32 32.042-32h64.083c17.696 0 32.042 14.326 32.042 32v64c0 17.674-14.346 32-32.042 32h-64.083c-17.696 0-32.042-14.326-32.042-32v-64zM582.173 800c0-17.674-14.346-32-32.042-32h-64.083c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM710.342 160c0-17.673 14.346-32 32.045-32h64.083c17.696 0 32.042 14.327 32.042 32v64c0 17.673-14.346 32-32.042 32h-64.083c-17.699 0-32.045-14.327-32.045-32v-64zM838.512 373.334c0-17.674-14.346-32-32.042-32h-64.083c-17.699 0-32.045 14.326-32.045 32v64c0 17.674 14.346 32 32.045 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM710.342 586.666c0-17.674 14.346-32 32.045-32h64.083c17.696 0 32.042 14.326 32.042 32v64c0 17.674-14.346 32-32.042 32h-64.083c-17.699 0-32.045-14.326-32.045-32v-64zM325.837 373.334c0-17.674-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.085c17.696 0 32.043-14.326 32.043-32v-64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["dialpad"],"defaultCode":59721,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":993,"name":"dialpad","prevSize":32,"id":81,"code":59721},"setIdx":0,"setId":6,"iconIdx":81},{"icon":{"paths":["M478.65 672c-17.674 0-32-14.326-32-32v-32h-32c-17.674 0-32-14.326-32-32s14.326-32 32-32h32v-58.88h-32c-17.674 0-32-14.326-32-32s14.326-32 32-32h32v-37.12c0-17.674 14.326-32 32-32 17.67 0 32 14.326 32 32v37.12h58.88v-37.12c0-17.674 14.326-32 32-32s32 14.326 32 32v37.12h37.12c17.67 0 32 14.326 32 32s-14.33 32-32 32h-37.12v58.88h37.12c17.67 0 32 14.326 32 32s-14.33 32-32 32h-37.12v32c0 17.674-14.326 32-32 32s-32-14.326-32-32v-32h-58.88v32c0 17.674-14.33 32-32 32zM510.65 544h58.88v-58.88h-58.88v58.88z","M158.648 672h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-192h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-160c0-35.346 28.654-64 64-64h608.001c35.344 0 64 28.654 64 64v640c0 35.347-28.656 64-64 64h-608.001c-35.346 0-64-28.653-64-64v-160zM830.65 192h-608.001v160h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v192h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v160h608.001v-640z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["directory"],"defaultCode":59648,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":994,"id":82,"name":"directory","prevSize":32,"code":59648},"setIdx":0,"setId":6,"iconIdx":82},{"icon":{"paths":["M833.35 128c10.285 0 20 2.425 28.611 6.735-11.834 4.684-22.922 11.812-32.493 21.383l-35.882 35.882h-568.236v160h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v192h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v88.237l-64 64v-152.237h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-192h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-160c0-35.346 28.654-64 64-64h607.999z","M361.117 896l64-64h408.234v-408.237l64-64v472.237c0 35.347-28.653 64-64 64h-472.234z","M604.23 352c8.166 0 15.616 3.056 21.267 8.090l-53.267 53.267v-29.357c0-17.674 14.33-32 32-32z","M513.35 421.12h51.117l-115.117 115.117v-51.117h-32c-17.67 0-32-14.326-32-32s14.33-32 32-32h32v-37.12c0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32v37.12z","M391.174 594.413l50.413-50.413h-24.237c-17.67 0-32 14.326-32 32 0 6.854 2.157 13.203 5.824 18.413z","M919.978 201.372c-12.496-12.497-32.755-12.497-45.254 0l-671.999 672c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l671.999-672c12.499-12.497 12.499-32.758 0-45.255z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["directory-disabled"],"defaultCode":59649,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":995,"id":83,"name":"directory-disabled","prevSize":32,"code":59649},"setIdx":0,"setId":6,"iconIdx":83},{"icon":{"paths":["M919.978 105.372c12.499 12.497 12.499 32.758 0 45.255l-89.373 89.372 89.373 89.373c12.499 12.496 12.499 32.758 0 45.254-12.496 12.496-32.755 12.496-45.254 0l-89.373-89.372-89.373 89.372c-12.496 12.496-32.755 12.496-45.254 0-12.496-12.496-12.496-32.758 0-45.254l89.373-89.373-89.373-89.372c-12.496-12.497-12.496-32.758 0-45.255 12.499-12.497 32.758-12.497 45.254 0l89.373 89.373 89.373-89.373c12.499-12.497 32.758-12.497 45.254 0z","M512.419 126.678c1.491 17.61-11.578 33.094-29.187 34.585-180.289 15.259-321.88 166.478-321.88 350.731 0 194.406 157.596 352 351.999 352 194.406 0 352-157.594 352-352 0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32 0 229.75-186.25 416-416 416s-415.999-186.25-415.999-416c0-217.79 167.341-396.462 380.482-414.503 17.61-1.491 33.094 11.577 34.586 29.187z","M119.219 432.47c0-17.674 14.327-32 32-32h329.037c17.67 0 32 14.326 32 32 0 17.67-14.33 32-32 32h-329.037c-17.673 0-32-14.33-32-32z","M119.233 640c0-17.674 14.327-32 32-32h724.255c17.674 0 32 14.326 32 32s-14.326 32-32 32h-724.255c-17.673 0-32-14.326-32-32z","M504.81 121.090c11.117 13.739 8.992 33.888-4.749 45.005-8.666 7.012-18.886 20.139-29.238 40.961-10.179 20.471-19.61 46.603-27.635 77.587-16.042 61.955-25.837 140.879-25.837 227.356 0 103.555 14.038 195.981 35.85 261.411 10.96 32.88 23.306 57.181 35.462 72.605 12.438 15.786 21.024 17.978 24.688 17.978 3.667 0 12.253-2.192 24.691-17.978 12.157-15.424 24.502-39.725 35.462-72.605 21.808-65.43 35.846-157.856 35.846-261.411 0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32 0 108.522-14.614 208.096-39.133 281.648-12.202 36.608-27.437 68.544-45.91 91.984-18.186 23.078-43.274 42.362-74.957 42.362-31.68 0-56.768-19.283-74.957-42.362-18.47-23.44-33.706-55.376-45.91-91.984-24.515-73.552-39.133-173.126-39.133-281.648 0-90.915 10.256-175.338 27.882-243.4 8.81-34.025 19.619-64.572 32.282-90.038 12.49-25.115 27.712-47.185 46.288-62.217 13.741-11.117 33.888-8.992 45.008 4.746z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["directory-error"],"defaultCode":59650,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":996,"id":84,"name":"directory-error","prevSize":32,"code":59650},"setIdx":0,"setId":6,"iconIdx":84},{"icon":{"paths":["M561.667 127.992c-121.696 0-200.973 50.509-248.813 115.801-46.216 63.073-61.638 137.752-61.933 188.616-8.705 98.746 28.601 172.896 89.422 223.469 59.686 49.626 140.202 75.258 217.85 83.738 77.75 8.486 161.715 1.197 227.856-12.547 33.066-6.87 62.774-15.581 85.642-25.331 11.366-4.848 22.029-10.368 30.797-16.669 7.875-5.661 18.541-14.976 23.242-28.835 7.286-21.475-3.133-38.784-11.965-48.102-8.41-8.877-19.427-15.405-28.24-20.016-9.306-4.867-19.379-9.206-27.533-12.707-8.973-3.856-14.858-6.4-18.56-8.432-4.845-2.662-8.842-5.088-12.026-7.203 20.256-47.142 31.549-77.043 37.696-99.19 7.293-26.272 7.315-41.725 7.315-58.909 0-21.523-9.603-88.542-52.81-151.108-44.701-64.73-124.074-122.573-257.939-122.573zM314.916 433.898c0-40.416 12.607-101.84 49.564-152.277 35.782-48.836 95.882-89.628 197.187-89.628 112.086 0 172.090 46.886 205.277 94.94 34.678 50.219 41.472 104.040 41.472 114.741v0.198c0 14.918 0 23.638-4.982 41.594-5.491 19.779-16.963 50.189-41.539 106.538-5.802 13.296-2.762 25.77 1.155 33.754 3.664 7.478 9.005 13.242 13.331 17.261 8.835 8.211 20.653 15.686 32.224 22.045 6.618 3.638 15.238 7.334 22.563 10.477l1.562 0.672c5.904 2.534 11.52 4.97 16.688 7.418-0.909 0.406-1.856 0.819-2.835 1.238-17.741 7.568-43.078 15.206-73.555 21.539-60.947 12.666-138.064 19.21-207.888 11.587-69.926-7.635-136.982-30.336-183.878-69.328-45.459-37.798-73.674-92.064-66.481-169.821l0.136-1.469v-1.478zM819.162 553.354l-0.074-0.086c0 0.003 0.010 0.013 0.029 0.035 0.010 0.013 0.026 0.029 0.045 0.051z","M178.552 502.474c7.496-11.258 16.26-22.259 26.436-32.592 0.876 31.747 6.169 61.226 15.216 88.358-15.094 30.877-18.374 59.315-18.374 65.357v0.186c0 11.382 0 17.536 3.524 30.701 3.993 14.918 12.441 38.211 30.867 82.022 5.256 12.496 2.48 24.099-0.985 31.43-3.249 6.874-7.925 12.058-11.512 15.514-7.319 7.053-16.852 13.254-25.75 18.326-5.008 2.854-11.333 5.706-16.546 8.029 11.182 3.939 24.98 7.814 40.802 11.226 44.977 9.693 101.833 14.669 153.062 8.87 51.28-5.808 99.776-23.014 133.35-51.965l0.608-0.528c14.794 2.784 29.53 4.938 44.051 6.525 10.886 1.187 21.862 2.086 32.877 2.72-10.122 14.797-22.163 28.045-35.741 39.754-46.362 39.974-108.547 60.362-167.946 67.088-59.45 6.73-123.405 0.947-173.744-9.901-25.17-5.424-48.056-12.352-65.901-20.243-8.86-3.92-17.458-8.502-24.686-13.891-6.431-4.794-15.831-13.171-20.001-25.92-6.422-19.632 2.792-35.443 10.458-43.834 7.193-7.872 16.405-13.462 23.248-17.174 7.309-3.965 15.158-7.466 21.235-10.173 6.907-3.078 10.854-4.858 13.183-6.186 1.349-0.768 2.591-1.501 3.727-2.195-13.937-33.885-21.976-56.118-26.48-72.947-5.68-21.222-5.7-33.875-5.7-47.434 0-17.712 7.436-71.139 40.721-121.123zM155.337 797.248c-0.012 0 0.084 0.102 0.317 0.301-0.19-0.202-0.306-0.301-0.317-0.301zM179.587 737.085c-0.004 0-0.052 0.051-0.137 0.15l0.112-0.118c0.019-0.022 0.027-0.032 0.025-0.032z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["discussions"],"defaultCode":59722,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":997,"name":"discussions","prevSize":32,"id":85,"code":59722},"setIdx":0,"setId":6,"iconIdx":85},{"icon":{"paths":["M160 256c0-17.673 14.327-32 32-32h640c17.674 0 32 14.327 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.327-32-32zM160 421.162c0-17.674 14.327-32 32-32h640c17.674 0 32 14.326 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.326-32-32zM160 602.838c0-17.674 14.327-32 32-32h640c17.674 0 32 14.326 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.326-32-32zM160 768c0-17.674 14.327-32 32-32h344.614c17.674 0 32 14.326 32 32s-14.326 32-32 32h-344.614c-17.673 0-32-14.326-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["document"],"defaultCode":59723,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":998,"name":"document","prevSize":32,"id":86,"code":59723},"setIdx":0,"setId":6,"iconIdx":86},{"icon":{"paths":["M128.169 352c0-17.674 14.346-32 32.042-32h704.928c17.696 0 32.045 14.326 32.045 32s-14.349 32-32.045 32h-704.928c-17.696 0-32.042-14.326-32.042-32zM213.615 522.669c0-17.674 14.346-32 32.042-32h534.036c17.699 0 32.045 14.326 32.045 32s-14.346 32-32.045 32h-534.036c-17.697 0-32.042-14.326-32.042-32zM331.104 661.331c-17.698 0-32.043 14.326-32.043 32s14.346 32 32.043 32h363.146c17.696 0 32.042-14.326 32.042-32s-14.346-32-32.042-32h-363.146z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["donner"],"defaultCode":59724,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":999,"name":"donner","prevSize":32,"id":87,"code":59724},"setIdx":0,"setId":6,"iconIdx":87},{"icon":{"paths":["M273.128 356.678c-6.62 27.766-2.384 63.757 25.498 105.581l21.374 32.061v17.69h-48c-44.011 0-70.483 14.874-86.278 33.619-16.496 19.578-24.573 47.264-23.734 77.491 0.841 30.262 10.601 59.968 25.818 81.312 15.127 21.216 33.404 31.578 52.195 31.578h79.999v64h-80c-45.209 0-80.932-25.642-104.306-58.426-23.283-32.656-36.522-74.95-37.682-116.688-1.16-41.773 9.763-86.083 38.766-120.506 20.726-24.598 49.155-42.32 84.825-50.784-16.1-39.011-19.009-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.4-22.798 85.677-32.139 131.303-21.965 35.584 7.935 68.909 27.48 95.251 59.554 53.75-35.147 127.584-30.892 182.483-2.495 34.438 17.812 64.794 46.382 81.437 85.010 12.294 28.531 16.438 61.011 10.608 96.205 46.112 6.682 81.507 25.155 105.613 53.456 30.349 35.626 38.106 81.35 33.446 123.283-4.659 41.917-21.946 83.485-46.544 115.114-24.061 30.934-59.354 57.354-101.261 57.354h-80v-64h80c14.093 0 32.8-9.581 50.742-32.646 17.398-22.371 30.112-52.806 33.453-82.89 3.341-30.067-2.902-56.339-18.554-74.714-15.222-17.869-44.035-33.75-97.642-33.75h-45.686l15.613-42.938c13.546-37.251 11.091-66.742 1.437-89.149-9.856-22.87-28.502-41.302-52.064-53.488-49.587-25.649-107.475-18.625-134.717 14.064l-30.134 36.16-22.541-41.325c-19.757-36.219-47.232-54.175-74.87-60.339-28.378-6.327-59.098-0.669-84.701 14.53-25.512 15.148-44.461 38.855-51.208 67.152zM630.979 787.222c12.298-12.691 11.981-32.95-0.707-45.251-12.691-12.298-32.95-11.981-45.251 0.707l-41.021 42.326v-273.005c0-17.674-14.326-32-32-32s-32 14.326-32 32v273.005l-41.021-42.326c-12.301-12.688-32.56-13.005-45.251-0.707-12.688 12.301-13.005 32.56-0.707 45.251l96 99.050c6.029 6.218 14.32 9.728 22.979 9.728s16.95-3.51 22.979-9.728l96-99.050z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["download"],"defaultCode":59725,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1000,"name":"download","prevSize":32,"id":88,"code":59725},"setIdx":0,"setId":6,"iconIdx":88},{"icon":{"paths":["M795.648 132.004c-25.027-25.027-65.603-25.027-90.63-0l-530.467 530.469c-9.577 9.574-15.873 21.939-17.985 35.318l-19.611 124.186c-1.386 8.771-0.942 17.299 1.006 25.261 7.597 31.037 38.083 53.44 72.291 48.038l124.184-19.613c13.379-2.112 25.744-8.41 35.322-17.984l530.467-530.47c12.512-12.513 18.768-28.914 18.768-45.316 0-10.379-2.506-20.757-7.517-30.15-2.906-5.451-6.656-10.57-11.251-15.164l-104.576-104.575zM630.675 296.979l119.658-119.658 104.576 104.574-119.658 119.657-104.576-104.573zM200.255 831.974l19.611-124.186 365.494-365.494 104.576 104.573-365.494 365.494-124.187 19.613z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["edit"],"defaultCode":59726,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1001,"name":"edit","prevSize":32,"id":89,"code":59726},"setIdx":0,"setId":6,"iconIdx":89},{"icon":{"paths":["M330.074 644.886c-21.572-19.619-6.010-52.886 23.152-52.886 8.963 0 17.526 3.53 24.272 9.437 21.603 18.918 42.64 31.958 62.701 40.509 36.563 15.59 71.805 17.107 104.794 9.939 37.632-8.176 72.659-27.808 102.109-51.341 6.726-5.376 14.995-8.544 23.606-8.544 30.218 0 45.616 34.256 22.397 53.594-36.912 30.742-82.79 57.59-134.522 68.832-44.794 9.734-93.67 7.632-143.485-13.606-28.79-12.275-57.232-30.653-85.024-55.933z","M400.17 480c35.344 0 64-28.653 64-64s-28.656-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64z","M624.17 480c35.344 0 64-28.653 64-64s-28.656-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64z","M928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["emoji"],"defaultCode":59729,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1002,"name":"emoji","prevSize":32,"id":90,"code":59729},"setIdx":0,"setId":6,"iconIdx":90},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM400.166 480c-35.347 0-64-28.653-64-64s28.653-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64zM688.166 416c0-35.347-28.653-64-64-64s-64 28.653-64 64c0 35.347 28.653 64 64 64s64-28.653 64-64zM353.226 720c8.963 0 17.526-3.53 24.272-9.437 21.603-18.918 42.64-31.958 62.701-40.509 36.563-15.59 71.805-17.107 104.794-9.939 37.632 8.176 72.659 27.808 102.109 51.341 6.726 5.376 14.995 8.544 23.606 8.544 30.218 0 45.616-34.256 22.397-53.594-36.912-30.742-82.79-57.59-134.522-68.832-44.794-9.734-93.67-7.632-143.485 13.606-28.79 12.275-57.232 30.653-85.024 55.933-21.572 19.619-6.010 52.886 23.152 52.886z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["emoji-bad-mood"],"defaultCode":59727,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1003,"name":"emoji-bad-mood","prevSize":32,"id":91,"code":59727},"setIdx":0,"setId":6,"iconIdx":91},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM400.166 480c-35.347 0-64-28.653-64-64s28.653-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64zM688.166 416c0-35.347-28.653-64-64-64s-64 28.653-64 64c0 35.347 28.653 64 64 64s64-28.653 64-64zM384 640h256c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32s14.326-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["emoji-neutral-mood"],"defaultCode":59728,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1004,"name":"emoji-neutral-mood","prevSize":32,"id":92,"code":59728},"setIdx":0,"setId":6,"iconIdx":92},{"icon":{"paths":["M655.744 512c88.365 0 160-71.635 160-160s-71.635-160-160-160c-88.368 0-160 71.635-160 160 0 26.934 6.653 52.314 18.41 74.582l-11.914 11.914 0.128 0.131-299.135 299.136c-3.533 9.926-6.41 20.976-7.738 31.606-1.652 13.219-0.563 22.966 1.874 28.938 1.768 4.333 4.22 7.232 10.772 9.014 8.316 2.262 24.518 2.794 52.822-5.501 8.524-3.808 27.721-16.285 45.132-35.382 18.18-19.939 29.648-41.856 29.648-62.438 0-15.642 11.309-28.992 26.736-31.565l91.75-15.293c3.766-2.656 18.768-15.693 10.134-58.867-2.099-10.49 1.184-21.338 8.749-28.902l88.198-88.195c26.467 19.379 59.114 30.822 94.432 30.822zM439.571 410.915c-5.104-18.771-7.827-38.525-7.827-58.915 0-123.712 100.288-224 224-224 123.709 0 224 100.288 224 224s-100.291 224-224 224c-29.29 0-57.264-5.619-82.906-15.843l-43.008 43.008c7.158 65.494-23.99 104.534-55.968 115.194l-2.384 0.794-74.854 12.477c-7.085 31.405-25.174 58.122-43.235 77.933-23.123 25.357-50.958 44.627-69.762 52.15l-1.324 0.528-1.365 0.41c-34.714 10.416-64.73 13.19-89.594 6.429-26.782-7.286-44.33-24.784-53.228-46.586-8.23-20.163-8.473-42.282-6.126-61.062 2.402-19.216 7.899-37.958 14.042-53.315 1.61-4.022 4.020-7.677 7.084-10.742l286.456-286.458zM623.744 336c0 26.509 21.488 48 48 48 26.509 0 48-21.491 48-48s-21.491-48-48-48c-26.512 0-48 21.49-48 48z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["encrypted"],"defaultCode":59730,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1005,"name":"encrypted","prevSize":32,"id":93,"code":59730},"setIdx":0,"setId":6,"iconIdx":93},{"icon":{"paths":["M536.89 64c233.677 0 423.11 189.433 423.11 423.11h-423.11v-423.11z","M64 536.89c0-233.678 189.433-423.112 423.11-423.112v423.112h423.11c0 233.677-189.43 423.11-423.11 423.11-233.677 0-423.11-189.434-423.11-423.11z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["engagement-dashboard"],"defaultCode":59731,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1006,"name":"engagement-dashboard","prevSize":32,"id":94,"code":59731},"setIdx":0,"setId":6,"iconIdx":94},{"icon":{"paths":["M416 586.445v177.232l75.514-62.928c11.869-9.888 29.104-9.888 40.973 0l75.514 62.928v-177.232c-29.098 13.821-61.645 21.555-96 21.555s-66.902-7.734-96-21.555zM352 540.768v291.232c0 12.416 7.184 23.712 18.426 28.979 11.245 5.267 24.522 3.552 34.061-4.397l107.514-89.594 107.514 89.594c9.539 7.949 22.816 9.664 34.061 4.397 11.242-5.267 18.426-16.563 18.426-28.979v-291.232c39.59-40.403 64-95.734 64-156.768 0-123.712-100.288-224.001-224-224.001s-224 100.288-224 224.001c0 61.034 24.41 116.365 64 156.768zM416 512.013l-0.016-0.013c-38.854-29.19-63.984-75.661-63.984-128 0-88.366 71.635-160.001 160-160.001s160 71.635 160 160.001c0 52.339-25.13 98.81-63.984 128l-0.016 0.013c-26.742 20.083-59.981 31.987-96 31.987s-69.258-11.904-96-31.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["enterprise-feature"],"defaultCode":59732,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1007,"name":"enterprise-feature","prevSize":32,"id":95,"code":59732},"setIdx":0,"setId":6,"iconIdx":95},{"icon":{"paths":["M500.64 128c213.35 0 386.336 172.985 386.336 386.336 0 192.87-141.254 352.707-325.974 381.664v-269.958h90.022l17.114-111.706h-107.136v-72.47c0-11.462 2.102-22.822 7.274-32.544 2.474-4.656 5.651-8.934 9.635-12.666 9.866-9.245 24.688-15.152 46.058-15.152h48.733v-95.080c0 0-44.224-7.552-86.493-7.552-84.698 0-141.258 49.313-145.651 138.907-0.182 3.738-0.275 7.546-0.275 11.424v85.133h-98.122v111.706h98.122v269.958c-184.721-29.011-325.978-188.848-325.978-381.664 0-213.351 172.985-386.336 386.336-386.336z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["facebook-monochromatic"],"defaultCode":59733,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1008,"name":"facebook-monochromatic","prevSize":32,"id":96,"code":59733},"setIdx":0,"setId":6,"iconIdx":96},{"icon":{"paths":["M865.139 512c0 33.28-4.624 65.485-13.267 96h-183.274c2.803-30.816 4.288-62.957 4.288-96 0-16.234-0.358-32.25-1.056-48h190.061c2.141 15.696 3.248 31.718 3.248 48zM607.68 464c0.739 15.67 1.123 31.686 1.123 48 0 33.398-1.61 65.555-4.57 96h-183.117c-2.963-30.445-4.57-62.602-4.57-96 0-16.314 0.384-32.33 1.123-48h190.010zM667.014 400c-10.016-93.226-32.221-173.252-61.875-227.763 113.702 30.788 204.579 116.981 241.782 227.763h-179.907zM420.211 172.237c-29.654 54.51-51.862 134.537-61.875 227.763h-179.91c37.204-110.782 128.083-196.975 241.785-227.763zM422.816 400c7.171-62.314 20.064-116.804 36.384-159.18 12.842-33.339 26.56-55.927 38.528-69.070 8.406-9.235 13.446-11.291 14.947-11.698 1.501 0.407 6.541 2.463 14.947 11.698 11.968 13.143 25.686 35.731 38.525 69.070 16.32 42.377 29.216 96.867 36.387 159.18h-179.718zM353.52 464c-0.698 15.75-1.056 31.766-1.056 48 0 33.043 1.482 65.184 4.288 96h-183.275c-8.643-30.515-13.268-62.72-13.268-96 0-16.282 1.107-32.304 3.249-48h190.061zM364.742 672c11.667 72.646 31.040 134.861 55.466 179.763-96.678-26.179-176.854-92.413-221.565-179.763h166.1zM513.152 928c229.834-0.259 416.070-186.41 416.070-416 0-229.75-186.493-416-416.547-416s-416.55 186.25-416.55 416c0 229.59 186.237 415.741 416.070 416 0.16 0 0.32 0 0.48 0s0.32 0 0.477 0zM605.142 851.763c24.426-44.902 43.798-107.117 55.466-179.763h166.099c-44.71 87.35-124.89 153.584-221.565 179.763zM595.638 672c-7.379 42.458-17.514 80.083-29.491 111.184-12.838 33.338-26.557 55.926-38.525 69.069-8.406 9.235-13.446 11.29-14.947 11.699-1.501-0.41-6.541-2.464-14.947-11.699-11.968-13.142-25.686-35.731-38.528-69.069-11.978-31.101-22.109-68.726-29.488-111.184h165.926z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["federation"],"defaultCode":59652,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1009,"id":97,"name":"federation","prevSize":32,"code":59652},"setIdx":0,"setId":6,"iconIdx":97},{"icon":{"paths":["M542.65 96c80.093 0 154.902 22.636 218.374 61.859l-46.746 46.746c-24.739-13.843-51.322-24.785-79.286-32.368 12.166 22.395 23.078 49.095 32.406 79.249l-52 51.999c-5.654-22.994-12.17-44.005-19.347-62.666-12.822-33.339-26.522-55.927-38.474-69.070-8.397-9.235-13.43-11.291-14.928-11.698-1.498 0.407-6.531 2.463-14.928 11.698-11.952 13.143-25.654 35.731-38.477 69.070-16.298 42.377-29.174 96.867-36.336 159.18h65.974l-64 64h-7.114c-0.118 2.47-0.224 4.95-0.323 7.437l-64.538 64.538c-0.173-7.933-0.259-15.926-0.259-23.974 0-16.234 0.358-32.25 1.053-48h-189.809c-2.14 15.696-3.245 31.718-3.245 48 0 33.28 4.619 65.485 13.251 96h106.984l-64 64h-17.852c2.004 3.92 4.078 7.798 6.223 11.629l-46.746 46.749c-39.223-63.475-61.859-138.282-61.859-218.378 0-229.75 186.25-416 416.001-416zM896.79 293.623l-46.746 46.748c10.56 18.87 19.43 38.816 26.413 59.629h-86.045l-64 64h164.992c2.138 15.696 3.245 31.718 3.245 48 0 33.28-4.621 65.485-13.251 96h-183.030c2.8-30.816 4.282-62.957 4.282-96 0-8.045-0.090-16.042-0.262-23.974l-64.534 64.534c-0.752 19.008-2.026 37.523-3.766 55.44h-51.674l-64 64h107.088c-7.37 42.458-17.488 80.083-29.45 111.184-12.822 33.338-26.522 55.926-38.474 69.069-8.397 9.235-13.43 11.29-14.928 11.699-1.498-0.41-6.531-2.464-14.928-11.699-11.952-13.142-25.654-35.731-38.477-69.069-7.178-18.662-13.69-39.677-19.344-62.669l-52 51.997c9.325 30.154 20.237 56.854 32.403 79.251-27.965-7.584-54.547-18.525-79.286-32.368l-46.746 46.746c63.347 39.146 137.984 61.77 217.901 61.859h0.954c229.53-0.259 415.523-186.41 415.523-416 0-80.096-22.637-154.902-61.859-218.377zM450.307 172.237c-113.552 30.788-204.312 116.98-241.467 227.763h179.675c10-93.226 32.176-173.252 61.792-227.763zM634.995 851.763c24.394-44.902 43.741-107.117 55.392-179.763h165.878c-44.653 87.35-124.723 153.584-221.27 179.763zM856.022 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672.001 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672.001-672z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["federation-disabled"],"defaultCode":59651,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1010,"id":98,"name":"federation-disabled","prevSize":32,"code":59651},"setIdx":0,"setId":6,"iconIdx":98},{"icon":{"paths":["M373.334 448c0-17.674 14.326-32 32-32h213.331c17.674 0 32 14.326 32 32s-14.326 32-32 32h-213.331c-17.674 0-32-14.326-32-32z","M405.334 544c-17.674 0-32 14.326-32 32s14.326 32 32 32h213.331c17.674 0 32-14.326 32-32s-14.326-32-32-32h-213.331z","M256 128c-17.673 0-32 14.327-32 32v704c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-501.744c0-6.672-2.083-13.174-5.962-18.602l-144.467-202.254c-6.006-8.409-15.706-13.4-26.038-13.4h-367.533zM736 372.509v459.491h-448v-640h319.066l128.934 180.509z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["file-document"],"defaultCode":59734,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1011,"name":"file-document","prevSize":32,"id":99,"code":59734},"setIdx":0,"setId":6,"iconIdx":99},{"icon":{"paths":["M128 192c-17.673 0-32 14.327-32 32v576.019c0 17.674 14.327 32 32 32h768c17.674 0 32-14.326 32-32v-576.019c0-17.673-14.326-32-32-32h-768zM160 378.301v-122.301h149.333v122.301h-149.333zM160 442.301h149.333v141.722h-149.333v-141.722zM160 648.022h149.333v119.997h-149.333v-119.997zM373.334 768.019v-119.997h490.666v119.997h-490.666zM864 584.022h-490.666v-141.722h490.666v141.722zM864 378.301h-490.666v-122.301h490.666v122.301z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["file-sheet"],"defaultCode":59735,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1012,"name":"file-sheet","prevSize":32,"id":100,"code":59735},"setIdx":0,"setId":6,"iconIdx":100},{"icon":{"paths":["M206.667 293.692c-30.421-42.402-0.116-101.442 52.070-101.442h518.572c51.174 0 81.706 57.026 53.334 99.615l-180.678 271.207v220.762c0 46.352-47.693 77.373-90.067 58.582l-121.424-53.85c-23.168-10.275-38.102-33.238-38.102-58.582v-166.304l-193.704-269.988zM777.309 256.334h-518.572l193.705 269.989c7.811 10.89 12.013 23.955 12.013 37.357v166.304l121.424 53.85v-220.762c0-12.646 3.741-25.008 10.752-35.533l180.678-271.205z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["filter"],"defaultCode":59736,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1013,"name":"filter","prevSize":32,"id":101,"code":59736},"setIdx":0,"setId":6,"iconIdx":101},{"icon":{"paths":["M623.091 896c-2.806 0-5.296-0.624-7.168-0.938-62-16.858-102.816-39.648-145.811-80.858-55.149-54.010-85.37-125.814-85.37-202.301 0-65.875 56.704-119.571 126.496-119.571s126.496 53.696 126.496 119.571c0 34.963 31.469 63.373 69.792 63.373s69.789-28.41 69.789-63.373c0-135.808-119.642-246.637-266.701-246.637-104.998 0-200.338 57.133-243.334 145.795-14.332 29.347-21.498 63.066-21.498 100.842 0 28.72 2.492 73.363 24.925 131.744 2.804 7.181 2.492 14.675-0.623 21.856-3.116 6.867-9.035 11.862-16.201 14.358-2.804 1.251-6.231 1.562-9.659 1.562-11.84 0-22.433-7.181-26.484-18.106-19.005-50.266-28.353-99.904-28.353-151.728 0-46.205 9.036-88.352 26.795-125.504 52.343-108.019 167.936-177.638 294.432-177.638 178.528 0 323.718 135.804 323.718 302.828 0 65.875-56.704 119.571-126.806 119.571s-126.81-53.696-126.81-119.571c0-34.963-31.469-63.373-69.792-63.373-38.634 0-69.789 28.41-69.789 63.373 0 61.504 24.301 119.261 68.544 162.342 35.206 34.029 68.858 53.072 120.576 67.123 7.168 1.872 13.398 6.557 17.136 13.11 3.741 6.557 4.675 14.362 2.806 21.229-2.806 11.866-14.022 20.918-27.107 20.918zM426.803 888.195c-7.789 0-15.267-3.123-20.253-8.742-33.338-32.781-51.718-54.010-77.891-100.525-26.795-47.142-41.127-105.21-41.127-167.338 0-116.448 100.948-211.357 224.951-211.357s224.954 94.909 224.954 211.357c0 15.61-12.464 28.096-28.352 28.096-15.891 0-28.666-12.173-28.666-28.096 0-85.542-75.398-155.162-168.246-155.162s-168.246 69.619-168.246 155.162c0 52.448 11.84 100.528 34.272 139.552 23.366 41.52 38.947 59.005 68.858 88.662 10.902 11.238 10.902 28.723 0 39.648-5.92 5.933-13.088 8.742-20.253 8.742zM699.738 818.886c-47.36 0-88.797-11.862-123.382-34.963-59.197-39.651-94.717-103.962-94.717-172.333 0-15.61 12.464-28.099 28.352-28.099 15.891 0 28.355 12.49 28.355 28.099 0 49.638 26.17 96.781 69.789 125.501 25.238 16.861 55.149 24.976 91.603 24.976 7.789 0 22.432-0.934 38.010-3.744 1.558-0.314 3.427-0.314 4.986-0.314 13.709 0 25.238 9.99 27.728 23.414 1.248 7.181-0.31 14.672-4.362 20.605-4.362 6.243-10.902 10.614-18.694 11.862-23.366 4.685-43.93 4.995-47.667 4.995zM188.765 435.824c-5.608 0-11.217-1.562-16.202-4.995-6.543-4.058-10.593-10.614-12.151-18.106-1.246-7.494 0.311-14.986 4.985-21.232 38.635-53.696 87.862-95.843 146.125-125.501 60.132-30.595 129.613-46.829 200.961-46.829 71.037 0 140.205 15.922 200.029 46.205 58.573 29.659 107.802 71.492 146.125 124.567 4.362 5.93 6.23 13.424 4.986 20.915-1.248 7.494-5.61 14.048-11.84 18.419-4.986 3.437-10.595 4.995-16.515 4.995-9.034 0-17.757-4.371-23.056-11.862-33.338-45.891-75.709-82.109-125.562-107.083-52.342-26.224-112.787-40.273-174.477-40.273-62.314 0-122.758 14.049-175.101 40.585-49.852 25.913-92.537 62.128-126.186 108.643-3.739 6.87-12.463 11.552-22.121 11.552zM733.696 239.141c-4.672 0-9.347-1.249-13.395-3.434-71.35-35.902-133.354-51.512-207.504-51.512-74.467 0-144.256 17.483-207.817 51.824-4.050 2.185-8.724 3.122-13.397 3.122-10.282 0-19.629-5.62-24.925-14.361-3.739-6.556-4.673-14.361-2.492-21.541s7.166-13.424 13.709-16.859c72.594-38.712 151.733-58.38 234.924-58.38 82.563 0 154.848 17.795 233.987 58.068 6.854 3.434 11.84 9.366 14.33 16.859 2.182 7.18 1.248 14.673-2.179 21.229-4.986 9.054-14.643 14.985-25.238 14.985z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["fingerprint"],"defaultCode":59737,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1014,"name":"fingerprint","prevSize":32,"id":102,"code":59737},"setIdx":0,"setId":6,"iconIdx":102},{"icon":{"paths":["M266.667 170.664c0-17.673 14.327-32 32-32h500.623c12.122 0 23.2 6.848 28.621 17.689s4.253 23.814-3.021 33.511l-122.134 162.843 122.134 162.845c7.274 9.696 8.442 22.672 3.021 33.51-5.421 10.842-16.499 17.69-28.621 17.69h-468.624v286.579c0 17.674-14.325 32-31.999 32s-32-14.326-32-32v-682.667zM330.666 502.752h404.624l-98.134-130.845c-8.531-11.376-8.531-27.021 0-38.4l98.134-130.843h-404.624v300.088z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["flag"],"defaultCode":59738,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1015,"name":"flag","prevSize":32,"id":103,"code":59738},"setIdx":0,"setId":6,"iconIdx":103},{"icon":{"paths":["M140.020 213.336c0-17.673 14.327-32 32-32h234.057c7.181 0 14.157 2.416 19.798 6.86l88.813 69.94h339.997c17.674 0 32 14.327 32 32v520.533c0 17.674-14.326 32-32 32h-682.665c-17.673 0-32-14.326-32-32v-597.333zM204.020 245.336v533.333h618.665v-456.534h-319.085c-7.181 0-14.154-2.415-19.798-6.858l-88.813-69.94h-190.969z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["folder"],"defaultCode":59739,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1016,"name":"folder","prevSize":32,"id":104,"code":59739},"setIdx":0,"setId":6,"iconIdx":104},{"icon":{"paths":["M370.704 544c0-17.674-14.326-32-32-32s-31.999 14.326-31.999 32v32h-32c-17.673 0-32 14.326-32 32s14.327 32 32 32h32v32c0 17.674 14.325 32 31.999 32s32-14.326 32-32v-32h32c17.674 0 32-14.326 32-32s-14.326-32-32-32h-32v-32z","M746.704 624c30.928 0 56-25.072 56-56s-25.072-56-56-56c-30.928 0-56 25.072-56 56s25.072 56 56 56z","M674.704 664c0 30.928-25.072 56-56 56s-56-25.072-56-56c0-30.928 25.072-56 56-56s56 25.072 56 56z","M706.704 128c0-17.673-14.326-32-32-32s-32 14.327-32 32v96h-128c-17.674 0-32 14.327-32 32v96h-191.999c-106.038 0-192 85.962-192 192v128c0 106.038 85.961 192 192 192h447.999c106.038 0 192-85.962 192-192v-128c0-106.038-85.962-192-192-192h-192v-64h128c17.674 0 32-14.327 32-32v-128zM866.704 544v128c0 70.691-57.306 128-128 128h-447.999c-70.692 0-128-57.309-128-128v-128c0-70.691 57.308-128 128-128h447.999c70.694 0 128 57.309 128 128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["game"],"defaultCode":59753,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1017,"name":"game","prevSize":32,"id":105,"code":59753},"setIdx":0,"setId":6,"iconIdx":105},{"icon":{"paths":["M494.31 170.648l23.037 24.005 23.629-24.005 74.669 0.041v75.854h74.669v75.856h74.666v26.518h0.003v504.419h-522.678v-682.689h252.006zM540.976 246.503h-224.004v530.979h373.341v-379.229h-149.338v-151.75z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["giphy-monochromatic"],"defaultCode":59754,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1018,"name":"giphy-monochromatic","prevSize":32,"id":106,"code":59754},"setIdx":0,"setId":6,"iconIdx":106},{"icon":{"paths":["M862.454 324.045c-35.2-60.31-82.944-108.057-143.248-143.253-60.314-35.198-126.16-52.792-197.581-52.792-71.414 0-137.28 17.6-197.581 52.792-60.31 35.194-108.053 82.943-143.253 143.253-35.194 60.307-52.792 126.166-52.792 197.571 0 85.77 25.024 162.899 75.086 231.405 50.056 68.509 114.721 115.917 193.989 142.224 9.229 1.712 16.058 0.509 20.499-3.584 4.442-4.096 6.662-9.226 6.662-15.37 0-1.024-0.090-10.246-0.259-27.674-0.176-17.43-0.259-32.637-0.259-45.61l-11.789 2.038c-7.517 1.379-16.998 1.962-28.445 1.795-11.443-0.16-23.322-1.357-35.619-3.587-12.304-2.211-23.747-7.334-34.342-15.366-10.588-8.029-18.104-18.538-22.547-31.514l-5.125-11.795c-3.416-7.853-8.795-16.573-16.142-26.134-7.348-9.571-14.778-16.058-22.294-19.475l-3.588-2.57c-2.391-1.706-4.61-3.766-6.662-6.154-2.050-2.39-3.585-4.781-4.61-7.174-1.027-2.397-0.176-4.365 2.562-5.907 2.738-1.539 7.685-2.288 14.864-2.288l10.247 1.53c6.834 1.37 15.287 5.462 25.371 12.298 10.078 6.835 18.363 15.715 24.856 26.646 7.863 14.013 17.335 24.688 28.445 32.038 11.101 7.347 22.294 11.014 33.568 11.014s21.011-0.854 29.216-2.557c8.192-1.709 15.882-4.275 23.062-7.69 3.075-22.902 11.446-40.499 25.11-52.797-19.475-2.045-36.982-5.13-52.534-9.226-15.542-4.106-31.603-10.765-48.173-20-16.579-9.222-30.331-20.672-41.262-34.333-10.932-13.67-19.905-31.613-26.904-53.818-7.003-22.214-10.505-47.837-10.505-76.88 0-41.35 13.5-76.541 40.493-105.584-12.645-31.088-11.451-65.939 3.585-104.55 9.908-3.079 24.606-0.768 44.078 6.916 19.478 7.689 33.738 14.275 42.797 19.736 9.059 5.46 16.317 10.087 21.786 13.837 31.782-8.88 64.582-13.322 98.406-13.322s66.63 4.442 98.416 13.322l19.475-12.295c13.318-8.204 29.046-15.722 47.142-22.556 18.112-6.83 31.958-8.712 41.53-5.633 15.37 38.612 16.739 73.46 4.093 104.548 26.992 29.046 40.496 64.243 40.496 105.587 0 29.043-3.514 54.746-10.506 77.13-7.002 22.387-16.051 40.314-27.152 53.818-11.114 13.501-24.957 24.864-41.526 34.083-16.573 9.226-32.637 15.888-48.179 19.99-15.552 4.102-33.059 7.187-52.534 9.238 17.763 15.37 26.646 39.632 26.646 72.774v108.134c0 6.141 2.134 11.27 6.41 15.37 4.272 4.090 11.018 5.296 20.243 3.581 79.28-26.304 143.946-73.712 194-142.224 50.048-68.502 75.082-145.632 75.082-231.405-0.019-71.395-17.626-137.248-52.803-197.555z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["github-monochromatic"],"defaultCode":59655,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1019,"name":"github-monochromatic","prevSize":32,"id":107,"code":59655},"setIdx":0,"setId":6,"iconIdx":107},{"icon":{"paths":["M133.618 423.61h215.092l-92.537-284.607c-4.74-14.67-25.504-14.67-30.244 0l-92.311 284.607zM86.899 567.171l46.72-143.546h737.133l46.72 143.546c4.288 13.088-0.451 27.533-11.51 35.434l-403.776 293.408-403.776-293.408c-11.060-7.901-15.799-22.346-11.511-35.434zM655.661 423.61h215.091l-92.31-284.607c-4.739-14.67-25.504-14.67-30.243 0l-92.538 284.607z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["gitlab-monochromatic"],"defaultCode":59656,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1020,"name":"gitlab-monochromatic","prevSize":32,"id":108,"code":59656},"setIdx":0,"setId":6,"iconIdx":108},{"icon":{"paths":["M226.9 260.289c6.691-2.875 13.811-4.319 20.961-4.288 17.673 0.077 32.062-14.187 32.14-31.86s-14.187-32.062-31.86-32.14c-15.989-0.070-31.8 3.167-46.506 9.485-14.702 6.317-27.969 15.571-39.071 27.156-11.1 11.582-19.822 25.269-25.729 40.238-5.898 14.946-8.889 30.916-8.834 47.005l-0.001 15.941 0.001-11.899v255.848c-0 0.074-0.001 0.15-0.001 0.224v89.6c0 43.642 16.497 85.792 46.318 117.104 29.872 31.366 70.73 49.296 113.682 49.296 42.954 0 83.811-17.93 113.683-49.296 29.821-31.312 46.317-73.462 46.317-117.104v-57.6h128v57.6c0 43.642 16.496 85.792 46.317 117.104 29.872 31.366 70.73 49.296 113.683 49.296s83.811-17.93 113.683-49.296c29.821-31.312 46.317-73.462 46.317-117.104v-89.6c0-0.077 0-0.15 0-0.227v-259.883c0.054-16.090-2.938-32.062-8.835-47.010-5.907-14.969-14.627-28.656-25.728-40.238-11.104-11.585-24.368-20.839-39.072-27.156-14.704-6.318-30.515-9.555-46.506-9.485-17.674 0.077-31.936 14.467-31.859 32.14s14.467 31.937 32.141 31.86c7.149-0.031 14.269 1.413 20.96 4.288 6.694 2.876 12.867 7.147 18.128 12.636 5.264 5.492 9.501 12.090 12.403 19.448 2.906 7.36 4.4 15.292 4.368 23.326v228.302h-639.999l0-228.173-0-0.128c-0.032-8.034 1.462-15.965 4.366-23.326 2.904-7.358 7.141-13.957 12.404-19.448 5.26-5.489 11.434-9.759 18.129-12.636zM269.255 608l104.214 104.214c6.826-14.237 10.531-30.173 10.531-46.614v-57.6h-114.745zM717.254 608l104.214 104.214c6.826-14.237 10.531-30.173 10.531-46.614v-57.6h-114.746zM896 315.89v0zM128.001 319.928l0-3.973-0-0.069v4.043zM328.954 758.208l-136.954-136.954v44.346c0 27.648 10.475 53.869 28.663 72.966 18.137 19.043 42.394 29.434 67.337 29.434 14.208 0 28.194-3.37 40.954-9.792zM640 665.6v-44.346l136.954 136.954c-12.758 6.422-26.746 9.792-40.954 9.792-24.944 0-49.2-10.39-67.338-29.434-18.189-19.098-28.662-45.318-28.662-72.966z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["glasses"],"defaultCode":59812,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1021,"id":109,"name":"glasses","prevSize":32,"code":59812},"setIdx":0,"setId":6,"iconIdx":109},{"icon":{"paths":["M634.803 170.664h-256.112l-264.387 460.802 124.984 221.866h534.916l124.982-221.866-264.384-460.802zM367.814 631.466l138.931-239.789 138.934 239.789h-277.866z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["google-drive-monochromatic"],"defaultCode":59756,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1022,"name":"google-drive-monochromatic","prevSize":32,"id":110,"code":59756},"setIdx":0,"setId":6,"iconIdx":110},{"icon":{"paths":["M658.794 338.154c-39.798-38.052-90.416-57.426-146.794-57.426-100.016 0-184.669 67.548-214.865 158.313l-0.002-0.003c-7.679 23.040-12.042 47.648-12.042 72.957s4.364 49.92 12.044 72.96l0 0.003c30.196 90.765 114.849 158.314 214.865 158.314 51.664 0 95.651-13.613 130.035-36.653v-0.016c40.669-27.229 67.725-67.898 76.627-115.898h-206.662v-148.538h361.658c4.538 25.136 6.982 51.315 6.982 78.547 0 116.944-41.891 215.389-114.502 282.24v0.013c-63.533 58.646-150.458 93.030-254.138 93.030-150.109 0-279.971-86.048-343.156-211.549l-0-0.003c-26.007-51.84-40.844-110.49-40.844-172.451 0-61.965 14.836-120.611 40.844-172.451h0.004c63.187-125.495 193.047-211.542 343.153-211.542 103.504 0 190.429 38.051 256.931 100.014l-110.138 110.139z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["google-monochromatic"],"defaultCode":59657,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1023,"name":"google-monochromatic","prevSize":32,"id":111,"code":59657},"setIdx":0,"setId":6,"iconIdx":111},{"icon":{"paths":["M129.354 272c0-17.673 14.327-32 32-32h704c17.674 0 32 14.327 32 32s-14.326 32-32 32h-704c-17.673 0-32-14.327-32-32zM289.354 432c0 17.674-14.327 32-32 32s-32-14.326-32-32c0-17.674 14.327-32 32-32s32 14.326 32 32zM289.354 752c0 17.674-14.327 32-32 32s-32-14.326-32-32c0-17.674 14.327-32 32-32s32 14.326 32 32zM449.354 624c17.674 0 32-14.326 32-32s-14.326-32-32-32c-17.674 0-32 14.326-32 32s14.326 32 32 32zM385.354 400c-17.674 0-32 14.326-32 32s14.326 32 32 32h480c17.674 0 32-14.326 32-32s-14.326-32-32-32h-480zM353.354 752c0-17.674 14.326-32 32-32h480c17.674 0 32 14.326 32 32s-14.326 32-32 32h-480c-17.674 0-32-14.326-32-32zM577.354 560c-17.674 0-32 14.326-32 32s14.326 32 32 32h288c17.674 0 32-14.326 32-32s-14.326-32-32-32h-288z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["group-by-type"],"defaultCode":59757,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1024,"name":"group-by-type","prevSize":32,"id":112,"code":59757},"setIdx":0,"setId":6,"iconIdx":112},{"icon":{"paths":["M170.668 245.336c0-17.673 14.327-32 32-32h640.846c17.674 0 32 14.327 32 32s-14.326 32-32 32h-640.846c-17.673 0-32-14.327-32-32zM170.668 501.334c0-17.67 14.327-32 32-32h640.846c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-640.846c-17.673 0-32-14.326-32-32zM170.668 757.334c0-17.67 14.327-32 32-32h640.846c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-640.846c-17.673 0-32-14.326-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["hamburguer"],"defaultCode":59758,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1025,"name":"hamburguer","prevSize":32,"id":113,"code":59758},"setIdx":0,"setId":6,"iconIdx":113},{"icon":{"paths":["M832 512c0 176.73-143.27 320-320 320s-320-143.27-320-320h-64c0 212.077 171.923 384 384 384s384-171.923 384-384c0-212.077-171.923-384-384-384-123.718 0-233.772 58.508-304 149.364v-101.364c0-17.673-14.327-32-32-32s-32 14.327-32 32v192c0 17.674 14.327 32 32 32h176c17.674 0 32-14.326 32-32s-14.326-32-32-32h-107.295c57.24-86.756 155.583-144 267.295-144 176.73 0 320 143.27 320 320z","M544 320c0-17.673-14.326-32-32-32s-32 14.327-32 32v224c0 8.486 3.373 16.627 9.373 22.627l96 96c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-86.627-86.627v-210.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["history"],"defaultCode":59759,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1026,"name":"history","prevSize":32,"id":114,"code":59759},"setIdx":0,"setId":6,"iconIdx":114},{"icon":{"paths":["M522.042 195.354l224.464 260.044v366.234c0 5.856-4.752 10.605-10.614 10.605h-136.416v-149.821c0-23.424-19.014-42.413-42.47-42.413h-85.955c-23.453 0-42.467 18.989-42.467 42.413v149.821h-136.41c-5.864 0-10.617-4.749-10.617-10.605v-366.307l224.403-259.971c4.237-4.907 11.85-4.907 16.083 0zM560.57 895.856h175.322c41.043 0 74.32-33.232 74.32-74.224v-244.205h56.227c12.454 0 23.766-7.251 28.954-18.557 5.19-11.309 3.302-24.602-4.829-34.022l-320.272-371.033c-29.648-34.347-82.934-34.347-112.582 0l-320.27 371.033c-8.132 9.421-10.020 22.714-4.831 34.022 5.188 11.306 16.501 18.557 28.956 18.557h56.288v244.205c0 40.992 33.274 74.224 74.32 74.224h175.316c1.174 0.096 2.362 0.147 3.562 0.147h85.955c1.2 0 2.39-0.051 3.565-0.147z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["home"],"defaultCode":59760,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1027,"name":"home","prevSize":32,"id":115,"code":59760},"setIdx":0,"setId":6,"iconIdx":115},{"icon":{"paths":["M864 512c0-86.89-31.482-166.429-83.664-227.826l-496.162 496.162c61.397 52.182 140.937 83.664 227.826 83.664 194.403 0 352-157.597 352-352zM239.349 734.65l495.3-495.3c-60.662-49.597-138.182-79.349-222.65-79.349-194.404 0-352 157.596-352 352 0 84.467 29.753 161.987 79.349 222.65zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["ignore"],"defaultCode":59740,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1028,"name":"ignore","prevSize":32,"id":116,"code":59740},"setIdx":0,"setId":6,"iconIdx":116},{"icon":{"paths":["M406.685 405.334c0 47.126-38.205 85.331-85.334 85.331-47.127 0-85.332-38.205-85.332-85.331 0-47.13 38.205-85.334 85.332-85.334 47.13 0 85.334 38.205 85.334 85.334z","M97.352 192c0-17.673 14.327-32 32-32h767.999c17.674 0 32 14.327 32 32v640c0 17.674-14.326 32-32 32h-767.999c-17.673 0-32-14.326-32-32v-640zM161.352 764.163l151.704-176.989c9.271-10.813 24.57-14.202 37.536-8.307l153.123 69.603 160.474-204.24c6.010-7.651 15.174-12.15 24.902-12.23s18.963 4.272 25.098 11.821l151.162 186.048v-405.869h-703.999v540.163zM214.927 800h650.423v-68.64l-175.581-216.099-166.781 212.269-176.989-80.448-131.073 152.918z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["image"],"defaultCode":59761,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1029,"name":"image","prevSize":32,"id":117,"code":59761},"setIdx":0,"setId":6,"iconIdx":117},{"icon":{"paths":["M512 873.027c-199.389 0-361.026-161.635-361.026-361.024s161.636-361.026 361.026-361.026c199.389 0 361.024 161.637 361.024 361.026s-161.635 361.024-361.024 361.024zM512 938.669c235.642 0 426.666-191.024 426.666-426.666s-191.024-426.667-426.666-426.667c-235.642 0-426.667 191.025-426.667 426.667s191.025 426.666 426.667 426.666zM544.819 347.901c0 18.125-14.694 32.819-32.819 32.819-18.128 0-32.822-14.694-32.822-32.819 0-18.128 14.694-32.821 32.822-32.821 18.125 0 32.819 14.693 32.819 32.821zM512 413.542c-18.128 0-32.822 14.694-32.822 32.819v229.744c0 18.125 14.694 32.819 32.822 32.819 18.125 0 32.819-14.694 32.819-32.819v-229.744c0-18.125-14.694-32.819-32.819-32.819z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["info"],"defaultCode":59762,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1030,"name":"info","prevSize":32,"id":118,"code":59762},"setIdx":0,"setId":6,"iconIdx":118},{"icon":{"paths":["M512 864c-194.404 0-352-157.597-352-352s157.596-352 352-352c194.403 0 352 157.596 352 352s-157.597 352-352 352zM512 928c229.75 0 416-186.25 416-416s-186.25-416-416-416c-229.75 0-416 186.25-416 416s186.25 416 416 416zM662.627 361.373c12.496 12.496 12.496 32.758 0 45.254l-105.373 105.373 105.373 105.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-105.373-105.373-105.373 105.373c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l105.373-105.373-105.373-105.373c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l105.373 105.373 105.373-105.373c12.496-12.496 32.758-12.496 45.254 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["input-clear"],"defaultCode":59763,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1031,"name":"input-clear","prevSize":32,"id":119,"code":59763},"setIdx":0,"setId":6,"iconIdx":119},{"icon":{"paths":["M384 288c-17.674 0-32 14.327-32 32s14.326 32 32 32h256c17.674 0 32-14.326 32-32s-14.326-32-32-32h-256z","M352 448c0-17.674 14.326-32 32-32h256c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M512 640c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M224 224v576c0 35.347 28.654 64 64 64h448c35.347 0 64-28.653 64-64v-576c0-35.346-28.653-64-64-64h-448c-35.346 0-64 28.654-64 64zM288 800v-576h448v576h-448z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["instance"],"defaultCode":59764,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1032,"name":"instance","prevSize":32,"id":120,"code":59764},"setIdx":0,"setId":6,"iconIdx":120},{"icon":{"paths":["M563.59 255.992l-170.669 512.001h-136.941c-17.673 0-32 14.326-32 32 0 17.67 14.327 32 32 32h320c17.674 0 32-14.33 32-32 0-17.674-14.326-32-32-32h-115.597l170.669-512.001h136.928c17.674 0 32-14.327 32-32s-14.326-32-32-32h-159.002c-0.666-0.021-1.328-0.021-1.99 0h-159.008c-17.674 0-32 14.327-32 32s14.326 32 32 32h115.61z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["italic"],"defaultCode":59765,"grid":0},"attrs":[{}],"properties":{"order":1033,"name":"italic","prevSize":32,"id":121,"code":59765},"setIdx":0,"setId":6,"iconIdx":121},{"icon":{"paths":["M497.136 169.372c12.499 12.497 12.499 32.758 0 45.255l-35.958 35.96c1.078-0.016 2.163-0.025 3.245-0.025h191.152c115.11 0 208.426 93.316 208.426 208.426 0 115.107-93.315 208.422-208.426 208.422h-15.574v-64h15.574c79.763 0 144.426-64.659 144.426-144.422 0-79.766-64.662-144.426-144.426-144.426h-191.152c-1.030 0-2.058 0.011-3.082 0.032l35.795 35.796c12.499 12.499 12.499 32.758 0 45.258-12.496 12.496-32.758 12.496-45.254 0l-90.509-90.511c-12.496-12.497-12.496-32.758 0-45.255l90.509-90.51c12.496-12.497 32.758-12.497 45.254 0zM201.318 500.746h56.159v325.818h-59.023v-268.387h-1.909l-76.204 48.682v-54.090l80.977-52.022zM570.41 719.494c0 64.749-48.045 111.523-116.931 111.523-63.638 0-110.886-38.979-112.48-93.069h57.274c2.070 26.726 25.773 45.341 55.206 45.341 34.838 0 59.978-25.933 59.818-62.365 0.16-36.909-25.613-63.318-61.411-63.475-19.568-0.16-40.25 7.955-51.226 20.045l-53.296-8.749 17.024-168h188.998v49.318h-140.16l-9.386 86.384h1.91c12.090-14.317 35.475-24.816 61.885-24.816 59.184 0 102.774 45.181 102.774 107.862z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-backward"],"defaultCode":59766,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1034,"name":"jump-backward","prevSize":32,"id":122,"code":59766},"setIdx":0,"setId":6,"iconIdx":122},{"icon":{"paths":["M494.861 169.372c-12.496 12.497-12.496 32.758 0 45.255l35.962 35.96c-1.082-0.016-2.163-0.025-3.248-0.025h-191.149c-115.111 0-208.426 93.316-208.426 208.426 0 115.107 93.315 208.422 208.426 208.422h15.574v-64h-15.574c-79.764 0-144.426-64.659-144.426-144.422 0-79.766 64.661-144.426 144.426-144.426h191.149c1.030 0 2.061 0.011 3.085 0.032l-35.798 35.796c-12.496 12.499-12.496 32.758 0 45.258 12.499 12.496 32.758 12.496 45.258 0l90.509-90.511c12.496-12.497 12.496-32.758 0-45.255l-90.509-90.51c-12.499-12.497-32.758-12.497-45.258 0zM521.318 500.746h56.157v325.818h-59.021v-268.387h-1.91l-76.205 48.682v-54.090l80.979-52.022zM890.41 719.494c0 64.749-48.048 111.523-116.934 111.523-63.635 0-110.886-38.979-112.477-93.069h57.274c2.067 26.726 25.773 45.341 55.203 45.341 34.842 0 59.978-25.933 59.821-62.365 0.157-36.909-25.616-63.318-61.411-63.475-19.568-0.16-40.25 7.955-51.226 20.045l-53.296-8.749 17.021-168h189.002v49.318h-140.16l-9.386 86.384h1.91c12.090-14.317 35.475-24.816 61.885-24.816 59.181 0 102.774 45.181 102.774 107.862z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-forward"],"defaultCode":59767,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1035,"name":"jump-forward","prevSize":32,"id":123,"code":59767},"setIdx":0,"setId":6,"iconIdx":123},{"icon":{"paths":["M769.296 649.373c12.496 12.496 12.496 32.758 0 45.254l-192 192c-12.499 12.496-32.758 12.496-45.258 0l-192-192c-12.496-12.496-12.496-32.758 0-45.254 12.499-12.496 32.758-12.496 45.258 0l137.37 137.373v-578.746h-192v192c0 17.674-14.325 32-31.999 32s-32-14.326-32-32v-224c0-17.673 14.327-32 32-32h255.999c17.674 0 32 14.327 32 32v610.746l137.373-137.373c12.499-12.496 32.758-12.496 45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-to-message"],"defaultCode":59768,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1036,"name":"jump-to-message","prevSize":32,"id":124,"code":59768},"setIdx":0,"setId":6,"iconIdx":124},{"icon":{"paths":["M576 256c0 35.346-28.653 64-64 64s-64-28.654-64-64c0-35.346 28.653-64 64-64s64 28.654 64 64z","M576 512c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64z","M576 768c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["kebab"],"defaultCode":59769,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1037,"name":"kebab","prevSize":32,"id":125,"code":59769},"setIdx":0,"setId":6,"iconIdx":125},{"icon":{"paths":["M160 224c-35.346 0-64 28.654-64 64v448c0 35.347 28.654 64 64 64h704c35.347 0 64-28.653 64-64v-448c0-35.346-28.653-64-64-64h-704zM160 288h704v448h-704v-448zM256 352c-17.673 0-32 14.326-32 32s14.327 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM256 512c0-17.674 14.327-32 32-32h64c17.674 0 32 14.326 32 32s-14.326 32-32 32h-64c-17.673 0-32-14.326-32-32zM480 480c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM640 512c0-17.674 14.326-32 32-32h64c17.674 0 32 14.326 32 32s-14.326 32-32 32h-64c-17.674 0-32-14.326-32-32zM480 352c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM320 640c0-17.674 14.326-32 32-32h320c17.674 0 32 14.326 32 32s-14.326 32-32 32h-320c-17.674 0-32-14.326-32-32zM704 352c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["keyboard"],"defaultCode":59770,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1038,"name":"keyboard","prevSize":32,"id":126,"code":59770},"setIdx":0,"setId":6,"iconIdx":126},{"icon":{"paths":["M505.133 128.078c60.819-1.376 120.422 15.569 170.346 48.251 49.904 32.67 87.501 79.327 107.75 133.159 20.24 53.808 22.205 112.266 5.648 167.165-16.554 54.89-50.864 103.683-98.368 139.309-15.501 11.462-28.189 26.246-36.989 43.309-8.822 17.107-13.469 36-13.507 55.216v21.514h-96.013v-148.774l120.989-151.235c11.040-13.802 8.803-33.939-4.998-44.979s-33.939-8.803-44.979 4.998l-103.011 128.765-103.011-128.765c-11.040-13.802-31.178-16.038-44.979-4.998s-16.038 31.178-4.998 44.979l120.989 151.235v148.774h-95.994v-21.677c-0.138-19.030-4.762-37.728-13.462-54.691-8.694-16.954-21.21-31.69-36.509-43.194l-19.229 25.578 19.069-25.696c-34.247-25.418-61.857-57.84-80.845-94.736-18.985-36.89-28.886-77.331-29.027-118.285v-0.045c-0.71-146.981 123.709-271.715 281.13-275.177zM640.013 800c16.506 0 32.618-6.243 44.72-17.795 12.157-11.603 19.28-27.664 19.28-44.746v-22.842c0.022-8.947 2.182-17.856 6.39-26.016 4.214-8.176 10.406-15.459 18.208-21.216l0.192-0.144c58.173-43.59 100.733-103.75 121.35-172.109 20.621-68.378 18.154-141.245-7.021-208.177-25.168-66.908-71.664-124.28-132.602-164.174-60.915-39.878-133.274-60.348-206.826-58.689-189.76 4.184-344.567 155.060-343.702 339.427l0 0.045 32-0.154-32 0.109c0.176 51.165 12.553 101.558 36.121 147.35 23.547 45.754 57.616 85.658 99.521 116.774 7.682 5.792 13.781 13.062 17.952 21.194 4.164 8.122 6.33 16.944 6.409 25.84v22.781c0 17.082 7.123 33.142 19.28 44.746 12.106 11.552 28.218 17.795 44.72 17.795h256.006zM352 864c-17.674 0-32 14.326-32 32s14.326 32 32 32h320c17.674 0 32-14.326 32-32s-14.326-32-32-32h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["lamp-bulb"],"defaultCode":59836,"grid":0},"attrs":[{}],"properties":{"order":1039,"id":127,"name":"lamp-bulb","prevSize":32,"code":59836},"setIdx":0,"setId":6,"iconIdx":127},{"icon":{"paths":["M681.904 256c0-17.673-14.326-32-32-32s-32 14.327-32 32v56.875l-80.346 13.998c-17.411 3.034-29.069 19.61-26.035 37.021 3.034 17.408 19.61 29.066 37.021 26.032l69.36-12.086v69.373c-30.384 6.851-60.461 20.074-84.154 43.139-27.923 27.184-44.070 65.238-44.070 113.808 0 25.741 6.262 48.262 18.451 66.621 12.186 18.349 29.062 30.682 47.251 38 35.357 14.221 76.72 10.173 108.128-4.579l1.206-0.566c31.126-14.621 62.493-29.354 90.723-57.818 21.325-21.507 39.709-49.539 56.848-88.678 5.654 9.498 9.594 20.966 10.285 34.339 1.632 31.526-14.275 82.813-87.955 153.418-12.758 12.227-13.19 32.483-0.963 45.245 12.227 12.758 32.486 13.19 45.245 0.963 80.192-76.851 110.586-145.034 107.59-202.934-2.986-57.658-38.586-96.022-70.675-113.955-20.774-13.014-50.214-22.826-81.216-28.288-16.624-2.931-34.47-4.749-52.694-4.995v-74.243l101.718-17.722c17.411-3.034 29.066-19.61 26.032-37.019-3.034-17.411-19.606-29.066-37.018-26.032l-90.733 15.809v-45.724zM578.394 536.208c10.163-9.891 23.565-17.475 39.51-22.704v138.653c-13.443 2.547-27.485 1.731-38.634-2.752-7.712-3.104-13.658-7.757-17.824-14.029-4.157-6.262-7.766-15.997-7.766-31.216 0-33.35 10.563-54.176 24.714-67.952zM709.994 600.752c-8.682 8.755-17.782 15.706-28.090 22.074v-117.888c14.125 0.24 28.224 1.661 41.587 4.016 13.587 2.397 25.683 5.622 35.763 9.165-16.88 42.038-33.069 66.304-49.261 82.634zM247.704 565.334h98.386l-49.193-184.883-49.193 184.883zM390.851 733.562l-27.734-104.227h-132.442l-27.732 104.227c-4.544 17.078-22.073 27.242-39.152 22.694-17.079-4.544-27.24-22.070-22.696-39.152l106.323-399.598c13.494-50.714 85.462-50.713 98.956 0l106.323 399.598c4.544 17.082-5.616 34.608-22.694 39.152-17.078 4.547-34.608-5.616-39.152-22.694z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["language"],"defaultCode":59771,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1040,"name":"language","prevSize":32,"id":128,"code":59771},"setIdx":0,"setId":6,"iconIdx":128},{"icon":{"paths":["M234.831 743.917c-75.198-141.606-58.197-285.718 40.507-391.734 101.776-109.314 284.915-172.318 524.636-158.217 16.192 0.953 29.114 13.872 30.064 30.066 14.102 239.723-48.902 422.859-158.218 524.635-106.016 98.707-250.128 115.706-391.737 40.506l-65.457 65.456c-12.497 12.499-32.758 12.499-45.255 0-12.497-12.496-12.497-32.758 0-45.254l65.458-65.456zM282.51 696.237l300.107-300.109c12.496-12.496 32.758-12.496 45.254 0 12.496 12.499 12.496 32.758 0 45.258l-300.109 300.106c113.565 53.238 220.73 34.554 300.448-39.664 86.579-80.611 146.157-231.866 139.251-445.286-213.418-6.905-364.675 52.673-445.283 139.254-74.219 79.715-92.904 186.877-39.669 300.442z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["leaf"],"defaultCode":59814,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1041,"id":129,"name":"leaf","prevSize":32,"code":59814},"setIdx":0,"setId":6,"iconIdx":129},{"icon":{"paths":["M254.841 275.612l-13.972 14.271c-37.092 37.883-36.449 98.664 1.435 135.758l145.619 142.573c37.885 37.091 98.666 36.448 135.76-1.437l13.971-14.269c0.723-0.739 1.43-1.488 2.128-2.243l0.099 0.099c5.805-5.904 13.888-9.568 22.822-9.568 17.674 0 32 14.326 32 32 0 9.6-4.227 18.211-10.922 24.077l-0.397 0.41-13.974 14.269c-61.818 63.142-163.12 64.214-226.259 2.394l-145.622-142.576c-63.141-61.818-64.212-163.119-2.392-226.26l13.972-14.27c61.82-63.141 163.12-64.212 226.263-2.392l74.691 73.131c0.976 0.847 1.901 1.752 2.768 2.71l0.374 0.366-0.026 0.026c4.934 5.63 7.923 13.005 7.923 21.078 0 17.674-14.326 32-32 32-7.83 0-15.005-2.813-20.566-7.482l-0.106 0.109-77.834-76.206c-37.885-37.092-98.666-36.45-135.757 1.435zM790.566 768.003l13.971-14.269c37.091-37.885 36.448-98.666-1.437-135.757l-145.619-142.576c-37.885-37.091-98.666-36.448-135.757 1.437l-13.971 14.269c-0.723 0.739-1.434 1.488-2.128 2.243l-0.102-0.099c-5.805 5.907-13.885 9.568-22.822 9.568-17.67 0-32-14.326-32-32 0-9.6 4.227-18.211 10.922-24.077l0.4-0.406 13.971-14.272c61.821-63.142 163.12-64.211 226.262-2.39l145.619 142.573c63.142 61.821 64.211 163.12 2.394 226.262l-13.971 14.269c-61.821 63.142-163.123 64.211-226.262 2.394l-74.694-73.133c-0.976-0.845-1.901-1.75-2.768-2.71l-0.374-0.365 0.026-0.026c-4.931-5.629-7.923-13.005-7.923-21.078 0-17.674 14.326-32 32-32 7.83 0 15.005 2.813 20.566 7.482l0.106-0.109 77.837 76.208c37.885 37.091 98.662 36.448 135.757-1.437z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["link"],"defaultCode":59752,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1042,"name":"link","prevSize":32,"id":130,"code":59752},"setIdx":0,"setId":6,"iconIdx":130},{"icon":{"paths":["M840.541 128c31.318 0 56.813 24.79 56.813 55.383v657.212c0 30.592-25.494 55.427-56.813 55.427h-654.546c-31.254 0-56.642-24.835-56.642-55.427v-657.212c0-30.593 25.387-55.383 56.642-55.383h654.546zM300.196 233.75c-36.588 0-66.093 29.59-66.093 66.050 0 36.482 29.505 66.072 66.093 66.072 36.437 0 66.005-29.59 66.005-66.072 0-36.46-29.568-66.050-66.005-66.050zM243.148 782.461h114.029v-366.515h-114.029v366.515zM537.814 415.923h-109.187v366.515h113.773v-181.274c0-47.83 9.046-94.147 68.333-94.147 58.454 0 59.181 54.678 59.181 97.174v178.246h113.901v-201.008c0-98.714-21.312-174.598-136.666-174.598-55.402 0-92.566 30.381-107.757 59.203h-1.578v-50.112z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["linkedin-monochromatic"],"defaultCode":59658,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1043,"name":"linkedin-monochromatic","prevSize":32,"id":131,"code":59658},"setIdx":0,"setId":6,"iconIdx":131},{"icon":{"paths":["M700.144 361.891c4.685-24.973 34.704-34.093 49.13-13.171 31.994 46.403 50.726 102.653 50.726 163.28s-18.733 116.88-50.726 163.283c-14.426 20.922-44.445 11.802-49.13-13.174l-1.706-9.101c-1.581-8.429 0.384-17.082 4.858-24.403 20.749-33.965 32.704-73.888 32.704-116.605 0-42.714-11.955-82.637-32.704-116.605-4.474-7.318-6.438-15.971-4.858-24.4l1.706-9.104z","M320.704 395.395c-20.748 33.968-32.704 73.891-32.704 116.605 0 42.717 11.956 82.64 32.704 116.605 4.474 7.322 6.438 15.974 4.858 24.403l-1.706 9.101c-4.684 24.976-34.705 34.096-49.128 13.174-31.994-46.403-50.728-102.656-50.728-163.283s18.733-116.877 50.728-163.28c14.424-20.922 44.444-11.802 49.128 13.171l1.706 9.104c1.581 8.429-0.384 17.082-4.858 24.4z","M728.765 209.256l-0.515 2.747c-2.234 11.911 2.534 23.967 11.763 31.821 75.866 64.565 123.987 160.751 123.987 268.175 0 107.427-48.122 203.613-123.987 268.176-9.229 7.856-13.997 19.914-11.763 31.824l0.515 2.746c4.192 22.362 29.69 33.194 47.261 18.746 92.794-76.294 151.974-191.981 151.974-321.491 0-129.507-59.181-245.193-151.974-321.489-17.571-14.448-43.069-3.615-47.261 18.745z","M283.986 243.825c9.228-7.854 13.998-19.911 11.764-31.821l-0.515-2.747c-4.192-22.359-29.69-33.193-47.262-18.745-92.793 76.296-151.973 191.981-151.973 321.489 0 129.51 59.18 245.197 151.973 321.491 17.572 14.448 43.070 3.616 47.262-18.746l0.515-2.746c2.233-11.91-2.536-23.968-11.764-31.824-75.864-64.563-123.986-160.749-123.986-268.176 0-107.424 48.122-203.61 123.986-268.175z","M608 512c0 53.021-42.979 96-96 96s-96-42.979-96-96c0-53.018 42.979-96 96-96s96 42.982 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["live"],"defaultCode":59774,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1044,"name":"live","prevSize":32,"id":132,"code":59774},"setIdx":0,"setId":6,"iconIdx":132},{"icon":{"paths":["M439.274 704.374c0-33.645 26.278-47.677 72.726-47.677s72.73 14.032 72.73 47.677c0 32.96-13.19 111.069-23.914 149.76-4.963 17.808-22.080 25.171-48.816 25.171s-43.85-7.363-48.813-25.174c-10.717-38.666-23.914-116.688-23.914-149.757zM616.778 870.374l0.026-0.090c6.176-22.291 12.566-53.869 17.386-83.453 4.688-28.787 8.72-60.707 8.72-82.458 0-35.891-15.811-67.802-46.797-87.114-26.035-16.227-57.152-19.926-84.112-19.926-26.957 0-58.077 3.699-84.112 19.926-30.982 19.312-46.797 51.222-46.797 87.114 0 21.805 4.035 53.728 8.726 82.515 4.819 29.578 11.21 61.123 17.379 83.392l0.026 0.086c7.402 26.557 24.982 45.664 46.87 56.467 19.472 9.61 40.426 11.834 57.907 11.834 17.485 0 38.435-2.224 57.907-11.83 21.888-10.8 39.469-29.907 46.87-56.464zM459.635 460.8c0-28.275 23.446-51.2 52.365-51.2s52.365 22.925 52.365 51.2c0 28.278-23.446 51.2-52.365 51.2s-52.365-22.922-52.365-51.2zM512 341.334c-67.478 0-122.182 53.488-122.182 119.466 0 65.981 54.704 119.469 122.182 119.469s122.182-53.488 122.182-119.469c0-65.978-54.704-119.466-122.182-119.466zM677.802 537.254c-6.662 13.792-3.882 31.11 6.278 42.573 14.086 15.894 39.85 17.939 50.205-0.602 19.642-35.174 30.806-75.526 30.806-118.426 0-136.672-113.315-247.465-253.091-247.465-139.779 0-253.092 110.793-253.092 247.465 0 42.899 11.164 83.251 30.806 118.426 10.354 18.541 36.119 16.496 50.205 0.602 10.16-11.462 12.938-28.781 6.275-42.573-11.203-23.187-17.469-49.104-17.469-76.454 0-98.97 82.054-179.199 183.274-179.199s183.27 80.229 183.27 179.199c0 27.35-6.262 53.267-17.469 76.454zM730.16 699.795c-0.304-10.659 3.542-21.072 10.928-28.762 52.771-54.957 85.094-128.902 85.094-210.234 0-169.661-140.666-307.199-314.182-307.199s-314.182 137.538-314.182 307.199c0 81.331 32.323 155.28 85.093 210.234 7.386 7.69 11.234 18.102 10.928 28.762-0.833 29.018-31.273 47.917-52.121 27.715-70.223-68.042-113.718-162.41-113.718-266.71 0-207.363 171.923-375.465 384-375.465s384 168.102 384 375.465c0 104.304-43.498 198.672-113.722 266.714-20.848 20.202-51.286 1.302-52.118-27.718z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["live-streaming"],"defaultCode":59773,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1045,"name":"live-streaming","prevSize":32,"id":133,"code":59773},"setIdx":0,"setId":6,"iconIdx":133},{"icon":{"paths":["M397.011 527.334c26.576 0 48.122-21.587 48.122-48.214s-21.546-48.214-48.122-48.214c-26.576 0-48.118 21.587-48.118 48.214s21.542 48.214 48.118 48.214z","M589.491 479.12c0 26.627-21.542 48.214-48.118 48.214s-48.122-21.587-48.122-48.214c0-26.627 21.546-48.214 48.122-48.214s48.118 21.587 48.118 48.214z","M733.853 479.12c0 26.627-21.542 48.214-48.118 48.214s-48.122-21.587-48.122-48.214c0-26.627 21.546-48.214 48.122-48.214s48.118 21.587 48.118 48.214z","M88.039 813.683l119.625 31.283c85.312 22.307 173.45-16.256 238.691-79.709 29.501 4.794 59.875 7.242 90.678 7.242 218.294 0 404.339-122.864 404.339-294.518 0-171.664-186.042-294.52-404.339-294.52-218.314 0-404.351 122.852-404.34 294.523 0 65.072 27.642 125.014 75.655 173.587-2.847 24.835-14.596 44.73-36.049 68.55l-84.261 93.562zM537.034 258.997c183.13 0 331.6 98.043 331.6 218.984 0 120.931-148.47 218.982-331.6 218.982-40.781 0-79.834-4.877-115.91-13.763-36.669 45.6-117.335 109.008-195.697 88.518 25.489-28.304 63.251-76.131 55.168-154.909-46.968-37.779-75.162-86.134-75.162-138.829-0.008-120.95 148.461-218.984 331.6-218.984z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["livechat-monochromatic"],"defaultCode":59775,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1046,"name":"livechat-monochromatic","prevSize":32,"id":134,"code":59775},"setIdx":0,"setId":6,"iconIdx":134},{"icon":{"paths":["M512 128c-97.203 0-176 78.798-176 176v142.477h-16c-53.020 0-96 42.979-96 96v257.523c0 53.021 42.981 96 96 96h384c53.021 0 96-42.979 96-96v-257.523c0-53.021-42.979-96-96-96h-16v-142.477c0-97.202-78.797-176-176-176zM624 304v142.477h-224v-142.477c0-61.856 50.144-112 112-112s112 50.144 112 112z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["lock-filled"],"defaultCode":59748,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1047,"name":"lock-filled","prevSize":32,"id":135,"code":59748},"setIdx":0,"setId":6,"iconIdx":135},{"icon":{"paths":["M336 304c0-97.202 78.797-176 176-176s176 78.798 176 176v142.477h16c53.021 0 96 42.979 96 96v257.523c0 53.021-42.979 96-96 96h-384c-53.019 0-96-42.979-96-96v-257.523c0-53.021 42.981-96 96-96h16v-142.477zM400 446.477h224v-142.477c0-61.856-50.144-112-112-112s-112 50.144-112 112v142.477zM320 510.477c-17.673 0-32 14.326-32 32v257.523c0 17.674 14.327 32 32 32h384c17.674 0 32-14.326 32-32v-257.523c0-17.674-14.326-32-32-32h-384z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["locker"],"defaultCode":59749,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1048,"name":"locker","prevSize":32,"id":136,"code":59749},"setIdx":0,"setId":6,"iconIdx":136},{"icon":{"paths":["M341.334 778.672c-17.674 0-32 14.326-32 32s14.326 32 32 32h341.334c17.674 0 32-14.326 32-32s-14.326-32-32-32h-341.334zM85.335 298.672c0-70.692 57.308-128 128-128h597.334c70.691 0 128 57.308 128 128v298.666c0 70.694-57.309 128-128 128h-597.334c-70.692 0-128-57.306-128-128v-298.666zM213.335 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.347 28.654 64 64 64h597.334c35.344 0 64-28.653 64-64v-298.666c0-35.347-28.656-64-64-64h-597.334zM256 320c0-11.782 9.551-21.333 21.333-21.333h170.667c11.782 0 21.334 9.551 21.334 21.333s-9.552 21.334-21.334 21.334h-170.667c-11.782 0-21.333-9.552-21.333-21.334zM277.333 554.666c-11.782 0-21.333 9.552-21.333 21.334s9.551 21.334 21.333 21.334h85.332c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-85.332zM554.666 320c0-11.782 9.552-21.333 21.334-21.333h170.666c11.782 0 21.334 9.551 21.334 21.333s-9.552 21.334-21.334 21.334h-170.666c-11.782 0-21.334-9.552-21.334-21.334zM448 554.666c-11.782 0-21.334 9.552-21.334 21.334s9.552 21.334 21.334 21.334h298.666c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-298.666zM256 448c0-11.782 9.551-21.334 21.333-21.334h213.332c11.782 0 21.334 9.552 21.334 21.334s-9.552 21.334-21.334 21.334h-213.332c-11.782 0-21.333-9.552-21.333-21.334zM618.666 426.666c-11.782 0-21.331 9.552-21.331 21.334s9.549 21.334 21.331 21.334h128c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["log-view"],"defaultCode":59778,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1049,"name":"log-view","prevSize":32,"id":137,"code":59778},"setIdx":0,"setId":6,"iconIdx":137},{"icon":{"paths":["M176 96c-17.673 0-32 14.327-32 32v768c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-96c0-17.674-14.326-32-32-32s-32 14.326-32 32v64h-448v-704h448v64c0 17.673 14.326 32 32 32s32-14.327 32-32v-96c0-17.673-14.326-32-32-32h-512zM521.373 329.373c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.254l-105.373 105.373h418.746c17.674 0 32 14.326 32 32s-14.326 32-32 32h-418.746l105.373 105.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-160-160c-12.496-12.496-12.496-32.758 0-45.254l160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["login"],"defaultCode":59779,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1050,"name":"login","prevSize":32,"id":138,"code":59779},"setIdx":0,"setId":6,"iconIdx":138},{"icon":{"paths":["M268.099 96c-17.673 0-32 14.327-32 32v768c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-96c0-17.674-14.326-32-32-32s-32 14.326-32 32v64h-448v-704h448v64c0 17.673 14.326 32 32 32s32-14.327 32-32v-96c0-17.673-14.326-32-32-32h-512zM994.726 489.373l-160-160c-12.496-12.497-32.758-12.497-45.254 0s-12.496 32.758 0 45.254l105.373 105.373h-418.746c-17.674 0-32 14.326-32 32s14.326 32 32 32h418.746l-105.373 105.373c-12.496 12.496-12.496 32.758 0 45.254s32.758 12.496 45.254 0l160-160c12.496-12.496 12.496-32.758 0-45.254z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["logout"],"defaultCode":59780,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1051,"name":"logout","prevSize":32,"id":139,"code":59780},"setIdx":0,"setId":6,"iconIdx":139},{"icon":{"paths":["M192 736h640v-448h-640v448zM128 256c0-17.673 14.327-32 32-32h704c17.674 0 32 14.327 32 32v512c0 17.674-14.326 32-32 32h-704c-17.673 0-32-14.326-32-32v-512zM305.304 389.082c-14.866-9.555-34.665-5.251-44.222 9.613-9.557 14.867-5.253 34.666 9.613 44.224l241.304 155.123 241.306-155.123c14.864-9.558 19.168-29.357 9.613-44.224-9.558-14.864-29.357-19.168-44.224-9.613l-206.694 132.877-206.696-132.877z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["mail"],"defaultCode":59781,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1052,"name":"mail","prevSize":32,"id":140,"code":59781},"setIdx":0,"setId":6,"iconIdx":140},{"icon":{"paths":["M302.769 192h418.463l23.187 72.727h-0.211l23.792 63.999c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818c0-18.476-14.326-33.454-32-33.454s-32 14.978-32 33.454c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818c0-18.476-14.326-33.454-32-33.454s-32 14.978-32 33.454c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818l23.794-63.999h-0.213l23.188-72.727zM212.406 264.727l36.491-114.448c4.231-13.27 16.56-22.279 30.488-22.279h465.23c13.93 0 26.259 9.009 30.49 22.279l56.896 178.447c0 33.939-12.083 64.925-32 88.515v350.778c0 53.018-42.979 96-96 96h-384c-53.019 0-96-42.982-96-96v-350.778c-19.916-23.59-32-54.576-32-88.515l20.406-63.999zM288 458.33v309.69c0 17.67 14.327 32 32 32h128v-192.019h128v192.019h128c17.674 0 32-14.33 32-32v-309.69c-10.227 2.752-20.95 4.214-32 4.214-38.23 0-72.547-17.52-96-45.302-23.453 27.782-57.77 45.302-96 45.302s-72.547-17.52-96-45.302c-23.453 27.782-57.77 45.302-96 45.302-11.050 0-21.772-1.462-32-4.214z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["marketplace"],"defaultCode":59782,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1053,"name":"marketplace","prevSize":32,"id":141,"code":59782},"setIdx":0,"setId":6,"iconIdx":141},{"icon":{"paths":["M773.072 576c-35.344 0-64-28.653-64-64s28.656-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64z","M517.072 576c-35.344 0-64-28.653-64-64s28.656-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64z","M261.073 576c-35.346 0-64-28.653-64-64s28.654-64 64-64c35.346 0 63.999 28.653 63.999 64s-28.652 64-63.999 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["meatballs"],"defaultCode":59783,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1054,"name":"meatballs","prevSize":32,"id":142,"code":59783},"setIdx":0,"setId":6,"iconIdx":142},{"icon":{"paths":["M651.36 116.071c-57.242-19.989-105.792-20.069-138.358-20.071v64l-1.002-64c-92.006 0.342-297.345 47.824-381.242 242.995-17.897 38.97-34.758 103.344-34.758 173.005 0 69.958 17.020 146.285 52.216 207.875 23.229 40.653 92.799 131.376 191.179 173.536 94.861 40.656 206.368 52.349 296.49 16.301 16.41-6.563 24.39-25.187 17.827-41.597s-25.187-24.39-41.597-17.827c-69.878 27.952-163.171 20.445-247.51-15.699-80.819-34.64-141.384-112.451-160.821-146.464-28.804-50.41-43.784-115.418-43.784-176.125 0-60.765 15.020-116.182 29.055-146.589l0.184-0.4 0.173-0.406c69.507-162.181 243.823-204.604 323.589-204.605 31.594 0.002 70.877 0.296 117.258 16.493 46.147 16.114 101.389 48.779 161.824 116.767 43.658 49.115 63.533 114.977 69.389 177.713 5.891 63.12-2.854 118.189-11.546 142.093-6.4 17.6-20.429 45.44-59.392 45.699-18.259-0.806-72.822-14.672-83.12-69.568v-235.062c0-17.674-3.414-34.134-29.014-34.134-19.338 0-26.454 16.461-26.454 34.134v34.131c-35.181-39.859-95.402-68.266-152.746-68.266-106.038 0-192 85.962-192 192s85.962 192 192 192c62.179 0 117.658-29.555 152.746-75.386 25.715 71.078 102.57 93.027 137.014 94.134l0.515 0.016h0.512c82.643 0 111.715-64.806 120.086-87.83 12.64-34.762 21.674-99.696 15.12-169.907-6.589-70.595-29.379-151.401-85.277-214.287-66.902-75.265-131.075-114.597-188.557-134.67zM627.2 512c0 70.691-57.309 128-128 128s-128-57.309-128-128c0-70.691 57.309-128 128-128s128 57.309 128 128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["mention"],"defaultCode":59784,"grid":0},"attrs":[{}],"properties":{"order":1055,"name":"mention","prevSize":32,"id":143,"code":59784},"setIdx":0,"setId":6,"iconIdx":143},{"icon":{"paths":["M223.311 308.609c-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-9.348 103.235 27.547 175.997 86.848 226.374 60.643 51.52 146.602 80.998 235.29 90.893 88.614 9.885 186.224 1.398 263.341-14.973 38.56-8.189 70.928-18.125 93.888-28.128 8.906-3.882 15.837-7.536 20.944-10.765-2.378-1.514-5.248-3.197-8.675-5.030-8.886-4.749-19.059-9.261-29.613-13.894l-1.843-0.81c-9.315-4.083-19.725-8.65-27.613-13.078-14.291-8.026-28.317-17.155-38.544-26.867-5.034-4.781-10.762-11.194-14.595-19.184-4.054-8.454-6.96-21.078-1.261-34.435 30.816-72.186 45.459-111.725 52.554-137.834 6.621-24.378 6.621-36.653 6.621-56.17v-0.179c0-15.51-8.979-86.595-53.776-152.876-43.376-64.174-121.395-125.729-264.832-125.729-129.725 0-207.83 53.576-254.529 118.696zM173.267 272.433c58.132-81.063 154.749-144.433 304.573-144.433 164.896 0 261.594 72.589 315.859 152.878 52.838 78.181 64.416 161.881 64.416 187.641 0 21.654-0.022 40.336-8.797 72.64-7.83 28.835-22.627 68.614-50.048 133.424 5.069 4.032 12.592 9.005 22.506 14.57 5.123 2.877 12.995 6.339 24.054 11.194 10.266 4.506 22.582 9.93 33.891 15.978 10.848 5.798 23.526 13.571 32.954 23.738 9.859 10.63 20.208 28.87 12.816 51.139-4.87 14.672-16.182 25.091-25.61 32.016-10.24 7.52-22.947 14.278-36.858 20.342-27.946 12.176-64.582 23.181-105.68 31.907-82.198 17.453-186.522 26.688-282.909 15.936-96.31-10.746-195.346-43.178-268.313-105.165-74.031-62.893-119.295-154.778-108.551-277.856 0.276-63.411 19.117-157.053 75.696-235.948z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["message"],"defaultCode":59786,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1056,"name":"message","prevSize":32,"id":144,"code":59786},"setIdx":0,"setId":6,"iconIdx":144},{"icon":{"paths":["M477.84 128c104.256 0 181.251 29.018 237.494 70.652l-44.317 44.317c-45.52-31.22-107.747-53.057-193.178-53.057-129.725 0-207.83 53.576-254.529 118.696-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-7.328 80.928 13.761 143.126 51.784 190.499l-43.879 43.878c-50.179-59.901-78.131-139.043-69.441-238.595 0.276-63.411 19.117-157.053 75.696-235.948 58.132-81.063 154.749-144.433 304.573-144.433zM822.848 332.499l-47.008 47.008c16.502 42.634 20.608 78.525 20.608 89.011v0.179c0 19.517 0 31.792-6.621 56.17-7.094 26.109-21.738 65.648-52.554 137.834-5.699 13.357-2.794 25.981 1.261 34.435 3.834 7.99 9.562 14.403 14.595 19.184 10.227 9.712 24.253 18.842 38.544 26.867 7.888 4.429 18.298 8.995 27.613 13.078l1.843 0.81c10.554 4.634 20.726 9.146 29.613 13.894 3.427 1.834 6.298 3.517 8.672 5.030-5.104 3.229-12.035 6.883-20.941 10.765-22.96 10.003-55.328 19.939-93.888 28.128-77.12 16.371-174.73 24.858-263.341 14.973-43.744-4.88-86.826-14.525-126.534-29.229l-47.542 47.542c52.771 23.018 110.492 36.886 167.267 43.222 96.387 10.752 200.71 1.517 282.909-15.936 41.098-8.726 77.731-19.731 105.68-31.907 13.91-6.064 26.618-12.822 36.858-20.342 9.427-6.925 20.739-17.344 25.61-32.016 7.392-22.269-2.957-40.509-12.816-51.139-9.427-10.166-22.106-17.939-32.954-23.738-11.309-6.048-23.626-11.472-33.891-15.978-11.059-4.854-18.934-8.317-24.054-11.194-9.914-5.565-17.437-10.538-22.506-14.57 27.421-64.81 42.214-104.589 50.048-133.424 8.774-32.304 8.797-50.986 8.797-72.64 0-20.106-7.053-75.501-35.267-136.019zM836.038 153.372c12.499-12.497 32.758-12.497 45.254 0 12.499 12.497 12.499 32.758 0 45.255l-682.665 682.665c-12.497 12.499-32.758 12.499-45.255 0-12.497-12.496-12.497-32.755 0-45.254l682.666-682.666z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["message-disabled"],"defaultCode":59785,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1057,"name":"message-disabled","prevSize":32,"id":145,"code":59785},"setIdx":0,"setId":6,"iconIdx":145},{"icon":{"paths":["M86.686 85.336l730.792 774.088c0 0 24.899 17.558 43.936-2.928 19.040-20.486 4.394-40.973 4.394-40.973l-779.122-730.187zM318.080 158.503l556.516 599.955c0 0 24.896 17.558 43.936-2.928 19.037-20.486 4.394-40.973 4.394-40.973l-604.845-556.054zM712.035 915.030l-556.517-599.955 604.843 556.054c0 0 14.646 20.486-4.39 40.973-19.040 20.486-43.936 2.928-43.936 2.928zM513.693 221.419l388.803 419.15c0 0 17.395 12.269 30.694-2.042 13.302-14.314 3.069-28.627 3.069-28.627l-422.566-388.482zM597.878 915.677l-388.805-419.152 422.568 388.48c0 0 10.234 14.314-3.069 28.627-13.302 14.31-30.694 2.045-30.694 2.045zM713.498 312.143l176.221 190.551c0 0 8.605 5.747 15.184-0.96 6.579-6.704 1.517-13.411 1.517-13.411l-192.922-176.18zM482.582 880.23l-176.219-190.55 192.923 176.179c0 0 5.059 6.707-1.52 13.414-6.579 6.704-15.184 0.957-15.184 0.957z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["meteor-monochromatic"],"defaultCode":59659,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1058,"name":"meteor-monochromatic","prevSize":32,"id":146,"code":59659},"setIdx":0,"setId":6,"iconIdx":146},{"icon":{"paths":["M608 288c0-53.019-42.979-96-96-96s-96 42.981-96 96v128c0 53.021 42.979 96 96 96s96-42.979 96-96v-128zM352 288c0-88.365 71.635-160 160-160s160 71.635 160 160v128c0 88.365-71.635 160-160 160s-160-71.635-160-160v-128zM256 384c17.673 0 32 14.326 32 32 0 92.086 37.757 149.632 83.722 185.6 46.464 36.358 102.736 51.581 140.278 54.326 37.542-2.746 93.814-17.968 140.278-54.326 45.962-35.968 83.722-93.514 83.722-185.6 0-17.674 14.326-32 32-32s32 14.326 32 32c0 112.714-47.574 188.499-108.278 236-47.904 37.485-103.082 56.762-147.722 64.381v115.619h160c17.674 0 32 14.326 32 32s-14.326 32-32 32h-384c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-115.619c-44.64-7.619-99.818-26.896-147.722-64.381-60.703-47.501-108.278-123.286-108.278-236 0-17.674 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["microphone"],"defaultCode":59788,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1059,"name":"microphone","prevSize":32,"id":147,"code":59788},"setIdx":0,"setId":6,"iconIdx":147},{"icon":{"paths":["M512 128c75.546 0 138.861 52.356 155.645 122.762l-59.645 59.644v-22.405c0-53.019-42.979-96-96-96s-96 42.981-96 96v128c0 24.067 8.858 46.067 23.488 62.915l-45.322 45.325c-26.182-28.49-42.166-66.499-42.166-108.24v-128c0-88.365 71.635-160 160-160zM561.35 568.243l102.893-102.893c-15.763 48.672-54.221 87.13-102.893 102.893zM288 416c0 72.154 23.181 123.101 55.328 159.078l-45.304 45.302c-43.428-47.35-74.024-113.99-74.024-204.381 0-17.674 14.327-32 32-32s32 14.326 32 32zM478.659 650.938l-51.808 51.808c18.56 6.374 36.579 10.806 53.149 13.635v115.619h-160c-17.673 0-32 14.326-32 32s14.327 32 32 32h384c17.674 0 32-14.326 32-32s-14.326-32-32-32h-160v-115.619c44.64-7.619 99.818-26.896 147.722-64.381 60.704-47.501 108.278-123.286 108.278-236 0-17.674-14.326-32-32-32s-32 14.326-32 32c0 92.086-37.757 149.632-83.722 185.6-46.464 36.358-102.736 51.581-140.278 54.326-9.971-0.73-21.264-2.339-33.341-4.989zM825.373 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672-672z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["microphone-disabled"],"defaultCode":59787,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1060,"name":"microphone-disabled","prevSize":32,"id":148,"code":59787},"setIdx":0,"setId":6,"iconIdx":148},{"icon":{"paths":["M234.666 170.661c0-47.128 38.205-85.333 85.333-85.333h384.001c47.126 0 85.331 38.205 85.331 85.333v682.667c0 47.13-38.205 85.334-85.331 85.334h-384.001c-47.128 0-85.333-38.205-85.333-85.334v-682.667zM298.666 170.661v682.667c0 11.782 9.551 21.334 21.333 21.334h384.001c11.782 0 21.331-9.552 21.331-21.334v-682.667c0-11.782-9.549-21.333-21.331-21.333h-96.291c-2.653 24.002-23.002 42.672-47.709 42.672h-96c-24.707 0-45.056-18.67-47.709-42.672h-96.292c-11.782 0-21.333 9.551-21.333 21.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["mobile"],"defaultCode":59789,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1061,"name":"mobile","prevSize":32,"id":149,"code":59789},"setIdx":0,"setId":6,"iconIdx":149},{"icon":{"paths":["M319.247 231.566c-62.882 49.504-135.086 136.549-141.94 266.127-5.762 108.922 37.404 187.184 89.915 241.51 53.258 55.098 115.702 84.925 144.25 94.438 41.859 13.955 114.269 29.536 234.643-15.603 34.858-13.072 73.165-42.096 108.304-78.426 14.272-14.755 27.616-30.294 39.6-45.773-28.778 9.293-61.699 17.754-96.589 23.594-56.192 9.405-119.29 12.32-179.411-0.237-2.49-0.518-4.96-1.030-7.408-1.536-22.195-4.576-42.733-8.816-62.589-17.648-23.091-10.275-43.805-25.891-69.299-51.386-42.096-42.096-89.142-107.222-89.371-213.843-1.569-34.080 4.622-81.878 13.764-129.216 4.624-23.946 10.142-48.465 16.132-72.003zM345.562 138.217c32.8-17.15 63.709 15.843 53.875 45.907-12.234 37.414-24.586 85.511-33.482 131.58-9.024 46.732-13.949 88.633-12.643 114.7l0.038 0.797v0.8c0 84.915 36.173 134.918 70.627 169.373 22.509 22.509 36.835 32.278 50.064 38.166 13.229 5.885 26.832 8.717 51.085 13.763 1.923 0.4 3.917 0.816 5.978 1.248 49.914 10.426 104.534 8.336 155.76-0.237 65.434-10.954 122.384-31.981 152.374-47.386 17.562-9.021 34.992-2.47 44.477 5.965 9.661 8.589 19.376 27.152 8.886 46.954-20.637 38.95-53.645 84.419-92.182 124.259-38.211 39.51-84.317 76.038-131.834 93.859-135.626 50.858-223.216 34.438-277.354 16.394-36.515-12.173-108.392-46.912-170.026-110.675-62.381-64.534-114.684-159.427-107.81-289.373 10.79-203.979 157.583-317.098 232.165-356.093z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["moon"],"defaultCode":59790,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1062,"name":"moon","prevSize":32,"id":150,"code":59790},"setIdx":0,"setId":6,"iconIdx":150},{"icon":{"paths":["M144 160c-17.673 0-32 14.327-32 32s14.327 32 32 32h192c17.674 0 32-14.327 32-32s-14.326-32-32-32h-192zM700.4 346.646c11.795-13.165 32.026-14.272 45.187-2.48 13.162 11.795 14.272 32.026 2.477 45.187l-81.222 90.646h216.358c17.674 0 32 14.326 32 32s-14.326 32-32 32h-216.358l81.222 90.646c11.795 13.162 10.685 33.392-2.477 45.187-13.162 11.792-33.392 10.685-45.187-2.48l-129.030-144c-10.893-12.154-10.893-30.554 0-42.707l129.030-144zM112 512c0-17.674 14.327-32 32-32h192c17.674 0 32 14.326 32 32s-14.326 32-32 32h-192c-17.673 0-32-14.326-32-32zM144 640c-17.673 0-32 14.326-32 32s14.327 32 32 32h192c17.674 0 32-14.326 32-32s-14.326-32-32-32h-192zM112 352c0-17.674 14.327-32 32-32h192c17.674 0 32 14.326 32 32s-14.326 32-32 32h-192c-17.673 0-32-14.326-32-32zM144 800c-17.673 0-32 14.326-32 32s14.327 32 32 32h192c17.674 0 32-14.326 32-32s-14.326-32-32-32h-192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["move-to-the-queue"],"defaultCode":59791,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1063,"name":"move-to-the-queue","prevSize":32,"id":151,"code":59791},"setIdx":0,"setId":6,"iconIdx":151},{"icon":{"paths":["M809.002 166.758c7.782 6.063 12.333 15.377 12.333 25.242v448h-0.112c0.074 1.734 0.112 3.478 0.112 5.229 0 69.053-57.309 125.030-128 125.030-70.694 0-128-55.978-128-125.030s57.306-125.030 128-125.030c23.312 0 45.171 6.090 64 16.73v-303.86l-384 96.798v409.136c0 69.053-57.309 125.037-128.001 125.037s-128-55.978-128-125.030c0-69.050 57.308-125.027 128-125.027 23.314 0 45.173 6.086 64 16.726v-325.777c0-14.66 9.962-27.446 24.177-31.029l448-112.93c9.568-2.411 19.709-0.276 27.491 5.788z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["musical-note"],"defaultCode":59792,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1064,"name":"musical-note","prevSize":32,"id":152,"code":59792},"setIdx":0,"setId":6,"iconIdx":152},{"icon":{"paths":["M208 176c-35.346 0-64 28.654-64 64v576c0 35.347 28.654 64 64 64h576c35.347 0 64-28.653 64-64v-576c0-35.346-28.653-64-64-64h-576zM208 240h576v576h-576v-576zM698.627 558.15c-0.189 17.674-14.669 31.846-32.339 31.658-17.674-0.189-31.846-14.669-31.658-32.339l1.318-123.594-309.341 308.774c-12.51 12.483-32.771 12.464-45.256-0.042-12.485-12.509-12.467-32.771 0.042-45.258l309.195-308.624-123.382 1.315c-17.674 0.189-32.154-13.984-32.339-31.654-0.189-17.674 13.984-32.15 31.654-32.339l201.92-2.157c8.605-0.093 16.886 3.286 22.97 9.37 6.086 6.086 9.462 14.365 9.373 22.97l-2.157 201.92z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["new-window"],"defaultCode":59793,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1065,"name":"new-window","prevSize":32,"id":153,"code":59793},"setIdx":0,"setId":6,"iconIdx":153},{"icon":{"paths":["M601.331 808.928h-174.154c0.003 48.090 38.989 87.072 87.078 87.072s87.075-38.982 87.075-87.072zM815.597 731.677c7.274 9.696 8.442 22.669 3.021 33.51s-16.499 17.69-28.621 17.69h-565.996c-12.943 0-24.611-7.798-29.564-19.757-4.953-11.955-2.215-25.718 6.937-34.87l51.653-51.654v-274.032c0-144.272 116.957-261.228 261.229-261.228s261.229 116.956 261.229 261.228v275.629l40.112 53.485zM711.485 715.894v-313.331c0-108.926-88.304-197.228-197.229-197.228-108.928 0-197.229 88.302-197.229 197.228v313.331h394.458z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["notification"],"defaultCode":59795,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1066,"name":"notification","prevSize":32,"id":154,"code":59795},"setIdx":0,"setId":6,"iconIdx":154},{"icon":{"paths":["M781.837 402.634c0-5.245-0.154-10.454-0.461-15.622l-63.539 63.539v265.363h-265.363l-66.979 66.979h425.363c12.944 0 24.611-7.795 29.565-19.754 4.954-11.955 2.214-25.722-6.938-34.874l-51.648-51.648v-273.984zM704.765 217.373l-45.254 45.255c-35.638-35.351-84.704-57.189-138.867-57.189-108.909 0-197.194 88.287-197.194 197.195v196.054l-64.001 64v-260.054c0-144.254 116.941-261.195 261.194-261.195 71.837 0 136.899 29.001 184.122 75.934zM433.578 808.934c0 48.086 38.982 87.066 87.066 87.066s87.066-38.979 87.066-87.066h-174.131zM854.275 190.982c-11.334-11.334-29.709-11.334-41.043 0l-612.732 612.733c-11.333 11.331-11.333 29.709 0 41.040 11.334 11.334 29.709 11.334 41.043 0l612.732-612.731c11.334-11.333 11.334-29.709 0-41.043z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["notification-disabled"],"defaultCode":59794,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1067,"name":"notification-disabled","prevSize":32,"id":155,"code":59794},"setIdx":0,"setId":6,"iconIdx":155},{"icon":{"paths":["M712.051 512.675v54.89c-0.195 76.736-43.741 143.283-107.44 176.445-5.53-25.67-28.362-44.906-55.683-44.906h-72.502c-31.459 0-56.963 25.501-56.963 56.963v41.427c0 31.462 25.504 56.963 56.963 56.963h72.502c28.509 0 52.128-20.944 56.307-48.288 69.261-26.829 123.962-82.883 148.966-153.030 4.723 1.27 9.69 1.946 14.813 1.946h28.483c31.459 0 56.963-25.504 56.963-56.963v-85.446c0-31.459-25.504-56.963-56.963-56.963h-28.483v-28.483c0-141.572-114.765-256.338-256.336-256.338s-256.339 114.766-256.339 256.338v23.302h-28.483c-31.46 0-56.964 25.504-56.964 56.966v103.571c0 31.459 25.504 56.963 56.964 56.963h28.482c31.46 0 56.964-25.504 56.964-56.963v-36.253h0.149c-0.099-2.576-0.148-5.165-0.148-7.766v-139.821c0-110.111 89.263-199.374 199.375-199.374s199.373 89.263 199.373 199.374v85.446z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["omnichannel"],"defaultCode":59796,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1068,"name":"omnichannel","prevSize":32,"id":156,"code":59796},"setIdx":0,"setId":6,"iconIdx":156},{"icon":{"paths":["M705.578 633.158c9.507-9.235 24.701-9.018 33.939 0.486 9.238 9.507 9.021 24.701-0.486 33.939l-208.275 202.387c-9.312 9.050-24.138 9.050-33.45 0l-208.276-202.387c-9.506-9.238-9.724-24.432-0.487-33.939 9.237-9.504 24.432-9.722 33.937-0.486l191.549 186.134 191.549-186.134zM705.578 411.584c9.507 9.238 24.701 9.021 33.939-0.486s9.021-24.701-0.486-33.939l-208.275-202.385c-9.312-9.051-24.138-9.051-33.45 0l-208.276 202.385c-9.506 9.238-9.724 24.432-0.487 33.939 9.237 9.504 24.432 9.725 33.937 0.486l191.549-186.134 191.549 186.134z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["order"],"defaultCode":59797,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1069,"name":"order","prevSize":32,"id":157,"code":59797},"setIdx":0,"setId":6,"iconIdx":157},{"icon":{"paths":["M742.317 652.566c12.666-12.323 12.944-32.582 0.618-45.248-12.323-12.669-32.582-12.944-45.251-0.621l44.634 45.869zM512 832.019l-22.317 22.934c12.422 12.086 32.211 12.086 44.634 0l-22.317-22.934zM326.317 606.698c-12.667-12.323-32.927-12.048-45.252 0.621-12.324 12.666-12.047 32.925 0.619 45.248l44.632-45.869zM697.683 606.698l-208 202.387 44.634 45.869 208-202.387-44.634-45.869zM534.317 809.085l-208-202.387-44.632 45.869 207.999 202.387 44.634-45.869z","M742.317 371.456c12.666 12.323 12.944 32.582 0.618 45.251-12.323 12.666-32.582 12.944-45.251 0.618l44.634-45.869zM512 192.004l-22.317-22.935c12.422-12.087 32.211-12.087 44.634 0l-22.317 22.935zM326.317 417.325c-12.668 12.326-32.927 12.048-45.252-0.618-12.325-12.669-12.048-32.928 0.619-45.251l44.633 45.869zM697.683 417.325l-208-202.386 44.634-45.87 208 202.387-44.634 45.869zM534.317 214.939l-208 202.386-44.633-45.869 207.999-202.387 44.634 45.87z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":9}]},"tags":["ordering-ascending"],"defaultCode":59798,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":1070,"name":"ordering-ascending","prevSize":32,"codes":[59798,59799],"id":158,"code":59798},"setIdx":0,"setId":6,"iconIdx":158},{"icon":{"paths":["M281.684 371.434c-12.667 12.323-12.944 32.582-0.619 45.248 12.324 12.669 32.584 12.944 45.252 0.621l-44.633-45.869zM512 191.981l22.317-22.935c-12.422-12.087-32.211-12.087-44.634 0l22.317 22.935zM697.683 417.302c12.669 12.323 32.928 12.048 45.251-0.621 12.326-12.666 12.048-32.925-0.618-45.248l-44.634 45.869zM326.317 417.302l208-202.387-44.634-45.869-207.999 202.387 44.633 45.869zM489.683 214.916l208 202.387 44.634-45.869-208-202.387-44.634 45.869z","M281.684 652.544c-12.667-12.323-12.944-32.582-0.619-45.251 12.324-12.666 32.584-12.944 45.252-0.618l-44.633 45.869zM512 831.997l22.317 22.934c-12.422 12.086-32.211 12.086-44.634 0l22.317-22.934zM697.683 606.675c12.669-12.326 32.928-12.048 45.251 0.618 12.326 12.669 12.048 32.928-0.618 45.251l-44.634-45.869zM326.317 606.675l208 202.384-44.634 45.872-207.999-202.387 44.633-45.869zM489.683 809.059l208-202.384 44.634 45.869-208 202.387-44.634-45.872z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":9}]},"tags":["ordering-descending"],"defaultCode":59800,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":1071,"name":"ordering-descending","prevSize":32,"codes":[59800,59801],"id":159,"code":59800},"setIdx":0,"setId":6,"iconIdx":159},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352-194.405 0-352.001 157.596-352.001 352s157.596 352 352.001 352c194.403 0 352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416-229.752 0-416.001-186.25-416.001-416s186.25-416 416.001-416c229.75 0 416 186.25 416 416zM399.997 383.994v256c0 17.674 14.326 32 32 32s32-14.326 32-32v-256c0-17.67-14.326-32-32-32s-32 14.33-32 32zM559.997 383.994v256c0 17.674 14.326 32 32 32s32-14.326 32-32v-256c0-17.67-14.326-32-32-32s-32 14.33-32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pause"],"defaultCode":59803,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1072,"name":"pause","prevSize":32,"id":160,"code":59803},"setIdx":0,"setId":6,"iconIdx":160},{"icon":{"paths":["M512 928c229.75 0 416-186.25 416-416s-186.25-416-416-416c-229.752 0-416.001 186.25-416.001 416s186.25 416 416.001 416zM399.997 383.994c0-17.67 14.326-32 32-32s32 14.33 32 32v256c0 17.674-14.326 32-32 32s-32-14.326-32-32v-256zM559.997 383.994c0-17.67 14.326-32 32-32s32 14.33 32 32v256c0 17.674-14.326 32-32 32s-32-14.326-32-32v-256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pause-filled"],"defaultCode":59802,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1073,"name":"pause-filled","prevSize":32,"id":161,"code":59802},"setIdx":0,"setId":6,"iconIdx":161},{"icon":{"paths":["M822.627 201.372c12.496 12.497 12.496 32.758 0 45.255l-576 576c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l576-576c12.496-12.497 32.758-12.497 45.254 0z","M192 320c0-70.692 57.308-128 128-128 70.691 0 128 57.308 128 128 0 70.691-57.309 128-128 128-70.692 0-128-57.309-128-128zM320 256c-35.346 0-64 28.654-64 64s28.654 64 64 64c35.347 0 64-28.653 64-64s-28.653-64-64-64z","M704 576c-70.691 0-128 57.309-128 128s57.309 128 128 128c70.691 0 128-57.309 128-128s-57.309-128-128-128zM640 704c0-35.347 28.653-64 64-64s64 28.653 64 64c0 35.347-28.653 64-64 64s-64-28.653-64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["percentage"],"defaultCode":59777,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1074,"id":162,"name":"percentage","prevSize":32,"code":59777},"setIdx":0,"setId":6,"iconIdx":162},{"icon":{"paths":["M410.502 204.616c-10.419-21.362-34.202-37.856-62.189-33.137-38.104 6.425-88.825 25.194-126.247 57.060-18.972 16.155-35.817 36.795-44.757 62.246-9.15 26.048-9.211 54.919 2.087 85.195 21.202 56.816 60.513 117.456 97.761 167.264 37.482 50.122 74.609 91.552 93.329 110.269l44.173-44.173c-16.406-16.403-51.6-55.536-87.472-103.51-36.11-48.285-71.192-103.264-89.264-151.69-6.437-17.248-5.748-31.056-1.675-42.651 4.283-12.192 13.134-24.16 26.319-35.388 25.849-22.012 63.292-36.814 92.623-42.392l59.075 121.097c0.019 0.074 0.045 0.285-0.013 0.688-0.112 0.749-0.502 1.827-1.344 2.883-7.117 8.95-14.899 20-20.941 31.741-5.674 11.024-11.715 26.246-10.976 42.47 0.643 14.138 7.76 27.773 13.222 36.973 6.275 10.576 14.416 21.741 22.79 32.291 16.806 21.171 36.541 42.326 49.68 55.466l44.173-44.173c-11.952-11.952-29.981-31.309-44.928-50.134-7.504-9.453-13.738-18.157-17.997-25.334-2.87-4.838-3.984-7.578-4.387-8.57l-0.038-0.093c0.266-1.382 1.139-4.736 4.006-10.31 3.552-6.902 8.717-14.438 14.291-21.443 14.611-18.374 20.518-45.424 8.611-69.837l-59.914-122.808zM819.386 613.504c21.36 10.419 37.856 34.202 33.136 62.189-6.426 38.106-25.194 88.826-57.059 126.246-16.157 18.973-36.797 35.818-62.246 44.758-26.048 9.149-54.922 9.21-85.197-2.086-56.813-21.203-117.453-60.515-167.261-97.763-50.122-37.482-91.555-74.608-110.272-93.328l44.173-44.173c16.403 16.406 55.539 51.6 103.51 87.472 48.285 36.109 103.267 71.194 151.69 89.264 17.248 6.435 31.056 5.747 42.653 1.674 12.192-4.282 24.16-13.133 35.386-26.317 22.013-25.85 36.816-63.293 42.394-92.624l-121.094-59.075c-0.077-0.019-0.288-0.048-0.688 0.013-0.752 0.112-1.83 0.502-2.886 1.344-8.95 7.117-20 14.899-31.741 20.941-11.024 5.674-26.246 11.715-42.47 10.976-14.134-0.643-27.773-7.76-36.973-13.222-10.576-6.275-21.741-14.416-32.288-22.79-21.174-16.806-42.33-36.541-55.469-49.68l44.173-44.173c11.952 11.952 31.309 29.981 50.134 44.928 9.453 7.504 18.16 13.738 25.334 17.997 4.838 2.87 7.578 3.984 8.57 4.387l0.093 0.038c1.382-0.266 4.739-1.139 10.314-4.006 6.899-3.552 14.435-8.717 21.44-14.291 18.374-14.611 45.427-20.518 69.837-8.611l122.81 59.914z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone"],"defaultCode":59806,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1075,"name":"phone","prevSize":32,"id":163,"code":59806},"setIdx":0,"setId":6,"iconIdx":163},{"icon":{"paths":["M825.373 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672-672zM575.613 569.069l-44.707 44.707c7.846 5.904 15.846 11.453 23.533 16.016 9.2 5.459 22.838 12.579 36.973 13.222 16.224 0.736 31.446-5.302 42.47-10.976 11.741-6.042 22.79-13.824 31.744-20.944 1.053-0.838 2.134-1.232 2.883-1.341 0.403-0.061 0.611-0.032 0.688-0.013l121.094 59.075c-5.578 29.331-20.381 66.771-42.39 92.621-11.229 13.187-23.197 22.038-35.389 26.32-11.597 4.074-25.402 4.762-42.653-1.677-48.422-18.070-103.405-53.152-151.69-89.261-14.026-10.49-27.299-20.922-39.469-30.842l-44.387 44.39c14.186 11.683 29.84 24.061 46.445 36.48 49.808 37.248 110.448 76.56 167.261 97.76 30.275 11.299 59.149 11.238 85.197 2.086 25.45-8.938 46.090-25.786 62.246-44.755 31.866-37.424 50.634-88.144 57.059-126.246 4.72-27.987-11.776-51.77-33.136-62.192l-122.81-59.91c-24.41-11.907-51.462-6-69.834 8.611-7.008 5.571-14.544 10.739-21.443 14.291-5.574 2.867-8.931 3.741-10.314 4.003l-0.093-0.038c-0.992-0.4-3.731-1.514-8.57-4.387-3.277-1.942-6.87-4.301-10.71-7.002zM313.636 589.683l44.389-44.387c-9.92-12.17-20.349-25.44-30.838-39.466-36.109-48.285-71.192-103.267-89.263-151.69-6.437-17.251-5.748-31.056-1.675-42.652 4.283-12.192 13.134-24.16 26.319-35.388 25.849-22.012 63.291-36.814 92.622-42.392l59.075 121.095c0.019 0.077 0.048 0.285-0.013 0.688-0.109 0.752-0.502 1.83-1.341 2.883-7.12 8.954-14.902 20.003-20.944 31.744-5.674 11.024-11.715 26.246-10.976 42.47 0.643 14.134 7.763 27.773 13.222 36.973 4.563 7.686 10.109 15.683 16.013 23.53l44.707-44.707c-2.701-3.837-5.056-7.434-7.002-10.707-2.87-4.838-3.984-7.578-4.387-8.57l-0.038-0.093c0.266-1.382 1.139-4.739 4.006-10.314 3.552-6.899 8.72-14.435 14.291-21.443 14.611-18.371 20.518-45.424 8.611-69.834l-59.91-122.809c-10.422-21.362-34.205-37.856-62.192-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.757 62.246-9.15 26.048-9.211 54.921 2.087 85.196 21.202 56.813 60.513 117.453 97.761 167.261 12.417 16.605 24.795 32.256 36.478 46.442z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone-disabled"],"defaultCode":59804,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1076,"name":"phone-disabled","prevSize":32,"id":164,"code":59804},"setIdx":0,"setId":6,"iconIdx":164},{"icon":{"paths":["M801.123 657.59c22.474 7.734 50.954 2.582 67.408-20.544 22.4-31.488 44.992-80.624 48.922-129.619 1.99-24.838-0.691-51.344-12.368-75.661-11.949-24.89-32.32-45.35-61.718-58.768-55.165-25.181-125.84-40.262-187.398-49.146-61.946-8.936-117.494-11.98-143.965-11.98v62.469c23.2 0 75.757 2.787 135.043 11.341 59.677 8.611 123.36 22.682 170.381 44.144 16.749 7.645 26.022 17.894 31.344 28.973 5.59 11.651 7.795 26.371 6.413 43.635-2.717 33.843-18.723 70.784-35.52 95.469l-127.398-43.853c-0.067-0.042-0.237-0.17-0.48-0.496-0.451-0.608-0.934-1.651-1.088-2.989-1.296-11.363-3.606-24.678-7.635-37.254-3.786-11.808-10.278-26.842-22.272-37.792-10.451-9.539-25.126-14.15-35.494-16.794-11.914-3.040-25.568-5.181-38.944-6.717-26.858-3.088-55.773-4.093-74.352-4.093v62.47c16.902 0 43.338 0.938 67.219 3.683 11.99 1.379 22.554 3.123 30.64 5.187 5.45 1.389 8.173 2.541 9.162 2.957l0.093 0.038c0.79 1.165 2.544 4.154 4.458 10.125 2.368 7.392 4.045 16.374 5.059 25.267 2.659 23.325 17.61 46.63 43.29 55.469l129.203 44.477zM222.875 657.584c-22.474 7.738-50.954 2.586-67.407-20.544-22.4-31.485-44.993-80.621-48.922-129.616-1.992-24.838 0.691-51.344 12.366-75.664 11.949-24.886 32.321-45.347 61.719-58.765 55.165-25.181 125.841-40.262 187.4-49.146 61.946-8.937 117.494-11.98 143.965-11.98v62.47c-23.2 0-75.757 2.787-135.046 11.341-59.674 8.608-123.358 22.682-170.378 44.144-16.748 7.645-26.024 17.894-31.343 28.973-5.593 11.651-7.797 26.371-6.412 43.635 2.714 33.843 18.721 70.784 35.518 95.469l127.4-43.856c0.067-0.038 0.234-0.166 0.477-0.493 0.454-0.611 0.938-1.651 1.091-2.989 1.296-11.363 3.606-24.682 7.635-37.254 3.786-11.808 10.275-26.842 22.272-37.792 10.448-9.542 25.126-14.15 35.491-16.794 11.917-3.040 25.568-5.181 38.947-6.717 26.858-3.088 55.77-4.093 74.349-4.093v62.47c-16.899 0-43.338 0.938-67.216 3.683-11.99 1.376-22.554 3.123-30.64 5.187-5.453 1.389-8.176 2.541-9.162 2.957l-0.093 0.038c-0.79 1.162-2.547 4.154-4.458 10.125-2.371 7.389-4.045 16.371-5.059 25.267-2.659 23.322-17.61 46.627-43.293 55.469l-129.202 44.474z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone-end"],"defaultCode":59805,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1077,"name":"phone-end","prevSize":32,"id":165,"code":59805},"setIdx":0,"setId":6,"iconIdx":165},{"icon":{"paths":["M717.254 352l137.37-137.372c12.499-12.497 12.499-32.758 0-45.255-12.496-12.497-32.755-12.497-45.254 0l-137.373 137.373v-82.745c0-17.673-14.326-32-32-32-17.67 0-32 14.327-32 32v160c0 4.339 0.864 8.477 2.429 12.25 1.526 3.686 3.773 7.149 6.736 10.166 0.138 0.141 0.278 0.282 0.419 0.419 3.018 2.966 6.48 5.21 10.17 6.736 3.773 1.565 7.91 2.429 12.246 2.429h160c17.674 0 32-14.326 32-32s-14.326-32-32-32h-82.742z","M819.478 613.379l-122.88-59.84c-11.261-5.29-23.786-7.283-36.128-5.757-12.346 1.53-24.003 6.522-33.632 14.397-6.816 5.274-13.978 10.086-21.44 14.4-3.382 1.632-6.922 2.918-10.56 3.84-3.008-1.235-5.901-2.736-8.64-4.48-8.752-5.504-17.19-11.488-25.28-17.92-18.88-15.040-38.080-32-50.24-44.8s-29.76-32-44.8-50.24c-6.435-8.093-12.416-16.531-17.92-25.28-1.747-2.742-3.248-5.635-4.48-8.64 0.918-3.642 2.205-7.181 3.84-10.56 4.314-7.462 9.123-14.627 14.4-21.44 7.875-9.629 12.864-21.29 14.394-33.635 1.53-12.342-0.467-24.867-5.754-36.125l-59.84-122.881c-5.635-11.286-14.73-20.477-25.952-26.234-11.226-5.756-23.997-7.776-36.448-5.766-46.072 7.753-89.44 27.015-126.081 56-20.379 16.952-35.847 39.050-44.8 64-9.479 27.726-8.684 57.931 2.24 85.121 25.032 59.536 57.851 115.491 97.6 166.4 28.686 38.71 59.902 75.485 93.441 110.080 34.406 33.296 70.966 64.298 109.44 92.8 51.203 39.821 107.485 72.643 167.36 97.6 27.158 11.066 57.418 11.862 85.12 2.24 24.368-9.203 45.888-24.653 62.4-44.8 29.328-36.544 48.925-79.92 56.96-126.080 1.984-12.49-0.083-25.286-5.901-36.515-5.814-11.229-15.075-20.301-26.419-25.885zM747.798 761.219c-9.187 11.802-21.331 20.963-35.2 26.56-14.051 4.416-29.197 3.85-42.88-1.6-54.202-23.091-105.187-53.101-151.68-89.28-35.83-27.52-69.923-57.232-102.080-88.96-31.334-32.611-60.618-67.13-87.68-103.36-36.201-46.426-66.113-97.427-88.961-151.68-5.832-13.587-6.514-28.829-1.92-42.881 5.595-13.87 14.757-26.014 26.56-35.2 26.691-20.806 57.953-34.956 91.201-41.28l60.8 121.281c0.154 0.954 0.154 1.926 0 2.88-7.933 9.981-14.899 20.698-20.8 32-7.347 12.966-11.101 27.658-10.88 42.56 1.354 13.142 5.853 25.763 13.12 36.8 6.934 11.104 14.522 21.789 22.72 32 16.96 21.12 36.48 42.56 49.6 55.68s34.56 32 55.68 49.6c10.208 8.198 20.893 15.782 32 22.72 11.034 7.264 23.658 11.763 36.8 13.12 14.899 0.218 29.59-3.536 42.56-10.88 11.302-5.904 22.016-12.867 32-20.8 0.851-0.707 1.827-1.251 2.88-1.6l118.72 59.84c-6.509 33.811-21.11 65.542-42.56 92.48z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["phone-in"],"grid":0},"attrs":[{},{}],"properties":{"order":1078,"id":166,"name":"phone-in","prevSize":32,"code":59809},"setIdx":0,"setId":6,"iconIdx":166},{"icon":{"paths":["M649.373 137.372c12.496-12.497 32.758-12.497 45.254 0l73.373 73.373 73.373-73.373c12.499-12.497 32.758-12.497 45.254 0 12.499 12.497 12.499 32.758 0 45.255l-73.373 73.372 73.373 73.373c12.499 12.496 12.499 32.758 0 45.254-12.496 12.496-32.755 12.496-45.254 0l-73.373-73.372-73.373 73.372c-12.496 12.496-32.755 12.496-45.254 0-12.496-12.496-12.496-32.758 0-45.254l73.373-73.373-73.373-73.372c-12.496-12.497-12.496-32.758 0-45.255zM361.062 167.708c28.672-4.835 53.037 12.064 63.712 33.949l61.379 125.818c12.202 25.008 6.147 52.72-8.822 71.546-5.706 7.178-11.002 14.899-14.64 21.968-2.938 5.712-3.834 9.149-4.102 10.563 0.378 0.928 1.494 3.754 4.534 8.877 4.362 7.35 10.749 16.269 18.438 25.952 15.312 19.29 33.782 39.12 46.026 51.363s32.077 30.717 51.363 46.029c9.683 7.69 18.602 14.077 25.955 18.442 5.12 3.040 7.946 4.154 8.874 4.534 1.414-0.272 4.854-1.165 10.563-4.106 7.069-3.638 14.79-8.931 21.968-14.64 18.822-14.97 46.538-21.021 71.546-8.822l125.818 61.379c21.885 10.678 38.784 35.040 33.949 63.715-6.582 39.037-25.811 90.998-58.458 129.338-16.55 19.437-37.696 36.694-63.773 45.856-26.685 9.373-56.266 9.437-87.283-2.141-58.205-21.722-120.33-61.997-171.36-100.16-51.347-38.4-93.795-76.438-112.973-95.616s-57.213-61.622-95.613-112.973c-38.16-51.027-78.435-113.152-100.156-171.357-11.575-31.018-11.513-60.598-2.138-87.284 9.159-26.075 26.417-47.22 45.854-63.771 38.339-32.647 90.303-51.876 129.34-58.458zM368.106 231.463c-30.048 5.715-68.407 20.88-94.89 43.431-13.508 11.503-22.577 23.764-26.964 36.255-4.173 11.878-4.878 26.025 1.716 43.696 18.514 49.61 54.456 105.939 91.45 155.408 36.752 49.146 72.806 89.238 89.613 106.045 16.81 16.81 56.902 52.864 106.048 89.619 49.469 36.995 105.798 72.938 155.408 91.453 17.67 6.592 31.818 5.888 43.696 1.715 12.49-4.387 24.752-13.456 36.256-26.963 22.55-26.483 37.715-64.842 43.43-94.893l-124.064-60.522c-0.077-0.019-0.291-0.048-0.704 0.013-0.768 0.112-1.875 0.515-2.954 1.376-9.171 7.293-20.493 15.264-32.518 21.456-11.296 5.811-26.89 12-43.514 11.245-14.483-0.659-28.454-7.955-37.878-13.549-10.835-6.432-22.275-14.771-33.082-23.35-21.69-17.222-43.363-37.44-56.822-50.899s-33.677-35.133-50.896-56.826c-8.579-10.803-16.918-22.246-23.35-33.078-5.594-9.427-12.886-23.398-13.546-37.878-0.755-16.624 5.434-32.218 11.245-43.514 6.189-12.026 14.163-23.347 21.456-32.518 0.858-1.078 1.261-2.186 1.376-2.954 0.061-0.413 0.032-0.627 0.013-0.704l-60.525-124.063z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["phone-issue"],"grid":0},"attrs":[{}],"properties":{"order":1079,"id":167,"name":"phone-issue","prevSize":32,"code":59835},"setIdx":0,"setId":6,"iconIdx":167},{"icon":{"paths":["M428.346 199.399c17.542-17.543 45.984-17.543 63.53 0 17.542 17.543 17.542 45.986 0 63.53l-43.661 43.659 177.83 177.828 60.339-60.339c24.992-24.995 65.517-24.995 90.509 0l45.254 45.254-331.869 331.869-45.254-45.254c-24.992-24.995-24.992-65.517 0-90.509l60.339-60.339-177.827-177.83-43.661 43.661c-17.543 17.542-45.987 17.542-63.53 0s-17.543-45.987 0-63.53l208.001-207.999zM175.090 362.144c-42.537 42.538-42.537 111.501 0 154.038 42.001 42.003 109.771 42.531 152.42 1.587l87.334 87.334-15.075 15.075c-49.987 49.987-49.987 131.034 0 181.021l67.882 67.882c12.496 12.496 32.758 12.496 45.254 0l167.936-167.933 88.013 92.003c12.218 12.771 32.474 13.219 45.245 1.002 12.771-12.214 13.219-32.47 1.002-45.242l-88.995-93.030 163.923-163.923c12.499-12.496 12.499-32.758 0-45.254l-67.882-67.882c-49.987-49.987-131.030-49.987-181.018 0l-15.907 15.907-87.325-87.323c41.766-42.596 41.51-110.983-0.768-153.262-42.538-42.537-111.504-42.537-154.042 0l-207.998 208z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pin"],"defaultCode":59808,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1080,"name":"pin","prevSize":32,"id":168,"code":59808},"setIdx":0,"setId":6,"iconIdx":168},{"icon":{"paths":["M512.608 128.019c-72.378-1.376-144.906 25.78-199.307 80.524-54.654 54.999-89.301 136.056-89.301 239.464 0 80.234 44.5 174.87 97.546 252.806 53.066 77.965 120.829 148.157 176.141 175.821l15.194 7.6 14.81-8.326c217.158-122.154 272.31-333.882 272.31-427.898 0-101.731-27.923-181.776-80.179-236.932-52.346-55.248-125.296-81.503-207.213-83.060zM288 448.006c0-88.589 29.353-152.745 70.698-194.351 41.6-41.862 97.072-62.705 152.694-61.648 68.992 1.311 124.038 23.054 161.968 63.088 38.019 40.126 62.64 102.649 62.64 192.914 0 74.55-44.691 253.677-224.176 363.030-39.683-25.61-92.186-79.853-137.37-146.237-50.954-74.864-86.454-156.221-86.454-216.797zM544 416c0-17.674-14.326-32-32-32s-32 14.326-32 32c0 17.674 14.326 32 32 32s32-14.326 32-32zM608 416c0 53.021-42.979 96-96 96s-96-42.979-96-96c0-53.021 42.979-96 96-96s96 42.979 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pin-map"],"defaultCode":59807,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1081,"name":"pin-map","prevSize":32,"id":169,"code":59807},"setIdx":0,"setId":6,"iconIdx":169},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM451.85 357.187l195.254 136.768c14.208 9.949 18.496 30.87 9.581 46.726-2.432 4.326-5.706 7.981-9.581 10.694l-195.254 136.768c-14.208 9.952-32.954 5.165-41.869-10.694-3.037-5.398-4.646-11.642-4.646-18.016v-273.536c0-18.723 13.597-33.898 30.371-33.898 5.709 0 11.306 1.798 16.144 5.187z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["play"],"defaultCode":59811,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1082,"name":"play","prevSize":32,"id":170,"code":59811},"setIdx":0,"setId":6,"iconIdx":170},{"icon":{"paths":["M512 928.003c229.75 0 416-186.25 416-416s-186.25-415.999-416-415.999c-229.75 0-416 186.25-416 415.999s186.25 416 416 416zM451.846 357.19l195.258 136.768c14.205 9.952 18.496 30.874 9.578 46.73-2.429 4.323-5.706 7.978-9.578 10.691l-195.258 136.768c-14.205 9.952-32.95 5.165-41.866-10.691-3.037-5.398-4.646-11.645-4.646-18.019v-273.536c0-18.72 13.597-33.894 30.368-33.894 5.712 0 11.309 1.795 16.144 5.184z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["play-filled"],"defaultCode":59810,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1083,"name":"play-filled","prevSize":32,"id":171,"code":59810},"setIdx":0,"setId":6,"iconIdx":171},{"icon":{"paths":["M325.686 430.88l224.49 224.49-126.118 126.118-224.491-224.49 126.12-126.118zM370.941 385.626l192.115-192.117 224.49 224.491-192.115 192.115-224.49-224.49zM585.683 125.627c-12.496-12.497-32.758-12.497-45.254 0l-408.745 408.745c-12.497 12.496-12.497 32.758 0 45.254l269.746 269.747c5.229 5.229 11.818 8.269 18.63 9.123v0.067h0.57c2.278 0.243 4.576 0.243 6.851 0h440.579c17.674 0 32-14.33 32-32 0-17.674-14.326-32.003-32-32.003h-366.566l353.936-353.933c12.496-12.496 12.496-32.758 0-45.254l-269.747-269.746z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["prune"],"defaultCode":59817,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1084,"name":"prune","prevSize":32,"id":172,"code":59817},"setIdx":0,"setId":6,"iconIdx":172},{"icon":{"paths":["M230.486 636.688c-14.92-9.472-34.694-5.056-44.167 9.862-9.473 14.922-5.057 34.694 9.862 44.166l298.666 189.632c10.47 6.646 23.837 6.646 34.304 0l298.669-189.632c14.918-9.472 19.334-29.245 9.862-44.166-9.475-14.918-29.248-19.334-44.166-9.862l-281.517 178.739-281.514-178.739zM186.319 494.848c9.473-14.922 29.247-19.334 44.167-9.862l281.514 178.739 281.517-178.739c14.918-9.472 34.691-5.059 44.166 9.862 9.472 14.918 5.056 34.694-9.862 44.166l-298.669 189.632c-10.467 6.646-23.834 6.646-34.304 0l-298.666-189.632c-14.92-9.472-19.335-29.248-9.862-44.166zM529.152 143.657l298.669 189.629c9.245 5.872 14.848 16.064 14.848 27.014 0 10.954-5.603 21.146-14.848 27.014l-298.669 189.632c-10.467 6.646-23.834 6.646-34.304 0l-298.666-189.632c-9.246-5.869-14.848-16.061-14.848-27.014 0-10.95 5.602-21.142 14.848-27.014l298.666-189.629c10.47-6.647 23.837-6.647 34.304 0zM273.035 360.301l238.965 151.725 238.966-151.725-238.966-151.724-238.965 151.724z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["queue"],"defaultCode":59818,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1085,"name":"queue","prevSize":32,"id":173,"code":59818},"setIdx":0,"setId":6,"iconIdx":173},{"icon":{"paths":["M161.352 800c-11.706 0-22.477-6.39-28.087-16.666s-5.161-22.79 1.169-32.64l112.304-174.694h-69.387c-17.673 0-32-14.326-32-32v-288c0-17.673 14.327-32 32-32h255.999c17.674 0 32 14.327 32 32v288c0 6.138-1.763 12.144-5.082 17.306l-143.999 224c-5.888 9.158-16.029 14.694-26.918 14.694h-128zM332.269 561.306l-112.304 174.694h51.916l129.469-201.398v-246.602h-191.999v224h96c11.706 0 22.479 6.39 28.085 16.666 5.61 10.275 5.162 22.79-1.168 32.64zM577.35 800c-11.706 0-22.477-6.39-28.086-16.666s-5.162-22.79 1.171-32.64l112.304-174.694h-69.389c-17.67 0-32-14.326-32-32v-288c0-17.673 14.33-32 32-32h256c17.674 0 32 14.327 32 32v288c0 6.138-1.763 12.144-5.082 17.306l-144 224c-5.888 9.158-16.029 14.694-26.918 14.694h-128zM748.269 561.306l-112.304 174.694h51.917l129.469-201.398v-246.602h-192v224h96c11.706 0 22.48 6.39 28.086 16.666 5.61 10.275 5.162 22.79-1.168 32.64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["quote"],"defaultCode":59819,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1086,"name":"quote","prevSize":32,"id":174,"code":59819},"setIdx":0,"setId":6,"iconIdx":174},{"icon":{"paths":["M800 560c0 176.73-143.27 320-320 320-176.731 0-320-143.27-320-320s143.269-320 320-320v-64c-212.077 0-384 171.923-384 384s171.923 384 384 384c212.077 0 384-171.923 384-384 0-10.778-0.445-21.45-1.315-32h-64.266c1.046 10.525 1.581 21.2 1.581 32zM800 128c0-17.673-14.326-32-32-32s-32 14.327-32 32v112h-112c-17.674 0-32 14.327-32 32s14.326 32 32 32h112v112c0 17.674 14.326 32 32 32s32-14.326 32-32v-112h112c17.674 0 32-14.327 32-32s-14.326-32-32-32h-112v-112zM384 528c35.347 0 64-28.653 64-64s-28.653-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64zM640 464c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64zM329.805 605.075c-10.451-14.25-30.477-17.331-44.728-6.88s-17.333 30.477-6.882 44.73c37.658 51.35 77.754 84.624 119.178 102.662 41.741 18.179 82.797 19.99 120.362 11.651 73.469-16.307 132.211-70.87 164.070-114.314 10.451-14.253 7.37-34.278-6.88-44.73-14.253-10.451-34.278-7.37-44.73 6.88-26.81 36.557-73.664 77.994-126.33 89.686-25.501 5.661-52.643 4.474-80.938-7.85-28.608-12.461-60.381-37.187-93.123-81.837z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["reaction-add"],"defaultCode":59820,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1087,"name":"reaction-add","prevSize":32,"id":175,"code":59820},"setIdx":0,"setId":6,"iconIdx":175},{"icon":{"paths":["M832 512c0-176.73-143.27-320-320-320s-320 143.27-320 320c0 176.73 143.27 320 320 320s320-143.27 320-320zM896 512c0 212.077-171.923 384-384 384s-384-171.923-384-384c0-212.077 171.923-384 384-384s384 171.923 384 384zM512 704c-106.038 0-192-85.962-192-192s85.962-192 192-192c106.038 0 192 85.962 192 192s-85.962 192-192 192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["record"],"defaultCode":59821,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1088,"name":"record","prevSize":32,"id":176,"code":59821},"setIdx":0,"setId":6,"iconIdx":176},{"icon":{"paths":["M896 512h-63.984c0-175.414-145.754-320-328.518-320-115.27 0-215.818 57.513-274.362 144h110.768c17.674 0 32 14.326 32 32s-14.326 32-32 32h-179.904c-17.673 0-32-14.326-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v102.32c71.751-91.401 184.589-150.32 311.498-150.32 216.781 0 392.502 171.923 392.502 384 0 1.114 0.010 2.227 0 3.338v-3.338z","M127.997 512h63.986c0 175.414 145.751 320 328.519 320 115.27 0 215.818-57.514 274.358-144h-110.768c-17.67 0-32-14.326-32-32s14.33-32 32-32h179.907c17.67 0 32 14.326 32 32v192c0 17.674-14.33 32-32 32-17.674 0-32-14.326-32-32v-102.32c-71.754 91.402-184.592 150.32-311.498 150.32-216.782 0-392.505-171.923-392.505-384 0-1.082-0.009-2.166 0-3.245v3.245z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["refresh"],"defaultCode":59822,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1089,"name":"refresh","prevSize":32,"id":177,"code":59822},"setIdx":0,"setId":6,"iconIdx":177},{"icon":{"paths":["M565.802 233.862l-97.261 97.261h-187.521l-0.456 0.003c-14.696 0.208-28.717 6.186-39.042 16.637l-97.095 96.797-0.048 0.048c-7.165 7.174-12.248 16.157-14.707 25.994-2.459 9.834-2.202 20.154 0.745 29.856 2.946 9.699 8.471 18.419 15.984 25.226 7.506 6.8 16.746 11.443 26.678 13.424l125.65 25.19c5.103 1.024 10.166 0.771 14.859-0.538l162.866 162.867c1.987 1.987 4.17 3.654 6.483 5.011l22.88 114.128c1.981 9.936 6.618 19.146 13.418 26.653 6.81 7.514 15.526 13.037 25.229 15.984s20.019 3.203 29.856 0.746c9.837-2.461 18.819-7.542 25.994-14.707l96.842-97.146c10.451-10.323 16.432-24.346 16.64-39.040l0.003-0.454v-193.802c0-2.893-0.384-5.693-1.104-8.358l77.443-77.44c110.522-110.525 110.474-223.191 103.152-273.759-1.862-13.592-8.122-26.204-17.824-35.908s-22.317-15.962-35.907-17.823c-50.57-7.321-163.235-7.371-273.757 103.151zM611.056 279.117c92.138-92.138 182.144-90.373 218.947-85.121 5.254 36.804 7.018 126.811-85.12 218.948l-245.798 245.802-133.83-133.827 245.802-245.802zM404.541 395.123l-104.222 104.221-100.071-20.064 84.42-84.157h119.873zM542.89 705.446l106.909-106.906v135.61l-84.16 84.422-22.266-111.062c-0.138-0.698-0.301-1.386-0.483-2.064z","M286.325 699.699c15.297-8.851 20.524-28.426 11.674-43.725-8.85-15.296-28.426-20.522-43.723-11.674-49.486 28.63-72.438 77.786-83.25 115.523-5.52 19.267-8.252 36.813-9.619 49.539-0.687 6.397-1.037 11.661-1.217 15.424-0.090 1.885-0.137 3.402-0.162 4.499l-0.023 1.334-0.004 0.422-0.001 0.15v0.083c0 8.486 3.372 16.65 9.372 22.65 6.001 6.003 14.14 9.373 22.628 9.373v-32c0 32 0.037 32 0.048 32h0.208l0.424-0.003 1.333-0.022c1.099-0.026 2.614-0.074 4.498-0.163 3.764-0.179 9.029-0.528 15.425-1.216 12.727-1.366 30.272-4.099 49.54-9.619 37.739-10.813 86.892-33.763 115.523-83.251 8.851-15.296 3.622-34.87-11.674-43.722s-34.874-3.626-43.725 11.674c-16.669 28.813-47.164 45.011-77.751 53.776-6.095 1.744-12.005 3.139-17.55 4.25 1.111-5.546 2.505-11.456 4.251-17.549 8.763-30.589 24.961-61.085 53.775-77.754zM192 831.299l-32-0.022c0 0.013 0 0.022 32 0.022z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["rocket"],"defaultCode":59816,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1090,"id":178,"name":"rocket","prevSize":32,"code":59816},"setIdx":0,"setId":6,"iconIdx":178},{"icon":{"paths":["M713.718 450.362c0-142.689-115.824-258.362-258.701-258.362-142.878 0-258.704 115.673-258.704 258.362 0 142.691 115.826 258.365 258.704 258.365 142.877 0 258.701-115.674 258.701-258.365zM659.302 699.965c-55.645 45.475-126.774 72.762-204.285 72.762-178.271 0-322.788-144.326-322.788-322.365 0-178.035 144.517-322.362 322.788-322.362 178.269 0 322.787 144.327 322.787 322.362 0 77.408-27.318 148.442-72.854 204.013l186.838 186.592c12.608 12.589 12.608 33.002 0 45.59-12.605 12.589-33.043 12.589-45.648 0l-186.838-186.592z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["search"],"defaultCode":59823,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1091,"name":"search","prevSize":32,"id":179,"code":59823},"setIdx":0,"setId":6,"iconIdx":179},{"icon":{"paths":["M878.022 192.974c7.85 9.521 9.526 22.708 4.31 33.891l-298.669 640.002c-5.69 12.195-18.403 19.526-31.811 18.342-13.405-1.184-24.637-10.627-28.106-23.632l-81.619-306.070-285.772-142.886c-11.978-5.987-18.959-18.8-17.498-32.112s11.056-24.307 24.048-27.552l682.665-170.668c11.974-2.993 24.598 1.165 32.451 10.686zM505.821 545.968l57.082 214.051 233.027-499.35-533.58 133.395 203.606 101.802 69.51-52.131c14.141-10.605 34.198-7.741 44.8 6.4 10.605 14.138 7.741 34.195-6.4 44.8l-68.045 51.034z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["send"],"defaultCode":59825,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1092,"name":"send","prevSize":32,"id":180,"code":59825},"setIdx":0,"setId":6,"iconIdx":180},{"icon":{"paths":["M891.494 238.96l-297.475 637.446c-16.854 36.115-69.622 31.459-79.891-7.050l-66-247.498 151.248-189.059-219.994 109.997-226.833-113.418c-35.43-17.715-29.696-69.949 8.733-79.555l681.197-170.3c34.842-8.71 64.202 26.892 49.014 59.436z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["send-filled"],"defaultCode":59824,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1093,"name":"send-filled","prevSize":32,"id":181,"code":59824},"setIdx":0,"setId":6,"iconIdx":181},{"icon":{"paths":["M421.334 256c0-44.183-35.818-80-80-80s-80 35.817-80 80c0 44.183 35.817 80 80 80s80-35.817 80-80zM465.302 288c-14.211 55.206-64.326 96-123.968 96-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.327-32-32s14.327-32 32-32h89.367c14.209-55.207 64.324-96 123.968-96 59.642 0 109.757 40.793 123.968 96h430.698c17.674 0 32 14.327 32 32s-14.326 32-32 32h-430.698zM96 768c0-17.674 14.327-32 32-32h89.367c14.209-55.206 64.324-96 123.968-96 60.781 0 111.67 42.365 124.742 99.181 4.208-2.038 8.934-3.181 13.923-3.181h416c17.674 0 32 14.326 32 32s-14.326 32-32 32h-416c-4.989 0-9.715-1.142-13.923-3.181-13.072 56.816-63.962 99.181-124.742 99.181-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.326-32-32zM341.334 848c44.182 0 80-35.818 80-80s-35.818-80-80-80c-44.183 0-80 35.818-80 80s35.817 80 80 80zM796.029 543.757c-14.122 55.331-64.298 96.243-124.029 96.243s-109.904-40.912-124.029-96.243c-1.302 0.16-2.627 0.243-3.971 0.243h-416c-17.673 0-32-14.326-32-32s14.327-32 32-32h416c1.344 0 2.669 0.083 3.971 0.243 14.125-55.331 64.298-96.243 124.029-96.243s109.907 40.912 124.029 96.243c1.302-0.16 2.627-0.243 3.971-0.243h96c17.674 0 32 14.326 32 32s-14.326 32-32 32h-96c-1.344 0-2.669-0.083-3.971-0.243zM752 512c0-44.182-35.818-80-80-80s-80 35.818-80 80c0 44.182 35.818 80 80 80s80-35.818 80-80z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["settings"],"defaultCode":59826,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1094,"name":"settings","prevSize":32,"id":182,"code":59826},"setIdx":0,"setId":6,"iconIdx":182},{"icon":{"paths":["M690.176 301.708c11.645-11.977 11.645-31.396 0-43.374l-149.091-153.351c-11.645-11.977-30.525-11.977-42.17 0l-149.091 153.351c-11.645 11.977-11.645 31.397 0 43.374s30.525 11.978 42.17 0l98.189-100.993v401.343c0 16.938 13.35 30.669 29.818 30.669s29.818-13.731 29.818-30.669v-401.343l98.189 100.993c11.645 11.978 30.525 11.978 42.17 0z","M221.818 379.274h149.091v59.635h-119.272v387.635h536.728v-387.635h-119.274v-59.635h149.091c16.467 0 29.818 13.35 29.818 29.818v447.274c0 16.467-13.35 29.818-29.818 29.818h-596.364c-16.468 0-29.818-13.35-29.818-29.818v-447.274c0-16.467 13.35-29.818 29.818-29.818z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["share"],"defaultCode":59827,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1095,"name":"share","prevSize":32,"id":183,"code":59827},"setIdx":0,"setId":6,"iconIdx":183},{"icon":{"paths":["M502.627 142.69c12.915-3.408 26.509-3.289 39.363 0.345l245.194 69.317c29.165 8.245 51.254 33.818 53.504 65.14 24.506 341.145-184.394 520.422-272.611 580.214-33.053 22.403-75.28 22.474-108.416 0.259-88.758-59.504-300.1-238.589-276.51-579.794 2.205-31.89 24.96-57.772 54.753-65.633l264.724-69.849zM524.579 204.621c-1.837-0.519-3.779-0.536-5.622-0.049l-264.725 69.849c-4.4 1.161-6.999 4.775-7.233 8.165-21.305 308.166 168.214 468.531 248.301 522.218 11.507 7.715 25.434 7.677 36.87-0.077 79.379-53.798 266.835-214.288 244.685-522.649-0.243-3.358-2.787-6.925-7.082-8.139l-245.194-69.317z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["set-as-moderator"],"defaultCode":59661,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1096,"name":"shield","prevSize":32,"id":184,"code":59661},"setIdx":0,"setId":6,"iconIdx":184},{"icon":{"paths":["M513.302 142.705c12.915-3.408 26.509-3.289 39.36 0.345l245.197 69.318c29.165 8.245 51.254 33.818 53.504 65.14 24.506 341.142-184.397 520.422-272.611 580.214-33.053 22.403-75.28 22.47-108.416 0.259-88.762-59.504-300.101-238.589-276.511-579.794 2.205-31.89 24.96-57.772 54.753-65.633l264.725-69.849zM535.251 204.637c-1.834-0.519-3.776-0.536-5.622-0.050l-264.723 69.849c-4.4 1.161-6.999 4.775-7.234 8.164-21.305 308.164 168.216 468.532 248.299 522.218 11.507 7.715 25.434 7.677 36.874-0.077 79.379-53.798 266.832-214.288 244.682-522.65-0.24-3.358-2.784-6.925-7.078-8.139l-245.197-69.317z","M490.672 337.334c-19.76 4.672-47.245 12.31-81.149 24.554 20.81 108.771 53.219 187.014 81.149 238.832v-263.386zM492.867 271.316c33.77-6.898 61.805 19.742 61.805 51.125v360.963c0 17.024-10.333 31.747-25.642 37.52-15.67 5.91-33.779 1.331-44.861-12.675-32.656-41.267-106.323-152.95-141.19-354.563-3.242-18.746 7.066-37.695 25.328-44.726 56.186-21.63 99.094-32.442 124.56-37.644z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["shield"],"defaultCode":59829,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1097,"name":"shield-alt","prevSize":32,"id":185,"code":59829},"setIdx":0,"setId":6,"iconIdx":185},{"icon":{"paths":["M664.083 405.072c11.638-13.299 10.288-33.517-3.011-45.155s-33.517-10.288-45.155 3.011l-125.251 143.142-39.917-45.619c-11.638-13.299-31.853-14.646-45.155-3.011-13.299 11.638-14.646 31.856-3.008 45.155l64 73.142c6.077 6.944 14.854 10.928 24.080 10.928 9.229 0 18.006-3.984 24.083-10.928l149.334-170.666z","M541.99 143.050c-12.854-3.634-26.448-3.753-39.363-0.345l-264.724 69.849c-29.793 7.861-52.548 33.743-54.753 65.633-23.589 341.205 187.752 520.29 276.51 579.794 33.136 22.211 75.363 22.144 108.416-0.259 88.218-59.792 297.117-239.072 272.611-580.214-2.25-31.321-24.339-56.895-53.504-65.14l-245.194-69.318zM518.957 204.587c1.843-0.487 3.786-0.47 5.622 0.049l245.194 69.318c4.294 1.214 6.838 4.781 7.082 8.139 22.15 308.362-165.306 468.851-244.685 522.65-11.437 7.754-25.363 7.792-36.87 0.077-80.086-53.686-269.606-214.054-248.301-522.218 0.234-3.389 2.833-7.004 7.233-8.164l264.725-69.849z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["shield-check"],"defaultCode":59828,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1098,"name":"shield-check","prevSize":32,"id":186,"code":59828},"setIdx":0,"setId":6,"iconIdx":186},{"icon":{"paths":["M778.64 213.336c-17.674 0-32 14.327-32 32v533.333c0 17.674 14.326 32 32 32s32-14.326 32-32v-533.333c0-17.673-14.326-32-32-32z","M600.87 341.334c-17.674 0-32 14.33-32 32v405.334c0 17.674 14.326 32 32 32s32-14.326 32-32v-405.334c0-17.67-14.326-32-32-32z","M423.104 810.669c-17.674 0-32-14.326-32-32v-277.334c0-17.67 14.326-32 32-32 17.67 0 32 14.33 32 32v277.334c0 17.674-14.33 32-32 32z","M245.333 597.334c-17.673 0-32 14.33-32 32v149.334c0 17.674 14.327 32 32 32s32-14.326 32-32v-149.334c0-17.67-14.327-32-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["signal"],"defaultCode":59830,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1099,"name":"signal","prevSize":32,"id":187,"code":59830},"setIdx":0,"setId":6,"iconIdx":187},{"icon":{"paths":["M772.986 470.432h-40.186c-1.104-12.381-10.090-19.757-26.454-19.757-16.278 0-24.416 6.867-24.502 16.365-0.339 10.342 9.667 15.6 25.437 18.992l14.922 3.389c34.253 7.546 52.989 24.502 53.158 52.227-0.17 32.982-25.773 52.566-69.014 52.566-43.661 0-71.894-19.414-72.403-60.026h40.186c0.934 16.701 13.142 25.35 31.709 25.35 16.874 0 26.794-7.376 26.963-17.974-0.17-9.75-8.733-14.922-27.811-19.331l-18.141-4.24c-30.016-6.867-48.496-21.706-48.413-48.070-0.253-32.304 28.317-53.923 67.997-53.923 40.355 0 66.214 21.958 66.554 54.432z","M354.858 470.432h40.186c-0.339-32.474-26.198-54.432-66.554-54.432-39.679 0-68.251 21.619-67.996 53.923-0.085 26.365 18.398 41.203 48.411 48.070l18.145 4.24c19.075 4.41 27.638 9.581 27.808 19.331-0.17 10.598-10.090 17.974-26.96 17.974-18.569 0-30.778-8.65-31.71-25.35h-40.187c0.509 40.611 28.741 60.026 72.403 60.026 43.242 0 68.845-19.584 69.014-52.566-0.17-27.725-18.906-44.682-53.158-52.227l-14.922-3.389c-15.77-3.392-25.774-8.65-25.435-18.992 0.085-9.498 8.224-16.365 24.501-16.365 16.365 0 25.35 7.376 26.454 19.757z","M418.614 418.374v173.635h40.864v-107.251h1.443l41.712 106.15h26.112l41.715-105.555h1.44v106.656h40.867v-173.635h-51.974l-44.086 107.504h-2.035l-44.086-107.504h-51.971z","M864 192c16.973 0 33.251 6.743 45.254 18.745s18.746 28.281 18.746 45.255v635.296c0 12.186-3.478 24.122-10.032 34.397-6.55 10.278-15.898 18.474-26.947 23.619-11.046 5.146-23.334 7.027-35.418 5.43-12.083-1.6-23.456-6.614-32.787-14.458l-128.81-108.285h-534.006c-16.974 0-33.252-6.742-45.255-18.746s-18.745-28.282-18.745-45.254v-512c0-16.974 6.743-33.252 18.745-45.255s28.281-18.745 45.255-18.745h704zM864 256h-704v512h534.006c15.066 0 29.648 5.315 41.181 15.011l128.813 108.285v-635.296z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["sms"],"defaultCode":59772,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1100,"name":"sms","prevSize":32,"id":188,"code":59772},"setIdx":0,"setId":6,"iconIdx":188},{"icon":{"paths":["M919.258 667.229c12.605-12.253 12.877-32.394 0.605-44.982-12.269-12.589-32.435-12.858-45.040-0.605l-106.112 103.155v-500.8c0-17.568-14.259-31.81-31.853-31.81-17.59 0-31.85 14.242-31.85 31.81v500.8l-106.115-103.155c-12.605-12.253-32.768-11.984-45.040 0.605-12.269 12.589-11.997 32.73 0.608 44.982l160.179 155.718c12.368 12.019 32.070 12.019 44.435 0l160.182-155.718zM560.659 333.667c17.59 0 31.85-14.243 31.85-31.811s-14.259-31.809-31.85-31.809h-432.49c-17.591 0-31.852 14.242-31.852 31.809s14.26 31.811 31.852 31.811h432.49zM464.55 536.099c17.59 0 31.85-14.243 31.85-31.811 0-17.565-14.259-31.808-31.85-31.808h-336.381c-17.591 0-31.852 14.24-31.852 31.808s14.26 31.811 31.852 31.811h336.381zM384.458 722.96c17.594 0 31.853-14.24 31.853-31.808s-14.259-31.811-31.853-31.811h-256.289c-17.591 0-31.852 14.243-31.852 31.811s14.26 31.808 31.852 31.808h256.289z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["sort"],"defaultCode":59832,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1101,"name":"sort","prevSize":32,"id":189,"code":59832},"setIdx":0,"setId":6,"iconIdx":189},{"icon":{"paths":["M289.362 192c13.364 0 25.321 8.305 29.987 20.829l96.001 257.699c6.17 16.56-2.256 34.986-18.816 41.155-16.563 6.17-34.989-2.253-41.158-18.816l-20.477-54.963h-91.074l-20.476 54.963c-6.17 16.563-24.597 24.986-41.158 18.816s-24.986-24.595-18.816-41.155l96-257.699c4.666-12.524 16.622-20.829 29.987-20.829zM311.058 373.904l-21.695-58.238-21.695 58.238h43.391z","M522.131 626.435c-12.154 12.829-11.606 33.082 1.222 45.238l160 151.587c12.342 11.693 31.674 11.693 44.016 0l160-151.587c12.832-12.157 13.376-32.41 1.222-45.238s-32.41-13.376-45.238-1.222l-105.99 100.419v-501.632c0-17.673-14.326-32-32-32s-32 14.327-32 32v501.632l-105.994-100.419c-12.829-12.154-33.082-11.606-45.238 1.222z","M193.362 570.947c-17.673 0-32 14.326-32 32 0 17.67 14.327 32 32 32h116.145l-139.065 142.73c-8.979 9.216-11.565 22.915-6.564 34.771 5.001 11.853 16.617 19.562 29.484 19.562h192.001c17.674 0 32-14.326 32-32s-14.326-32-32-32h-116.146l139.064-142.733c8.979-9.216 11.565-22.915 6.563-34.768-4.998-11.856-16.614-19.562-29.482-19.562h-192.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["sort-az"],"defaultCode":59831,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1102,"name":"sort-az","prevSize":32,"id":190,"code":59831},"setIdx":0,"setId":6,"iconIdx":190},{"icon":{"paths":["M472.618 173.508c18.166-58.554 100.454-60.461 121.322-2.812l69.821 192.91h195.44c57.872 0 86.026 70.611 43.994 110.336l-147.888 139.782 53.386 217.363c14.17 57.696-51.251 101.805-99.536 67.11l-177.741-127.709-177.741 127.709c-48.283 34.691-113.703-9.414-99.533-67.11l53.209-216.64-157.591-139.024c-44.179-38.973-16.577-111.818 42.37-111.818h221.513l58.976-190.098zM603.574 385.334l-69.824-192.91-58.976 190.098c-8.304 26.758-33.085 45.002-61.133 45.002h-221.513l157.59 139.021c17.837 15.731 25.456 40.048 19.789 63.13l-53.209 216.643 177.74-127.709c22.33-16.045 52.426-16.045 74.755 0l177.738 127.709-53.386-217.363c-5.478-22.317 1.456-45.856 18.166-61.648l147.888-139.782h-195.44c-26.957 0-51.024-16.87-60.186-42.189z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["star"],"defaultCode":59834,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1103,"name":"star","prevSize":32,"id":191,"code":59834},"setIdx":0,"setId":6,"iconIdx":191},{"icon":{"paths":["M593.939 170.244c-20.867-57.726-103.155-55.816-121.322 2.815l-58.976 190.348h-221.513c-58.947 0-86.549 72.944-42.37 111.968l157.591 139.206-53.209 216.928c-14.17 57.77 51.25 101.936 99.533 67.197l177.741-127.875 177.741 127.875c48.285 34.739 113.706-9.427 99.536-67.197l-53.386-217.651 147.888-139.968c42.032-39.779 13.878-110.483-43.99-110.483h-195.443l-69.821-193.164z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["star-filled"],"defaultCode":59833,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1104,"name":"star-filled","prevSize":32,"id":192,"code":59833},"setIdx":0,"setId":6,"iconIdx":192},{"icon":{"paths":["M512 896c-212.077 0-384-171.923-384-384s171.923-384 384-384c212.077 0 384 171.923 384 384s-171.923 384-384 384zM565.334 288c0-29.455-23.878-53.333-53.334-53.333s-53.334 23.878-53.334 53.333v249.632l180.016 144.013c23.002 18.403 56.563 14.672 74.963-8.326 18.403-23.002 14.672-56.563-8.326-74.963l-139.984-111.987v-198.368z"],"attrs":[{"fill":"rgb(243, 190, 8)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":3}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":2}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":3}]},"tags":["status-away"],"defaultCode":59741,"grid":0},"attrs":[{"fill":"rgb(243, 190, 8)"}],"properties":{"order":1105,"name":"status-away","prevSize":32,"id":193,"code":59741},"setIdx":0,"setId":6,"iconIdx":193},{"icon":{"paths":["M512 896c-212.077 0-384-171.923-384-384s171.923-384 384-384c212.077 0 384 171.923 384 384s-171.923 384-384 384zM384 458.666c-29.456 0-53.334 23.875-53.334 53.331s23.878 53.334 53.334 53.334h256c29.456 0 53.334-23.878 53.334-53.334s-23.878-53.331-53.334-53.331h-256z"],"attrs":[{"fill":"rgb(245, 69, 92)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":6}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":6}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":8}]},"tags":["status-busy"],"defaultCode":59742,"grid":0},"attrs":[{"fill":"rgb(245, 69, 92)"}],"properties":{"order":1106,"name":"status-busy","prevSize":32,"id":194,"code":59742},"setIdx":0,"setId":6,"iconIdx":194},{"icon":{"paths":["M512 896c212.077 0 384-171.923 384-384s-171.923-384-384-384c-212.077 0-384 171.923-384 384s171.923 384 384 384zM554.774 298.667v298.668c0 23.562-19.101 42.666-42.666 42.666s-42.669-19.104-42.669-42.666v-298.668c0-23.564 19.104-42.667 42.669-42.667s42.666 19.102 42.666 42.667zM554.774 725.334c0 23.562-19.101 42.666-42.666 42.666s-42.669-19.104-42.669-42.666c0-23.565 19.104-42.669 42.669-42.669s42.666 19.104 42.666 42.669z"],"attrs":[{"fill":"rgb(243, 140, 57)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":5}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":7}]},"tags":["status-disabled"],"defaultCode":59837,"grid":0},"attrs":[{"fill":"rgb(243, 140, 57)"}],"properties":{"order":1107,"id":195,"name":"status-disabled","prevSize":32,"code":59837},"setIdx":0,"setId":6,"iconIdx":195},{"icon":{"paths":["M888.691 586.941l-125.568-24.838c3.187-16.102 4.877-32.842 4.877-50.102s-1.69-34-4.877-50.102l125.568-24.838c4.794 24.237 7.309 49.296 7.309 74.941s-2.515 50.704-7.309 74.941zM831.322 298.644l-106.365 71.209c-18.726-27.971-42.838-52.083-70.81-70.81l71.21-106.364c41.875 28.035 77.93 64.089 105.965 105.965zM586.941 135.309l-24.838 125.566c-16.102-3.185-32.842-4.876-50.102-4.876s-34 1.69-50.102 4.876l-24.838-125.566c24.237-4.795 49.296-7.309 74.941-7.309s50.704 2.514 74.941 7.309zM298.644 192.679l71.209 106.364c-27.971 18.727-52.083 42.839-70.81 70.81l-106.364-71.209c28.035-41.876 64.089-77.93 105.965-105.964zM135.309 437.059c-4.795 24.237-7.309 49.296-7.309 74.941s2.514 50.704 7.309 74.941l125.566-24.838c-3.185-16.102-4.876-32.842-4.876-50.102s1.69-34 4.876-50.102l-125.566-24.838zM192.679 725.357l106.364-71.21c18.727 27.971 42.839 52.083 70.81 70.81l-71.209 106.365c-41.876-28.035-77.93-64.090-105.964-105.965zM437.059 888.691l24.838-125.568c16.102 3.187 32.842 4.877 50.102 4.877s34-1.69 50.102-4.877l24.838 125.568c-24.237 4.794-49.296 7.309-74.941 7.309s-50.704-2.515-74.941-7.309zM725.357 831.322l-71.21-106.365c27.971-18.726 52.083-42.838 70.81-70.81l106.365 71.21c-28.035 41.875-64.090 77.93-105.965 105.965z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["status-loading"],"defaultCode":59743,"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":1108,"name":"status-loading","prevSize":32,"id":196,"code":59743},"setIdx":0,"setId":6,"iconIdx":196},{"icon":{"paths":["M512 789.334c-153.168 0-277.333-124.166-277.333-277.334s124.165-277.333 277.333-277.333c153.168 0 277.334 124.165 277.334 277.333s-124.166 277.334-277.334 277.334zM512 896c212.077 0 384-171.923 384-384s-171.923-384-384-384c-212.077 0-384 171.923-384 384s171.923 384 384 384z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["status-offline"],"defaultCode":59744,"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":1109,"name":"status-offline","prevSize":32,"id":197,"code":59744},"setIdx":0,"setId":6,"iconIdx":197},{"icon":{"paths":["M896 512c0 212.077-171.923 384-384 384s-384-171.923-384-384c0-212.077 171.923-384 384-384s384 171.923 384 384z"],"attrs":[{"fill":"rgb(45, 224, 165)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":4}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":3}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":5}]},"tags":["status-online"],"defaultCode":59745,"grid":0},"attrs":[{"fill":"rgb(45, 224, 165)"}],"properties":{"order":1110,"name":"status-online","prevSize":32,"id":198,"code":59745},"setIdx":0,"setId":6,"iconIdx":198},{"icon":{"paths":["M511.997 224c-114.163 0-179.555 64.46-179.555 128v0.253c-0.061 7.453 1.072 14.867 3.354 21.962 5.411 16.826-3.84 34.851-20.666 40.259-16.825 5.411-34.85-3.84-40.261-20.666-4.357-13.546-6.527-27.702-6.428-41.933 0.081-113.124 110.343-191.875 243.556-191.875 103.597 0 190.97 46.311 226.886 120.071 7.738 15.889 1.13 35.043-14.762 42.78-15.888 7.738-35.043 1.13-42.781-14.761-22.259-45.713-82.714-84.090-169.344-84.090z","M128 512c0-17.674 14.327-32 32-32h392.893c0.467-0.010 0.938-0.010 1.408 0h309.699c17.674 0 32 14.326 32 32s-14.326 32-32 32h-160.432c38.198 29.328 64.432 70.438 64.432 128.003 0 57.2-32.512 105.965-79.008 139.178-46.557 33.254-109.235 52.822-176.992 52.822s-130.435-19.568-176.992-52.822c-46.495-33.213-79.008-81.978-79.008-139.178 0-17.674 14.327-32 32-32s32 14.326 32 32c0 31.168 17.632 62.4 52.208 87.098 34.515 24.653 83.837 40.902 139.792 40.902s105.277-16.25 139.792-40.902c34.576-24.698 52.208-55.93 52.208-87.098 0-35.558-15.216-59.581-42.134-79.283-27.824-20.368-67.005-35.082-112.88-48.72h-388.986c-17.673 0-32-14.326-32-32z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{},{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["strike"],"defaultCode":59846,"grid":0},"attrs":[{},{}],"properties":{"order":1111,"name":"strike","prevSize":32,"id":199,"code":59846},"setIdx":0,"setId":6,"iconIdx":199},{"icon":{"paths":["M481.35 117.336c0-17.673 14.326-32 32-32s32 14.327 32 32v106.667c0 17.673-14.326 32-32 32s-32-14.327-32-32v-106.667zM771.392 214.631c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-75.411 75.413c-12.499 12.496-32.758 12.496-45.254 0-12.499-12.496-12.499-32.759 0-45.255l75.411-75.412zM336.73 694.63c-12.499-12.496-32.759-12.496-45.256 0l-75.495 75.498c-12.497 12.496-12.497 32.755 0 45.254 12.497 12.496 32.758 12.496 45.255 0l75.496-75.498c12.496-12.496 12.496-32.755 0-45.254zM481.35 800.003c0-17.674 14.326-32 32-32s32 14.326 32 32v106.669c0 17.67-14.326 32-32 32s-32-14.33-32-32v-106.669zM213.352 212.001c-12.497 12.497-12.497 32.758 0 45.255l75.349 75.348c12.497 12.496 32.758 12.496 45.254 0 12.499-12.496 12.496-32.757 0-45.254l-75.348-75.349c-12.497-12.497-32.758-12.497-45.255 0zM695.978 739.885c-12.496-12.496-12.496-32.758 0-45.254 12.499-12.496 32.758-12.496 45.254 0l75.331 75.328c12.496 12.496 12.496 32.758 0 45.254-12.499 12.496-32.758 12.496-45.258 0l-75.328-75.328zM87.751 512.003c0 17.674 14.327 32 32 32h106.667c17.673 0 32-14.326 32-32s-14.327-32-32-32h-106.667c-17.673 0-32 14.326-32 32zM801.35 544.003c-17.674 0-32-14.326-32-32s14.326-32 32-32h106.669c17.67 0 32 14.326 32 32s-14.33 32-32 32h-106.669zM668.17 512c0-85.504-69.315-154.816-154.819-154.816-85.507 0-154.819 69.312-154.819 154.816 0 85.507 69.312 154.819 154.819 154.819 85.504 0 154.819-69.312 154.819-154.819zM726.682 512c0 117.821-95.51 213.334-213.331 213.334s-213.335-95.514-213.335-213.334c0-117.821 95.514-213.332 213.335-213.332s213.331 95.511 213.331 213.332z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["sun"],"defaultCode":59847,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1112,"name":"sun","prevSize":32,"id":200,"code":59847},"setIdx":0,"setId":6,"iconIdx":200},{"icon":{"paths":["M930.704 512c0 229.75-186.25 416-416 416s-415.999-186.25-415.999-416c0-229.75 186.25-416 415.999-416s416 186.25 416 416zM570.49 859.603l-41.827-156.102c-4.611 0.33-9.264 0.499-13.958 0.499-4.57 0-9.101-0.16-13.594-0.474l-41.837 156.134c18.058 2.854 36.573 4.339 55.43 4.339 18.986 0 37.616-1.504 55.786-4.397zM438.893 688.451c-47.549-20.454-85.181-59.571-103.674-108.125l-155.029 41.539c33.968 103.485 114.617 185.805 217.045 222.058l41.658-155.472zM162.705 512c0 16.090 1.080 31.926 3.17 47.443l156.906-42.042c-0.051-1.795-0.077-3.594-0.077-5.402 0-4.909 0.186-9.776 0.547-14.595l-156.051-41.814c-2.958 18.368-4.496 37.21-4.496 56.41zM396.31 180.407c-99.16 35.408-177.786 114.033-213.196 213.19l155.535 41.677c19.357-44.352 54.982-79.978 99.334-99.331l-41.674-155.536zM514.704 160c-19.197 0-38.035 1.537-56.4 4.494l41.814 156.053c4.813-0.362 9.68-0.547 14.586-0.547 5.030 0 10.019 0.192 14.95 0.573l41.808-156.021c-18.477-2.995-37.437-4.552-56.758-4.552zM632.512 843.802c102.659-36.451 183.392-119.194 217.094-223.12l-154.973-41.526c-18.291 48.982-56.010 88.493-103.786 109.155l41.664 155.491zM863.699 558.198c1.984-15.117 3.005-30.538 3.005-46.198 0-18.771-1.469-37.197-4.298-55.171l-156.157 41.84c0.301 4.406 0.454 8.851 0.454 13.331 0 1.376-0.013 2.752-0.042 4.122l157.037 42.077zM846.714 394.774c-35.165-99.6-113.885-178.641-213.277-214.247l-41.68 155.559c44.582 19.555 80.314 55.565 99.504 100.342l155.453-41.654zM642.704 512c0-70.691-57.306-128-128-128-70.691 0-128 57.309-128 128s57.309 128 128 128c70.694 0 128-57.309 128-128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["support"],"defaultCode":59848,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1113,"name":"support","prevSize":32,"id":201,"code":59848},"setIdx":0,"setId":6,"iconIdx":201},{"icon":{"paths":["M368 412.982c-53.592 0-96-42.877-96-94.491 0-51.616 42.408-94.491 96-94.491 53.594 0 96 42.876 96 94.491 0 51.614-42.406 94.491-96 94.491zM368 476.982c88.365 0 160-70.96 160-158.491s-71.635-158.491-160-158.491c-88.365 0-160 70.959-160 158.491s71.635 158.491 160 158.491zM713.6 397.133c-35.92 0-64-28.685-64-62.794s28.080-62.792 64-62.792c35.92 0 64 28.684 64 62.792s-28.080 62.794-64 62.794zM713.6 461.133c70.691 0 128-56.768 128-126.794s-57.309-126.792-128-126.792c-70.691 0-128 56.767-128 126.792s57.309 126.794 128 126.794zM197.459 527.267c27.344-8.707 56.67-9.242 84.319-1.539l48.491 13.51c24.205 6.742 49.882 6.275 73.824-1.347l30.099-9.584c29.475-9.386 61.085-9.962 90.89-1.658 67.962 18.934 114.918 80.333 114.918 150.269v91.987c0 52.518-42.979 95.094-96 95.094h-352c-53.019 0-96-42.576-96-95.094v-103.766c0-62.909 40.999-118.621 101.459-137.872zM264.451 586.758c-15.545-4.333-32.034-4.032-47.407 0.864-33.993 10.822-57.044 42.147-57.044 77.517v103.766c0 17.507 14.327 31.699 32 31.699h352c17.674 0 32-14.192 32-31.699v-91.987c0-41.533-27.885-77.997-68.246-89.242-17.699-4.931-36.474-4.589-53.978 0.986l-30.099 9.584c-35.91 11.434-74.426 12.138-110.737 2.019l-48.489-13.507zM691.2 778.717h140.8c53.021 0 96-42.979 96-96v-30.611c0-56.877-38.614-106.49-93.747-120.454-21.398-5.418-43.853-5.040-65.056 1.098l-16.4 4.746c-21.843 6.323-44.973 6.714-67.018 1.13l-29.805-7.549c-19.907-5.043-40.797-4.691-60.522 1.018-1.066 0.31-2.122 0.634-3.174 0.97 10.71 4.048 20.896 9.539 30.253 16.374l2.429 1.776 15.040 13.206c9.939 8.726 18.141 19.248 24.182 31.014l2.208 4.301 3.677 0.931c33.062 8.374 67.76 7.789 100.525-1.693l16.4-4.749c10.282-2.976 21.171-3.158 31.546-0.531 26.736 6.771 45.462 30.832 45.462 58.413v30.611c0 17.674-14.326 32-32 32h-140.8v64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["team"],"defaultCode":59849,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1114,"name":"team","prevSize":32,"id":202,"code":59849},"setIdx":0,"setId":6,"iconIdx":202},{"icon":{"paths":["M281.184 336c17.673 0 32-14.326 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM281.184 400c-53.020 0-96-42.979-96-96 0-53.019 42.98-96 96-96 53.018 0 96 42.981 96 96 0 53.021-42.982 96-96 96zM576 320c0-26.51-21.491-48-48-48s-48 21.49-48 48c0 26.509 21.491 48 48 48s48-21.491 48-48zM640 320c0 61.856-50.144 112-112 112s-112-50.144-112-112c0-61.856 50.144-112 112-112s112 50.144 112 112zM477.901 478.515c-28.56-10.957-60.291-10.211-88.307 2.067-42.282 18.534-69.594 60.326-69.594 106.49v132.928c0 53.021 42.979 96 96 96h224c53.021 0 96-42.979 96-96v-125.062c0-51.162-31.536-97.034-79.306-115.354-30.352-11.642-64.067-10.851-93.84 2.198l-2.070 0.909c-21.523 9.434-45.901 10.006-67.843 1.59l-15.040-5.766zM415.286 539.2c12.595-5.52 26.858-5.856 39.699-0.931l15.040 5.77c37.664 14.445 79.504 13.462 116.451-2.73l2.070-0.909c14.349-6.288 30.602-6.669 45.229-1.059 23.024 8.829 38.224 30.938 38.224 55.597v125.062c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32v-132.928c0-20.752 12.278-39.539 31.286-47.872zM768 336c-17.674 0-32-14.326-32-32s14.326-32 32-32c17.674 0 32 14.327 32 32s-14.326 32-32 32zM768 400c53.021 0 96-42.979 96-96 0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96zM840.714 681.766h-72.714v-64h72.714c17.674 0 32-14.326 32-32v-44.688c0-15.050-9.664-28.394-23.958-33.091-7.536-2.474-15.69-2.304-23.114 0.483l-4.554 1.709c-19.77 7.421-40.89 9.978-61.619 7.632-12.438-31.683-37.722-57.549-70.774-70.227-1.754-0.672-3.52-1.302-5.296-1.894 18.058-5.312 37.36-5.040 55.344 0.867l14.182 4.659c14.886 4.893 30.998 4.554 45.667-0.954l4.554-1.709c21.069-7.91 44.205-8.394 65.581-1.37 40.566 13.325 67.987 51.197 67.987 93.894v44.688c0 53.021-42.982 96-96 96zM625.267 624h-0.797c0.259 0.598 0.525 1.194 0.797 1.786v-1.786zM357.594 448.582c2.528-1.107 5.088-2.122 7.674-3.043-17.907-5.155-37.014-4.832-54.824 1.018l-14.183 4.659c-14.887 4.893-30.998 4.554-45.668-0.954l-4.554-1.709c-21.067-7.91-44.203-8.394-65.581-1.37-40.565 13.325-67.986 51.197-67.986 93.894v44.688c0 53.021 42.981 96 96 96h79.53v-64h-79.53c-17.673 0-32-14.326-32-32v-44.688c0-15.050 9.664-28.394 23.96-33.091 7.534-2.474 15.688-2.304 23.112 0.483l4.554 1.709c21.238 7.974 44.041 10.333 66.238 7.027 10.398-30.173 32.994-55.357 63.259-68.624zM423.917 624h0.797c-0.259 0.598-0.525 1.194-0.797 1.786v-1.786z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["teams"],"defaultCode":59751,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1115,"name":"teams","prevSize":32,"id":203,"code":59751},"setIdx":0,"setId":6,"iconIdx":203},{"icon":{"paths":["M631.997 256h24v-56c0-57.437 46.563-104 104-104 57.44 0 104 46.562 104 104v56h24c17.674 0 32 14.327 32 32v192c0 17.674-14.326 32-32 32h-256c-17.67 0-32-14.326-32-32v-192c0-17.673 14.33-32 32-32zM759.997 160c-22.090 0-40 17.908-40 40v55.238h80v-55.238c0-22.092-17.907-40-40-40z","M527.997 224c10.096 0 19.882 1.336 29.184 3.84-13.251 16.46-21.184 37.383-21.184 60.16v0.664c-2.602-0.436-5.274-0.664-8-0.664-26.509 0-48 21.49-48 48s21.491 48 48 48c2.726 0 5.398-0.227 8-0.662v64.381c-2.64 0.186-5.309 0.282-8 0.282-61.856 0-112-50.144-112-112s50.144-112 112-112z","M492.941 500.282c14.883 5.709 30.883 7.283 46.355 4.758 6.182 22.938 20.646 42.474 39.987 55.206-35.123 13.318-74.019 13.309-109.261-0.208l-15.040-5.77c-12.838-4.925-27.104-4.589-39.699 0.931-19.008 8.333-31.286 27.12-31.286 47.872v132.928c0 17.674 14.33 32 32 32h224c17.674 0 32-14.326 32-32v-125.062c0-12.842-4.122-24.995-11.325-34.938h70.291c3.29 11.162 5.034 22.902 5.034 34.938v125.062c0 53.021-42.979 96-96 96h-224c-53.018 0-95.999-42.979-95.999-96v-132.928c0-46.163 27.311-87.955 69.592-106.49 28.019-12.278 59.747-13.024 88.31-2.067l15.040 5.766z","M887.997 576h-15.286v25.766c0 17.674-14.326 32-32 32h-72.714v64h72.714c53.021 0 96-42.979 96-96v-39.027c-14.278 8.426-30.931 13.261-48.714 13.261z","M281.182 416c53.020 0 95.999-42.979 95.999-96 0-53.019-42.979-96-95.999-96s-96 42.981-96 96c0 53.021 42.98 96 96 96zM281.182 352c-17.673 0-32-14.326-32-32s14.327-32 32-32c17.673 0 32 14.327 32 32s-14.327 32-32 32z","M625.267 640h-0.8c0.262 0.598 0.528 1.194 0.8 1.786v-1.786z","M357.59 464.582c2.531-1.107 5.091-2.122 7.674-3.043-17.907-5.155-37.011-4.832-54.823 1.018l-14.183 4.659c-14.887 4.893-30.998 4.554-45.668-0.954l-4.554-1.709c-21.067-7.91-44.203-8.394-65.581-1.37-40.565 13.325-67.986 51.197-67.986 93.894v44.688c0 53.021 42.98 96 96 96h79.53v-64h-79.53c-17.673 0-32-14.326-32-32v-44.688c0-15.050 9.664-28.394 23.96-33.091 7.534-2.474 15.688-2.304 23.112 0.483l4.554 1.709c21.238 7.974 44.041 10.333 66.238 7.027 10.398-30.173 32.992-55.357 63.258-68.624z","M423.914 640h0.797c-0.259 0.598-0.525 1.194-0.797 1.786v-1.786z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["teams-private"],"defaultCode":59750,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1116,"name":"teams-private","prevSize":32,"id":204,"code":59750},"setIdx":0,"setId":6,"iconIdx":204},{"icon":{"paths":["M170.664 192c0-17.673 14.327-32 32-32h618.667c17.674 0 32 14.327 32 32v128c0 17.674-14.326 32-32 32s-32-14.326-32-32v-96h-245.334v576h96c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.67 0-32-14.326-32-32s14.33-32 32-32h96v-576h-245.333v96c0 17.674-14.327 32-32 32s-32-14.326-32-32v-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["text-format"],"defaultCode":59839,"grid":0},"attrs":[{}],"properties":{"order":1117,"id":205,"name":"text-format","prevSize":32,"code":59839},"setIdx":0,"setId":6,"iconIdx":205},{"icon":{"paths":["M223.311 308.609c-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-9.348 103.235 27.547 175.997 86.848 226.374 60.642 51.52 146.602 80.998 235.29 90.893 88.611 9.885 186.221 1.398 263.341-14.973 38.56-8.189 70.928-18.125 93.888-28.128 8.906-3.882 15.837-7.536 20.941-10.765-2.374-1.514-5.245-3.197-8.672-5.030-8.886-4.749-19.059-9.261-29.613-13.894l-1.843-0.81c-9.315-4.083-19.725-8.65-27.613-13.078-14.291-8.026-28.317-17.155-38.544-26.867-5.034-4.781-10.762-11.194-14.595-19.184-4.054-8.454-6.96-21.078-1.261-34.435 30.816-72.186 45.459-111.725 52.554-137.834 6.621-24.378 6.621-36.653 6.621-56.17v-0.179c0-15.51-8.979-86.595-53.776-152.876-43.376-64.174-121.398-125.729-264.832-125.729-129.725 0-207.83 53.576-254.529 118.696zM173.267 272.433c58.132-81.063 154.749-144.433 304.573-144.433 164.896 0 261.594 72.589 315.859 152.878 52.838 78.181 64.416 161.881 64.416 187.641 0 21.654-0.022 40.336-8.797 72.64-7.834 28.835-22.627 68.614-50.048 133.424 5.069 4.032 12.592 9.005 22.506 14.57 5.12 2.877 12.995 6.339 24.054 11.194 10.266 4.506 22.582 9.93 33.891 15.978 10.848 5.798 23.526 13.571 32.954 23.738 9.859 10.63 20.208 28.87 12.816 51.139-4.87 14.672-16.182 25.091-25.61 32.016-10.24 7.52-22.947 14.278-36.858 20.342-27.949 12.176-64.582 23.181-105.68 31.907-82.198 17.453-186.522 26.688-282.909 15.936-96.31-10.746-195.346-43.178-268.313-105.165-74.031-62.893-119.295-154.778-108.551-277.856 0.276-63.411 19.117-157.053 75.696-235.948zM333.952 422.051c0-17.648 14.25-31.955 31.83-31.955h183.008c17.578 0 31.827 14.307 31.827 31.955s-14.25 31.955-31.827 31.955h-183.008c-17.581 0-31.83-14.307-31.83-31.955zM365.782 539.709c-17.581 0-31.83 14.307-31.83 31.955s14.25 31.955 31.83 31.955h224.118c17.578 0 31.827-14.307 31.827-31.955s-14.25-31.955-31.827-31.955h-224.118z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["threads"],"defaultCode":59850,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1118,"name":"threads","prevSize":32,"id":206,"code":59850},"setIdx":0,"setId":6,"iconIdx":206},{"icon":{"paths":["M353.354 320c0-17.673 14.326-32 32-32h256c17.674 0 32 14.327 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M385.354 416c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M481.354 448c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M641.354 416c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M353.354 576c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M513.354 544c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M609.354 576c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M385.354 672c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M481.354 704c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M641.354 672c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M289.353 160h448.001c35.344 0 64 28.654 64 64v576c0 35.347-28.656 64-64 64h-448.001c-35.346 0-64-28.653-64-64v-576c0-35.346 28.654-64 64-64zM289.353 224v576h448.001v-576h-448.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["total"],"defaultCode":59851,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1119,"name":"total","prevSize":32,"id":207,"code":59851},"setIdx":0,"setId":6,"iconIdx":207},{"icon":{"paths":["M713.613 91.356c13.162-11.794 33.392-10.685 45.187 2.477l129.034 144c10.89 12.154 10.89 30.556 0 42.71l-129.034 144.001c-11.795 13.162-32.026 14.269-45.187 2.477-13.162-11.795-14.272-32.026-2.477-45.187l81.222-90.646h-216.358c-17.674 0-32-14.327-32-32s14.326-32 32-32h216.358l-81.222-90.645c-11.795-13.162-10.685-33.393 2.477-45.187zM340.026 464.461c8.586-15.45 28.067-21.018 43.514-12.432l128.461 71.366 128.461-71.366c15.446-8.586 34.928-3.018 43.514 12.432 8.582 15.45 3.014 34.931-12.435 43.514l-159.539 88.634-159.539-88.634c-15.45-8.582-21.018-28.064-12.435-43.514zM192 288v448h640v-192c0-17.674 14.326-32 32-32s32 14.326 32 32v224c0 17.674-14.326 32-32 32h-704c-17.673 0-32-14.326-32-32v-512c0-17.673 14.327-32 32-32h272c17.674 0 32 14.327 32 32s-14.326 32-32 32h-240z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["transcript"],"defaultCode":59852,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1120,"name":"transcript","prevSize":32,"id":208,"code":59852},"setIdx":0,"setId":6,"iconIdx":208},{"icon":{"paths":["M378.861 853.331c317.456 0 491.091-262.662 491.091-490.442 0-7.462 0-14.89-0.506-22.282 33.779-24.401 62.938-54.614 86.112-89.224-31.501 13.94-64.918 23.082-99.136 27.12 36.032-21.542 62.998-55.424 75.882-95.34-33.878 20.078-70.944 34.228-109.597 41.839-53.501-56.814-138.515-70.72-207.37-33.919-68.851 36.801-104.426 115.155-86.768 191.127-138.774-6.947-268.074-72.409-355.715-180.093-45.811 78.76-22.412 179.517 53.436 230.1-27.467-0.813-54.335-8.214-78.337-21.574 0 0.704 0 1.443 0 2.182 0.022 82.051 57.937 152.723 138.47 168.97-25.41 6.922-52.071 7.933-77.933 2.957 22.611 70.218 87.409 118.32 161.25 119.706-61.116 47.968-136.616 74.010-214.35 73.933-13.732-0.026-27.452-0.858-41.087-2.486 78.931 50.586 170.772 77.418 264.557 77.293z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["twitter-monochromatic"],"defaultCode":59660,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1121,"name":"twitter-monochromatic","prevSize":32,"id":209,"code":59660},"setIdx":0,"setId":6,"iconIdx":209},{"icon":{"paths":["M384 320c0-17.673-14.326-32-32-32s-32 14.327-32 32v256c0 106.038 85.962 192 192 192s192-85.962 192-192v-256c0-17.673-14.326-32-32-32s-32 14.327-32 32v256c0 70.691-57.309 128-128 128s-128-57.309-128-128v-256zM352 856c-13.254 0-24 10.746-24 24s10.746 24 24 24h320c13.254 0 24-10.746 24-24s-10.746-24-24-24h-320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["underline"],"defaultCode":59853,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1122,"name":"underline","prevSize":32,"id":210,"code":59853},"setIdx":0,"setId":6,"iconIdx":210},{"icon":{"paths":["M512 832c176.73 0 320-143.27 320-320s-143.27-320-320-320c-111.712 0-210.056 57.244-267.295 144h107.295c17.674 0 32 14.326 32 32s-14.326 32-32 32h-176c-17.673 0-32-14.326-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v101.364c70.228-90.856 180.282-149.364 304-149.364 212.077 0 384 171.923 384 384s-171.923 384-384 384c-212.077 0-384-171.923-384-384h64c0 176.73 143.27 320 320 320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["undo"],"defaultCode":59854,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1123,"name":"undo","prevSize":32,"id":211,"code":59854},"setIdx":0,"setId":6,"iconIdx":211},{"icon":{"paths":["M589.36 729.43c-107.366 23.603-252.288-9.875-422.339-221.158 65.137-95.478 165.885-189.15 280.79-213.871 108.314-23.302 251.286 10.604 413.674 221.404-61.546 95.187-158.653 188.682-272.125 213.626zM916.819 482.714c-347.59-456.963-669.742-211.156-808.018-2.662-12.655 19.082-10.846 44.304 3.402 62.227 362.786 456.419 677.038 209.142 808.011 0.563 11.674-18.589 9.894-42.656-3.395-60.128zM619.462 512c0-53.709-45.517-100.57-105.834-100.57s-105.834 46.861-105.834 100.57c0 53.709 45.517 100.573 105.834 100.573s105.834-46.864 105.834-100.573zM683.546 512c0 90.893-76.074 164.573-169.917 164.573s-169.917-73.68-169.917-164.573c0-90.89 76.074-164.57 169.917-164.57s169.917 73.68 169.917 164.57z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["unread-on-top"],"defaultCode":59857,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1124,"name":"unread-on-top","prevSize":32,"id":212,"code":59857},"setIdx":0,"setId":6,"iconIdx":212},{"icon":{"paths":["M829.168 153.372c12.515-12.497 32.803-12.497 45.315 0 12.515 12.497 12.515 32.758 0 45.255l-672.887 672c-12.513 12.496-32.801 12.496-45.315 0s-12.513-32.758 0-45.254l672.887-672zM110.155 480.051c101.936-153.699 303.797-327.676 542.114-225.436l-49.578 49.512c-56.528-19.209-108.077-19.504-153.526-9.726-114.906 24.721-215.653 118.392-280.79 213.871 38.633 48 75.969 86.822 111.862 117.885l-45.363 45.302c-39.684-34.736-80.189-77.437-121.317-129.181-14.248-17.923-16.056-43.146-3.402-62.227zM797.981 350.454l-45.328 45.27c35.546 31.427 72.336 70.947 110.186 120.080-61.546 95.187-158.656 188.682-272.125 213.626-46.752 10.278-100.624 9.734-160.592-11.603l-49.331 49.267c244.662 107.334 443.389-69.158 540.778-224.253 11.674-18.589 9.894-42.656-3.395-60.128-40.493-53.235-80.64-96.931-120.192-132.259zM514.982 347.43c13.709 0 27.037 1.571 39.802 4.541l-203.738 203.469c-3.901-13.837-5.981-28.403-5.981-43.44 0-90.89 76.074-164.57 169.917-164.57zM679.091 469.184l-203.264 202.998c12.57 2.87 25.68 4.39 39.155 4.39 93.843 0 169.917-73.68 169.917-164.573 0-14.81-2.019-29.162-5.808-42.816z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["unread-on-top-disabled"],"defaultCode":59856,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1125,"name":"unread-on-top-disabled","prevSize":32,"id":213,"code":59856},"setIdx":0,"setId":6,"iconIdx":213},{"icon":{"paths":["M273.128 356.678c-6.62 27.766-2.384 63.757 25.498 105.581l33.166 49.75h-59.792c-44.011 0-70.484 14.874-86.279 33.619-16.496 19.578-24.573 47.264-23.734 77.491 0.841 30.262 10.601 59.968 25.818 81.312 15.127 21.216 33.404 31.578 52.195 31.578h143.999v64h-144c-45.209 0-80.932-25.642-104.306-58.426-23.283-32.656-36.522-74.95-37.682-116.688-1.16-41.773 9.763-86.083 38.766-120.506 20.726-24.598 49.155-42.32 84.825-50.784-16.1-39.011-19.009-77.050-10.731-111.77 11.253-47.2 42.305-84.492 80.791-107.342 38.4-22.798 85.677-32.139 131.303-21.965 35.584 7.935 68.909 27.48 95.251 59.554 53.75-35.147 127.584-30.892 182.483-2.495 34.438 17.812 64.794 46.382 81.437 85.010 12.294 28.531 16.438 61.011 10.608 96.205 46.112 6.682 81.507 25.155 105.616 53.456 30.346 35.626 38.102 81.35 33.443 123.283-4.659 41.917-21.946 83.485-46.544 115.114-24.061 30.934-59.354 57.354-101.261 57.354h-144v-64h144c14.093 0 32.8-9.581 50.742-32.646 17.398-22.371 30.112-52.806 33.453-82.89 3.341-30.067-2.902-56.339-18.554-74.714-15.222-17.869-44.035-33.75-97.642-33.75h-45.686l15.613-42.938c13.546-37.251 11.091-66.742 1.437-89.149-9.856-22.87-28.502-41.302-52.064-53.488-49.587-25.649-107.475-18.625-134.717 14.064l-30.134 36.16-22.541-41.325c-19.757-36.219-47.232-54.175-74.87-60.339-28.378-6.327-59.098-0.669-84.701 14.53-25.512 15.148-44.461 38.855-51.208 67.152zM630.979 588.778l-96-99.050c-6.029-6.218-14.32-9.728-22.979-9.728s-16.95 3.51-22.979 9.728l-96 99.050c-12.298 12.691-11.981 32.95 0.707 45.251 12.691 12.298 32.95 11.981 45.251-0.707l41.021-42.326v273.005c0 17.674 14.326 32 32 32s32-14.326 32-32v-273.005l41.021 42.326c12.301 12.688 32.56 13.005 45.251 0.707 12.691-12.301 13.005-32.56 0.707-45.251z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["upload"],"defaultCode":59858,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1126,"name":"upload","prevSize":32,"id":214,"code":59858},"setIdx":0,"setId":6,"iconIdx":214},{"icon":{"paths":["M609.354 336c0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96s96-42.979 96-96zM673.354 336c0 88.365-71.635 160-160 160s-160-71.635-160-160c0-88.365 71.635-160 160-160s160 71.635 160 160zM413.805 551.802c-24.621-5.77-50.285-5.366-74.714 1.178-67.086 17.968-113.738 78.762-113.738 148.211v66.81c0 53.021 42.98 96 96 96h384c53.021 0 96-42.979 96-96v-58.531c0-74.301-51.149-138.826-123.488-155.779l-6.458-1.514c-25.674-6.016-52.435-5.594-77.907 1.229l-49.626 13.293c-20.378 5.456-41.789 5.795-62.326 0.979l-67.744-15.875zM355.651 614.8c14.237-3.814 29.197-4.051 43.549-0.688l67.744 15.878c30.806 7.219 62.925 6.714 93.488-1.472l49.629-13.293c15.283-4.096 31.341-4.349 46.742-0.736l6.458 1.51c43.402 10.173 74.093 48.89 74.093 93.469v58.531c0 17.674-14.326 32-32 32h-384c-17.673 0-32-14.326-32-32v-66.81c0-40.483 27.193-75.917 66.298-86.39z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["user"],"defaultCode":59861,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1127,"name":"user","prevSize":32,"id":215,"code":59861},"setIdx":0,"setId":6,"iconIdx":215},{"icon":{"paths":["M553.411 326.282c0 91.578-75.846 165.818-169.411 165.818-93.564 0-169.412-74.24-169.412-165.818 0-91.581 75.848-165.821 169.412-165.821 93.565 0 169.411 74.24 169.411 165.821zM485.648 326.282c0-54.949-45.51-99.493-101.648-99.493s-101.647 44.544-101.647 99.493c0 54.947 45.509 99.491 101.647 99.491s101.648-44.544 101.648-99.491z","M203.427 511.232c28.952-9.11 60.004-9.67 89.279-1.61l51.342 14.131c25.632 7.056 52.819 6.566 78.166-1.408l31.872-10.026c31.206-9.821 64.678-10.422 96.234-1.738 71.962 19.811 121.68 84.051 121.68 157.219v96.24c0 54.947-45.51 99.491-101.648 99.491h-372.705c-56.138 0-101.647-44.544-101.647-99.491v-108.566c0-65.814 43.411-124.106 107.427-144.243zM274.359 573.472c-16.46-4.531-33.918-4.218-50.196 0.906-35.992 11.322-60.399 44.093-60.399 81.098v108.566c0 18.317 15.17 33.165 33.882 33.165h372.705c18.714 0 33.882-14.848 33.882-33.165v-96.24c0-43.453-29.523-81.603-72.259-93.366-18.739-5.158-38.618-4.8-57.152 1.030l-31.872 10.026c-38.022 11.962-78.803 12.698-117.248 2.115l-51.343-14.134z","M797.091 189.321c0-15.913-13.024-28.812-29.091-28.812s-29.091 12.9-29.091 28.812v100.844h-101.818c-16.067 0-29.091 12.9-29.091 28.812s13.024 28.812 29.091 28.812h101.818v100.845c0 15.914 13.024 28.813 29.091 28.813s29.091-12.899 29.091-28.813v-100.845h101.818c16.067 0 29.091-12.899 29.091-28.812s-13.024-28.812-29.091-28.812h-101.818v-100.844z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["user-add"],"defaultCode":59859,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1128,"name":"user-add","prevSize":32,"id":216,"code":59859},"setIdx":0,"setId":6,"iconIdx":216},{"icon":{"paths":["M464 318.747c0-51.548-42.406-94.366-96-94.366-53.592 0-96 42.819-96 94.366s42.408 94.367 96 94.367c53.594 0 96-42.819 96-94.367zM528 318.747c0 87.416-71.635 158.284-160 158.284s-160-70.867-160-158.284c0-87.417 71.635-158.282 160-158.282s160 70.865 160 158.282zM281.778 525.712c-27.649-7.693-56.976-7.158-84.319 1.536-60.46 19.226-101.459 74.864-101.459 137.69v103.629c0 52.451 42.981 94.97 96 94.97h352c3.606 0 7.165-0.195 10.666-0.579v-64.534c-3.334 1.168-6.925 1.802-10.666 1.802h-352c-17.673 0-32-14.173-32-31.658v-103.629c0-35.325 23.051-66.605 57.044-77.414 15.373-4.89 31.862-5.187 47.407-0.864l48.489 13.491c36.311 10.102 74.827 9.402 110.737-2.016l30.099-9.571c17.504-5.568 36.278-5.91 53.978-0.986 18.899 5.261 35.066 16.042 46.912 30.282v-79.712c-9.309-4.749-19.203-8.627-29.584-11.517-29.805-8.291-61.414-7.715-90.89 1.654l-30.099 9.574c-23.942 7.61-49.619 8.080-73.824 1.344l-48.491-13.491zM763.366 489.709c-12.326-12.646-32.586-12.918-45.248-0.608-12.666 12.31-12.938 32.544-0.611 45.19l102.842 105.51h-324.349c-17.674 0-32 14.307-32 31.958 0 17.648 14.326 31.958 32 31.958h324.349l-102.842 105.507c-12.326 12.65-12.054 32.88 0.611 45.194 12.662 12.31 32.922 12.038 45.248-0.611l155.718-159.757c12.093-12.406 12.093-32.176 0-44.582l-155.718-159.76z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["user-forward"],"defaultCode":59860,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1129,"name":"user-forward","prevSize":32,"id":217,"code":59860},"setIdx":0,"setId":6,"iconIdx":217},{"icon":{"paths":["M201.583 672c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 576c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M201.583 480c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 384c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M201.583 288c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M329.584 192c-17.674 0-32.001 14.327-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.327 32-32s-14.326-32-32-32h-544z","M201.583 864c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 768c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["view-condensed"],"defaultCode":59862,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1130,"name":"view-condensed","prevSize":32,"id":218,"code":59862},"setIdx":0,"setId":6,"iconIdx":218},{"icon":{"paths":["M288 192c0-17.673 14.327-32 32-32h544c17.674 0 32 14.327 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 288c0-17.673 14.327-32 32-32h448c17.674 0 32 14.327 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 304c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M288 464c0-17.674 14.327-32 32-32h544c17.674 0 32 14.326 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.326-32-32zM288 560c0-17.674 14.327-32 32-32h448c17.674 0 32 14.326 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.326-32-32zM192 576c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M288 736c0-17.674 14.327-32 32-32h544c17.674 0 32 14.326 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.326-32-32zM288 832c0-17.674 14.327-32 32-32h448c17.674 0 32 14.326 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.326-32-32zM192 848c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["view-extended"],"defaultCode":59863,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1131,"name":"view-extended","prevSize":32,"id":219,"code":59863},"setIdx":0,"setId":6,"iconIdx":219},{"icon":{"paths":["M192 320c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M320 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.674 0 32-14.327 32-32s-14.326-32-32-32h-544z","M192 576c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M320 480c-17.673 0-32 14.326-32 32s14.327 32 32 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M192 832c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M320 736c-17.673 0-32 14.326-32 32s14.327 32 32 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["view-medium"],"defaultCode":59864,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1132,"name":"view-medium","prevSize":32,"id":220,"code":59864},"setIdx":0,"setId":6,"iconIdx":220},{"icon":{"paths":["M640.854 256c26.512 0 48-21.49 48-48s-21.488-48-48-48c-26.509 0-48 21.49-48 48s21.491 48 48 48zM640.854 320c61.856 0 112-50.144 112-112s-50.144-112-112-112c-61.856 0-112 50.144-112 112s50.144 112 112 112zM592.854 416v256h-160v128h32v-96h224v-288h-96zM528.854 768h160c35.347 0 64-28.653 64-64v-288c0-35.347-28.653-64-64-64h-96c-35.344 0-64 28.653-64 64v192h-96c-35.344 0-64 28.653-64 64v128c0 35.347 28.656 64 64 64h32c35.347 0 64-28.653 64-64v-32zM784.854 448c0-17.674 14.326-32 32-32s32 14.326 32 32v384c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32s14.326-32 32-32h192v-352zM368.403 401.52c9.677-9.059 10.176-24.246 1.117-33.923l-48.272-51.558v-47.925c0-13.255-10.746-24-24-24s-24 10.745-24 24v57.406c0 6.093 2.316 11.955 6.48 16.403l54.752 58.48c9.059 9.677 24.246 10.176 33.923 1.117zM170.974 414.278c53.308 74.218 156.687 91.171 230.908 37.862 10.765-7.731 25.76-5.274 33.494 5.491 7.731 10.768 5.274 25.763-5.494 33.494-95.75 68.771-229.121 46.902-297.894-48.848s-46.902-229.123 48.848-297.895c75.545-54.26 174.453-52.073 246.597-1.796 10.874 7.578 13.546 22.538 5.968 33.412s-22.538 13.547-33.411 5.968c-55.971-39.005-132.65-40.618-191.153 1.402-74.219 53.308-91.171 156.688-37.864 230.909z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["waiting-on-me"],"defaultCode":59865,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1133,"name":"waiting-on-me","prevSize":32,"id":221,"code":59865},"setIdx":0,"setId":6,"iconIdx":221},{"icon":{"paths":["M512 352.003c17.674 0 32 14.33 32 32v224c0 17.674-14.326 32-32 32s-32-14.326-32-32v-224c0-17.67 14.326-32 32-32z","M512 672.003c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32s-32-14.326-32-32c0-17.67 14.326-32 32-32z","M567.101 158.348c-24.774-41.922-85.427-41.922-110.202 0l-359.92 609.099c-25.21 42.662 5.544 96.557 55.099 96.557h719.845c49.555 0 80.307-53.894 55.098-96.557l-359.92-609.099zM512 190.906l359.923 609.097h-719.845l359.922-609.097z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["warning"],"defaultCode":59866,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1134,"name":"warning","prevSize":32,"id":222,"code":59866},"setIdx":0,"setId":6,"iconIdx":222},{"icon":{"paths":["M784.131 240.143c-35.43-35.658-77.581-63.931-124.016-83.181s-96.227-29.094-146.493-28.961c-210.863 0-382.322 171.532-382.414 382.376-0.085 67.104 17.523 133.043 51.047 191.171l-54.256 198.154 202.72-53.174c56.064 30.531 118.883 46.531 182.717 46.538h0.166c210.752 0 382.32-171.552 382.394-382.394 0.16-50.25-9.645-100.029-28.848-146.464-19.2-46.436-47.418-88.604-83.018-124.065zM513.622 828.486h-0.186c-56.922 0.006-112.797-15.293-161.776-44.298l-11.606-6.896-120.302 31.555 32.124-117.347-7.573-12.029c-31.783-50.64-48.608-109.232-48.535-169.021 0-175.235 142.653-317.816 317.981-317.816 84.301 0.049 165.13 33.58 224.707 93.218 59.581 59.638 93.034 140.499 92.998 224.8-0.074 175.254-142.653 317.834-317.834 317.834zM687.958 590.451c-9.552-4.787-56.528-27.907-65.293-31.171s-15.126-4.768-21.491 4.784c-6.362 9.555-24.678 31.171-30.253 37.462-5.574 6.288-11.149 7.187-20.701 2.4-9.555-4.784-40.339-14.87-76.845-47.434-28.403-25.322-47.584-56.621-53.174-66.192-5.594-9.571-0.589-14.669 4.198-19.491 4.291-4.291 9.552-11.168 14.32-16.742s6.381-9.571 9.552-15.933c3.174-6.362 1.597-11.955-0.787-16.739-2.384-4.787-21.491-51.818-29.466-70.96-7.757-18.63-15.622-16.099-21.491-16.394-5.501-0.275-11.955-0.349-18.336-0.349-4.842 0.131-9.606 1.264-13.994 3.325-4.387 2.058-8.298 5.005-11.491 8.65-8.749 9.552-33.428 32.675-33.428 79.706s34.234 92.467 39.002 98.848c4.765 6.381 67.382 102.883 163.187 144.266 17.792 7.68 35.974 14.413 54.477 20.17 22.902 7.334 43.731 6.237 60.179 3.779 18.336-2.733 56.547-23.104 64.506-45.418 7.955-22.317 7.955-41.459 5.501-45.456-2.458-3.997-8.618-6.326-18.173-11.11z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["whatsapp-monochromatic"],"defaultCode":59868,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1135,"name":"whatsapp-monochromatic","prevSize":32,"id":223,"code":59868},"setIdx":0,"setId":6,"iconIdx":223},{"icon":{"paths":["M354.006 399.123l14.029 0.627-0.541-16.726-152.878 1.578c49.916-116.491 165.64-198.133 300.366-198.133 99.645 0 188.893 44.659 248.81 115.065-3.712 0.171-7.491 0.492-11.526 1.068 0 0-63.76 14.898-13.302 118.708 0 0 31.085 84.541-19.306 198.774l-28.403 73.306-99.101-264.723c0 0-5.984-28.154 23.61-28.154l23.76-1.472 0.339-16.035h-228.368v14.458c0 0 39.83-0.288 56.15 27.149l40.762 103.779-73.014 174.403-108.608-272.4c0 0-3.389-31.779 27.222-31.27z","M841.603 513.168c0-33.862-5.235-66.643-14.726-97.357l-145.949 378.755c96.134-56.88 160.675-161.571 160.675-281.398z","M411.478 823.011c32.49 10.912 67.267 16.778 103.488 16.778 37.85 0 74.102-6.406 107.898-18.256l-99.709-258.502-111.677 259.981z","M188.279 513.149c0-32.083 4.712-63.066 13.339-92.336l1 2.051 152.656 375.229c-99.606-55.882-166.994-162.538-166.994-284.944z","M130.705 512.093c0-211.775 172.316-384.093 384.076-384.093 211.725 0 383.923 172.318 383.923 384.093 0 211.776-172.198 384.010-383.923 384.010-211.757 0-384.076-172.234-384.076-384.010zM514.781 879.254c202.384 0 367.11-164.742 367.11-367.178 0-202.486-164.726-367.145-367.11-367.161-202.489 0-367.213 164.673-367.213 367.161 0 202.435 164.724 367.178 367.213 367.178z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["wordpress-monochromatic"],"defaultCode":59755,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1136,"name":"wordpress-monochromatic","prevSize":32,"id":224,"code":59755},"setIdx":0,"setId":6,"iconIdx":224},{"icon":{"paths":["M193.353 405.334h213.332v-213.334h-213.332v213.334zM129.353 170.667c0-23.564 19.102-42.667 42.667-42.667h256c23.565 0 42.666 19.102 42.666 42.667v255.999c0 23.565-19.101 42.669-42.666 42.669h-256c-23.564 0-42.667-19.104-42.667-42.669v-255.999zM620.019 405.334h213.334v-213.334h-213.334v213.334zM556.019 170.667c0-23.564 19.104-42.667 42.666-42.667h256c23.565 0 42.669 19.102 42.669 42.667v255.999c0 23.565-19.104 42.669-42.669 42.669h-256c-23.562 0-42.666-19.104-42.666-42.669v-255.999zM620.019 618.666h213.334v213.334h-213.334v-213.334zM598.685 554.666c-23.562 0-42.666 19.104-42.666 42.669v256c0 23.562 19.104 42.666 42.666 42.666h256c23.565 0 42.669-19.104 42.669-42.666v-256c0-23.565-19.104-42.669-42.669-42.669h-256zM193.353 832h213.332v-213.334h-213.332v213.334zM129.353 597.334c0-23.565 19.102-42.669 42.667-42.669h256c23.565 0 42.666 19.104 42.666 42.669v256c0 23.562-19.101 42.666-42.666 42.666h-256c-23.564 0-42.667-19.104-42.667-42.666v-256z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["workspaces"],"defaultCode":59870,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1137,"name":"workspaces","prevSize":32,"id":225,"code":59870},"setIdx":0,"setId":6,"iconIdx":225},{"icon":{"paths":["M384.509 149.333c0-11.782 9.562-21.333 21.36-21.333h85.446c11.798 0 21.363 9.551 21.363 21.333v106.667h-106.81c-11.798 0-21.36-9.551-21.36-21.333v-85.333z","M512.678 256h106.806c11.798 0 21.36 9.551 21.36 21.333v85.332c0 11.782-9.562 21.334-21.36 21.334h-106.806v-128z","M384.509 405.334c0-11.782 9.562-21.334 21.36-21.334h106.81v128h-106.81c-11.798 0-21.36-9.552-21.36-21.334v-85.331z","M512.678 512h106.806c11.798 0 21.36 9.552 21.36 21.334v106.666h-128.166v-128z","M427.232 640c-23.597 0-42.723 19.104-42.723 42.666v170.669c0 23.562 19.126 42.666 42.723 42.666h170.89c23.597 0 42.723-19.104 42.723-42.666v-213.334h-213.613zM491.315 725.334c-11.798 0-21.36 9.549-21.36 21.331v42.669c0 11.782 9.562 21.331 21.36 21.331h42.723c11.798 0 21.36-9.549 21.36-21.331v-42.669c0-11.782-9.562-21.331-21.36-21.331h-42.723z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["zip"],"defaultCode":59871,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1138,"name":"zip","prevSize":32,"id":226,"code":59871},"setIdx":0,"setId":6,"iconIdx":226},{"icon":{"paths":["M373.437 492.374c25.77-8.39 53.667-8.131 79.376 0.906l19.187 6.752c25.293 8.893 52.963 8.275 77.843-1.718l4.877-1.971c26.989-10.842 56.726-12.432 84.592-4.685 2.832 0.787 5.648 1.674 8.438 2.656 22.342 7.856 41.504 21.35 56.25 38.499 17.84 20.742 29.178 46.848 31.533 75.030 0.304 3.645 0.467 7.328 0.467 11.030v117.126c0 9.936-1.51 19.517-4.314 28.531-4.467 14.371-12.275 27.245-22.435 37.843-2.595 2.704-5.296 5.302-8.189 7.69-2.368 1.952-4.822 3.805-7.376 5.53-5.107 3.453-10.57 6.413-16.31 8.845-11.491 4.861-24.115 7.562-37.376 7.562l-260.938-0.125c-3.277-0.166-6.506-0.515-9.686-1.002-7.949-1.213-15.571-3.398-22.752-6.435-5.741-2.432-11.203-5.392-16.31-8.845-2.55-1.725-5.008-3.578-7.376-5.53-2.893-2.387-5.595-4.986-8.188-7.69-10.162-10.598-17.97-23.472-22.437-37.843-2.803-9.014-4.312-18.595-4.313-28.531v-125.968c0-0.675 0.052-1.357 0.062-2.032 0.487-29.827 11.671-57.741 30.531-79.344 12.578-14.41 28.523-26.032 47.032-33.469 2.576-1.034 5.187-1.958 7.811-2.813zM426.374 552.093c-10.461-2.643-21.446-2.406-31.779 0.688-1.728 0.518-3.443 1.104-5.126 1.782-1.757 0.704-3.466 1.488-5.126 2.342-0.115 0.061-0.227 0.128-0.342 0.189-19.514 10.24-31.997 30.573-32 52.938v125.968c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-117.126c-0.003-23.798-12.39-45.472-32-57.718-0.253-0.157-0.525-0.282-0.781-0.435-1.555-0.944-3.142-1.837-4.781-2.656-0.57-0.288-1.139-0.576-1.718-0.845-2.006-0.934-4.070-1.786-6.189-2.531-3.894-1.37-7.878-2.394-11.907-3.030-10.070-1.597-20.403-0.883-30.218 2.061-1.958 0.589-3.901 1.264-5.811 2.032l-4.877 1.936c-9.818 3.946-19.914 6.973-30.157 9.062-12.81 2.618-25.85 3.763-38.874 3.469l-7.814-0.342c-10.406-0.704-20.774-2.333-30.966-4.906-2.547-0.643-5.072-1.366-7.594-2.125-2.522-0.762-5.037-1.562-7.533-2.438l-19.219-6.749c-1.709-0.602-3.443-1.123-5.187-1.565z","M174.188 458.624c19.051-8.506 40.722-9.024 60.156-1.437l7.906 3.094c8.268 3.229 17.489 2.992 25.594-0.624l0.844-0.378c20.012-8.931 42.773-9.469 63.188-1.498 6.358 2.483 12.262 5.722 17.658 9.562-27.331 11.914-50.085 31.030-66.283 54.688-20.961 6.541-43.62 5.914-64.281-2.157l-7.906-3.062c-3.484-1.36-7.366-1.274-10.781 0.25-5.037 2.25-8.281 7.264-8.281 12.781v49.219c0.001 15.981 12.956 28.938 28.938 28.938h35.125c-0.009 0.675-0.062 1.357-0.062 2.032v61.968h-35.062c-51.328 0-92.937-41.61-92.938-92.938v-49.219c0-30.768 18.093-58.672 46.188-71.219z","M878.406 422.813c11.197 14.163 17.594 31.891 17.594 50.563v102.624c0 53.021-42.979 96-96 96h-32v-53.126l-0.125-6.499c-0.058-1.462-0.246-2.922-0.342-4.374h32.467c17.674 0 32-14.326 32-32v-102.624c0-3.12-0.842-6.109-2.342-8.72 13.494-10.003 27.248-21.219 40.374-33.562 2.797-2.634 5.539-5.45 8.374-8.282z","M512.032 192c-0.106 19.205 0.71 40.743 2.938 64.156-0.986-0.045-1.974-0.156-2.97-0.156-35.347 0-64 28.654-64 64s28.653 64 64 64c14.624 0 28.035-4.995 38.813-13.251 12.131 18.838 26.362 35.45 40.406 49.718-21.798 17.213-49.29 27.533-79.219 27.533-70.691 0-128-57.309-128-128 0-70.692 57.338-128 128.032-128z","M256 224c53.019 0 96 42.981 96 96 0 53.021-42.981 96-96 96s-96-42.979-96-96c0-53.019 42.981-96 96-96zM256 288c-17.673 0-32 14.327-32 32s14.327 32 32 32c17.673 0 32-14.326 32-32s-14.327-32-32-32z","M735.997 96c44.746 0 121.2 10.367 153.827 29.086 4.662 18.723 11.184 75.812 0 154.423-11.187 78.625-107.213 145.092-153.824 168.49-46.614-23.402-142.637-89.869-153.824-168.49-11.184-78.609-4.662-135.699 0-154.423 32.627-18.719 109.072-29.084 153.821-29.086z"],"attrs":[{},{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["team-shield"]},"attrs":[{},{},{},{},{},{}],"properties":{"order":14,"id":1,"name":"team-shield","prevSize":32,"code":59877},"setIdx":4,"setId":2,"iconIdx":0},{"icon":{"paths":["M352 128c17.674 0 32 14.327 32 32v160h142.25c7.789 23.664 19.898 45.082 33.718 64h-175.968v256h256v-177.126c23.274 17.472 46 31.267 64 40.563v136.563h160c17.674 0 32 14.326 32 32s-14.326 32-32 32h-160v160c0 17.674-14.326 32-32 32s-32-14.326-32-32v-160h-256v160c0 17.674-14.326 32-32 32s-32-14.326-32-32v-160h-160c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-256h-160c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-160c0-17.673 14.326-32 32-32z","M735.997 96c44.746 0 121.2 10.367 153.827 29.086 4.662 18.723 11.184 75.812 0 154.423-11.187 78.625-107.213 145.092-153.824 168.49-46.614-23.402-142.637-89.869-153.824-168.49-11.184-78.609-4.662-135.699 0-154.423 32.627-18.719 109.072-29.084 153.821-29.086z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["hash-shield"]},"attrs":[{},{}],"properties":{"order":15,"id":0,"name":"hash-shield","prevSize":32,"code":59878},"setIdx":4,"setId":2,"iconIdx":1}],"height":1024,"metadata":{"name":"custom"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"custom","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon","name":"icomoon"},"historySize":50,"showCodes":true,"gridSize":16}} \ No newline at end of file +{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M224 192c-17.673 0-32 14.327-32 32v576c0 17.674 14.327 32 32 32h192c17.674 0 32-14.326 32-32v-576c0-17.673-14.326-32-32-32h-192zM256 768v-512h128v512h-128z","M608 192c-17.674 0-32 14.327-32 32v576c0 17.674 14.326 32 32 32h192c17.674 0 32-14.326 32-32v-576c0-17.673-14.326-32-32-32h-192zM640 768v-512h128v512h-128z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause-shape-unfilled"],"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]}},"attrs":[{},{}],"properties":{"order":1152,"id":227,"name":"pause-shape-unfilled","prevSize":32,"code":59879},"setIdx":0,"setId":6,"iconIdx":0},{"icon":{"paths":["M727.050 406.195c12.259-12.73 11.878-32.986-0.854-45.245-12.73-12.259-32.986-11.878-45.245 0.854l-254.285 264.061-115.615-120.061c-12.259-12.733-32.516-13.114-45.247-0.854s-13.113 32.515-0.854 45.245l138.666 144c6.032 6.266 14.355 9.805 23.050 9.805 8.698 0 17.021-3.539 23.053-9.805l277.331-288z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["check-single"],"grid":0},"attrs":[{}],"properties":{"order":1151,"id":0,"name":"check-single","prevSize":32,"code":59876},"setIdx":0,"setId":6,"iconIdx":1},{"icon":{"paths":["M599.050 406.195c12.259-12.73 11.878-32.986-0.854-45.245-12.73-12.259-32.986-11.878-45.245 0.854l-254.284 264.061-115.616-120.061c-12.259-12.733-32.516-13.114-45.247-0.854s-13.113 32.515-0.854 45.245l138.667 144c6.032 6.266 14.354 9.805 23.050 9.805s17.018-3.539 23.052-9.805l277.331-288z","M887.021 406.227c12.275-12.714 11.92-32.973-0.794-45.248s-32.973-11.92-45.248 0.794l-255.040 264.157-50.918-52.739c-12.275-12.714-32.534-13.069-45.248-0.794s-13.069 32.534-0.794 45.248l73.939 76.582c6.029 6.246 14.339 9.773 23.021 9.773s16.992-3.526 23.021-9.773l278.061-288z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["check-double"],"grid":0},"attrs":[{},{}],"properties":{"order":1150,"id":1,"name":"check-double","prevSize":32,"code":59875},"setIdx":0,"setId":6,"iconIdx":2},{"icon":{"paths":["M511.997 256c35.347 0 64-28.654 64-64s-28.653-64-64-64c-35.344 0-64 28.654-64 64s28.656 64 64 64zM639.997 192c0 70.692-57.306 128-128 128-70.691 0-128-57.308-128-128s57.309-128 128-128c70.694 0 128 57.308 128 128z","M192.859 431.645c0.669 1.446 2.097 3.488 5.957 5.232 18.33 8.272 67.426 22.054 115.377 34.39 23.244 5.981 45.187 11.366 61.327 15.261 8.067 1.946 14.672 3.517 19.258 4.598l7.078 1.664c0 0 0.026 0.003-0.218 1.046l0.218-1.046c8.33 1.933 15.562 7.123 20.042 14.406 4.48 7.28 5.859 16.054 3.834 24.358l-83.856 343.437c-0.483 1.984-1.155 3.914-2.006 5.77-1.155 2.509-1.242 5.302-0.272 7.853 0.982 2.573 3.053 4.893 6.006 6.237 2.976 1.357 6.438 1.523 9.568 0.435 3.114-1.082 5.44-3.238 6.688-5.754 0.362-0.73 0.749-1.443 1.165-2.144l121.434-204.461c5.766-9.706 16.224-15.658 27.514-15.658 11.293 0 21.747 5.952 27.514 15.658l121.437 204.461c0.413 0.701 0.803 1.414 1.165 2.144 1.245 2.515 3.571 4.672 6.685 5.754 3.13 1.088 6.592 0.922 9.568-0.435 2.957-1.344 5.027-3.664 6.006-6.237 0.97-2.55 0.883-5.344-0.269-7.853-0.854-1.856-1.526-3.786-2.010-5.77l-83.853-343.437c-2.029-8.304-0.65-17.075 3.83-24.358 4.48-7.28 11.686-12.467 20.013-14.4l0.266 1.139c-0.262-1.139-0.266-1.139-0.266-1.139l1.821-0.426 5.283-1.245c4.582-1.082 11.184-2.653 19.248-4.598 16.138-3.894 38.074-9.28 61.312-15.261 47.936-12.333 97.046-26.118 115.424-34.4 3.888-1.75 5.322-3.802 5.994-5.248 0.813-1.763 1.155-4.179 0.557-6.861-0.602-2.678-1.974-4.858-3.629-6.259-1.402-1.187-3.76-2.499-8.109-2.499h-615.975c-4.316 0-6.656 1.302-8.052 2.486-1.647 1.402-3.026 3.581-3.628 6.272s-0.26 5.12 0.556 6.886zM172.486 495.21c-75.805-34.218-48.392-143.21 31.498-143.21h615.975c79.907 0 107.44 108.989 31.478 143.216-24.554 11.066-79.939 26.24-125.766 38.032-21.494 5.533-41.85 10.554-57.651 14.384l75.597 309.616c6.986 17.306 7.216 36.614 0.538 54.147-7.085 18.598-21.283 33.501-39.283 41.699-17.978 8.189-38.474 9.126-57.123 2.64-18.234-6.342-33.469-19.36-42.39-36.566l-93.386-157.232-93.386 157.232c-8.918 17.206-24.157 30.224-42.387 36.566-18.653 6.486-39.146 5.549-57.126-2.64-18-8.198-32.198-23.101-39.282-41.699-6.678-17.533-6.449-36.842 0.539-54.147l75.595-309.613c-15.808-3.83-36.172-8.854-57.676-14.387-45.829-11.789-101.229-26.966-125.761-38.038z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["accessibility"],"grid":0},"attrs":[{},{}],"properties":{"order":1147,"id":2,"name":"accessibility","prevSize":32,"code":59874},"setIdx":0,"setId":6,"iconIdx":3},{"icon":{"paths":["M512 928c-229.75 0-416-186.246-416-416 0-229.75 186.25-416 416-416 229.754 0 416 186.25 416 416 0 229.754-186.246 416-416 416zM678.176 433.884c12.742-12.247 13.139-32.504 0.896-45.246-12.25-12.742-32.506-13.143-45.247-0.896l-207.030 198.991-68.644-65.834c-12.755-12.232-33.012-11.809-45.245 0.946s-11.809 33.012 0.946 45.245l90.819 87.1c12.39 11.885 31.948 11.872 44.324-0.026l229.183-220.28z"],"attrs":[{"fill":"rgb(20, 134, 96)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":0}]},"tags":["success-circle"],"grid":0},"attrs":[{"fill":"rgb(20, 134, 96)"}],"properties":{"order":1143,"id":3,"name":"success-circle","prevSize":32,"code":59869},"setIdx":0,"setId":6,"iconIdx":4},{"icon":{"paths":["M928 512c0-229.75-186.246-416-416-416-229.75 0-416 186.25-416 416 0 229.754 186.25 416 416 416 229.754 0 416-186.246 416-416zM662.63 361.373c12.493 12.497 12.493 32.758 0 45.254l-105.375 105.373 105.375 105.373c12.493 12.497 12.493 32.758 0 45.258-12.499 12.493-32.761 12.493-45.258 0l-105.373-105.375-105.373 105.375c-12.497 12.493-32.758 12.493-45.254 0-12.497-12.499-12.497-32.761 0-45.258l105.372-105.373-105.372-105.373c-12.497-12.497-12.497-32.758 0-45.254s32.758-12.497 45.254 0l105.373 105.372 105.373-105.372c12.497-12.497 32.758-12.497 45.258 0z"],"attrs":[{"fill":"rgb(212, 12, 38)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":1}]},"tags":["error-circle"],"grid":0},"attrs":[{"fill":"rgb(212, 12, 38)"}],"properties":{"order":1144,"id":4,"name":"error-circle","prevSize":32,"code":59873},"setIdx":0,"setId":6,"iconIdx":5},{"icon":{"paths":["M512 819.2c169.661 0 307.2-137.539 307.2-307.2s-137.539-307.2-307.2-307.2c-169.662 0-307.2 137.538-307.2 307.2s137.538 307.2 307.2 307.2z","M1024 512c0-282.77-229.228-512-512-512-282.77 0-512 229.23-512 512 0 282.772 229.23 512 512 512 282.772 0 512-229.228 512-512zM921.6 512c0 226.217-183.383 409.6-409.6 409.6-226.216 0-409.6-183.383-409.6-409.6 0-226.215 183.384-409.6 409.6-409.6 226.217 0 409.6 183.385 409.6 409.6z"],"attrs":[{"fill":"rgb(21, 111, 245)"},{"fill":"rgb(21, 111, 245)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912111124512431405712431908124569921291162451452241651":[{"f":2},{"f":2}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":4},{"f":4}]},"tags":["radio-checked"],"grid":0},"attrs":[{"fill":"rgb(21, 111, 245)"},{"fill":"rgb(21, 111, 245)"}],"properties":{"order":5,"id":5,"name":"radio-checked","prevSize":32,"code":59855},"setIdx":0,"setId":6,"iconIdx":6},{"icon":{"paths":["M512 0c282.767 0 512 229.23 512 512 0 282.767-229.233 512-512 512-282.77 0-512-229.233-512-512 0-282.77 229.23-512 512-512zM512 921.6c226.217 0 409.6-183.383 409.6-409.6 0-226.216-183.383-409.6-409.6-409.6-226.216 0-409.6 183.384-409.6 409.6 0 226.217 183.384 409.6 409.6 409.6z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912111124512431405712431908124569921291162451452241651":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["radio-unchecked"],"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":4,"id":6,"name":"radio-unchecked","prevSize":32,"code":59867},"setIdx":0,"setId":6,"iconIdx":7},{"icon":{"paths":["M678.736 135.922c7.414-5.157 16.23-7.922 25.264-7.922s17.85 2.764 25.264 7.922c7.414 5.157 13.075 12.46 16.218 20.928l0.074 0.2 32.371 89.024 89.226 32.445c8.467 3.143 15.77 8.803 20.928 16.219 5.155 7.415 7.92 16.231 7.92 25.264 0 9.034-2.765 17.85-7.92 25.264-5.158 7.414-12.461 13.075-20.931 16.218l-0.198 0.074-89.024 32.371-32.445 89.226c-3.142 8.467-8.803 15.77-16.218 20.928-7.414 5.155-16.23 7.92-25.264 7.92s-17.85-2.765-25.264-7.92c-7.414-5.158-13.075-12.461-16.218-20.931l-0.074-0.198-32.371-89.024-89.226-32.445c-8.467-3.142-15.77-8.803-20.928-16.218-5.155-7.414-7.92-16.23-7.92-25.264 0-9.032 2.765-17.848 7.92-25.264 5.158-7.415 12.461-13.075 20.931-16.218l0.198-0.074 89.024-32.372 32.445-89.224c3.142-8.468 8.803-15.771 16.218-20.928zM713.437 384l7.533-20.717c2.224-6.029 5.725-11.504 10.269-16.045 4.541-4.544 10.016-8.045 16.045-10.269l0.128-0.045 46.541-16.925-46.669-16.971c-6.029-2.221-11.504-5.724-16.045-10.267-4.544-4.542-8.045-10.017-10.269-16.044l-0.045-0.128-16.925-46.541-16.97 46.669c-2.221 6.028-5.725 11.502-10.269 16.044-4.541 4.543-10.016 8.045-16.045 10.267l-0.128 0.047-46.541 16.924 46.669 16.97c6.029 2.221 11.504 5.725 16.045 10.269 4.544 4.541 8.045 10.016 10.269 16.045l0.045 0.128 16.925 46.541 9.437-25.952z","M323.091 265.629c8.256-6.153 18.346-9.629 28.909-9.629s20.653 3.477 28.909 9.629c8.224 6.127 14.17 14.542 17.402 23.873l0.067 0.191 47.674 140.467 130.595 50.883c9.696 3.856 17.67 10.64 23.126 19.046 5.44 8.381 8.227 18.118 8.227 27.91s-2.787 19.53-8.227 27.91c-5.456 8.406-13.434 15.19-23.126 19.046l-0.208 0.083-130.387 50.8-47.741 140.659c-3.232 9.328-9.178 17.744-17.402 23.872-8.256 6.15-18.346 9.629-28.909 9.629s-20.653-3.478-28.909-9.629c-8.223-6.128-14.17-14.544-17.402-23.875l-0.066-0.189-47.673-140.467-130.596-50.883c-9.694-3.856-17.669-10.64-23.125-19.046-5.442-8.381-8.228-18.118-8.228-27.91s2.787-19.53 8.228-27.91c5.456-8.406 13.431-15.19 23.125-19.046l0.208-0.083 130.388-50.8 47.739-140.658c3.233-9.331 9.18-17.746 17.403-23.873zM381.222 617.712l6.314-18.602c2.291-6.659 5.958-12.874 10.88-18.147 4.928-5.28 11.014-9.507 17.917-12.23l0.134-0.054 104.41-40.678-104.544-40.733c-6.902-2.723-12.989-6.95-17.917-12.23-4.922-5.274-8.589-11.488-10.88-18.147l-0.042-0.125-35.494-104.579-35.536 104.704c-2.291 6.659-5.959 12.874-10.881 18.147-4.929 5.28-11.015 9.507-17.916 12.23l-0.133 0.054-104.411 40.678 104.544 40.733c6.901 2.723 12.988 6.95 17.916 12.23 4.923 5.274 8.59 11.488 10.881 18.147l0.042 0.125 35.494 104.579 29.222-86.102z","M704 544c-9.034 0-17.85 2.765-25.264 7.92-7.414 5.158-13.075 12.461-16.218 20.928l-32.445 89.226-89.222 32.445c-8.47 3.142-15.773 8.803-20.931 16.218-5.155 7.414-7.92 16.23-7.92 25.264s2.765 17.85 7.92 25.264c5.158 7.414 12.461 13.075 20.928 16.218l89.226 32.445 32.445 89.222c3.142 8.47 8.803 15.773 16.218 20.931 7.414 5.155 16.23 7.92 25.264 7.92s17.85-2.765 25.264-7.92c7.414-5.158 13.075-12.461 16.218-20.928l32.445-89.226 89.222-32.445c8.47-3.142 15.773-8.803 20.931-16.218 5.155-7.414 7.92-16.23 7.92-25.264s-2.765-17.85-7.92-25.264c-5.158-7.414-12.461-13.075-20.928-16.218l-89.226-32.445-32.445-89.222c-3.142-8.47-8.803-15.773-16.218-20.931-7.414-5.155-16.23-7.92-25.264-7.92zM720.97 779.283l-6.829 18.784-10.141 27.885-16.97-46.669c-2.224-6.029-5.725-11.504-10.269-16.045-4.541-4.544-10.016-8.048-16.045-10.269l-46.669-16.97 46.669-16.97c6.029-2.221 11.504-5.725 16.045-10.269 4.544-4.541 8.048-10.016 10.269-16.045l16.97-46.669 16.97 46.669c2.224 6.029 5.725 11.504 10.269 16.045 4.541 4.544 10.016 8.048 16.045 10.269l46.669 16.97-46.669 16.97c-6.029 2.224-11.504 5.725-16.045 10.269-4.544 4.541-8.045 10.016-10.269 16.045z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{},{}]},"tags":["stars"],"grid":0},"attrs":[{},{},{}],"properties":{"order":1139,"id":7,"name":"stars","prevSize":32,"code":59845},"setIdx":0,"setId":6,"iconIdx":8},{"icon":{"paths":["M810.666 512c0.022 8.358-2.173 16.579-6.371 23.862-4.195 7.283-10.253 13.382-17.581 17.706l-454.067 271.187c-7.658 4.576-16.425 7.075-25.4 7.235-8.975 0.163-17.832-2.016-25.656-6.314-7.749-4.23-14.205-10.397-18.702-17.872-4.498-7.472-6.875-15.981-6.888-24.65v-542.311c0.013-8.668 2.39-17.176 6.888-24.649s10.953-13.642 18.702-17.872c7.824-4.297 16.681-6.477 25.656-6.315s17.743 2.661 25.4 7.237l454.067 271.186c7.328 4.323 13.386 10.422 17.581 17.706 4.198 7.283 6.394 15.504 6.371 23.862z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["play-shape-filled"],"grid":0},"attrs":[{}],"properties":{"order":4,"id":8,"name":"play-shape-filled","prevSize":32,"code":59842},"setIdx":0,"setId":6,"iconIdx":9},{"icon":{"paths":["M832 245.333v533.332c0 14.147-5.693 27.712-15.824 37.712-10.131 10.003-23.872 15.622-38.202 15.622h-135.066c-14.33 0-28.070-5.619-38.202-15.622-10.131-10-15.824-23.565-15.824-37.712v-533.332c0-14.145 5.693-27.71 15.824-37.712s23.872-15.621 38.202-15.621h135.066c14.33 0 28.070 5.619 38.202 15.621s15.824 23.567 15.824 37.712zM381.091 192h-135.065c-14.329 0-28.070 5.619-38.202 15.621s-15.824 23.567-15.824 37.712v533.332c0 14.147 5.692 27.712 15.824 37.712 10.132 10.003 23.874 15.622 38.202 15.622h135.065c14.33 0 28.070-5.619 38.202-15.622 10.131-10 15.824-23.565 15.824-37.712v-533.332c0-14.145-5.693-27.71-15.824-37.712s-23.872-15.621-38.202-15.621z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["pause-shape-filled"],"grid":0},"attrs":[{}],"properties":{"order":3,"id":9,"name":"pause-shape-filled","prevSize":32,"code":59843},"setIdx":0,"setId":6,"iconIdx":10},{"icon":{"paths":["M593.158 920.006c-80.698 16.051-164.342 7.814-240.355-23.674-76.014-31.485-140.984-84.806-186.695-153.216s-70.108-148.842-70.108-231.117h64c0 69.619 20.644 137.674 59.323 195.562 38.678 57.885 93.653 103.002 157.973 129.645 64.32 26.64 135.094 33.613 203.376 20.029 68.282-13.581 131.002-47.107 180.23-96.333 49.226-49.229 82.752-111.949 96.333-180.23 13.584-68.282 6.611-139.056-20.029-203.376-26.643-64.32-71.76-119.295-129.645-157.973-57.888-38.678-125.942-59.323-195.562-59.323v-64c82.278 0 162.707 24.398 231.117 70.109s121.731 110.681 153.216 186.695v0c31.488 76.013 39.725 159.658 23.674 240.355-16.051 80.694-55.67 154.819-113.85 212.998s-132.304 97.798-212.998 113.85z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["loading"],"grid":0},"attrs":[{}],"properties":{"order":2,"id":10,"name":"loading","prevSize":32,"code":59844},"setIdx":0,"setId":6,"iconIdx":11},{"icon":{"paths":["M544 208c0-17.673-14.326-32-32-32s-32 14.327-32 32v271.997h-271.998c-17.673 0-32 14.326-32 32s14.327 32 32 32h271.998v272.003c0 17.674 14.326 32 32 32s32-14.326 32-32v-272.003l272-0.003c17.674 0 32-14.326 32-32s-14.326-32-32-32l-272 0.003v-271.997z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["add"],"defaultCode":59872,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":923,"name":"add","prevSize":32,"id":11,"code":59872},"setIdx":0,"setId":6,"iconIdx":12},{"icon":{"paths":["M512 928c-14.218 0-28.275-0.714-42.144-2.112-16.694-1.68-30.557-12.528-36.688-27.395l-40.538-98.304-98.162 40.838c-14.837 6.173-32.3 4.048-45.292-6.554-21.838-17.818-41.831-37.811-59.65-59.648-10.601-12.992-12.726-30.454-6.553-45.293l40.839-98.16-98.307-40.541c-14.864-6.131-25.714-19.994-27.395-36.688-1.396-13.869-2.111-27.926-2.111-42.144 0-14.214 0.714-28.275 2.11-42.141 1.681-16.694 12.531-30.557 27.395-36.688l98.308-40.541-40.84-98.163c-6.173-14.837-4.047-32.3 6.553-45.292 17.818-21.838 37.81-41.83 59.648-59.648 12.992-10.6 30.455-12.726 45.292-6.553l98.165 40.84 40.541-98.309c6.128-14.865 19.994-25.714 36.688-27.395 13.866-1.396 27.926-2.11 42.141-2.11s28.275 0.714 42.141 2.11c16.694 1.681 30.56 12.531 36.688 27.395l40.541 98.309 98.163-40.84c14.838-6.173 32.301-4.047 45.293 6.553 21.837 17.818 41.83 37.81 59.648 59.648 10.602 12.992 12.726 30.455 6.554 45.292l-40.842 98.163 98.31 40.541c14.864 6.131 25.712 19.994 27.392 36.688 1.398 13.866 2.112 27.926 2.112 42.141 0 14.218-0.714 28.275-2.112 42.144-1.68 16.694-12.528 30.557-27.395 36.688l-98.307 40.541 40.842 98.16c6.173 14.838 4.045 32.301-6.554 45.293-17.821 21.837-37.811 41.83-59.651 59.648-12.992 10.602-30.454 12.726-45.29 6.554l-98.163-40.838-40.538 98.304c-6.131 14.867-19.994 25.715-36.688 27.395-13.869 1.398-27.93 2.112-42.144 2.112zM444.451 757.984l43.386 105.2c7.981 0.541 16.038 0.816 24.163 0.816s16.182-0.275 24.163-0.816l43.382-105.2c9.456-22.925 35.731-33.808 58.627-24.285l105.056 43.709c12.157-10.602 23.578-22.022 34.179-34.179l-43.709-105.056c-9.526-22.893 1.36-49.171 24.282-58.624l105.203-43.386c0.541-7.978 0.816-16.038 0.816-24.163s-0.275-16.182-0.816-24.16l-105.203-43.386c-22.922-9.453-33.808-35.731-24.282-58.624l43.709-105.060c-10.602-12.156-22.022-23.577-34.176-34.177l-105.059 43.708c-22.896 9.525-49.171-1.359-58.627-24.283l-43.382-105.204c-7.981-0.54-16.038-0.815-24.163-0.815s-16.182 0.275-24.163 0.815l-43.386 105.204c-9.453 22.924-35.728 33.808-58.624 24.283l-105.058-43.708c-12.156 10.6-23.577 22.021-34.177 34.177l43.708 105.059c9.525 22.893-1.359 49.171-24.284 58.624l-105.203 43.386c-0.54 7.978-0.815 16.035-0.815 24.16 0 8.128 0.275 16.186 0.815 24.163l105.203 43.386c22.924 9.453 33.809 35.731 24.284 58.624l-43.708 105.056c10.601 12.157 22.022 23.578 34.178 34.179l105.056-43.709c22.896-9.523 49.171 1.36 58.624 24.285zM416 512c0-53.021 42.979-96 96-96s96 42.979 96 96c0 53.021-42.979 96-96 96s-96-42.979-96-96zM512 352c-88.365 0-160 71.635-160 160s71.635 160 160 160c88.365 0 160-71.635 160-160s-71.635-160-160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["administration"],"defaultCode":59662,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":924,"name":"administration","prevSize":32,"id":12,"code":59662},"setIdx":0,"setId":6,"iconIdx":13},{"icon":{"paths":["M878.739 567.622c-41.853-41.136-161.235-29.824-220.925-22.282-59.005-35.997-98.458-85.706-126.243-158.73 13.379-55.194 34.646-139.185 18.525-191.98-14.41-89.82-129.674-80.907-146.141-20.227-15.094 55.195-1.373 131.988 24.013 230.034-34.304 81.936-85.421 191.984-121.441 255.062-68.611 35.312-161.235 89.821-174.957 158.384-11.321 54.166 89.194 189.238 261.063-106.96 76.845-25.37 160.547-56.566 234.65-68.909 64.835 34.97 140.65 58.282 191.421 58.282 87.478 0 96.054-96.678 60.035-132.675zM199.152 834.342c17.496-46.97 84.048-101.133 104.288-119.99-65.18 103.875-104.288 122.39-104.288 119.99zM479.082 180.918c25.386 0 22.986 110.047 6.176 139.873-15.094-47.653-14.752-139.873-6.176-139.873zM395.379 649.216c33.274-57.936 61.747-126.845 84.733-187.526 28.474 51.766 64.838 93.251 103.258 121.706-71.354 14.739-133.446 44.909-187.99 65.821zM846.835 632.074c0 0-17.152 20.57-127.958-26.739 120.413-8.912 140.307 18.512 127.958 26.739z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["adobe-reader-monochromatic"],"defaultCode":59663,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":925,"name":"adobe-reader-monochromatic","prevSize":32,"id":13,"code":59663},"setIdx":0,"setId":6,"iconIdx":14},{"icon":{"paths":["M512 192c-13.056 0-25.578 5.187-34.813 14.419-9.232 9.233-14.419 21.755-14.419 34.812v162.462c0 12.122-6.848 23.2-17.686 28.621l-253.082 126.541v49.498l232.493-46.499c9.402-1.882 19.149 0.554 26.563 6.63 7.414 6.080 11.712 15.162 11.712 24.749v108.307c0 8.486-3.37 16.624-9.373 22.627l-44.781 44.781v47.789l91.501-36.602c7.629-3.050 16.141-3.050 23.77 0l91.501 36.602v-47.789l-44.781-44.781c-6.003-6.003-9.373-14.141-9.373-22.627v-108.307c0-9.587 4.298-18.669 11.712-24.749 7.414-6.077 17.162-8.512 26.563-6.63l232.493 46.499v-49.498l-253.082-126.541c-10.838-5.421-17.686-16.499-17.686-28.621v-162.462c0-13.057-5.187-25.579-14.419-34.812-9.235-9.232-21.757-14.419-34.813-14.419zM431.933 161.164c21.235-21.235 50.035-33.164 80.067-33.164s58.832 11.93 80.067 33.164c21.235 21.235 33.165 50.036 33.165 80.066v142.686l253.078 126.538c10.842 5.421 17.69 16.502 17.69 28.624v108.307c0 9.587-4.298 18.669-11.712 24.746s-17.162 8.512-26.563 6.63l-232.493-46.496v56.019l44.781 44.781c6 6 9.373 14.141 9.373 22.627v108.307c0 10.618-5.267 20.544-14.061 26.499-8.794 5.952-19.965 7.155-29.824 3.213l-123.501-49.402-123.501 49.402c-9.859 3.942-21.030 2.739-29.824-3.213-8.794-5.955-14.061-15.882-14.061-26.499v-108.307c0-8.486 3.373-16.627 9.373-22.627l44.781-44.781v-56.019l-232.492 46.496c-9.401 1.882-19.149-0.554-26.564-6.63s-11.712-15.158-11.712-24.746v-108.307c0-12.122 6.848-23.203 17.689-28.624l253.079-126.538v-142.686c0-30.031 11.93-58.831 33.165-80.066z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["airplane"],"defaultCode":59815,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":926,"id":14,"name":"airplane","prevSize":32,"code":59815},"setIdx":0,"setId":6,"iconIdx":15},{"icon":{"paths":["M448 188.865c0 33.615 27.251 60.865 60.864 60.865 33.616 0 60.867-27.25 60.867-60.865s-27.251-60.865-60.867-60.865c-33.613 0-60.864 27.25-60.864 60.865zM384 188.865c0 59.026 40.957 108.485 96 121.512v77.745c-44.314 11.69-78.986 47.13-89.578 91.878h-80.045c-13.027-55.043-62.486-96-121.512-96-68.961 0-124.865 55.904-124.865 124.864 0 68.963 55.904 124.867 124.865 124.867 56.762 0 104.678-37.875 119.854-89.731h83.361c12.227 41.773 45.696 74.47 87.92 85.61v77.744c-55.043 13.027-96 62.486-96 121.51 0 68.963 55.904 124.867 124.864 124.867 68.963 0 124.867-55.904 124.867-124.867 0-56.762-37.875-104.675-89.731-119.853v-79.437c42.163-11.171 75.578-43.846 87.789-85.574h77.222c15.178 51.856 63.091 89.731 119.853 89.731 68.963 0 124.867-55.904 124.867-124.867 0-68.96-55.904-124.864-124.867-124.864-59.024 0-108.483 40.957-121.51 96h-73.907c-10.579-44.707-45.194-80.122-89.446-91.843v-79.438c51.856-15.176 89.731-63.092 89.731-119.854 0-68.961-55.904-124.865-124.867-124.865-68.96 0-124.864 55.904-124.864 124.865zM828.864 569.731c-33.613 0-60.864-27.251-60.864-60.867 0-33.613 27.251-60.864 60.864-60.864 33.616 0 60.867 27.251 60.867 60.864 0 33.616-27.251 60.867-60.867 60.867zM188.865 569.731c-33.615 0-60.865-27.251-60.865-60.867 0-33.613 27.25-60.864 60.865-60.864s60.865 27.251 60.865 60.864c0 33.616-27.25 60.867-60.865 60.867zM451.069 508.864c0 33.616 27.251 60.867 60.867 60.867 33.613 0 60.864-27.251 60.864-60.867 0-33.613-27.251-60.864-60.864-60.864-33.616 0-60.867 27.251-60.867 60.864zM508.864 889.731c-33.613 0-60.864-27.251-60.864-60.867 0-33.613 27.251-60.864 60.864-60.864 33.616 0 60.867 27.251 60.867 60.864 0 33.616-27.251 60.867-60.867 60.867z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["all-contacts-in-channels"],"defaultCode":59664,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":927,"name":"all-contacts-in-channels","prevSize":32,"id":15,"code":59664},"setIdx":0,"setId":6,"iconIdx":16},{"icon":{"paths":["M861.437 160c17.67 0 32 14.327 32 32s-14.33 32-32 32h-384c-17.674 0-32-14.327-32-32s14.326-32 32-32h384zM334.717 442.397c-24.962 0-45.197-20.237-45.197-45.2 0-24.96 20.236-45.197 45.197-45.197 24.963 0 45.2 20.237 45.2 45.197 0 24.963-20.237 45.2-45.2 45.2zM334.717 506.397c-60.308 0-109.197-48.89-109.197-109.2 0-60.307 48.89-109.197 109.197-109.197 60.31 0 109.2 48.89 109.2 109.197 0 60.31-48.89 109.2-109.2 109.2zM456.278 535.504c-18.288-4.899-37.504-5.2-55.939-0.88l-45.005 10.547c-13.194 3.091-26.947 2.877-40.036-0.63l-31.676-8.483c-19.669-5.27-40.384-5.562-60.154-0.928-55.68 13.050-95.468 62.781-95.468 120.179v34.752c0 42.906 34.783 77.686 77.689 77.686h258.057c42.906 0 77.69-34.781 77.69-77.686v-43.587c0-52-34.928-97.514-85.158-110.97zM414.944 596.934c8.166-1.914 16.675-1.779 24.774 0.39 22.246 5.958 37.718 26.118 37.718 49.149v43.587c0 7.558-6.131 13.686-13.69 13.686h-258.057c-7.56 0-13.689-6.128-13.689-13.686v-34.752c0-27.469 19.123-51.552 46.072-57.869 9.556-2.24 19.564-2.086 28.99 0.438l31.676 8.483c23.277 6.237 47.738 6.621 71.2 1.12l45.005-10.547zM893.437 512c0-17.674-14.33-32-32-32h-224c-17.674 0-32 14.326-32 32s14.326 32 32 32h224c17.67 0 32-14.326 32-32zM861.437 640c17.67 0 32 14.326 32 32s-14.33 32-32 32h-192c-17.674 0-32-14.326-32-32s14.326-32 32-32h192zM893.437 352c0-17.674-14.33-32-32-32h-288c-17.674 0-32 14.326-32 32s14.326 32 32 32h288c17.67 0 32-14.326 32-32zM861.437 800c17.67 0 32 14.326 32 32s-14.33 32-32 32h-256c-17.674 0-32-14.326-32-32s14.326-32 32-32h256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["all-contacts-in-queue"],"defaultCode":59665,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":928,"name":"all-contacts-in-queue","prevSize":32,"id":16,"code":59665},"setIdx":0,"setId":6,"iconIdx":17},{"icon":{"paths":["M523.571 295.385c33.133 0 74.669-22.133 99.402-51.645 22.4-26.745 38.733-64.095 38.733-101.445 0-5.072-0.467-10.144-1.402-14.294-36.864 1.383-81.2 24.439-107.798 55.334-21.002 23.517-40.134 60.406-40.134 98.218 0 5.533 0.934 11.067 1.402 12.911 2.333 0.461 6.067 0.922 9.798 0.922zM406.906 853.334c45.267 0 65.334-29.974 121.798-29.974 57.402 0 70 29.050 120.4 29.050 49.469 0 82.602-45.187 113.869-89.456 34.998-50.72 49.466-100.522 50.4-102.829-3.267-0.922-98-39.194-98-146.634 0-93.146 74.666-135.107 78.867-138.333-49.469-70.090-124.602-71.935-145.136-71.935-55.533 0-100.8 33.199-129.264 33.199-30.8 0-71.402-31.354-119.469-31.354-91.466 0-184.333 74.701-184.333 215.802 0 87.61 34.533 180.294 77 240.24 36.402 50.723 68.133 92.224 113.867 92.224z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["apple-monochromatic"],"defaultCode":59666,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":929,"name":"apple-monochromatic","prevSize":32,"id":17,"code":59666},"setIdx":0,"setId":6,"iconIdx":18},{"icon":{"paths":["M498.694 141.561l-298.666 136.533c-11.39 5.207-18.696 16.58-18.696 29.103v386.844c0 11.818 6.513 22.675 16.941 28.237l298.667 159.286c9.411 5.021 20.707 5.021 30.118 0l298.666-159.286c10.429-5.562 16.941-16.419 16.941-28.237v-386.844c0-12.524-7.306-23.896-18.694-29.103l-298.666-136.533c-8.451-3.862-18.16-3.862-26.611 0zM245.333 357.011l234.667 107.277v335.709l-234.667-125.155v-317.83zM544 799.997l234.666-125.155v-317.83l-234.666 107.277v335.709zM512 408.544l-221.7-101.347 221.7-101.348 221.699 101.348-221.699 101.347z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["apps"],"defaultCode":59667,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":930,"name":"apps","prevSize":32,"id":18,"code":59667},"setIdx":0,"setId":6,"iconIdx":19},{"icon":{"paths":["M374.627 297.372c-12.496-12.497-32.758-12.497-45.254 0l-192 192c-12.497 12.496-12.497 32.758 0 45.254l192 192c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-137.372-137.373h578.745v128c0 17.674 14.326 32 32 32s32-14.326 32-32v-160c0-17.674-14.326-32-32-32h-610.745l137.372-137.373c12.496-12.496 12.496-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-back"],"defaultCode":59668,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":931,"name":"arrow-back","prevSize":32,"id":19,"code":59668},"setIdx":0,"setId":6,"iconIdx":20},{"icon":{"paths":["M551.392 242.502c0.189-17.672 14.669-31.845 32.339-31.656 17.674 0.189 31.846 14.668 31.658 32.34l-1.318 123.489 193.44-193.439c12.496-12.497 32.755-12.497 45.254 0 12.496 12.497 12.496 32.758 0 45.255l-193.44 193.439 123.488-1.318c17.674-0.189 32.154 13.984 32.339 31.654 0.189 17.674-13.984 32.154-31.654 32.342l-201.92 2.154c-8.605 0.093-16.886-3.283-22.97-9.37-6.086-6.083-9.462-14.365-9.373-22.97l2.157-201.92zM475.981 782.147c-0.189 17.674-14.669 31.846-32.339 31.658-17.674-0.189-31.846-14.669-31.658-32.342l1.318-123.488-193.438 193.44c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l193.438-193.44-123.488 1.318c-17.672 0.189-32.151-13.984-32.34-31.654-0.189-17.674 13.984-32.154 31.656-32.342l201.922-2.154c8.605-0.093 16.883 3.283 22.966 9.37 6.086 6.083 9.462 14.365 9.373 22.97l-2.157 201.92z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-collapse"],"defaultCode":59669,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":932,"name":"arrow-collapse","prevSize":32,"id":20,"code":59669},"setIdx":0,"setId":6,"iconIdx":21},{"icon":{"paths":["M576 672c-17.674 0-32 14.326-32 32s14.326 32 32 32h224c17.674 0 32-14.326 32-32v-208c0-17.674-14.326-32-32-32s-32 14.326-32 32v130.746l-233.373-233.373c-12.496-12.496-32.758-12.496-45.254 0l-73.373 73.373-169.372-169.373c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.759 0 45.255l192 192c12.496 12.496 32.758 12.496 45.254 0l73.373-73.373 210.746 210.746h-146.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-decrease"],"defaultCode":59670,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":933,"name":"arrow-decrease","prevSize":32,"id":21,"code":59670},"setIdx":0,"setId":6,"iconIdx":22},{"icon":{"paths":["M726.88 526.064c12.355 12.637 12.128 32.896-0.509 45.254l-191.968 187.715c-12.438 12.163-32.31 12.163-44.746 0l-191.97-187.715c-12.636-12.358-12.863-32.618-0.507-45.254 12.356-12.634 32.615-12.861 45.252-0.506l137.597 134.55v-372.109c0-17.673 14.33-32 32-32 17.674 0 32 14.327 32 32v372.109l137.6-134.55c12.634-12.355 32.896-12.128 45.251 0.506z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-down"],"defaultCode":59673,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":934,"name":"arrow-down","prevSize":32,"id":22,"code":59673},"setIdx":0,"setId":6,"iconIdx":23},{"icon":{"paths":["M329.373 550.627c-12.497-12.496-12.497-32.758 0-45.254s32.758-12.496 45.254 0l105.373 105.373v-418.746c0-17.673 14.326-32 32-32s32 14.327 32 32v418.746l105.373-105.373c12.496-12.496 32.758-12.496 45.254 0s12.496 32.758 0 45.254l-160 160c-12.496 12.496-32.758 12.496-45.254 0l-160-160zM112 864c0 17.674 14.327 32 32 32h768c17.674 0 32-14.326 32-32v-512c0-17.674-14.326-32-32-32h-96c-17.674 0-32 14.326-32 32s14.326 32 32 32h64v448h-704v-448h64c17.673 0 32-14.326 32-32s-14.327-32-32-32h-96c-17.673 0-32 14.326-32 32v512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-down-box"],"defaultCode":59671,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":935,"name":"arrow-down-box","prevSize":32,"id":23,"code":59671},"setIdx":0,"setId":6,"iconIdx":24},{"icon":{"paths":["M866.49 512c0-194.404-157.802-352-352.464-352-194.661 0-352.465 157.596-352.465 352s157.804 352 352.465 352c194.662 0 352.464-157.597 352.464-352zM930.576 512c0 229.75-186.496 416-416.55 416s-416.549-186.25-416.549-416c0-229.75 186.495-416 416.549-416s416.55 186.25 416.55 416zM696.525 571.37c12.682-12.33 12.957-32.589 0.611-45.251-12.342-12.666-32.63-12.938-45.309-0.611l-105.789 102.842v-276.349c0-17.674-14.346-32-32.045-32-17.696 0-32.042 14.326-32.042 32v276.349l-105.789-102.842c-12.678-12.326-32.966-12.054-45.309 0.611-12.344 12.662-12.071 32.922 0.608 45.251l160.182 155.715c12.438 12.093 32.259 12.093 44.701 0l160.179-155.715z"],"width":1056,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-down-circle"],"defaultCode":59672,"grid":0},"attrs":[{}],"properties":{"order":936,"name":"arrow-down-circle","prevSize":32,"id":24,"code":59672},"setIdx":0,"setId":6,"iconIdx":25},{"icon":{"paths":["M859.978 398.15c-0.189 17.67-14.666 31.843-32.339 31.654-17.67-0.189-31.846-14.666-31.658-32.339l1.318-123.488-193.437 193.437c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.755 0-45.254l193.437-193.437-123.488 1.318c-17.67 0.189-32.15-13.984-32.339-31.656s13.984-32.151 31.658-32.34l201.92-2.156c8.605-0.092 16.883 3.286 22.97 9.371 6.083 6.085 9.462 14.364 9.37 22.969l-2.157 201.922zM167.394 626.522c0.189-17.674 14.668-31.846 32.34-31.658s31.845 14.669 31.657 32.339l-1.319 123.488 193.438-193.437c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-193.438 193.437 123.489-1.318c17.67-0.189 32.15 13.984 32.339 31.658 0.189 17.67-13.984 32.15-31.658 32.339l-201.92 2.157c-8.605 0.093-16.884-3.286-22.969-9.37-6.085-6.086-9.463-14.365-9.371-22.97l2.156-201.92z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-expand"],"defaultCode":59674,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":937,"name":"arrow-expand","prevSize":32,"id":25,"code":59674},"setIdx":0,"setId":6,"iconIdx":26},{"icon":{"paths":["M623.488 420.944h-129.030c-146.778 0-279.962 128.675-298.822 309.533 98.511-81.834 219.072-127.946 345.446-127.946h82.406v123.408l188.595-214.202-188.595-214.2v123.406zM888.045 501.165c5.322 6.045 5.325 15.104 0 21.149l-300.547 341.354c-9.747 11.069-28.010 4.176-28.010-10.573v-186.563h-18.406c-15.286 0-30.496 0.774-45.594 2.298-112.397 11.35-218.514 64.397-302.132 150.954-2.078 2.15-4.142 4.32-6.191 6.512-7.238 7.741-14.299 15.738-21.173 23.984-2.611 3.133-5.195 6.301-7.751 9.504l-0.376 0.474c-9.438 11.834-28.508 5.158-28.508-9.978v-75.606c0-230.707 163.46-417.728 365.102-417.728h65.030v-186.56c0-14.749 18.262-21.643 28.010-10.573l300.547 341.354z"],"width":1056,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-forward"],"defaultCode":59841,"grid":0},"attrs":[{}],"properties":{"order":938,"id":26,"name":"arrow-forward","prevSize":32,"code":59841},"setIdx":0,"setId":6,"iconIdx":27},{"icon":{"paths":["M576 352c-17.674 0-32-14.326-32-32s14.326-32 32-32h224c17.674 0 32 14.327 32 32v208c0 17.674-14.326 32-32 32s-32-14.326-32-32v-130.746l-233.373 233.373c-12.496 12.496-32.758 12.496-45.254 0l-73.373-73.373-169.372 169.373c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l192-192c12.496-12.496 32.758-12.496 45.254 0l73.373 73.373 210.746-210.746h-146.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-increase"],"defaultCode":59675,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":939,"name":"arrow-increase","prevSize":32,"id":27,"code":59675},"setIdx":0,"setId":6,"iconIdx":28},{"icon":{"paths":["M297.766 105.372c12.513-12.497 32.801-12.497 45.316 0 12.512 12.497 12.512 32.758 0 45.255l-105.513 105.372h611.551c17.699 0 32.045 14.327 32.045 32v112c0 17.674-14.346 32-32.045 32-17.696 0-32.042-14.326-32.042-32v-80h-579.51l105.513 105.373c12.512 12.496 12.512 32.758 0 45.254-12.515 12.496-32.803 12.496-45.316 0l-160.212-160c-12.513-12.497-12.513-32.758 0-45.255l160.212-160zM711.568 918.627c-12.515 12.496-32.803 12.496-45.315 0-12.515-12.496-12.515-32.758 0-45.254l105.51-105.373h-611.552c-17.696 0-32.042-14.326-32.042-32v-112c0-17.674 14.346-32 32.042-32s32.042 14.326 32.042 32v80h579.509l-105.51-105.373c-12.515-12.496-12.515-32.758 0-45.254 12.512-12.496 32.8-12.496 45.315 0l160.211 160c12.512 12.496 12.512 32.758 0 45.254l-160.211 160z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-looping"],"defaultCode":59677,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":940,"name":"arrow-looping","prevSize":32,"id":28,"code":59677},"setIdx":0,"setId":6,"iconIdx":29},{"icon":{"paths":["M374.627 769.296c-12.496 12.496-32.758 12.496-45.254 0l-192-192c-12.497-12.496-12.497-32.758 0-45.254l192-192c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-137.372 137.373h578.745v-192h-192c-17.674 0-32-14.328-32-32.001s14.326-32 32-32h224c17.674 0 32 14.327 32 32v256.001c0 17.674-14.326 32-32 32h-610.745l137.372 137.373c12.496 12.496 12.496 32.758 0 45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-return"],"defaultCode":59678,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":941,"name":"arrow-return","prevSize":32,"id":29,"code":59678},"setIdx":0,"setId":6,"iconIdx":30},{"icon":{"paths":["M526.064 297.121c12.637-12.356 32.896-12.129 45.254 0.507l187.715 191.969c12.163 12.438 12.163 32.31 0 44.746l-187.715 191.971c-12.358 12.634-32.618 12.861-45.254 0.506-12.634-12.355-12.861-32.614-0.506-45.251l134.55-137.597h-372.109c-17.673 0-32-14.33-32-32 0-17.674 14.327-32 32-32h372.109l-134.55-137.6c-12.355-12.634-12.128-32.894 0.506-45.251z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-right"],"defaultCode":59838,"grid":0},"attrs":[{}],"properties":{"order":942,"id":30,"name":"arrow-right","prevSize":32,"code":59838},"setIdx":0,"setId":6,"iconIdx":31},{"icon":{"paths":["M297.181 498.090c-12.356-12.634-12.129-32.896 0.507-45.251l191.97-187.717c12.435-12.161 32.307-12.161 44.746 0l191.968 187.717c12.637 12.355 12.864 32.618 0.509 45.251-12.355 12.637-32.618 12.864-45.251 0.509l-137.6-134.55v372.109c0 17.674-14.326 32-32 32-17.67 0-32-14.326-32-32v-372.109l-137.597 134.55c-12.637 12.355-32.895 12.128-45.251-0.509z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-up"],"defaultCode":59680,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":943,"name":"arrow-up","prevSize":32,"id":31,"code":59680},"setIdx":0,"setId":6,"iconIdx":32},{"icon":{"paths":["M694.627 473.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-105.373-105.373v418.746c0 17.674-14.326 32-32 32s-32-14.326-32-32v-418.746l-105.373 105.373c-12.496 12.496-32.758 12.496-45.254 0s-12.497-32.758 0-45.254l160-160c12.496-12.497 32.758-12.497 45.254 0l160 160zM912 160c0-17.673-14.326-32-32-32h-768c-17.673 0-32 14.327-32 32v512c0 17.674 14.327 32 32 32h96c17.673 0 32-14.326 32-32s-14.327-32-32-32h-64v-448h704v448h-64c-17.674 0-32 14.326-32 32s14.326 32 32 32h96c17.674 0 32-14.326 32-32v-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-up-box"],"defaultCode":59679,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":944,"name":"arrow-up-box","prevSize":32,"id":32,"code":59679},"setIdx":0,"setId":6,"iconIdx":33},{"icon":{"paths":["M649.427 192c-26.454 0-52.016 10.804-71.005 30.343l-305.1 313.906c-31.48 32.387-49.322 76.506-49.322 122.694 0 46.186 17.842 90.304 49.322 122.694 31.451 32.355 73.91 50.362 117.984 50.362s86.531-18.006 117.981-50.362l305.101-313.907c12.317-12.672 32.576-12.96 45.248-0.643 12.675 12.317 12.963 32.576 0.646 45.251l-305.101 313.904c-43.302 44.554-102.23 69.757-163.875 69.757s-120.574-25.203-163.877-69.757c-43.273-44.522-67.428-104.717-67.428-167.299s24.155-122.781 67.428-167.302l305.1-313.905c30.845-31.735 72.874-49.737 116.899-49.737s86.054 18.002 116.899 49.737c30.816 31.704 47.971 74.514 47.971 118.968s-17.155 87.263-47.971 118.969l-305.43 313.904c-0.003 0.006 0.003-0.003 0 0-18.384 18.909-43.523 29.718-69.923 29.718-26.406 0-51.539-10.8-69.923-29.718-18.356-18.883-28.512-44.31-28.512-70.634 0-26.326 10.156-51.754 28.512-70.637l281.872-289.668c12.326-12.666 32.586-12.942 45.251-0.617s12.941 32.585 0.618 45.251l-281.846 289.638c-6.557 6.752-10.406 16.106-10.406 26.032 0 9.93 3.843 19.277 10.406 26.029 6.531 6.72 15.194 10.323 24.029 10.323s17.498-3.603 24.029-10.323l305.43-313.907c19.024-19.568 29.866-46.301 29.866-74.361 0-28.059-10.842-54.791-29.866-74.362-18.989-19.54-44.55-30.343-71.005-30.343z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["attach"],"defaultCode":59676,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":945,"name":"attach","prevSize":32,"id":33,"code":59676},"setIdx":0,"setId":6,"iconIdx":34},{"icon":{"paths":["M300.1 631.12h-113.433v-280.89h113.433l12.366-48.048c11.054-42.953 50.123-74.619 96.423-74.619h58.666v526.223h-58.666c-46.301 0-85.37-31.667-96.423-74.621l-12.366-48.045zM163.556 695.12h86.931c18.156 70.541 82.192 122.666 158.403 122.666h81.776c22.582 0 40.89-18.307 40.89-40.89v-572.444c0-22.582-18.307-40.889-40.89-40.889h-81.776c-76.211 0-140.247 52.124-158.403 122.667h-86.931c-22.582 0-40.889 18.306-40.889 40.89v327.11c0 22.582 18.307 40.89 40.889 40.89zM646.461 316.515c17.146-4.286 34.518 6.138 38.806 23.284l11.136 44.55c20.81 83.229 20.81 170.301 0 253.533l-11.136 44.55c-4.288 17.146-21.661 27.568-38.806 23.283-17.146-4.288-27.571-21.661-23.283-38.806l11.136-44.55c18.262-73.040 18.262-149.45 0.003-222.486l-11.139-44.55c-4.288-17.146 6.138-34.522 23.283-38.807zM807.472 235.936c-5.197-16.892-23.104-26.372-39.994-21.174-16.893 5.197-26.371 23.104-21.174 39.996l35.536 115.489c28.112 91.37 26.976 189.242-3.254 279.933l-32.054 96.16c-5.59 16.765 3.472 34.886 20.237 40.477 16.768 5.587 34.89-3.472 40.48-20.24l32.051-96.16c34.448-103.344 35.747-214.87 3.709-318.989l-35.536-115.491z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio"],"defaultCode":59683,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":946,"name":"audio","prevSize":32,"id":34,"code":59683},"setIdx":0,"setId":6,"iconIdx":35},{"icon":{"paths":["M866.128 153.127c-12.496-12.497-32.758-12.497-45.254 0l-668.246 668.245c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l668.246-668.245c12.496-12.497 12.496-32.758 0-45.255zM674.643 480.358l55.92-55.923c16.259 79.565 14.515 161.866-5.229 240.842l-11.622 46.49c-4.288 17.146-21.661 27.571-38.806 23.283-17.146-4.285-27.568-21.661-23.283-38.806l11.622-46.486c13.875-55.507 17.677-112.874 11.398-169.398zM817.162 385.923l-11.312-36.771 51.203-51.206 21.28 69.155c33.344 108.368 31.994 224.445-3.859 332.010l-33.45 100.342c-5.587 16.765-23.709 25.827-40.477 20.24-16.765-5.59-25.827-23.712-20.237-40.48l33.446-100.339c31.635-94.912 32.826-197.334 3.405-292.95zM490.666 664.333l64-64v210.346c0 23.562-19.101 42.666-42.666 42.666h-85.334c-35.459 0-68.394-10.816-95.683-29.325l46.611-46.611c14.701 7.629 31.395 11.936 49.072 11.936h64v-125.011zM128 682.678c0 19.738 13.403 36.346 31.604 41.216l62.552-62.55h-30.156v-298.666h118.99l12.367-48.049c11.843-46.020 53.696-79.953 103.309-79.953h64v158.155l64-64v-115.488c0-23.564-19.101-42.667-42.666-42.667h-85.334c-79.523 0-146.343 54.39-165.289 128h-90.71c-23.564 0-42.667 19.102-42.667 42.667v341.334z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio-disabled"],"defaultCode":59681,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":947,"name":"audio-disabled","prevSize":32,"id":35,"code":59681},"setIdx":0,"setId":6,"iconIdx":36},{"icon":{"paths":["M310.99 661.344h-118.99v-298.666h118.99l12.367-48.049c11.843-46.020 53.696-79.953 103.309-79.953h64v554.667h-64c-49.613 0-91.466-33.933-103.309-79.952l-12.367-48.048zM170.667 725.344h90.71c18.946 73.61 85.766 128 165.289 128h85.334c23.565 0 42.666-19.104 42.666-42.666v-597.335c0-23.564-19.101-42.667-42.666-42.667h-85.334c-79.523 0-146.343 54.39-165.289 128h-90.71c-23.564 0-42.667 19.102-42.667 42.667v341.334c0 23.562 19.103 42.666 42.667 42.666zM886.627 393.373c12.496 12.496 12.496 32.758 0 45.254l-73.373 73.373 73.373 73.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-73.373-73.373-73.373 73.373c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l73.373-73.373-73.373-73.373c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l73.373 73.373 73.373-73.373c12.496-12.496 32.758-12.496 45.254 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio-unavailable"],"defaultCode":59682,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":948,"name":"audio-unavailable","prevSize":32,"id":36,"code":59682},"setIdx":0,"setId":6,"iconIdx":37},{"icon":{"paths":["M418.704 128c-35.344 0-64 28.654-64 64v226.637c20.774-2.822 42.134-3.456 64-1.526v-225.11h176v180.707c0 35.344 28.656 64 64 64h176v331.293h-120.554c-17.155 22.179-36.323 43.869-57.312 64h177.866c35.347 0 64-28.653 64-64v-363.293c0-6.413-1.923-12.675-5.526-17.978l-156.63-230.681c-11.914-17.544-31.741-28.049-52.947-28.049h-264.896zM658.704 372.707v-180.707h24.896l122.698 180.707h-147.594zM167.939 668.547c120.524 156.138 218.24 174.586 285.133 158.739 73.293-17.36 139.232-81.648 183.466-151.763-115.155-155.869-211.581-174.589-279.149-158.915-74.362 17.251-142.707 81.683-189.45 151.939zM104.428 649.037c100.621-162.8 337.62-357.19 593.252 1.789 9.072 12.739 10.32 29.818 2.422 43.315-95.27 162.854-326.394 358.346-593.234-0.224-9.745-13.094-11.022-30.995-2.44-44.88zM401.664 735.994c31.514 0 60.269-26.858 60.269-64 0-37.146-28.755-64-60.269-64-31.51 0-60.266 26.854-60.266 64 0 37.142 28.755 64 60.266 64zM401.664 799.994c68.634 0 124.269-57.309 124.269-128 0-70.694-55.635-128-124.269-128-68.63 0-124.267 57.306-124.267 128 0 70.691 55.636 128 124.267 128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["auditing"],"defaultCode":59684,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":949,"name":"auditing","prevSize":32,"id":37,"code":59684},"setIdx":0,"setId":6,"iconIdx":38},{"icon":{"paths":["M224 224c-17.673 0-32 14.327-32 32v544c0 17.674 14.327 32 32 32h544c17.674 0 32-14.326 32-32v-544c0-17.673-14.326-32-32-32h-544zM128 256c0-53.019 42.981-96 96-96h544c53.021 0 96 42.981 96 96v544c0 53.021-42.979 96-96 96h-544c-53.019 0-96-42.979-96-96v-544zM608 460.813c0 41.798-26.714 77.357-64 90.538v133.462h-64v-133.462c-37.286-13.181-64-48.739-64-90.538 0-53.021 42.979-96 96-96s96 42.979 96 96zM608 588.826c38.861-29.19 64-75.667 64-128.013 0-88.365-71.635-160-160-160s-160 71.636-160 160c0 52.346 25.139 98.822 64 128.013v127.987c0 17.674 14.326 32 32 32h128c17.674 0 32-14.326 32-32v-127.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["auth"],"defaultCode":59685,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":950,"name":"auth","prevSize":32,"id":38,"code":59685},"setIdx":0,"setId":6,"iconIdx":39},{"icon":{"paths":["M513.35 554.019c66.467 0 120.349-52.493 120.349-117.242 0-64.752-53.882-117.243-120.349-117.243-66.464 0-120.346 52.491-120.346 117.243 0 64.749 53.882 117.242 120.346 117.242zM513.35 490.019c-32.704 0-56.346-25.405-56.346-53.242 0-27.84 23.642-53.242 56.346-53.242 32.707 0 56.349 25.402 56.349 53.242 0 27.837-23.642 53.242-56.349 53.242z","M365.478 894.144h-172.126c-17.673 0-32-14.33-32-32v-702.144c0-17.673 14.327-32 32-32h640.001c17.674 0 32 14.327 32 32v702.144c0 17.67-14.326 32-32 32h-172.128c-6.24 1.274-12.701 1.942-19.318 1.942h-257.11c-6.618 0-13.078-0.669-19.318-1.942zM225.353 830.144h68.244c-3.114-9.456-4.799-19.558-4.799-30.058v-93.446c0-56.109 37.881-105.142 92.172-119.309 19.171-5.002 39.264-5.312 58.579-0.902l42.778 9.766c20.051 4.579 40.909 4.259 60.81-0.934l28.070-7.325c20.694-5.398 42.384-5.734 63.232-0.973 60.534 13.821 103.469 67.664 103.469 129.754v83.37c0 10.499-1.686 20.602-4.8 30.058h68.246v-638.144h-576.001v638.144zM652.918 830.144c12.246-4.49 20.989-16.253 20.989-30.058v-83.37c0-32.234-22.288-60.186-53.715-67.36-10.822-2.47-22.083-2.298-32.826 0.506l-28.070 7.325c-29.853 7.789-61.139 8.272-91.216 1.405l-42.774-9.766c-9.293-2.122-18.957-1.974-28.176 0.432-26.112 6.813-44.333 30.397-44.333 57.382v93.446c0 13.805 8.742 25.568 20.989 30.058h279.133z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["avatar"],"defaultCode":59686,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":951,"name":"avatar","prevSize":32,"id":39,"code":59686},"setIdx":0,"setId":6,"iconIdx":40},{"icon":{"paths":["M737.779 361.376c12.499 12.496 12.499 32.758 0 45.254l-110.947 110.95 110.947 110.947c12.499 12.496 12.499 32.758 0 45.254-12.496 12.499-32.758 12.499-45.254 0l-110.947-110.947-110.95 110.947c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.758 0-45.254l110.95-110.947-110.95-110.95c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l110.95 110.95 110.947-110.95c12.496-12.496 32.758-12.496 45.254 0z","M312.246 218.073c12.061-16.393 31.2-26.073 51.552-26.073h468.202c35.347 0 64 28.654 64 64v512c0 35.347-28.653 64-64 64h-468.202c-20.352 0-39.491-9.68-51.552-26.074l-188.343-256c-16.598-22.56-16.598-53.293 0-75.853l188.343-256.001zM363.798 256l-188.343 256 188.343 256h468.202v-512h-468.202z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["backspace"],"defaultCode":59687,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":952,"name":"backspace","prevSize":32,"id":40,"code":59687},"setIdx":0,"setId":6,"iconIdx":41},{"icon":{"paths":["M896 512c0-212.077-171.923-384-384-384s-384 171.923-384 384c0 212.077 171.923 384 384 384s384-171.923 384-384zM480 544v286.419c-56.483-5.606-108.646-25.904-152.618-57.011 46.403-78.992 67.251-156.97 71.734-229.408h80.883zM334.8 544c-4.282 58.995-21.005 122.198-56.631 186.458-46.616-49.875-77.462-114.678-84.589-186.458h141.22zM398.954 480c-6.192-93.13-37.366-173.574-70.627-230.072 43.773-30.733 95.594-50.78 151.674-56.348v286.42h-81.046zM279.095 292.556c26.251 47.457 50.118 112.532 55.644 187.444h-141.159c7.174-72.253 38.381-137.437 85.515-187.444zM544 544h80.883c4.483 72.438 25.331 150.416 71.734 229.408-43.971 31.107-96.134 51.405-152.618 57.011v-286.419zM830.419 544c-7.126 71.779-37.971 136.582-84.589 186.458-35.626-64.259-52.349-127.462-56.63-186.458h141.219zM830.419 480h-141.158c5.526-74.912 29.395-139.987 55.645-187.444 47.133 50.008 78.339 115.192 85.514 187.444zM544 193.58c56.080 5.568 107.901 25.614 151.674 56.348-33.261 56.499-64.435 136.943-70.627 230.072h-81.046v-286.42z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["basketball"],"defaultCode":59776,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":953,"id":41,"name":"basketball","prevSize":32,"code":59776},"setIdx":0,"setId":6,"iconIdx":42},{"icon":{"paths":["M233.358 169.364c6.002-6.001 14.141-9.372 22.629-9.372l304.020 0.020c0 0 0.003 0 0 0 46.678 0 91.446 18.543 124.451 51.549 33.008 33.006 51.549 77.772 51.549 124.452s-18.541 91.443-51.549 124.451c-0.803 0.803-1.616 1.6-2.435 2.387 22.867 9.552 43.888 23.533 61.75 41.395 36.006 36.006 56.234 84.845 56.234 135.766s-20.227 99.757-56.234 135.763c-36.006 36.006-84.845 56.237-135.766 56.237l-352.024-0.019c-17.673-0.003-31.998-14.33-31.998-32v-608.001c0-8.487 3.372-16.627 9.373-22.628zM560.006 448.013c29.706 0 58.192-11.802 79.197-32.806 21.005-21.002 32.803-49.491 32.803-79.194 0-29.705-11.798-58.193-32.803-79.197s-49.491-32.804-79.197-32.804l-272.022-0.018v224.019h272.022zM287.984 512.013v255.981l320.022 0.019c0 0 0.003 0 0 0 33.949 0 66.506-13.488 90.512-37.491 24.003-24.006 37.488-56.563 37.488-90.509 0-33.949-13.485-66.506-37.488-90.512-24.006-24.003-56.563-37.488-90.512-37.488h-320.022z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["bold"],"defaultCode":59688,"grid":0},"attrs":[{}],"properties":{"order":954,"name":"bold","prevSize":32,"id":42,"code":59688},"setIdx":0,"setId":6,"iconIdx":43},{"icon":{"paths":["M352 445.437c0-17.67 14.326-32 32-32h256c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M352 322.557c0-17.672 14.326-31.999 32-31.999h256c17.674 0 32 14.327 32 31.999 0 17.674-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M864 679.68c0 17.674-14.326 32-32 32h-18.509c-8.218 40.547-8.218 82.333 0 122.88h19.789c16.966 0 30.72 13.754 30.72 30.72s-13.754 30.72-30.72 30.72h-545.28c-70.692 0-128-55.014-128-122.88v-453.12c0-106.038 85.961-192 192-192h480c17.674 0 32 14.327 32 32v519.68zM748.419 834.56c-6.787-40.678-6.787-82.202 0-122.88h-460.419c-35.346 0-64 27.507-64 61.44s28.654 61.44 64 61.44h460.419zM224 647.68h576v-455.68h-448c-70.692 0-128 57.308-128 128v327.68z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["book"],"defaultCode":59689,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":955,"name":"book","prevSize":32,"id":43,"code":59689},"setIdx":0,"setId":6,"iconIdx":44},{"icon":{"paths":["M193.603 416h-33.603c-17.673 0-32 14.326-32 32s14.327 32 32 32h704c17.674 0 32-14.326 32-32s-14.326-32-32-32h-33.603c-7.347-73.117-39.702-141.853-92.122-194.274-60.013-60.012-141.405-93.726-226.275-93.726s-166.262 33.714-226.274 93.726c-52.421 52.421-84.777 121.157-92.123 194.274zM330.979 266.981c48.010-48.010 113.126-74.981 181.021-74.981s133.011 26.971 181.021 74.981c40.403 40.404 65.907 92.923 72.973 149.019h-507.987c7.066-56.096 32.57-108.615 72.972-149.019z","M877.242 605.133c16.090-7.315 23.203-26.285 15.891-42.374-7.315-16.090-26.285-23.203-42.374-15.891l-127.558 57.981-127.558-57.981c-8.413-3.824-18.070-3.824-26.483 0l-127.558 57.981-127.558-57.981c-8.413-3.824-18.070-3.824-26.483 0l-140.8 64c-16.089 7.315-23.203 26.285-15.89 42.374s26.284 23.203 42.373 15.891l18.758-8.528v29.68c0 38.102 15.908 74.31 43.672 100.752 27.712 26.394 64.978 40.963 103.528 40.963h345.6c38.55 0 75.814-14.57 103.526-40.963 27.766-26.442 43.674-62.65 43.674-100.752v-64.589l45.242-20.563zM736.442 669.133l31.558-14.346v35.498c0 20.093-8.368 39.699-23.811 54.41-15.494 14.758-36.832 23.306-59.389 23.306h-345.6c-22.556 0-43.893-8.547-59.39-23.306-15.444-14.71-23.81-34.317-23.81-54.41v-58.771l44.8-20.362 127.558 57.981c8.413 3.824 18.070 3.824 26.483 0l127.558-57.981 127.558 57.981c8.413 3.824 18.070 3.824 26.483 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["burger"],"defaultCode":59813,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":956,"id":44,"name":"burger","prevSize":32,"code":59813},"setIdx":0,"setId":6,"iconIdx":45},{"icon":{"paths":["M224 224h320v576h-96v-112c0-8.835-7.165-16-16-16h-96c-8.835 0-16 7.165-16 16v112h-96v-576zM608 448h192v352h-192v-352zM832 384h-224v-192c0-17.673-14.326-32-32-32h-384c-17.673 0-32 14.327-32 32v640c0 17.674 14.327 32 32 32h640c17.674 0 32-14.326 32-32v-416c0-17.674-14.326-32-32-32zM304 288c-8.836 0-16 7.164-16 16v32c0 8.835 7.164 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.836-7.165-16-16-16h-32zM288 432c0-8.835 7.164-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.836 0-16-7.165-16-16v-32zM304 544c-8.836 0-16 7.165-16 16v32c0 8.835 7.164 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM416 304c0-8.836 7.165-16 16-16h32c8.835 0 16 7.164 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32zM432 416c-8.835 0-16 7.165-16 16v32c0 8.835 7.165 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM416 560c0-8.835 7.165-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32zM688 512c-8.835 0-16 7.165-16 16v32c0 8.835 7.165 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM672 656c0-8.835 7.165-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["business"],"defaultCode":59690,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":957,"name":"business","prevSize":32,"id":45,"code":59690},"setIdx":0,"setId":6,"iconIdx":46},{"icon":{"paths":["M277.831 157.44c0-16.259 13.181-29.44 29.44-29.44s29.439 13.181 29.439 29.44v58.876h353.28v-58.876c0-16.259 13.181-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.876h85.76c17.674 0 32 14.327 32 32v583.68c0 17.674-14.326 32-32 32h-642.559c-17.673 0-32-14.326-32-32v-583.68c0-1.105 0.056-2.196 0.165-3.272 1.639-16.136 15.266-28.728 31.835-28.728h85.76v-58.876zM802.63 392.957h-578.559v407.040h578.559v-407.040zM425.034 644.474c0-8.835 7.162-16 16-16h26.88c8.835 0 16 7.165 16 16v26.88c0 8.838-7.165 16-16 16h-26.88c-8.838 0-16-7.162-16-16v-26.88zM323.27 510.72c-8.836 0-15.999 7.162-15.999 16v26.88c0 8.835 7.163 16 15.999 16h26.88c8.838 0 16-7.165 16-16v-26.88c0-8.838-7.162-16-16-16h-26.88zM542.79 526.72c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.835-7.162 16-16 16h-26.88c-8.835 0-16-7.165-16-16v-26.88zM323.27 628.474c-8.835 0-15.999 7.165-15.999 16v26.88c0 8.838 7.164 16 15.999 16h26.88c8.838 0 16-7.162 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88zM542.79 644.474c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.838-7.162 16-16 16h-26.88c-8.835 0-16-7.162-16-16v-26.88zM441.030 510.72c-8.835 0-16 7.165-16 16v26.88c0 8.835 7.165 16 16 16h26.88c8.838 0 16-7.165 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88zM660.55 526.72c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.835-7.162 16-16 16h-26.88c-8.835 0-16-7.165-16-16v-26.88zM676.55 628.474c-8.835 0-16 7.165-16 16v26.88c0 8.838 7.165 16 16 16h26.88c8.838 0 16-7.162 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["calendar"],"defaultCode":59691,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":958,"name":"calendar","prevSize":32,"id":46,"code":59691},"setIdx":0,"setId":6,"iconIdx":47},{"icon":{"paths":["M256 202.672c0-17.673 19.102-32 42.667-32h255.999c23.565 0 42.669 14.327 42.669 32s-19.104 32-42.669 32h-255.999c-23.564 0-42.667-14.327-42.667-32zM160 383.994c0-5.891 4.776-10.666 10.667-10.666h511.999c5.891 0 10.669 4.774 10.669 10.666v85.334c0 11.376 6.038 21.894 15.859 27.632s21.949 5.83 31.856 0.243l97.83-55.165c2.531-1.427 4.858-3.19 6.912-5.248 6.72-6.717 18.208-1.958 18.208 7.546v263.318c0 9.504-11.488 14.262-18.208 7.542-2.054-2.054-4.381-3.818-6.912-5.245l-97.83-55.165c-9.907-5.587-22.035-5.494-31.856 0.243s-15.859 16.256-15.859 27.632v85.331c0 5.891-4.778 10.669-10.669 10.669h-511.999c-5.891 0-10.667-4.778-10.667-10.669v-384zM170.667 309.328c-41.237 0-74.667 33.43-74.667 74.666v384c0 41.238 33.429 74.669 74.667 74.669h511.999c41.238 0 74.669-33.43 74.669-74.669v-30.55l46.778 26.374c47.418 41.99 123.888 8.701 123.888-56.163v-263.318c0-64.864-76.47-98.157-123.888-56.166l-46.778 26.378v-30.554c0-41.235-33.43-74.666-74.669-74.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["camera"],"defaultCode":59696,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":959,"name":"camera","prevSize":32,"id":47,"code":59696},"setIdx":0,"setId":6,"iconIdx":48},{"icon":{"paths":["M866.128 153.126c-12.496-12.497-32.758-12.497-45.254 0l-668.246 668.246c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l668.246-668.246c12.496-12.497 12.496-32.758 0-45.255zM298.667 170.671c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h255.999c23.565 0 42.669-14.327 42.669-32s-19.104-32-42.669-32h-255.999zM574.173 309.327h-403.506c-41.237 0-74.667 33.428-74.667 74.667v384c0 6.010 0.71 11.856 2.051 17.453l61.949-61.949v-339.504c0-5.891 4.776-10.666 10.667-10.666h339.506l64-64.001zM376.339 778.659h306.326c5.891 0 10.669-4.774 10.669-10.666v-85.334c0-11.373 6.038-21.891 15.859-27.629s21.949-5.83 31.856-0.243l97.83 55.162c2.531 1.427 4.858 3.194 6.912 5.248 6.72 6.72 18.208 1.962 18.208-7.542v-263.322c0-9.501-11.488-14.262-18.208-7.542-2.054 2.054-4.381 3.821-6.912 5.248l-97.83 55.162c-9.907 5.587-22.035 5.494-31.856-0.243-9.821-5.734-15.859-16.256-15.859-27.629v-7.661l110.778-73.498c47.418-41.99 123.888-8.701 123.888 56.163v263.322c0 64.864-76.47 98.154-123.888 56.163l-46.778-26.378v30.554c0 41.238-33.43 74.666-74.669 74.666h-370.327l64.001-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["camera-disabled"],"defaultCode":59692,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":960,"name":"camera-disabled","prevSize":32,"id":48,"code":59692},"setIdx":0,"setId":6,"iconIdx":49},{"icon":{"paths":["M288 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h256c17.674 0 32-14.327 32-32s-14.326-32-32-32h-256z","M170.667 341.328c-23.564 0-42.667 19.104-42.667 42.666v384c0 23.565 19.102 42.669 42.667 42.669h511.999c23.565 0 42.669-19.104 42.669-42.669v-128l97.83 97.83c26.877 26.88 72.835 7.843 72.835-30.17v-263.318c0-38.013-45.958-57.050-72.835-30.173l-97.83 97.83v-128c0-23.562-19.104-42.666-42.669-42.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["camera-filled"],"defaultCode":59693,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":961,"name":"camera-filled","prevSize":32,"id":49,"code":59693},"setIdx":0,"setId":6,"iconIdx":50},{"icon":{"paths":["M196.731 191.997c0-15.807 12.814-28.622 28.622-28.622h128.001c15.805 0 28.621 12.814 28.621 28.622s-12.816 28.621-28.621 28.621h-128.001c-15.807 0-28.622-12.814-28.622-28.621z","M737.354 559.997c0 97.203-78.8 176-176 176-97.203 0-176-78.797-176-176s78.797-176 176-176c97.2 0 176 78.797 176 176zM673.354 559.997c0-61.856-50.144-112-112-112s-112 50.144-112 112c0 61.856 50.144 112 112 112s112-50.144 112-112z","M193.353 255.997c-35.346 0-64 28.654-64 64v448c0 35.347 28.654 64 64 64h640.001c35.344 0 64-28.653 64-64v-448c0-35.346-28.656-64-64-64h-640.001zM833.354 319.997v448h-640.001v-448h640.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["camera-photo"],"defaultCode":59694,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":962,"name":"camera-photo","prevSize":32,"id":50,"code":59694},"setIdx":0,"setId":6,"iconIdx":51},{"icon":{"paths":["M298.667 170.672c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h255.999c23.565 0 42.669-14.327 42.669-32s-19.104-32-42.669-32h-255.999z","M545.712 503.453c11.267-11.267 11.19-29.61-0.17-40.97s-29.706-11.437-40.973-0.17l-71.402 71.402-71.994-71.997c-11.363-11.36-29.706-11.437-40.973-0.17s-11.19 29.61 0.17 40.97l71.997 71.997-71.402 71.402c-11.266 11.267-11.19 29.61 0.17 40.97 11.363 11.36 29.706 11.437 40.973 0.17l71.402-71.402 71.997 71.997c11.36 11.36 29.702 11.437 40.97 0.17s11.19-29.61-0.17-40.97l-71.997-71.997 71.402-71.402z","M96 383.994c0-41.235 33.429-74.666 74.667-74.666h511.999c41.238 0 74.669 33.43 74.669 74.666v30.554l46.778-26.378c47.418-41.99 123.888-8.698 123.888 56.166v263.318c0 64.864-76.47 98.154-123.888 56.163l-46.778-26.374v30.55c0 41.238-33.43 74.669-74.669 74.669h-511.999c-41.237 0-74.667-33.43-74.667-74.669v-384zM170.667 373.328c-5.891 0-10.667 4.774-10.667 10.666v384c0 5.891 4.776 10.669 10.667 10.669h511.999c5.891 0 10.669-4.778 10.669-10.669v-85.331c0-11.376 6.038-21.894 15.859-27.632s21.949-5.83 31.856-0.243l97.83 55.165c2.531 1.427 4.858 3.19 6.912 5.245 6.72 6.72 18.208 1.962 18.208-7.542v-263.318c0-9.504-11.488-14.262-18.208-7.546-2.054 2.058-4.381 3.821-6.912 5.248l-97.83 55.165c-9.907 5.587-22.035 5.494-31.856-0.243s-15.859-16.256-15.859-27.632v-85.334c0-5.891-4.778-10.666-10.669-10.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["camera-unavailable"],"defaultCode":59695,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":963,"name":"camera-unavailable","prevSize":32,"id":51,"code":59695},"setIdx":0,"setId":6,"iconIdx":52},{"icon":{"paths":["M224.248 304.026c-49.642 68.947-66.502 152.646-66.502 207.968v1.453l-0.132 1.446c-9.702 106.717 28.59 181.93 90.135 234.006 62.938 53.254 152.152 83.731 244.197 93.958 91.965 10.218 193.27 1.446 273.306-15.482 40.022-8.461 73.616-18.733 97.443-29.075 9.245-4.013 16.438-7.786 21.734-11.126-2.464-1.565-5.446-3.306-9.002-5.197-9.222-4.912-19.779-9.578-30.733-14.368l-1.914-0.835c-9.667-4.221-20.47-8.941-28.656-13.517-14.835-8.298-29.389-17.734-40.006-27.776-5.222-4.941-11.165-11.571-15.146-19.827-4.208-8.742-7.226-21.792-1.306-35.597 31.978-74.621 47.178-115.494 54.538-142.483 6.874-25.2 6.874-37.888 6.874-58.064v-0.182c0-16.035-9.318-89.517-55.811-158.032-45.018-66.338-125.99-129.968-274.854-129.968-134.637 0-215.698 55.382-264.165 122.698zM172.309 266.63c60.333-83.796 160.606-149.302 316.103-149.302 171.136 0 271.494 75.037 327.811 158.032 54.842 80.819 66.854 167.338 66.854 193.968 0 22.384-0.022 41.696-9.126 75.088-8.131 29.805-23.485 70.928-51.946 137.923 5.261 4.166 13.072 9.306 23.36 15.062 5.315 2.97 13.485 6.55 24.963 11.568 10.653 4.659 23.437 10.266 35.174 16.515 11.258 5.994 24.416 14.029 34.202 24.538 10.234 10.992 20.973 29.846 13.299 52.864-5.056 15.168-16.794 25.939-26.576 33.094-10.63 7.776-23.818 14.762-38.253 21.030-29.008 12.589-67.030 23.962-109.683 32.982-85.309 18.038-193.581 27.587-293.616 16.474-99.955-11.107-202.74-44.634-278.468-108.71-76.833-65.011-123.811-159.994-112.66-287.222 0.286-65.549 19.841-162.349 78.561-243.904zM493.744 320c17.674 0 32 14.326 32 32v224c0 17.674-14.326 32-32 32s-32-14.326-32-32v-224c0-17.674 14.326-32 32-32zM525.744 672c0-17.674-14.326-32-32-32s-32 14.326-32 32c0 17.674 14.326 32 32 32s32-14.326 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["canned-response"],"defaultCode":59697,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":964,"name":"canned-response","prevSize":32,"id":52,"code":59697},"setIdx":0,"setId":6,"iconIdx":53},{"icon":{"paths":["M193.352 181.331c-53.020 0-96 42.981-96 96v469.335c0 53.018 42.98 96 96 96h639.999c53.021 0 96-42.982 96-96v-469.335c0-53.019-42.979-96-96-96h-639.999zM161.352 277.331c0-17.673 14.327-32 32-32h639.999c17.674 0 32 14.327 32 32v202.673h-703.999v-202.673zM161.352 544.003h703.999v202.662c0 17.67-14.326 32-32 32h-639.999c-17.673 0-32-14.33-32-32v-202.662zM812.016 661.331c0-35.347-28.653-64-64-64-35.344 0-64 28.653-64 64s28.656 64 64 64c35.347 0 64-28.653 64-64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["card"],"defaultCode":59698,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":965,"name":"card","prevSize":32,"id":53,"code":59698},"setIdx":0,"setId":6,"iconIdx":54},{"icon":{"paths":["M368 182.4c0-17.673-14.326-32-32-32s-32 14.327-32 32v144h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v288h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v144c0 17.674 14.327 32 32 32s32-14.326 32-32v-144h288v144c0 17.674 14.326 32 32 32s32-14.326 32-32v-144h144c17.674 0 32-14.326 32-32s-14.326-32-32-32h-144v-80h-64v80h-288v-288h80v-64h-80v-144z","M640.515 327.283c-15.328-3.59-31.306-3.338-46.512 0.733-41.763 11.187-70.803 49.030-70.803 92.269v35.539c0 36.003 29.187 65.194 65.194 65.194h210.413c36.006 0 65.194-29.19 65.194-65.194v-28.336c0-47.667-33.040-88.957-79.27-99.792-16.413-3.846-33.613-3.603-49.946 0.771l-25.827 6.918c-10.381 2.781-21.286 2.95-31.747 0.499l-36.694-8.602z","M782.637 217.037c0 49.174-39.862 89.037-89.037 89.037s-89.037-39.863-89.037-89.037c0-49.174 39.862-89.037 89.037-89.037s89.037 39.863 89.037 89.037z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["channel-auto-join"],"defaultCode":59746,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":966,"name":"channel-auto-join","prevSize":32,"id":54,"code":59746},"setIdx":0,"setId":6,"iconIdx":55},{"icon":{"paths":["M236.709 162.578c11.779-5.037 25.426-2.564 34.688 6.286l150.709 144c6.32 6.037 9.894 14.396 9.894 23.136s-3.574 17.101-9.894 23.136l-150.709 144c-9.262 8.851-22.909 11.325-34.688 6.288s-19.419-16.614-19.419-29.424v-112h-73.29c-17.673 0-32-14.326-32-32 0-17.672 14.327-31.999 32-31.999h73.29v-112c0-12.81 7.64-24.386 19.419-29.423zM320 368.179v-0.179h0.189l-0.189 0.179zM320.189 304.001h-0.189v-0.179l0.189 0.179z","M492.899 303.258c8.762-9.388 21.245-15.258 35.101-15.258 26.509 0 48 21.49 48 48s-21.491 48-48 48c-16.582 0-31.203-8.41-39.824-21.197l-43.098 48.483c20.49 22.554 50.051 36.714 82.922 36.714 61.856 0 112-50.144 112-112s-50.144-112-112-112c-25.549 0-49.098 8.554-67.942 22.955l32.842 56.303z","M145.615 483.229l32.174 64.349c-0.861 3.040-1.318 6.23-1.318 9.501v44.688c0 17.674 14.327 32 32 32h79.53v64h-79.53c-53.019 0-96-42.979-96-96v-44.688c0-28.848 12.515-55.488 33.144-73.85z","M625.267 640h-0.797c0.259 0.598 0.525 1.194 0.797 1.786v-1.786z","M424.714 640h-0.797v1.786c0.272-0.592 0.538-1.187 0.797-1.786z","M477.901 494.515c-28.56-10.957-60.291-10.211-88.307 2.067-42.282 18.534-69.594 60.326-69.594 106.49v132.928c0 53.021 42.979 96 96 96h224c53.021 0 96-42.979 96-96v-125.062c0-51.162-31.536-97.034-79.306-115.354-30.352-11.642-64.067-10.851-93.84 2.198l-2.070 0.909c-21.523 9.434-45.901 10.006-67.843 1.59l-15.040-5.766zM415.286 555.2c12.595-5.52 26.858-5.856 39.699-0.931l15.040 5.77c37.664 14.445 79.504 13.462 116.451-2.73l2.070-0.909c14.349-6.288 30.602-6.669 45.229-1.059 23.024 8.829 38.224 30.938 38.224 55.597v125.062c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32v-132.928c0-20.752 12.278-39.539 31.286-47.872z","M864 320c0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96s96-42.979 96-96zM800 320c0 17.674-14.326 32-32 32s-32-14.326-32-32c0-17.673 14.326-32 32-32s32 14.327 32 32z","M840.714 697.766h-72.714v-64h72.714c17.674 0 32-14.326 32-32v-44.688c0-15.050-9.664-28.394-23.958-33.091-7.536-2.474-15.69-2.304-23.114 0.483l-4.554 1.709c-19.77 7.421-40.89 9.978-61.619 7.632-12.438-31.683-37.722-57.549-70.774-70.227-1.754-0.672-3.52-1.302-5.296-1.894 18.058-5.312 37.36-5.040 55.344 0.867l14.182 4.659c14.886 4.893 30.998 4.554 45.667-0.954l4.554-1.709c21.069-7.91 44.205-8.394 65.581-1.37 40.566 13.325 67.987 51.197 67.987 93.894v44.688c0 53.021-42.982 96-96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["channel-move-to-team"],"defaultCode":59747,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":967,"name":"channel-move-to-team","prevSize":32,"id":55,"code":59747},"setIdx":0,"setId":6,"iconIdx":56},{"icon":{"paths":["M368 160c0-17.673-14.326-32-32-32s-32 14.327-32 32v144h-144c-17.673 0-32 14.327-32 32s14.327 32 32 32h144v288h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v144c0 17.674 14.327 32 32 32s32-14.326 32-32v-144h288v144c0 17.674 14.326 32 32 32s32-14.326 32-32v-144h144c17.674 0 32-14.326 32-32s-14.326-32-32-32h-144v-80h-58.666c-1.786 0-3.565-0.042-5.334-0.118v80.118h-288v-288h168.79c-0.522-5.264-0.79-10.602-0.79-16v-48h-168v-144z","M760 96c-57.437 0-104 46.562-104 104v56h-24c-17.674 0-32 14.327-32 32v192c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-192c0-17.673-14.326-32-32-32h-24v-56c0-57.438-46.563-104-104-104zM800 255.238h-80v-55.238c0-22.092 17.907-40 40-40s40 17.908 40 40v55.238z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["channel-private"],"defaultCode":59699,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":968,"name":"channel-private","prevSize":32,"id":56,"code":59699},"setIdx":0,"setId":6,"iconIdx":57},{"icon":{"paths":["M336 128c17.674 0 32 14.327 32 32v144h288v-144c0-17.673 14.326-32 32-32s32 14.327 32 32v144h144c17.674 0 32 14.327 32 32s-14.326 32-32 32h-144v288h144c17.674 0 32 14.326 32 32s-14.326 32-32 32h-144v144c0 17.674-14.326 32-32 32s-32-14.326-32-32v-144h-288v144c0 17.674-14.326 32-32 32s-32-14.326-32-32v-144h-144c-17.673 0-32-14.326-32-32s14.327-32 32-32h144v-288h-144c-17.673 0-32-14.326-32-32s14.327-32 32-32h144v-144c0-17.673 14.327-32 32-32zM368 368v288h288v-288h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["channel-public"],"defaultCode":59700,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":969,"name":"channel-public","prevSize":32,"id":57,"code":59700},"setIdx":0,"setId":6,"iconIdx":58},{"icon":{"paths":["M886.627 105.372c12.496 12.497 12.496 32.758 0 45.255l-89.373 89.372 89.373 89.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-89.373-89.372-89.373 89.372c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l89.373-89.373-89.373-89.372c-12.496-12.497-12.496-32.758 0-45.255s32.758-12.497 45.254 0l89.373 89.373 89.373-89.373c12.496-12.497 32.758-12.497 45.254 0zM226.501 304.042c-49.642 68.947-66.502 152.646-66.502 207.968v1.453l-0.132 1.446c-9.701 106.717 28.59 181.93 90.135 234.006 62.938 53.254 152.151 83.731 244.196 93.958 91.968 10.218 193.27 1.446 273.309-15.482 40.019-8.461 73.613-18.733 97.44-29.075 9.245-4.013 16.438-7.786 21.738-11.126-2.467-1.565-5.446-3.306-9.005-5.2-9.222-4.909-19.776-9.574-30.733-14.365l-1.917-0.838c-9.667-4.221-20.47-8.938-28.653-13.517-14.835-8.294-29.389-17.731-40.003-27.773-5.226-4.941-11.168-11.571-15.146-19.827-4.211-8.742-7.226-21.792-1.309-35.6 42.086-98.205 54.957-137.722 59.219-163.318 2.906-17.434 19.392-29.21 36.822-26.307 17.434 2.906 29.213 19.389 26.307 36.822-5.453 32.749-20.333 76.41-58.006 165.088 5.261 4.166 13.069 9.306 23.357 15.059 5.315 2.973 13.485 6.554 24.963 11.571 10.656 4.656 23.437 10.266 35.174 16.515 11.261 5.994 24.419 14.029 34.202 24.538 10.234 10.992 20.973 29.846 13.299 52.864-5.053 15.168-16.794 25.939-26.576 33.094-10.627 7.776-23.814 14.762-38.253 21.027-29.005 12.592-67.027 23.965-109.68 32.986-85.312 18.038-193.584 27.587-293.616 16.47-99.955-11.104-202.742-44.63-278.471-108.707-76.833-65.014-123.811-159.997-112.66-287.222 0.286-65.549 19.841-162.349 78.561-243.904 60.333-83.796 160.605-149.302 316.103-149.302 17.674 0 32 14.327 32 32s-14.326 32-32 32c-134.637 0-215.697 55.382-264.164 122.698z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chat-close"],"defaultCode":59701,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":970,"name":"chat-close","prevSize":32,"id":58,"code":59701},"setIdx":0,"setId":6,"iconIdx":59},{"icon":{"paths":["M778 93.833c-11.795-13.162-32.026-14.271-45.187-2.477s-14.272 32.025-2.477 45.187l81.222 90.645h-216.358c-17.674 0-32 14.327-32 32s14.326 32 32 32h216.358l-81.222 90.646c-11.795 13.162-10.685 33.392 2.477 45.187 13.162 11.792 33.392 10.685 45.187-2.477l129.030-144.001c10.893-12.154 10.893-30.556 0-42.71l-129.030-144zM159.999 512.010c0-55.322 16.86-139.021 66.502-207.968 48.467-67.316 129.527-122.698 264.164-122.698 17.674 0 32-14.327 32-32s-14.326-32-32-32c-155.498 0-255.77 65.507-316.102 149.302-58.72 81.555-78.275 178.355-78.561 243.904-11.151 127.229 35.827 222.211 112.66 287.222 75.729 64.077 178.516 97.603 278.471 108.707 100.032 11.117 208.304 1.568 293.616-16.47 42.653-9.021 80.675-20.394 109.68-32.982 14.438-6.269 27.626-13.254 38.253-21.030 9.782-7.155 21.523-17.926 26.579-33.094 7.67-23.018-3.069-41.872-13.302-52.864-9.782-10.509-22.941-18.544-34.202-24.538-11.738-6.25-24.518-11.859-35.171-16.515-11.482-5.018-19.651-8.598-24.966-11.571-10.288-5.754-18.096-10.89-23.357-15.059 37.674-88.678 52.554-132.339 58.010-165.088 2.902-17.43-8.877-33.917-26.31-36.822-17.43-2.902-33.917 8.877-36.822 26.307-4.262 25.597-17.133 65.114-59.219 163.318-5.917 13.808-2.902 26.858 1.309 35.6 3.978 8.256 9.92 14.886 15.146 19.827 10.614 10.042 25.171 19.478 40.003 27.776 8.186 4.576 18.989 9.296 28.656 13.517v0l1.914 0.835c10.957 4.79 21.51 9.456 30.733 14.368 3.558 1.891 6.541 3.632 9.005 5.197-5.299 3.341-12.493 7.114-21.738 11.126-23.827 10.342-57.421 20.614-97.44 29.075-80.038 16.928-181.341 25.699-273.309 15.482-92.045-10.227-181.258-40.704-244.196-93.958-61.545-52.077-99.836-127.29-90.135-234.006l0.132-1.446v-1.453z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chat-forward"],"defaultCode":59702,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":971,"name":"chat-forward","prevSize":32,"id":59,"code":59702},"setIdx":0,"setId":6,"iconIdx":60},{"icon":{"paths":["M854.506 233.252c12.563 12.429 12.672 32.691 0.243 45.254l-474.877 480c-6.013 6.077-14.208 9.498-22.755 9.494-8.55-0.003-16.742-3.427-22.752-9.507l-165.126-167.088c-12.423-12.57-12.303-32.832 0.268-45.254s32.831-12.304 45.254 0.269l142.375 144.067 452.115-456.992c12.429-12.564 32.691-12.672 45.254-0.243z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["check"],"defaultCode":59703,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":972,"name":"check","prevSize":32,"id":60,"code":59703},"setIdx":0,"setId":6,"iconIdx":61},{"icon":{"paths":["M204.8 128h614.4c42.416 0 76.8 34.385 76.8 76.8v614.4c0 42.416-34.384 76.8-76.8 76.8h-614.4c-42.415 0-76.8-34.384-76.8-76.8v-614.4c0-42.415 34.385-76.8 76.8-76.8zM769.062 336.88c9.322-9.424 9.238-24.619-0.182-33.941-9.424-9.322-24.621-9.241-33.942 0.182l-339.085 342.745-106.782-108.051c-9.317-9.43-24.513-9.52-33.94-0.202s-9.518 24.512-0.201 33.939l123.842 125.318c4.509 4.56 10.653 7.126 17.066 7.13s12.557-2.563 17.069-7.12l356.157-360z"],"attrs":[{"fill":"rgb(29, 116, 245)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":5}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":4}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":6}]},"tags":["checkbox-checked"],"defaultCode":59654,"grid":0},"attrs":[{"fill":"rgb(29, 116, 245)"}],"properties":{"order":973,"name":"checkbox-checked","prevSize":32,"id":61,"code":59654},"setIdx":0,"setId":6,"iconIdx":62},{"icon":{"paths":["M819.2 204.8v614.4h-614.4v-614.4h614.4zM204.8 128c-42.415 0-76.8 34.385-76.8 76.8v614.4c0 42.416 34.385 76.8 76.8 76.8h614.4c42.416 0 76.8-34.384 76.8-76.8v-614.4c0-42.415-34.384-76.8-76.8-76.8h-614.4z"],"attrs":[{"fill":"rgb(203, 206, 209)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":8}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":8}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":10}]},"tags":["checkbox-unchecked"],"defaultCode":59653,"grid":0},"attrs":[{"fill":"rgb(203, 206, 209)"}],"properties":{"order":974,"name":"checkbox-unchecked","prevSize":32,"id":62,"code":59653},"setIdx":0,"setId":6,"iconIdx":63},{"icon":{"paths":["M281.372 436.042c12.497-12.499 32.758-12.499 45.255 0l185.373 185.373 185.373-185.373c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-208 208c-12.496 12.496-32.758 12.496-45.254 0l-208-208c-12.497-12.496-12.497-32.758 0-45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-down"],"defaultCode":59704,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":975,"name":"chevron-down","prevSize":32,"id":63,"code":59704},"setIdx":0,"setId":6,"iconIdx":64},{"icon":{"paths":["M587.962 281.372c12.496 12.497 12.496 32.758 0 45.255l-185.373 185.373 185.373 185.373c12.496 12.496 12.496 32.758 0 45.254-12.499 12.496-32.758 12.496-45.258 0l-208-208c-12.496-12.496-12.496-32.758 0-45.254l208-208c12.499-12.497 32.758-12.497 45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-left"],"defaultCode":59706,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":976,"name":"chevron-left","prevSize":32,"id":64,"code":59706},"setIdx":0,"setId":6,"iconIdx":65},{"icon":{"paths":["M670.17 183.165c16.662 16.662 16.662 43.677 0 60.34l-268.496 268.495 268.496 268.499c16.662 16.662 16.662 43.677 0 60.339s-43.677 16.662-60.339 0l-298.668-298.669c-8.002-8-12.497-18.851-12.497-30.17 0-11.315 4.495-22.166 12.497-30.17l298.668-298.666c16.662-16.662 43.677-16.662 60.339 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-left-big"],"defaultCode":59705,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":977,"name":"chevron-left-big","prevSize":32,"id":65,"code":59705},"setIdx":0,"setId":6,"iconIdx":66},{"icon":{"paths":["M436.038 742.627c-12.496-12.496-12.496-32.758 0-45.254l185.373-185.373-185.373-185.373c-12.496-12.497-12.496-32.758 0-45.254 12.499-12.497 32.758-12.497 45.254 0l208 208c12.499 12.496 12.499 32.758 0 45.254l-207.997 208c-12.499 12.496-32.758 12.496-45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-right"],"defaultCode":59707,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":978,"name":"chevron-right","prevSize":32,"id":66,"code":59707},"setIdx":0,"setId":6,"iconIdx":67},{"icon":{"paths":["M742.627 587.958c-12.496 12.499-32.758 12.499-45.254 0l-185.373-185.373-185.373 185.373c-12.496 12.499-32.758 12.499-45.254 0-12.497-12.496-12.497-32.758 0-45.254l208-208c12.496-12.496 32.758-12.496 45.254 0l208 208c12.496 12.496 12.496 32.758 0 45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-up"],"defaultCode":59708,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":979,"name":"chevron-up","prevSize":32,"id":67,"code":59708},"setIdx":0,"setId":6,"iconIdx":68},{"icon":{"paths":["M512 864c194.403 0 352-157.597 352-352 0-46.522-9.024-90.931-25.418-131.581l48.518-48.518c26.211 54.496 40.899 115.581 40.899 180.099 0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416 95.376 0 183.254 32.096 253.424 86.076l-45.712 45.712c-58.221-42.623-130.029-67.788-207.712-67.788-194.404 0-352 157.596-352 352s157.596 352 352 352zM902.63 230.623c12.496-12.499 12.493-32.76-0.006-45.255s-32.762-12.491-45.254 0.008l-345.386 345.503-105.341-105.491c-12.486-12.506-32.749-12.522-45.254-0.032-12.506 12.486-12.522 32.749-0.032 45.254l127.971 128.157c6 6.006 14.144 9.386 22.634 9.389 8.493 0 16.637-3.373 22.64-9.376l368.029-368.157z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["circle-check"],"defaultCode":59709,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":980,"name":"circle-check","prevSize":32,"id":68,"code":59709},"setIdx":0,"setId":6,"iconIdx":69},{"icon":{"paths":["M608 192c0-53.019-42.979-96-96-96s-96 42.981-96 96h-192c-17.673 0-32 14.327-32 32v672c0 17.674 14.327 32 32 32h576c17.674 0 32-14.326 32-32v-672c0-17.673-14.326-32-32-32h-192zM256 864v-608h96v64c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-64h96v608h-512zM512 224c17.674 0 32-14.327 32-32s-14.326-32-32-32c-17.674 0-32 14.327-32 32s14.326 32 32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["clipboard"],"defaultCode":59710,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":981,"name":"clipboard","prevSize":32,"id":69,"code":59710},"setIdx":0,"setId":6,"iconIdx":70},{"icon":{"paths":["M864 512c0 194.403-157.597 352-352 352s-352-157.597-352-352c0-194.404 157.596-352 352-352s352 157.596 352 352zM928 512c0-229.75-186.25-416-416-416s-416 186.25-416 416c0 229.75 186.25 416 416 416s416-186.25 416-416zM544 288c0-17.673-14.326-32-32-32s-32 14.327-32 32v224c0 8.486 3.373 16.627 9.373 22.627l96 96c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-86.627-86.627v-210.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["clock"],"defaultCode":59711,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":982,"name":"clock","prevSize":32,"id":70,"code":59711},"setIdx":0,"setId":6,"iconIdx":71},{"icon":{"paths":["M806.627 262.628c12.496-12.497 12.496-32.758 0-45.255s-32.758-12.497-45.254 0l-249.373 249.373-249.372-249.373c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l249.373 249.372-249.373 249.373c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l249.372-249.373 249.373 249.373c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-249.373-249.373 249.373-249.372z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["close"],"defaultCode":59712,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":983,"name":"close","prevSize":32,"id":71,"code":59712},"setIdx":0,"setId":6,"iconIdx":72},{"icon":{"paths":["M273.129 356.678c6.747-28.298 25.696-52.004 51.21-67.152 25.6-15.2 56.323-20.858 84.698-14.53 27.642 6.163 55.117 24.12 74.874 60.339l22.541 41.325 30.134-36.16c27.238-32.689 85.126-39.713 134.714-14.064 23.562 12.186 42.208 30.618 52.064 53.488 9.654 22.406 12.112 51.898-1.434 89.149l-15.616 42.938h45.686c53.606 0 82.419 15.882 97.642 33.75 15.651 18.374 21.898 44.646 18.557 74.714-3.344 30.083-16.054 60.518-33.456 82.89-17.939 23.066-36.646 32.646-50.742 32.646h-543.998c-18.791 0-37.068-10.362-52.195-31.578-15.217-21.344-24.978-51.050-25.818-81.312-0.84-30.227 7.237-57.914 23.733-77.491 15.796-18.746 42.268-33.619 86.279-33.619h59.791l-33.165-49.75c-27.882-41.824-32.118-77.814-25.498-105.581zM518.218 272.084c-26.339-32.073-59.667-51.619-95.251-59.554-45.626-10.174-92.902-0.833-131.301 21.965-38.487 22.85-69.538 60.142-80.791 107.342-8.278 34.72-5.369 72.758 10.731 111.77-35.67 8.464-64.099 26.186-84.825 50.784-29.004 34.422-39.927 78.733-38.766 120.506 1.159 41.738 14.399 84.032 37.682 116.688 23.373 32.784 59.097 58.426 104.306 58.426h543.999c41.907 0 77.2-26.419 101.261-57.354 24.598-31.629 41.888-73.197 46.544-115.114 4.659-41.933-3.094-87.658-33.443-123.283-24.106-28.301-59.504-46.774-105.616-53.456 5.83-35.194 1.686-67.674-10.605-96.205-16.646-38.628-46.998-67.197-81.437-85.010-54.902-28.397-128.733-32.652-182.486 2.495zM512 437.331c17.674 0 32 14.33 32 32v53.328h53.334c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-53.334v53.341c0 17.674-14.326 32-32 32s-32-14.326-32-32v-53.341h-53.331c-17.674 0-32-14.326-32-32 0-17.67 14.326-32 32-32h53.331v-53.328c0-17.67 14.326-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["cloud-connectivity"],"defaultCode":59713,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":984,"name":"cloud-connectivity","prevSize":32,"id":72,"code":59713},"setIdx":0,"setId":6,"iconIdx":73},{"icon":{"paths":["M630.157 204.798c16.493 6.344 24.723 24.859 18.378 41.355l-213.331 554.667c-6.346 16.496-24.861 24.723-41.357 18.381-16.493-6.346-24.723-24.861-18.378-41.357l213.331-554.666c6.346-16.495 24.861-24.724 41.357-18.38zM321.296 361.37c12.496 12.499 12.496 32.758 0 45.258l-105.373 105.37 105.373 105.373c12.496 12.499 12.496 32.758 0 45.258-12.497 12.496-32.759 12.496-45.255 0l-128-128c-12.497-12.499-12.497-32.758 0-45.258l128-128c12.497-12.496 32.758-12.496 45.255 0zM702.707 361.37c12.496-12.496 32.758-12.496 45.254 0l128 128c12.496 12.499 12.496 32.758 0 45.258l-128 128c-12.496 12.496-32.758 12.496-45.254 0-12.496-12.499-12.496-32.758 0-45.258l105.373-105.373-105.373-105.37c-12.496-12.499-12.496-32.758 0-45.258z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["code"],"defaultCode":59714,"grid":0},"attrs":[{}],"properties":{"order":985,"name":"code","prevSize":32,"id":73,"code":59714},"setIdx":0,"setId":6,"iconIdx":74},{"icon":{"paths":["M507.488 130.134c16.496 6.344 24.723 24.859 18.378 41.354l-160 416c-6.342 16.496-24.858 24.723-41.354 18.381-16.494-6.346-24.723-24.861-18.379-41.357l160.002-415.998c6.342-16.495 24.858-24.724 41.354-18.38z","M278.628 249.373c12.497 12.497 12.497 32.758 0 45.255l-73.373 73.372 73.373 73.373c12.497 12.496 12.497 32.758 0 45.254-12.497 12.499-32.758 12.499-45.255 0l-96-96c-6.001-6-9.372-14.141-9.372-22.627s3.372-16.624 9.372-22.627l96-95.999c12.497-12.497 32.758-12.497 45.255 0z","M553.373 249.373c12.496-12.497 32.758-12.497 45.254 0l96 95.999c6 6.003 9.373 14.141 9.373 22.627s-3.373 16.627-9.373 22.627l-96 96c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.758 0-45.254l73.373-73.373-73.373-73.372c-12.496-12.497-12.496-32.758 0-45.255z","M672 160c0-17.673 14.326-32 32-32h96c53.021 0 96 42.981 96 96v576c0 53.021-42.979 96-96 96h-576c-53.020 0-96-42.979-96-96v-160c0-17.674 14.327-32 32-32s32 14.326 32 32v192h640v-640h-128c-17.674 0-32-14.327-32-32z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{},{},{},{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{},{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{},{},{}]},"tags":["code-block"],"defaultCode":59840,"grid":0},"attrs":[{},{},{},{}],"properties":{"order":986,"id":74,"name":"code-block","prevSize":32,"code":59840},"setIdx":0,"setId":6,"iconIdx":75},{"icon":{"paths":["M770.704 224c17.674 0 32 14.327 32 32v544c0 17.674-14.326 32-32 32h-543.999c-17.673 0-32-14.326-32-32v-128c17.673 0 32-14.326 32-32s-14.327-32-32-32v-192c17.673 0 32-14.326 32-32s-14.327-32-32-32v-96c0-17.673 14.327-32 32-32h543.999zM130.705 608c-17.673 0-32 14.326-32 32s14.327 32 32 32v128c0 53.021 42.981 96 96 96h543.999c53.021 0 96-42.979 96-96v-544c0-53.019-42.979-96-96-96h-543.999c-53.019 0-96 42.981-96 96v96c-17.673 0-32 14.326-32 32s14.327 32 32 32v192zM427.91 514.266c13.315-3.568 27.309-3.789 40.73-0.643l31.52 7.389c8.73 2.045 17.83 1.904 26.49-0.416l22.186-5.942c14.285-3.827 29.328-4.042 43.683-0.675 40.429 9.475 69.325 45.584 69.325 87.277v24.336c0 31.811-25.789 57.6-57.6 57.6h-180.739c-31.811 0-57.6-25.789-57.6-57.6v-30.525c0-37.862 25.434-71.005 62.006-80.8zM456.957 563.472c-5.206-1.219-10.634-1.133-15.798 0.25-14.189 3.798-24.054 16.656-24.054 31.344v30.525c0 3.536 2.867 6.4 6.4 6.4h180.739c3.533 0 6.4-2.864 6.4-6.4v-24.336c0-17.75-12.365-33.341-29.808-37.427-6.186-1.45-12.662-1.35-18.752 0.282l-22.186 5.942c-16.813 4.502-34.474 4.781-51.421 0.81l-31.52-7.389zM539.155 420.48c0-13.962-11.318-25.28-25.28-25.28s-25.283 11.318-25.283 25.28c0 13.962 11.322 25.28 25.283 25.28s25.28-11.318 25.28-25.28zM590.355 420.48c0 42.24-34.243 76.48-76.48 76.48-42.24 0-76.483-34.24-76.483-76.48s34.243-76.48 76.483-76.48c42.237 0 76.48 34.24 76.48 76.48z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["contacts"],"defaultCode":59715,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":987,"name":"contacts","prevSize":32,"id":75,"code":59715},"setIdx":0,"setId":6,"iconIdx":76},{"icon":{"paths":["M464 272c-35.347 0-64 28.654-64 64v480c0 35.347 28.653 64 64 64h352c35.347 0 64-28.653 64-64v-304c0-6.509-1.984-12.864-5.69-18.214l-134.458-194.215c-11.952-17.267-31.619-27.571-52.621-27.571h-223.232zM464 336h144v144c0 35.347 28.653 64 64 64h144v272h-352v-480zM672 480v-144h15.232l99.693 144h-114.925zM144 208c0-35.346 28.654-64 64-64h241.844c18.032 0 35.229 7.607 47.357 20.949l39.136 43.051h-328.336v480h128v64h-128c-35.346 0-64-28.653-64-64v-480z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["copy"],"defaultCode":59716,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":988,"name":"copy","prevSize":32,"id":76,"code":59716},"setIdx":0,"setId":6,"iconIdx":77},{"icon":{"paths":["M824.682 183.521c-37.19-37.986-98.202-38.583-136.131-1.333l-348.48 342.237c-12.739 12.512-21.733 28.32-25.976 45.654l-23.681 96.749c-6.94 28.355 16.754 54.845 45.747 51.142l90.691-11.578c20.224-2.582 39.104-11.52 53.907-25.52l360.486-340.922c38.986-36.868 40.173-98.482 2.637-136.82l-19.2-19.61zM733.485 227.821c12.643-12.417 32.979-12.218 45.376 0.444l19.2 19.61c12.512 12.78 12.115 33.317-0.88 45.607l-69.965 66.169-63.446-63.364 69.715-68.466zM618.074 341.162l62.592 62.512-243.971 230.73c-4.934 4.666-11.229 7.645-17.968 8.506l-58.307 7.443 15.926-65.075c1.414-5.779 4.413-11.046 8.659-15.219l233.069-228.896zM193.608 265.602c0-17.673 14.346-32 32.042-32h281.332c17.696 0 32.042-14.327 32.042-32s-14.346-32-32.042-32h-281.332c-53.089 0-96.127 42.981-96.127 96v534.402c0 53.018 43.037 95.997 96.127 95.997h529.764c53.091 0 96.128-42.979 96.128-96v-279.414c0-17.67-14.346-32-32.042-32s-32.042 14.33-32.042 32v279.414c0 17.674-14.346 32-32.045 32h-529.764c-17.696 0-32.042-14.326-32.042-31.997v-534.402z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["create"],"defaultCode":59717,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":989,"name":"create","prevSize":32,"id":77,"code":59717},"setIdx":0,"setId":6,"iconIdx":78},{"icon":{"paths":["M717.373 298.663c0-17.673-14.326-32-32-32s-32 14.327-32 32v426.665c0 17.674 14.326 32 32 32s32-14.326 32-32v-426.665z","M514.704 394.672c17.674 0 32 14.326 32 32v298.666c0 17.674-14.326 32-32 32s-32-14.326-32-32v-298.666c0-17.674 14.326-32 32-32z","M376.038 554.672c0-17.674-14.326-32-32-32s-32 14.326-32 32v170.669c0 17.67 14.327 32 32 32s32-14.33 32-32v-170.669z","M130.705 199.556v624.889c0 39.52 32.036 71.555 71.556 71.555h624.888c39.52 0 71.555-32.035 71.555-71.555v-624.889c0-39.519-32.035-71.556-71.555-71.556h-624.888c-39.519 0-71.556 32.036-71.556 71.556zM202.26 192h624.888c4.173 0 7.555 3.383 7.555 7.556v624.889c0 4.173-3.382 7.555-7.555 7.555h-624.888c-4.173 0-7.556-3.382-7.556-7.555v-624.889c0-4.173 3.383-7.556 7.556-7.556z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["dashboard"],"defaultCode":59718,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":990,"name":"dashboard","prevSize":32,"id":78,"code":59718},"setIdx":0,"setId":6,"iconIdx":79},{"icon":{"paths":["M739.68 864v-448h-448.593v448h448.593zM227.003 864v-448c-35.393 0-64.084-28.653-64.084-64v-128c0-35.346 28.692-64 64.084-64h224.297c0-35.346 28.691-64 64.083-64 35.395 0 64.086 28.654 64.086 64h224.294c35.395 0 64.086 28.654 64.086 64v128c0 35.347-28.691 64-64.086 64v448c0 35.347-28.691 64-64.083 64h-448.593c-35.393 0-64.085-28.653-64.085-64zM803.763 224h-576.761v128h576.761v-128zM419.258 544v192c0 17.674 14.346 32 32.042 32s32.042-14.326 32.042-32v-192c0-17.674-14.346-32-32.042-32s-32.042 14.326-32.042 32zM579.469 512c17.696 0 32.042 14.326 32.042 32v192c0 17.674-14.346 32-32.042 32s-32.042-14.326-32.042-32v-192c0-17.674 14.346-32 32.042-32z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["delete"],"defaultCode":59719,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":991,"name":"delete","prevSize":32,"id":79,"code":59719},"setIdx":0,"setId":6,"iconIdx":80},{"icon":{"paths":["M341.334 778.672c-17.674 0-32 14.326-32 32s14.327 32 32 32h341.334c17.67 0 32-14.326 32-32s-14.33-32-32-32h-341.334z","M85.334 298.672c0-70.692 57.308-128 128-128h597.335c70.691 0 128 57.308 128 128v298.666c0 70.694-57.309 128-128 128h-597.335c-70.692 0-128-57.306-128-128v-298.666zM213.334 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.347 28.654 64 64 64h597.335c35.344 0 64-28.653 64-64v-298.666c0-35.347-28.656-64-64-64h-597.335z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["desktop"],"defaultCode":59720,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":992,"name":"desktop","prevSize":32,"id":80,"code":59720},"setIdx":0,"setId":6,"iconIdx":81},{"icon":{"paths":["M325.837 160c0-17.673-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.327-32.042 32v64c0 17.673 14.346 32 32.042 32h64.085c17.696 0 32.043-14.327 32.043-32v-64zM325.837 586.666c0-17.674-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.085c17.696 0 32.043-14.326 32.043-32v-64zM454.006 160c0-17.673 14.346-32 32.042-32h64.083c17.696 0 32.042 14.327 32.042 32v64c0 17.673-14.346 32-32.042 32h-64.083c-17.696 0-32.042-14.327-32.042-32v-64zM582.173 373.334c0-17.674-14.346-32-32.042-32h-64.083c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM454.006 586.666c0-17.674 14.346-32 32.042-32h64.083c17.696 0 32.042 14.326 32.042 32v64c0 17.674-14.346 32-32.042 32h-64.083c-17.696 0-32.042-14.326-32.042-32v-64zM582.173 800c0-17.674-14.346-32-32.042-32h-64.083c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM710.342 160c0-17.673 14.346-32 32.045-32h64.083c17.696 0 32.042 14.327 32.042 32v64c0 17.673-14.346 32-32.042 32h-64.083c-17.699 0-32.045-14.327-32.045-32v-64zM838.512 373.334c0-17.674-14.346-32-32.042-32h-64.083c-17.699 0-32.045 14.326-32.045 32v64c0 17.674 14.346 32 32.045 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM710.342 586.666c0-17.674 14.346-32 32.045-32h64.083c17.696 0 32.042 14.326 32.042 32v64c0 17.674-14.346 32-32.042 32h-64.083c-17.699 0-32.045-14.326-32.045-32v-64zM325.837 373.334c0-17.674-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.085c17.696 0 32.043-14.326 32.043-32v-64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["dialpad"],"defaultCode":59721,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":993,"name":"dialpad","prevSize":32,"id":81,"code":59721},"setIdx":0,"setId":6,"iconIdx":82},{"icon":{"paths":["M478.65 672c-17.674 0-32-14.326-32-32v-32h-32c-17.674 0-32-14.326-32-32s14.326-32 32-32h32v-58.88h-32c-17.674 0-32-14.326-32-32s14.326-32 32-32h32v-37.12c0-17.674 14.326-32 32-32 17.67 0 32 14.326 32 32v37.12h58.88v-37.12c0-17.674 14.326-32 32-32s32 14.326 32 32v37.12h37.12c17.67 0 32 14.326 32 32s-14.33 32-32 32h-37.12v58.88h37.12c17.67 0 32 14.326 32 32s-14.33 32-32 32h-37.12v32c0 17.674-14.326 32-32 32s-32-14.326-32-32v-32h-58.88v32c0 17.674-14.33 32-32 32zM510.65 544h58.88v-58.88h-58.88v58.88z","M158.648 672h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-192h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-160c0-35.346 28.654-64 64-64h608.001c35.344 0 64 28.654 64 64v640c0 35.347-28.656 64-64 64h-608.001c-35.346 0-64-28.653-64-64v-160zM830.65 192h-608.001v160h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v192h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v160h608.001v-640z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["directory"],"defaultCode":59648,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":994,"id":82,"name":"directory","prevSize":32,"code":59648},"setIdx":0,"setId":6,"iconIdx":83},{"icon":{"paths":["M833.35 128c10.285 0 20 2.425 28.611 6.735-11.834 4.684-22.922 11.812-32.493 21.383l-35.882 35.882h-568.236v160h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v192h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v88.237l-64 64v-152.237h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-192h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-160c0-35.346 28.654-64 64-64h607.999z","M361.117 896l64-64h408.234v-408.237l64-64v472.237c0 35.347-28.653 64-64 64h-472.234z","M604.23 352c8.166 0 15.616 3.056 21.267 8.090l-53.267 53.267v-29.357c0-17.674 14.33-32 32-32z","M513.35 421.12h51.117l-115.117 115.117v-51.117h-32c-17.67 0-32-14.326-32-32s14.33-32 32-32h32v-37.12c0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32v37.12z","M391.174 594.413l50.413-50.413h-24.237c-17.67 0-32 14.326-32 32 0 6.854 2.157 13.203 5.824 18.413z","M919.978 201.372c-12.496-12.497-32.755-12.497-45.254 0l-671.999 672c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l671.999-672c12.499-12.497 12.499-32.758 0-45.255z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["directory-disabled"],"defaultCode":59649,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":995,"id":83,"name":"directory-disabled","prevSize":32,"code":59649},"setIdx":0,"setId":6,"iconIdx":84},{"icon":{"paths":["M919.978 105.372c12.499 12.497 12.499 32.758 0 45.255l-89.373 89.372 89.373 89.373c12.499 12.496 12.499 32.758 0 45.254-12.496 12.496-32.755 12.496-45.254 0l-89.373-89.372-89.373 89.372c-12.496 12.496-32.755 12.496-45.254 0-12.496-12.496-12.496-32.758 0-45.254l89.373-89.373-89.373-89.372c-12.496-12.497-12.496-32.758 0-45.255 12.499-12.497 32.758-12.497 45.254 0l89.373 89.373 89.373-89.373c12.499-12.497 32.758-12.497 45.254 0z","M512.419 126.678c1.491 17.61-11.578 33.094-29.187 34.585-180.289 15.259-321.88 166.478-321.88 350.731 0 194.406 157.596 352 351.999 352 194.406 0 352-157.594 352-352 0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32 0 229.75-186.25 416-416 416s-415.999-186.25-415.999-416c0-217.79 167.341-396.462 380.482-414.503 17.61-1.491 33.094 11.577 34.586 29.187z","M119.219 432.47c0-17.674 14.327-32 32-32h329.037c17.67 0 32 14.326 32 32 0 17.67-14.33 32-32 32h-329.037c-17.673 0-32-14.33-32-32z","M119.233 640c0-17.674 14.327-32 32-32h724.255c17.674 0 32 14.326 32 32s-14.326 32-32 32h-724.255c-17.673 0-32-14.326-32-32z","M504.81 121.090c11.117 13.739 8.992 33.888-4.749 45.005-8.666 7.012-18.886 20.139-29.238 40.961-10.179 20.471-19.61 46.603-27.635 77.587-16.042 61.955-25.837 140.879-25.837 227.356 0 103.555 14.038 195.981 35.85 261.411 10.96 32.88 23.306 57.181 35.462 72.605 12.438 15.786 21.024 17.978 24.688 17.978 3.667 0 12.253-2.192 24.691-17.978 12.157-15.424 24.502-39.725 35.462-72.605 21.808-65.43 35.846-157.856 35.846-261.411 0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32 0 108.522-14.614 208.096-39.133 281.648-12.202 36.608-27.437 68.544-45.91 91.984-18.186 23.078-43.274 42.362-74.957 42.362-31.68 0-56.768-19.283-74.957-42.362-18.47-23.44-33.706-55.376-45.91-91.984-24.515-73.552-39.133-173.126-39.133-281.648 0-90.915 10.256-175.338 27.882-243.4 8.81-34.025 19.619-64.572 32.282-90.038 12.49-25.115 27.712-47.185 46.288-62.217 13.741-11.117 33.888-8.992 45.008 4.746z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["directory-error"],"defaultCode":59650,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":996,"id":84,"name":"directory-error","prevSize":32,"code":59650},"setIdx":0,"setId":6,"iconIdx":85},{"icon":{"paths":["M561.667 127.992c-121.696 0-200.973 50.509-248.813 115.801-46.216 63.073-61.638 137.752-61.933 188.616-8.705 98.746 28.601 172.896 89.422 223.469 59.686 49.626 140.202 75.258 217.85 83.738 77.75 8.486 161.715 1.197 227.856-12.547 33.066-6.87 62.774-15.581 85.642-25.331 11.366-4.848 22.029-10.368 30.797-16.669 7.875-5.661 18.541-14.976 23.242-28.835 7.286-21.475-3.133-38.784-11.965-48.102-8.41-8.877-19.427-15.405-28.24-20.016-9.306-4.867-19.379-9.206-27.533-12.707-8.973-3.856-14.858-6.4-18.56-8.432-4.845-2.662-8.842-5.088-12.026-7.203 20.256-47.142 31.549-77.043 37.696-99.19 7.293-26.272 7.315-41.725 7.315-58.909 0-21.523-9.603-88.542-52.81-151.108-44.701-64.73-124.074-122.573-257.939-122.573zM314.916 433.898c0-40.416 12.607-101.84 49.564-152.277 35.782-48.836 95.882-89.628 197.187-89.628 112.086 0 172.090 46.886 205.277 94.94 34.678 50.219 41.472 104.040 41.472 114.741v0.198c0 14.918 0 23.638-4.982 41.594-5.491 19.779-16.963 50.189-41.539 106.538-5.802 13.296-2.762 25.77 1.155 33.754 3.664 7.478 9.005 13.242 13.331 17.261 8.835 8.211 20.653 15.686 32.224 22.045 6.618 3.638 15.238 7.334 22.563 10.477l1.562 0.672c5.904 2.534 11.52 4.97 16.688 7.418-0.909 0.406-1.856 0.819-2.835 1.238-17.741 7.568-43.078 15.206-73.555 21.539-60.947 12.666-138.064 19.21-207.888 11.587-69.926-7.635-136.982-30.336-183.878-69.328-45.459-37.798-73.674-92.064-66.481-169.821l0.136-1.469v-1.478zM819.162 553.354l-0.074-0.086c0 0.003 0.010 0.013 0.029 0.035 0.010 0.013 0.026 0.029 0.045 0.051z","M178.552 502.474c7.496-11.258 16.26-22.259 26.436-32.592 0.876 31.747 6.169 61.226 15.216 88.358-15.094 30.877-18.374 59.315-18.374 65.357v0.186c0 11.382 0 17.536 3.524 30.701 3.993 14.918 12.441 38.211 30.867 82.022 5.256 12.496 2.48 24.099-0.985 31.43-3.249 6.874-7.925 12.058-11.512 15.514-7.319 7.053-16.852 13.254-25.75 18.326-5.008 2.854-11.333 5.706-16.546 8.029 11.182 3.939 24.98 7.814 40.802 11.226 44.977 9.693 101.833 14.669 153.062 8.87 51.28-5.808 99.776-23.014 133.35-51.965l0.608-0.528c14.794 2.784 29.53 4.938 44.051 6.525 10.886 1.187 21.862 2.086 32.877 2.72-10.122 14.797-22.163 28.045-35.741 39.754-46.362 39.974-108.547 60.362-167.946 67.088-59.45 6.73-123.405 0.947-173.744-9.901-25.17-5.424-48.056-12.352-65.901-20.243-8.86-3.92-17.458-8.502-24.686-13.891-6.431-4.794-15.831-13.171-20.001-25.92-6.422-19.632 2.792-35.443 10.458-43.834 7.193-7.872 16.405-13.462 23.248-17.174 7.309-3.965 15.158-7.466 21.235-10.173 6.907-3.078 10.854-4.858 13.183-6.186 1.349-0.768 2.591-1.501 3.727-2.195-13.937-33.885-21.976-56.118-26.48-72.947-5.68-21.222-5.7-33.875-5.7-47.434 0-17.712 7.436-71.139 40.721-121.123zM155.337 797.248c-0.012 0 0.084 0.102 0.317 0.301-0.19-0.202-0.306-0.301-0.317-0.301zM179.587 737.085c-0.004 0-0.052 0.051-0.137 0.15l0.112-0.118c0.019-0.022 0.027-0.032 0.025-0.032z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["discussions"],"defaultCode":59722,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":997,"name":"discussions","prevSize":32,"id":85,"code":59722},"setIdx":0,"setId":6,"iconIdx":86},{"icon":{"paths":["M160 256c0-17.673 14.327-32 32-32h640c17.674 0 32 14.327 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.327-32-32zM160 421.162c0-17.674 14.327-32 32-32h640c17.674 0 32 14.326 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.326-32-32zM160 602.838c0-17.674 14.327-32 32-32h640c17.674 0 32 14.326 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.326-32-32zM160 768c0-17.674 14.327-32 32-32h344.614c17.674 0 32 14.326 32 32s-14.326 32-32 32h-344.614c-17.673 0-32-14.326-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["document"],"defaultCode":59723,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":998,"name":"document","prevSize":32,"id":86,"code":59723},"setIdx":0,"setId":6,"iconIdx":87},{"icon":{"paths":["M128.169 352c0-17.674 14.346-32 32.042-32h704.928c17.696 0 32.045 14.326 32.045 32s-14.349 32-32.045 32h-704.928c-17.696 0-32.042-14.326-32.042-32zM213.615 522.669c0-17.674 14.346-32 32.042-32h534.036c17.699 0 32.045 14.326 32.045 32s-14.346 32-32.045 32h-534.036c-17.697 0-32.042-14.326-32.042-32zM331.104 661.331c-17.698 0-32.043 14.326-32.043 32s14.346 32 32.043 32h363.146c17.696 0 32.042-14.326 32.042-32s-14.346-32-32.042-32h-363.146z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["donner"],"defaultCode":59724,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":999,"name":"donner","prevSize":32,"id":87,"code":59724},"setIdx":0,"setId":6,"iconIdx":88},{"icon":{"paths":["M273.128 356.678c-6.62 27.766-2.384 63.757 25.498 105.581l21.374 32.061v17.69h-48c-44.011 0-70.483 14.874-86.278 33.619-16.496 19.578-24.573 47.264-23.734 77.491 0.841 30.262 10.601 59.968 25.818 81.312 15.127 21.216 33.404 31.578 52.195 31.578h79.999v64h-80c-45.209 0-80.932-25.642-104.306-58.426-23.283-32.656-36.522-74.95-37.682-116.688-1.16-41.773 9.763-86.083 38.766-120.506 20.726-24.598 49.155-42.32 84.825-50.784-16.1-39.011-19.009-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.4-22.798 85.677-32.139 131.303-21.965 35.584 7.935 68.909 27.48 95.251 59.554 53.75-35.147 127.584-30.892 182.483-2.495 34.438 17.812 64.794 46.382 81.437 85.010 12.294 28.531 16.438 61.011 10.608 96.205 46.112 6.682 81.507 25.155 105.613 53.456 30.349 35.626 38.106 81.35 33.446 123.283-4.659 41.917-21.946 83.485-46.544 115.114-24.061 30.934-59.354 57.354-101.261 57.354h-80v-64h80c14.093 0 32.8-9.581 50.742-32.646 17.398-22.371 30.112-52.806 33.453-82.89 3.341-30.067-2.902-56.339-18.554-74.714-15.222-17.869-44.035-33.75-97.642-33.75h-45.686l15.613-42.938c13.546-37.251 11.091-66.742 1.437-89.149-9.856-22.87-28.502-41.302-52.064-53.488-49.587-25.649-107.475-18.625-134.717 14.064l-30.134 36.16-22.541-41.325c-19.757-36.219-47.232-54.175-74.87-60.339-28.378-6.327-59.098-0.669-84.701 14.53-25.512 15.148-44.461 38.855-51.208 67.152zM630.979 787.222c12.298-12.691 11.981-32.95-0.707-45.251-12.691-12.298-32.95-11.981-45.251 0.707l-41.021 42.326v-273.005c0-17.674-14.326-32-32-32s-32 14.326-32 32v273.005l-41.021-42.326c-12.301-12.688-32.56-13.005-45.251-0.707-12.688 12.301-13.005 32.56-0.707 45.251l96 99.050c6.029 6.218 14.32 9.728 22.979 9.728s16.95-3.51 22.979-9.728l96-99.050z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["download"],"defaultCode":59725,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1000,"name":"download","prevSize":32,"id":88,"code":59725},"setIdx":0,"setId":6,"iconIdx":89},{"icon":{"paths":["M795.648 132.004c-25.027-25.027-65.603-25.027-90.63-0l-530.467 530.469c-9.577 9.574-15.873 21.939-17.985 35.318l-19.611 124.186c-1.386 8.771-0.942 17.299 1.006 25.261 7.597 31.037 38.083 53.44 72.291 48.038l124.184-19.613c13.379-2.112 25.744-8.41 35.322-17.984l530.467-530.47c12.512-12.513 18.768-28.914 18.768-45.316 0-10.379-2.506-20.757-7.517-30.15-2.906-5.451-6.656-10.57-11.251-15.164l-104.576-104.575zM630.675 296.979l119.658-119.658 104.576 104.574-119.658 119.657-104.576-104.573zM200.255 831.974l19.611-124.186 365.494-365.494 104.576 104.573-365.494 365.494-124.187 19.613z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["edit"],"defaultCode":59726,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1001,"name":"edit","prevSize":32,"id":89,"code":59726},"setIdx":0,"setId":6,"iconIdx":90},{"icon":{"paths":["M330.074 644.886c-21.572-19.619-6.010-52.886 23.152-52.886 8.963 0 17.526 3.53 24.272 9.437 21.603 18.918 42.64 31.958 62.701 40.509 36.563 15.59 71.805 17.107 104.794 9.939 37.632-8.176 72.659-27.808 102.109-51.341 6.726-5.376 14.995-8.544 23.606-8.544 30.218 0 45.616 34.256 22.397 53.594-36.912 30.742-82.79 57.59-134.522 68.832-44.794 9.734-93.67 7.632-143.485-13.606-28.79-12.275-57.232-30.653-85.024-55.933z","M400.17 480c35.344 0 64-28.653 64-64s-28.656-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64z","M624.17 480c35.344 0 64-28.653 64-64s-28.656-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64z","M928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["emoji"],"defaultCode":59729,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1002,"name":"emoji","prevSize":32,"id":90,"code":59729},"setIdx":0,"setId":6,"iconIdx":91},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM400.166 480c-35.347 0-64-28.653-64-64s28.653-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64zM688.166 416c0-35.347-28.653-64-64-64s-64 28.653-64 64c0 35.347 28.653 64 64 64s64-28.653 64-64zM353.226 720c8.963 0 17.526-3.53 24.272-9.437 21.603-18.918 42.64-31.958 62.701-40.509 36.563-15.59 71.805-17.107 104.794-9.939 37.632 8.176 72.659 27.808 102.109 51.341 6.726 5.376 14.995 8.544 23.606 8.544 30.218 0 45.616-34.256 22.397-53.594-36.912-30.742-82.79-57.59-134.522-68.832-44.794-9.734-93.67-7.632-143.485 13.606-28.79 12.275-57.232 30.653-85.024 55.933-21.572 19.619-6.010 52.886 23.152 52.886z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["emoji-bad-mood"],"defaultCode":59727,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1003,"name":"emoji-bad-mood","prevSize":32,"id":91,"code":59727},"setIdx":0,"setId":6,"iconIdx":92},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM400.166 480c-35.347 0-64-28.653-64-64s28.653-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64zM688.166 416c0-35.347-28.653-64-64-64s-64 28.653-64 64c0 35.347 28.653 64 64 64s64-28.653 64-64zM384 640h256c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32s14.326-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["emoji-neutral-mood"],"defaultCode":59728,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1004,"name":"emoji-neutral-mood","prevSize":32,"id":92,"code":59728},"setIdx":0,"setId":6,"iconIdx":93},{"icon":{"paths":["M655.744 512c88.365 0 160-71.635 160-160s-71.635-160-160-160c-88.368 0-160 71.635-160 160 0 26.934 6.653 52.314 18.41 74.582l-11.914 11.914 0.128 0.131-299.135 299.136c-3.533 9.926-6.41 20.976-7.738 31.606-1.652 13.219-0.563 22.966 1.874 28.938 1.768 4.333 4.22 7.232 10.772 9.014 8.316 2.262 24.518 2.794 52.822-5.501 8.524-3.808 27.721-16.285 45.132-35.382 18.18-19.939 29.648-41.856 29.648-62.438 0-15.642 11.309-28.992 26.736-31.565l91.75-15.293c3.766-2.656 18.768-15.693 10.134-58.867-2.099-10.49 1.184-21.338 8.749-28.902l88.198-88.195c26.467 19.379 59.114 30.822 94.432 30.822zM439.571 410.915c-5.104-18.771-7.827-38.525-7.827-58.915 0-123.712 100.288-224 224-224 123.709 0 224 100.288 224 224s-100.291 224-224 224c-29.29 0-57.264-5.619-82.906-15.843l-43.008 43.008c7.158 65.494-23.99 104.534-55.968 115.194l-2.384 0.794-74.854 12.477c-7.085 31.405-25.174 58.122-43.235 77.933-23.123 25.357-50.958 44.627-69.762 52.15l-1.324 0.528-1.365 0.41c-34.714 10.416-64.73 13.19-89.594 6.429-26.782-7.286-44.33-24.784-53.228-46.586-8.23-20.163-8.473-42.282-6.126-61.062 2.402-19.216 7.899-37.958 14.042-53.315 1.61-4.022 4.020-7.677 7.084-10.742l286.456-286.458zM623.744 336c0 26.509 21.488 48 48 48 26.509 0 48-21.491 48-48s-21.491-48-48-48c-26.512 0-48 21.49-48 48z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["encrypted"],"defaultCode":59730,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1005,"name":"encrypted","prevSize":32,"id":93,"code":59730},"setIdx":0,"setId":6,"iconIdx":94},{"icon":{"paths":["M536.89 64c233.677 0 423.11 189.433 423.11 423.11h-423.11v-423.11z","M64 536.89c0-233.678 189.433-423.112 423.11-423.112v423.112h423.11c0 233.677-189.43 423.11-423.11 423.11-233.677 0-423.11-189.434-423.11-423.11z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["engagement-dashboard"],"defaultCode":59731,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1006,"name":"engagement-dashboard","prevSize":32,"id":94,"code":59731},"setIdx":0,"setId":6,"iconIdx":95},{"icon":{"paths":["M416 586.445v177.232l75.514-62.928c11.869-9.888 29.104-9.888 40.973 0l75.514 62.928v-177.232c-29.098 13.821-61.645 21.555-96 21.555s-66.902-7.734-96-21.555zM352 540.768v291.232c0 12.416 7.184 23.712 18.426 28.979 11.245 5.267 24.522 3.552 34.061-4.397l107.514-89.594 107.514 89.594c9.539 7.949 22.816 9.664 34.061 4.397 11.242-5.267 18.426-16.563 18.426-28.979v-291.232c39.59-40.403 64-95.734 64-156.768 0-123.712-100.288-224.001-224-224.001s-224 100.288-224 224.001c0 61.034 24.41 116.365 64 156.768zM416 512.013l-0.016-0.013c-38.854-29.19-63.984-75.661-63.984-128 0-88.366 71.635-160.001 160-160.001s160 71.635 160 160.001c0 52.339-25.13 98.81-63.984 128l-0.016 0.013c-26.742 20.083-59.981 31.987-96 31.987s-69.258-11.904-96-31.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["enterprise-feature"],"defaultCode":59732,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1007,"name":"enterprise-feature","prevSize":32,"id":95,"code":59732},"setIdx":0,"setId":6,"iconIdx":96},{"icon":{"paths":["M500.64 128c213.35 0 386.336 172.985 386.336 386.336 0 192.87-141.254 352.707-325.974 381.664v-269.958h90.022l17.114-111.706h-107.136v-72.47c0-11.462 2.102-22.822 7.274-32.544 2.474-4.656 5.651-8.934 9.635-12.666 9.866-9.245 24.688-15.152 46.058-15.152h48.733v-95.080c0 0-44.224-7.552-86.493-7.552-84.698 0-141.258 49.313-145.651 138.907-0.182 3.738-0.275 7.546-0.275 11.424v85.133h-98.122v111.706h98.122v269.958c-184.721-29.011-325.978-188.848-325.978-381.664 0-213.351 172.985-386.336 386.336-386.336z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["facebook-monochromatic"],"defaultCode":59733,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1008,"name":"facebook-monochromatic","prevSize":32,"id":96,"code":59733},"setIdx":0,"setId":6,"iconIdx":97},{"icon":{"paths":["M865.139 512c0 33.28-4.624 65.485-13.267 96h-183.274c2.803-30.816 4.288-62.957 4.288-96 0-16.234-0.358-32.25-1.056-48h190.061c2.141 15.696 3.248 31.718 3.248 48zM607.68 464c0.739 15.67 1.123 31.686 1.123 48 0 33.398-1.61 65.555-4.57 96h-183.117c-2.963-30.445-4.57-62.602-4.57-96 0-16.314 0.384-32.33 1.123-48h190.010zM667.014 400c-10.016-93.226-32.221-173.252-61.875-227.763 113.702 30.788 204.579 116.981 241.782 227.763h-179.907zM420.211 172.237c-29.654 54.51-51.862 134.537-61.875 227.763h-179.91c37.204-110.782 128.083-196.975 241.785-227.763zM422.816 400c7.171-62.314 20.064-116.804 36.384-159.18 12.842-33.339 26.56-55.927 38.528-69.070 8.406-9.235 13.446-11.291 14.947-11.698 1.501 0.407 6.541 2.463 14.947 11.698 11.968 13.143 25.686 35.731 38.525 69.070 16.32 42.377 29.216 96.867 36.387 159.18h-179.718zM353.52 464c-0.698 15.75-1.056 31.766-1.056 48 0 33.043 1.482 65.184 4.288 96h-183.275c-8.643-30.515-13.268-62.72-13.268-96 0-16.282 1.107-32.304 3.249-48h190.061zM364.742 672c11.667 72.646 31.040 134.861 55.466 179.763-96.678-26.179-176.854-92.413-221.565-179.763h166.1zM513.152 928c229.834-0.259 416.070-186.41 416.070-416 0-229.75-186.493-416-416.547-416s-416.55 186.25-416.55 416c0 229.59 186.237 415.741 416.070 416 0.16 0 0.32 0 0.48 0s0.32 0 0.477 0zM605.142 851.763c24.426-44.902 43.798-107.117 55.466-179.763h166.099c-44.71 87.35-124.89 153.584-221.565 179.763zM595.638 672c-7.379 42.458-17.514 80.083-29.491 111.184-12.838 33.338-26.557 55.926-38.525 69.069-8.406 9.235-13.446 11.29-14.947 11.699-1.501-0.41-6.541-2.464-14.947-11.699-11.968-13.142-25.686-35.731-38.528-69.069-11.978-31.101-22.109-68.726-29.488-111.184h165.926z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["federation"],"defaultCode":59652,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1009,"id":97,"name":"federation","prevSize":32,"code":59652},"setIdx":0,"setId":6,"iconIdx":98},{"icon":{"paths":["M542.65 96c80.093 0 154.902 22.636 218.374 61.859l-46.746 46.746c-24.739-13.843-51.322-24.785-79.286-32.368 12.166 22.395 23.078 49.095 32.406 79.249l-52 51.999c-5.654-22.994-12.17-44.005-19.347-62.666-12.822-33.339-26.522-55.927-38.474-69.070-8.397-9.235-13.43-11.291-14.928-11.698-1.498 0.407-6.531 2.463-14.928 11.698-11.952 13.143-25.654 35.731-38.477 69.070-16.298 42.377-29.174 96.867-36.336 159.18h65.974l-64 64h-7.114c-0.118 2.47-0.224 4.95-0.323 7.437l-64.538 64.538c-0.173-7.933-0.259-15.926-0.259-23.974 0-16.234 0.358-32.25 1.053-48h-189.809c-2.14 15.696-3.245 31.718-3.245 48 0 33.28 4.619 65.485 13.251 96h106.984l-64 64h-17.852c2.004 3.92 4.078 7.798 6.223 11.629l-46.746 46.749c-39.223-63.475-61.859-138.282-61.859-218.378 0-229.75 186.25-416 416.001-416zM896.79 293.623l-46.746 46.748c10.56 18.87 19.43 38.816 26.413 59.629h-86.045l-64 64h164.992c2.138 15.696 3.245 31.718 3.245 48 0 33.28-4.621 65.485-13.251 96h-183.030c2.8-30.816 4.282-62.957 4.282-96 0-8.045-0.090-16.042-0.262-23.974l-64.534 64.534c-0.752 19.008-2.026 37.523-3.766 55.44h-51.674l-64 64h107.088c-7.37 42.458-17.488 80.083-29.45 111.184-12.822 33.338-26.522 55.926-38.474 69.069-8.397 9.235-13.43 11.29-14.928 11.699-1.498-0.41-6.531-2.464-14.928-11.699-11.952-13.142-25.654-35.731-38.477-69.069-7.178-18.662-13.69-39.677-19.344-62.669l-52 51.997c9.325 30.154 20.237 56.854 32.403 79.251-27.965-7.584-54.547-18.525-79.286-32.368l-46.746 46.746c63.347 39.146 137.984 61.77 217.901 61.859h0.954c229.53-0.259 415.523-186.41 415.523-416 0-80.096-22.637-154.902-61.859-218.377zM450.307 172.237c-113.552 30.788-204.312 116.98-241.467 227.763h179.675c10-93.226 32.176-173.252 61.792-227.763zM634.995 851.763c24.394-44.902 43.741-107.117 55.392-179.763h165.878c-44.653 87.35-124.723 153.584-221.27 179.763zM856.022 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672.001 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672.001-672z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["federation-disabled"],"defaultCode":59651,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1010,"id":98,"name":"federation-disabled","prevSize":32,"code":59651},"setIdx":0,"setId":6,"iconIdx":99},{"icon":{"paths":["M373.334 448c0-17.674 14.326-32 32-32h213.331c17.674 0 32 14.326 32 32s-14.326 32-32 32h-213.331c-17.674 0-32-14.326-32-32z","M405.334 544c-17.674 0-32 14.326-32 32s14.326 32 32 32h213.331c17.674 0 32-14.326 32-32s-14.326-32-32-32h-213.331z","M256 128c-17.673 0-32 14.327-32 32v704c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-501.744c0-6.672-2.083-13.174-5.962-18.602l-144.467-202.254c-6.006-8.409-15.706-13.4-26.038-13.4h-367.533zM736 372.509v459.491h-448v-640h319.066l128.934 180.509z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["file-document"],"defaultCode":59734,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1011,"name":"file-document","prevSize":32,"id":99,"code":59734},"setIdx":0,"setId":6,"iconIdx":100},{"icon":{"paths":["M128 192c-17.673 0-32 14.327-32 32v576.019c0 17.674 14.327 32 32 32h768c17.674 0 32-14.326 32-32v-576.019c0-17.673-14.326-32-32-32h-768zM160 378.301v-122.301h149.333v122.301h-149.333zM160 442.301h149.333v141.722h-149.333v-141.722zM160 648.022h149.333v119.997h-149.333v-119.997zM373.334 768.019v-119.997h490.666v119.997h-490.666zM864 584.022h-490.666v-141.722h490.666v141.722zM864 378.301h-490.666v-122.301h490.666v122.301z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["file-sheet"],"defaultCode":59735,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1012,"name":"file-sheet","prevSize":32,"id":100,"code":59735},"setIdx":0,"setId":6,"iconIdx":101},{"icon":{"paths":["M206.667 293.692c-30.421-42.402-0.116-101.442 52.070-101.442h518.572c51.174 0 81.706 57.026 53.334 99.615l-180.678 271.207v220.762c0 46.352-47.693 77.373-90.067 58.582l-121.424-53.85c-23.168-10.275-38.102-33.238-38.102-58.582v-166.304l-193.704-269.988zM777.309 256.334h-518.572l193.705 269.989c7.811 10.89 12.013 23.955 12.013 37.357v166.304l121.424 53.85v-220.762c0-12.646 3.741-25.008 10.752-35.533l180.678-271.205z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["filter"],"defaultCode":59736,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1013,"name":"filter","prevSize":32,"id":101,"code":59736},"setIdx":0,"setId":6,"iconIdx":102},{"icon":{"paths":["M623.091 896c-2.806 0-5.296-0.624-7.168-0.938-62-16.858-102.816-39.648-145.811-80.858-55.149-54.010-85.37-125.814-85.37-202.301 0-65.875 56.704-119.571 126.496-119.571s126.496 53.696 126.496 119.571c0 34.963 31.469 63.373 69.792 63.373s69.789-28.41 69.789-63.373c0-135.808-119.642-246.637-266.701-246.637-104.998 0-200.338 57.133-243.334 145.795-14.332 29.347-21.498 63.066-21.498 100.842 0 28.72 2.492 73.363 24.925 131.744 2.804 7.181 2.492 14.675-0.623 21.856-3.116 6.867-9.035 11.862-16.201 14.358-2.804 1.251-6.231 1.562-9.659 1.562-11.84 0-22.433-7.181-26.484-18.106-19.005-50.266-28.353-99.904-28.353-151.728 0-46.205 9.036-88.352 26.795-125.504 52.343-108.019 167.936-177.638 294.432-177.638 178.528 0 323.718 135.804 323.718 302.828 0 65.875-56.704 119.571-126.806 119.571s-126.81-53.696-126.81-119.571c0-34.963-31.469-63.373-69.792-63.373-38.634 0-69.789 28.41-69.789 63.373 0 61.504 24.301 119.261 68.544 162.342 35.206 34.029 68.858 53.072 120.576 67.123 7.168 1.872 13.398 6.557 17.136 13.11 3.741 6.557 4.675 14.362 2.806 21.229-2.806 11.866-14.022 20.918-27.107 20.918zM426.803 888.195c-7.789 0-15.267-3.123-20.253-8.742-33.338-32.781-51.718-54.010-77.891-100.525-26.795-47.142-41.127-105.21-41.127-167.338 0-116.448 100.948-211.357 224.951-211.357s224.954 94.909 224.954 211.357c0 15.61-12.464 28.096-28.352 28.096-15.891 0-28.666-12.173-28.666-28.096 0-85.542-75.398-155.162-168.246-155.162s-168.246 69.619-168.246 155.162c0 52.448 11.84 100.528 34.272 139.552 23.366 41.52 38.947 59.005 68.858 88.662 10.902 11.238 10.902 28.723 0 39.648-5.92 5.933-13.088 8.742-20.253 8.742zM699.738 818.886c-47.36 0-88.797-11.862-123.382-34.963-59.197-39.651-94.717-103.962-94.717-172.333 0-15.61 12.464-28.099 28.352-28.099 15.891 0 28.355 12.49 28.355 28.099 0 49.638 26.17 96.781 69.789 125.501 25.238 16.861 55.149 24.976 91.603 24.976 7.789 0 22.432-0.934 38.010-3.744 1.558-0.314 3.427-0.314 4.986-0.314 13.709 0 25.238 9.99 27.728 23.414 1.248 7.181-0.31 14.672-4.362 20.605-4.362 6.243-10.902 10.614-18.694 11.862-23.366 4.685-43.93 4.995-47.667 4.995zM188.765 435.824c-5.608 0-11.217-1.562-16.202-4.995-6.543-4.058-10.593-10.614-12.151-18.106-1.246-7.494 0.311-14.986 4.985-21.232 38.635-53.696 87.862-95.843 146.125-125.501 60.132-30.595 129.613-46.829 200.961-46.829 71.037 0 140.205 15.922 200.029 46.205 58.573 29.659 107.802 71.492 146.125 124.567 4.362 5.93 6.23 13.424 4.986 20.915-1.248 7.494-5.61 14.048-11.84 18.419-4.986 3.437-10.595 4.995-16.515 4.995-9.034 0-17.757-4.371-23.056-11.862-33.338-45.891-75.709-82.109-125.562-107.083-52.342-26.224-112.787-40.273-174.477-40.273-62.314 0-122.758 14.049-175.101 40.585-49.852 25.913-92.537 62.128-126.186 108.643-3.739 6.87-12.463 11.552-22.121 11.552zM733.696 239.141c-4.672 0-9.347-1.249-13.395-3.434-71.35-35.902-133.354-51.512-207.504-51.512-74.467 0-144.256 17.483-207.817 51.824-4.050 2.185-8.724 3.122-13.397 3.122-10.282 0-19.629-5.62-24.925-14.361-3.739-6.556-4.673-14.361-2.492-21.541s7.166-13.424 13.709-16.859c72.594-38.712 151.733-58.38 234.924-58.38 82.563 0 154.848 17.795 233.987 58.068 6.854 3.434 11.84 9.366 14.33 16.859 2.182 7.18 1.248 14.673-2.179 21.229-4.986 9.054-14.643 14.985-25.238 14.985z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["fingerprint"],"defaultCode":59737,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1014,"name":"fingerprint","prevSize":32,"id":102,"code":59737},"setIdx":0,"setId":6,"iconIdx":103},{"icon":{"paths":["M266.667 170.664c0-17.673 14.327-32 32-32h500.623c12.122 0 23.2 6.848 28.621 17.689s4.253 23.814-3.021 33.511l-122.134 162.843 122.134 162.845c7.274 9.696 8.442 22.672 3.021 33.51-5.421 10.842-16.499 17.69-28.621 17.69h-468.624v286.579c0 17.674-14.325 32-31.999 32s-32-14.326-32-32v-682.667zM330.666 502.752h404.624l-98.134-130.845c-8.531-11.376-8.531-27.021 0-38.4l98.134-130.843h-404.624v300.088z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["flag"],"defaultCode":59738,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1015,"name":"flag","prevSize":32,"id":103,"code":59738},"setIdx":0,"setId":6,"iconIdx":104},{"icon":{"paths":["M140.020 213.336c0-17.673 14.327-32 32-32h234.057c7.181 0 14.157 2.416 19.798 6.86l88.813 69.94h339.997c17.674 0 32 14.327 32 32v520.533c0 17.674-14.326 32-32 32h-682.665c-17.673 0-32-14.326-32-32v-597.333zM204.020 245.336v533.333h618.665v-456.534h-319.085c-7.181 0-14.154-2.415-19.798-6.858l-88.813-69.94h-190.969z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["folder"],"defaultCode":59739,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1016,"name":"folder","prevSize":32,"id":104,"code":59739},"setIdx":0,"setId":6,"iconIdx":105},{"icon":{"paths":["M370.704 544c0-17.674-14.326-32-32-32s-31.999 14.326-31.999 32v32h-32c-17.673 0-32 14.326-32 32s14.327 32 32 32h32v32c0 17.674 14.325 32 31.999 32s32-14.326 32-32v-32h32c17.674 0 32-14.326 32-32s-14.326-32-32-32h-32v-32z","M746.704 624c30.928 0 56-25.072 56-56s-25.072-56-56-56c-30.928 0-56 25.072-56 56s25.072 56 56 56z","M674.704 664c0 30.928-25.072 56-56 56s-56-25.072-56-56c0-30.928 25.072-56 56-56s56 25.072 56 56z","M706.704 128c0-17.673-14.326-32-32-32s-32 14.327-32 32v96h-128c-17.674 0-32 14.327-32 32v96h-191.999c-106.038 0-192 85.962-192 192v128c0 106.038 85.961 192 192 192h447.999c106.038 0 192-85.962 192-192v-128c0-106.038-85.962-192-192-192h-192v-64h128c17.674 0 32-14.327 32-32v-128zM866.704 544v128c0 70.691-57.306 128-128 128h-447.999c-70.692 0-128-57.309-128-128v-128c0-70.691 57.308-128 128-128h447.999c70.694 0 128 57.309 128 128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["game"],"defaultCode":59753,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1017,"name":"game","prevSize":32,"id":105,"code":59753},"setIdx":0,"setId":6,"iconIdx":106},{"icon":{"paths":["M494.31 170.648l23.037 24.005 23.629-24.005 74.669 0.041v75.854h74.669v75.856h74.666v26.518h0.003v504.419h-522.678v-682.689h252.006zM540.976 246.503h-224.004v530.979h373.341v-379.229h-149.338v-151.75z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["giphy-monochromatic"],"defaultCode":59754,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1018,"name":"giphy-monochromatic","prevSize":32,"id":106,"code":59754},"setIdx":0,"setId":6,"iconIdx":107},{"icon":{"paths":["M862.454 324.045c-35.2-60.31-82.944-108.057-143.248-143.253-60.314-35.198-126.16-52.792-197.581-52.792-71.414 0-137.28 17.6-197.581 52.792-60.31 35.194-108.053 82.943-143.253 143.253-35.194 60.307-52.792 126.166-52.792 197.571 0 85.77 25.024 162.899 75.086 231.405 50.056 68.509 114.721 115.917 193.989 142.224 9.229 1.712 16.058 0.509 20.499-3.584 4.442-4.096 6.662-9.226 6.662-15.37 0-1.024-0.090-10.246-0.259-27.674-0.176-17.43-0.259-32.637-0.259-45.61l-11.789 2.038c-7.517 1.379-16.998 1.962-28.445 1.795-11.443-0.16-23.322-1.357-35.619-3.587-12.304-2.211-23.747-7.334-34.342-15.366-10.588-8.029-18.104-18.538-22.547-31.514l-5.125-11.795c-3.416-7.853-8.795-16.573-16.142-26.134-7.348-9.571-14.778-16.058-22.294-19.475l-3.588-2.57c-2.391-1.706-4.61-3.766-6.662-6.154-2.050-2.39-3.585-4.781-4.61-7.174-1.027-2.397-0.176-4.365 2.562-5.907 2.738-1.539 7.685-2.288 14.864-2.288l10.247 1.53c6.834 1.37 15.287 5.462 25.371 12.298 10.078 6.835 18.363 15.715 24.856 26.646 7.863 14.013 17.335 24.688 28.445 32.038 11.101 7.347 22.294 11.014 33.568 11.014s21.011-0.854 29.216-2.557c8.192-1.709 15.882-4.275 23.062-7.69 3.075-22.902 11.446-40.499 25.11-52.797-19.475-2.045-36.982-5.13-52.534-9.226-15.542-4.106-31.603-10.765-48.173-20-16.579-9.222-30.331-20.672-41.262-34.333-10.932-13.67-19.905-31.613-26.904-53.818-7.003-22.214-10.505-47.837-10.505-76.88 0-41.35 13.5-76.541 40.493-105.584-12.645-31.088-11.451-65.939 3.585-104.55 9.908-3.079 24.606-0.768 44.078 6.916 19.478 7.689 33.738 14.275 42.797 19.736 9.059 5.46 16.317 10.087 21.786 13.837 31.782-8.88 64.582-13.322 98.406-13.322s66.63 4.442 98.416 13.322l19.475-12.295c13.318-8.204 29.046-15.722 47.142-22.556 18.112-6.83 31.958-8.712 41.53-5.633 15.37 38.612 16.739 73.46 4.093 104.548 26.992 29.046 40.496 64.243 40.496 105.587 0 29.043-3.514 54.746-10.506 77.13-7.002 22.387-16.051 40.314-27.152 53.818-11.114 13.501-24.957 24.864-41.526 34.083-16.573 9.226-32.637 15.888-48.179 19.99-15.552 4.102-33.059 7.187-52.534 9.238 17.763 15.37 26.646 39.632 26.646 72.774v108.134c0 6.141 2.134 11.27 6.41 15.37 4.272 4.090 11.018 5.296 20.243 3.581 79.28-26.304 143.946-73.712 194-142.224 50.048-68.502 75.082-145.632 75.082-231.405-0.019-71.395-17.626-137.248-52.803-197.555z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["github-monochromatic"],"defaultCode":59655,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1019,"name":"github-monochromatic","prevSize":32,"id":107,"code":59655},"setIdx":0,"setId":6,"iconIdx":108},{"icon":{"paths":["M133.618 423.61h215.092l-92.537-284.607c-4.74-14.67-25.504-14.67-30.244 0l-92.311 284.607zM86.899 567.171l46.72-143.546h737.133l46.72 143.546c4.288 13.088-0.451 27.533-11.51 35.434l-403.776 293.408-403.776-293.408c-11.060-7.901-15.799-22.346-11.511-35.434zM655.661 423.61h215.091l-92.31-284.607c-4.739-14.67-25.504-14.67-30.243 0l-92.538 284.607z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["gitlab-monochromatic"],"defaultCode":59656,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1020,"name":"gitlab-monochromatic","prevSize":32,"id":108,"code":59656},"setIdx":0,"setId":6,"iconIdx":109},{"icon":{"paths":["M226.9 260.289c6.691-2.875 13.811-4.319 20.961-4.288 17.673 0.077 32.062-14.187 32.14-31.86s-14.187-32.062-31.86-32.14c-15.989-0.070-31.8 3.167-46.506 9.485-14.702 6.317-27.969 15.571-39.071 27.156-11.1 11.582-19.822 25.269-25.729 40.238-5.898 14.946-8.889 30.916-8.834 47.005l-0.001 15.941 0.001-11.899v255.848c-0 0.074-0.001 0.15-0.001 0.224v89.6c0 43.642 16.497 85.792 46.318 117.104 29.872 31.366 70.73 49.296 113.682 49.296 42.954 0 83.811-17.93 113.683-49.296 29.821-31.312 46.317-73.462 46.317-117.104v-57.6h128v57.6c0 43.642 16.496 85.792 46.317 117.104 29.872 31.366 70.73 49.296 113.683 49.296s83.811-17.93 113.683-49.296c29.821-31.312 46.317-73.462 46.317-117.104v-89.6c0-0.077 0-0.15 0-0.227v-259.883c0.054-16.090-2.938-32.062-8.835-47.010-5.907-14.969-14.627-28.656-25.728-40.238-11.104-11.585-24.368-20.839-39.072-27.156-14.704-6.318-30.515-9.555-46.506-9.485-17.674 0.077-31.936 14.467-31.859 32.14s14.467 31.937 32.141 31.86c7.149-0.031 14.269 1.413 20.96 4.288 6.694 2.876 12.867 7.147 18.128 12.636 5.264 5.492 9.501 12.090 12.403 19.448 2.906 7.36 4.4 15.292 4.368 23.326v228.302h-639.999l0-228.173-0-0.128c-0.032-8.034 1.462-15.965 4.366-23.326 2.904-7.358 7.141-13.957 12.404-19.448 5.26-5.489 11.434-9.759 18.129-12.636zM269.255 608l104.214 104.214c6.826-14.237 10.531-30.173 10.531-46.614v-57.6h-114.745zM717.254 608l104.214 104.214c6.826-14.237 10.531-30.173 10.531-46.614v-57.6h-114.746zM896 315.89v0zM128.001 319.928l0-3.973-0-0.069v4.043zM328.954 758.208l-136.954-136.954v44.346c0 27.648 10.475 53.869 28.663 72.966 18.137 19.043 42.394 29.434 67.337 29.434 14.208 0 28.194-3.37 40.954-9.792zM640 665.6v-44.346l136.954 136.954c-12.758 6.422-26.746 9.792-40.954 9.792-24.944 0-49.2-10.39-67.338-29.434-18.189-19.098-28.662-45.318-28.662-72.966z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["glasses"],"defaultCode":59812,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1021,"id":109,"name":"glasses","prevSize":32,"code":59812},"setIdx":0,"setId":6,"iconIdx":110},{"icon":{"paths":["M634.803 170.664h-256.112l-264.387 460.802 124.984 221.866h534.916l124.982-221.866-264.384-460.802zM367.814 631.466l138.931-239.789 138.934 239.789h-277.866z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["google-drive-monochromatic"],"defaultCode":59756,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1022,"name":"google-drive-monochromatic","prevSize":32,"id":110,"code":59756},"setIdx":0,"setId":6,"iconIdx":111},{"icon":{"paths":["M658.794 338.154c-39.798-38.052-90.416-57.426-146.794-57.426-100.016 0-184.669 67.548-214.865 158.313l-0.002-0.003c-7.679 23.040-12.042 47.648-12.042 72.957s4.364 49.92 12.044 72.96l0 0.003c30.196 90.765 114.849 158.314 214.865 158.314 51.664 0 95.651-13.613 130.035-36.653v-0.016c40.669-27.229 67.725-67.898 76.627-115.898h-206.662v-148.538h361.658c4.538 25.136 6.982 51.315 6.982 78.547 0 116.944-41.891 215.389-114.502 282.24v0.013c-63.533 58.646-150.458 93.030-254.138 93.030-150.109 0-279.971-86.048-343.156-211.549l-0-0.003c-26.007-51.84-40.844-110.49-40.844-172.451 0-61.965 14.836-120.611 40.844-172.451h0.004c63.187-125.495 193.047-211.542 343.153-211.542 103.504 0 190.429 38.051 256.931 100.014l-110.138 110.139z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["google-monochromatic"],"defaultCode":59657,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1023,"name":"google-monochromatic","prevSize":32,"id":111,"code":59657},"setIdx":0,"setId":6,"iconIdx":112},{"icon":{"paths":["M129.354 272c0-17.673 14.327-32 32-32h704c17.674 0 32 14.327 32 32s-14.326 32-32 32h-704c-17.673 0-32-14.327-32-32zM289.354 432c0 17.674-14.327 32-32 32s-32-14.326-32-32c0-17.674 14.327-32 32-32s32 14.326 32 32zM289.354 752c0 17.674-14.327 32-32 32s-32-14.326-32-32c0-17.674 14.327-32 32-32s32 14.326 32 32zM449.354 624c17.674 0 32-14.326 32-32s-14.326-32-32-32c-17.674 0-32 14.326-32 32s14.326 32 32 32zM385.354 400c-17.674 0-32 14.326-32 32s14.326 32 32 32h480c17.674 0 32-14.326 32-32s-14.326-32-32-32h-480zM353.354 752c0-17.674 14.326-32 32-32h480c17.674 0 32 14.326 32 32s-14.326 32-32 32h-480c-17.674 0-32-14.326-32-32zM577.354 560c-17.674 0-32 14.326-32 32s14.326 32 32 32h288c17.674 0 32-14.326 32-32s-14.326-32-32-32h-288z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["group-by-type"],"defaultCode":59757,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1024,"name":"group-by-type","prevSize":32,"id":112,"code":59757},"setIdx":0,"setId":6,"iconIdx":113},{"icon":{"paths":["M170.668 245.336c0-17.673 14.327-32 32-32h640.846c17.674 0 32 14.327 32 32s-14.326 32-32 32h-640.846c-17.673 0-32-14.327-32-32zM170.668 501.334c0-17.67 14.327-32 32-32h640.846c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-640.846c-17.673 0-32-14.326-32-32zM170.668 757.334c0-17.67 14.327-32 32-32h640.846c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-640.846c-17.673 0-32-14.326-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["hamburguer"],"defaultCode":59758,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1025,"name":"hamburguer","prevSize":32,"id":113,"code":59758},"setIdx":0,"setId":6,"iconIdx":114},{"icon":{"paths":["M832 512c0 176.73-143.27 320-320 320s-320-143.27-320-320h-64c0 212.077 171.923 384 384 384s384-171.923 384-384c0-212.077-171.923-384-384-384-123.718 0-233.772 58.508-304 149.364v-101.364c0-17.673-14.327-32-32-32s-32 14.327-32 32v192c0 17.674 14.327 32 32 32h176c17.674 0 32-14.326 32-32s-14.326-32-32-32h-107.295c57.24-86.756 155.583-144 267.295-144 176.73 0 320 143.27 320 320z","M544 320c0-17.673-14.326-32-32-32s-32 14.327-32 32v224c0 8.486 3.373 16.627 9.373 22.627l96 96c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-86.627-86.627v-210.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["history"],"defaultCode":59759,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1026,"name":"history","prevSize":32,"id":114,"code":59759},"setIdx":0,"setId":6,"iconIdx":115},{"icon":{"paths":["M522.042 195.354l224.464 260.044v366.234c0 5.856-4.752 10.605-10.614 10.605h-136.416v-149.821c0-23.424-19.014-42.413-42.47-42.413h-85.955c-23.453 0-42.467 18.989-42.467 42.413v149.821h-136.41c-5.864 0-10.617-4.749-10.617-10.605v-366.307l224.403-259.971c4.237-4.907 11.85-4.907 16.083 0zM560.57 895.856h175.322c41.043 0 74.32-33.232 74.32-74.224v-244.205h56.227c12.454 0 23.766-7.251 28.954-18.557 5.19-11.309 3.302-24.602-4.829-34.022l-320.272-371.033c-29.648-34.347-82.934-34.347-112.582 0l-320.27 371.033c-8.132 9.421-10.020 22.714-4.831 34.022 5.188 11.306 16.501 18.557 28.956 18.557h56.288v244.205c0 40.992 33.274 74.224 74.32 74.224h175.316c1.174 0.096 2.362 0.147 3.562 0.147h85.955c1.2 0 2.39-0.051 3.565-0.147z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["home"],"defaultCode":59760,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1027,"name":"home","prevSize":32,"id":115,"code":59760},"setIdx":0,"setId":6,"iconIdx":116},{"icon":{"paths":["M864 512c0-86.89-31.482-166.429-83.664-227.826l-496.162 496.162c61.397 52.182 140.937 83.664 227.826 83.664 194.403 0 352-157.597 352-352zM239.349 734.65l495.3-495.3c-60.662-49.597-138.182-79.349-222.65-79.349-194.404 0-352 157.596-352 352 0 84.467 29.753 161.987 79.349 222.65zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["ignore"],"defaultCode":59740,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1028,"name":"ignore","prevSize":32,"id":116,"code":59740},"setIdx":0,"setId":6,"iconIdx":117},{"icon":{"paths":["M406.685 405.334c0 47.126-38.205 85.331-85.334 85.331-47.127 0-85.332-38.205-85.332-85.331 0-47.13 38.205-85.334 85.332-85.334 47.13 0 85.334 38.205 85.334 85.334z","M97.352 192c0-17.673 14.327-32 32-32h767.999c17.674 0 32 14.327 32 32v640c0 17.674-14.326 32-32 32h-767.999c-17.673 0-32-14.326-32-32v-640zM161.352 764.163l151.704-176.989c9.271-10.813 24.57-14.202 37.536-8.307l153.123 69.603 160.474-204.24c6.010-7.651 15.174-12.15 24.902-12.23s18.963 4.272 25.098 11.821l151.162 186.048v-405.869h-703.999v540.163zM214.927 800h650.423v-68.64l-175.581-216.099-166.781 212.269-176.989-80.448-131.073 152.918z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["image"],"defaultCode":59761,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1029,"name":"image","prevSize":32,"id":117,"code":59761},"setIdx":0,"setId":6,"iconIdx":118},{"icon":{"paths":["M512 873.027c-199.389 0-361.026-161.635-361.026-361.024s161.636-361.026 361.026-361.026c199.389 0 361.024 161.637 361.024 361.026s-161.635 361.024-361.024 361.024zM512 938.669c235.642 0 426.666-191.024 426.666-426.666s-191.024-426.667-426.666-426.667c-235.642 0-426.667 191.025-426.667 426.667s191.025 426.666 426.667 426.666zM544.819 347.901c0 18.125-14.694 32.819-32.819 32.819-18.128 0-32.822-14.694-32.822-32.819 0-18.128 14.694-32.821 32.822-32.821 18.125 0 32.819 14.693 32.819 32.821zM512 413.542c-18.128 0-32.822 14.694-32.822 32.819v229.744c0 18.125 14.694 32.819 32.822 32.819 18.125 0 32.819-14.694 32.819-32.819v-229.744c0-18.125-14.694-32.819-32.819-32.819z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["info"],"defaultCode":59762,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1030,"name":"info","prevSize":32,"id":118,"code":59762},"setIdx":0,"setId":6,"iconIdx":119},{"icon":{"paths":["M512 864c-194.404 0-352-157.597-352-352s157.596-352 352-352c194.403 0 352 157.596 352 352s-157.597 352-352 352zM512 928c229.75 0 416-186.25 416-416s-186.25-416-416-416c-229.75 0-416 186.25-416 416s186.25 416 416 416zM662.627 361.373c12.496 12.496 12.496 32.758 0 45.254l-105.373 105.373 105.373 105.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-105.373-105.373-105.373 105.373c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l105.373-105.373-105.373-105.373c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l105.373 105.373 105.373-105.373c12.496-12.496 32.758-12.496 45.254 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["input-clear"],"defaultCode":59763,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1031,"name":"input-clear","prevSize":32,"id":119,"code":59763},"setIdx":0,"setId":6,"iconIdx":120},{"icon":{"paths":["M384 288c-17.674 0-32 14.327-32 32s14.326 32 32 32h256c17.674 0 32-14.326 32-32s-14.326-32-32-32h-256z","M352 448c0-17.674 14.326-32 32-32h256c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M512 640c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M224 224v576c0 35.347 28.654 64 64 64h448c35.347 0 64-28.653 64-64v-576c0-35.346-28.653-64-64-64h-448c-35.346 0-64 28.654-64 64zM288 800v-576h448v576h-448z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["instance"],"defaultCode":59764,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1032,"name":"instance","prevSize":32,"id":120,"code":59764},"setIdx":0,"setId":6,"iconIdx":121},{"icon":{"paths":["M563.59 255.992l-170.669 512.001h-136.941c-17.673 0-32 14.326-32 32 0 17.67 14.327 32 32 32h320c17.674 0 32-14.33 32-32 0-17.674-14.326-32-32-32h-115.597l170.669-512.001h136.928c17.674 0 32-14.327 32-32s-14.326-32-32-32h-159.002c-0.666-0.021-1.328-0.021-1.99 0h-159.008c-17.674 0-32 14.327-32 32s14.326 32 32 32h115.61z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["italic"],"defaultCode":59765,"grid":0},"attrs":[{}],"properties":{"order":1033,"name":"italic","prevSize":32,"id":121,"code":59765},"setIdx":0,"setId":6,"iconIdx":122},{"icon":{"paths":["M497.136 169.372c12.499 12.497 12.499 32.758 0 45.255l-35.958 35.96c1.078-0.016 2.163-0.025 3.245-0.025h191.152c115.11 0 208.426 93.316 208.426 208.426 0 115.107-93.315 208.422-208.426 208.422h-15.574v-64h15.574c79.763 0 144.426-64.659 144.426-144.422 0-79.766-64.662-144.426-144.426-144.426h-191.152c-1.030 0-2.058 0.011-3.082 0.032l35.795 35.796c12.499 12.499 12.499 32.758 0 45.258-12.496 12.496-32.758 12.496-45.254 0l-90.509-90.511c-12.496-12.497-12.496-32.758 0-45.255l90.509-90.51c12.496-12.497 32.758-12.497 45.254 0zM201.318 500.746h56.159v325.818h-59.023v-268.387h-1.909l-76.204 48.682v-54.090l80.977-52.022zM570.41 719.494c0 64.749-48.045 111.523-116.931 111.523-63.638 0-110.886-38.979-112.48-93.069h57.274c2.070 26.726 25.773 45.341 55.206 45.341 34.838 0 59.978-25.933 59.818-62.365 0.16-36.909-25.613-63.318-61.411-63.475-19.568-0.16-40.25 7.955-51.226 20.045l-53.296-8.749 17.024-168h188.998v49.318h-140.16l-9.386 86.384h1.91c12.090-14.317 35.475-24.816 61.885-24.816 59.184 0 102.774 45.181 102.774 107.862z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-backward"],"defaultCode":59766,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1034,"name":"jump-backward","prevSize":32,"id":122,"code":59766},"setIdx":0,"setId":6,"iconIdx":123},{"icon":{"paths":["M494.861 169.372c-12.496 12.497-12.496 32.758 0 45.255l35.962 35.96c-1.082-0.016-2.163-0.025-3.248-0.025h-191.149c-115.111 0-208.426 93.316-208.426 208.426 0 115.107 93.315 208.422 208.426 208.422h15.574v-64h-15.574c-79.764 0-144.426-64.659-144.426-144.422 0-79.766 64.661-144.426 144.426-144.426h191.149c1.030 0 2.061 0.011 3.085 0.032l-35.798 35.796c-12.496 12.499-12.496 32.758 0 45.258 12.499 12.496 32.758 12.496 45.258 0l90.509-90.511c12.496-12.497 12.496-32.758 0-45.255l-90.509-90.51c-12.499-12.497-32.758-12.497-45.258 0zM521.318 500.746h56.157v325.818h-59.021v-268.387h-1.91l-76.205 48.682v-54.090l80.979-52.022zM890.41 719.494c0 64.749-48.048 111.523-116.934 111.523-63.635 0-110.886-38.979-112.477-93.069h57.274c2.067 26.726 25.773 45.341 55.203 45.341 34.842 0 59.978-25.933 59.821-62.365 0.157-36.909-25.616-63.318-61.411-63.475-19.568-0.16-40.25 7.955-51.226 20.045l-53.296-8.749 17.021-168h189.002v49.318h-140.16l-9.386 86.384h1.91c12.090-14.317 35.475-24.816 61.885-24.816 59.181 0 102.774 45.181 102.774 107.862z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-forward"],"defaultCode":59767,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1035,"name":"jump-forward","prevSize":32,"id":123,"code":59767},"setIdx":0,"setId":6,"iconIdx":124},{"icon":{"paths":["M769.296 649.373c12.496 12.496 12.496 32.758 0 45.254l-192 192c-12.499 12.496-32.758 12.496-45.258 0l-192-192c-12.496-12.496-12.496-32.758 0-45.254 12.499-12.496 32.758-12.496 45.258 0l137.37 137.373v-578.746h-192v192c0 17.674-14.325 32-31.999 32s-32-14.326-32-32v-224c0-17.673 14.327-32 32-32h255.999c17.674 0 32 14.327 32 32v610.746l137.373-137.373c12.499-12.496 32.758-12.496 45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-to-message"],"defaultCode":59768,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1036,"name":"jump-to-message","prevSize":32,"id":124,"code":59768},"setIdx":0,"setId":6,"iconIdx":125},{"icon":{"paths":["M576 256c0 35.346-28.653 64-64 64s-64-28.654-64-64c0-35.346 28.653-64 64-64s64 28.654 64 64z","M576 512c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64z","M576 768c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["kebab"],"defaultCode":59769,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1037,"name":"kebab","prevSize":32,"id":125,"code":59769},"setIdx":0,"setId":6,"iconIdx":126},{"icon":{"paths":["M160 224c-35.346 0-64 28.654-64 64v448c0 35.347 28.654 64 64 64h704c35.347 0 64-28.653 64-64v-448c0-35.346-28.653-64-64-64h-704zM160 288h704v448h-704v-448zM256 352c-17.673 0-32 14.326-32 32s14.327 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM256 512c0-17.674 14.327-32 32-32h64c17.674 0 32 14.326 32 32s-14.326 32-32 32h-64c-17.673 0-32-14.326-32-32zM480 480c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM640 512c0-17.674 14.326-32 32-32h64c17.674 0 32 14.326 32 32s-14.326 32-32 32h-64c-17.674 0-32-14.326-32-32zM480 352c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM320 640c0-17.674 14.326-32 32-32h320c17.674 0 32 14.326 32 32s-14.326 32-32 32h-320c-17.674 0-32-14.326-32-32zM704 352c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["keyboard"],"defaultCode":59770,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1038,"name":"keyboard","prevSize":32,"id":126,"code":59770},"setIdx":0,"setId":6,"iconIdx":127},{"icon":{"paths":["M505.133 128.078c60.819-1.376 120.422 15.569 170.346 48.251 49.904 32.67 87.501 79.327 107.75 133.159 20.24 53.808 22.205 112.266 5.648 167.165-16.554 54.89-50.864 103.683-98.368 139.309-15.501 11.462-28.189 26.246-36.989 43.309-8.822 17.107-13.469 36-13.507 55.216v21.514h-96.013v-148.774l120.989-151.235c11.040-13.802 8.803-33.939-4.998-44.979s-33.939-8.803-44.979 4.998l-103.011 128.765-103.011-128.765c-11.040-13.802-31.178-16.038-44.979-4.998s-16.038 31.178-4.998 44.979l120.989 151.235v148.774h-95.994v-21.677c-0.138-19.030-4.762-37.728-13.462-54.691-8.694-16.954-21.21-31.69-36.509-43.194l-19.229 25.578 19.069-25.696c-34.247-25.418-61.857-57.84-80.845-94.736-18.985-36.89-28.886-77.331-29.027-118.285v-0.045c-0.71-146.981 123.709-271.715 281.13-275.177zM640.013 800c16.506 0 32.618-6.243 44.72-17.795 12.157-11.603 19.28-27.664 19.28-44.746v-22.842c0.022-8.947 2.182-17.856 6.39-26.016 4.214-8.176 10.406-15.459 18.208-21.216l0.192-0.144c58.173-43.59 100.733-103.75 121.35-172.109 20.621-68.378 18.154-141.245-7.021-208.177-25.168-66.908-71.664-124.28-132.602-164.174-60.915-39.878-133.274-60.348-206.826-58.689-189.76 4.184-344.567 155.060-343.702 339.427l0 0.045 32-0.154-32 0.109c0.176 51.165 12.553 101.558 36.121 147.35 23.547 45.754 57.616 85.658 99.521 116.774 7.682 5.792 13.781 13.062 17.952 21.194 4.164 8.122 6.33 16.944 6.409 25.84v22.781c0 17.082 7.123 33.142 19.28 44.746 12.106 11.552 28.218 17.795 44.72 17.795h256.006zM352 864c-17.674 0-32 14.326-32 32s14.326 32 32 32h320c17.674 0 32-14.326 32-32s-14.326-32-32-32h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["lamp-bulb"],"defaultCode":59836,"grid":0},"attrs":[{}],"properties":{"order":1039,"id":127,"name":"lamp-bulb","prevSize":32,"code":59836},"setIdx":0,"setId":6,"iconIdx":128},{"icon":{"paths":["M681.904 256c0-17.673-14.326-32-32-32s-32 14.327-32 32v56.875l-80.346 13.998c-17.411 3.034-29.069 19.61-26.035 37.021 3.034 17.408 19.61 29.066 37.021 26.032l69.36-12.086v69.373c-30.384 6.851-60.461 20.074-84.154 43.139-27.923 27.184-44.070 65.238-44.070 113.808 0 25.741 6.262 48.262 18.451 66.621 12.186 18.349 29.062 30.682 47.251 38 35.357 14.221 76.72 10.173 108.128-4.579l1.206-0.566c31.126-14.621 62.493-29.354 90.723-57.818 21.325-21.507 39.709-49.539 56.848-88.678 5.654 9.498 9.594 20.966 10.285 34.339 1.632 31.526-14.275 82.813-87.955 153.418-12.758 12.227-13.19 32.483-0.963 45.245 12.227 12.758 32.486 13.19 45.245 0.963 80.192-76.851 110.586-145.034 107.59-202.934-2.986-57.658-38.586-96.022-70.675-113.955-20.774-13.014-50.214-22.826-81.216-28.288-16.624-2.931-34.47-4.749-52.694-4.995v-74.243l101.718-17.722c17.411-3.034 29.066-19.61 26.032-37.019-3.034-17.411-19.606-29.066-37.018-26.032l-90.733 15.809v-45.724zM578.394 536.208c10.163-9.891 23.565-17.475 39.51-22.704v138.653c-13.443 2.547-27.485 1.731-38.634-2.752-7.712-3.104-13.658-7.757-17.824-14.029-4.157-6.262-7.766-15.997-7.766-31.216 0-33.35 10.563-54.176 24.714-67.952zM709.994 600.752c-8.682 8.755-17.782 15.706-28.090 22.074v-117.888c14.125 0.24 28.224 1.661 41.587 4.016 13.587 2.397 25.683 5.622 35.763 9.165-16.88 42.038-33.069 66.304-49.261 82.634zM247.704 565.334h98.386l-49.193-184.883-49.193 184.883zM390.851 733.562l-27.734-104.227h-132.442l-27.732 104.227c-4.544 17.078-22.073 27.242-39.152 22.694-17.079-4.544-27.24-22.070-22.696-39.152l106.323-399.598c13.494-50.714 85.462-50.713 98.956 0l106.323 399.598c4.544 17.082-5.616 34.608-22.694 39.152-17.078 4.547-34.608-5.616-39.152-22.694z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["language"],"defaultCode":59771,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1040,"name":"language","prevSize":32,"id":128,"code":59771},"setIdx":0,"setId":6,"iconIdx":129},{"icon":{"paths":["M234.831 743.917c-75.198-141.606-58.197-285.718 40.507-391.734 101.776-109.314 284.915-172.318 524.636-158.217 16.192 0.953 29.114 13.872 30.064 30.066 14.102 239.723-48.902 422.859-158.218 524.635-106.016 98.707-250.128 115.706-391.737 40.506l-65.457 65.456c-12.497 12.499-32.758 12.499-45.255 0-12.497-12.496-12.497-32.758 0-45.254l65.458-65.456zM282.51 696.237l300.107-300.109c12.496-12.496 32.758-12.496 45.254 0 12.496 12.499 12.496 32.758 0 45.258l-300.109 300.106c113.565 53.238 220.73 34.554 300.448-39.664 86.579-80.611 146.157-231.866 139.251-445.286-213.418-6.905-364.675 52.673-445.283 139.254-74.219 79.715-92.904 186.877-39.669 300.442z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["leaf"],"defaultCode":59814,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1041,"id":129,"name":"leaf","prevSize":32,"code":59814},"setIdx":0,"setId":6,"iconIdx":130},{"icon":{"paths":["M254.841 275.612l-13.972 14.271c-37.092 37.883-36.449 98.664 1.435 135.758l145.619 142.573c37.885 37.091 98.666 36.448 135.76-1.437l13.971-14.269c0.723-0.739 1.43-1.488 2.128-2.243l0.099 0.099c5.805-5.904 13.888-9.568 22.822-9.568 17.674 0 32 14.326 32 32 0 9.6-4.227 18.211-10.922 24.077l-0.397 0.41-13.974 14.269c-61.818 63.142-163.12 64.214-226.259 2.394l-145.622-142.576c-63.141-61.818-64.212-163.119-2.392-226.26l13.972-14.27c61.82-63.141 163.12-64.212 226.263-2.392l74.691 73.131c0.976 0.847 1.901 1.752 2.768 2.71l0.374 0.366-0.026 0.026c4.934 5.63 7.923 13.005 7.923 21.078 0 17.674-14.326 32-32 32-7.83 0-15.005-2.813-20.566-7.482l-0.106 0.109-77.834-76.206c-37.885-37.092-98.666-36.45-135.757 1.435zM790.566 768.003l13.971-14.269c37.091-37.885 36.448-98.666-1.437-135.757l-145.619-142.576c-37.885-37.091-98.666-36.448-135.757 1.437l-13.971 14.269c-0.723 0.739-1.434 1.488-2.128 2.243l-0.102-0.099c-5.805 5.907-13.885 9.568-22.822 9.568-17.67 0-32-14.326-32-32 0-9.6 4.227-18.211 10.922-24.077l0.4-0.406 13.971-14.272c61.821-63.142 163.12-64.211 226.262-2.39l145.619 142.573c63.142 61.821 64.211 163.12 2.394 226.262l-13.971 14.269c-61.821 63.142-163.123 64.211-226.262 2.394l-74.694-73.133c-0.976-0.845-1.901-1.75-2.768-2.71l-0.374-0.365 0.026-0.026c-4.931-5.629-7.923-13.005-7.923-21.078 0-17.674 14.326-32 32-32 7.83 0 15.005 2.813 20.566 7.482l0.106-0.109 77.837 76.208c37.885 37.091 98.662 36.448 135.757-1.437z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["link"],"defaultCode":59752,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1042,"name":"link","prevSize":32,"id":130,"code":59752},"setIdx":0,"setId":6,"iconIdx":131},{"icon":{"paths":["M840.541 128c31.318 0 56.813 24.79 56.813 55.383v657.212c0 30.592-25.494 55.427-56.813 55.427h-654.546c-31.254 0-56.642-24.835-56.642-55.427v-657.212c0-30.593 25.387-55.383 56.642-55.383h654.546zM300.196 233.75c-36.588 0-66.093 29.59-66.093 66.050 0 36.482 29.505 66.072 66.093 66.072 36.437 0 66.005-29.59 66.005-66.072 0-36.46-29.568-66.050-66.005-66.050zM243.148 782.461h114.029v-366.515h-114.029v366.515zM537.814 415.923h-109.187v366.515h113.773v-181.274c0-47.83 9.046-94.147 68.333-94.147 58.454 0 59.181 54.678 59.181 97.174v178.246h113.901v-201.008c0-98.714-21.312-174.598-136.666-174.598-55.402 0-92.566 30.381-107.757 59.203h-1.578v-50.112z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["linkedin-monochromatic"],"defaultCode":59658,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1043,"name":"linkedin-monochromatic","prevSize":32,"id":131,"code":59658},"setIdx":0,"setId":6,"iconIdx":132},{"icon":{"paths":["M700.144 361.891c4.685-24.973 34.704-34.093 49.13-13.171 31.994 46.403 50.726 102.653 50.726 163.28s-18.733 116.88-50.726 163.283c-14.426 20.922-44.445 11.802-49.13-13.174l-1.706-9.101c-1.581-8.429 0.384-17.082 4.858-24.403 20.749-33.965 32.704-73.888 32.704-116.605 0-42.714-11.955-82.637-32.704-116.605-4.474-7.318-6.438-15.971-4.858-24.4l1.706-9.104z","M320.704 395.395c-20.748 33.968-32.704 73.891-32.704 116.605 0 42.717 11.956 82.64 32.704 116.605 4.474 7.322 6.438 15.974 4.858 24.403l-1.706 9.101c-4.684 24.976-34.705 34.096-49.128 13.174-31.994-46.403-50.728-102.656-50.728-163.283s18.733-116.877 50.728-163.28c14.424-20.922 44.444-11.802 49.128 13.171l1.706 9.104c1.581 8.429-0.384 17.082-4.858 24.4z","M728.765 209.256l-0.515 2.747c-2.234 11.911 2.534 23.967 11.763 31.821 75.866 64.565 123.987 160.751 123.987 268.175 0 107.427-48.122 203.613-123.987 268.176-9.229 7.856-13.997 19.914-11.763 31.824l0.515 2.746c4.192 22.362 29.69 33.194 47.261 18.746 92.794-76.294 151.974-191.981 151.974-321.491 0-129.507-59.181-245.193-151.974-321.489-17.571-14.448-43.069-3.615-47.261 18.745z","M283.986 243.825c9.228-7.854 13.998-19.911 11.764-31.821l-0.515-2.747c-4.192-22.359-29.69-33.193-47.262-18.745-92.793 76.296-151.973 191.981-151.973 321.489 0 129.51 59.18 245.197 151.973 321.491 17.572 14.448 43.070 3.616 47.262-18.746l0.515-2.746c2.233-11.91-2.536-23.968-11.764-31.824-75.864-64.563-123.986-160.749-123.986-268.176 0-107.424 48.122-203.61 123.986-268.175z","M608 512c0 53.021-42.979 96-96 96s-96-42.979-96-96c0-53.018 42.979-96 96-96s96 42.982 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["live"],"defaultCode":59774,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1044,"name":"live","prevSize":32,"id":132,"code":59774},"setIdx":0,"setId":6,"iconIdx":133},{"icon":{"paths":["M439.274 704.374c0-33.645 26.278-47.677 72.726-47.677s72.73 14.032 72.73 47.677c0 32.96-13.19 111.069-23.914 149.76-4.963 17.808-22.080 25.171-48.816 25.171s-43.85-7.363-48.813-25.174c-10.717-38.666-23.914-116.688-23.914-149.757zM616.778 870.374l0.026-0.090c6.176-22.291 12.566-53.869 17.386-83.453 4.688-28.787 8.72-60.707 8.72-82.458 0-35.891-15.811-67.802-46.797-87.114-26.035-16.227-57.152-19.926-84.112-19.926-26.957 0-58.077 3.699-84.112 19.926-30.982 19.312-46.797 51.222-46.797 87.114 0 21.805 4.035 53.728 8.726 82.515 4.819 29.578 11.21 61.123 17.379 83.392l0.026 0.086c7.402 26.557 24.982 45.664 46.87 56.467 19.472 9.61 40.426 11.834 57.907 11.834 17.485 0 38.435-2.224 57.907-11.83 21.888-10.8 39.469-29.907 46.87-56.464zM459.635 460.8c0-28.275 23.446-51.2 52.365-51.2s52.365 22.925 52.365 51.2c0 28.278-23.446 51.2-52.365 51.2s-52.365-22.922-52.365-51.2zM512 341.334c-67.478 0-122.182 53.488-122.182 119.466 0 65.981 54.704 119.469 122.182 119.469s122.182-53.488 122.182-119.469c0-65.978-54.704-119.466-122.182-119.466zM677.802 537.254c-6.662 13.792-3.882 31.11 6.278 42.573 14.086 15.894 39.85 17.939 50.205-0.602 19.642-35.174 30.806-75.526 30.806-118.426 0-136.672-113.315-247.465-253.091-247.465-139.779 0-253.092 110.793-253.092 247.465 0 42.899 11.164 83.251 30.806 118.426 10.354 18.541 36.119 16.496 50.205 0.602 10.16-11.462 12.938-28.781 6.275-42.573-11.203-23.187-17.469-49.104-17.469-76.454 0-98.97 82.054-179.199 183.274-179.199s183.27 80.229 183.27 179.199c0 27.35-6.262 53.267-17.469 76.454zM730.16 699.795c-0.304-10.659 3.542-21.072 10.928-28.762 52.771-54.957 85.094-128.902 85.094-210.234 0-169.661-140.666-307.199-314.182-307.199s-314.182 137.538-314.182 307.199c0 81.331 32.323 155.28 85.093 210.234 7.386 7.69 11.234 18.102 10.928 28.762-0.833 29.018-31.273 47.917-52.121 27.715-70.223-68.042-113.718-162.41-113.718-266.71 0-207.363 171.923-375.465 384-375.465s384 168.102 384 375.465c0 104.304-43.498 198.672-113.722 266.714-20.848 20.202-51.286 1.302-52.118-27.718z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["live-streaming"],"defaultCode":59773,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1045,"name":"live-streaming","prevSize":32,"id":133,"code":59773},"setIdx":0,"setId":6,"iconIdx":134},{"icon":{"paths":["M397.011 527.334c26.576 0 48.122-21.587 48.122-48.214s-21.546-48.214-48.122-48.214c-26.576 0-48.118 21.587-48.118 48.214s21.542 48.214 48.118 48.214z","M589.491 479.12c0 26.627-21.542 48.214-48.118 48.214s-48.122-21.587-48.122-48.214c0-26.627 21.546-48.214 48.122-48.214s48.118 21.587 48.118 48.214z","M733.853 479.12c0 26.627-21.542 48.214-48.118 48.214s-48.122-21.587-48.122-48.214c0-26.627 21.546-48.214 48.122-48.214s48.118 21.587 48.118 48.214z","M88.039 813.683l119.625 31.283c85.312 22.307 173.45-16.256 238.691-79.709 29.501 4.794 59.875 7.242 90.678 7.242 218.294 0 404.339-122.864 404.339-294.518 0-171.664-186.042-294.52-404.339-294.52-218.314 0-404.351 122.852-404.34 294.523 0 65.072 27.642 125.014 75.655 173.587-2.847 24.835-14.596 44.73-36.049 68.55l-84.261 93.562zM537.034 258.997c183.13 0 331.6 98.043 331.6 218.984 0 120.931-148.47 218.982-331.6 218.982-40.781 0-79.834-4.877-115.91-13.763-36.669 45.6-117.335 109.008-195.697 88.518 25.489-28.304 63.251-76.131 55.168-154.909-46.968-37.779-75.162-86.134-75.162-138.829-0.008-120.95 148.461-218.984 331.6-218.984z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["livechat-monochromatic"],"defaultCode":59775,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1046,"name":"livechat-monochromatic","prevSize":32,"id":134,"code":59775},"setIdx":0,"setId":6,"iconIdx":135},{"icon":{"paths":["M512 128c-97.203 0-176 78.798-176 176v142.477h-16c-53.020 0-96 42.979-96 96v257.523c0 53.021 42.981 96 96 96h384c53.021 0 96-42.979 96-96v-257.523c0-53.021-42.979-96-96-96h-16v-142.477c0-97.202-78.797-176-176-176zM624 304v142.477h-224v-142.477c0-61.856 50.144-112 112-112s112 50.144 112 112z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["lock-filled"],"defaultCode":59748,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1047,"name":"lock-filled","prevSize":32,"id":135,"code":59748},"setIdx":0,"setId":6,"iconIdx":136},{"icon":{"paths":["M336 304c0-97.202 78.797-176 176-176s176 78.798 176 176v142.477h16c53.021 0 96 42.979 96 96v257.523c0 53.021-42.979 96-96 96h-384c-53.019 0-96-42.979-96-96v-257.523c0-53.021 42.981-96 96-96h16v-142.477zM400 446.477h224v-142.477c0-61.856-50.144-112-112-112s-112 50.144-112 112v142.477zM320 510.477c-17.673 0-32 14.326-32 32v257.523c0 17.674 14.327 32 32 32h384c17.674 0 32-14.326 32-32v-257.523c0-17.674-14.326-32-32-32h-384z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["locker"],"defaultCode":59749,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1048,"name":"locker","prevSize":32,"id":136,"code":59749},"setIdx":0,"setId":6,"iconIdx":137},{"icon":{"paths":["M341.334 778.672c-17.674 0-32 14.326-32 32s14.326 32 32 32h341.334c17.674 0 32-14.326 32-32s-14.326-32-32-32h-341.334zM85.335 298.672c0-70.692 57.308-128 128-128h597.334c70.691 0 128 57.308 128 128v298.666c0 70.694-57.309 128-128 128h-597.334c-70.692 0-128-57.306-128-128v-298.666zM213.335 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.347 28.654 64 64 64h597.334c35.344 0 64-28.653 64-64v-298.666c0-35.347-28.656-64-64-64h-597.334zM256 320c0-11.782 9.551-21.333 21.333-21.333h170.667c11.782 0 21.334 9.551 21.334 21.333s-9.552 21.334-21.334 21.334h-170.667c-11.782 0-21.333-9.552-21.333-21.334zM277.333 554.666c-11.782 0-21.333 9.552-21.333 21.334s9.551 21.334 21.333 21.334h85.332c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-85.332zM554.666 320c0-11.782 9.552-21.333 21.334-21.333h170.666c11.782 0 21.334 9.551 21.334 21.333s-9.552 21.334-21.334 21.334h-170.666c-11.782 0-21.334-9.552-21.334-21.334zM448 554.666c-11.782 0-21.334 9.552-21.334 21.334s9.552 21.334 21.334 21.334h298.666c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-298.666zM256 448c0-11.782 9.551-21.334 21.333-21.334h213.332c11.782 0 21.334 9.552 21.334 21.334s-9.552 21.334-21.334 21.334h-213.332c-11.782 0-21.333-9.552-21.333-21.334zM618.666 426.666c-11.782 0-21.331 9.552-21.331 21.334s9.549 21.334 21.331 21.334h128c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["log-view"],"defaultCode":59778,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1049,"name":"log-view","prevSize":32,"id":137,"code":59778},"setIdx":0,"setId":6,"iconIdx":138},{"icon":{"paths":["M176 96c-17.673 0-32 14.327-32 32v768c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-96c0-17.674-14.326-32-32-32s-32 14.326-32 32v64h-448v-704h448v64c0 17.673 14.326 32 32 32s32-14.327 32-32v-96c0-17.673-14.326-32-32-32h-512zM521.373 329.373c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.254l-105.373 105.373h418.746c17.674 0 32 14.326 32 32s-14.326 32-32 32h-418.746l105.373 105.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-160-160c-12.496-12.496-12.496-32.758 0-45.254l160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["login"],"defaultCode":59779,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1050,"name":"login","prevSize":32,"id":138,"code":59779},"setIdx":0,"setId":6,"iconIdx":139},{"icon":{"paths":["M268.099 96c-17.673 0-32 14.327-32 32v768c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-96c0-17.674-14.326-32-32-32s-32 14.326-32 32v64h-448v-704h448v64c0 17.673 14.326 32 32 32s32-14.327 32-32v-96c0-17.673-14.326-32-32-32h-512zM994.726 489.373l-160-160c-12.496-12.497-32.758-12.497-45.254 0s-12.496 32.758 0 45.254l105.373 105.373h-418.746c-17.674 0-32 14.326-32 32s14.326 32 32 32h418.746l-105.373 105.373c-12.496 12.496-12.496 32.758 0 45.254s32.758 12.496 45.254 0l160-160c12.496-12.496 12.496-32.758 0-45.254z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["logout"],"defaultCode":59780,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1051,"name":"logout","prevSize":32,"id":139,"code":59780},"setIdx":0,"setId":6,"iconIdx":140},{"icon":{"paths":["M192 736h640v-448h-640v448zM128 256c0-17.673 14.327-32 32-32h704c17.674 0 32 14.327 32 32v512c0 17.674-14.326 32-32 32h-704c-17.673 0-32-14.326-32-32v-512zM305.304 389.082c-14.866-9.555-34.665-5.251-44.222 9.613-9.557 14.867-5.253 34.666 9.613 44.224l241.304 155.123 241.306-155.123c14.864-9.558 19.168-29.357 9.613-44.224-9.558-14.864-29.357-19.168-44.224-9.613l-206.694 132.877-206.696-132.877z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["mail"],"defaultCode":59781,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1052,"name":"mail","prevSize":32,"id":140,"code":59781},"setIdx":0,"setId":6,"iconIdx":141},{"icon":{"paths":["M302.769 192h418.463l23.187 72.727h-0.211l23.792 63.999c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818c0-18.476-14.326-33.454-32-33.454s-32 14.978-32 33.454c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818c0-18.476-14.326-33.454-32-33.454s-32 14.978-32 33.454c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818l23.794-63.999h-0.213l23.188-72.727zM212.406 264.727l36.491-114.448c4.231-13.27 16.56-22.279 30.488-22.279h465.23c13.93 0 26.259 9.009 30.49 22.279l56.896 178.447c0 33.939-12.083 64.925-32 88.515v350.778c0 53.018-42.979 96-96 96h-384c-53.019 0-96-42.982-96-96v-350.778c-19.916-23.59-32-54.576-32-88.515l20.406-63.999zM288 458.33v309.69c0 17.67 14.327 32 32 32h128v-192.019h128v192.019h128c17.674 0 32-14.33 32-32v-309.69c-10.227 2.752-20.95 4.214-32 4.214-38.23 0-72.547-17.52-96-45.302-23.453 27.782-57.77 45.302-96 45.302s-72.547-17.52-96-45.302c-23.453 27.782-57.77 45.302-96 45.302-11.050 0-21.772-1.462-32-4.214z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["marketplace"],"defaultCode":59782,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1053,"name":"marketplace","prevSize":32,"id":141,"code":59782},"setIdx":0,"setId":6,"iconIdx":142},{"icon":{"paths":["M773.072 576c-35.344 0-64-28.653-64-64s28.656-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64z","M517.072 576c-35.344 0-64-28.653-64-64s28.656-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64z","M261.073 576c-35.346 0-64-28.653-64-64s28.654-64 64-64c35.346 0 63.999 28.653 63.999 64s-28.652 64-63.999 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["meatballs"],"defaultCode":59783,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1054,"name":"meatballs","prevSize":32,"id":142,"code":59783},"setIdx":0,"setId":6,"iconIdx":143},{"icon":{"paths":["M651.36 116.071c-57.242-19.989-105.792-20.069-138.358-20.071v64l-1.002-64c-92.006 0.342-297.345 47.824-381.242 242.995-17.897 38.97-34.758 103.344-34.758 173.005 0 69.958 17.020 146.285 52.216 207.875 23.229 40.653 92.799 131.376 191.179 173.536 94.861 40.656 206.368 52.349 296.49 16.301 16.41-6.563 24.39-25.187 17.827-41.597s-25.187-24.39-41.597-17.827c-69.878 27.952-163.171 20.445-247.51-15.699-80.819-34.64-141.384-112.451-160.821-146.464-28.804-50.41-43.784-115.418-43.784-176.125 0-60.765 15.020-116.182 29.055-146.589l0.184-0.4 0.173-0.406c69.507-162.181 243.823-204.604 323.589-204.605 31.594 0.002 70.877 0.296 117.258 16.493 46.147 16.114 101.389 48.779 161.824 116.767 43.658 49.115 63.533 114.977 69.389 177.713 5.891 63.12-2.854 118.189-11.546 142.093-6.4 17.6-20.429 45.44-59.392 45.699-18.259-0.806-72.822-14.672-83.12-69.568v-235.062c0-17.674-3.414-34.134-29.014-34.134-19.338 0-26.454 16.461-26.454 34.134v34.131c-35.181-39.859-95.402-68.266-152.746-68.266-106.038 0-192 85.962-192 192s85.962 192 192 192c62.179 0 117.658-29.555 152.746-75.386 25.715 71.078 102.57 93.027 137.014 94.134l0.515 0.016h0.512c82.643 0 111.715-64.806 120.086-87.83 12.64-34.762 21.674-99.696 15.12-169.907-6.589-70.595-29.379-151.401-85.277-214.287-66.902-75.265-131.075-114.597-188.557-134.67zM627.2 512c0 70.691-57.309 128-128 128s-128-57.309-128-128c0-70.691 57.309-128 128-128s128 57.309 128 128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["mention"],"defaultCode":59784,"grid":0},"attrs":[{}],"properties":{"order":1055,"name":"mention","prevSize":32,"id":143,"code":59784},"setIdx":0,"setId":6,"iconIdx":144},{"icon":{"paths":["M223.311 308.609c-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-9.348 103.235 27.547 175.997 86.848 226.374 60.643 51.52 146.602 80.998 235.29 90.893 88.614 9.885 186.224 1.398 263.341-14.973 38.56-8.189 70.928-18.125 93.888-28.128 8.906-3.882 15.837-7.536 20.944-10.765-2.378-1.514-5.248-3.197-8.675-5.030-8.886-4.749-19.059-9.261-29.613-13.894l-1.843-0.81c-9.315-4.083-19.725-8.65-27.613-13.078-14.291-8.026-28.317-17.155-38.544-26.867-5.034-4.781-10.762-11.194-14.595-19.184-4.054-8.454-6.96-21.078-1.261-34.435 30.816-72.186 45.459-111.725 52.554-137.834 6.621-24.378 6.621-36.653 6.621-56.17v-0.179c0-15.51-8.979-86.595-53.776-152.876-43.376-64.174-121.395-125.729-264.832-125.729-129.725 0-207.83 53.576-254.529 118.696zM173.267 272.433c58.132-81.063 154.749-144.433 304.573-144.433 164.896 0 261.594 72.589 315.859 152.878 52.838 78.181 64.416 161.881 64.416 187.641 0 21.654-0.022 40.336-8.797 72.64-7.83 28.835-22.627 68.614-50.048 133.424 5.069 4.032 12.592 9.005 22.506 14.57 5.123 2.877 12.995 6.339 24.054 11.194 10.266 4.506 22.582 9.93 33.891 15.978 10.848 5.798 23.526 13.571 32.954 23.738 9.859 10.63 20.208 28.87 12.816 51.139-4.87 14.672-16.182 25.091-25.61 32.016-10.24 7.52-22.947 14.278-36.858 20.342-27.946 12.176-64.582 23.181-105.68 31.907-82.198 17.453-186.522 26.688-282.909 15.936-96.31-10.746-195.346-43.178-268.313-105.165-74.031-62.893-119.295-154.778-108.551-277.856 0.276-63.411 19.117-157.053 75.696-235.948z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["message"],"defaultCode":59786,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1056,"name":"message","prevSize":32,"id":144,"code":59786},"setIdx":0,"setId":6,"iconIdx":145},{"icon":{"paths":["M477.84 128c104.256 0 181.251 29.018 237.494 70.652l-44.317 44.317c-45.52-31.22-107.747-53.057-193.178-53.057-129.725 0-207.83 53.576-254.529 118.696-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-7.328 80.928 13.761 143.126 51.784 190.499l-43.879 43.878c-50.179-59.901-78.131-139.043-69.441-238.595 0.276-63.411 19.117-157.053 75.696-235.948 58.132-81.063 154.749-144.433 304.573-144.433zM822.848 332.499l-47.008 47.008c16.502 42.634 20.608 78.525 20.608 89.011v0.179c0 19.517 0 31.792-6.621 56.17-7.094 26.109-21.738 65.648-52.554 137.834-5.699 13.357-2.794 25.981 1.261 34.435 3.834 7.99 9.562 14.403 14.595 19.184 10.227 9.712 24.253 18.842 38.544 26.867 7.888 4.429 18.298 8.995 27.613 13.078l1.843 0.81c10.554 4.634 20.726 9.146 29.613 13.894 3.427 1.834 6.298 3.517 8.672 5.030-5.104 3.229-12.035 6.883-20.941 10.765-22.96 10.003-55.328 19.939-93.888 28.128-77.12 16.371-174.73 24.858-263.341 14.973-43.744-4.88-86.826-14.525-126.534-29.229l-47.542 47.542c52.771 23.018 110.492 36.886 167.267 43.222 96.387 10.752 200.71 1.517 282.909-15.936 41.098-8.726 77.731-19.731 105.68-31.907 13.91-6.064 26.618-12.822 36.858-20.342 9.427-6.925 20.739-17.344 25.61-32.016 7.392-22.269-2.957-40.509-12.816-51.139-9.427-10.166-22.106-17.939-32.954-23.738-11.309-6.048-23.626-11.472-33.891-15.978-11.059-4.854-18.934-8.317-24.054-11.194-9.914-5.565-17.437-10.538-22.506-14.57 27.421-64.81 42.214-104.589 50.048-133.424 8.774-32.304 8.797-50.986 8.797-72.64 0-20.106-7.053-75.501-35.267-136.019zM836.038 153.372c12.499-12.497 32.758-12.497 45.254 0 12.499 12.497 12.499 32.758 0 45.255l-682.665 682.665c-12.497 12.499-32.758 12.499-45.255 0-12.497-12.496-12.497-32.755 0-45.254l682.666-682.666z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["message-disabled"],"defaultCode":59785,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1057,"name":"message-disabled","prevSize":32,"id":145,"code":59785},"setIdx":0,"setId":6,"iconIdx":146},{"icon":{"paths":["M86.686 85.336l730.792 774.088c0 0 24.899 17.558 43.936-2.928 19.040-20.486 4.394-40.973 4.394-40.973l-779.122-730.187zM318.080 158.503l556.516 599.955c0 0 24.896 17.558 43.936-2.928 19.037-20.486 4.394-40.973 4.394-40.973l-604.845-556.054zM712.035 915.030l-556.517-599.955 604.843 556.054c0 0 14.646 20.486-4.39 40.973-19.040 20.486-43.936 2.928-43.936 2.928zM513.693 221.419l388.803 419.15c0 0 17.395 12.269 30.694-2.042 13.302-14.314 3.069-28.627 3.069-28.627l-422.566-388.482zM597.878 915.677l-388.805-419.152 422.568 388.48c0 0 10.234 14.314-3.069 28.627-13.302 14.31-30.694 2.045-30.694 2.045zM713.498 312.143l176.221 190.551c0 0 8.605 5.747 15.184-0.96 6.579-6.704 1.517-13.411 1.517-13.411l-192.922-176.18zM482.582 880.23l-176.219-190.55 192.923 176.179c0 0 5.059 6.707-1.52 13.414-6.579 6.704-15.184 0.957-15.184 0.957z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["meteor-monochromatic"],"defaultCode":59659,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1058,"name":"meteor-monochromatic","prevSize":32,"id":146,"code":59659},"setIdx":0,"setId":6,"iconIdx":147},{"icon":{"paths":["M608 288c0-53.019-42.979-96-96-96s-96 42.981-96 96v128c0 53.021 42.979 96 96 96s96-42.979 96-96v-128zM352 288c0-88.365 71.635-160 160-160s160 71.635 160 160v128c0 88.365-71.635 160-160 160s-160-71.635-160-160v-128zM256 384c17.673 0 32 14.326 32 32 0 92.086 37.757 149.632 83.722 185.6 46.464 36.358 102.736 51.581 140.278 54.326 37.542-2.746 93.814-17.968 140.278-54.326 45.962-35.968 83.722-93.514 83.722-185.6 0-17.674 14.326-32 32-32s32 14.326 32 32c0 112.714-47.574 188.499-108.278 236-47.904 37.485-103.082 56.762-147.722 64.381v115.619h160c17.674 0 32 14.326 32 32s-14.326 32-32 32h-384c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-115.619c-44.64-7.619-99.818-26.896-147.722-64.381-60.703-47.501-108.278-123.286-108.278-236 0-17.674 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["microphone"],"defaultCode":59788,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1059,"name":"microphone","prevSize":32,"id":147,"code":59788},"setIdx":0,"setId":6,"iconIdx":148},{"icon":{"paths":["M512 128c75.546 0 138.861 52.356 155.645 122.762l-59.645 59.644v-22.405c0-53.019-42.979-96-96-96s-96 42.981-96 96v128c0 24.067 8.858 46.067 23.488 62.915l-45.322 45.325c-26.182-28.49-42.166-66.499-42.166-108.24v-128c0-88.365 71.635-160 160-160zM561.35 568.243l102.893-102.893c-15.763 48.672-54.221 87.13-102.893 102.893zM288 416c0 72.154 23.181 123.101 55.328 159.078l-45.304 45.302c-43.428-47.35-74.024-113.99-74.024-204.381 0-17.674 14.327-32 32-32s32 14.326 32 32zM478.659 650.938l-51.808 51.808c18.56 6.374 36.579 10.806 53.149 13.635v115.619h-160c-17.673 0-32 14.326-32 32s14.327 32 32 32h384c17.674 0 32-14.326 32-32s-14.326-32-32-32h-160v-115.619c44.64-7.619 99.818-26.896 147.722-64.381 60.704-47.501 108.278-123.286 108.278-236 0-17.674-14.326-32-32-32s-32 14.326-32 32c0 92.086-37.757 149.632-83.722 185.6-46.464 36.358-102.736 51.581-140.278 54.326-9.971-0.73-21.264-2.339-33.341-4.989zM825.373 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672-672z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["microphone-disabled"],"defaultCode":59787,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1060,"name":"microphone-disabled","prevSize":32,"id":148,"code":59787},"setIdx":0,"setId":6,"iconIdx":149},{"icon":{"paths":["M234.666 170.661c0-47.128 38.205-85.333 85.333-85.333h384.001c47.126 0 85.331 38.205 85.331 85.333v682.667c0 47.13-38.205 85.334-85.331 85.334h-384.001c-47.128 0-85.333-38.205-85.333-85.334v-682.667zM298.666 170.661v682.667c0 11.782 9.551 21.334 21.333 21.334h384.001c11.782 0 21.331-9.552 21.331-21.334v-682.667c0-11.782-9.549-21.333-21.331-21.333h-96.291c-2.653 24.002-23.002 42.672-47.709 42.672h-96c-24.707 0-45.056-18.67-47.709-42.672h-96.292c-11.782 0-21.333 9.551-21.333 21.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["mobile"],"defaultCode":59789,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1061,"name":"mobile","prevSize":32,"id":149,"code":59789},"setIdx":0,"setId":6,"iconIdx":150},{"icon":{"paths":["M319.247 231.566c-62.882 49.504-135.086 136.549-141.94 266.127-5.762 108.922 37.404 187.184 89.915 241.51 53.258 55.098 115.702 84.925 144.25 94.438 41.859 13.955 114.269 29.536 234.643-15.603 34.858-13.072 73.165-42.096 108.304-78.426 14.272-14.755 27.616-30.294 39.6-45.773-28.778 9.293-61.699 17.754-96.589 23.594-56.192 9.405-119.29 12.32-179.411-0.237-2.49-0.518-4.96-1.030-7.408-1.536-22.195-4.576-42.733-8.816-62.589-17.648-23.091-10.275-43.805-25.891-69.299-51.386-42.096-42.096-89.142-107.222-89.371-213.843-1.569-34.080 4.622-81.878 13.764-129.216 4.624-23.946 10.142-48.465 16.132-72.003zM345.562 138.217c32.8-17.15 63.709 15.843 53.875 45.907-12.234 37.414-24.586 85.511-33.482 131.58-9.024 46.732-13.949 88.633-12.643 114.7l0.038 0.797v0.8c0 84.915 36.173 134.918 70.627 169.373 22.509 22.509 36.835 32.278 50.064 38.166 13.229 5.885 26.832 8.717 51.085 13.763 1.923 0.4 3.917 0.816 5.978 1.248 49.914 10.426 104.534 8.336 155.76-0.237 65.434-10.954 122.384-31.981 152.374-47.386 17.562-9.021 34.992-2.47 44.477 5.965 9.661 8.589 19.376 27.152 8.886 46.954-20.637 38.95-53.645 84.419-92.182 124.259-38.211 39.51-84.317 76.038-131.834 93.859-135.626 50.858-223.216 34.438-277.354 16.394-36.515-12.173-108.392-46.912-170.026-110.675-62.381-64.534-114.684-159.427-107.81-289.373 10.79-203.979 157.583-317.098 232.165-356.093z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["moon"],"defaultCode":59790,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1062,"name":"moon","prevSize":32,"id":150,"code":59790},"setIdx":0,"setId":6,"iconIdx":151},{"icon":{"paths":["M144 160c-17.673 0-32 14.327-32 32s14.327 32 32 32h192c17.674 0 32-14.327 32-32s-14.326-32-32-32h-192zM700.4 346.646c11.795-13.165 32.026-14.272 45.187-2.48 13.162 11.795 14.272 32.026 2.477 45.187l-81.222 90.646h216.358c17.674 0 32 14.326 32 32s-14.326 32-32 32h-216.358l81.222 90.646c11.795 13.162 10.685 33.392-2.477 45.187-13.162 11.792-33.392 10.685-45.187-2.48l-129.030-144c-10.893-12.154-10.893-30.554 0-42.707l129.030-144zM112 512c0-17.674 14.327-32 32-32h192c17.674 0 32 14.326 32 32s-14.326 32-32 32h-192c-17.673 0-32-14.326-32-32zM144 640c-17.673 0-32 14.326-32 32s14.327 32 32 32h192c17.674 0 32-14.326 32-32s-14.326-32-32-32h-192zM112 352c0-17.674 14.327-32 32-32h192c17.674 0 32 14.326 32 32s-14.326 32-32 32h-192c-17.673 0-32-14.326-32-32zM144 800c-17.673 0-32 14.326-32 32s14.327 32 32 32h192c17.674 0 32-14.326 32-32s-14.326-32-32-32h-192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["move-to-the-queue"],"defaultCode":59791,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1063,"name":"move-to-the-queue","prevSize":32,"id":151,"code":59791},"setIdx":0,"setId":6,"iconIdx":152},{"icon":{"paths":["M809.002 166.758c7.782 6.063 12.333 15.377 12.333 25.242v448h-0.112c0.074 1.734 0.112 3.478 0.112 5.229 0 69.053-57.309 125.030-128 125.030-70.694 0-128-55.978-128-125.030s57.306-125.030 128-125.030c23.312 0 45.171 6.090 64 16.73v-303.86l-384 96.798v409.136c0 69.053-57.309 125.037-128.001 125.037s-128-55.978-128-125.030c0-69.050 57.308-125.027 128-125.027 23.314 0 45.173 6.086 64 16.726v-325.777c0-14.66 9.962-27.446 24.177-31.029l448-112.93c9.568-2.411 19.709-0.276 27.491 5.788z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["musical-note"],"defaultCode":59792,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1064,"name":"musical-note","prevSize":32,"id":152,"code":59792},"setIdx":0,"setId":6,"iconIdx":153},{"icon":{"paths":["M208 176c-35.346 0-64 28.654-64 64v576c0 35.347 28.654 64 64 64h576c35.347 0 64-28.653 64-64v-576c0-35.346-28.653-64-64-64h-576zM208 240h576v576h-576v-576zM698.627 558.15c-0.189 17.674-14.669 31.846-32.339 31.658-17.674-0.189-31.846-14.669-31.658-32.339l1.318-123.594-309.341 308.774c-12.51 12.483-32.771 12.464-45.256-0.042-12.485-12.509-12.467-32.771 0.042-45.258l309.195-308.624-123.382 1.315c-17.674 0.189-32.154-13.984-32.339-31.654-0.189-17.674 13.984-32.15 31.654-32.339l201.92-2.157c8.605-0.093 16.886 3.286 22.97 9.37 6.086 6.086 9.462 14.365 9.373 22.97l-2.157 201.92z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["new-window"],"defaultCode":59793,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1065,"name":"new-window","prevSize":32,"id":153,"code":59793},"setIdx":0,"setId":6,"iconIdx":154},{"icon":{"paths":["M601.331 808.928h-174.154c0.003 48.090 38.989 87.072 87.078 87.072s87.075-38.982 87.075-87.072zM815.597 731.677c7.274 9.696 8.442 22.669 3.021 33.51s-16.499 17.69-28.621 17.69h-565.996c-12.943 0-24.611-7.798-29.564-19.757-4.953-11.955-2.215-25.718 6.937-34.87l51.653-51.654v-274.032c0-144.272 116.957-261.228 261.229-261.228s261.229 116.956 261.229 261.228v275.629l40.112 53.485zM711.485 715.894v-313.331c0-108.926-88.304-197.228-197.229-197.228-108.928 0-197.229 88.302-197.229 197.228v313.331h394.458z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["notification"],"defaultCode":59795,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1066,"name":"notification","prevSize":32,"id":154,"code":59795},"setIdx":0,"setId":6,"iconIdx":155},{"icon":{"paths":["M781.837 402.634c0-5.245-0.154-10.454-0.461-15.622l-63.539 63.539v265.363h-265.363l-66.979 66.979h425.363c12.944 0 24.611-7.795 29.565-19.754 4.954-11.955 2.214-25.722-6.938-34.874l-51.648-51.648v-273.984zM704.765 217.373l-45.254 45.255c-35.638-35.351-84.704-57.189-138.867-57.189-108.909 0-197.194 88.287-197.194 197.195v196.054l-64.001 64v-260.054c0-144.254 116.941-261.195 261.194-261.195 71.837 0 136.899 29.001 184.122 75.934zM433.578 808.934c0 48.086 38.982 87.066 87.066 87.066s87.066-38.979 87.066-87.066h-174.131zM854.275 190.982c-11.334-11.334-29.709-11.334-41.043 0l-612.732 612.733c-11.333 11.331-11.333 29.709 0 41.040 11.334 11.334 29.709 11.334 41.043 0l612.732-612.731c11.334-11.333 11.334-29.709 0-41.043z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["notification-disabled"],"defaultCode":59794,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1067,"name":"notification-disabled","prevSize":32,"id":155,"code":59794},"setIdx":0,"setId":6,"iconIdx":156},{"icon":{"paths":["M712.051 512.675v54.89c-0.195 76.736-43.741 143.283-107.44 176.445-5.53-25.67-28.362-44.906-55.683-44.906h-72.502c-31.459 0-56.963 25.501-56.963 56.963v41.427c0 31.462 25.504 56.963 56.963 56.963h72.502c28.509 0 52.128-20.944 56.307-48.288 69.261-26.829 123.962-82.883 148.966-153.030 4.723 1.27 9.69 1.946 14.813 1.946h28.483c31.459 0 56.963-25.504 56.963-56.963v-85.446c0-31.459-25.504-56.963-56.963-56.963h-28.483v-28.483c0-141.572-114.765-256.338-256.336-256.338s-256.339 114.766-256.339 256.338v23.302h-28.483c-31.46 0-56.964 25.504-56.964 56.966v103.571c0 31.459 25.504 56.963 56.964 56.963h28.482c31.46 0 56.964-25.504 56.964-56.963v-36.253h0.149c-0.099-2.576-0.148-5.165-0.148-7.766v-139.821c0-110.111 89.263-199.374 199.375-199.374s199.373 89.263 199.373 199.374v85.446z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["omnichannel"],"defaultCode":59796,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1068,"name":"omnichannel","prevSize":32,"id":156,"code":59796},"setIdx":0,"setId":6,"iconIdx":157},{"icon":{"paths":["M705.578 633.158c9.507-9.235 24.701-9.018 33.939 0.486 9.238 9.507 9.021 24.701-0.486 33.939l-208.275 202.387c-9.312 9.050-24.138 9.050-33.45 0l-208.276-202.387c-9.506-9.238-9.724-24.432-0.487-33.939 9.237-9.504 24.432-9.722 33.937-0.486l191.549 186.134 191.549-186.134zM705.578 411.584c9.507 9.238 24.701 9.021 33.939-0.486s9.021-24.701-0.486-33.939l-208.275-202.385c-9.312-9.051-24.138-9.051-33.45 0l-208.276 202.385c-9.506 9.238-9.724 24.432-0.487 33.939 9.237 9.504 24.432 9.725 33.937 0.486l191.549-186.134 191.549 186.134z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["order"],"defaultCode":59797,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1069,"name":"order","prevSize":32,"id":157,"code":59797},"setIdx":0,"setId":6,"iconIdx":158},{"icon":{"paths":["M742.317 652.566c12.666-12.323 12.944-32.582 0.618-45.248-12.323-12.669-32.582-12.944-45.251-0.621l44.634 45.869zM512 832.019l-22.317 22.934c12.422 12.086 32.211 12.086 44.634 0l-22.317-22.934zM326.317 606.698c-12.667-12.323-32.927-12.048-45.252 0.621-12.324 12.666-12.047 32.925 0.619 45.248l44.632-45.869zM697.683 606.698l-208 202.387 44.634 45.869 208-202.387-44.634-45.869zM534.317 809.085l-208-202.387-44.632 45.869 207.999 202.387 44.634-45.869z","M742.317 371.456c12.666 12.323 12.944 32.582 0.618 45.251-12.323 12.666-32.582 12.944-45.251 0.618l44.634-45.869zM512 192.004l-22.317-22.935c12.422-12.087 32.211-12.087 44.634 0l-22.317 22.935zM326.317 417.325c-12.668 12.326-32.927 12.048-45.252-0.618-12.325-12.669-12.048-32.928 0.619-45.251l44.633 45.869zM697.683 417.325l-208-202.386 44.634-45.87 208 202.387-44.634 45.869zM534.317 214.939l-208 202.386-44.633-45.869 207.999-202.387 44.634 45.87z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":9}]},"tags":["ordering-ascending"],"defaultCode":59798,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":1070,"name":"ordering-ascending","prevSize":32,"codes":[59798,59799],"id":158,"code":59798},"setIdx":0,"setId":6,"iconIdx":159},{"icon":{"paths":["M281.684 371.434c-12.667 12.323-12.944 32.582-0.619 45.248 12.324 12.669 32.584 12.944 45.252 0.621l-44.633-45.869zM512 191.981l22.317-22.935c-12.422-12.087-32.211-12.087-44.634 0l22.317 22.935zM697.683 417.302c12.669 12.323 32.928 12.048 45.251-0.621 12.326-12.666 12.048-32.925-0.618-45.248l-44.634 45.869zM326.317 417.302l208-202.387-44.634-45.869-207.999 202.387 44.633 45.869zM489.683 214.916l208 202.387 44.634-45.869-208-202.387-44.634 45.869z","M281.684 652.544c-12.667-12.323-12.944-32.582-0.619-45.251 12.324-12.666 32.584-12.944 45.252-0.618l-44.633 45.869zM512 831.997l22.317 22.934c-12.422 12.086-32.211 12.086-44.634 0l22.317-22.934zM697.683 606.675c12.669-12.326 32.928-12.048 45.251 0.618 12.326 12.669 12.048 32.928-0.618 45.251l-44.634-45.869zM326.317 606.675l208 202.384-44.634 45.872-207.999-202.387 44.633-45.869zM489.683 809.059l208-202.384 44.634 45.869-208 202.387-44.634-45.872z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":9}]},"tags":["ordering-descending"],"defaultCode":59800,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":1071,"name":"ordering-descending","prevSize":32,"codes":[59800,59801],"id":159,"code":59800},"setIdx":0,"setId":6,"iconIdx":160},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352-194.405 0-352.001 157.596-352.001 352s157.596 352 352.001 352c194.403 0 352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416-229.752 0-416.001-186.25-416.001-416s186.25-416 416.001-416c229.75 0 416 186.25 416 416zM399.997 383.994v256c0 17.674 14.326 32 32 32s32-14.326 32-32v-256c0-17.67-14.326-32-32-32s-32 14.33-32 32zM559.997 383.994v256c0 17.674 14.326 32 32 32s32-14.326 32-32v-256c0-17.67-14.326-32-32-32s-32 14.33-32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pause"],"defaultCode":59803,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1072,"name":"pause","prevSize":32,"id":160,"code":59803},"setIdx":0,"setId":6,"iconIdx":161},{"icon":{"paths":["M512 928c229.75 0 416-186.25 416-416s-186.25-416-416-416c-229.752 0-416.001 186.25-416.001 416s186.25 416 416.001 416zM399.997 383.994c0-17.67 14.326-32 32-32s32 14.33 32 32v256c0 17.674-14.326 32-32 32s-32-14.326-32-32v-256zM559.997 383.994c0-17.67 14.326-32 32-32s32 14.33 32 32v256c0 17.674-14.326 32-32 32s-32-14.326-32-32v-256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pause-filled"],"defaultCode":59802,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1073,"name":"pause-filled","prevSize":32,"id":161,"code":59802},"setIdx":0,"setId":6,"iconIdx":162},{"icon":{"paths":["M822.627 201.372c12.496 12.497 12.496 32.758 0 45.255l-576 576c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l576-576c12.496-12.497 32.758-12.497 45.254 0z","M192 320c0-70.692 57.308-128 128-128 70.691 0 128 57.308 128 128 0 70.691-57.309 128-128 128-70.692 0-128-57.309-128-128zM320 256c-35.346 0-64 28.654-64 64s28.654 64 64 64c35.347 0 64-28.653 64-64s-28.653-64-64-64z","M704 576c-70.691 0-128 57.309-128 128s57.309 128 128 128c70.691 0 128-57.309 128-128s-57.309-128-128-128zM640 704c0-35.347 28.653-64 64-64s64 28.653 64 64c0 35.347-28.653 64-64 64s-64-28.653-64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["percentage"],"defaultCode":59777,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1074,"id":162,"name":"percentage","prevSize":32,"code":59777},"setIdx":0,"setId":6,"iconIdx":163},{"icon":{"paths":["M410.502 204.616c-10.419-21.362-34.202-37.856-62.189-33.137-38.104 6.425-88.825 25.194-126.247 57.060-18.972 16.155-35.817 36.795-44.757 62.246-9.15 26.048-9.211 54.919 2.087 85.195 21.202 56.816 60.513 117.456 97.761 167.264 37.482 50.122 74.609 91.552 93.329 110.269l44.173-44.173c-16.406-16.403-51.6-55.536-87.472-103.51-36.11-48.285-71.192-103.264-89.264-151.69-6.437-17.248-5.748-31.056-1.675-42.651 4.283-12.192 13.134-24.16 26.319-35.388 25.849-22.012 63.292-36.814 92.623-42.392l59.075 121.097c0.019 0.074 0.045 0.285-0.013 0.688-0.112 0.749-0.502 1.827-1.344 2.883-7.117 8.95-14.899 20-20.941 31.741-5.674 11.024-11.715 26.246-10.976 42.47 0.643 14.138 7.76 27.773 13.222 36.973 6.275 10.576 14.416 21.741 22.79 32.291 16.806 21.171 36.541 42.326 49.68 55.466l44.173-44.173c-11.952-11.952-29.981-31.309-44.928-50.134-7.504-9.453-13.738-18.157-17.997-25.334-2.87-4.838-3.984-7.578-4.387-8.57l-0.038-0.093c0.266-1.382 1.139-4.736 4.006-10.31 3.552-6.902 8.717-14.438 14.291-21.443 14.611-18.374 20.518-45.424 8.611-69.837l-59.914-122.808zM819.386 613.504c21.36 10.419 37.856 34.202 33.136 62.189-6.426 38.106-25.194 88.826-57.059 126.246-16.157 18.973-36.797 35.818-62.246 44.758-26.048 9.149-54.922 9.21-85.197-2.086-56.813-21.203-117.453-60.515-167.261-97.763-50.122-37.482-91.555-74.608-110.272-93.328l44.173-44.173c16.403 16.406 55.539 51.6 103.51 87.472 48.285 36.109 103.267 71.194 151.69 89.264 17.248 6.435 31.056 5.747 42.653 1.674 12.192-4.282 24.16-13.133 35.386-26.317 22.013-25.85 36.816-63.293 42.394-92.624l-121.094-59.075c-0.077-0.019-0.288-0.048-0.688 0.013-0.752 0.112-1.83 0.502-2.886 1.344-8.95 7.117-20 14.899-31.741 20.941-11.024 5.674-26.246 11.715-42.47 10.976-14.134-0.643-27.773-7.76-36.973-13.222-10.576-6.275-21.741-14.416-32.288-22.79-21.174-16.806-42.33-36.541-55.469-49.68l44.173-44.173c11.952 11.952 31.309 29.981 50.134 44.928 9.453 7.504 18.16 13.738 25.334 17.997 4.838 2.87 7.578 3.984 8.57 4.387l0.093 0.038c1.382-0.266 4.739-1.139 10.314-4.006 6.899-3.552 14.435-8.717 21.44-14.291 18.374-14.611 45.427-20.518 69.837-8.611l122.81 59.914z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone"],"defaultCode":59806,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1075,"name":"phone","prevSize":32,"id":163,"code":59806},"setIdx":0,"setId":6,"iconIdx":164},{"icon":{"paths":["M825.373 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672-672zM575.613 569.069l-44.707 44.707c7.846 5.904 15.846 11.453 23.533 16.016 9.2 5.459 22.838 12.579 36.973 13.222 16.224 0.736 31.446-5.302 42.47-10.976 11.741-6.042 22.79-13.824 31.744-20.944 1.053-0.838 2.134-1.232 2.883-1.341 0.403-0.061 0.611-0.032 0.688-0.013l121.094 59.075c-5.578 29.331-20.381 66.771-42.39 92.621-11.229 13.187-23.197 22.038-35.389 26.32-11.597 4.074-25.402 4.762-42.653-1.677-48.422-18.070-103.405-53.152-151.69-89.261-14.026-10.49-27.299-20.922-39.469-30.842l-44.387 44.39c14.186 11.683 29.84 24.061 46.445 36.48 49.808 37.248 110.448 76.56 167.261 97.76 30.275 11.299 59.149 11.238 85.197 2.086 25.45-8.938 46.090-25.786 62.246-44.755 31.866-37.424 50.634-88.144 57.059-126.246 4.72-27.987-11.776-51.77-33.136-62.192l-122.81-59.91c-24.41-11.907-51.462-6-69.834 8.611-7.008 5.571-14.544 10.739-21.443 14.291-5.574 2.867-8.931 3.741-10.314 4.003l-0.093-0.038c-0.992-0.4-3.731-1.514-8.57-4.387-3.277-1.942-6.87-4.301-10.71-7.002zM313.636 589.683l44.389-44.387c-9.92-12.17-20.349-25.44-30.838-39.466-36.109-48.285-71.192-103.267-89.263-151.69-6.437-17.251-5.748-31.056-1.675-42.652 4.283-12.192 13.134-24.16 26.319-35.388 25.849-22.012 63.291-36.814 92.622-42.392l59.075 121.095c0.019 0.077 0.048 0.285-0.013 0.688-0.109 0.752-0.502 1.83-1.341 2.883-7.12 8.954-14.902 20.003-20.944 31.744-5.674 11.024-11.715 26.246-10.976 42.47 0.643 14.134 7.763 27.773 13.222 36.973 4.563 7.686 10.109 15.683 16.013 23.53l44.707-44.707c-2.701-3.837-5.056-7.434-7.002-10.707-2.87-4.838-3.984-7.578-4.387-8.57l-0.038-0.093c0.266-1.382 1.139-4.739 4.006-10.314 3.552-6.899 8.72-14.435 14.291-21.443 14.611-18.371 20.518-45.424 8.611-69.834l-59.91-122.809c-10.422-21.362-34.205-37.856-62.192-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.757 62.246-9.15 26.048-9.211 54.921 2.087 85.196 21.202 56.813 60.513 117.453 97.761 167.261 12.417 16.605 24.795 32.256 36.478 46.442z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone-disabled"],"defaultCode":59804,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1076,"name":"phone-disabled","prevSize":32,"id":164,"code":59804},"setIdx":0,"setId":6,"iconIdx":165},{"icon":{"paths":["M801.123 657.59c22.474 7.734 50.954 2.582 67.408-20.544 22.4-31.488 44.992-80.624 48.922-129.619 1.99-24.838-0.691-51.344-12.368-75.661-11.949-24.89-32.32-45.35-61.718-58.768-55.165-25.181-125.84-40.262-187.398-49.146-61.946-8.936-117.494-11.98-143.965-11.98v62.469c23.2 0 75.757 2.787 135.043 11.341 59.677 8.611 123.36 22.682 170.381 44.144 16.749 7.645 26.022 17.894 31.344 28.973 5.59 11.651 7.795 26.371 6.413 43.635-2.717 33.843-18.723 70.784-35.52 95.469l-127.398-43.853c-0.067-0.042-0.237-0.17-0.48-0.496-0.451-0.608-0.934-1.651-1.088-2.989-1.296-11.363-3.606-24.678-7.635-37.254-3.786-11.808-10.278-26.842-22.272-37.792-10.451-9.539-25.126-14.15-35.494-16.794-11.914-3.040-25.568-5.181-38.944-6.717-26.858-3.088-55.773-4.093-74.352-4.093v62.47c16.902 0 43.338 0.938 67.219 3.683 11.99 1.379 22.554 3.123 30.64 5.187 5.45 1.389 8.173 2.541 9.162 2.957l0.093 0.038c0.79 1.165 2.544 4.154 4.458 10.125 2.368 7.392 4.045 16.374 5.059 25.267 2.659 23.325 17.61 46.63 43.29 55.469l129.203 44.477zM222.875 657.584c-22.474 7.738-50.954 2.586-67.407-20.544-22.4-31.485-44.993-80.621-48.922-129.616-1.992-24.838 0.691-51.344 12.366-75.664 11.949-24.886 32.321-45.347 61.719-58.765 55.165-25.181 125.841-40.262 187.4-49.146 61.946-8.937 117.494-11.98 143.965-11.98v62.47c-23.2 0-75.757 2.787-135.046 11.341-59.674 8.608-123.358 22.682-170.378 44.144-16.748 7.645-26.024 17.894-31.343 28.973-5.593 11.651-7.797 26.371-6.412 43.635 2.714 33.843 18.721 70.784 35.518 95.469l127.4-43.856c0.067-0.038 0.234-0.166 0.477-0.493 0.454-0.611 0.938-1.651 1.091-2.989 1.296-11.363 3.606-24.682 7.635-37.254 3.786-11.808 10.275-26.842 22.272-37.792 10.448-9.542 25.126-14.15 35.491-16.794 11.917-3.040 25.568-5.181 38.947-6.717 26.858-3.088 55.77-4.093 74.349-4.093v62.47c-16.899 0-43.338 0.938-67.216 3.683-11.99 1.376-22.554 3.123-30.64 5.187-5.453 1.389-8.176 2.541-9.162 2.957l-0.093 0.038c-0.79 1.162-2.547 4.154-4.458 10.125-2.371 7.389-4.045 16.371-5.059 25.267-2.659 23.322-17.61 46.627-43.293 55.469l-129.202 44.474z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone-end"],"defaultCode":59805,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1077,"name":"phone-end","prevSize":32,"id":165,"code":59805},"setIdx":0,"setId":6,"iconIdx":166},{"icon":{"paths":["M717.254 352l137.37-137.372c12.499-12.497 12.499-32.758 0-45.255-12.496-12.497-32.755-12.497-45.254 0l-137.373 137.373v-82.745c0-17.673-14.326-32-32-32-17.67 0-32 14.327-32 32v160c0 4.339 0.864 8.477 2.429 12.25 1.526 3.686 3.773 7.149 6.736 10.166 0.138 0.141 0.278 0.282 0.419 0.419 3.018 2.966 6.48 5.21 10.17 6.736 3.773 1.565 7.91 2.429 12.246 2.429h160c17.674 0 32-14.326 32-32s-14.326-32-32-32h-82.742z","M819.478 613.379l-122.88-59.84c-11.261-5.29-23.786-7.283-36.128-5.757-12.346 1.53-24.003 6.522-33.632 14.397-6.816 5.274-13.978 10.086-21.44 14.4-3.382 1.632-6.922 2.918-10.56 3.84-3.008-1.235-5.901-2.736-8.64-4.48-8.752-5.504-17.19-11.488-25.28-17.92-18.88-15.040-38.080-32-50.24-44.8s-29.76-32-44.8-50.24c-6.435-8.093-12.416-16.531-17.92-25.28-1.747-2.742-3.248-5.635-4.48-8.64 0.918-3.642 2.205-7.181 3.84-10.56 4.314-7.462 9.123-14.627 14.4-21.44 7.875-9.629 12.864-21.29 14.394-33.635 1.53-12.342-0.467-24.867-5.754-36.125l-59.84-122.881c-5.635-11.286-14.73-20.477-25.952-26.234-11.226-5.756-23.997-7.776-36.448-5.766-46.072 7.753-89.44 27.015-126.081 56-20.379 16.952-35.847 39.050-44.8 64-9.479 27.726-8.684 57.931 2.24 85.121 25.032 59.536 57.851 115.491 97.6 166.4 28.686 38.71 59.902 75.485 93.441 110.080 34.406 33.296 70.966 64.298 109.44 92.8 51.203 39.821 107.485 72.643 167.36 97.6 27.158 11.066 57.418 11.862 85.12 2.24 24.368-9.203 45.888-24.653 62.4-44.8 29.328-36.544 48.925-79.92 56.96-126.080 1.984-12.49-0.083-25.286-5.901-36.515-5.814-11.229-15.075-20.301-26.419-25.885zM747.798 761.219c-9.187 11.802-21.331 20.963-35.2 26.56-14.051 4.416-29.197 3.85-42.88-1.6-54.202-23.091-105.187-53.101-151.68-89.28-35.83-27.52-69.923-57.232-102.080-88.96-31.334-32.611-60.618-67.13-87.68-103.36-36.201-46.426-66.113-97.427-88.961-151.68-5.832-13.587-6.514-28.829-1.92-42.881 5.595-13.87 14.757-26.014 26.56-35.2 26.691-20.806 57.953-34.956 91.201-41.28l60.8 121.281c0.154 0.954 0.154 1.926 0 2.88-7.933 9.981-14.899 20.698-20.8 32-7.347 12.966-11.101 27.658-10.88 42.56 1.354 13.142 5.853 25.763 13.12 36.8 6.934 11.104 14.522 21.789 22.72 32 16.96 21.12 36.48 42.56 49.6 55.68s34.56 32 55.68 49.6c10.208 8.198 20.893 15.782 32 22.72 11.034 7.264 23.658 11.763 36.8 13.12 14.899 0.218 29.59-3.536 42.56-10.88 11.302-5.904 22.016-12.867 32-20.8 0.851-0.707 1.827-1.251 2.88-1.6l118.72 59.84c-6.509 33.811-21.11 65.542-42.56 92.48z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["phone-in"],"grid":0},"attrs":[{},{}],"properties":{"order":1078,"id":166,"name":"phone-in","prevSize":32,"code":59809},"setIdx":0,"setId":6,"iconIdx":167},{"icon":{"paths":["M649.373 137.372c12.496-12.497 32.758-12.497 45.254 0l73.373 73.373 73.373-73.373c12.499-12.497 32.758-12.497 45.254 0 12.499 12.497 12.499 32.758 0 45.255l-73.373 73.372 73.373 73.373c12.499 12.496 12.499 32.758 0 45.254-12.496 12.496-32.755 12.496-45.254 0l-73.373-73.372-73.373 73.372c-12.496 12.496-32.755 12.496-45.254 0-12.496-12.496-12.496-32.758 0-45.254l73.373-73.373-73.373-73.372c-12.496-12.497-12.496-32.758 0-45.255zM361.062 167.708c28.672-4.835 53.037 12.064 63.712 33.949l61.379 125.818c12.202 25.008 6.147 52.72-8.822 71.546-5.706 7.178-11.002 14.899-14.64 21.968-2.938 5.712-3.834 9.149-4.102 10.563 0.378 0.928 1.494 3.754 4.534 8.877 4.362 7.35 10.749 16.269 18.438 25.952 15.312 19.29 33.782 39.12 46.026 51.363s32.077 30.717 51.363 46.029c9.683 7.69 18.602 14.077 25.955 18.442 5.12 3.040 7.946 4.154 8.874 4.534 1.414-0.272 4.854-1.165 10.563-4.106 7.069-3.638 14.79-8.931 21.968-14.64 18.822-14.97 46.538-21.021 71.546-8.822l125.818 61.379c21.885 10.678 38.784 35.040 33.949 63.715-6.582 39.037-25.811 90.998-58.458 129.338-16.55 19.437-37.696 36.694-63.773 45.856-26.685 9.373-56.266 9.437-87.283-2.141-58.205-21.722-120.33-61.997-171.36-100.16-51.347-38.4-93.795-76.438-112.973-95.616s-57.213-61.622-95.613-112.973c-38.16-51.027-78.435-113.152-100.156-171.357-11.575-31.018-11.513-60.598-2.138-87.284 9.159-26.075 26.417-47.22 45.854-63.771 38.339-32.647 90.303-51.876 129.34-58.458zM368.106 231.463c-30.048 5.715-68.407 20.88-94.89 43.431-13.508 11.503-22.577 23.764-26.964 36.255-4.173 11.878-4.878 26.025 1.716 43.696 18.514 49.61 54.456 105.939 91.45 155.408 36.752 49.146 72.806 89.238 89.613 106.045 16.81 16.81 56.902 52.864 106.048 89.619 49.469 36.995 105.798 72.938 155.408 91.453 17.67 6.592 31.818 5.888 43.696 1.715 12.49-4.387 24.752-13.456 36.256-26.963 22.55-26.483 37.715-64.842 43.43-94.893l-124.064-60.522c-0.077-0.019-0.291-0.048-0.704 0.013-0.768 0.112-1.875 0.515-2.954 1.376-9.171 7.293-20.493 15.264-32.518 21.456-11.296 5.811-26.89 12-43.514 11.245-14.483-0.659-28.454-7.955-37.878-13.549-10.835-6.432-22.275-14.771-33.082-23.35-21.69-17.222-43.363-37.44-56.822-50.899s-33.677-35.133-50.896-56.826c-8.579-10.803-16.918-22.246-23.35-33.078-5.594-9.427-12.886-23.398-13.546-37.878-0.755-16.624 5.434-32.218 11.245-43.514 6.189-12.026 14.163-23.347 21.456-32.518 0.858-1.078 1.261-2.186 1.376-2.954 0.061-0.413 0.032-0.627 0.013-0.704l-60.525-124.063z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["phone-issue"],"grid":0},"attrs":[{}],"properties":{"order":1079,"id":167,"name":"phone-issue","prevSize":32,"code":59835},"setIdx":0,"setId":6,"iconIdx":168},{"icon":{"paths":["M428.346 199.399c17.542-17.543 45.984-17.543 63.53 0 17.542 17.543 17.542 45.986 0 63.53l-43.661 43.659 177.83 177.828 60.339-60.339c24.992-24.995 65.517-24.995 90.509 0l45.254 45.254-331.869 331.869-45.254-45.254c-24.992-24.995-24.992-65.517 0-90.509l60.339-60.339-177.827-177.83-43.661 43.661c-17.543 17.542-45.987 17.542-63.53 0s-17.543-45.987 0-63.53l208.001-207.999zM175.090 362.144c-42.537 42.538-42.537 111.501 0 154.038 42.001 42.003 109.771 42.531 152.42 1.587l87.334 87.334-15.075 15.075c-49.987 49.987-49.987 131.034 0 181.021l67.882 67.882c12.496 12.496 32.758 12.496 45.254 0l167.936-167.933 88.013 92.003c12.218 12.771 32.474 13.219 45.245 1.002 12.771-12.214 13.219-32.47 1.002-45.242l-88.995-93.030 163.923-163.923c12.499-12.496 12.499-32.758 0-45.254l-67.882-67.882c-49.987-49.987-131.030-49.987-181.018 0l-15.907 15.907-87.325-87.323c41.766-42.596 41.51-110.983-0.768-153.262-42.538-42.537-111.504-42.537-154.042 0l-207.998 208z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pin"],"defaultCode":59808,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1080,"name":"pin","prevSize":32,"id":168,"code":59808},"setIdx":0,"setId":6,"iconIdx":169},{"icon":{"paths":["M512.608 128.019c-72.378-1.376-144.906 25.78-199.307 80.524-54.654 54.999-89.301 136.056-89.301 239.464 0 80.234 44.5 174.87 97.546 252.806 53.066 77.965 120.829 148.157 176.141 175.821l15.194 7.6 14.81-8.326c217.158-122.154 272.31-333.882 272.31-427.898 0-101.731-27.923-181.776-80.179-236.932-52.346-55.248-125.296-81.503-207.213-83.060zM288 448.006c0-88.589 29.353-152.745 70.698-194.351 41.6-41.862 97.072-62.705 152.694-61.648 68.992 1.311 124.038 23.054 161.968 63.088 38.019 40.126 62.64 102.649 62.64 192.914 0 74.55-44.691 253.677-224.176 363.030-39.683-25.61-92.186-79.853-137.37-146.237-50.954-74.864-86.454-156.221-86.454-216.797zM544 416c0-17.674-14.326-32-32-32s-32 14.326-32 32c0 17.674 14.326 32 32 32s32-14.326 32-32zM608 416c0 53.021-42.979 96-96 96s-96-42.979-96-96c0-53.021 42.979-96 96-96s96 42.979 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pin-map"],"defaultCode":59807,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1081,"name":"pin-map","prevSize":32,"id":169,"code":59807},"setIdx":0,"setId":6,"iconIdx":170},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM451.85 357.187l195.254 136.768c14.208 9.949 18.496 30.87 9.581 46.726-2.432 4.326-5.706 7.981-9.581 10.694l-195.254 136.768c-14.208 9.952-32.954 5.165-41.869-10.694-3.037-5.398-4.646-11.642-4.646-18.016v-273.536c0-18.723 13.597-33.898 30.371-33.898 5.709 0 11.306 1.798 16.144 5.187z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["play"],"defaultCode":59811,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1082,"name":"play","prevSize":32,"id":170,"code":59811},"setIdx":0,"setId":6,"iconIdx":171},{"icon":{"paths":["M512 928.003c229.75 0 416-186.25 416-416s-186.25-415.999-416-415.999c-229.75 0-416 186.25-416 415.999s186.25 416 416 416zM451.846 357.19l195.258 136.768c14.205 9.952 18.496 30.874 9.578 46.73-2.429 4.323-5.706 7.978-9.578 10.691l-195.258 136.768c-14.205 9.952-32.95 5.165-41.866-10.691-3.037-5.398-4.646-11.645-4.646-18.019v-273.536c0-18.72 13.597-33.894 30.368-33.894 5.712 0 11.309 1.795 16.144 5.184z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["play-filled"],"defaultCode":59810,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1083,"name":"play-filled","prevSize":32,"id":171,"code":59810},"setIdx":0,"setId":6,"iconIdx":172},{"icon":{"paths":["M325.686 430.88l224.49 224.49-126.118 126.118-224.491-224.49 126.12-126.118zM370.941 385.626l192.115-192.117 224.49 224.491-192.115 192.115-224.49-224.49zM585.683 125.627c-12.496-12.497-32.758-12.497-45.254 0l-408.745 408.745c-12.497 12.496-12.497 32.758 0 45.254l269.746 269.747c5.229 5.229 11.818 8.269 18.63 9.123v0.067h0.57c2.278 0.243 4.576 0.243 6.851 0h440.579c17.674 0 32-14.33 32-32 0-17.674-14.326-32.003-32-32.003h-366.566l353.936-353.933c12.496-12.496 12.496-32.758 0-45.254l-269.747-269.746z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["prune"],"defaultCode":59817,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1084,"name":"prune","prevSize":32,"id":172,"code":59817},"setIdx":0,"setId":6,"iconIdx":173},{"icon":{"paths":["M230.486 636.688c-14.92-9.472-34.694-5.056-44.167 9.862-9.473 14.922-5.057 34.694 9.862 44.166l298.666 189.632c10.47 6.646 23.837 6.646 34.304 0l298.669-189.632c14.918-9.472 19.334-29.245 9.862-44.166-9.475-14.918-29.248-19.334-44.166-9.862l-281.517 178.739-281.514-178.739zM186.319 494.848c9.473-14.922 29.247-19.334 44.167-9.862l281.514 178.739 281.517-178.739c14.918-9.472 34.691-5.059 44.166 9.862 9.472 14.918 5.056 34.694-9.862 44.166l-298.669 189.632c-10.467 6.646-23.834 6.646-34.304 0l-298.666-189.632c-14.92-9.472-19.335-29.248-9.862-44.166zM529.152 143.657l298.669 189.629c9.245 5.872 14.848 16.064 14.848 27.014 0 10.954-5.603 21.146-14.848 27.014l-298.669 189.632c-10.467 6.646-23.834 6.646-34.304 0l-298.666-189.632c-9.246-5.869-14.848-16.061-14.848-27.014 0-10.95 5.602-21.142 14.848-27.014l298.666-189.629c10.47-6.647 23.837-6.647 34.304 0zM273.035 360.301l238.965 151.725 238.966-151.725-238.966-151.724-238.965 151.724z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["queue"],"defaultCode":59818,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1085,"name":"queue","prevSize":32,"id":173,"code":59818},"setIdx":0,"setId":6,"iconIdx":174},{"icon":{"paths":["M161.352 800c-11.706 0-22.477-6.39-28.087-16.666s-5.161-22.79 1.169-32.64l112.304-174.694h-69.387c-17.673 0-32-14.326-32-32v-288c0-17.673 14.327-32 32-32h255.999c17.674 0 32 14.327 32 32v288c0 6.138-1.763 12.144-5.082 17.306l-143.999 224c-5.888 9.158-16.029 14.694-26.918 14.694h-128zM332.269 561.306l-112.304 174.694h51.916l129.469-201.398v-246.602h-191.999v224h96c11.706 0 22.479 6.39 28.085 16.666 5.61 10.275 5.162 22.79-1.168 32.64zM577.35 800c-11.706 0-22.477-6.39-28.086-16.666s-5.162-22.79 1.171-32.64l112.304-174.694h-69.389c-17.67 0-32-14.326-32-32v-288c0-17.673 14.33-32 32-32h256c17.674 0 32 14.327 32 32v288c0 6.138-1.763 12.144-5.082 17.306l-144 224c-5.888 9.158-16.029 14.694-26.918 14.694h-128zM748.269 561.306l-112.304 174.694h51.917l129.469-201.398v-246.602h-192v224h96c11.706 0 22.48 6.39 28.086 16.666 5.61 10.275 5.162 22.79-1.168 32.64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["quote"],"defaultCode":59819,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1086,"name":"quote","prevSize":32,"id":174,"code":59819},"setIdx":0,"setId":6,"iconIdx":175},{"icon":{"paths":["M800 560c0 176.73-143.27 320-320 320-176.731 0-320-143.27-320-320s143.269-320 320-320v-64c-212.077 0-384 171.923-384 384s171.923 384 384 384c212.077 0 384-171.923 384-384 0-10.778-0.445-21.45-1.315-32h-64.266c1.046 10.525 1.581 21.2 1.581 32zM800 128c0-17.673-14.326-32-32-32s-32 14.327-32 32v112h-112c-17.674 0-32 14.327-32 32s14.326 32 32 32h112v112c0 17.674 14.326 32 32 32s32-14.326 32-32v-112h112c17.674 0 32-14.327 32-32s-14.326-32-32-32h-112v-112zM384 528c35.347 0 64-28.653 64-64s-28.653-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64zM640 464c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64zM329.805 605.075c-10.451-14.25-30.477-17.331-44.728-6.88s-17.333 30.477-6.882 44.73c37.658 51.35 77.754 84.624 119.178 102.662 41.741 18.179 82.797 19.99 120.362 11.651 73.469-16.307 132.211-70.87 164.070-114.314 10.451-14.253 7.37-34.278-6.88-44.73-14.253-10.451-34.278-7.37-44.73 6.88-26.81 36.557-73.664 77.994-126.33 89.686-25.501 5.661-52.643 4.474-80.938-7.85-28.608-12.461-60.381-37.187-93.123-81.837z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["reaction-add"],"defaultCode":59820,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1087,"name":"reaction-add","prevSize":32,"id":175,"code":59820},"setIdx":0,"setId":6,"iconIdx":176},{"icon":{"paths":["M832 512c0-176.73-143.27-320-320-320s-320 143.27-320 320c0 176.73 143.27 320 320 320s320-143.27 320-320zM896 512c0 212.077-171.923 384-384 384s-384-171.923-384-384c0-212.077 171.923-384 384-384s384 171.923 384 384zM512 704c-106.038 0-192-85.962-192-192s85.962-192 192-192c106.038 0 192 85.962 192 192s-85.962 192-192 192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["record"],"defaultCode":59821,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1088,"name":"record","prevSize":32,"id":176,"code":59821},"setIdx":0,"setId":6,"iconIdx":177},{"icon":{"paths":["M896 512h-63.984c0-175.414-145.754-320-328.518-320-115.27 0-215.818 57.513-274.362 144h110.768c17.674 0 32 14.326 32 32s-14.326 32-32 32h-179.904c-17.673 0-32-14.326-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v102.32c71.751-91.401 184.589-150.32 311.498-150.32 216.781 0 392.502 171.923 392.502 384 0 1.114 0.010 2.227 0 3.338v-3.338z","M127.997 512h63.986c0 175.414 145.751 320 328.519 320 115.27 0 215.818-57.514 274.358-144h-110.768c-17.67 0-32-14.326-32-32s14.33-32 32-32h179.907c17.67 0 32 14.326 32 32v192c0 17.674-14.33 32-32 32-17.674 0-32-14.326-32-32v-102.32c-71.754 91.402-184.592 150.32-311.498 150.32-216.782 0-392.505-171.923-392.505-384 0-1.082-0.009-2.166 0-3.245v3.245z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["refresh"],"defaultCode":59822,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1089,"name":"refresh","prevSize":32,"id":177,"code":59822},"setIdx":0,"setId":6,"iconIdx":178},{"icon":{"paths":["M565.802 233.862l-97.261 97.261h-187.521l-0.456 0.003c-14.696 0.208-28.717 6.186-39.042 16.637l-97.095 96.797-0.048 0.048c-7.165 7.174-12.248 16.157-14.707 25.994-2.459 9.834-2.202 20.154 0.745 29.856 2.946 9.699 8.471 18.419 15.984 25.226 7.506 6.8 16.746 11.443 26.678 13.424l125.65 25.19c5.103 1.024 10.166 0.771 14.859-0.538l162.866 162.867c1.987 1.987 4.17 3.654 6.483 5.011l22.88 114.128c1.981 9.936 6.618 19.146 13.418 26.653 6.81 7.514 15.526 13.037 25.229 15.984s20.019 3.203 29.856 0.746c9.837-2.461 18.819-7.542 25.994-14.707l96.842-97.146c10.451-10.323 16.432-24.346 16.64-39.040l0.003-0.454v-193.802c0-2.893-0.384-5.693-1.104-8.358l77.443-77.44c110.522-110.525 110.474-223.191 103.152-273.759-1.862-13.592-8.122-26.204-17.824-35.908s-22.317-15.962-35.907-17.823c-50.57-7.321-163.235-7.371-273.757 103.151zM611.056 279.117c92.138-92.138 182.144-90.373 218.947-85.121 5.254 36.804 7.018 126.811-85.12 218.948l-245.798 245.802-133.83-133.827 245.802-245.802zM404.541 395.123l-104.222 104.221-100.071-20.064 84.42-84.157h119.873zM542.89 705.446l106.909-106.906v135.61l-84.16 84.422-22.266-111.062c-0.138-0.698-0.301-1.386-0.483-2.064z","M286.325 699.699c15.297-8.851 20.524-28.426 11.674-43.725-8.85-15.296-28.426-20.522-43.723-11.674-49.486 28.63-72.438 77.786-83.25 115.523-5.52 19.267-8.252 36.813-9.619 49.539-0.687 6.397-1.037 11.661-1.217 15.424-0.090 1.885-0.137 3.402-0.162 4.499l-0.023 1.334-0.004 0.422-0.001 0.15v0.083c0 8.486 3.372 16.65 9.372 22.65 6.001 6.003 14.14 9.373 22.628 9.373v-32c0 32 0.037 32 0.048 32h0.208l0.424-0.003 1.333-0.022c1.099-0.026 2.614-0.074 4.498-0.163 3.764-0.179 9.029-0.528 15.425-1.216 12.727-1.366 30.272-4.099 49.54-9.619 37.739-10.813 86.892-33.763 115.523-83.251 8.851-15.296 3.622-34.87-11.674-43.722s-34.874-3.626-43.725 11.674c-16.669 28.813-47.164 45.011-77.751 53.776-6.095 1.744-12.005 3.139-17.55 4.25 1.111-5.546 2.505-11.456 4.251-17.549 8.763-30.589 24.961-61.085 53.775-77.754zM192 831.299l-32-0.022c0 0.013 0 0.022 32 0.022z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["rocket"],"defaultCode":59816,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1090,"id":178,"name":"rocket","prevSize":32,"code":59816},"setIdx":0,"setId":6,"iconIdx":179},{"icon":{"paths":["M713.718 450.362c0-142.689-115.824-258.362-258.701-258.362-142.878 0-258.704 115.673-258.704 258.362 0 142.691 115.826 258.365 258.704 258.365 142.877 0 258.701-115.674 258.701-258.365zM659.302 699.965c-55.645 45.475-126.774 72.762-204.285 72.762-178.271 0-322.788-144.326-322.788-322.365 0-178.035 144.517-322.362 322.788-322.362 178.269 0 322.787 144.327 322.787 322.362 0 77.408-27.318 148.442-72.854 204.013l186.838 186.592c12.608 12.589 12.608 33.002 0 45.59-12.605 12.589-33.043 12.589-45.648 0l-186.838-186.592z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["search"],"defaultCode":59823,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1091,"name":"search","prevSize":32,"id":179,"code":59823},"setIdx":0,"setId":6,"iconIdx":180},{"icon":{"paths":["M878.022 192.974c7.85 9.521 9.526 22.708 4.31 33.891l-298.669 640.002c-5.69 12.195-18.403 19.526-31.811 18.342-13.405-1.184-24.637-10.627-28.106-23.632l-81.619-306.070-285.772-142.886c-11.978-5.987-18.959-18.8-17.498-32.112s11.056-24.307 24.048-27.552l682.665-170.668c11.974-2.993 24.598 1.165 32.451 10.686zM505.821 545.968l57.082 214.051 233.027-499.35-533.58 133.395 203.606 101.802 69.51-52.131c14.141-10.605 34.198-7.741 44.8 6.4 10.605 14.138 7.741 34.195-6.4 44.8l-68.045 51.034z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["send"],"defaultCode":59825,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1092,"name":"send","prevSize":32,"id":180,"code":59825},"setIdx":0,"setId":6,"iconIdx":181},{"icon":{"paths":["M891.494 238.96l-297.475 637.446c-16.854 36.115-69.622 31.459-79.891-7.050l-66-247.498 151.248-189.059-219.994 109.997-226.833-113.418c-35.43-17.715-29.696-69.949 8.733-79.555l681.197-170.3c34.842-8.71 64.202 26.892 49.014 59.436z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["send-filled"],"defaultCode":59824,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1093,"name":"send-filled","prevSize":32,"id":181,"code":59824},"setIdx":0,"setId":6,"iconIdx":182},{"icon":{"paths":["M421.334 256c0-44.183-35.818-80-80-80s-80 35.817-80 80c0 44.183 35.817 80 80 80s80-35.817 80-80zM465.302 288c-14.211 55.206-64.326 96-123.968 96-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.327-32-32s14.327-32 32-32h89.367c14.209-55.207 64.324-96 123.968-96 59.642 0 109.757 40.793 123.968 96h430.698c17.674 0 32 14.327 32 32s-14.326 32-32 32h-430.698zM96 768c0-17.674 14.327-32 32-32h89.367c14.209-55.206 64.324-96 123.968-96 60.781 0 111.67 42.365 124.742 99.181 4.208-2.038 8.934-3.181 13.923-3.181h416c17.674 0 32 14.326 32 32s-14.326 32-32 32h-416c-4.989 0-9.715-1.142-13.923-3.181-13.072 56.816-63.962 99.181-124.742 99.181-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.326-32-32zM341.334 848c44.182 0 80-35.818 80-80s-35.818-80-80-80c-44.183 0-80 35.818-80 80s35.817 80 80 80zM796.029 543.757c-14.122 55.331-64.298 96.243-124.029 96.243s-109.904-40.912-124.029-96.243c-1.302 0.16-2.627 0.243-3.971 0.243h-416c-17.673 0-32-14.326-32-32s14.327-32 32-32h416c1.344 0 2.669 0.083 3.971 0.243 14.125-55.331 64.298-96.243 124.029-96.243s109.907 40.912 124.029 96.243c1.302-0.16 2.627-0.243 3.971-0.243h96c17.674 0 32 14.326 32 32s-14.326 32-32 32h-96c-1.344 0-2.669-0.083-3.971-0.243zM752 512c0-44.182-35.818-80-80-80s-80 35.818-80 80c0 44.182 35.818 80 80 80s80-35.818 80-80z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["settings"],"defaultCode":59826,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1094,"name":"settings","prevSize":32,"id":182,"code":59826},"setIdx":0,"setId":6,"iconIdx":183},{"icon":{"paths":["M690.176 301.708c11.645-11.977 11.645-31.396 0-43.374l-149.091-153.351c-11.645-11.977-30.525-11.977-42.17 0l-149.091 153.351c-11.645 11.977-11.645 31.397 0 43.374s30.525 11.978 42.17 0l98.189-100.993v401.343c0 16.938 13.35 30.669 29.818 30.669s29.818-13.731 29.818-30.669v-401.343l98.189 100.993c11.645 11.978 30.525 11.978 42.17 0z","M221.818 379.274h149.091v59.635h-119.272v387.635h536.728v-387.635h-119.274v-59.635h149.091c16.467 0 29.818 13.35 29.818 29.818v447.274c0 16.467-13.35 29.818-29.818 29.818h-596.364c-16.468 0-29.818-13.35-29.818-29.818v-447.274c0-16.467 13.35-29.818 29.818-29.818z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["share"],"defaultCode":59827,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1095,"name":"share","prevSize":32,"id":183,"code":59827},"setIdx":0,"setId":6,"iconIdx":184},{"icon":{"paths":["M502.627 142.69c12.915-3.408 26.509-3.289 39.363 0.345l245.194 69.317c29.165 8.245 51.254 33.818 53.504 65.14 24.506 341.145-184.394 520.422-272.611 580.214-33.053 22.403-75.28 22.474-108.416 0.259-88.758-59.504-300.1-238.589-276.51-579.794 2.205-31.89 24.96-57.772 54.753-65.633l264.724-69.849zM524.579 204.621c-1.837-0.519-3.779-0.536-5.622-0.049l-264.725 69.849c-4.4 1.161-6.999 4.775-7.233 8.165-21.305 308.166 168.214 468.531 248.301 522.218 11.507 7.715 25.434 7.677 36.87-0.077 79.379-53.798 266.835-214.288 244.685-522.649-0.243-3.358-2.787-6.925-7.082-8.139l-245.194-69.317z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["set-as-moderator"],"defaultCode":59661,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1096,"name":"shield","prevSize":32,"id":184,"code":59661},"setIdx":0,"setId":6,"iconIdx":185},{"icon":{"paths":["M513.302 142.705c12.915-3.408 26.509-3.289 39.36 0.345l245.197 69.318c29.165 8.245 51.254 33.818 53.504 65.14 24.506 341.142-184.397 520.422-272.611 580.214-33.053 22.403-75.28 22.47-108.416 0.259-88.762-59.504-300.101-238.589-276.511-579.794 2.205-31.89 24.96-57.772 54.753-65.633l264.725-69.849zM535.251 204.637c-1.834-0.519-3.776-0.536-5.622-0.050l-264.723 69.849c-4.4 1.161-6.999 4.775-7.234 8.164-21.305 308.164 168.216 468.532 248.299 522.218 11.507 7.715 25.434 7.677 36.874-0.077 79.379-53.798 266.832-214.288 244.682-522.65-0.24-3.358-2.784-6.925-7.078-8.139l-245.197-69.317z","M490.672 337.334c-19.76 4.672-47.245 12.31-81.149 24.554 20.81 108.771 53.219 187.014 81.149 238.832v-263.386zM492.867 271.316c33.77-6.898 61.805 19.742 61.805 51.125v360.963c0 17.024-10.333 31.747-25.642 37.52-15.67 5.91-33.779 1.331-44.861-12.675-32.656-41.267-106.323-152.95-141.19-354.563-3.242-18.746 7.066-37.695 25.328-44.726 56.186-21.63 99.094-32.442 124.56-37.644z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["shield"],"defaultCode":59829,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1097,"name":"shield-alt","prevSize":32,"id":185,"code":59829},"setIdx":0,"setId":6,"iconIdx":186},{"icon":{"paths":["M664.083 405.072c11.638-13.299 10.288-33.517-3.011-45.155s-33.517-10.288-45.155 3.011l-125.251 143.142-39.917-45.619c-11.638-13.299-31.853-14.646-45.155-3.011-13.299 11.638-14.646 31.856-3.008 45.155l64 73.142c6.077 6.944 14.854 10.928 24.080 10.928 9.229 0 18.006-3.984 24.083-10.928l149.334-170.666z","M541.99 143.050c-12.854-3.634-26.448-3.753-39.363-0.345l-264.724 69.849c-29.793 7.861-52.548 33.743-54.753 65.633-23.589 341.205 187.752 520.29 276.51 579.794 33.136 22.211 75.363 22.144 108.416-0.259 88.218-59.792 297.117-239.072 272.611-580.214-2.25-31.321-24.339-56.895-53.504-65.14l-245.194-69.318zM518.957 204.587c1.843-0.487 3.786-0.47 5.622 0.049l245.194 69.318c4.294 1.214 6.838 4.781 7.082 8.139 22.15 308.362-165.306 468.851-244.685 522.65-11.437 7.754-25.363 7.792-36.87 0.077-80.086-53.686-269.606-214.054-248.301-522.218 0.234-3.389 2.833-7.004 7.233-8.164l264.725-69.849z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["shield-check"],"defaultCode":59828,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1098,"name":"shield-check","prevSize":32,"id":186,"code":59828},"setIdx":0,"setId":6,"iconIdx":187},{"icon":{"paths":["M778.64 213.336c-17.674 0-32 14.327-32 32v533.333c0 17.674 14.326 32 32 32s32-14.326 32-32v-533.333c0-17.673-14.326-32-32-32z","M600.87 341.334c-17.674 0-32 14.33-32 32v405.334c0 17.674 14.326 32 32 32s32-14.326 32-32v-405.334c0-17.67-14.326-32-32-32z","M423.104 810.669c-17.674 0-32-14.326-32-32v-277.334c0-17.67 14.326-32 32-32 17.67 0 32 14.33 32 32v277.334c0 17.674-14.33 32-32 32z","M245.333 597.334c-17.673 0-32 14.33-32 32v149.334c0 17.674 14.327 32 32 32s32-14.326 32-32v-149.334c0-17.67-14.327-32-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["signal"],"defaultCode":59830,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1099,"name":"signal","prevSize":32,"id":187,"code":59830},"setIdx":0,"setId":6,"iconIdx":188},{"icon":{"paths":["M772.986 470.432h-40.186c-1.104-12.381-10.090-19.757-26.454-19.757-16.278 0-24.416 6.867-24.502 16.365-0.339 10.342 9.667 15.6 25.437 18.992l14.922 3.389c34.253 7.546 52.989 24.502 53.158 52.227-0.17 32.982-25.773 52.566-69.014 52.566-43.661 0-71.894-19.414-72.403-60.026h40.186c0.934 16.701 13.142 25.35 31.709 25.35 16.874 0 26.794-7.376 26.963-17.974-0.17-9.75-8.733-14.922-27.811-19.331l-18.141-4.24c-30.016-6.867-48.496-21.706-48.413-48.070-0.253-32.304 28.317-53.923 67.997-53.923 40.355 0 66.214 21.958 66.554 54.432z","M354.858 470.432h40.186c-0.339-32.474-26.198-54.432-66.554-54.432-39.679 0-68.251 21.619-67.996 53.923-0.085 26.365 18.398 41.203 48.411 48.070l18.145 4.24c19.075 4.41 27.638 9.581 27.808 19.331-0.17 10.598-10.090 17.974-26.96 17.974-18.569 0-30.778-8.65-31.71-25.35h-40.187c0.509 40.611 28.741 60.026 72.403 60.026 43.242 0 68.845-19.584 69.014-52.566-0.17-27.725-18.906-44.682-53.158-52.227l-14.922-3.389c-15.77-3.392-25.774-8.65-25.435-18.992 0.085-9.498 8.224-16.365 24.501-16.365 16.365 0 25.35 7.376 26.454 19.757z","M418.614 418.374v173.635h40.864v-107.251h1.443l41.712 106.15h26.112l41.715-105.555h1.44v106.656h40.867v-173.635h-51.974l-44.086 107.504h-2.035l-44.086-107.504h-51.971z","M864 192c16.973 0 33.251 6.743 45.254 18.745s18.746 28.281 18.746 45.255v635.296c0 12.186-3.478 24.122-10.032 34.397-6.55 10.278-15.898 18.474-26.947 23.619-11.046 5.146-23.334 7.027-35.418 5.43-12.083-1.6-23.456-6.614-32.787-14.458l-128.81-108.285h-534.006c-16.974 0-33.252-6.742-45.255-18.746s-18.745-28.282-18.745-45.254v-512c0-16.974 6.743-33.252 18.745-45.255s28.281-18.745 45.255-18.745h704zM864 256h-704v512h534.006c15.066 0 29.648 5.315 41.181 15.011l128.813 108.285v-635.296z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["sms"],"defaultCode":59772,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1100,"name":"sms","prevSize":32,"id":188,"code":59772},"setIdx":0,"setId":6,"iconIdx":189},{"icon":{"paths":["M919.258 667.229c12.605-12.253 12.877-32.394 0.605-44.982-12.269-12.589-32.435-12.858-45.040-0.605l-106.112 103.155v-500.8c0-17.568-14.259-31.81-31.853-31.81-17.59 0-31.85 14.242-31.85 31.81v500.8l-106.115-103.155c-12.605-12.253-32.768-11.984-45.040 0.605-12.269 12.589-11.997 32.73 0.608 44.982l160.179 155.718c12.368 12.019 32.070 12.019 44.435 0l160.182-155.718zM560.659 333.667c17.59 0 31.85-14.243 31.85-31.811s-14.259-31.809-31.85-31.809h-432.49c-17.591 0-31.852 14.242-31.852 31.809s14.26 31.811 31.852 31.811h432.49zM464.55 536.099c17.59 0 31.85-14.243 31.85-31.811 0-17.565-14.259-31.808-31.85-31.808h-336.381c-17.591 0-31.852 14.24-31.852 31.808s14.26 31.811 31.852 31.811h336.381zM384.458 722.96c17.594 0 31.853-14.24 31.853-31.808s-14.259-31.811-31.853-31.811h-256.289c-17.591 0-31.852 14.243-31.852 31.811s14.26 31.808 31.852 31.808h256.289z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["sort"],"defaultCode":59832,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1101,"name":"sort","prevSize":32,"id":189,"code":59832},"setIdx":0,"setId":6,"iconIdx":190},{"icon":{"paths":["M289.362 192c13.364 0 25.321 8.305 29.987 20.829l96.001 257.699c6.17 16.56-2.256 34.986-18.816 41.155-16.563 6.17-34.989-2.253-41.158-18.816l-20.477-54.963h-91.074l-20.476 54.963c-6.17 16.563-24.597 24.986-41.158 18.816s-24.986-24.595-18.816-41.155l96-257.699c4.666-12.524 16.622-20.829 29.987-20.829zM311.058 373.904l-21.695-58.238-21.695 58.238h43.391z","M522.131 626.435c-12.154 12.829-11.606 33.082 1.222 45.238l160 151.587c12.342 11.693 31.674 11.693 44.016 0l160-151.587c12.832-12.157 13.376-32.41 1.222-45.238s-32.41-13.376-45.238-1.222l-105.99 100.419v-501.632c0-17.673-14.326-32-32-32s-32 14.327-32 32v501.632l-105.994-100.419c-12.829-12.154-33.082-11.606-45.238 1.222z","M193.362 570.947c-17.673 0-32 14.326-32 32 0 17.67 14.327 32 32 32h116.145l-139.065 142.73c-8.979 9.216-11.565 22.915-6.564 34.771 5.001 11.853 16.617 19.562 29.484 19.562h192.001c17.674 0 32-14.326 32-32s-14.326-32-32-32h-116.146l139.064-142.733c8.979-9.216 11.565-22.915 6.563-34.768-4.998-11.856-16.614-19.562-29.482-19.562h-192.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["sort-az"],"defaultCode":59831,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1102,"name":"sort-az","prevSize":32,"id":190,"code":59831},"setIdx":0,"setId":6,"iconIdx":191},{"icon":{"paths":["M472.618 173.508c18.166-58.554 100.454-60.461 121.322-2.812l69.821 192.91h195.44c57.872 0 86.026 70.611 43.994 110.336l-147.888 139.782 53.386 217.363c14.17 57.696-51.251 101.805-99.536 67.11l-177.741-127.709-177.741 127.709c-48.283 34.691-113.703-9.414-99.533-67.11l53.209-216.64-157.591-139.024c-44.179-38.973-16.577-111.818 42.37-111.818h221.513l58.976-190.098zM603.574 385.334l-69.824-192.91-58.976 190.098c-8.304 26.758-33.085 45.002-61.133 45.002h-221.513l157.59 139.021c17.837 15.731 25.456 40.048 19.789 63.13l-53.209 216.643 177.74-127.709c22.33-16.045 52.426-16.045 74.755 0l177.738 127.709-53.386-217.363c-5.478-22.317 1.456-45.856 18.166-61.648l147.888-139.782h-195.44c-26.957 0-51.024-16.87-60.186-42.189z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["star"],"defaultCode":59834,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1103,"name":"star","prevSize":32,"id":191,"code":59834},"setIdx":0,"setId":6,"iconIdx":192},{"icon":{"paths":["M593.939 170.244c-20.867-57.726-103.155-55.816-121.322 2.815l-58.976 190.348h-221.513c-58.947 0-86.549 72.944-42.37 111.968l157.591 139.206-53.209 216.928c-14.17 57.77 51.25 101.936 99.533 67.197l177.741-127.875 177.741 127.875c48.285 34.739 113.706-9.427 99.536-67.197l-53.386-217.651 147.888-139.968c42.032-39.779 13.878-110.483-43.99-110.483h-195.443l-69.821-193.164z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["star-filled"],"defaultCode":59833,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1104,"name":"star-filled","prevSize":32,"id":192,"code":59833},"setIdx":0,"setId":6,"iconIdx":193},{"icon":{"paths":["M512 896c-212.077 0-384-171.923-384-384s171.923-384 384-384c212.077 0 384 171.923 384 384s-171.923 384-384 384zM565.334 288c0-29.455-23.878-53.333-53.334-53.333s-53.334 23.878-53.334 53.333v249.632l180.016 144.013c23.002 18.403 56.563 14.672 74.963-8.326 18.403-23.002 14.672-56.563-8.326-74.963l-139.984-111.987v-198.368z"],"attrs":[{"fill":"rgb(243, 190, 8)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":3}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":2}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":3}]},"tags":["status-away"],"defaultCode":59741,"grid":0},"attrs":[{"fill":"rgb(243, 190, 8)"}],"properties":{"order":1105,"name":"status-away","prevSize":32,"id":193,"code":59741},"setIdx":0,"setId":6,"iconIdx":194},{"icon":{"paths":["M512 896c-212.077 0-384-171.923-384-384s171.923-384 384-384c212.077 0 384 171.923 384 384s-171.923 384-384 384zM384 458.666c-29.456 0-53.334 23.875-53.334 53.331s23.878 53.334 53.334 53.334h256c29.456 0 53.334-23.878 53.334-53.334s-23.878-53.331-53.334-53.331h-256z"],"attrs":[{"fill":"rgb(245, 69, 92)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":6}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":6}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":8}]},"tags":["status-busy"],"defaultCode":59742,"grid":0},"attrs":[{"fill":"rgb(245, 69, 92)"}],"properties":{"order":1106,"name":"status-busy","prevSize":32,"id":194,"code":59742},"setIdx":0,"setId":6,"iconIdx":195},{"icon":{"paths":["M512 896c212.077 0 384-171.923 384-384s-171.923-384-384-384c-212.077 0-384 171.923-384 384s171.923 384 384 384zM554.774 298.667v298.668c0 23.562-19.101 42.666-42.666 42.666s-42.669-19.104-42.669-42.666v-298.668c0-23.564 19.104-42.667 42.669-42.667s42.666 19.102 42.666 42.667zM554.774 725.334c0 23.562-19.101 42.666-42.666 42.666s-42.669-19.104-42.669-42.666c0-23.565 19.104-42.669 42.669-42.669s42.666 19.104 42.666 42.669z"],"attrs":[{"fill":"rgb(243, 140, 57)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":5}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":7}]},"tags":["status-disabled"],"defaultCode":59837,"grid":0},"attrs":[{"fill":"rgb(243, 140, 57)"}],"properties":{"order":1107,"id":195,"name":"status-disabled","prevSize":32,"code":59837},"setIdx":0,"setId":6,"iconIdx":196},{"icon":{"paths":["M888.691 586.941l-125.568-24.838c3.187-16.102 4.877-32.842 4.877-50.102s-1.69-34-4.877-50.102l125.568-24.838c4.794 24.237 7.309 49.296 7.309 74.941s-2.515 50.704-7.309 74.941zM831.322 298.644l-106.365 71.209c-18.726-27.971-42.838-52.083-70.81-70.81l71.21-106.364c41.875 28.035 77.93 64.089 105.965 105.965zM586.941 135.309l-24.838 125.566c-16.102-3.185-32.842-4.876-50.102-4.876s-34 1.69-50.102 4.876l-24.838-125.566c24.237-4.795 49.296-7.309 74.941-7.309s50.704 2.514 74.941 7.309zM298.644 192.679l71.209 106.364c-27.971 18.727-52.083 42.839-70.81 70.81l-106.364-71.209c28.035-41.876 64.089-77.93 105.965-105.964zM135.309 437.059c-4.795 24.237-7.309 49.296-7.309 74.941s2.514 50.704 7.309 74.941l125.566-24.838c-3.185-16.102-4.876-32.842-4.876-50.102s1.69-34 4.876-50.102l-125.566-24.838zM192.679 725.357l106.364-71.21c18.727 27.971 42.839 52.083 70.81 70.81l-71.209 106.365c-41.876-28.035-77.93-64.090-105.964-105.965zM437.059 888.691l24.838-125.568c16.102 3.187 32.842 4.877 50.102 4.877s34-1.69 50.102-4.877l24.838 125.568c-24.237 4.794-49.296 7.309-74.941 7.309s-50.704-2.515-74.941-7.309zM725.357 831.322l-71.21-106.365c27.971-18.726 52.083-42.838 70.81-70.81l106.365 71.21c-28.035 41.875-64.090 77.93-105.965 105.965z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["status-loading"],"defaultCode":59743,"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":1108,"name":"status-loading","prevSize":32,"id":196,"code":59743},"setIdx":0,"setId":6,"iconIdx":197},{"icon":{"paths":["M512 789.334c-153.168 0-277.333-124.166-277.333-277.334s124.165-277.333 277.333-277.333c153.168 0 277.334 124.165 277.334 277.333s-124.166 277.334-277.334 277.334zM512 896c212.077 0 384-171.923 384-384s-171.923-384-384-384c-212.077 0-384 171.923-384 384s171.923 384 384 384z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["status-offline"],"defaultCode":59744,"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":1109,"name":"status-offline","prevSize":32,"id":197,"code":59744},"setIdx":0,"setId":6,"iconIdx":198},{"icon":{"paths":["M896 512c0 212.077-171.923 384-384 384s-384-171.923-384-384c0-212.077 171.923-384 384-384s384 171.923 384 384z"],"attrs":[{"fill":"rgb(45, 224, 165)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":4}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":3}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":5}]},"tags":["status-online"],"defaultCode":59745,"grid":0},"attrs":[{"fill":"rgb(45, 224, 165)"}],"properties":{"order":1110,"name":"status-online","prevSize":32,"id":198,"code":59745},"setIdx":0,"setId":6,"iconIdx":199},{"icon":{"paths":["M511.997 224c-114.163 0-179.555 64.46-179.555 128v0.253c-0.061 7.453 1.072 14.867 3.354 21.962 5.411 16.826-3.84 34.851-20.666 40.259-16.825 5.411-34.85-3.84-40.261-20.666-4.357-13.546-6.527-27.702-6.428-41.933 0.081-113.124 110.343-191.875 243.556-191.875 103.597 0 190.97 46.311 226.886 120.071 7.738 15.889 1.13 35.043-14.762 42.78-15.888 7.738-35.043 1.13-42.781-14.761-22.259-45.713-82.714-84.090-169.344-84.090z","M128 512c0-17.674 14.327-32 32-32h392.893c0.467-0.010 0.938-0.010 1.408 0h309.699c17.674 0 32 14.326 32 32s-14.326 32-32 32h-160.432c38.198 29.328 64.432 70.438 64.432 128.003 0 57.2-32.512 105.965-79.008 139.178-46.557 33.254-109.235 52.822-176.992 52.822s-130.435-19.568-176.992-52.822c-46.495-33.213-79.008-81.978-79.008-139.178 0-17.674 14.327-32 32-32s32 14.326 32 32c0 31.168 17.632 62.4 52.208 87.098 34.515 24.653 83.837 40.902 139.792 40.902s105.277-16.25 139.792-40.902c34.576-24.698 52.208-55.93 52.208-87.098 0-35.558-15.216-59.581-42.134-79.283-27.824-20.368-67.005-35.082-112.88-48.72h-388.986c-17.673 0-32-14.326-32-32z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{},{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["strike"],"defaultCode":59846,"grid":0},"attrs":[{},{}],"properties":{"order":1111,"name":"strike","prevSize":32,"id":199,"code":59846},"setIdx":0,"setId":6,"iconIdx":200},{"icon":{"paths":["M481.35 117.336c0-17.673 14.326-32 32-32s32 14.327 32 32v106.667c0 17.673-14.326 32-32 32s-32-14.327-32-32v-106.667zM771.392 214.631c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-75.411 75.413c-12.499 12.496-32.758 12.496-45.254 0-12.499-12.496-12.499-32.759 0-45.255l75.411-75.412zM336.73 694.63c-12.499-12.496-32.759-12.496-45.256 0l-75.495 75.498c-12.497 12.496-12.497 32.755 0 45.254 12.497 12.496 32.758 12.496 45.255 0l75.496-75.498c12.496-12.496 12.496-32.755 0-45.254zM481.35 800.003c0-17.674 14.326-32 32-32s32 14.326 32 32v106.669c0 17.67-14.326 32-32 32s-32-14.33-32-32v-106.669zM213.352 212.001c-12.497 12.497-12.497 32.758 0 45.255l75.349 75.348c12.497 12.496 32.758 12.496 45.254 0 12.499-12.496 12.496-32.757 0-45.254l-75.348-75.349c-12.497-12.497-32.758-12.497-45.255 0zM695.978 739.885c-12.496-12.496-12.496-32.758 0-45.254 12.499-12.496 32.758-12.496 45.254 0l75.331 75.328c12.496 12.496 12.496 32.758 0 45.254-12.499 12.496-32.758 12.496-45.258 0l-75.328-75.328zM87.751 512.003c0 17.674 14.327 32 32 32h106.667c17.673 0 32-14.326 32-32s-14.327-32-32-32h-106.667c-17.673 0-32 14.326-32 32zM801.35 544.003c-17.674 0-32-14.326-32-32s14.326-32 32-32h106.669c17.67 0 32 14.326 32 32s-14.33 32-32 32h-106.669zM668.17 512c0-85.504-69.315-154.816-154.819-154.816-85.507 0-154.819 69.312-154.819 154.816 0 85.507 69.312 154.819 154.819 154.819 85.504 0 154.819-69.312 154.819-154.819zM726.682 512c0 117.821-95.51 213.334-213.331 213.334s-213.335-95.514-213.335-213.334c0-117.821 95.514-213.332 213.335-213.332s213.331 95.511 213.331 213.332z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["sun"],"defaultCode":59847,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1112,"name":"sun","prevSize":32,"id":200,"code":59847},"setIdx":0,"setId":6,"iconIdx":201},{"icon":{"paths":["M930.704 512c0 229.75-186.25 416-416 416s-415.999-186.25-415.999-416c0-229.75 186.25-416 415.999-416s416 186.25 416 416zM570.49 859.603l-41.827-156.102c-4.611 0.33-9.264 0.499-13.958 0.499-4.57 0-9.101-0.16-13.594-0.474l-41.837 156.134c18.058 2.854 36.573 4.339 55.43 4.339 18.986 0 37.616-1.504 55.786-4.397zM438.893 688.451c-47.549-20.454-85.181-59.571-103.674-108.125l-155.029 41.539c33.968 103.485 114.617 185.805 217.045 222.058l41.658-155.472zM162.705 512c0 16.090 1.080 31.926 3.17 47.443l156.906-42.042c-0.051-1.795-0.077-3.594-0.077-5.402 0-4.909 0.186-9.776 0.547-14.595l-156.051-41.814c-2.958 18.368-4.496 37.21-4.496 56.41zM396.31 180.407c-99.16 35.408-177.786 114.033-213.196 213.19l155.535 41.677c19.357-44.352 54.982-79.978 99.334-99.331l-41.674-155.536zM514.704 160c-19.197 0-38.035 1.537-56.4 4.494l41.814 156.053c4.813-0.362 9.68-0.547 14.586-0.547 5.030 0 10.019 0.192 14.95 0.573l41.808-156.021c-18.477-2.995-37.437-4.552-56.758-4.552zM632.512 843.802c102.659-36.451 183.392-119.194 217.094-223.12l-154.973-41.526c-18.291 48.982-56.010 88.493-103.786 109.155l41.664 155.491zM863.699 558.198c1.984-15.117 3.005-30.538 3.005-46.198 0-18.771-1.469-37.197-4.298-55.171l-156.157 41.84c0.301 4.406 0.454 8.851 0.454 13.331 0 1.376-0.013 2.752-0.042 4.122l157.037 42.077zM846.714 394.774c-35.165-99.6-113.885-178.641-213.277-214.247l-41.68 155.559c44.582 19.555 80.314 55.565 99.504 100.342l155.453-41.654zM642.704 512c0-70.691-57.306-128-128-128-70.691 0-128 57.309-128 128s57.309 128 128 128c70.694 0 128-57.309 128-128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["support"],"defaultCode":59848,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1113,"name":"support","prevSize":32,"id":201,"code":59848},"setIdx":0,"setId":6,"iconIdx":202},{"icon":{"paths":["M368 412.982c-53.592 0-96-42.877-96-94.491 0-51.616 42.408-94.491 96-94.491 53.594 0 96 42.876 96 94.491 0 51.614-42.406 94.491-96 94.491zM368 476.982c88.365 0 160-70.96 160-158.491s-71.635-158.491-160-158.491c-88.365 0-160 70.959-160 158.491s71.635 158.491 160 158.491zM713.6 397.133c-35.92 0-64-28.685-64-62.794s28.080-62.792 64-62.792c35.92 0 64 28.684 64 62.792s-28.080 62.794-64 62.794zM713.6 461.133c70.691 0 128-56.768 128-126.794s-57.309-126.792-128-126.792c-70.691 0-128 56.767-128 126.792s57.309 126.794 128 126.794zM197.459 527.267c27.344-8.707 56.67-9.242 84.319-1.539l48.491 13.51c24.205 6.742 49.882 6.275 73.824-1.347l30.099-9.584c29.475-9.386 61.085-9.962 90.89-1.658 67.962 18.934 114.918 80.333 114.918 150.269v91.987c0 52.518-42.979 95.094-96 95.094h-352c-53.019 0-96-42.576-96-95.094v-103.766c0-62.909 40.999-118.621 101.459-137.872zM264.451 586.758c-15.545-4.333-32.034-4.032-47.407 0.864-33.993 10.822-57.044 42.147-57.044 77.517v103.766c0 17.507 14.327 31.699 32 31.699h352c17.674 0 32-14.192 32-31.699v-91.987c0-41.533-27.885-77.997-68.246-89.242-17.699-4.931-36.474-4.589-53.978 0.986l-30.099 9.584c-35.91 11.434-74.426 12.138-110.737 2.019l-48.489-13.507zM691.2 778.717h140.8c53.021 0 96-42.979 96-96v-30.611c0-56.877-38.614-106.49-93.747-120.454-21.398-5.418-43.853-5.040-65.056 1.098l-16.4 4.746c-21.843 6.323-44.973 6.714-67.018 1.13l-29.805-7.549c-19.907-5.043-40.797-4.691-60.522 1.018-1.066 0.31-2.122 0.634-3.174 0.97 10.71 4.048 20.896 9.539 30.253 16.374l2.429 1.776 15.040 13.206c9.939 8.726 18.141 19.248 24.182 31.014l2.208 4.301 3.677 0.931c33.062 8.374 67.76 7.789 100.525-1.693l16.4-4.749c10.282-2.976 21.171-3.158 31.546-0.531 26.736 6.771 45.462 30.832 45.462 58.413v30.611c0 17.674-14.326 32-32 32h-140.8v64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["team"],"defaultCode":59849,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1114,"name":"team","prevSize":32,"id":202,"code":59849},"setIdx":0,"setId":6,"iconIdx":203},{"icon":{"paths":["M281.184 336c17.673 0 32-14.326 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM281.184 400c-53.020 0-96-42.979-96-96 0-53.019 42.98-96 96-96 53.018 0 96 42.981 96 96 0 53.021-42.982 96-96 96zM576 320c0-26.51-21.491-48-48-48s-48 21.49-48 48c0 26.509 21.491 48 48 48s48-21.491 48-48zM640 320c0 61.856-50.144 112-112 112s-112-50.144-112-112c0-61.856 50.144-112 112-112s112 50.144 112 112zM477.901 478.515c-28.56-10.957-60.291-10.211-88.307 2.067-42.282 18.534-69.594 60.326-69.594 106.49v132.928c0 53.021 42.979 96 96 96h224c53.021 0 96-42.979 96-96v-125.062c0-51.162-31.536-97.034-79.306-115.354-30.352-11.642-64.067-10.851-93.84 2.198l-2.070 0.909c-21.523 9.434-45.901 10.006-67.843 1.59l-15.040-5.766zM415.286 539.2c12.595-5.52 26.858-5.856 39.699-0.931l15.040 5.77c37.664 14.445 79.504 13.462 116.451-2.73l2.070-0.909c14.349-6.288 30.602-6.669 45.229-1.059 23.024 8.829 38.224 30.938 38.224 55.597v125.062c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32v-132.928c0-20.752 12.278-39.539 31.286-47.872zM768 336c-17.674 0-32-14.326-32-32s14.326-32 32-32c17.674 0 32 14.327 32 32s-14.326 32-32 32zM768 400c53.021 0 96-42.979 96-96 0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96zM840.714 681.766h-72.714v-64h72.714c17.674 0 32-14.326 32-32v-44.688c0-15.050-9.664-28.394-23.958-33.091-7.536-2.474-15.69-2.304-23.114 0.483l-4.554 1.709c-19.77 7.421-40.89 9.978-61.619 7.632-12.438-31.683-37.722-57.549-70.774-70.227-1.754-0.672-3.52-1.302-5.296-1.894 18.058-5.312 37.36-5.040 55.344 0.867l14.182 4.659c14.886 4.893 30.998 4.554 45.667-0.954l4.554-1.709c21.069-7.91 44.205-8.394 65.581-1.37 40.566 13.325 67.987 51.197 67.987 93.894v44.688c0 53.021-42.982 96-96 96zM625.267 624h-0.797c0.259 0.598 0.525 1.194 0.797 1.786v-1.786zM357.594 448.582c2.528-1.107 5.088-2.122 7.674-3.043-17.907-5.155-37.014-4.832-54.824 1.018l-14.183 4.659c-14.887 4.893-30.998 4.554-45.668-0.954l-4.554-1.709c-21.067-7.91-44.203-8.394-65.581-1.37-40.565 13.325-67.986 51.197-67.986 93.894v44.688c0 53.021 42.981 96 96 96h79.53v-64h-79.53c-17.673 0-32-14.326-32-32v-44.688c0-15.050 9.664-28.394 23.96-33.091 7.534-2.474 15.688-2.304 23.112 0.483l4.554 1.709c21.238 7.974 44.041 10.333 66.238 7.027 10.398-30.173 32.994-55.357 63.259-68.624zM423.917 624h0.797c-0.259 0.598-0.525 1.194-0.797 1.786v-1.786z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["teams"],"defaultCode":59751,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1115,"name":"teams","prevSize":32,"id":203,"code":59751},"setIdx":0,"setId":6,"iconIdx":204},{"icon":{"paths":["M631.997 256h24v-56c0-57.437 46.563-104 104-104 57.44 0 104 46.562 104 104v56h24c17.674 0 32 14.327 32 32v192c0 17.674-14.326 32-32 32h-256c-17.67 0-32-14.326-32-32v-192c0-17.673 14.33-32 32-32zM759.997 160c-22.090 0-40 17.908-40 40v55.238h80v-55.238c0-22.092-17.907-40-40-40z","M527.997 224c10.096 0 19.882 1.336 29.184 3.84-13.251 16.46-21.184 37.383-21.184 60.16v0.664c-2.602-0.436-5.274-0.664-8-0.664-26.509 0-48 21.49-48 48s21.491 48 48 48c2.726 0 5.398-0.227 8-0.662v64.381c-2.64 0.186-5.309 0.282-8 0.282-61.856 0-112-50.144-112-112s50.144-112 112-112z","M492.941 500.282c14.883 5.709 30.883 7.283 46.355 4.758 6.182 22.938 20.646 42.474 39.987 55.206-35.123 13.318-74.019 13.309-109.261-0.208l-15.040-5.77c-12.838-4.925-27.104-4.589-39.699 0.931-19.008 8.333-31.286 27.12-31.286 47.872v132.928c0 17.674 14.33 32 32 32h224c17.674 0 32-14.326 32-32v-125.062c0-12.842-4.122-24.995-11.325-34.938h70.291c3.29 11.162 5.034 22.902 5.034 34.938v125.062c0 53.021-42.979 96-96 96h-224c-53.018 0-95.999-42.979-95.999-96v-132.928c0-46.163 27.311-87.955 69.592-106.49 28.019-12.278 59.747-13.024 88.31-2.067l15.040 5.766z","M887.997 576h-15.286v25.766c0 17.674-14.326 32-32 32h-72.714v64h72.714c53.021 0 96-42.979 96-96v-39.027c-14.278 8.426-30.931 13.261-48.714 13.261z","M281.182 416c53.020 0 95.999-42.979 95.999-96 0-53.019-42.979-96-95.999-96s-96 42.981-96 96c0 53.021 42.98 96 96 96zM281.182 352c-17.673 0-32-14.326-32-32s14.327-32 32-32c17.673 0 32 14.327 32 32s-14.327 32-32 32z","M625.267 640h-0.8c0.262 0.598 0.528 1.194 0.8 1.786v-1.786z","M357.59 464.582c2.531-1.107 5.091-2.122 7.674-3.043-17.907-5.155-37.011-4.832-54.823 1.018l-14.183 4.659c-14.887 4.893-30.998 4.554-45.668-0.954l-4.554-1.709c-21.067-7.91-44.203-8.394-65.581-1.37-40.565 13.325-67.986 51.197-67.986 93.894v44.688c0 53.021 42.98 96 96 96h79.53v-64h-79.53c-17.673 0-32-14.326-32-32v-44.688c0-15.050 9.664-28.394 23.96-33.091 7.534-2.474 15.688-2.304 23.112 0.483l4.554 1.709c21.238 7.974 44.041 10.333 66.238 7.027 10.398-30.173 32.992-55.357 63.258-68.624z","M423.914 640h0.797c-0.259 0.598-0.525 1.194-0.797 1.786v-1.786z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["teams-private"],"defaultCode":59750,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1116,"name":"teams-private","prevSize":32,"id":204,"code":59750},"setIdx":0,"setId":6,"iconIdx":205},{"icon":{"paths":["M170.664 192c0-17.673 14.327-32 32-32h618.667c17.674 0 32 14.327 32 32v128c0 17.674-14.326 32-32 32s-32-14.326-32-32v-96h-245.334v576h96c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.67 0-32-14.326-32-32s14.33-32 32-32h96v-576h-245.333v96c0 17.674-14.327 32-32 32s-32-14.326-32-32v-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["text-format"],"defaultCode":59839,"grid":0},"attrs":[{}],"properties":{"order":1117,"id":205,"name":"text-format","prevSize":32,"code":59839},"setIdx":0,"setId":6,"iconIdx":206},{"icon":{"paths":["M223.311 308.609c-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-9.348 103.235 27.547 175.997 86.848 226.374 60.642 51.52 146.602 80.998 235.29 90.893 88.611 9.885 186.221 1.398 263.341-14.973 38.56-8.189 70.928-18.125 93.888-28.128 8.906-3.882 15.837-7.536 20.941-10.765-2.374-1.514-5.245-3.197-8.672-5.030-8.886-4.749-19.059-9.261-29.613-13.894l-1.843-0.81c-9.315-4.083-19.725-8.65-27.613-13.078-14.291-8.026-28.317-17.155-38.544-26.867-5.034-4.781-10.762-11.194-14.595-19.184-4.054-8.454-6.96-21.078-1.261-34.435 30.816-72.186 45.459-111.725 52.554-137.834 6.621-24.378 6.621-36.653 6.621-56.17v-0.179c0-15.51-8.979-86.595-53.776-152.876-43.376-64.174-121.398-125.729-264.832-125.729-129.725 0-207.83 53.576-254.529 118.696zM173.267 272.433c58.132-81.063 154.749-144.433 304.573-144.433 164.896 0 261.594 72.589 315.859 152.878 52.838 78.181 64.416 161.881 64.416 187.641 0 21.654-0.022 40.336-8.797 72.64-7.834 28.835-22.627 68.614-50.048 133.424 5.069 4.032 12.592 9.005 22.506 14.57 5.12 2.877 12.995 6.339 24.054 11.194 10.266 4.506 22.582 9.93 33.891 15.978 10.848 5.798 23.526 13.571 32.954 23.738 9.859 10.63 20.208 28.87 12.816 51.139-4.87 14.672-16.182 25.091-25.61 32.016-10.24 7.52-22.947 14.278-36.858 20.342-27.949 12.176-64.582 23.181-105.68 31.907-82.198 17.453-186.522 26.688-282.909 15.936-96.31-10.746-195.346-43.178-268.313-105.165-74.031-62.893-119.295-154.778-108.551-277.856 0.276-63.411 19.117-157.053 75.696-235.948zM333.952 422.051c0-17.648 14.25-31.955 31.83-31.955h183.008c17.578 0 31.827 14.307 31.827 31.955s-14.25 31.955-31.827 31.955h-183.008c-17.581 0-31.83-14.307-31.83-31.955zM365.782 539.709c-17.581 0-31.83 14.307-31.83 31.955s14.25 31.955 31.83 31.955h224.118c17.578 0 31.827-14.307 31.827-31.955s-14.25-31.955-31.827-31.955h-224.118z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["threads"],"defaultCode":59850,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1118,"name":"threads","prevSize":32,"id":206,"code":59850},"setIdx":0,"setId":6,"iconIdx":207},{"icon":{"paths":["M353.354 320c0-17.673 14.326-32 32-32h256c17.674 0 32 14.327 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M385.354 416c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M481.354 448c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M641.354 416c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M353.354 576c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M513.354 544c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M609.354 576c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M385.354 672c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M481.354 704c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M641.354 672c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M289.353 160h448.001c35.344 0 64 28.654 64 64v576c0 35.347-28.656 64-64 64h-448.001c-35.346 0-64-28.653-64-64v-576c0-35.346 28.654-64 64-64zM289.353 224v576h448.001v-576h-448.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["total"],"defaultCode":59851,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1119,"name":"total","prevSize":32,"id":207,"code":59851},"setIdx":0,"setId":6,"iconIdx":208},{"icon":{"paths":["M713.613 91.356c13.162-11.794 33.392-10.685 45.187 2.477l129.034 144c10.89 12.154 10.89 30.556 0 42.71l-129.034 144.001c-11.795 13.162-32.026 14.269-45.187 2.477-13.162-11.795-14.272-32.026-2.477-45.187l81.222-90.646h-216.358c-17.674 0-32-14.327-32-32s14.326-32 32-32h216.358l-81.222-90.645c-11.795-13.162-10.685-33.393 2.477-45.187zM340.026 464.461c8.586-15.45 28.067-21.018 43.514-12.432l128.461 71.366 128.461-71.366c15.446-8.586 34.928-3.018 43.514 12.432 8.582 15.45 3.014 34.931-12.435 43.514l-159.539 88.634-159.539-88.634c-15.45-8.582-21.018-28.064-12.435-43.514zM192 288v448h640v-192c0-17.674 14.326-32 32-32s32 14.326 32 32v224c0 17.674-14.326 32-32 32h-704c-17.673 0-32-14.326-32-32v-512c0-17.673 14.327-32 32-32h272c17.674 0 32 14.327 32 32s-14.326 32-32 32h-240z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["transcript"],"defaultCode":59852,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1120,"name":"transcript","prevSize":32,"id":208,"code":59852},"setIdx":0,"setId":6,"iconIdx":209},{"icon":{"paths":["M378.861 853.331c317.456 0 491.091-262.662 491.091-490.442 0-7.462 0-14.89-0.506-22.282 33.779-24.401 62.938-54.614 86.112-89.224-31.501 13.94-64.918 23.082-99.136 27.12 36.032-21.542 62.998-55.424 75.882-95.34-33.878 20.078-70.944 34.228-109.597 41.839-53.501-56.814-138.515-70.72-207.37-33.919-68.851 36.801-104.426 115.155-86.768 191.127-138.774-6.947-268.074-72.409-355.715-180.093-45.811 78.76-22.412 179.517 53.436 230.1-27.467-0.813-54.335-8.214-78.337-21.574 0 0.704 0 1.443 0 2.182 0.022 82.051 57.937 152.723 138.47 168.97-25.41 6.922-52.071 7.933-77.933 2.957 22.611 70.218 87.409 118.32 161.25 119.706-61.116 47.968-136.616 74.010-214.35 73.933-13.732-0.026-27.452-0.858-41.087-2.486 78.931 50.586 170.772 77.418 264.557 77.293z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["twitter-monochromatic"],"defaultCode":59660,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1121,"name":"twitter-monochromatic","prevSize":32,"id":209,"code":59660},"setIdx":0,"setId":6,"iconIdx":210},{"icon":{"paths":["M384 320c0-17.673-14.326-32-32-32s-32 14.327-32 32v256c0 106.038 85.962 192 192 192s192-85.962 192-192v-256c0-17.673-14.326-32-32-32s-32 14.327-32 32v256c0 70.691-57.309 128-128 128s-128-57.309-128-128v-256zM352 856c-13.254 0-24 10.746-24 24s10.746 24 24 24h320c13.254 0 24-10.746 24-24s-10.746-24-24-24h-320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["underline"],"defaultCode":59853,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1122,"name":"underline","prevSize":32,"id":210,"code":59853},"setIdx":0,"setId":6,"iconIdx":211},{"icon":{"paths":["M512 832c176.73 0 320-143.27 320-320s-143.27-320-320-320c-111.712 0-210.056 57.244-267.295 144h107.295c17.674 0 32 14.326 32 32s-14.326 32-32 32h-176c-17.673 0-32-14.326-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v101.364c70.228-90.856 180.282-149.364 304-149.364 212.077 0 384 171.923 384 384s-171.923 384-384 384c-212.077 0-384-171.923-384-384h64c0 176.73 143.27 320 320 320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["undo"],"defaultCode":59854,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1123,"name":"undo","prevSize":32,"id":211,"code":59854},"setIdx":0,"setId":6,"iconIdx":212},{"icon":{"paths":["M589.36 729.43c-107.366 23.603-252.288-9.875-422.339-221.158 65.137-95.478 165.885-189.15 280.79-213.871 108.314-23.302 251.286 10.604 413.674 221.404-61.546 95.187-158.653 188.682-272.125 213.626zM916.819 482.714c-347.59-456.963-669.742-211.156-808.018-2.662-12.655 19.082-10.846 44.304 3.402 62.227 362.786 456.419 677.038 209.142 808.011 0.563 11.674-18.589 9.894-42.656-3.395-60.128zM619.462 512c0-53.709-45.517-100.57-105.834-100.57s-105.834 46.861-105.834 100.57c0 53.709 45.517 100.573 105.834 100.573s105.834-46.864 105.834-100.573zM683.546 512c0 90.893-76.074 164.573-169.917 164.573s-169.917-73.68-169.917-164.573c0-90.89 76.074-164.57 169.917-164.57s169.917 73.68 169.917 164.57z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["unread-on-top"],"defaultCode":59857,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1124,"name":"unread-on-top","prevSize":32,"id":212,"code":59857},"setIdx":0,"setId":6,"iconIdx":213},{"icon":{"paths":["M829.168 153.372c12.515-12.497 32.803-12.497 45.315 0 12.515 12.497 12.515 32.758 0 45.255l-672.887 672c-12.513 12.496-32.801 12.496-45.315 0s-12.513-32.758 0-45.254l672.887-672zM110.155 480.051c101.936-153.699 303.797-327.676 542.114-225.436l-49.578 49.512c-56.528-19.209-108.077-19.504-153.526-9.726-114.906 24.721-215.653 118.392-280.79 213.871 38.633 48 75.969 86.822 111.862 117.885l-45.363 45.302c-39.684-34.736-80.189-77.437-121.317-129.181-14.248-17.923-16.056-43.146-3.402-62.227zM797.981 350.454l-45.328 45.27c35.546 31.427 72.336 70.947 110.186 120.080-61.546 95.187-158.656 188.682-272.125 213.626-46.752 10.278-100.624 9.734-160.592-11.603l-49.331 49.267c244.662 107.334 443.389-69.158 540.778-224.253 11.674-18.589 9.894-42.656-3.395-60.128-40.493-53.235-80.64-96.931-120.192-132.259zM514.982 347.43c13.709 0 27.037 1.571 39.802 4.541l-203.738 203.469c-3.901-13.837-5.981-28.403-5.981-43.44 0-90.89 76.074-164.57 169.917-164.57zM679.091 469.184l-203.264 202.998c12.57 2.87 25.68 4.39 39.155 4.39 93.843 0 169.917-73.68 169.917-164.573 0-14.81-2.019-29.162-5.808-42.816z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["unread-on-top-disabled"],"defaultCode":59856,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1125,"name":"unread-on-top-disabled","prevSize":32,"id":213,"code":59856},"setIdx":0,"setId":6,"iconIdx":214},{"icon":{"paths":["M273.128 356.678c-6.62 27.766-2.384 63.757 25.498 105.581l33.166 49.75h-59.792c-44.011 0-70.484 14.874-86.279 33.619-16.496 19.578-24.573 47.264-23.734 77.491 0.841 30.262 10.601 59.968 25.818 81.312 15.127 21.216 33.404 31.578 52.195 31.578h143.999v64h-144c-45.209 0-80.932-25.642-104.306-58.426-23.283-32.656-36.522-74.95-37.682-116.688-1.16-41.773 9.763-86.083 38.766-120.506 20.726-24.598 49.155-42.32 84.825-50.784-16.1-39.011-19.009-77.050-10.731-111.77 11.253-47.2 42.305-84.492 80.791-107.342 38.4-22.798 85.677-32.139 131.303-21.965 35.584 7.935 68.909 27.48 95.251 59.554 53.75-35.147 127.584-30.892 182.483-2.495 34.438 17.812 64.794 46.382 81.437 85.010 12.294 28.531 16.438 61.011 10.608 96.205 46.112 6.682 81.507 25.155 105.616 53.456 30.346 35.626 38.102 81.35 33.443 123.283-4.659 41.917-21.946 83.485-46.544 115.114-24.061 30.934-59.354 57.354-101.261 57.354h-144v-64h144c14.093 0 32.8-9.581 50.742-32.646 17.398-22.371 30.112-52.806 33.453-82.89 3.341-30.067-2.902-56.339-18.554-74.714-15.222-17.869-44.035-33.75-97.642-33.75h-45.686l15.613-42.938c13.546-37.251 11.091-66.742 1.437-89.149-9.856-22.87-28.502-41.302-52.064-53.488-49.587-25.649-107.475-18.625-134.717 14.064l-30.134 36.16-22.541-41.325c-19.757-36.219-47.232-54.175-74.87-60.339-28.378-6.327-59.098-0.669-84.701 14.53-25.512 15.148-44.461 38.855-51.208 67.152zM630.979 588.778l-96-99.050c-6.029-6.218-14.32-9.728-22.979-9.728s-16.95 3.51-22.979 9.728l-96 99.050c-12.298 12.691-11.981 32.95 0.707 45.251 12.691 12.298 32.95 11.981 45.251-0.707l41.021-42.326v273.005c0 17.674 14.326 32 32 32s32-14.326 32-32v-273.005l41.021 42.326c12.301 12.688 32.56 13.005 45.251 0.707 12.691-12.301 13.005-32.56 0.707-45.251z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["upload"],"defaultCode":59858,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1126,"name":"upload","prevSize":32,"id":214,"code":59858},"setIdx":0,"setId":6,"iconIdx":215},{"icon":{"paths":["M609.354 336c0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96s96-42.979 96-96zM673.354 336c0 88.365-71.635 160-160 160s-160-71.635-160-160c0-88.365 71.635-160 160-160s160 71.635 160 160zM413.805 551.802c-24.621-5.77-50.285-5.366-74.714 1.178-67.086 17.968-113.738 78.762-113.738 148.211v66.81c0 53.021 42.98 96 96 96h384c53.021 0 96-42.979 96-96v-58.531c0-74.301-51.149-138.826-123.488-155.779l-6.458-1.514c-25.674-6.016-52.435-5.594-77.907 1.229l-49.626 13.293c-20.378 5.456-41.789 5.795-62.326 0.979l-67.744-15.875zM355.651 614.8c14.237-3.814 29.197-4.051 43.549-0.688l67.744 15.878c30.806 7.219 62.925 6.714 93.488-1.472l49.629-13.293c15.283-4.096 31.341-4.349 46.742-0.736l6.458 1.51c43.402 10.173 74.093 48.89 74.093 93.469v58.531c0 17.674-14.326 32-32 32h-384c-17.673 0-32-14.326-32-32v-66.81c0-40.483 27.193-75.917 66.298-86.39z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["user"],"defaultCode":59861,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1127,"name":"user","prevSize":32,"id":215,"code":59861},"setIdx":0,"setId":6,"iconIdx":216},{"icon":{"paths":["M553.411 326.282c0 91.578-75.846 165.818-169.411 165.818-93.564 0-169.412-74.24-169.412-165.818 0-91.581 75.848-165.821 169.412-165.821 93.565 0 169.411 74.24 169.411 165.821zM485.648 326.282c0-54.949-45.51-99.493-101.648-99.493s-101.647 44.544-101.647 99.493c0 54.947 45.509 99.491 101.647 99.491s101.648-44.544 101.648-99.491z","M203.427 511.232c28.952-9.11 60.004-9.67 89.279-1.61l51.342 14.131c25.632 7.056 52.819 6.566 78.166-1.408l31.872-10.026c31.206-9.821 64.678-10.422 96.234-1.738 71.962 19.811 121.68 84.051 121.68 157.219v96.24c0 54.947-45.51 99.491-101.648 99.491h-372.705c-56.138 0-101.647-44.544-101.647-99.491v-108.566c0-65.814 43.411-124.106 107.427-144.243zM274.359 573.472c-16.46-4.531-33.918-4.218-50.196 0.906-35.992 11.322-60.399 44.093-60.399 81.098v108.566c0 18.317 15.17 33.165 33.882 33.165h372.705c18.714 0 33.882-14.848 33.882-33.165v-96.24c0-43.453-29.523-81.603-72.259-93.366-18.739-5.158-38.618-4.8-57.152 1.030l-31.872 10.026c-38.022 11.962-78.803 12.698-117.248 2.115l-51.343-14.134z","M797.091 189.321c0-15.913-13.024-28.812-29.091-28.812s-29.091 12.9-29.091 28.812v100.844h-101.818c-16.067 0-29.091 12.9-29.091 28.812s13.024 28.812 29.091 28.812h101.818v100.845c0 15.914 13.024 28.813 29.091 28.813s29.091-12.899 29.091-28.813v-100.845h101.818c16.067 0 29.091-12.899 29.091-28.812s-13.024-28.812-29.091-28.812h-101.818v-100.844z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["user-add"],"defaultCode":59859,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1128,"name":"user-add","prevSize":32,"id":216,"code":59859},"setIdx":0,"setId":6,"iconIdx":217},{"icon":{"paths":["M464 318.747c0-51.548-42.406-94.366-96-94.366-53.592 0-96 42.819-96 94.366s42.408 94.367 96 94.367c53.594 0 96-42.819 96-94.367zM528 318.747c0 87.416-71.635 158.284-160 158.284s-160-70.867-160-158.284c0-87.417 71.635-158.282 160-158.282s160 70.865 160 158.282zM281.778 525.712c-27.649-7.693-56.976-7.158-84.319 1.536-60.46 19.226-101.459 74.864-101.459 137.69v103.629c0 52.451 42.981 94.97 96 94.97h352c3.606 0 7.165-0.195 10.666-0.579v-64.534c-3.334 1.168-6.925 1.802-10.666 1.802h-352c-17.673 0-32-14.173-32-31.658v-103.629c0-35.325 23.051-66.605 57.044-77.414 15.373-4.89 31.862-5.187 47.407-0.864l48.489 13.491c36.311 10.102 74.827 9.402 110.737-2.016l30.099-9.571c17.504-5.568 36.278-5.91 53.978-0.986 18.899 5.261 35.066 16.042 46.912 30.282v-79.712c-9.309-4.749-19.203-8.627-29.584-11.517-29.805-8.291-61.414-7.715-90.89 1.654l-30.099 9.574c-23.942 7.61-49.619 8.080-73.824 1.344l-48.491-13.491zM763.366 489.709c-12.326-12.646-32.586-12.918-45.248-0.608-12.666 12.31-12.938 32.544-0.611 45.19l102.842 105.51h-324.349c-17.674 0-32 14.307-32 31.958 0 17.648 14.326 31.958 32 31.958h324.349l-102.842 105.507c-12.326 12.65-12.054 32.88 0.611 45.194 12.662 12.31 32.922 12.038 45.248-0.611l155.718-159.757c12.093-12.406 12.093-32.176 0-44.582l-155.718-159.76z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["user-forward"],"defaultCode":59860,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1129,"name":"user-forward","prevSize":32,"id":217,"code":59860},"setIdx":0,"setId":6,"iconIdx":218},{"icon":{"paths":["M201.583 672c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 576c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M201.583 480c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 384c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M201.583 288c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M329.584 192c-17.674 0-32.001 14.327-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.327 32-32s-14.326-32-32-32h-544z","M201.583 864c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 768c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["view-condensed"],"defaultCode":59862,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1130,"name":"view-condensed","prevSize":32,"id":218,"code":59862},"setIdx":0,"setId":6,"iconIdx":219},{"icon":{"paths":["M288 192c0-17.673 14.327-32 32-32h544c17.674 0 32 14.327 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 288c0-17.673 14.327-32 32-32h448c17.674 0 32 14.327 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 304c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M288 464c0-17.674 14.327-32 32-32h544c17.674 0 32 14.326 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.326-32-32zM288 560c0-17.674 14.327-32 32-32h448c17.674 0 32 14.326 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.326-32-32zM192 576c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M288 736c0-17.674 14.327-32 32-32h544c17.674 0 32 14.326 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.326-32-32zM288 832c0-17.674 14.327-32 32-32h448c17.674 0 32 14.326 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.326-32-32zM192 848c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["view-extended"],"defaultCode":59863,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1131,"name":"view-extended","prevSize":32,"id":219,"code":59863},"setIdx":0,"setId":6,"iconIdx":220},{"icon":{"paths":["M192 320c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M320 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.674 0 32-14.327 32-32s-14.326-32-32-32h-544z","M192 576c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M320 480c-17.673 0-32 14.326-32 32s14.327 32 32 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M192 832c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M320 736c-17.673 0-32 14.326-32 32s14.327 32 32 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["view-medium"],"defaultCode":59864,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1132,"name":"view-medium","prevSize":32,"id":220,"code":59864},"setIdx":0,"setId":6,"iconIdx":221},{"icon":{"paths":["M640.854 256c26.512 0 48-21.49 48-48s-21.488-48-48-48c-26.509 0-48 21.49-48 48s21.491 48 48 48zM640.854 320c61.856 0 112-50.144 112-112s-50.144-112-112-112c-61.856 0-112 50.144-112 112s50.144 112 112 112zM592.854 416v256h-160v128h32v-96h224v-288h-96zM528.854 768h160c35.347 0 64-28.653 64-64v-288c0-35.347-28.653-64-64-64h-96c-35.344 0-64 28.653-64 64v192h-96c-35.344 0-64 28.653-64 64v128c0 35.347 28.656 64 64 64h32c35.347 0 64-28.653 64-64v-32zM784.854 448c0-17.674 14.326-32 32-32s32 14.326 32 32v384c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32s14.326-32 32-32h192v-352zM368.403 401.52c9.677-9.059 10.176-24.246 1.117-33.923l-48.272-51.558v-47.925c0-13.255-10.746-24-24-24s-24 10.745-24 24v57.406c0 6.093 2.316 11.955 6.48 16.403l54.752 58.48c9.059 9.677 24.246 10.176 33.923 1.117zM170.974 414.278c53.308 74.218 156.687 91.171 230.908 37.862 10.765-7.731 25.76-5.274 33.494 5.491 7.731 10.768 5.274 25.763-5.494 33.494-95.75 68.771-229.121 46.902-297.894-48.848s-46.902-229.123 48.848-297.895c75.545-54.26 174.453-52.073 246.597-1.796 10.874 7.578 13.546 22.538 5.968 33.412s-22.538 13.547-33.411 5.968c-55.971-39.005-132.65-40.618-191.153 1.402-74.219 53.308-91.171 156.688-37.864 230.909z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["waiting-on-me"],"defaultCode":59865,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1133,"name":"waiting-on-me","prevSize":32,"id":221,"code":59865},"setIdx":0,"setId":6,"iconIdx":222},{"icon":{"paths":["M512 352.003c17.674 0 32 14.33 32 32v224c0 17.674-14.326 32-32 32s-32-14.326-32-32v-224c0-17.67 14.326-32 32-32z","M512 672.003c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32s-32-14.326-32-32c0-17.67 14.326-32 32-32z","M567.101 158.348c-24.774-41.922-85.427-41.922-110.202 0l-359.92 609.099c-25.21 42.662 5.544 96.557 55.099 96.557h719.845c49.555 0 80.307-53.894 55.098-96.557l-359.92-609.099zM512 190.906l359.923 609.097h-719.845l359.922-609.097z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["warning"],"defaultCode":59866,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1134,"name":"warning","prevSize":32,"id":222,"code":59866},"setIdx":0,"setId":6,"iconIdx":223},{"icon":{"paths":["M784.131 240.143c-35.43-35.658-77.581-63.931-124.016-83.181s-96.227-29.094-146.493-28.961c-210.863 0-382.322 171.532-382.414 382.376-0.085 67.104 17.523 133.043 51.047 191.171l-54.256 198.154 202.72-53.174c56.064 30.531 118.883 46.531 182.717 46.538h0.166c210.752 0 382.32-171.552 382.394-382.394 0.16-50.25-9.645-100.029-28.848-146.464-19.2-46.436-47.418-88.604-83.018-124.065zM513.622 828.486h-0.186c-56.922 0.006-112.797-15.293-161.776-44.298l-11.606-6.896-120.302 31.555 32.124-117.347-7.573-12.029c-31.783-50.64-48.608-109.232-48.535-169.021 0-175.235 142.653-317.816 317.981-317.816 84.301 0.049 165.13 33.58 224.707 93.218 59.581 59.638 93.034 140.499 92.998 224.8-0.074 175.254-142.653 317.834-317.834 317.834zM687.958 590.451c-9.552-4.787-56.528-27.907-65.293-31.171s-15.126-4.768-21.491 4.784c-6.362 9.555-24.678 31.171-30.253 37.462-5.574 6.288-11.149 7.187-20.701 2.4-9.555-4.784-40.339-14.87-76.845-47.434-28.403-25.322-47.584-56.621-53.174-66.192-5.594-9.571-0.589-14.669 4.198-19.491 4.291-4.291 9.552-11.168 14.32-16.742s6.381-9.571 9.552-15.933c3.174-6.362 1.597-11.955-0.787-16.739-2.384-4.787-21.491-51.818-29.466-70.96-7.757-18.63-15.622-16.099-21.491-16.394-5.501-0.275-11.955-0.349-18.336-0.349-4.842 0.131-9.606 1.264-13.994 3.325-4.387 2.058-8.298 5.005-11.491 8.65-8.749 9.552-33.428 32.675-33.428 79.706s34.234 92.467 39.002 98.848c4.765 6.381 67.382 102.883 163.187 144.266 17.792 7.68 35.974 14.413 54.477 20.17 22.902 7.334 43.731 6.237 60.179 3.779 18.336-2.733 56.547-23.104 64.506-45.418 7.955-22.317 7.955-41.459 5.501-45.456-2.458-3.997-8.618-6.326-18.173-11.11z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["whatsapp-monochromatic"],"defaultCode":59868,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1135,"name":"whatsapp-monochromatic","prevSize":32,"id":223,"code":59868},"setIdx":0,"setId":6,"iconIdx":224},{"icon":{"paths":["M354.006 399.123l14.029 0.627-0.541-16.726-152.878 1.578c49.916-116.491 165.64-198.133 300.366-198.133 99.645 0 188.893 44.659 248.81 115.065-3.712 0.171-7.491 0.492-11.526 1.068 0 0-63.76 14.898-13.302 118.708 0 0 31.085 84.541-19.306 198.774l-28.403 73.306-99.101-264.723c0 0-5.984-28.154 23.61-28.154l23.76-1.472 0.339-16.035h-228.368v14.458c0 0 39.83-0.288 56.15 27.149l40.762 103.779-73.014 174.403-108.608-272.4c0 0-3.389-31.779 27.222-31.27z","M841.603 513.168c0-33.862-5.235-66.643-14.726-97.357l-145.949 378.755c96.134-56.88 160.675-161.571 160.675-281.398z","M411.478 823.011c32.49 10.912 67.267 16.778 103.488 16.778 37.85 0 74.102-6.406 107.898-18.256l-99.709-258.502-111.677 259.981z","M188.279 513.149c0-32.083 4.712-63.066 13.339-92.336l1 2.051 152.656 375.229c-99.606-55.882-166.994-162.538-166.994-284.944z","M130.705 512.093c0-211.775 172.316-384.093 384.076-384.093 211.725 0 383.923 172.318 383.923 384.093 0 211.776-172.198 384.010-383.923 384.010-211.757 0-384.076-172.234-384.076-384.010zM514.781 879.254c202.384 0 367.11-164.742 367.11-367.178 0-202.486-164.726-367.145-367.11-367.161-202.489 0-367.213 164.673-367.213 367.161 0 202.435 164.724 367.178 367.213 367.178z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["wordpress-monochromatic"],"defaultCode":59755,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1136,"name":"wordpress-monochromatic","prevSize":32,"id":224,"code":59755},"setIdx":0,"setId":6,"iconIdx":225},{"icon":{"paths":["M193.353 405.334h213.332v-213.334h-213.332v213.334zM129.353 170.667c0-23.564 19.102-42.667 42.667-42.667h256c23.565 0 42.666 19.102 42.666 42.667v255.999c0 23.565-19.101 42.669-42.666 42.669h-256c-23.564 0-42.667-19.104-42.667-42.669v-255.999zM620.019 405.334h213.334v-213.334h-213.334v213.334zM556.019 170.667c0-23.564 19.104-42.667 42.666-42.667h256c23.565 0 42.669 19.102 42.669 42.667v255.999c0 23.565-19.104 42.669-42.669 42.669h-256c-23.562 0-42.666-19.104-42.666-42.669v-255.999zM620.019 618.666h213.334v213.334h-213.334v-213.334zM598.685 554.666c-23.562 0-42.666 19.104-42.666 42.669v256c0 23.562 19.104 42.666 42.666 42.666h256c23.565 0 42.669-19.104 42.669-42.666v-256c0-23.565-19.104-42.669-42.669-42.669h-256zM193.353 832h213.332v-213.334h-213.332v213.334zM129.353 597.334c0-23.565 19.102-42.669 42.667-42.669h256c23.565 0 42.666 19.104 42.666 42.669v256c0 23.562-19.101 42.666-42.666 42.666h-256c-23.564 0-42.667-19.104-42.667-42.666v-256z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["workspaces"],"defaultCode":59870,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1137,"name":"workspaces","prevSize":32,"id":225,"code":59870},"setIdx":0,"setId":6,"iconIdx":226},{"icon":{"paths":["M384.509 149.333c0-11.782 9.562-21.333 21.36-21.333h85.446c11.798 0 21.363 9.551 21.363 21.333v106.667h-106.81c-11.798 0-21.36-9.551-21.36-21.333v-85.333z","M512.678 256h106.806c11.798 0 21.36 9.551 21.36 21.333v85.332c0 11.782-9.562 21.334-21.36 21.334h-106.806v-128z","M384.509 405.334c0-11.782 9.562-21.334 21.36-21.334h106.81v128h-106.81c-11.798 0-21.36-9.552-21.36-21.334v-85.331z","M512.678 512h106.806c11.798 0 21.36 9.552 21.36 21.334v106.666h-128.166v-128z","M427.232 640c-23.597 0-42.723 19.104-42.723 42.666v170.669c0 23.562 19.126 42.666 42.723 42.666h170.89c23.597 0 42.723-19.104 42.723-42.666v-213.334h-213.613zM491.315 725.334c-11.798 0-21.36 9.549-21.36 21.331v42.669c0 11.782 9.562 21.331 21.36 21.331h42.723c11.798 0 21.36-9.549 21.36-21.331v-42.669c0-11.782-9.562-21.331-21.36-21.331h-42.723z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["zip"],"defaultCode":59871,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1138,"name":"zip","prevSize":32,"id":226,"code":59871},"setIdx":0,"setId":6,"iconIdx":227},{"icon":{"paths":["M373.437 492.374c25.77-8.39 53.667-8.131 79.376 0.906l19.187 6.752c25.293 8.893 52.963 8.275 77.843-1.718l4.877-1.971c26.989-10.842 56.726-12.432 84.592-4.685 2.832 0.787 5.648 1.674 8.438 2.656 22.342 7.856 41.504 21.35 56.25 38.499 17.84 20.742 29.178 46.848 31.533 75.030 0.304 3.645 0.467 7.328 0.467 11.030v117.126c0 9.936-1.51 19.517-4.314 28.531-4.467 14.371-12.275 27.245-22.435 37.843-2.595 2.704-5.296 5.302-8.189 7.69-2.368 1.952-4.822 3.805-7.376 5.53-5.107 3.453-10.57 6.413-16.31 8.845-11.491 4.861-24.115 7.562-37.376 7.562l-260.938-0.125c-3.277-0.166-6.506-0.515-9.686-1.002-7.949-1.213-15.571-3.398-22.752-6.435-5.741-2.432-11.203-5.392-16.31-8.845-2.55-1.725-5.008-3.578-7.376-5.53-2.893-2.387-5.595-4.986-8.188-7.69-10.162-10.598-17.97-23.472-22.437-37.843-2.803-9.014-4.312-18.595-4.313-28.531v-125.968c0-0.675 0.052-1.357 0.062-2.032 0.487-29.827 11.671-57.741 30.531-79.344 12.578-14.41 28.523-26.032 47.032-33.469 2.576-1.034 5.187-1.958 7.811-2.813zM426.374 552.093c-10.461-2.643-21.446-2.406-31.779 0.688-1.728 0.518-3.443 1.104-5.126 1.782-1.757 0.704-3.466 1.488-5.126 2.342-0.115 0.061-0.227 0.128-0.342 0.189-19.514 10.24-31.997 30.573-32 52.938v125.968c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-117.126c-0.003-23.798-12.39-45.472-32-57.718-0.253-0.157-0.525-0.282-0.781-0.435-1.555-0.944-3.142-1.837-4.781-2.656-0.57-0.288-1.139-0.576-1.718-0.845-2.006-0.934-4.070-1.786-6.189-2.531-3.894-1.37-7.878-2.394-11.907-3.030-10.070-1.597-20.403-0.883-30.218 2.061-1.958 0.589-3.901 1.264-5.811 2.032l-4.877 1.936c-9.818 3.946-19.914 6.973-30.157 9.062-12.81 2.618-25.85 3.763-38.874 3.469l-7.814-0.342c-10.406-0.704-20.774-2.333-30.966-4.906-2.547-0.643-5.072-1.366-7.594-2.125-2.522-0.762-5.037-1.562-7.533-2.438l-19.219-6.749c-1.709-0.602-3.443-1.123-5.187-1.565z","M174.188 458.624c19.051-8.506 40.722-9.024 60.156-1.437l7.906 3.094c8.268 3.229 17.489 2.992 25.594-0.624l0.844-0.378c20.012-8.931 42.773-9.469 63.188-1.498 6.358 2.483 12.262 5.722 17.658 9.562-27.331 11.914-50.085 31.030-66.283 54.688-20.961 6.541-43.62 5.914-64.281-2.157l-7.906-3.062c-3.484-1.36-7.366-1.274-10.781 0.25-5.037 2.25-8.281 7.264-8.281 12.781v49.219c0.001 15.981 12.956 28.938 28.938 28.938h35.125c-0.009 0.675-0.062 1.357-0.062 2.032v61.968h-35.062c-51.328 0-92.937-41.61-92.938-92.938v-49.219c0-30.768 18.093-58.672 46.188-71.219z","M878.406 422.813c11.197 14.163 17.594 31.891 17.594 50.563v102.624c0 53.021-42.979 96-96 96h-32v-53.126l-0.125-6.499c-0.058-1.462-0.246-2.922-0.342-4.374h32.467c17.674 0 32-14.326 32-32v-102.624c0-3.12-0.842-6.109-2.342-8.72 13.494-10.003 27.248-21.219 40.374-33.562 2.797-2.634 5.539-5.45 8.374-8.282z","M512.032 192c-0.106 19.205 0.71 40.743 2.938 64.156-0.986-0.045-1.974-0.156-2.97-0.156-35.347 0-64 28.654-64 64s28.653 64 64 64c14.624 0 28.035-4.995 38.813-13.251 12.131 18.838 26.362 35.45 40.406 49.718-21.798 17.213-49.29 27.533-79.219 27.533-70.691 0-128-57.309-128-128 0-70.692 57.338-128 128.032-128z","M256 224c53.019 0 96 42.981 96 96 0 53.021-42.981 96-96 96s-96-42.979-96-96c0-53.019 42.981-96 96-96zM256 288c-17.673 0-32 14.327-32 32s14.327 32 32 32c17.673 0 32-14.326 32-32s-14.327-32-32-32z","M735.997 96c44.746 0 121.2 10.367 153.827 29.086 4.662 18.723 11.184 75.812 0 154.423-11.187 78.625-107.213 145.092-153.824 168.49-46.614-23.402-142.637-89.869-153.824-168.49-11.184-78.609-4.662-135.699 0-154.423 32.627-18.719 109.072-29.084 153.821-29.086z"],"attrs":[{},{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["team-shield"]},"attrs":[{},{},{},{},{},{}],"properties":{"order":14,"id":1,"name":"team-shield","prevSize":32,"code":59877},"setIdx":4,"setId":2,"iconIdx":0},{"icon":{"paths":["M352 128c17.674 0 32 14.327 32 32v160h142.25c7.789 23.664 19.898 45.082 33.718 64h-175.968v256h256v-177.126c23.274 17.472 46 31.267 64 40.563v136.563h160c17.674 0 32 14.326 32 32s-14.326 32-32 32h-160v160c0 17.674-14.326 32-32 32s-32-14.326-32-32v-160h-256v160c0 17.674-14.326 32-32 32s-32-14.326-32-32v-160h-160c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-256h-160c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-160c0-17.673 14.326-32 32-32z","M735.997 96c44.746 0 121.2 10.367 153.827 29.086 4.662 18.723 11.184 75.812 0 154.423-11.187 78.625-107.213 145.092-153.824 168.49-46.614-23.402-142.637-89.869-153.824-168.49-11.184-78.609-4.662-135.699 0-154.423 32.627-18.719 109.072-29.084 153.821-29.086z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["hash-shield"]},"attrs":[{},{}],"properties":{"order":15,"id":0,"name":"hash-shield","prevSize":32,"code":59878},"setIdx":4,"setId":2,"iconIdx":1}],"height":1024,"metadata":{"name":"custom"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"custom","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon","name":"icomoon"},"historySize":50,"showCodes":true,"gridSize":16}} \ No newline at end of file diff --git a/ios/custom.ttf b/ios/custom.ttf index b0758f2fa60ec7d33ab136418ed1aa939022731b..3151388990e26173f1f0b9471ecf479503da664c 100644 GIT binary patch delta 403 zcmbPolX=E1=6VK31_lOhh6V;^1_S?KeItG$c5$G{9w1Ig&P^;354)Vlz`!U2UIGOfZ{#Lc6fpc?RApdzbpt4%ke8U7 zdi9^hS|A^2AY)ZQesKxVp+NAaWa18Y#%Gfly&0cv_F-K6SQ+FGAnwcBzB!)X<|_j? z3rHQ%W`3Z1A@t-KPt6%$Z@%z!4fE!Pmp2#%z@C52sLa3vQo_JAnenag=K9w&83FoE BQMCX7 From ece7e2710e14c2803e1831827c0373aa6afadaf7 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Wed, 14 Jan 2026 14:01:15 -0300 Subject: [PATCH 08/61] Base CallHeader --- app/AppContainer.tsx | 64 +++++----- app/containers/CallHeader/CallHeader.tsx | 86 ++++++++++++++ .../components/HeaderContainer/index.tsx | 9 +- app/lib/services/voip/useCallStore.ts | 1 + app/stacks/InsideStack.tsx | 2 +- app/views/CallView/index.tsx | 111 ++++++++---------- app/views/CallView/styles.ts | 18 +-- 7 files changed, 176 insertions(+), 115 deletions(-) create mode 100644 app/containers/CallHeader/CallHeader.tsx diff --git a/app/AppContainer.tsx b/app/AppContainer.tsx index 001b9d33a0d..8200dcb773f 100644 --- a/app/AppContainer.tsx +++ b/app/AppContainer.tsx @@ -19,6 +19,7 @@ import { ThemeContext } from './theme'; import { setCurrentScreen } from './lib/methods/helpers/log'; import { themes } from './lib/constants/colors'; import { emitter } from './lib/methods/helpers'; +import CallHeader from './containers/CallHeader/CallHeader'; const createStackNavigator = createNativeStackNavigator; @@ -34,6 +35,7 @@ const SetUsernameStack = () => ( const Stack = createStackNavigator(); const App = memo(({ root, isMasterDetail }: { root: string; isMasterDetail: boolean }) => { const { theme } = useContext(ThemeContext); + useEffect(() => { if (root) { const state = Navigation.navigationRef.current?.getRootState(); @@ -50,35 +52,39 @@ const App = memo(({ root, isMasterDetail }: { root: string; isMasterDetail: bool const navTheme = navigationTheme(theme); return ( - { - emitter.emit('navigationReady'); - }} - onStateChange={state => { - const previousRouteName = Navigation.routeNameRef.current; - const currentRouteName = getActiveRouteName(state); - if (previousRouteName !== currentRouteName) { - setCurrentScreen(currentRouteName); - } - Navigation.routeNameRef.current = currentRouteName; - }}> - - {root === RootEnum.ROOT_LOADING || root === RootEnum.ROOT_LOADING_SHARE_EXTENSION ? ( - - ) : null} - {root === RootEnum.ROOT_OUTSIDE ? : null} - {root === RootEnum.ROOT_INSIDE && isMasterDetail ? ( - - ) : null} - {root === RootEnum.ROOT_INSIDE && !isMasterDetail ? : null} - {root === RootEnum.ROOT_SET_USERNAME ? : null} - {root === RootEnum.ROOT_SHARE_EXTENSION ? ( - - ) : null} - - + <> + + { + emitter.emit('navigationReady'); + }} + onStateChange={state => { + const previousRouteName = Navigation.routeNameRef.current; + const currentRouteName = getActiveRouteName(state); + if (previousRouteName !== currentRouteName) { + setCurrentScreen(currentRouteName); + } + Navigation.routeNameRef.current = currentRouteName; + }}> + + {root === RootEnum.ROOT_LOADING || root === RootEnum.ROOT_LOADING_SHARE_EXTENSION ? ( + + ) : null} + {root === RootEnum.ROOT_OUTSIDE ? : null} + {root === RootEnum.ROOT_INSIDE && isMasterDetail ? ( + + ) : null} + {root === RootEnum.ROOT_INSIDE && !isMasterDetail ? : null} + {root === RootEnum.ROOT_SET_USERNAME ? : null} + {root === RootEnum.ROOT_SHARE_EXTENSION ? ( + + ) : null} + + + ); }); const mapStateToProps = (state: any) => ({ diff --git a/app/containers/CallHeader/CallHeader.tsx b/app/containers/CallHeader/CallHeader.tsx new file mode 100644 index 00000000000..7555c986812 --- /dev/null +++ b/app/containers/CallHeader/CallHeader.tsx @@ -0,0 +1,86 @@ +import { StyleSheet, Text, View, Pressable } from 'react-native'; +import { useSafeAreaInsets } from 'react-native-safe-area-context'; + +import { useTheme } from '../../theme'; +import sharedStyles from '../../views/Styles'; +import { simulateCall } from '../../lib/services/voip/simulateCall'; +import { useCallStore } from '../../lib/services/voip/useCallStore'; +import I18n from '../../i18n'; +import { CustomIcon } from '../CustomIcon'; + +const styles = StyleSheet.create({ + header: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 12, + paddingBottom: 12, + borderBottomWidth: StyleSheet.hairlineWidth + }, + headerTitle: { + ...sharedStyles.textSemibold, + fontSize: 16, + lineHeight: 24 + }, + headerButton: { + // padding: 8 + } +}); + +const CallHeader = () => { + const { colors } = useTheme(); + const insets = useSafeAreaInsets(); + + // const call = useCallStore(state => state.call); + const callState = useCallStore(state => state.callState); + const callStartTime = useCallStore(state => state.callStartTime); + const contact = useCallStore(state => state.contact); + const endCall = useCallStore(state => state.endCall); + const callDuration = '00:00'; + + // const handlePress = () => { + // simulateCall(); + // }; + + const handleCollapse = () => { + simulateCall(); + }; + + const handleEndCall = () => { + endCall(); + }; + + const callerName = contact.displayName || contact.username || I18n.t('Unknown'); + const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; + const isConnected = callState === 'active'; + + const getHeaderTitle = () => { + if (isConnecting) { + return I18n.t('Connecting'); + } + if (isConnected && callStartTime) { + return `${callerName} – ${callDuration}`; + } + return callerName; + }; + + return ( + + + + + + {getHeaderTitle()} + + + + + + ); +}; + +export default CallHeader; diff --git a/app/containers/Header/components/HeaderContainer/index.tsx b/app/containers/Header/components/HeaderContainer/index.tsx index bd7cb3ae5b0..60c6f132aa9 100644 --- a/app/containers/Header/components/HeaderContainer/index.tsx +++ b/app/containers/Header/components/HeaderContainer/index.tsx @@ -1,5 +1,5 @@ import React, { memo } from 'react'; -import { useWindowDimensions, View, type ViewProps, StyleSheet } from 'react-native'; +import { useWindowDimensions, View, type ViewProps, StyleSheet, Text } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useTheme } from '../../../../theme'; @@ -28,9 +28,9 @@ const HeaderContainer = memo( - {children} + {/* HeaderContainer content */} + {children} ); } diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index 373eca56091..1dd41cf3c3a 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -158,6 +158,7 @@ export const useCallStore = create((set, get) => ({ } get().reset(); + Navigation.back(); }, reset: () => { diff --git a/app/stacks/InsideStack.tsx b/app/stacks/InsideStack.tsx index 26001ec28d2..e77444470cb 100644 --- a/app/stacks/InsideStack.tsx +++ b/app/stacks/InsideStack.tsx @@ -340,7 +340,7 @@ const InsideStackNavigator = () => { {/* @ts-ignore */} - + ); }; diff --git a/app/views/CallView/index.tsx b/app/views/CallView/index.tsx index d9480a58cb2..0eac9cfc1e4 100644 --- a/app/views/CallView/index.tsx +++ b/app/views/CallView/index.tsx @@ -1,7 +1,5 @@ import React, { useEffect } from 'react'; import { Text, View, Pressable } from 'react-native'; -import { SafeAreaView } from 'react-native-safe-area-context'; -import { useNavigation } from '@react-navigation/native'; import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake'; import I18n from '../../i18n'; @@ -15,7 +13,6 @@ import { styles } from './styles'; import { useTheme } from '../../theme'; const CallView = (): React.ReactElement | null => { - const { goBack } = useNavigation(); const { colors } = useTheme(); // Get state from store @@ -63,7 +60,6 @@ const CallView = (): React.ReactElement | null => { const handleEndCall = () => { endCall(); - goBack(); }; if (!call) { @@ -85,71 +81,56 @@ const CallView = (): React.ReactElement | null => { }; return ( - - - {/* Header */} - - - - - - {getHeaderTitle()} - - - - + + {/* Caller Info */} + + + {/* Status Text */} + {isConnected && } + + {/* Action Buttons */} + + {/* First row of buttons */} + + + + - {/* Caller Info */} - - - {/* Status Text */} - {isConnected && } - - {/* Action Buttons */} - - {/* First row of buttons */} - - - - - - - {/* Second row of buttons */} - - - - - + {/* Second row of buttons */} + + + + - + ); }; diff --git a/app/views/CallView/styles.ts b/app/views/CallView/styles.ts index f8a38027c53..1b8261d7cd8 100644 --- a/app/views/CallView/styles.ts +++ b/app/views/CallView/styles.ts @@ -4,27 +4,13 @@ import sharedStyles from '../Styles'; export const styles = StyleSheet.create({ container: { - flex: 1 + flex: 1, + backgroundColor: 'red' }, contentContainer: { flex: 1, justifyContent: 'space-between' }, - header: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - paddingHorizontal: 16, - paddingVertical: 12 - }, - headerTitle: { - ...sharedStyles.textSemibold, - fontSize: 16, - lineHeight: 24 - }, - headerButton: { - padding: 8 - }, callerInfoContainer: { flex: 1, alignItems: 'center', From c3dd2aee510e5af09cb50c775b25ca197a124cf4 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Wed, 14 Jan 2026 14:11:31 -0300 Subject: [PATCH 09/61] toggleFocus --- app/containers/CallHeader/CallHeader.tsx | 8 +++----- app/lib/services/voip/simulateCall.ts | 2 +- app/lib/services/voip/useCallStore.ts | 17 +++++++++++++++-- app/sagas/login.js | 2 ++ .../RoomView/components/HeaderCallButton.tsx | 5 +++-- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/app/containers/CallHeader/CallHeader.tsx b/app/containers/CallHeader/CallHeader.tsx index 7555c986812..6ee3d589b86 100644 --- a/app/containers/CallHeader/CallHeader.tsx +++ b/app/containers/CallHeader/CallHeader.tsx @@ -7,6 +7,7 @@ import { simulateCall } from '../../lib/services/voip/simulateCall'; import { useCallStore } from '../../lib/services/voip/useCallStore'; import I18n from '../../i18n'; import { CustomIcon } from '../CustomIcon'; +import Navigation from '../../lib/navigation/appNavigation'; const styles = StyleSheet.create({ header: { @@ -36,14 +37,11 @@ const CallHeader = () => { const callStartTime = useCallStore(state => state.callStartTime); const contact = useCallStore(state => state.contact); const endCall = useCallStore(state => state.endCall); + const toggleFocus = useCallStore(state => state.toggleFocus); const callDuration = '00:00'; - // const handlePress = () => { - // simulateCall(); - // }; - const handleCollapse = () => { - simulateCall(); + toggleFocus(); }; const handleEndCall = () => { diff --git a/app/lib/services/voip/simulateCall.ts b/app/lib/services/voip/simulateCall.ts index 1777563288d..d59611a68d4 100644 --- a/app/lib/services/voip/simulateCall.ts +++ b/app/lib/services/voip/simulateCall.ts @@ -102,5 +102,5 @@ export const simulateCall = async (options: SimulateCallOptions = {}): Promise void; toggleHold: () => void; toggleSpeaker: () => void; + toggleFocus: () => void; endCall: () => void; reset: () => void; } @@ -47,7 +49,8 @@ const initialState: CallStoreState = { isOnHold: false, isSpeakerOn: false, callStartTime: null, - contact: {} + contact: {}, + focused: false }; export const useCallStore = create((set, get) => ({ @@ -142,6 +145,16 @@ export const useCallStore = create((set, get) => ({ set({ isSpeakerOn: !isSpeakerOn }); }, + toggleFocus: () => { + const isFocused = get().focused; + set({ focused: !isFocused }); + if (isFocused) { + Navigation.back(); + } else { + Navigation.navigate('CallView', { callUUID: get().callUUID }); + } + }, + endCall: () => { const { call, callState, callUUID } = get(); @@ -158,7 +171,7 @@ export const useCallStore = create((set, get) => ({ } get().reset(); - Navigation.back(); + Navigation.back(); // TODO: It could be collapsed, so going back woudln't make sense }, reset: () => { diff --git a/app/sagas/login.js b/app/sagas/login.js index 17eeae96473..99ee557cb8d 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -43,6 +43,7 @@ import appNavigation from '../lib/navigation/appNavigation'; import { showActionSheetRef } from '../containers/ActionSheet'; import { SupportedVersionsWarning } from '../containers/SupportedVersions'; import { mediaSessionInstance } from '../lib/services/voip/MediaSessionInstance'; +import { simulateCall } from '../lib/services/voip/simulateCall'; const getServer = state => state.server.server; const loginWithPasswordCall = args => loginWithPassword(args); @@ -271,6 +272,7 @@ const startVoipFork = function* startVoipFork() { yield call(initCallKeep); const userId = yield select(state => state.login.user.id); mediaSessionInstance.init(userId); + simulateCall(); } catch (e) { log(e); } diff --git a/app/views/RoomView/components/HeaderCallButton.tsx b/app/views/RoomView/components/HeaderCallButton.tsx index f62e9bca798..28c7cbcc455 100644 --- a/app/views/RoomView/components/HeaderCallButton.tsx +++ b/app/views/RoomView/components/HeaderCallButton.tsx @@ -2,7 +2,7 @@ import React from 'react'; import * as HeaderButton from '../../../containers/Header/components/HeaderButton'; import { useVideoConf } from '../../../lib/hooks/useVideoConf'; -import { simulateCall } from '../../../lib/services/voip/simulateCall'; +import { useCallStore } from '../../../lib/services/voip/useCallStore'; export const HeaderCallButton = ({ rid, @@ -26,12 +26,13 @@ export const HeaderCallButton = ({ // /> // ); // return null; + const toggleFocus = useCallStore(state => state.toggleFocus); return ( simulateCall()} + onPress={() => toggleFocus()} testID='room-view-header-call' /> ); From 1df1b292c8075d1096c151f6c632e24a712e6cd4 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Wed, 14 Jan 2026 14:16:02 -0300 Subject: [PATCH 10/61] collapse buttons --- app/containers/CallHeader/CallHeader.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/containers/CallHeader/CallHeader.tsx b/app/containers/CallHeader/CallHeader.tsx index 6ee3d589b86..0f45c7c6905 100644 --- a/app/containers/CallHeader/CallHeader.tsx +++ b/app/containers/CallHeader/CallHeader.tsx @@ -37,6 +37,7 @@ const CallHeader = () => { const callStartTime = useCallStore(state => state.callStartTime); const contact = useCallStore(state => state.contact); const endCall = useCallStore(state => state.endCall); + const focused = useCallStore(state => state.focused); const toggleFocus = useCallStore(state => state.toggleFocus); const callDuration = '00:00'; @@ -69,7 +70,7 @@ const CallHeader = () => { { backgroundColor: colors.surfaceNeutral, paddingTop: insets.top, borderBottomColor: colors.strokeLight } ]}> - + {getHeaderTitle()} From 8f9129e77d9f2b74dc365a394b10ce09e411d56b Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Wed, 14 Jan 2026 14:34:05 -0300 Subject: [PATCH 11/61] Header components --- app/containers/CallHeader/CallHeader.tsx | 62 +++---------------- .../CallHeader/components/Collapse.tsx | 22 +++++++ .../CallHeader/components/EndCall.tsx | 16 +++++ .../CallHeader/components/Title.tsx | 44 +++++++++++++ 4 files changed, 90 insertions(+), 54 deletions(-) create mode 100644 app/containers/CallHeader/components/Collapse.tsx create mode 100644 app/containers/CallHeader/components/EndCall.tsx create mode 100644 app/containers/CallHeader/components/Title.tsx diff --git a/app/containers/CallHeader/CallHeader.tsx b/app/containers/CallHeader/CallHeader.tsx index 0f45c7c6905..d6704a01767 100644 --- a/app/containers/CallHeader/CallHeader.tsx +++ b/app/containers/CallHeader/CallHeader.tsx @@ -1,13 +1,10 @@ -import { StyleSheet, Text, View, Pressable } from 'react-native'; +import { StyleSheet, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useTheme } from '../../theme'; -import sharedStyles from '../../views/Styles'; -import { simulateCall } from '../../lib/services/voip/simulateCall'; -import { useCallStore } from '../../lib/services/voip/useCallStore'; -import I18n from '../../i18n'; -import { CustomIcon } from '../CustomIcon'; -import Navigation from '../../lib/navigation/appNavigation'; +import Collapse from './components/Collapse'; +import Title from './components/Title'; +import EndCall from './components/EndCall'; const styles = StyleSheet.create({ header: { @@ -15,16 +12,8 @@ const styles = StyleSheet.create({ justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 12, - paddingBottom: 12, + paddingBottom: 4, borderBottomWidth: StyleSheet.hairlineWidth - }, - headerTitle: { - ...sharedStyles.textSemibold, - fontSize: 16, - lineHeight: 24 - }, - headerButton: { - // padding: 8 } }); @@ -33,35 +22,6 @@ const CallHeader = () => { const insets = useSafeAreaInsets(); // const call = useCallStore(state => state.call); - const callState = useCallStore(state => state.callState); - const callStartTime = useCallStore(state => state.callStartTime); - const contact = useCallStore(state => state.contact); - const endCall = useCallStore(state => state.endCall); - const focused = useCallStore(state => state.focused); - const toggleFocus = useCallStore(state => state.toggleFocus); - const callDuration = '00:00'; - - const handleCollapse = () => { - toggleFocus(); - }; - - const handleEndCall = () => { - endCall(); - }; - - const callerName = contact.displayName || contact.username || I18n.t('Unknown'); - const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; - const isConnected = callState === 'active'; - - const getHeaderTitle = () => { - if (isConnecting) { - return I18n.t('Connecting'); - } - if (isConnected && callStartTime) { - return `${callerName} – ${callDuration}`; - } - return callerName; - }; return ( { styles.header, { backgroundColor: colors.surfaceNeutral, paddingTop: insets.top, borderBottomColor: colors.strokeLight } ]}> - - - - - {getHeaderTitle()} - - - - + + + <EndCall /> </View> ); }; diff --git a/app/containers/CallHeader/components/Collapse.tsx b/app/containers/CallHeader/components/Collapse.tsx new file mode 100644 index 00000000000..0be095d93dc --- /dev/null +++ b/app/containers/CallHeader/components/Collapse.tsx @@ -0,0 +1,22 @@ +import I18n from '../../../i18n'; +import { useTheme } from '../../../theme'; +import { useCallStore } from '../../../lib/services/voip/useCallStore'; +import * as HeaderButton from '../../Header/components/HeaderButton'; + +const Collapse = () => { + const { colors } = useTheme(); + const focused = useCallStore(state => state.focused); + const toggleFocus = useCallStore(state => state.toggleFocus); + return ( + <HeaderButton.Container left> + <HeaderButton.Item + accessibilityLabel={I18n.t('Minimize')} + onPress={toggleFocus} + iconName={focused ? 'arrow-collapse' : 'arrow-expand'} + color={colors.fontDefault} + /> + </HeaderButton.Container> + ); +}; + +export default Collapse; diff --git a/app/containers/CallHeader/components/EndCall.tsx b/app/containers/CallHeader/components/EndCall.tsx new file mode 100644 index 00000000000..54538ed7ebb --- /dev/null +++ b/app/containers/CallHeader/components/EndCall.tsx @@ -0,0 +1,16 @@ +import I18n from '../../../i18n'; +import { useTheme } from '../../../theme'; +import { useCallStore } from '../../../lib/services/voip/useCallStore'; +import * as HeaderButton from '../../Header/components/HeaderButton'; + +const EndCall = () => { + const { colors } = useTheme(); + const endCall = useCallStore(state => state.endCall); + return ( + <HeaderButton.Container> + <HeaderButton.Item accessibilityLabel={I18n.t('End')} onPress={endCall} iconName='phone-end' color={colors.fontDanger} /> + </HeaderButton.Container> + ); +}; + +export default EndCall; diff --git a/app/containers/CallHeader/components/Title.tsx b/app/containers/CallHeader/components/Title.tsx new file mode 100644 index 00000000000..3b993e3d7d5 --- /dev/null +++ b/app/containers/CallHeader/components/Title.tsx @@ -0,0 +1,44 @@ +import { StyleSheet, Text } from 'react-native'; + +import { useTheme } from '../../../theme'; +import { useCallStore } from '../../../lib/services/voip/useCallStore'; +import I18n from '../../../i18n'; +import sharedStyles from '../../../views/Styles'; + +const styles = StyleSheet.create({ + headerTitle: { + ...sharedStyles.textSemibold, + fontSize: 16, + lineHeight: 24 + } +}); + +const Title = () => { + const { colors } = useTheme(); + const callState = useCallStore(state => state.callState); + const callStartTime = useCallStore(state => state.callStartTime); + const contact = useCallStore(state => state.contact); + + const callerName = contact.displayName || contact.username || I18n.t('Unknown'); + const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; + const isConnected = callState === 'active'; + const callDuration = '00:00'; + + const getHeaderTitle = () => { + if (isConnecting) { + return I18n.t('Connecting'); + } + if (isConnected && callStartTime) { + return `${callerName} – ${callDuration}`; + } + return callerName; + }; + + return ( + <Text style={[styles.headerTitle, { color: colors.fontDefault }]} testID='call-view-header-title'> + {getHeaderTitle()} + </Text> + ); +}; + +export default Title; From 8a5de040ee9ab05c063bb1eaa3a495c588e52364 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 14 Jan 2026 14:42:42 -0300 Subject: [PATCH 12/61] Hide header when no call --- app/containers/CallHeader/CallHeader.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/containers/CallHeader/CallHeader.tsx b/app/containers/CallHeader/CallHeader.tsx index d6704a01767..4c21d459a19 100644 --- a/app/containers/CallHeader/CallHeader.tsx +++ b/app/containers/CallHeader/CallHeader.tsx @@ -5,6 +5,7 @@ import { useTheme } from '../../theme'; import Collapse from './components/Collapse'; import Title from './components/Title'; import EndCall from './components/EndCall'; +import { useCallStore } from '../../lib/services/voip/useCallStore'; const styles = StyleSheet.create({ header: { @@ -21,14 +22,18 @@ const CallHeader = () => { const { colors } = useTheme(); const insets = useSafeAreaInsets(); - // const call = useCallStore(state => state.call); + const defaultHeaderStyle = { + backgroundColor: colors.surfaceNeutral, + paddingTop: insets.top + }; + + const call = useCallStore(state => state.call); + if (!call) { + return <View style={defaultHeaderStyle} />; + } return ( - <View - style={[ - styles.header, - { backgroundColor: colors.surfaceNeutral, paddingTop: insets.top, borderBottomColor: colors.strokeLight } - ]}> + <View style={[styles.header, { ...defaultHeaderStyle, borderBottomColor: colors.strokeLight }]}> <Collapse /> <Title /> <EndCall /> From a9ec70dcb6db611ed1ab5aaaec25cd59894f1d68 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 14 Jan 2026 15:14:36 -0300 Subject: [PATCH 13/61] Timer --- .../CallHeader/components/Timer.tsx | 33 +++++++++++++++++++ .../CallHeader/components/Title.tsx | 5 +-- 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 app/containers/CallHeader/components/Timer.tsx diff --git a/app/containers/CallHeader/components/Timer.tsx b/app/containers/CallHeader/components/Timer.tsx new file mode 100644 index 00000000000..8c5c6b307d7 --- /dev/null +++ b/app/containers/CallHeader/components/Timer.tsx @@ -0,0 +1,33 @@ +import { useEffect, useState } from 'react'; +import { Text } from 'react-native'; + +import { useCallStore } from '../../../lib/services/voip/useCallStore'; + +const formatDuration = (seconds: number): string => { + const hours = Math.floor(seconds / 3600); + const mins = Math.floor((seconds % 3600) / 60); + const secs = seconds % 60; + const hoursStr = hours > 0 ? `${hours.toString().padStart(2, '0')}:` : ''; + return `${hoursStr}${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; +}; + +const Timer = () => { + const callStartTime = useCallStore(state => state.callStartTime); + const [duration, setDuration] = useState(callStartTime ? Math.floor((new Date().getTime() - callStartTime) / 1000) : 0); + + useEffect(() => { + if (!callStartTime) { + return; + } + const updateDuration = () => { + setDuration(Math.floor((Date.now() - callStartTime) / 1000)); + }; + updateDuration(); + const interval = setInterval(updateDuration, 1000); + return () => clearInterval(interval); + }, [callStartTime]); + + return <Text>{formatDuration(duration)}</Text>; +}; + +export default Timer; diff --git a/app/containers/CallHeader/components/Title.tsx b/app/containers/CallHeader/components/Title.tsx index 3b993e3d7d5..baeff2d2206 100644 --- a/app/containers/CallHeader/components/Title.tsx +++ b/app/containers/CallHeader/components/Title.tsx @@ -4,6 +4,7 @@ import { useTheme } from '../../../theme'; import { useCallStore } from '../../../lib/services/voip/useCallStore'; import I18n from '../../../i18n'; import sharedStyles from '../../../views/Styles'; +import Timer from './Timer'; const styles = StyleSheet.create({ headerTitle: { @@ -22,14 +23,13 @@ const Title = () => { const callerName = contact.displayName || contact.username || I18n.t('Unknown'); const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; const isConnected = callState === 'active'; - const callDuration = '00:00'; const getHeaderTitle = () => { if (isConnecting) { return I18n.t('Connecting'); } if (isConnected && callStartTime) { - return `${callerName} – ${callDuration}`; + return `${callerName} – `; } return callerName; }; @@ -37,6 +37,7 @@ const Title = () => { return ( <Text style={[styles.headerTitle, { color: colors.fontDefault }]} testID='call-view-header-title'> {getHeaderTitle()} + <Timer /> </Text> ); }; From d6229d9fd51d460053c3dc7afbfdc965a8baeb8f Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 14 Jan 2026 15:16:02 -0300 Subject: [PATCH 14/61] Add use memo --- app/containers/CallHeader/CallHeader.tsx | 2 ++ app/containers/CallHeader/components/Collapse.tsx | 2 ++ app/containers/CallHeader/components/EndCall.tsx | 2 ++ app/containers/CallHeader/components/Timer.tsx | 2 ++ app/containers/CallHeader/components/Title.tsx | 2 ++ 5 files changed, 10 insertions(+) diff --git a/app/containers/CallHeader/CallHeader.tsx b/app/containers/CallHeader/CallHeader.tsx index 4c21d459a19..37f4f2d61ed 100644 --- a/app/containers/CallHeader/CallHeader.tsx +++ b/app/containers/CallHeader/CallHeader.tsx @@ -19,6 +19,8 @@ const styles = StyleSheet.create({ }); const CallHeader = () => { + 'use memo'; + const { colors } = useTheme(); const insets = useSafeAreaInsets(); diff --git a/app/containers/CallHeader/components/Collapse.tsx b/app/containers/CallHeader/components/Collapse.tsx index 0be095d93dc..6332df73287 100644 --- a/app/containers/CallHeader/components/Collapse.tsx +++ b/app/containers/CallHeader/components/Collapse.tsx @@ -4,6 +4,8 @@ import { useCallStore } from '../../../lib/services/voip/useCallStore'; import * as HeaderButton from '../../Header/components/HeaderButton'; const Collapse = () => { + 'use memo'; + const { colors } = useTheme(); const focused = useCallStore(state => state.focused); const toggleFocus = useCallStore(state => state.toggleFocus); diff --git a/app/containers/CallHeader/components/EndCall.tsx b/app/containers/CallHeader/components/EndCall.tsx index 54538ed7ebb..09f4caa10b3 100644 --- a/app/containers/CallHeader/components/EndCall.tsx +++ b/app/containers/CallHeader/components/EndCall.tsx @@ -4,6 +4,8 @@ import { useCallStore } from '../../../lib/services/voip/useCallStore'; import * as HeaderButton from '../../Header/components/HeaderButton'; const EndCall = () => { + 'use memo'; + const { colors } = useTheme(); const endCall = useCallStore(state => state.endCall); return ( diff --git a/app/containers/CallHeader/components/Timer.tsx b/app/containers/CallHeader/components/Timer.tsx index 8c5c6b307d7..fa784cf864e 100644 --- a/app/containers/CallHeader/components/Timer.tsx +++ b/app/containers/CallHeader/components/Timer.tsx @@ -12,6 +12,8 @@ const formatDuration = (seconds: number): string => { }; const Timer = () => { + 'use memo'; + const callStartTime = useCallStore(state => state.callStartTime); const [duration, setDuration] = useState(callStartTime ? Math.floor((new Date().getTime() - callStartTime) / 1000) : 0); diff --git a/app/containers/CallHeader/components/Title.tsx b/app/containers/CallHeader/components/Title.tsx index baeff2d2206..9ed5e46a661 100644 --- a/app/containers/CallHeader/components/Title.tsx +++ b/app/containers/CallHeader/components/Title.tsx @@ -15,6 +15,8 @@ const styles = StyleSheet.create({ }); const Title = () => { + 'use memo'; + const { colors } = useTheme(); const callState = useCallStore(state => state.callState); const callStartTime = useCallStore(state => state.callStartTime); From e7185612e86fb428e405eac526286ce7bb836725 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 14 Jan 2026 15:38:05 -0300 Subject: [PATCH 15/61] Add voice call item on sidebar --- app/i18n/locales/en.json | 1 + app/lib/services/voip/simulateCall.ts | 2 +- app/lib/services/voip/useCallStore.ts | 2 +- app/views/SidebarView/components/Stacks.tsx | 18 +++++++++++++--- app/views/SidebarView/index.tsx | 23 ++++++++------------- 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index c422c088149..df2a68a2a56 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -979,6 +979,7 @@ "video-conf-provider-not-configured-header": "Conference call not enabled", "View_Original": "View original", "View_Thread": "View thread", + "Voice_call": "Voice call", "Wait_activation_warning": "Before you can login, your account must be manually activated by an administrator.", "Waiting_for_answer": "Waiting for answer", "Waiting_for_network": "Waiting for network...", diff --git a/app/lib/services/voip/simulateCall.ts b/app/lib/services/voip/simulateCall.ts index d59611a68d4..5ce82715db6 100644 --- a/app/lib/services/voip/simulateCall.ts +++ b/app/lib/services/voip/simulateCall.ts @@ -1,7 +1,7 @@ import type { CallState, IClientMediaCall } from '@rocket.chat/media-signaling'; import { randomUuid } from '@rocket.chat/mobile-crypto'; -import Navigation from '../../navigation/appNavigation'; +// import Navigation from '../../navigation/appNavigation'; import { useCallStore } from './useCallStore'; interface SimulateCallOptions { diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index 9fbafb9559a..38eb606718d 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -170,8 +170,8 @@ export const useCallStore = create<CallStore>((set, get) => ({ RNCallKeep.endCall(callUUID); } + // Navigation.back(); // TODO: It could be collapsed, so going back woudln't make sense get().reset(); - Navigation.back(); // TODO: It could be collapsed, so going back woudln't make sense }, reset: () => { diff --git a/app/views/SidebarView/components/Stacks.tsx b/app/views/SidebarView/components/Stacks.tsx index 7b3d5e4cfa4..556c74d6921 100644 --- a/app/views/SidebarView/components/Stacks.tsx +++ b/app/views/SidebarView/components/Stacks.tsx @@ -1,15 +1,16 @@ -import { memo } from 'react'; - import { useTheme } from '../../../theme'; import * as List from '../../../containers/List'; import { sidebarNavigate } from '../methods/sidebarNavigate'; import { useAppSelector } from '../../../lib/hooks/useAppSelector'; +import { simulateCall } from '../../../lib/services/voip/simulateCall'; +import { useCallStore } from '../../../lib/services/voip/useCallStore'; const Stacks = ({ currentScreen }: { currentScreen: string | null }) => { 'use memo'; const { colors } = useTheme(); const isMasterDetail = useAppSelector(state => state.app.isMasterDetail); + const toggleFocus = useCallStore(state => state.toggleFocus); if (isMasterDetail) { return null; @@ -25,6 +26,17 @@ const Stacks = ({ currentScreen }: { currentScreen: string | null }) => { testID='sidebar-chats' /> <List.Separator /> + <List.Item + title={'Voice_call'} + left={() => <List.Icon name='phone' />} + onPress={() => { + simulateCall(); + toggleFocus(); + }} + // backgroundColor={currentScreen === 'ChatsStackNavigator' ? colors.strokeLight : undefined} + testID='sidebar-voice-call' + /> + <List.Separator /> <List.Item title={'Profile'} left={() => <List.Icon name='user' />} @@ -52,4 +64,4 @@ const Stacks = ({ currentScreen }: { currentScreen: string | null }) => { </> ); }; -export default memo(Stacks); +export default Stacks; diff --git a/app/views/SidebarView/index.tsx b/app/views/SidebarView/index.tsx index 8e870cfba1e..f65fd4050be 100644 --- a/app/views/SidebarView/index.tsx +++ b/app/views/SidebarView/index.tsx @@ -1,13 +1,11 @@ -import { memo, useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { type DrawerNavigationProp } from '@react-navigation/drawer'; import { ScrollView } from 'react-native'; import scrollPersistTaps from '../../lib/methods/helpers/scrollPersistTaps'; -import SafeAreaView from '../../containers/SafeAreaView'; import styles from './styles'; import { type DrawerParamList } from '../../stacks/types'; import SupportedVersionsWarnItem from './components/SupportedVersionsWarnItem'; -import { useAppSelector } from '../../lib/hooks/useAppSelector'; import CustomStatus from './components/CustomStatus'; import Stacks from './components/Stacks'; import Admin from './components/Admin'; @@ -16,7 +14,6 @@ import Profile from './components/Profile'; const SidebarView = ({ navigation }: { navigation: DrawerNavigationProp<DrawerParamList> }) => { 'use memo'; - const isMasterDetail = useAppSelector(state => state.app.isMasterDetail); const [currentScreen, setCurrentScreen] = useState<string | null>(null); useEffect(() => { @@ -28,16 +25,14 @@ const SidebarView = ({ navigation }: { navigation: DrawerNavigationProp<DrawerPa }, [navigation]); return ( - <SafeAreaView testID='sidebar-view' vertical={isMasterDetail}> - <ScrollView style={styles.container} {...scrollPersistTaps}> - <Profile navigation={navigation} /> - <SupportedVersionsWarnItem /> - <CustomStatus /> - <Stacks currentScreen={currentScreen} /> - <Admin currentScreen={currentScreen} /> - </ScrollView> - </SafeAreaView> + <ScrollView style={styles.container} {...scrollPersistTaps}> + <Profile navigation={navigation} /> + <SupportedVersionsWarnItem /> + <CustomStatus /> + <Stacks currentScreen={currentScreen} /> + <Admin currentScreen={currentScreen} /> + </ScrollView> ); }; -export default memo(SidebarView); +export default SidebarView; From 26502cbc34a5166659c0e0eec73bedc95595383c Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 14 Jan 2026 16:16:33 -0300 Subject: [PATCH 16/61] cleanup --- __mocks__/react-native-callkeep.js | 10 + .../components/HeaderContainer/index.tsx | 58 +- app/lib/services/voip/MediaSessionStore.ts | 9 +- app/lib/store/index.ts | 2 +- app/sagas/login.js | 1 - app/views/CallView/CallView.stories.tsx | 6 +- .../__snapshots__/index.test.tsx.snap | 4850 +++++++++++++++++ .../components/CallActionButton.stories.tsx | 2 - app/views/CallView/components/CallTimer.tsx | 30 - .../components/CallerInfo.stories.tsx | 8 +- .../CallView/components/CallerInfo.test.tsx | 20 +- .../CallActionButton.test.tsx.snap | 1066 ++++ .../__snapshots__/CallerInfo.test.tsx.snap | 758 +++ app/views/CallView/index.test.tsx | 412 ++ app/views/CallView/index.tsx | 28 +- .../RoomView/components/HeaderCallButton.tsx | 4 +- 16 files changed, 7140 insertions(+), 124 deletions(-) create mode 100644 __mocks__/react-native-callkeep.js create mode 100644 app/views/CallView/__snapshots__/index.test.tsx.snap delete mode 100644 app/views/CallView/components/CallTimer.tsx create mode 100644 app/views/CallView/components/__snapshots__/CallActionButton.test.tsx.snap create mode 100644 app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap create mode 100644 app/views/CallView/index.test.tsx diff --git a/__mocks__/react-native-callkeep.js b/__mocks__/react-native-callkeep.js new file mode 100644 index 00000000000..af4dfea2c9a --- /dev/null +++ b/__mocks__/react-native-callkeep.js @@ -0,0 +1,10 @@ +export default { + setup: jest.fn(), + canMakeMultipleCalls: jest.fn(), + displayIncomingCall: jest.fn(), + endCall: jest.fn(), + setCurrentCallActive: jest.fn(), + addEventListener: jest.fn((event, callback) => ({ + remove: jest.fn() + })) +}; diff --git a/app/containers/Header/components/HeaderContainer/index.tsx b/app/containers/Header/components/HeaderContainer/index.tsx index 60c6f132aa9..b1f6a402212 100644 --- a/app/containers/Header/components/HeaderContainer/index.tsx +++ b/app/containers/Header/components/HeaderContainer/index.tsx @@ -1,5 +1,5 @@ import React, { memo } from 'react'; -import { useWindowDimensions, View, type ViewProps, StyleSheet, Text } from 'react-native'; +import { View, type ViewProps, StyleSheet } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useTheme } from '../../../../theme'; @@ -11,38 +11,32 @@ interface IHeaderContainer extends ViewProps { customRightIcon?: boolean; } -const HeaderContainer = memo( - ({ addExtraNotchPadding = false, isMasterDetail = false, customRightIcon, customLeftIcon, children }: IHeaderContainer) => { - 'use memo'; +const HeaderContainer = memo(({ isMasterDetail = false, customRightIcon, customLeftIcon, children }: IHeaderContainer) => { + 'use memo'; - const insets = useSafeAreaInsets(); - const { colors } = useTheme(); - const { height, width } = useWindowDimensions(); - const isPortrait = height > width; - const paddingTop = isPortrait && !isMasterDetail ? 0 : 4; - const paddingBottom = 4; - const statusBarPadding = addExtraNotchPadding ? insets.top : 0; - const paddingRight = isMasterDetail || !customRightIcon ? 4 : 16; + const insets = useSafeAreaInsets(); + const { colors } = useTheme(); + const paddingTop = 4; + const paddingBottom = 4; + const paddingRight = isMasterDetail || !customRightIcon ? 4 : 16; - return ( - <View - style={{ - alignItems: 'center', - // flexDirection: 'row', - paddingBottom, - // paddingTop: statusBarPadding + paddingTop, - paddingRight: paddingRight + insets.right, - paddingLeft: insets.left + (customLeftIcon ? 10 : 4), - gap: isMasterDetail ? 4 : 12, - backgroundColor: colors.surfaceNeutral, - borderBottomWidth: StyleSheet.hairlineWidth, - borderBottomColor: colors.strokeLight - }}> - {/* <Text>HeaderContainer content</Text> */} - <View style={{ flexDirection: 'row' }}>{children}</View> - </View> - ); - } -); + return ( + <View + style={{ + alignItems: 'center', + flexDirection: 'row', + paddingBottom, + paddingTop, + paddingRight: paddingRight + insets.right, + paddingLeft: insets.left + (customLeftIcon ? 10 : 4), + gap: isMasterDetail ? 4 : 12, + backgroundColor: colors.surfaceNeutral, + borderBottomWidth: StyleSheet.hairlineWidth, + borderBottomColor: colors.strokeLight + }}> + {children} + </View> + ); +}); export default HeaderContainer; diff --git a/app/lib/services/voip/MediaSessionStore.ts b/app/lib/services/voip/MediaSessionStore.ts index 6f09cde2216..8fabe247350 100644 --- a/app/lib/services/voip/MediaSessionStore.ts +++ b/app/lib/services/voip/MediaSessionStore.ts @@ -7,7 +7,6 @@ import type { MediaCallWebRTCProcessor } from '@rocket.chat/media-signaling'; import { mediaDevices } from 'react-native-webrtc'; -import BackgroundTimer from 'react-native-background-timer'; import { MediaCallLogger } from './MediaCallLogger'; @@ -61,13 +60,7 @@ class MediaSessionStore extends Emitter<{ change: void }> { }, mediaStreamFactory: (constraints: any) => mediaDevices.getUserMedia(constraints) as unknown as Promise<MediaStream>, randomStringFactory, - logger: new MediaCallLogger(), - timerProcessor: { - setInterval: (callback: () => void, interval: number) => BackgroundTimer.setInterval(callback, interval), - clearInterval: (interval: number) => BackgroundTimer.clearInterval(interval), - setTimeout: (callback: () => void, timeout: number) => BackgroundTimer.setTimeout(callback, timeout), - clearTimeout: (timeout: number) => BackgroundTimer.clearTimeout(timeout) - } + logger: new MediaCallLogger() }); this.change(); diff --git a/app/lib/store/index.ts b/app/lib/store/index.ts index 25011f0f648..49ca36e1ff0 100644 --- a/app/lib/store/index.ts +++ b/app/lib/store/index.ts @@ -5,7 +5,7 @@ import reducers from '../../reducers'; import sagas from '../../sagas'; import applyAppStateMiddleware from './appStateMiddleware'; import applyInternetStateMiddleware from './internetStateMiddleware'; -import { logger } from './reduxLogger'; +// import { logger } from './reduxLogger'; let sagaMiddleware; let enhancers; diff --git a/app/sagas/login.js b/app/sagas/login.js index 99ee557cb8d..11fbb47408a 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -4,7 +4,6 @@ import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import { Q } from '@nozbe/watermelondb'; import RNCallKeep from 'react-native-callkeep'; import { PermissionsAndroid } from 'react-native'; -import BackgroundTimer from 'react-native-background-timer'; import dayjs from '../lib/dayjs'; import * as types from '../actions/actionsTypes'; diff --git a/app/views/CallView/CallView.stories.tsx b/app/views/CallView/CallView.stories.tsx index a57029eb652..d7bbaed81a4 100644 --- a/app/views/CallView/CallView.stories.tsx +++ b/app/views/CallView/CallView.stories.tsx @@ -4,7 +4,6 @@ import { NavigationContainer } from '@react-navigation/native'; import CallView from '.'; import { useCallStore } from '../../lib/services/voip/useCallStore'; -import { CALL_BACKGROUND_COLOR } from './styles'; import { BASE_ROW_HEIGHT, BASE_ROW_HEIGHT_CONDENSED, @@ -13,8 +12,7 @@ import { const styles = StyleSheet.create({ container: { - flex: 1, - backgroundColor: CALL_BACKGROUND_COLOR + flex: 1 } }); @@ -96,7 +94,7 @@ export default { }; export const ConnectedCall = () => { - setStoreState({ callState: 'active', callStartTime: Date.now() - 61000 }); + setStoreState({ callState: 'active', callStartTime: new Date().getTime() - 61000 }); return <CallView />; }; diff --git a/app/views/CallView/__snapshots__/index.test.tsx.snap b/app/views/CallView/__snapshots__/index.test.tsx.snap new file mode 100644 index 00000000000..b0404418151 --- /dev/null +++ b/app/views/CallView/__snapshots__/index.test.tsx.snap @@ -0,0 +1,4850 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "flex": 1, + "justifyContent": "space-between", + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="bob.burnquist's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Bob Burnquist + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "marginBottom": 8, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + testID="caller-info-extension" + > + 2244 + </Text> + </View> + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "textAlign": "center", + } + } + > +   + </Text> + <View + style={ + { + "padding": 24, + } + } + > + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Speaker" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-speaker" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Speaker + </Text> + </View> + <View> + <View + accessibilityLabel="Hold" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-hold" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Hold + </Text> + </View> + <View> + <View + accessibilityLabel="Mute" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-mute" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Mute + </Text> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Message" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Message + </Text> + </View> + <View> + <View + accessibilityLabel="End" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#EC0D2A", + }, + ] + } + testID="call-view-end" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + End + </Text> + </View> + <View> + <View + accessibilityLabel="More" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-more" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + More + </Text> + </View> + </View> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "flex": 1, + "justifyContent": "space-between", + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="bob.burnquist's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Bob Burnquist + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "marginBottom": 8, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + testID="caller-info-extension" + > + 2244 + </Text> + </View> + <View + style={ + { + "padding": 24, + } + } + > + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Speaker" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-speaker" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Speaker + </Text> + </View> + <View> + <View + accessibilityLabel="Hold" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": true, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + { + "opacity": 0.5, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-hold" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Hold + </Text> + </View> + <View> + <View + accessibilityLabel="Mute" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": true, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + { + "opacity": 0.5, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-mute" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Mute + </Text> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Message" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Message + </Text> + </View> + <View> + <View + accessibilityLabel="Cancel" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#EC0D2A", + }, + ] + } + testID="call-view-end" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Cancel + </Text> + </View> + <View> + <View + accessibilityLabel="More" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-more" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + More + </Text> + </View> + </View> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "flex": 1, + "justifyContent": "space-between", + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="bob.burnquist's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Bob Burnquist + </Text> + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + { + "marginLeft": 8, + }, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + testID="caller-info-muted" + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "marginBottom": 8, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + testID="caller-info-extension" + > + 2244 + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + On hold + , + <Text + style={ + { + "color": "#8E6300", + } + } + > + Muted + </Text> + </Text> + <View + style={ + { + "padding": 24, + } + } + > + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Speaker" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-speaker" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Speaker + </Text> + </View> + <View> + <View + accessibilityLabel="Unhold" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-hold" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#BB0B21", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Unhold + </Text> + </View> + <View> + <View + accessibilityLabel="Unmute" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-mute" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#BB0B21", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Unmute + </Text> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Message" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Message + </Text> + </View> + <View> + <View + accessibilityLabel="End" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#EC0D2A", + }, + ] + } + testID="call-view-end" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + End + </Text> + </View> + <View> + <View + accessibilityLabel="More" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-more" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + More + </Text> + </View> + </View> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "flex": 1, + "justifyContent": "space-between", + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="bob.burnquist's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Bob Burnquist + </Text> + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + { + "marginLeft": 8, + }, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + testID="caller-info-muted" + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "marginBottom": 8, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + testID="caller-info-extension" + > + 2244 + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "textAlign": "center", + }, + { + "color": "#8E6300", + }, + ] + } + > + Muted + </Text> + <View + style={ + { + "padding": 24, + } + } + > + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Speaker" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-speaker" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Speaker + </Text> + </View> + <View> + <View + accessibilityLabel="Hold" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-hold" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Hold + </Text> + </View> + <View> + <View + accessibilityLabel="Unmute" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-mute" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#BB0B21", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Unmute + </Text> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Message" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Message + </Text> + </View> + <View> + <View + accessibilityLabel="End" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#EC0D2A", + }, + ] + } + testID="call-view-end" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + End + </Text> + </View> + <View> + <View + accessibilityLabel="More" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-more" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + More + </Text> + </View> + </View> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "flex": 1, + "justifyContent": "space-between", + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="bob.burnquist's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Bob Burnquist + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "marginBottom": 8, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + testID="caller-info-extension" + > + 2244 + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + On hold + </Text> + <View + style={ + { + "padding": 24, + } + } + > + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Speaker" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-speaker" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Speaker + </Text> + </View> + <View> + <View + accessibilityLabel="Unhold" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-hold" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#BB0B21", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Unhold + </Text> + </View> + <View> + <View + accessibilityLabel="Mute" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-mute" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Mute + </Text> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Message" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Message + </Text> + </View> + <View> + <View + accessibilityLabel="End" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#EC0D2A", + }, + ] + } + testID="call-view-end" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + End + </Text> + </View> + <View> + <View + accessibilityLabel="More" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-more" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + More + </Text> + </View> + </View> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "flex": 1, + "justifyContent": "space-between", + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="bob.burnquist's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Bob Burnquist + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "marginBottom": 8, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + testID="caller-info-extension" + > + 2244 + </Text> + </View> + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "textAlign": "center", + } + } + > +   + </Text> + <View + style={ + { + "padding": 24, + } + } + > + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Speaker" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-speaker" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#BB0B21", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Speaker + </Text> + </View> + <View> + <View + accessibilityLabel="Hold" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-hold" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Hold + </Text> + </View> + <View> + <View + accessibilityLabel="Mute" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-mute" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Mute + </Text> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "justifyContent": "space-around", + "marginBottom": 24, + } + } + > + <View> + <View + accessibilityLabel="Message" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Message + </Text> + </View> + <View> + <View + accessibilityLabel="End" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#EC0D2A", + }, + ] + } + testID="call-view-end" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + End + </Text> + </View> + <View> + <View + accessibilityLabel="More" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-view-more" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": NaN, + }, + [ + { + "lineHeight": NaN, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + More + </Text> + </View> + </View> + </View> + </View> +</View> +`; diff --git a/app/views/CallView/components/CallActionButton.stories.tsx b/app/views/CallView/components/CallActionButton.stories.tsx index 1e475a189eb..b7ccf058e4d 100644 --- a/app/views/CallView/components/CallActionButton.stories.tsx +++ b/app/views/CallView/components/CallActionButton.stories.tsx @@ -2,11 +2,9 @@ import React from 'react'; import { View, StyleSheet } from 'react-native'; import CallActionButton from './CallActionButton'; -import { CALL_BACKGROUND_COLOR } from '../styles'; const styles = StyleSheet.create({ container: { - backgroundColor: CALL_BACKGROUND_COLOR, padding: 24, alignItems: 'center' }, diff --git a/app/views/CallView/components/CallTimer.tsx b/app/views/CallView/components/CallTimer.tsx deleted file mode 100644 index 0b36993f60d..00000000000 --- a/app/views/CallView/components/CallTimer.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { useEffect, useState } from 'react'; - -const formatDuration = (seconds: number): string => { - const mins = Math.floor(seconds / 60); - const secs = seconds % 60; - return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; -}; - -export const useCallTimer = (startTime: number | null): string => { - const [elapsed, setElapsed] = useState(0); - - useEffect(() => { - if (!startTime) { - setElapsed(0); - return; - } - - const updateElapsed = () => { - const now = Date.now(); - setElapsed(Math.floor((now - startTime) / 1000)); - }; - - updateElapsed(); - const interval = setInterval(updateElapsed, 1000); - - return () => clearInterval(interval); - }, [startTime]); - - return formatDuration(elapsed); -}; diff --git a/app/views/CallView/components/CallerInfo.stories.tsx b/app/views/CallView/components/CallerInfo.stories.tsx index db9afd358e0..595229ac548 100644 --- a/app/views/CallView/components/CallerInfo.stories.tsx +++ b/app/views/CallView/components/CallerInfo.stories.tsx @@ -2,12 +2,10 @@ import React from 'react'; import { View, StyleSheet } from 'react-native'; import CallerInfo from './CallerInfo'; -import { CALL_BACKGROUND_COLOR } from '../styles'; import { useCallStore } from '../../../lib/services/voip/useCallStore'; const styles = StyleSheet.create({ container: { - backgroundColor: CALL_BACKGROUND_COLOR, padding: 24, flex: 1, minHeight: 300 @@ -47,13 +45,13 @@ export default { export const Default = () => <CallerInfo />; -export const WithOnlineStatus = () => <CallerInfo showOnlineStatus />; +export const WithOnlineStatus = () => <CallerInfo />; -export const WithMutedIndicator = () => <CallerInfo isMuted showOnlineStatus />; +export const WithMutedIndicator = () => <CallerInfo isMuted />; export const NoExtension = () => { setStoreState({ displayName: 'Alice Attali', username: 'alice.attali' }); - return <CallerInfo showOnlineStatus />; + return <CallerInfo />; }; export const UsernameOnly = () => { diff --git a/app/views/CallView/components/CallerInfo.test.tsx b/app/views/CallView/components/CallerInfo.test.tsx index 752cf6b0236..7bd8bd55586 100644 --- a/app/views/CallView/components/CallerInfo.test.tsx +++ b/app/views/CallView/components/CallerInfo.test.tsx @@ -53,26 +53,18 @@ describe('CallerInfo', () => { expect(getByText('john.doe')).toBeTruthy(); }); - it('should show online status indicator when showOnlineStatus is true', () => { + it('should render status container (Status component is currently commented out)', () => { setStoreState({ displayName: 'Test User' }); const { getByTestId } = render( <Wrapper> - <CallerInfo showOnlineStatus /> - </Wrapper> - ); - - expect(getByTestId('caller-info-status')).toBeTruthy(); - }); - - it('should not show online status indicator when showOnlineStatus is false', () => { - setStoreState({ displayName: 'Test User' }); - const { queryByTestId } = render( - <Wrapper> - <CallerInfo showOnlineStatus={false} /> + <CallerInfo /> </Wrapper> ); - expect(queryByTestId('caller-info-status')).toBeNull(); + // The status container exists but Status component is commented out + // Verify the component renders correctly + expect(getByTestId('caller-info')).toBeTruthy(); + expect(getByTestId('avatar')).toBeTruthy(); }); it('should show muted indicator when isMuted is true', () => { diff --git a/app/views/CallView/components/__snapshots__/CallActionButton.test.tsx.snap b/app/views/CallView/components/__snapshots__/CallActionButton.test.tsx.snap new file mode 100644 index 00000000000..11a32bac24d --- /dev/null +++ b/app/views/CallView/components/__snapshots__/CallActionButton.test.tsx.snap @@ -0,0 +1,1066 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: ActiveButton should match snapshot 1`] = ` +<View + style={ + { + "alignItems": "center", + "padding": 24, + } + } +> + <View> + <View + accessibilityLabel="Unmute" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-action-button" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#BB0B21", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Unmute + </Text> + </View> +</View> +`; + +exports[`Story Snapshots: AllVariants should match snapshot 1`] = ` +<View + style={ + { + "alignItems": "center", + "padding": 24, + } + } +> + <View + style={ + { + "flexDirection": "row", + "gap": 16, + } + } + > + <View> + <View + accessibilityLabel="Speaker" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="speaker" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Speaker + </Text> + </View> + <View> + <View + accessibilityLabel="Hold" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="hold" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Hold + </Text> + </View> + <View> + <View + accessibilityLabel="Mute" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="mute" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Mute + </Text> + </View> + </View> + <View + style={ + [ + { + "flexDirection": "row", + "gap": 16, + }, + { + "marginTop": 24, + }, + ] + } + > + <View> + <View + accessibilityLabel="Message" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Message + </Text> + </View> + <View> + <View + accessibilityLabel="End" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#EC0D2A", + }, + ] + } + testID="end" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + End + </Text> + </View> + <View> + <View + accessibilityLabel="More" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="more" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + More + </Text> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: DangerButton should match snapshot 1`] = ` +<View + style={ + { + "alignItems": "center", + "padding": 24, + } + } +> + <View> + <View + accessibilityLabel="End" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#EC0D2A", + }, + ] + } + testID="call-action-button" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + End + </Text> + </View> +</View> +`; + +exports[`Story Snapshots: DefaultButton should match snapshot 1`] = ` +<View + style={ + { + "alignItems": "center", + "padding": 24, + } + } +> + <View> + <View + accessibilityLabel="Mute" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + false, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-action-button" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Mute + </Text> + </View> +</View> +`; + +exports[`Story Snapshots: DisabledButton should match snapshot 1`] = ` +<View + style={ + { + "alignItems": "center", + "padding": 24, + } + } +> + <View> + <View + accessibilityLabel="Hold" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": true, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 8, + "height": 64, + "justifyContent": "center", + "marginBottom": 8, + "width": 64, + }, + { + "opacity": 0.5, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + testID="call-action-button" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 32, + }, + [ + { + "lineHeight": 32, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 14, + "fontWeight": "400", + "lineHeight": 20, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Hold + </Text> + </View> +</View> +`; diff --git a/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap b/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap new file mode 100644 index 00000000000..a4633b97130 --- /dev/null +++ b/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap @@ -0,0 +1,758 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: Default should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "minHeight": 300, + "padding": 24, + } + } +> + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="bob.burnquist's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Bob Burnquist + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "marginBottom": 8, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + testID="caller-info-extension" + > + 2244 + </Text> + </View> +</View> +`; + +exports[`Story Snapshots: NoExtension should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "minHeight": 300, + "padding": 24, + } + } +> + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="alice.attali's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/alice.attali?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Alice Attali + </Text> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: UsernameOnly should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "minHeight": 300, + "padding": 24, + } + } +> + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="john.doe's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/john.doe?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + john.doe + </Text> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: WithMutedIndicator should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "minHeight": 300, + "padding": 24, + } + } +> + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="bob.burnquist's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Bob Burnquist + </Text> + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + { + "marginLeft": 8, + }, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + testID="caller-info-muted" + > +  + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "marginBottom": 8, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + testID="caller-info-extension" + > + 2244 + </Text> + </View> +</View> +`; + +exports[`Story Snapshots: WithOnlineStatus should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "minHeight": 300, + "padding": 24, + } + } +> + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + "paddingHorizontal": 24, + } + } + testID="caller-info" + > + <View + style={ + { + "marginBottom": 16, + "position": "relative", + } + } + > + <View + accessibilityLabel="bob.burnquist's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 16, + "height": 120, + "width": 120, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={16} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={120} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", + }, + ] + } + style={ + { + "borderRadius": 16, + "height": 120, + "width": 120, + } + } + transition={null} + width={120} + /> + <View + style={ + [ + { + "borderRadius": 10, + "bottom": -2, + "position": "absolute", + "right": -2, + }, + { + "backgroundColor": "#F2F3F5", + }, + ] + } + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 24, + "fontWeight": "700", + "lineHeight": 32, + "marginBottom": 4, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + testID="caller-info-name" + > + Bob Burnquist + </Text> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "400", + "lineHeight": 26, + "marginBottom": 8, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + testID="caller-info-extension" + > + 2244 + </Text> + </View> +</View> +`; diff --git a/app/views/CallView/index.test.tsx b/app/views/CallView/index.test.tsx new file mode 100644 index 00000000000..66316d13e3e --- /dev/null +++ b/app/views/CallView/index.test.tsx @@ -0,0 +1,412 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import CallView from '.'; +import { useCallStore } from '../../lib/services/voip/useCallStore'; +import { mockedStore } from '../../reducers/mockedStore'; +import * as stories from './CallView.stories'; +import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; + +// Mock expo-keep-awake +jest.mock('expo-keep-awake', () => ({ + activateKeepAwakeAsync: jest.fn(() => Promise.resolve()), + deactivateKeepAwake: jest.fn() +})); + +// Mock ResponsiveLayoutContext for snapshots +jest.mock('../../lib/hooks/useResponsiveLayout/useResponsiveLayout', () => { + const React = require('react'); + const actual = jest.requireActual('../../lib/hooks/useResponsiveLayout/useResponsiveLayout'); + return { + ...actual, + ResponsiveLayoutContext: React.createContext({ + fontScale: 1, + width: 350, + height: 800, + isLargeFontScale: false, + fontScaleLimited: 1, + rowHeight: 75, + rowHeightCondensed: 60 + }) + }; +}); + +// Mock alert +global.alert = jest.fn(); + +// Helper to create a mock call +const createMockCall = (overrides: any = {}) => ({ + state: 'active', + muted: false, + held: false, + contact: { + displayName: 'Bob Burnquist', + username: 'bob.burnquist', + sipExtension: '2244' + }, + setMuted: jest.fn(), + setHeld: jest.fn(), + hangup: jest.fn(), + reject: jest.fn(), + emitter: { + on: jest.fn(), + off: jest.fn() + }, + ...overrides +}); + +// Helper to set store state for tests +const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getState>> = {}) => { + const mockCall = createMockCall(); + useCallStore.setState({ + call: mockCall as any, + callUUID: 'test-uuid', + callState: 'active', + isMuted: false, + isOnHold: false, + isSpeakerOn: false, + callStartTime: Date.now(), + contact: { + displayName: 'Bob Burnquist', + username: 'bob.burnquist', + sipExtension: '2244' + }, + ...overrides + }); +}; + +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; + +describe('CallView', () => { + beforeEach(() => { + useCallStore.getState().reset(); + jest.clearAllMocks(); + }); + + it('should return null when there is no call', () => { + useCallStore.setState({ call: null }); + const { queryByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + expect(queryByTestId('caller-info')).toBeNull(); + }); + + it('should render when there is a call', () => { + setStoreState(); + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + expect(getByTestId('caller-info')).toBeTruthy(); + expect(getByTestId('call-view-speaker')).toBeTruthy(); + expect(getByTestId('call-view-hold')).toBeTruthy(); + expect(getByTestId('call-view-mute')).toBeTruthy(); + expect(getByTestId('call-view-message')).toBeTruthy(); + expect(getByTestId('call-view-end')).toBeTruthy(); + expect(getByTestId('call-view-more')).toBeTruthy(); + }); + + it('should show CallStatusText when call is active', () => { + setStoreState({ callState: 'active' }); + const { getByText } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + // CallStatusText should render (it shows a space when not muted/on hold) + expect(getByText(/\s/)).toBeTruthy(); + }); + + it('should not show CallStatusText when call is not active', () => { + setStoreState({ callState: 'ringing' }); + const { queryByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + // CallStatusText should not be rendered when not active + // We can't easily test for the Text component directly, so we verify the caller-info is rendered + // but CallStatusText won't be in the tree when callState is not 'active' + expect(queryByTestId('caller-info')).toBeTruthy(); + }); + + it('should disable hold and mute buttons when call is connecting', () => { + setStoreState({ callState: 'ringing' }); + const toggleHold = jest.fn(); + const toggleMute = jest.fn(); + useCallStore.setState({ toggleHold, toggleMute }); + + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + const holdButton = getByTestId('call-view-hold'); + const muteButton = getByTestId('call-view-mute'); + + // Test that disabled buttons don't trigger onPress + fireEvent.press(holdButton); + fireEvent.press(muteButton); + expect(toggleHold).not.toHaveBeenCalled(); + expect(toggleMute).not.toHaveBeenCalled(); + }); + + it('should enable hold and mute buttons when call is active', () => { + setStoreState({ callState: 'active' }); + const toggleHold = jest.fn(); + const toggleMute = jest.fn(); + useCallStore.setState({ toggleHold, toggleMute }); + + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + const holdButton = getByTestId('call-view-hold'); + const muteButton = getByTestId('call-view-mute'); + + // Test that enabled buttons trigger onPress + fireEvent.press(holdButton); + fireEvent.press(muteButton); + expect(toggleHold).toHaveBeenCalledTimes(1); + expect(toggleMute).toHaveBeenCalledTimes(1); + }); + + it('should call toggleMute when mute button is pressed', () => { + setStoreState({ callState: 'active' }); + const toggleMute = jest.fn(); + useCallStore.setState({ toggleMute }); + + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + fireEvent.press(getByTestId('call-view-mute')); + expect(toggleMute).toHaveBeenCalledTimes(1); + }); + + it('should call toggleHold when hold button is pressed', () => { + setStoreState({ callState: 'active' }); + const toggleHold = jest.fn(); + useCallStore.setState({ toggleHold }); + + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + fireEvent.press(getByTestId('call-view-hold')); + expect(toggleHold).toHaveBeenCalledTimes(1); + }); + + it('should call toggleSpeaker when speaker button is pressed', () => { + setStoreState({ callState: 'active' }); + const toggleSpeaker = jest.fn(); + useCallStore.setState({ toggleSpeaker }); + + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + fireEvent.press(getByTestId('call-view-speaker')); + expect(toggleSpeaker).toHaveBeenCalledTimes(1); + }); + + it('should call endCall when end button is pressed', () => { + setStoreState({ callState: 'active' }); + const endCall = jest.fn(); + useCallStore.setState({ endCall }); + + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + fireEvent.press(getByTestId('call-view-end')); + expect(endCall).toHaveBeenCalledTimes(1); + }); + + it('should show alert when message button is pressed', () => { + setStoreState({ callState: 'active' }); + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + fireEvent.press(getByTestId('call-view-message')); + expect(global.alert).toHaveBeenCalledWith('Message'); + }); + + it('should show alert when more button is pressed', () => { + setStoreState({ callState: 'active' }); + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + fireEvent.press(getByTestId('call-view-more')); + expect(global.alert).toHaveBeenCalledWith('More'); + }); + + it('should show "Cancel" label when call is connecting', () => { + setStoreState({ callState: 'ringing' }); + const { getByText } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + expect(getByText('Cancel')).toBeTruthy(); + }); + + it('should show "End" label when call is active', () => { + setStoreState({ callState: 'active' }); + const { getByText } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + expect(getByText('End')).toBeTruthy(); + }); + + it('should show muted indicator when call is muted and active', () => { + setStoreState({ callState: 'active', isMuted: true }); + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + expect(getByTestId('caller-info-muted')).toBeTruthy(); + }); + + it('should not show muted indicator when call is muted but not active', () => { + setStoreState({ callState: 'ringing', isMuted: true }); + const { queryByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + expect(queryByTestId('caller-info-muted')).toBeNull(); + }); + + it('should show correct icon for speaker button when speaker is on', () => { + setStoreState({ callState: 'active', isSpeakerOn: true }); + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + // The button should be rendered (we test behavior rather than props) + const speakerButton = getByTestId('call-view-speaker'); + expect(speakerButton).toBeTruthy(); + }); + + it('should show correct icon for speaker button when speaker is off', () => { + setStoreState({ callState: 'active', isSpeakerOn: false }); + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + // The button should be rendered (we test behavior rather than props) + const speakerButton = getByTestId('call-view-speaker'); + expect(speakerButton).toBeTruthy(); + }); + + it('should render mute button correctly when muted', () => { + setStoreState({ callState: 'active', isMuted: true }); + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + // The button should be rendered (we test behavior rather than props) + const muteButton = getByTestId('call-view-mute'); + expect(muteButton).toBeTruthy(); + }); + + it('should render hold button correctly when on hold', () => { + setStoreState({ callState: 'active', isOnHold: true }); + const { getByTestId } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + // The button should be rendered (we test behavior rather than props) + const holdButton = getByTestId('call-view-hold'); + expect(holdButton).toBeTruthy(); + }); + + it('should show correct label for hold button based on state', () => { + setStoreState({ callState: 'active', isOnHold: true }); + const { getByText } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + expect(getByText('Unhold')).toBeTruthy(); + }); + + it('should show correct label for mute button based on state', () => { + setStoreState({ callState: 'active', isMuted: true }); + const { getByText } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + expect(getByText('Unmute')).toBeTruthy(); + }); + + it('should activate keep awake on mount', () => { + const { activateKeepAwakeAsync } = require('expo-keep-awake'); + setStoreState(); + render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + expect(activateKeepAwakeAsync).toHaveBeenCalled(); + }); + + it('should deactivate keep awake on unmount', () => { + const { deactivateKeepAwake } = require('expo-keep-awake'); + setStoreState(); + const { unmount } = render( + <Wrapper> + <CallView /> + </Wrapper> + ); + + unmount(); + expect(deactivateKeepAwake).toHaveBeenCalled(); + }); +}); + +generateSnapshots(stories); diff --git a/app/views/CallView/index.tsx b/app/views/CallView/index.tsx index 0eac9cfc1e4..5c455897fad 100644 --- a/app/views/CallView/index.tsx +++ b/app/views/CallView/index.tsx @@ -1,18 +1,18 @@ import React, { useEffect } from 'react'; -import { Text, View, Pressable } from 'react-native'; +import { View } from 'react-native'; import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake'; import I18n from '../../i18n'; -import { CustomIcon } from '../../containers/CustomIcon'; import { useCallStore } from '../../lib/services/voip/useCallStore'; import CallerInfo from './components/CallerInfo'; import CallActionButton from './components/CallActionButton'; import CallStatusText from './components/CallStatusText'; -// import { useCallTimer } from './components/CallTimer'; import { styles } from './styles'; import { useTheme } from '../../theme'; const CallView = (): React.ReactElement | null => { + 'use memo'; + const { colors } = useTheme(); // Get state from store @@ -21,8 +21,6 @@ const CallView = (): React.ReactElement | null => { const isMuted = useCallStore(state => state.isMuted); const isOnHold = useCallStore(state => state.isOnHold); const isSpeakerOn = useCallStore(state => state.isSpeakerOn); - const callStartTime = useCallStore(state => state.callStartTime); - const contact = useCallStore(state => state.contact); // Get actions from store const toggleMute = useCallStore(state => state.toggleMute); @@ -30,10 +28,6 @@ const CallView = (): React.ReactElement | null => { const toggleSpeaker = useCallStore(state => state.toggleSpeaker); const endCall = useCallStore(state => state.endCall); - // Get formatted call duration - // const callDuration = useCallTimer(callStartTime); - const callDuration = '00:00'; - // Keep screen awake during call useEffect(() => { activateKeepAwakeAsync(); @@ -53,11 +47,6 @@ const CallView = (): React.ReactElement | null => { alert('More'); }; - const handleCollapse = () => { - // goBack(); - alert('Collapse call'); - }; - const handleEndCall = () => { endCall(); }; @@ -66,20 +55,9 @@ const CallView = (): React.ReactElement | null => { return null; } - const callerName = contact.displayName || contact.username || I18n.t('Unknown'); const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; const isConnected = callState === 'active'; - const getHeaderTitle = () => { - if (isConnecting) { - return I18n.t('Connecting'); - } - if (isConnected && callStartTime) { - return `${callerName} – ${callDuration}`; - } - return callerName; - }; - return ( <View style={[styles.contentContainer, { backgroundColor: colors.surfaceLight }]}> {/* Caller Info */} diff --git a/app/views/RoomView/components/HeaderCallButton.tsx b/app/views/RoomView/components/HeaderCallButton.tsx index 28c7cbcc455..f0fb0663992 100644 --- a/app/views/RoomView/components/HeaderCallButton.tsx +++ b/app/views/RoomView/components/HeaderCallButton.tsx @@ -1,11 +1,11 @@ import React from 'react'; import * as HeaderButton from '../../../containers/Header/components/HeaderButton'; -import { useVideoConf } from '../../../lib/hooks/useVideoConf'; +// import { useVideoConf } from '../../../lib/hooks/useVideoConf'; import { useCallStore } from '../../../lib/services/voip/useCallStore'; export const HeaderCallButton = ({ - rid, + // rid, disabled, accessibilityLabel }: { From db29a479a7d6c9cdce09a345bd0ac38d405dc726 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 14 Jan 2026 16:27:49 -0300 Subject: [PATCH 17/61] Temp use @rocket.chat/media-signaling from .tgz --- package.json | 2 +- packages/rocket.chat-media-signaling-0.1.0.tgz | Bin 0 -> 56685 bytes yarn.lock | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 packages/rocket.chat-media-signaling-0.1.0.tgz diff --git a/package.json b/package.json index 31556dcc49b..a229bd5c3b3 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@react-navigation/elements": "^2.6.1", "@react-navigation/native": "^7.1.16", "@react-navigation/native-stack": "^7.3.23", - "@rocket.chat/media-signaling": "/Users/diegomello/Development/Work/Rocket.Chat/packages/media-signaling", + "@rocket.chat/media-signaling": "file:./packages/rocket.chat-media-signaling-0.1.0.tgz", "@rocket.chat/message-parser": "^0.31.31", "@rocket.chat/mobile-crypto": "RocketChat/rocket.chat-mobile-crypto", "@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#mobile", diff --git a/packages/rocket.chat-media-signaling-0.1.0.tgz b/packages/rocket.chat-media-signaling-0.1.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..59bca49a746265a489a48276cff4b6018a873f6b GIT binary patch literal 56685 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%0DVkzpMP?g%Za}Vg*F; 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 literal 0 HcmV?d00001 diff --git a/yarn.lock b/yarn.lock index 3a2618aafa2..3e5a2cf37a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5016,8 +5016,9 @@ dependencies: eslint-plugin-import "^2.17.2" -"@rocket.chat/media-signaling@file:../Rocket.Chat/packages/media-signaling": +"@rocket.chat/media-signaling@file:./packages/rocket.chat-media-signaling-0.1.0.tgz": version "0.1.0" + resolved "file:./packages/rocket.chat-media-signaling-0.1.0.tgz#b73f0c2a642b65ecce4df8da2f44b22f93cd75fb" dependencies: "@rocket.chat/emitter" "~0.31.25" ajv "^8.17.1" From 2b16f4b6ba165b94746c2a77ef73ecf4e97bfd90 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Thu, 15 Jan 2026 13:52:28 -0300 Subject: [PATCH 18/61] cleanup --- app/sagas/login.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/sagas/login.js b/app/sagas/login.js index 11fbb47408a..ad9bbac1af3 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -42,7 +42,7 @@ import appNavigation from '../lib/navigation/appNavigation'; import { showActionSheetRef } from '../containers/ActionSheet'; import { SupportedVersionsWarning } from '../containers/SupportedVersions'; import { mediaSessionInstance } from '../lib/services/voip/MediaSessionInstance'; -import { simulateCall } from '../lib/services/voip/simulateCall'; +// import { simulateCall } from '../lib/services/voip/simulateCall'; const getServer = state => state.server.server; const loginWithPasswordCall = args => loginWithPassword(args); @@ -256,11 +256,6 @@ function* initCallKeep() { RNCallKeep.setup(options); RNCallKeep.canMakeMultipleCalls(false); - - const start = Date.now(); - setInterval(() => { - console.log('Timer fired after', Date.now() - start, 'ms'); - }, 1000); } catch (e) { log(e); } @@ -271,7 +266,7 @@ const startVoipFork = function* startVoipFork() { yield call(initCallKeep); const userId = yield select(state => state.login.user.id); mediaSessionInstance.init(userId); - simulateCall(); + // simulateCall(); } catch (e) { log(e); } From eae91374528edbdd65340b320a6fd98a507f643c Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Thu, 15 Jan 2026 16:01:21 -0300 Subject: [PATCH 19/61] Check module and permissions to enable voip --- app/lib/methods/enterpriseModules.ts | 5 ++++ app/lib/methods/getPermissions.ts | 4 +++- app/sagas/login.js | 35 ++++++++++++++++------------ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/app/lib/methods/enterpriseModules.ts b/app/lib/methods/enterpriseModules.ts index 0e40675a0f7..2c252df779e 100644 --- a/app/lib/methods/enterpriseModules.ts +++ b/app/lib/methods/enterpriseModules.ts @@ -61,3 +61,8 @@ export function isOmnichannelModuleAvailable() { const { enterpriseModules } = reduxStore.getState(); return [LICENSE_OMNICHANNEL_MOBILE_ENTERPRISE, LICENSE_LIVECHAT_ENTERPRISE].some(module => enterpriseModules.includes(module)); } + +export function isVoipModuleAvailable() { + const { enterpriseModules } = reduxStore.getState(); + return enterpriseModules.includes('teams-voip'); +} diff --git a/app/lib/methods/getPermissions.ts b/app/lib/methods/getPermissions.ts index 02082089ad1..cf38e96e466 100644 --- a/app/lib/methods/getPermissions.ts +++ b/app/lib/methods/getPermissions.ts @@ -68,7 +68,9 @@ export const SUPPORTED_PERMISSIONS = [ 'delete-team-channel', 'delete-team-group', 'mention-all', - 'mention-here' + 'mention-here', + 'allow-internal-voice-calls', + 'allow-external-voice-calls' ] as const; export async function setPermissions(): Promise<void> { diff --git a/app/sagas/login.js b/app/sagas/login.js index ad9bbac1af3..ea4665fe86c 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -27,7 +27,7 @@ import { RootEnum } from '../definitions'; import sdk from '../lib/services/sdk'; import { CURRENT_SERVER, TOKEN_KEY } from '../lib/constants/keys'; import { getCustomEmojis } from '../lib/methods/getCustomEmojis'; -import { getEnterpriseModules, isOmnichannelModuleAvailable } from '../lib/methods/enterpriseModules'; +import { getEnterpriseModules, isOmnichannelModuleAvailable, isVoipModuleAvailable } from '../lib/methods/enterpriseModules'; import { getPermissions } from '../lib/methods/getPermissions'; import { getRoles } from '../lib/methods/getRoles'; import { getSlashCommands } from '../lib/methods/getSlashCommands'; @@ -42,6 +42,7 @@ import appNavigation from '../lib/navigation/appNavigation'; import { showActionSheetRef } from '../containers/ActionSheet'; import { SupportedVersionsWarning } from '../containers/SupportedVersions'; import { mediaSessionInstance } from '../lib/services/voip/MediaSessionInstance'; +import { hasPermission } from '../lib/methods/helpers/helpers'; // import { simulateCall } from '../lib/services/voip/simulateCall'; const getServer = state => state.server.server; @@ -155,7 +156,7 @@ const subscribeSettingsFork = function* subscribeSettingsFork() { } }; -const fetchPermissionsFork = function* fetchPermissionsFork() { +const fetchPermissions = function* fetchPermissions() { try { yield getPermissions(); } catch (e) { @@ -204,7 +205,7 @@ const fetchUsersPresenceFork = function* fetchUsersPresenceFork() { } }; -const fetchEnterpriseModulesFork = function* fetchEnterpriseModulesFork({ user }) { +const fetchEnterpriseModules = function* fetchEnterpriseModules({ user }) { try { yield getEnterpriseModules(); @@ -263,10 +264,16 @@ function* initCallKeep() { const startVoipFork = function* startVoipFork() { try { - yield call(initCallKeep); - const userId = yield select(state => state.login.user.id); - mediaSessionInstance.init(userId); - // simulateCall(); + const allowInternalVoiceCallRoles = yield select(state => state.permissions['allow-internal-voice-calls']); + const allowExternalVoiceCallRoles = yield select(state => state.permissions['allow-external-voice-calls']); + + const hasPermissions = yield hasPermission([allowInternalVoiceCallRoles, allowExternalVoiceCallRoles]); + if (isVoipModuleAvailable() && (hasPermissions[0] || hasPermissions[1])) { + yield call(initCallKeep); + const userId = yield select(state => state.login.user.id); + mediaSessionInstance.init(userId); + // simulateCall(); + } } catch (e) { log(e); } @@ -274,24 +281,23 @@ const startVoipFork = function* startVoipFork() { const handleLoginSuccess = function* handleLoginSuccess({ user }) { try { - getUserPresence(user.id); + yield put(setUser(user)); + setLanguage(user?.language); const server = yield select(getServer); yield put(roomsRequest()); yield put(encryptionInit()); - yield fork(fetchPermissionsFork); + yield call(fetchPermissions); + yield call(fetchEnterpriseModules, { user }); + yield fork(startVoipFork); yield fork(fetchCustomEmojisFork); yield fork(fetchRolesFork); yield fork(fetchSlashCommandsFork); yield fork(registerPushTokenFork); yield fork(fetchUsersPresenceFork); - yield fork(fetchEnterpriseModulesFork, { user }); yield fork(subscribeSettingsFork); yield fork(fetchUsersRoles); - yield delay(1000); - yield fork(startVoipFork); - - setLanguage(user?.language); + yield getUserPresence(user.id); const serversDB = database.servers; const usersCollection = serversDB.get('users'); @@ -327,7 +333,6 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) { UserPreferences.setString(`${TOKEN_KEY}-${server}`, user.id); UserPreferences.setString(`${TOKEN_KEY}-${user.id}`, user.token); UserPreferences.setString(CURRENT_SERVER, server); - yield put(setUser(user)); EventEmitter.emit('connected'); const currentRoot = yield select(state => state.app.root); if (currentRoot !== RootEnum.ROOT_SHARE_EXTENSION && currentRoot !== RootEnum.ROOT_LOADING_SHARE_EXTENSION) { From bb2a8bb451c9382d90745c67f248694bbc158c74 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Thu, 15 Jan 2026 16:01:39 -0300 Subject: [PATCH 20/61] Refactor stop method to use optional chaining for media signal listeners --- app/lib/services/voip/MediaSessionInstance.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index a54a4855d36..8f9f80609b7 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -164,10 +164,10 @@ class MediaSessionInstance { } private stop() { - if (this.mediaSignalListener) { + if (this.mediaSignalListener?.stop) { this.mediaSignalListener.stop(); } - if (this.mediaSignalsListener) { + if (this.mediaSignalsListener?.stop) { this.mediaSignalsListener.stop(); } if (this.storeTimeoutUnsubscribe) { From 10593d642caa1ac597cf089418b68397df949583 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Fri, 16 Jan 2026 13:47:08 -0300 Subject: [PATCH 21/61] voip push first test --- index.js | 34 ++++++++++++++++++-- ios/AppDelegate.swift | 51 ++++++++++++++++++++++++++++++ ios/Podfile.lock | 6 ++++ ios/RocketChatRN-Bridging-Header.h | 2 ++ package.json | 1 + yarn.lock | 5 +++ 6 files changed, 96 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 778e46478d1..3aac1fca993 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,10 @@ import 'react-native-gesture-handler'; import 'react-native-console-time-polyfill'; import { AppRegistry, LogBox } from 'react-native'; +import VoipPushNotification from 'react-native-voip-push-notification'; import { name as appName } from './app.json'; -import { isAndroid } from './app/lib/methods/helpers'; +import { isAndroid, isIOS } from './app/lib/methods/helpers'; if (process.env.USE_STORYBOOK) { AppRegistry.registerComponent(appName, () => require('./.rnstorybook/index').default); @@ -22,8 +23,35 @@ if (process.env.USE_STORYBOOK) { LogBox.ignoreAllLogs(); - // Note: Android video conference notifications are now handled natively - // in RCFirebaseMessagingService -> CustomPushNotification -> VideoConfNotification + if (isIOS) { + VoipPushNotification.addEventListener('register', token => { + console.log('VoIP Token:', token); + // Send token to your server + }); + + VoipPushNotification.addEventListener('notification', notification => { + console.log('VoIP Notification Received:', notification); + const { uuid, callerName, handle } = notification; + + VoipPushNotification.onVoipNotificationCompleted(uuid); + }); + + VoipPushNotification.addEventListener('didLoadWithEvents', events => { + if (!events || !Array.isArray(events) || events.length < 1) { + return; + } + for (const voipPushEvent of events) { + const { name, data } = voipPushEvent; + console.log('didLoadWithEvents', voipPushEvent); + if (name === VoipPushNotification.RNVoipPushRemoteNotificationsRegisteredEvent) { + console.log('didLoadWithEvents VoIP Token: ', data); + } else if (name === VoipPushNotification.RNVoipPushRemoteNotificationReceivedEvent) { + // onVoipPushNotificationiReceived(data); + } + } + }); + VoipPushNotification.registerVoipToken(); + } AppRegistry.registerComponent(appName, () => require('./app/index').default); } diff --git a/ios/AppDelegate.swift b/ios/AppDelegate.swift index b0aa0e2851f..3dcb2241484 100644 --- a/ios/AppDelegate.swift +++ b/ios/AppDelegate.swift @@ -4,6 +4,7 @@ import ReactAppDependencyProvider import Firebase import Bugsnag import WatchConnectivity +import PushKit @UIApplicationMain public class AppDelegate: ExpoAppDelegate { @@ -25,6 +26,8 @@ public class AppDelegate: ExpoAppDelegate { FirebaseApp.configure() Bugsnag.start() ReplyNotification.configure() + RNVoipPushNotificationManager.voipRegistration() + RNCallKeep.setup(["appName": "Rocket.Chat"]) let delegate = ReactNativeDelegate() let factory = RCTReactNativeFactory(delegate: delegate) @@ -91,3 +94,51 @@ class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate { #endif } } + +// MARK: - PKPushRegistryDelegate + +extension AppDelegate: PKPushRegistryDelegate { + // Handle updated push credentials + public func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { + // Register VoIP push token (a property of PKPushCredentials) with server + RNVoipPushNotificationManager.didUpdate(credentials, forType: type.rawValue) + } + + public func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { + // The system calls this method when a previously provided push token is no longer valid for use. + // No action is necessary on your part to reregister the push type. + // Instead, use this method to notify your server not to send push notifications using the matching push token. + } + + public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { + // let uuid = UUID().uuidString.lowercased() + let callerName = payload.dictionaryPayload["caller"] as? String + let callId = payload.dictionaryPayload["callId"] as? String + let handle = payload.dictionaryPayload["caller"] as? String + + let callIdUUID = UUID(uuidString: callId ?? "")?.uuidString.lowercased() + if callIdUUID == nil { + completion() + return + } + + RNVoipPushNotificationManager.didReceiveIncomingPush(with: payload, forType: type.rawValue) + + RNCallKeep.reportNewIncomingCall( + callIdUUID, + handle: handle, + handleType: "generic", + hasVideo: true, + localizedCallerName: callerName, + supportsHolding: true, + supportsDTMF: true, + supportsGrouping: true, + supportsUngrouping: true, + fromPushKit: true, + payload: payload.dictionaryPayload, + withCompletionHandler: nil + ) + + completion() + } +} diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 848e26d5b2d..7a4be814f34 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2612,6 +2612,8 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - RNVoipPushNotification (3.3.3): + - React-Core - SDWebImage (5.21.0): - SDWebImage/Core (= 5.21.0) - SDWebImage/Core (5.21.0) @@ -2762,6 +2764,7 @@ DEPENDENCIES: - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) - RNSVG (from `../node_modules/react-native-svg`) + - RNVoipPushNotification (from `../node_modules/react-native-voip-push-notification`) - "simdjson (from `../node_modules/@nozbe/simdjson`)" - "WatermelonDB (from `../node_modules/@nozbe/watermelondb`)" - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -3043,6 +3046,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-screens" RNSVG: :path: "../node_modules/react-native-svg" + RNVoipPushNotification: + :path: "../node_modules/react-native-voip-push-notification" simdjson: :path: "../node_modules/@nozbe/simdjson" WatermelonDB: @@ -3193,6 +3198,7 @@ SPEC CHECKSUMS: RNReanimated: f52ccd5ceea2bae48d7421eec89b3f0c10d7b642 RNScreens: b13e4c45f0406f33986a39c0d8da0324bff94435 RNSVG: 680e961f640e381aab730a04b2371969686ed9f7 + RNVoipPushNotification: 4998fe6724d421da616dca765da7dc421ff54c4e SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90 SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c diff --git a/ios/RocketChatRN-Bridging-Header.h b/ios/RocketChatRN-Bridging-Header.h index 40e9146f471..3e55fda6b58 100644 --- a/ios/RocketChatRN-Bridging-Header.h +++ b/ios/RocketChatRN-Bridging-Header.h @@ -2,6 +2,8 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // +#import <RNVoipPushNotification/RNVoipPushNotificationManager.h> +#import <RNCallKeep/RNCallKeep.h> #import "SecureStorage.h" #import "MMKVKeyManager.h" #import "Shared/RocketChat/MMKVBridge.h" diff --git a/package.json b/package.json index a229bd5c3b3..b3c8e309cbb 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,7 @@ "react-native-slowlog": "1.0.2", "react-native-svg": "^15.12.1", "react-native-url-polyfill": "2.0.0", + "react-native-voip-push-notification": "^3.3.3", "react-native-webrtc": "^124.0.7", "react-native-webview": "^13.15.0", "react-redux": "8.0.5", diff --git a/yarn.lock b/yarn.lock index 3e5a2cf37a4..bf8a782547f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12893,6 +12893,11 @@ react-native-url-polyfill@2.0.0, react-native-url-polyfill@^2.0.0: dependencies: whatwg-url-without-unicode "8.0.0-3" +react-native-voip-push-notification@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/react-native-voip-push-notification/-/react-native-voip-push-notification-3.3.3.tgz#60169cc4083fc619383ab081f330e42a995c0dfa" + integrity sha512-cyWuI9//T1IQIq4RPq0QQe0NuEwIpnE0L98H2sUH4MjFsNMD/yNE4EJzEZN4cIwfPMZaASa0gQw6B1a7VwnkMA== + react-native-webrtc@^124.0.7: version "124.0.7" resolved "https://registry.yarnpkg.com/react-native-webrtc/-/react-native-webrtc-124.0.7.tgz#f50647a8eb3fae0ef29843eb1b5fe2c4ff75a56e" From b6766f3e942c98baecc7fa3de4d61c509cb954cb Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Fri, 16 Jan 2026 15:26:00 -0300 Subject: [PATCH 22/61] Add VoIP call handling with pending call management - Implemented VoIP push notification handling in index.js, including storing call info for later processing. - Added CallKeep event handlers for answering and ending calls from a cold start. - Introduced a new CallIdUUID module to convert call IDs to deterministic UUIDs for compatibility with CallKit. - Created a pending call store to manage incoming calls when the app is not fully initialized. - Updated deep linking actions to include VoIP call handling. - Enhanced MediaSessionInstance to process pending calls and manage call states effectively. --- app/actions/actionsTypes.ts | 2 +- app/actions/deepLinking.ts | 21 ++++ app/lib/native/CallIdUUID.ts | 22 +++++ app/lib/services/voip/MediaSessionInstance.ts | 53 +++++++---- app/lib/services/voip/pendingCallStore.ts | 91 ++++++++++++++++++ app/sagas/deepLinking.js | 68 +++++++++++++ index.js | 95 ++++++++++++++++--- ios/AppDelegate.swift | 14 +-- ios/CallIdUUID.m | 7 ++ ios/CallIdUUID.swift | 67 +++++++++++++ ios/{ => Libraries}/A11yFlowModule.h | 0 ios/{ => Libraries}/A11yFlowModule.m | 0 ios/Libraries/CallIdUUID.m | 7 ++ ios/Libraries/CallIdUUID.swift | 67 +++++++++++++ ios/{ => Libraries}/MMKVKeyManager.h | 0 ios/{ => Libraries}/MMKVKeyManager.mm | 2 +- ios/{ => Libraries}/SSLPinning.h | 0 ios/{ => Libraries}/SSLPinning.mm | 2 +- ios/{ => Libraries}/SecureStorage.h | 0 ios/{ => Libraries}/SecureStorage.m | 0 ios/RocketChatRN.xcodeproj/project.pbxproj | 76 ++++++++------- 21 files changed, 515 insertions(+), 79 deletions(-) create mode 100644 app/lib/native/CallIdUUID.ts create mode 100644 app/lib/services/voip/pendingCallStore.ts create mode 100644 ios/CallIdUUID.m create mode 100644 ios/CallIdUUID.swift rename ios/{ => Libraries}/A11yFlowModule.h (100%) rename ios/{ => Libraries}/A11yFlowModule.m (100%) create mode 100644 ios/Libraries/CallIdUUID.m create mode 100644 ios/Libraries/CallIdUUID.swift rename ios/{ => Libraries}/MMKVKeyManager.h (100%) rename ios/{ => Libraries}/MMKVKeyManager.mm (98%) rename ios/{ => Libraries}/SSLPinning.h (100%) rename ios/{ => Libraries}/SSLPinning.mm (99%) rename ios/{ => Libraries}/SecureStorage.h (100%) rename ios/{ => Libraries}/SecureStorage.m (100%) diff --git a/app/actions/actionsTypes.ts b/app/actions/actionsTypes.ts index 938ff7b9d5d..996edcd8a2f 100644 --- a/app/actions/actionsTypes.ts +++ b/app/actions/actionsTypes.ts @@ -59,7 +59,7 @@ export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DI export const LOGOUT = 'LOGOUT'; // logout is always success export const DELETE_ACCOUNT = 'DELETE_ACCOUNT'; export const SNIPPETED_MESSAGES = createRequestTypes('SNIPPETED_MESSAGES', ['OPEN', 'READY', 'CLOSE', 'MESSAGES_RECEIVED']); -export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN', 'OPEN_VIDEO_CONF']); +export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN', 'OPEN_VIDEO_CONF', 'VOIP_CALL']); export const SORT_PREFERENCES = createRequestTypes('SORT_PREFERENCES', ['SET_ALL', 'SET']); export const SET_CUSTOM_EMOJIS = 'SET_CUSTOM_EMOJIS'; export const ACTIVE_USERS = createRequestTypes('ACTIVE_USERS', ['SET', 'CLEAR']); diff --git a/app/actions/deepLinking.ts b/app/actions/deepLinking.ts index 7572cebe4ee..548aad8769a 100644 --- a/app/actions/deepLinking.ts +++ b/app/actions/deepLinking.ts @@ -16,6 +16,16 @@ interface IDeepLinkingOpen extends Action { params: Partial<IParams>; } +interface IVoipCallParams { + callId: string; + callUUID: string; + host: string; +} + +interface IVoipCallOpen extends Action { + params: IVoipCallParams; +} + export function deepLinkingOpen(params: Partial<IParams>): IDeepLinkingOpen { return { type: DEEP_LINKING.OPEN, @@ -29,3 +39,14 @@ export function deepLinkingClickCallPush(params: any): IDeepLinkingOpen { params }; } + +/** + * Action to handle VoIP call from push notification. + * Triggers server switching if needed and processes the incoming call. + */ +export function voipCallOpen(params: IVoipCallParams): IVoipCallOpen { + return { + type: DEEP_LINKING.VOIP_CALL, + params + }; +} diff --git a/app/lib/native/CallIdUUID.ts b/app/lib/native/CallIdUUID.ts new file mode 100644 index 00000000000..3b3f77dde49 --- /dev/null +++ b/app/lib/native/CallIdUUID.ts @@ -0,0 +1,22 @@ +import { NativeModules, Platform } from 'react-native'; + +interface ICallIdUUIDModule { + toUUID(callId: string): string; +} + +const { CallIdUUID } = NativeModules; + +/** + * Native module to convert a callId string to a deterministic UUID v5. + * This is used by CallKit which requires UUIDs, while the server sends random callId strings. + * The same UUID v5 algorithm is used in both native (AppDelegate) and JS for consistency. + */ +export const CallIdUUIDModule: ICallIdUUIDModule = { + toUUID: (callId: string): string => { + if (Platform.OS !== 'ios') { + // Android doesn't use CallKit, return the callId as-is or implement Android equivalent + return callId; + } + return CallIdUUID.toUUID(callId); + } +}; diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 8f9f80609b7..d67b9777a0c 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -7,19 +7,18 @@ import { } from '@rocket.chat/media-signaling'; import RNCallKeep, { type EventListener } from 'react-native-callkeep'; import { registerGlobals } from 'react-native-webrtc'; -import { randomUuid } from '@rocket.chat/mobile-crypto'; import { mediaSessionStore } from './MediaSessionStore'; import { useCallStore } from './useCallStore'; +import { getPendingCall, hasPendingAnsweredCall, clearPendingCall } from './pendingCallStore'; import { store } from '../../store/auxStore'; import sdk from '../sdk'; import Navigation from '../../navigation/appNavigation'; import { parseStringToIceServers } from './parseStringToIceServers'; +import { CallIdUUIDModule } from '../../native/CallIdUUID'; import type { IceServer } from '../../../definitions/Voip'; import type { IDDPMessage } from '../../../definitions/IDDPMessage'; -const localCallIdMap: Record<string, string> = {}; - class MediaSessionInstance { private iceServers: IceServer[] = []; private iceGatheringTimeout: number = 5000; @@ -72,14 +71,34 @@ class MediaSessionInstance { call.emitter.on('stateChange', oldState => { console.log(`📊 ${oldState} → ${call.state}`); }); - const callUUID = (await randomUuid()).toLowerCase(); - localCallIdMap[callUUID] = call.callId; - const displayName = call.contact.displayName || call.contact.username || 'Unknown'; - RNCallKeep.displayIncomingCall(callUUID, displayName, displayName, 'generic', false); + // Use deterministic UUID v5 from callId - same as native side + const callUUID = CallIdUUIDModule.toUUID(call.callId); + + // Check if this call was already answered from a VoIP push (cold start scenario) + const pendingCall = getPendingCall(); + if (pendingCall && pendingCall.callId === call.callId && hasPendingAnsweredCall()) { + console.log('[VoIP] Processing pending answered call:', call.callId); + try { + await call.accept(); + RNCallKeep.setCurrentCallActive(callUUID); + // Set call in Zustand store and navigate to CallView + useCallStore.getState().setCall(call, callUUID); + Navigation.navigate('CallView', { callUUID }); + } catch (e) { + console.log('[VoIP] Error accepting pending call:', e); + RNCallKeep.endCall(callUUID); + } finally { + clearPendingCall(); + } + } else { + // Normal flow: display incoming call UI + const displayName = call.contact.displayName || call.contact.username || 'Unknown'; + RNCallKeep.displayIncomingCall(callUUID, displayName, displayName, 'generic', false); + } call.emitter.on('ended', () => { RNCallKeep.endCall(callUUID); - delete localCallIdMap[callUUID]; + clearPendingCall(); }); } }); @@ -87,9 +106,9 @@ class MediaSessionInstance { private configureRNCallKeep = () => { this.callKeepListeners.answerCall = RNCallKeep.addEventListener('answerCall', async ({ callUUID }) => { - const callId = localCallIdMap[callUUID]; const mainCall = this.instance?.getMainCall(); - if (mainCall && mainCall.callId === callId) { + // Compare using deterministic UUID conversion + if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { await mainCall.accept(); RNCallKeep.setCurrentCallActive(callUUID); // Set call in Zustand store and navigate to CallView @@ -101,9 +120,9 @@ class MediaSessionInstance { }); this.callKeepListeners.endCall = RNCallKeep.addEventListener('endCall', ({ callUUID }) => { - const callId = localCallIdMap[callUUID]; const mainCall = this.instance?.getMainCall(); - if (mainCall && mainCall.callId === callId) { + // Compare using deterministic UUID conversion + if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { if (mainCall.state === 'ringing') { mainCall.reject(); } else { @@ -112,15 +131,14 @@ class MediaSessionInstance { } // Reset Zustand store useCallStore.getState().reset(); - delete localCallIdMap[callUUID]; }); this.callKeepListeners.didPerformSetMutedCallAction = RNCallKeep.addEventListener( 'didPerformSetMutedCallAction', ({ muted, callUUID }) => { - const callId = localCallIdMap[callUUID]; const mainCall = this.instance?.getMainCall(); - if (mainCall && mainCall.callId === callId) { + // Compare using deterministic UUID conversion + if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { mainCall.setMuted(muted); // Sync with Zustand store useCallStore.getState().updateFromCall(); @@ -129,9 +147,9 @@ class MediaSessionInstance { ); this.callKeepListeners.didPerformDTMFAction = RNCallKeep.addEventListener('didPerformDTMFAction', ({ digits, callUUID }) => { - const callId = localCallIdMap[callUUID]; const mainCall = this.instance?.getMainCall(); - if (mainCall && mainCall.callId === callId) { + // Compare using deterministic UUID conversion + if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { mainCall.sendDTMF(digits); } }); @@ -180,7 +198,6 @@ class MediaSessionInstance { this.instance.endSession(); } Object.values(this.callKeepListeners).forEach(listener => listener?.remove()); - Object.keys(localCallIdMap).forEach(key => delete localCallIdMap[key]); } } diff --git a/app/lib/services/voip/pendingCallStore.ts b/app/lib/services/voip/pendingCallStore.ts new file mode 100644 index 00000000000..6ebc2a5ef40 --- /dev/null +++ b/app/lib/services/voip/pendingCallStore.ts @@ -0,0 +1,91 @@ +/** + * Pending Call Store + * Stores call info from VoIP push notifications so JS can handle them when waking up. + * This is needed for the "app killed" scenario where native receives the VoIP push + * and shows CallKit before JS is fully initialized. + */ + +export interface PendingCall { + /** The server's call identifier */ + callId: string; + /** The CallKit UUID (derived from callId via UUID v5) */ + callUUID: string; + /** Caller display name */ + caller: string; + /** Server host URL (for server switching if needed) */ + host?: string; + /** Timestamp when the call was received */ + receivedAt: number; + /** Timestamp when the user answered (if answered) */ + answeredAt?: number; + /** Timestamp when the user declined (if declined) */ + declinedAt?: number; +} + +let pendingCall: PendingCall | null = null; + +/** + * Set a pending call from VoIP push notification. + * Called from index.js when a VoIP notification is received. + */ +export const setPendingCall = (call: Omit<PendingCall, 'receivedAt'>): void => { + pendingCall = { + ...call, + receivedAt: Date.now() + }; + console.log('[VoIP] Pending call set:', pendingCall.callId); +}; + +/** + * Get the current pending call (if any). + */ +export const getPendingCall = (): PendingCall | null => { + return pendingCall; +}; + +/** + * Mark the pending call as answered. + * Called when user answers via CallKit. + */ +export const markPendingCallAnswered = (): void => { + if (pendingCall) { + pendingCall.answeredAt = Date.now(); + console.log('[VoIP] Pending call marked as answered:', pendingCall.callId); + } +}; + +/** + * Mark the pending call as declined. + * Called when user declines via CallKit. + */ +export const markPendingCallDeclined = (): void => { + if (pendingCall) { + pendingCall.declinedAt = Date.now(); + console.log('[VoIP] Pending call marked as declined:', pendingCall.callId); + } +}; + +/** + * Clear the pending call. + * Called after the call has been processed by MediaSessionInstance. + */ +export const clearPendingCall = (): void => { + if (pendingCall) { + console.log('[VoIP] Pending call cleared:', pendingCall.callId); + } + pendingCall = null; +}; + +/** + * Check if there's a pending answered call. + */ +export const hasPendingAnsweredCall = (): boolean => { + return pendingCall !== null && pendingCall.answeredAt !== undefined && pendingCall.declinedAt === undefined; +}; + +/** + * Check if there's any pending call. + */ +export const hasPendingCall = (): boolean => { + return pendingCall !== null; +}; diff --git a/app/sagas/deepLinking.js b/app/sagas/deepLinking.js index 7afcadc7b92..d6033693698 100644 --- a/app/sagas/deepLinking.js +++ b/app/sagas/deepLinking.js @@ -297,8 +297,76 @@ const handleClickCallPush = function* handleClickCallPush({ params }) { } }; +/** + * Handle VoIP call from push notification. + * Ensures the app is connected to the correct server before the call can be processed. + * The actual call handling is done by MediaSessionInstance via the pending call store. + */ +const handleVoipCall = function* handleVoipCall({ params }) { + let { host } = params; + + console.log('[VoIP] handleVoipCall:', params); + + if (!host) { + // No host specified, assume current server + console.log('[VoIP] No host specified, using current server'); + return; + } + + // Normalize host URL + if (!/^(http|https)/.test(host)) { + if (/^localhost(:\d+)?/.test(host)) { + host = `http://${host}`; + } else { + host = `https://${host}`; + } + } else { + host = host.replace('http://', 'https://'); + } + if (host.slice(-1) === '/') { + host = host.slice(0, host.length - 1); + } + + const [server, user] = yield all([ + UserPreferences.getString(CURRENT_SERVER), + UserPreferences.getString(`${TOKEN_KEY}-${host}`) + ]); + + const serverRecord = yield getServerById(host); + + // If already connected to the correct server, nothing to do + // MediaSessionInstance will handle the call via pending store + if (server === host && user && serverRecord) { + const connected = yield select(state => state.server.connected); + if (!connected) { + console.log('[VoIP] Connecting to server:', host); + yield localAuthenticate(host); + yield put(selectServerRequest(host, serverRecord.version, true)); + yield take(types.LOGIN.SUCCESS); + console.log('[VoIP] Connected to server:', host); + } else { + console.log('[VoIP] Already connected to server:', host); + } + return; + } + + // Need to switch to a different server + if (user && serverRecord) { + console.log('[VoIP] Switching to server:', host); + yield localAuthenticate(host); + yield put(selectServerRequest(host, serverRecord.version, true, true)); + yield take(types.LOGIN.SUCCESS); + console.log('[VoIP] Switched to server:', host); + return; + } + + // Server not registered - can't handle this call + console.log('[VoIP] Server not registered, cannot handle call:', host); +}; + const root = function* root() { yield takeLatest(types.DEEP_LINKING.OPEN, handleOpen); yield takeLatest(types.DEEP_LINKING.OPEN_VIDEO_CONF, handleClickCallPush); + yield takeLatest(types.DEEP_LINKING.VOIP_CALL, handleVoipCall); }; export default root; diff --git a/index.js b/index.js index 3aac1fca993..c59b4ea99cb 100644 --- a/index.js +++ b/index.js @@ -2,9 +2,66 @@ import 'react-native-gesture-handler'; import 'react-native-console-time-polyfill'; import { AppRegistry, LogBox } from 'react-native'; import VoipPushNotification from 'react-native-voip-push-notification'; +import RNCallKeep from 'react-native-callkeep'; import { name as appName } from './app.json'; -import { isAndroid, isIOS } from './app/lib/methods/helpers'; +import { isIOS } from './app/lib/methods/helpers'; +import { + setPendingCall, + markPendingCallAnswered, + markPendingCallDeclined, + getPendingCall +} from './app/lib/services/voip/pendingCallStore'; +import { CallIdUUIDModule } from './app/lib/native/CallIdUUID'; +import store from './app/lib/store'; +import { voipCallOpen } from './app/actions/deepLinking'; + +/** + * Handle VoIP push notification received. + * Stores the call info in pending store for later processing. + */ +const handleVoipNotification = notification => { + console.log('[VoIP] Notification Received:', notification); + const { callId, caller, host } = notification; + + if (callId) { + const callUUID = CallIdUUIDModule.toUUID(callId); + setPendingCall({ + callId, + callUUID, + caller: caller || 'Unknown', + host + }); + } + + // Mark notification as completed + if (notification.uuid) { + VoipPushNotification.onVoipNotificationCompleted(notification.uuid); + } +}; + +/** + * Handle CallKeep answer call event (from cold start). + * This fires when user answered before JS was fully initialized. + */ +const handleCallKeepAnswerCall = ({ callUUID }) => { + console.log('[VoIP] CallKeep answerCall from cold start:', callUUID); + markPendingCallAnswered(); + + // Dispatch action to handle server switching and call connection + const pendingCall = getPendingCall(); + if (pendingCall && pendingCall.host) { + store.dispatch(voipCallOpen({ callId: pendingCall.callId, callUUID, host: pendingCall.host })); + } +}; + +/** + * Handle CallKeep end call event (from cold start). + */ +const handleCallKeepEndCall = ({ callUUID }) => { + console.log('[VoIP] CallKeep endCall from cold start:', callUUID); + markPendingCallDeclined(); +}; if (process.env.USE_STORYBOOK) { AppRegistry.registerComponent(appName, () => require('./.rnstorybook/index').default); @@ -24,32 +81,46 @@ if (process.env.USE_STORYBOOK) { LogBox.ignoreAllLogs(); if (isIOS) { + // VoIP Push Notification handlers VoipPushNotification.addEventListener('register', token => { - console.log('VoIP Token:', token); - // Send token to your server + console.log('[VoIP] Token:', token); + // Token will be sent to server during login }); - VoipPushNotification.addEventListener('notification', notification => { - console.log('VoIP Notification Received:', notification); - const { uuid, callerName, handle } = notification; - - VoipPushNotification.onVoipNotificationCompleted(uuid); - }); + VoipPushNotification.addEventListener('notification', handleVoipNotification); VoipPushNotification.addEventListener('didLoadWithEvents', events => { if (!events || !Array.isArray(events) || events.length < 1) { return; } + console.log('[VoIP] didLoadWithEvents:', events.length, 'events'); for (const voipPushEvent of events) { const { name, data } = voipPushEvent; - console.log('didLoadWithEvents', voipPushEvent); if (name === VoipPushNotification.RNVoipPushRemoteNotificationsRegisteredEvent) { - console.log('didLoadWithEvents VoIP Token: ', data); + console.log('[VoIP] Token from cold start:', data); } else if (name === VoipPushNotification.RNVoipPushRemoteNotificationReceivedEvent) { - // onVoipPushNotificationiReceived(data); + handleVoipNotification(data); + } + } + }); + + // CallKeep handlers for cold start scenario + // These handle events that occurred before JS was initialized + RNCallKeep.addEventListener('didLoadWithEvents', events => { + if (!events || !Array.isArray(events) || events.length < 1) { + return; + } + console.log('[VoIP] CallKeep didLoadWithEvents:', events.length, 'events'); + for (const event of events) { + const { name, data } = event; + if (name === 'RNCallKeepPerformAnswerCallAction') { + handleCallKeepAnswerCall(data); + } else if (name === 'RNCallKeepPerformEndCallAction') { + handleCallKeepEndCall(data); } } }); + VoipPushNotification.registerVoipToken(); } diff --git a/ios/AppDelegate.swift b/ios/AppDelegate.swift index 3dcb2241484..3bd831b45e0 100644 --- a/ios/AppDelegate.swift +++ b/ios/AppDelegate.swift @@ -111,25 +111,25 @@ extension AppDelegate: PKPushRegistryDelegate { } public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { - // let uuid = UUID().uuidString.lowercased() - let callerName = payload.dictionaryPayload["caller"] as? String let callId = payload.dictionaryPayload["callId"] as? String - let handle = payload.dictionaryPayload["caller"] as? String + let caller = payload.dictionaryPayload["caller"] as? String - let callIdUUID = UUID(uuidString: callId ?? "")?.uuidString.lowercased() - if callIdUUID == nil { + guard let callId = callId else { completion() return } + + // Convert callId to deterministic UUID v5 for CallKit + let callIdUUID = CallIdUUID.generateUUIDv5(from: callId) RNVoipPushNotificationManager.didReceiveIncomingPush(with: payload, forType: type.rawValue) RNCallKeep.reportNewIncomingCall( callIdUUID, - handle: handle, + handle: caller, handleType: "generic", hasVideo: true, - localizedCallerName: callerName, + localizedCallerName: caller, supportsHolding: true, supportsDTMF: true, supportsGrouping: true, diff --git a/ios/CallIdUUID.m b/ios/CallIdUUID.m new file mode 100644 index 00000000000..019b69f4938 --- /dev/null +++ b/ios/CallIdUUID.m @@ -0,0 +1,7 @@ +#import <React/RCTBridgeModule.h> + +@interface RCT_EXTERN_MODULE(CallIdUUID, NSObject) + +RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(toUUID:(NSString *)callId) + +@end diff --git a/ios/CallIdUUID.swift b/ios/CallIdUUID.swift new file mode 100644 index 00000000000..8318e45d36b --- /dev/null +++ b/ios/CallIdUUID.swift @@ -0,0 +1,67 @@ +import Foundation +import CommonCrypto + +/** + * CallIdUUID - Converts a callId string to a deterministic UUID v5. + * This is used by CallKit which requires UUIDs, while the server sends random callId strings. + */ +@objc(CallIdUUID) +final class CallIdUUID: NSObject { + + // Fixed namespace UUID for VoIP calls (RFC 4122 URL namespace) + // Using the standard URL namespace UUID: 6ba7b811-9dad-11d1-80b4-00c04fd430c8 + private static let namespaceUUID: [UInt8] = [ + 0x6b, 0xa7, 0xb8, 0x11, + 0x9d, 0xad, + 0x11, 0xd1, + 0x80, 0xb4, + 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + ] + + @objc + static func requiresMainQueueSetup() -> Bool { + return false + } + + /** + * Converts a callId string to a deterministic UUID v5 string. + * Uses SHA-1 hash of namespace + callId, then formats as UUID v5. + * This is a synchronous method for use from JavaScript. + */ + @objc + func toUUID(_ callId: String) -> String { + return CallIdUUID.generateUUIDv5(from: callId) + } + + /** + * Static method for use in AppDelegate and other native code. + * Generates a UUID v5 from a callId string. + */ + static func generateUUIDv5(from callId: String) -> String { + // Concatenate namespace UUID bytes with callId UTF-8 bytes + var data = Data(namespaceUUID) + data.append(callId.data(using: .utf8) ?? Data()) + + // SHA-1 hash + var hash = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH)) + data.withUnsafeBytes { dataBytes in + _ = CC_SHA1(dataBytes.baseAddress, CC_LONG(data.count), &hash) + } + + // Set version (4 bits) to 5 (0101) + hash[6] = (hash[6] & 0x0F) | 0x50 + + // Set variant (2 bits) to 10 + hash[8] = (hash[8] & 0x3F) | 0x80 + + // Format as UUID string (only use first 16 bytes) + let uuid = String(format: "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + hash[0], hash[1], hash[2], hash[3], + hash[4], hash[5], + hash[6], hash[7], + hash[8], hash[9], + hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]) + + return uuid + } +} diff --git a/ios/A11yFlowModule.h b/ios/Libraries/A11yFlowModule.h similarity index 100% rename from ios/A11yFlowModule.h rename to ios/Libraries/A11yFlowModule.h diff --git a/ios/A11yFlowModule.m b/ios/Libraries/A11yFlowModule.m similarity index 100% rename from ios/A11yFlowModule.m rename to ios/Libraries/A11yFlowModule.m diff --git a/ios/Libraries/CallIdUUID.m b/ios/Libraries/CallIdUUID.m new file mode 100644 index 00000000000..019b69f4938 --- /dev/null +++ b/ios/Libraries/CallIdUUID.m @@ -0,0 +1,7 @@ +#import <React/RCTBridgeModule.h> + +@interface RCT_EXTERN_MODULE(CallIdUUID, NSObject) + +RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(toUUID:(NSString *)callId) + +@end diff --git a/ios/Libraries/CallIdUUID.swift b/ios/Libraries/CallIdUUID.swift new file mode 100644 index 00000000000..8318e45d36b --- /dev/null +++ b/ios/Libraries/CallIdUUID.swift @@ -0,0 +1,67 @@ +import Foundation +import CommonCrypto + +/** + * CallIdUUID - Converts a callId string to a deterministic UUID v5. + * This is used by CallKit which requires UUIDs, while the server sends random callId strings. + */ +@objc(CallIdUUID) +final class CallIdUUID: NSObject { + + // Fixed namespace UUID for VoIP calls (RFC 4122 URL namespace) + // Using the standard URL namespace UUID: 6ba7b811-9dad-11d1-80b4-00c04fd430c8 + private static let namespaceUUID: [UInt8] = [ + 0x6b, 0xa7, 0xb8, 0x11, + 0x9d, 0xad, + 0x11, 0xd1, + 0x80, 0xb4, + 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + ] + + @objc + static func requiresMainQueueSetup() -> Bool { + return false + } + + /** + * Converts a callId string to a deterministic UUID v5 string. + * Uses SHA-1 hash of namespace + callId, then formats as UUID v5. + * This is a synchronous method for use from JavaScript. + */ + @objc + func toUUID(_ callId: String) -> String { + return CallIdUUID.generateUUIDv5(from: callId) + } + + /** + * Static method for use in AppDelegate and other native code. + * Generates a UUID v5 from a callId string. + */ + static func generateUUIDv5(from callId: String) -> String { + // Concatenate namespace UUID bytes with callId UTF-8 bytes + var data = Data(namespaceUUID) + data.append(callId.data(using: .utf8) ?? Data()) + + // SHA-1 hash + var hash = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH)) + data.withUnsafeBytes { dataBytes in + _ = CC_SHA1(dataBytes.baseAddress, CC_LONG(data.count), &hash) + } + + // Set version (4 bits) to 5 (0101) + hash[6] = (hash[6] & 0x0F) | 0x50 + + // Set variant (2 bits) to 10 + hash[8] = (hash[8] & 0x3F) | 0x80 + + // Format as UUID string (only use first 16 bytes) + let uuid = String(format: "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + hash[0], hash[1], hash[2], hash[3], + hash[4], hash[5], + hash[6], hash[7], + hash[8], hash[9], + hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]) + + return uuid + } +} diff --git a/ios/MMKVKeyManager.h b/ios/Libraries/MMKVKeyManager.h similarity index 100% rename from ios/MMKVKeyManager.h rename to ios/Libraries/MMKVKeyManager.h diff --git a/ios/MMKVKeyManager.mm b/ios/Libraries/MMKVKeyManager.mm similarity index 98% rename from ios/MMKVKeyManager.mm rename to ios/Libraries/MMKVKeyManager.mm index 5a26b2f13f0..579f1633d79 100644 --- a/ios/MMKVKeyManager.mm +++ b/ios/Libraries/MMKVKeyManager.mm @@ -9,7 +9,7 @@ #import "MMKVKeyManager.h" #import "SecureStorage.h" -#import "Shared/RocketChat/MMKVBridge.h" +#import "../Shared/RocketChat/MMKVBridge.h" static NSString *toHex(NSString *str) { if (!str) return @""; diff --git a/ios/SSLPinning.h b/ios/Libraries/SSLPinning.h similarity index 100% rename from ios/SSLPinning.h rename to ios/Libraries/SSLPinning.h diff --git a/ios/SSLPinning.mm b/ios/Libraries/SSLPinning.mm similarity index 99% rename from ios/SSLPinning.mm rename to ios/Libraries/SSLPinning.mm index ef863c3fd22..571b1ca9a8d 100644 --- a/ios/SSLPinning.mm +++ b/ios/Libraries/SSLPinning.mm @@ -8,7 +8,7 @@ #import <objc/runtime.h> #import "SSLPinning.h" -#import "Shared/RocketChat/MMKVBridge.h" +#import "../Shared/RocketChat/MMKVBridge.h" #import <SDWebImage/SDWebImageDownloader.h> #import "SecureStorage.h" #import "SRWebSocket.h" diff --git a/ios/SecureStorage.h b/ios/Libraries/SecureStorage.h similarity index 100% rename from ios/SecureStorage.h rename to ios/Libraries/SecureStorage.h diff --git a/ios/SecureStorage.m b/ios/Libraries/SecureStorage.m similarity index 100% rename from ios/SecureStorage.m rename to ios/Libraries/SecureStorage.m diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index 6dacd17fe10..777d9738899 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -289,8 +289,6 @@ 66C2701B2EBBCB570062725F /* MMKVKeyManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */; }; 66C2701C2EBBCB570062725F /* MMKVKeyManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */; }; 66C2701D2EBBCB570062725F /* MMKVKeyManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */; }; - 66C270202EBBCB780062725F /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701F2EBBCB780062725F /* SecureStorage.m */; }; - 66C270212EBBCB780062725F /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701F2EBBCB780062725F /* SecureStorage.m */; }; 79D8C97F8CE2EC1B6882826B /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A42CFB843397273C7EA /* SecureStorage.m */; }; 7A006F14229C83B600803143 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7A006F13229C83B600803143 /* GoogleService-Info.plist */; }; 7A0129D42C6E8EC800F84A97 /* ShareRocketChatRN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0129D22C6E8B5900F84A97 /* ShareRocketChatRN.swift */; }; @@ -299,6 +297,10 @@ 7A0D62D2242AB187006D5C06 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */; }; 7A14FCED257FEB3A005BDCD4 /* Experimental.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A14FCEC257FEB3A005BDCD4 /* Experimental.xcassets */; }; 7A14FCF4257FEB59005BDCD4 /* Official.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A14FCF3257FEB59005BDCD4 /* Official.xcassets */; }; + 7A3F4C6B2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F4C6A2F1AAFA700B6B4BD /* CallIdUUID.swift */; }; + 7A3F4C6C2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F4C692F1AAFA700B6B4BD /* CallIdUUID.m */; }; + 7A3F4C6D2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F4C6A2F1AAFA700B6B4BD /* CallIdUUID.swift */; }; + 7A3F4C6E2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F4C692F1AAFA700B6B4BD /* CallIdUUID.m */; }; 7A610CD227ECE38100B8ABDD /* custom.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7A610CD127ECE38100B8ABDD /* custom.ttf */; }; 7A610CD427ECE38100B8ABDD /* custom.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7A610CD127ECE38100B8ABDD /* custom.ttf */; }; 7A610CD527ECE38100B8ABDD /* custom.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7A610CD127ECE38100B8ABDD /* custom.ttf */; }; @@ -464,7 +466,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; }; + 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file; path = main.jsbundle; sourceTree = "<group>"; }; 06BB44DD4855498082A744AD /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 13B07F961A680F5B00A75B9A /* Rocket.Chat Experimental.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Rocket.Chat Experimental.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RocketChatRN/Images.xcassets; sourceTree = "<group>"; }; @@ -624,13 +626,13 @@ 65B9A7192AFC24190088956F /* ringtone.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ringtone.mp3; sourceTree = "<group>"; }; 66C270192EBBCB570062725F /* MMKVKeyManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMKVKeyManager.h; sourceTree = "<group>"; }; 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MMKVKeyManager.mm; sourceTree = "<group>"; }; - 66C2701E2EBBCB780062725F /* SecureStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecureStorage.h; sourceTree = "<group>"; }; - 66C2701F2EBBCB780062725F /* SecureStorage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecureStorage.m; sourceTree = "<group>"; }; 7A006F13229C83B600803143 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; }; 7A0129D22C6E8B5900F84A97 /* ShareRocketChatRN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareRocketChatRN.swift; sourceTree = "<group>"; }; 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; }; 7A14FCEC257FEB3A005BDCD4 /* Experimental.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Experimental.xcassets; sourceTree = "<group>"; }; 7A14FCF3257FEB59005BDCD4 /* Official.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Official.xcassets; sourceTree = "<group>"; }; + 7A3F4C692F1AAFA700B6B4BD /* CallIdUUID.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CallIdUUID.m; sourceTree = "<group>"; }; + 7A3F4C6A2F1AAFA700B6B4BD /* CallIdUUID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallIdUUID.swift; sourceTree = "<group>"; }; 7A610CD127ECE38100B8ABDD /* custom.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = custom.ttf; sourceTree = "<group>"; }; 7A8B30742BCD9D3F00146A40 /* SSLPinning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSLPinning.h; sourceTree = "<group>"; }; 7A8B30752BCD9D3F00146A40 /* SSLPinning.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SSLPinning.mm; sourceTree = "<group>"; }; @@ -725,13 +727,7 @@ 13B07FAE1A68108700A75B9A /* RocketChatRN */ = { isa = PBXGroup; children = ( - 66C2701E2EBBCB780062725F /* SecureStorage.h */, - 66C2701F2EBBCB780062725F /* SecureStorage.m */, 7ACFE7D82DDE48760090D9BC /* AppDelegate.swift */, - A48B46D72D3FFBD200945489 /* A11yFlowModule.h */, - A48B46D82D3FFBD200945489 /* A11yFlowModule.m */, - 7A8B30742BCD9D3F00146A40 /* SSLPinning.h */, - 7A8B30752BCD9D3F00146A40 /* SSLPinning.mm */, 65B9A7192AFC24190088956F /* ringtone.mp3 */, 7A006F13229C83B600803143 /* GoogleService-Info.plist */, 60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */, @@ -744,8 +740,6 @@ 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */, 1ED00BB02513E04400A1331F /* ReplyNotification.swift */, 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */, - 66C270192EBBCB570062725F /* MMKVKeyManager.h */, - 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */, ); name = RocketChatRN; sourceTree = "<group>"; @@ -1140,6 +1134,23 @@ name = ExpoModulesProviders; sourceTree = "<group>"; }; + 7A76DEE42F1AA6EF00750653 /* Libraries */ = { + isa = PBXGroup; + children = ( + 7A3F4C692F1AAFA700B6B4BD /* CallIdUUID.m */, + 7A3F4C6A2F1AAFA700B6B4BD /* CallIdUUID.swift */, + B179038FDD7AAF285047814B /* SecureStorage.h */, + 9B215A42CFB843397273C7EA /* SecureStorage.m */, + A48B46D72D3FFBD200945489 /* A11yFlowModule.h */, + A48B46D82D3FFBD200945489 /* A11yFlowModule.m */, + 66C270192EBBCB570062725F /* MMKVKeyManager.h */, + 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */, + 7A8B30742BCD9D3F00146A40 /* SSLPinning.h */, + 7A8B30752BCD9D3F00146A40 /* SSLPinning.mm */, + ); + path = Libraries; + sourceTree = "<group>"; + }; 7AC2B09613AA7C3FEBAC9F57 /* Pods */ = { isa = PBXGroup; children = ( @@ -1153,13 +1164,6 @@ path = Pods; sourceTree = "<group>"; }; - 832341AE1AAA6A7D00B99B32 /* Libraries */ = { - isa = PBXGroup; - children = ( - ); - name = Libraries; - sourceTree = "<group>"; - }; 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( @@ -1168,7 +1172,7 @@ 1E76CBC425152A7F0067298C /* Shared */, 1E068CFB24FD2DAF00A0FFC1 /* AppGroup */, 13B07FAE1A68108700A75B9A /* RocketChatRN */, - 832341AE1AAA6A7D00B99B32 /* Libraries */, + 7A76DEE42F1AA6EF00750653 /* Libraries */, 1EC6ACB122CB9FC300A41C61 /* ShareRocketChatRN */, 1EFEB5962493B6640072EDC0 /* NotificationService */, 1ED0388F2B507B4C00C007D4 /* RocketChat Watch App */, @@ -1178,8 +1182,6 @@ B8E79A681F3CCC69005B464F /* Recovered References */, 7AC2B09613AA7C3FEBAC9F57 /* Pods */, 7890E71355E6C0A3288089E7 /* ExpoModulesProviders */, - B179038FDD7AAF285047814B /* SecureStorage.h */, - 9B215A42CFB843397273C7EA /* SecureStorage.m */, ); indentWidth = 4; sourceTree = "<group>"; @@ -1551,7 +1553,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\"\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; + shellScript = "export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\"\nexport NODE_BINARY=/Users/diegomello/.nvm/versions/node/v22.14.0/bin/node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; }; 06C10D4F29CD7532492AD29E /* [Expo] Configure project */ = { isa = PBXShellScriptBuildPhase; @@ -1825,7 +1827,7 @@ inputFileListPaths = ( ); inputPaths = ( - "$TARGET_BUILD_DIR/$INFOPLIST_PATH", + $TARGET_BUILD_DIR/$INFOPLIST_PATH, ); name = "Upload source maps to Bugsnag"; outputFileListPaths = ( @@ -1845,7 +1847,7 @@ inputFileListPaths = ( ); inputPaths = ( - "$TARGET_BUILD_DIR/$INFOPLIST_PATH", + $TARGET_BUILD_DIR/$INFOPLIST_PATH, ); name = "Upload source maps to Bugsnag"; outputFileListPaths = ( @@ -1854,7 +1856,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "SOURCE_MAP=\"$TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh\n"; + shellScript = "#SOURCE_MAP=\"$TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh\n"; showEnvVarsInLog = 0; }; 86A998705576AFA7CE938617 /* [Expo] Configure project */ = { @@ -2049,6 +2051,8 @@ 1E76CBD825152C870067298C /* Request.swift in Sources */, 1E51411C2B85683C007BE94A /* SSLPinning.m in Sources */, 66C2701B2EBBCB570062725F /* MMKVKeyManager.mm in Sources */, + 7A3F4C6B2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */, + 7A3F4C6C2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */, 1ED00BB12513E04400A1331F /* ReplyNotification.swift in Sources */, 1E76CBC2251529560067298C /* Storage.swift in Sources */, 1E76CBD925152C8C0067298C /* Push.swift in Sources */, @@ -2086,7 +2090,6 @@ 7A8B30762BCD9D3F00146A40 /* SSLPinning.mm in Sources */, 1E76CBCF25152C310067298C /* NotificationType.swift in Sources */, 1E76CBDA25152C8E0067298C /* SendMessage.swift in Sources */, - 66C270212EBBCB780062725F /* SecureStorage.m in Sources */, 4C4C8603EF082F0A33A95522 /* ExpoModulesProvider.swift in Sources */, A2C6E2DD38F8BEE19BFB2E1D /* SecureStorage.m in Sources */, ); @@ -2324,6 +2327,8 @@ 7AAB3E16257E6A6E00707CF6 /* Request.swift in Sources */, 1E51411D2B85683C007BE94A /* SSLPinning.m in Sources */, 66C2701C2EBBCB570062725F /* MMKVKeyManager.mm in Sources */, + 7A3F4C6D2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */, + 7A3F4C6E2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */, 7AAB3E17257E6A6E00707CF6 /* ReplyNotification.swift in Sources */, 7AAB3E18257E6A6E00707CF6 /* Storage.swift in Sources */, 7AAB3E19257E6A6E00707CF6 /* Push.swift in Sources */, @@ -2361,7 +2366,6 @@ 7A8B30772BCD9D3F00146A40 /* SSLPinning.mm in Sources */, 7AAB3E30257E6A6E00707CF6 /* NotificationType.swift in Sources */, 7AAB3E31257E6A6E00707CF6 /* SendMessage.swift in Sources */, - 66C270202EBBCB780062725F /* SecureStorage.m in Sources */, BC404914E86821389EEB543D /* ExpoModulesProvider.swift in Sources */, 79D8C97F8CE2EC1B6882826B /* SecureStorage.m in Sources */, ); @@ -2597,7 +2601,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/rn-extensions-share/ios/**", "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - "$PODS_CONFIGURATION_BUILD_DIR/Firebase", + $PODS_CONFIGURATION_BUILD_DIR/Firebase, ); INFOPLIST_FILE = ShareRocketChatRN/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.1; @@ -2673,7 +2677,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/rn-extensions-share/ios/**", "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - "$PODS_CONFIGURATION_BUILD_DIR/Firebase", + $PODS_CONFIGURATION_BUILD_DIR/Firebase, ); INFOPLIST_FILE = ShareRocketChatRN/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.1; @@ -3198,10 +3202,7 @@ ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = "$(inherited)"; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; @@ -3265,10 +3266,7 @@ MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = "$(inherited)"; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; From ac85af87a3c054e9022f566c5bdfe1ebff5f51f2 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 20 Jan 2026 09:57:41 -0300 Subject: [PATCH 23/61] Remove pending store and create getInitialEvents on app/index --- app/index.tsx | 4 + app/lib/services/voip/MediaSessionInstance.ts | 27 +--- app/lib/services/voip/getInitialEvents.ts | 115 ++++++++++++++++++ app/lib/services/voip/pendingCallStore.ts | 91 -------------- index.js | 103 ---------------- 5 files changed, 122 insertions(+), 218 deletions(-) create mode 100644 app/lib/services/voip/getInitialEvents.ts delete mode 100644 app/lib/services/voip/pendingCallStore.ts diff --git a/app/index.tsx b/app/index.tsx index 88f8347445f..698610a68a5 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -5,6 +5,7 @@ import { SafeAreaProvider } from 'react-native-safe-area-context'; import { enableScreens } from 'react-native-screens'; import { Provider } from 'react-redux'; import { KeyboardProvider } from 'react-native-keyboard-controller'; +import RNCallKeep from 'react-native-callkeep'; import ResponsiveLayoutProvider from './lib/hooks/useResponsiveLayout/useResponsiveLayout'; import AppContainer from './AppContainer'; @@ -39,6 +40,7 @@ import { type TSupportedThemes, ThemeContext } from './theme'; import ChangePasscodeView from './views/ChangePasscodeView'; import ScreenLockedView from './views/ScreenLockedView'; import StatusBar from './containers/StatusBar'; +import { getInitialEvents } from './lib/services/voip/getInitialEvents'; enableScreens(); initStore(store); @@ -148,6 +150,8 @@ export default class Root extends React.Component<{}, IState> { return; } + await getInitialEvents(); + // Open app from deep linking const deepLinking = await Linking.getInitialURL(); const parsedDeepLinkingURL = parseDeepLinking(deepLinking!); diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index d67b9777a0c..ad0f0860a64 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -10,7 +10,6 @@ import { registerGlobals } from 'react-native-webrtc'; import { mediaSessionStore } from './MediaSessionStore'; import { useCallStore } from './useCallStore'; -import { getPendingCall, hasPendingAnsweredCall, clearPendingCall } from './pendingCallStore'; import { store } from '../../store/auxStore'; import sdk from '../sdk'; import Navigation from '../../navigation/appNavigation'; @@ -66,7 +65,7 @@ class MediaSessionInstance { this.instance.processSignal(signal); }); - this.instance?.on('newCall', async ({ call }: { call: IClientMediaCall }) => { + this.instance?.on('newCall', ({ call }: { call: IClientMediaCall }) => { if (call && !call.hidden) { call.emitter.on('stateChange', oldState => { console.log(`📊 ${oldState} → ${call.state}`); @@ -74,31 +73,11 @@ class MediaSessionInstance { // Use deterministic UUID v5 from callId - same as native side const callUUID = CallIdUUIDModule.toUUID(call.callId); - // Check if this call was already answered from a VoIP push (cold start scenario) - const pendingCall = getPendingCall(); - if (pendingCall && pendingCall.callId === call.callId && hasPendingAnsweredCall()) { - console.log('[VoIP] Processing pending answered call:', call.callId); - try { - await call.accept(); - RNCallKeep.setCurrentCallActive(callUUID); - // Set call in Zustand store and navigate to CallView - useCallStore.getState().setCall(call, callUUID); - Navigation.navigate('CallView', { callUUID }); - } catch (e) { - console.log('[VoIP] Error accepting pending call:', e); - RNCallKeep.endCall(callUUID); - } finally { - clearPendingCall(); - } - } else { - // Normal flow: display incoming call UI - const displayName = call.contact.displayName || call.contact.username || 'Unknown'; - RNCallKeep.displayIncomingCall(callUUID, displayName, displayName, 'generic', false); - } + const displayName = call.contact.displayName || call.contact.username || 'Unknown'; + RNCallKeep.displayIncomingCall(callUUID, displayName, displayName, 'generic', false); call.emitter.on('ended', () => { RNCallKeep.endCall(callUUID); - clearPendingCall(); }); } }); diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts new file mode 100644 index 00000000000..90d81ec4dc3 --- /dev/null +++ b/app/lib/services/voip/getInitialEvents.ts @@ -0,0 +1,115 @@ +import RNCallKeep from 'react-native-callkeep'; +import VoipPushNotification from 'react-native-voip-push-notification'; + +import { isIOS } from '../../methods/helpers'; +import { CallIdUUIDModule } from '../../native/CallIdUUID'; +import store from '../../store'; +import { voipCallOpen } from '../../../actions/deepLinking'; + +// const options = { +// ios: { +// appName: 'Rocket.Chat', +// supportsVideo: true, +// maximumCallGroups: 1, +// maximumCallsPerCallGroup: 1, +// includesCallsInRecents: false +// }, +// android: { +// alertTitle: 'Permissions required', +// alertDescription: 'This application needs to access your phone accounts', +// cancelButton: 'Cancel', +// okButton: 'ok' +// } +// }; + +// Store VoIP push data temporarily +let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; + +export const getInitialEvents = async () => { + if (!isIOS) { + return null; + } + + try { + // 1. Setup CallKeep FIRST (if not already done in native) + // Note: Setup is already done in AppDelegate.swift, but we need to ensure JS side is ready + // await RNCallKeep.setup(options); + // console.log('[CallKeep][getInitialEvents] Setup completed'); + + // 2. Get VoIP push events from didLoadWithEvents + VoipPushNotification.addEventListener('didLoadWithEvents', events => { + if (!events || !Array.isArray(events)) return; + + for (const event of events) { + const { name, data } = event; + + if (name === VoipPushNotification.RNVoipPushRemoteNotificationReceivedEvent) { + const { callId, caller, host } = data; + if (callId) { + const callUUID = CallIdUUIDModule.toUUID(callId); + voipPushData = { callId, caller, host, callUUID }; + console.log('[VoIP][getInitialEvents] Stored VoIP push data:', voipPushData); + } + } + } + }); + + RNCallKeep.addEventListener('answerCall', ({ callUUID }) => { + console.log('[CallKeep][getInitialEvents] Live answerCall event received:', callUUID); + + if (voipPushData && voipPushData.callUUID.toLowerCase() === callUUID.toLowerCase()) { + console.log('[CallKeep][getInitialEvents] Matched live answer to VoIP call'); + // handleAnsweredCall(voipPushData); + } else { + console.log('[CallKeep][getInitialEvents] Live answer UUID mismatch. Answer:', callUUID, 'VoIP:', voipPushData?.callUUID); + } + }); + + // 3. Get CallKeep initial events AFTER setup + const initialEvents = await RNCallKeep.getInitialEvents(); + console.log('[CallKeep][getInitialEvents] Initial events:', JSON.stringify(initialEvents, null, 2)); + + // 4. Process answer events + for (const event of initialEvents) { + const { name, data } = event; + + if (name === 'RNCallKeepPerformAnswerCallAction') { + const { callUUID } = data; + console.log('[CallKeep][getInitialEvents] Found ANSWER event:', callUUID); + + // Match to VoIP push data + if (voipPushData && voipPushData.callUUID.toLowerCase() === callUUID.toLowerCase()) { + console.log('[CallKeep][getInitialEvents] Matched answer to VoIP call:', voipPushData); + + // Dispatch action to handle server switching and call connection + if (voipPushData.host) { + store.dispatch( + voipCallOpen({ + callId: voipPushData.callId, + callUUID: voipPushData.callUUID, + host: voipPushData.host + }) + ); + console.log('[CallKeep][getInitialEvents] Dispatched voipCallOpen action'); + + // Clear events after processing + RNCallKeep.clearInitialEvents(); + return { answered: true, callData: voipPushData }; + } + } else { + console.log('[CallKeep][getInitialEvents] Answer event UUID does not match VoIP push UUID'); + } + } + } + + // Clear events if processed + if (initialEvents.length > 0) { + RNCallKeep.clearInitialEvents(); + } + + return { answered: false }; + } catch (error) { + console.error('[CallKeep][getInitialEvents] Error:', error); + return null; + } +}; diff --git a/app/lib/services/voip/pendingCallStore.ts b/app/lib/services/voip/pendingCallStore.ts deleted file mode 100644 index 6ebc2a5ef40..00000000000 --- a/app/lib/services/voip/pendingCallStore.ts +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Pending Call Store - * Stores call info from VoIP push notifications so JS can handle them when waking up. - * This is needed for the "app killed" scenario where native receives the VoIP push - * and shows CallKit before JS is fully initialized. - */ - -export interface PendingCall { - /** The server's call identifier */ - callId: string; - /** The CallKit UUID (derived from callId via UUID v5) */ - callUUID: string; - /** Caller display name */ - caller: string; - /** Server host URL (for server switching if needed) */ - host?: string; - /** Timestamp when the call was received */ - receivedAt: number; - /** Timestamp when the user answered (if answered) */ - answeredAt?: number; - /** Timestamp when the user declined (if declined) */ - declinedAt?: number; -} - -let pendingCall: PendingCall | null = null; - -/** - * Set a pending call from VoIP push notification. - * Called from index.js when a VoIP notification is received. - */ -export const setPendingCall = (call: Omit<PendingCall, 'receivedAt'>): void => { - pendingCall = { - ...call, - receivedAt: Date.now() - }; - console.log('[VoIP] Pending call set:', pendingCall.callId); -}; - -/** - * Get the current pending call (if any). - */ -export const getPendingCall = (): PendingCall | null => { - return pendingCall; -}; - -/** - * Mark the pending call as answered. - * Called when user answers via CallKit. - */ -export const markPendingCallAnswered = (): void => { - if (pendingCall) { - pendingCall.answeredAt = Date.now(); - console.log('[VoIP] Pending call marked as answered:', pendingCall.callId); - } -}; - -/** - * Mark the pending call as declined. - * Called when user declines via CallKit. - */ -export const markPendingCallDeclined = (): void => { - if (pendingCall) { - pendingCall.declinedAt = Date.now(); - console.log('[VoIP] Pending call marked as declined:', pendingCall.callId); - } -}; - -/** - * Clear the pending call. - * Called after the call has been processed by MediaSessionInstance. - */ -export const clearPendingCall = (): void => { - if (pendingCall) { - console.log('[VoIP] Pending call cleared:', pendingCall.callId); - } - pendingCall = null; -}; - -/** - * Check if there's a pending answered call. - */ -export const hasPendingAnsweredCall = (): boolean => { - return pendingCall !== null && pendingCall.answeredAt !== undefined && pendingCall.declinedAt === undefined; -}; - -/** - * Check if there's any pending call. - */ -export const hasPendingCall = (): boolean => { - return pendingCall !== null; -}; diff --git a/index.js b/index.js index c59b4ea99cb..626e7082141 100644 --- a/index.js +++ b/index.js @@ -1,67 +1,8 @@ import 'react-native-gesture-handler'; import 'react-native-console-time-polyfill'; import { AppRegistry, LogBox } from 'react-native'; -import VoipPushNotification from 'react-native-voip-push-notification'; -import RNCallKeep from 'react-native-callkeep'; import { name as appName } from './app.json'; -import { isIOS } from './app/lib/methods/helpers'; -import { - setPendingCall, - markPendingCallAnswered, - markPendingCallDeclined, - getPendingCall -} from './app/lib/services/voip/pendingCallStore'; -import { CallIdUUIDModule } from './app/lib/native/CallIdUUID'; -import store from './app/lib/store'; -import { voipCallOpen } from './app/actions/deepLinking'; - -/** - * Handle VoIP push notification received. - * Stores the call info in pending store for later processing. - */ -const handleVoipNotification = notification => { - console.log('[VoIP] Notification Received:', notification); - const { callId, caller, host } = notification; - - if (callId) { - const callUUID = CallIdUUIDModule.toUUID(callId); - setPendingCall({ - callId, - callUUID, - caller: caller || 'Unknown', - host - }); - } - - // Mark notification as completed - if (notification.uuid) { - VoipPushNotification.onVoipNotificationCompleted(notification.uuid); - } -}; - -/** - * Handle CallKeep answer call event (from cold start). - * This fires when user answered before JS was fully initialized. - */ -const handleCallKeepAnswerCall = ({ callUUID }) => { - console.log('[VoIP] CallKeep answerCall from cold start:', callUUID); - markPendingCallAnswered(); - - // Dispatch action to handle server switching and call connection - const pendingCall = getPendingCall(); - if (pendingCall && pendingCall.host) { - store.dispatch(voipCallOpen({ callId: pendingCall.callId, callUUID, host: pendingCall.host })); - } -}; - -/** - * Handle CallKeep end call event (from cold start). - */ -const handleCallKeepEndCall = ({ callUUID }) => { - console.log('[VoIP] CallKeep endCall from cold start:', callUUID); - markPendingCallDeclined(); -}; if (process.env.USE_STORYBOOK) { AppRegistry.registerComponent(appName, () => require('./.rnstorybook/index').default); @@ -80,49 +21,5 @@ if (process.env.USE_STORYBOOK) { LogBox.ignoreAllLogs(); - if (isIOS) { - // VoIP Push Notification handlers - VoipPushNotification.addEventListener('register', token => { - console.log('[VoIP] Token:', token); - // Token will be sent to server during login - }); - - VoipPushNotification.addEventListener('notification', handleVoipNotification); - - VoipPushNotification.addEventListener('didLoadWithEvents', events => { - if (!events || !Array.isArray(events) || events.length < 1) { - return; - } - console.log('[VoIP] didLoadWithEvents:', events.length, 'events'); - for (const voipPushEvent of events) { - const { name, data } = voipPushEvent; - if (name === VoipPushNotification.RNVoipPushRemoteNotificationsRegisteredEvent) { - console.log('[VoIP] Token from cold start:', data); - } else if (name === VoipPushNotification.RNVoipPushRemoteNotificationReceivedEvent) { - handleVoipNotification(data); - } - } - }); - - // CallKeep handlers for cold start scenario - // These handle events that occurred before JS was initialized - RNCallKeep.addEventListener('didLoadWithEvents', events => { - if (!events || !Array.isArray(events) || events.length < 1) { - return; - } - console.log('[VoIP] CallKeep didLoadWithEvents:', events.length, 'events'); - for (const event of events) { - const { name, data } = event; - if (name === 'RNCallKeepPerformAnswerCallAction') { - handleCallKeepAnswerCall(data); - } else if (name === 'RNCallKeepPerformEndCallAction') { - handleCallKeepEndCall(data); - } - } - }); - - VoipPushNotification.registerVoipToken(); - } - AppRegistry.registerComponent(appName, () => require('./app/index').default); } From 9b287707d566a055e51874e67a9abf4243cb4173 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 20 Jan 2026 14:24:09 -0300 Subject: [PATCH 24/61] Attempt to make iOS calls work from cold state --- app/index.tsx | 9 +- app/lib/methods/enterpriseModules.ts | 2 +- app/lib/services/voip/getInitialEvents.ts | 54 +-- ios/Podfile.lock | 2 +- ios/RocketChatRN.xcodeproj/project.pbxproj | 206 ++++---- patches/react-native-callkeep+4.3.16.patch | 516 --------------------- 6 files changed, 129 insertions(+), 660 deletions(-) diff --git a/app/index.tsx b/app/index.tsx index 698610a68a5..ef40551600e 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -5,7 +5,6 @@ import { SafeAreaProvider } from 'react-native-safe-area-context'; import { enableScreens } from 'react-native-screens'; import { Provider } from 'react-redux'; import { KeyboardProvider } from 'react-native-keyboard-controller'; -import RNCallKeep from 'react-native-callkeep'; import ResponsiveLayoutProvider from './lib/hooks/useResponsiveLayout/useResponsiveLayout'; import AppContainer from './AppContainer'; @@ -34,13 +33,13 @@ import { } from './lib/methods/helpers/theme'; import { initializePushNotifications, onNotification } from './lib/notifications'; import { getInitialNotification, setupVideoConfActionListener } from './lib/notifications/videoConf/getInitialNotification'; +import { getInitialEvents } from './lib/services/voip/getInitialEvents'; import store from './lib/store'; import { initStore } from './lib/store/auxStore'; import { type TSupportedThemes, ThemeContext } from './theme'; import ChangePasscodeView from './views/ChangePasscodeView'; import ScreenLockedView from './views/ScreenLockedView'; import StatusBar from './containers/StatusBar'; -import { getInitialEvents } from './lib/services/voip/getInitialEvents'; enableScreens(); initStore(store); @@ -150,7 +149,11 @@ export default class Root extends React.Component<{}, IState> { return; } - await getInitialEvents(); + // TODO: change name + const handledVoipCall = await getInitialEvents(); + if (handledVoipCall) { + return; + } // Open app from deep linking const deepLinking = await Linking.getInitialURL(); diff --git a/app/lib/methods/enterpriseModules.ts b/app/lib/methods/enterpriseModules.ts index 2c252df779e..682d1a4fb1d 100644 --- a/app/lib/methods/enterpriseModules.ts +++ b/app/lib/methods/enterpriseModules.ts @@ -64,5 +64,5 @@ export function isOmnichannelModuleAvailable() { export function isVoipModuleAvailable() { const { enterpriseModules } = reduxStore.getState(); - return enterpriseModules.includes('teams-voip'); + return true; // enterpriseModules.includes('teams-voip'); } diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index 90d81ec4dc3..d0ed89e1af1 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -6,37 +6,15 @@ import { CallIdUUIDModule } from '../../native/CallIdUUID'; import store from '../../store'; import { voipCallOpen } from '../../../actions/deepLinking'; -// const options = { -// ios: { -// appName: 'Rocket.Chat', -// supportsVideo: true, -// maximumCallGroups: 1, -// maximumCallsPerCallGroup: 1, -// includesCallsInRecents: false -// }, -// android: { -// alertTitle: 'Permissions required', -// alertDescription: 'This application needs to access your phone accounts', -// cancelButton: 'Cancel', -// okButton: 'ok' -// } -// }; - // Store VoIP push data temporarily let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; -export const getInitialEvents = async () => { +export const getInitialEvents = async (): Promise<boolean> => { if (!isIOS) { - return null; + return false; } try { - // 1. Setup CallKeep FIRST (if not already done in native) - // Note: Setup is already done in AppDelegate.swift, but we need to ensure JS side is ready - // await RNCallKeep.setup(options); - // console.log('[CallKeep][getInitialEvents] Setup completed'); - - // 2. Get VoIP push events from didLoadWithEvents VoipPushNotification.addEventListener('didLoadWithEvents', events => { if (!events || !Array.isArray(events)) return; @@ -44,10 +22,11 @@ export const getInitialEvents = async () => { const { name, data } = event; if (name === VoipPushNotification.RNVoipPushRemoteNotificationReceivedEvent) { - const { callId, caller, host } = data; + const voipData = data as { callId?: string; caller?: string; host?: string }; + const { callId, caller, host } = voipData; if (callId) { const callUUID = CallIdUUIDModule.toUUID(callId); - voipPushData = { callId, caller, host, callUUID }; + voipPushData = { callId, caller: caller || 'Unknown', host, callUUID }; console.log('[VoIP][getInitialEvents] Stored VoIP push data:', voipPushData); } } @@ -59,17 +38,24 @@ export const getInitialEvents = async () => { if (voipPushData && voipPushData.callUUID.toLowerCase() === callUUID.toLowerCase()) { console.log('[CallKeep][getInitialEvents] Matched live answer to VoIP call'); - // handleAnsweredCall(voipPushData); + if (voipPushData.host) { + store.dispatch( + voipCallOpen({ + callId: voipPushData.callId, + callUUID: voipPushData.callUUID, + host: voipPushData.host + }) + ); + console.log('[CallKeep][getInitialEvents] Dispatched voipCallOpen action from live listener'); + } } else { console.log('[CallKeep][getInitialEvents] Live answer UUID mismatch. Answer:', callUUID, 'VoIP:', voipPushData?.callUUID); } }); - // 3. Get CallKeep initial events AFTER setup const initialEvents = await RNCallKeep.getInitialEvents(); console.log('[CallKeep][getInitialEvents] Initial events:', JSON.stringify(initialEvents, null, 2)); - // 4. Process answer events for (const event of initialEvents) { const { name, data } = event; @@ -77,11 +63,9 @@ export const getInitialEvents = async () => { const { callUUID } = data; console.log('[CallKeep][getInitialEvents] Found ANSWER event:', callUUID); - // Match to VoIP push data if (voipPushData && voipPushData.callUUID.toLowerCase() === callUUID.toLowerCase()) { console.log('[CallKeep][getInitialEvents] Matched answer to VoIP call:', voipPushData); - // Dispatch action to handle server switching and call connection if (voipPushData.host) { store.dispatch( voipCallOpen({ @@ -92,9 +76,8 @@ export const getInitialEvents = async () => { ); console.log('[CallKeep][getInitialEvents] Dispatched voipCallOpen action'); - // Clear events after processing RNCallKeep.clearInitialEvents(); - return { answered: true, callData: voipPushData }; + return true; } } else { console.log('[CallKeep][getInitialEvents] Answer event UUID does not match VoIP push UUID'); @@ -102,14 +85,13 @@ export const getInitialEvents = async () => { } } - // Clear events if processed if (initialEvents.length > 0) { RNCallKeep.clearInitialEvents(); } - return { answered: false }; + return false; } catch (error) { console.error('[CallKeep][getInitialEvents] Error:', error); - return null; + return false; } }; diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 7a4be814f34..1fe52e8bac8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -3210,6 +3210,6 @@ SPEC CHECKSUMS: Yoga: dfabf1234ccd5ac41d1b1d43179f024366ae9831 ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5 -PODFILE CHECKSUM: 199f6fbbe6fb415c822cca992e6152000ac55b3e +PODFILE CHECKSUM: 5d562fbb33c24fb71c5fe4ab560e854f7a165148 COCOAPODS: 1.15.2 diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index 777d9738899..9c14e1eabd3 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -277,7 +277,7 @@ 3F56D232A9EBA1C9C749F15E /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; 3F56D232A9EBA1C9C749F15F /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; 3F56D232A9EBA1C9C749F160 /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; - 426FF478D77293099212881F /* Pods_defaults_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB9F534F3E8CBF9FEFFC4866 /* Pods_defaults_Rocket_Chat.framework */; }; + 48A421BADAE0581090F73A31 /* Pods_defaults_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C8B6905552E89D22ECC9A59 /* Pods_defaults_Rocket_Chat.framework */; }; 4C4C8603EF082F0A33A95522 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D5C142B655F8EFD006792C /* ExpoModulesProvider.swift */; }; 65AD38372BFBDF4A00271B39 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */; }; 65AD38392BFBDF4A00271B39 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */; }; @@ -365,10 +365,10 @@ A2C6E2DD38F8BEE19BFB2E1D /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A42CFB843397273C7EA /* SecureStorage.m */; }; A48B46D92D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; A48B46DA2D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; + BA8D65FC401BDCF46BC4A430 /* Pods_defaults_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF1F97CD8D80023897D69A96 /* Pods_defaults_NotificationService.framework */; }; BC404914E86821389EEB543D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */; }; - D220BA967F2E1E70183F9145 /* Pods_defaults_RocketChatRN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 595D750F5B210F6E68883689 /* Pods_defaults_RocketChatRN.framework */; }; + CC12B307799B2349A98FFD79 /* Pods_defaults_RocketChatRN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 918F9B00E7760D7709BE6B1C /* Pods_defaults_RocketChatRN.framework */; }; DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA7E862283664608B3894E34 /* libWatermelonDB.a */; }; - EE97DFD0E0BEC72B1240C322 /* Pods_defaults_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB05EB8B2044518903038699 /* Pods_defaults_NotificationService.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -616,11 +616,7 @@ 1EFEB5A12493B67D0072EDC0 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = "<group>"; }; 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-Rocket.Chat/ExpoModulesProvider.swift"; sourceTree = "<group>"; }; 45D5C142B655F8EFD006792C /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-RocketChatRN/ExpoModulesProvider.swift"; sourceTree = "<group>"; }; - 493A01BC9ACB23394D12AFDF /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = "<group>"; }; - 4E0E229CA6934B9EAF0B9493 /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = "<group>"; }; - 59533A56A22734482A5210FD /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = "<group>"; }; - 595D750F5B210F6E68883689 /* Pods_defaults_RocketChatRN.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_RocketChatRN.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5999665FA1FBE0F403918D2A /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; }; + 544428BFD00E045285A62CD7 /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; }; 60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = RocketChatRN.entitlements; path = RocketChatRN/RocketChatRN.entitlements; sourceTree = "<group>"; }; 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 65B9A7192AFC24190088956F /* ringtone.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ringtone.mp3; sourceTree = "<group>"; }; @@ -643,17 +639,21 @@ 7ACD4853222860DE00442C55 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 7ACFE7D82DDE48760090D9BC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 7AE10C0528A59530003593CB /* Inter.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Inter.ttf; sourceTree = "<group>"; }; + 7D58F328632F3CC231D7C525 /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = "<group>"; }; + 8C31C00B0E14F40F0C0EA8DE /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = "<group>"; }; + 918F9B00E7760D7709BE6B1C /* Pods_defaults_RocketChatRN.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_RocketChatRN.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9919F040FC3472AAAB898030 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = "<group>"; }; 9B215A42CFB843397273C7EA /* SecureStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = SecureStorage.m; sourceTree = "<group>"; }; 9B215A44CFB843397273C7EC /* MMKVBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MMKVBridge.mm; path = Shared/RocketChat/MMKVBridge.mm; sourceTree = "<group>"; }; + 9C8B6905552E89D22ECC9A59 /* Pods_defaults_Rocket_Chat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_Rocket_Chat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A025A0274DA20DB65BC36CBA /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = "<group>"; }; A48B46D72D3FFBD200945489 /* A11yFlowModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = A11yFlowModule.h; sourceTree = "<group>"; }; A48B46D82D3FFBD200945489 /* A11yFlowModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = A11yFlowModule.m; sourceTree = "<group>"; }; - A8AB3C26BAEA809C12CB9A87 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = "<group>"; }; B179038FDD7AAF285047814B /* SecureStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = SecureStorage.h; sourceTree = "<group>"; }; B37C79D9BD0742CE936B6982 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; BA7E862283664608B3894E34 /* libWatermelonDB.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libWatermelonDB.a; sourceTree = "<group>"; }; - CB05EB8B2044518903038699 /* Pods_defaults_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E48D2153CA15F36CA164CFDC /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = "<group>"; }; - EB9F534F3E8CBF9FEFFC4866 /* Pods_defaults_Rocket_Chat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_Rocket_Chat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BF1F97CD8D80023897D69A96 /* Pods_defaults_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E34E9152D963DFA1B0E08FA4 /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -674,7 +674,7 @@ 7ACD4897222860DE00442C55 /* JavaScriptCore.framework in Frameworks */, 24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */, DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */, - D220BA967F2E1E70183F9145 /* Pods_defaults_RocketChatRN.framework in Frameworks */, + CC12B307799B2349A98FFD79 /* Pods_defaults_RocketChatRN.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -696,7 +696,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - EE97DFD0E0BEC72B1240C322 /* Pods_defaults_NotificationService.framework in Frameworks */, + BA8D65FC401BDCF46BC4A430 /* Pods_defaults_NotificationService.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -717,7 +717,7 @@ 7AAB3E3D257E6A6E00707CF6 /* JavaScriptCore.framework in Frameworks */, 7AAB3E3E257E6A6E00707CF6 /* libz.tbd in Frameworks */, 7AAB3E3F257E6A6E00707CF6 /* libWatermelonDB.a in Frameworks */, - 426FF478D77293099212881F /* Pods_defaults_Rocket_Chat.framework in Frameworks */, + 48A421BADAE0581090F73A31 /* Pods_defaults_Rocket_Chat.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1154,12 +1154,12 @@ 7AC2B09613AA7C3FEBAC9F57 /* Pods */ = { isa = PBXGroup; children = ( - A8AB3C26BAEA809C12CB9A87 /* Pods-defaults-NotificationService.debug.xcconfig */, - 493A01BC9ACB23394D12AFDF /* Pods-defaults-NotificationService.release.xcconfig */, - 4E0E229CA6934B9EAF0B9493 /* Pods-defaults-Rocket.Chat.debug.xcconfig */, - E48D2153CA15F36CA164CFDC /* Pods-defaults-Rocket.Chat.release.xcconfig */, - 59533A56A22734482A5210FD /* Pods-defaults-RocketChatRN.debug.xcconfig */, - 5999665FA1FBE0F403918D2A /* Pods-defaults-RocketChatRN.release.xcconfig */, + 9919F040FC3472AAAB898030 /* Pods-defaults-NotificationService.debug.xcconfig */, + E34E9152D963DFA1B0E08FA4 /* Pods-defaults-NotificationService.release.xcconfig */, + 7D58F328632F3CC231D7C525 /* Pods-defaults-Rocket.Chat.debug.xcconfig */, + A025A0274DA20DB65BC36CBA /* Pods-defaults-Rocket.Chat.release.xcconfig */, + 8C31C00B0E14F40F0C0EA8DE /* Pods-defaults-RocketChatRN.debug.xcconfig */, + 544428BFD00E045285A62CD7 /* Pods-defaults-RocketChatRN.release.xcconfig */, ); path = Pods; sourceTree = "<group>"; @@ -1249,9 +1249,9 @@ 7ACD4853222860DE00442C55 /* JavaScriptCore.framework */, B37C79D9BD0742CE936B6982 /* libc++.tbd */, 06BB44DD4855498082A744AD /* libz.tbd */, - CB05EB8B2044518903038699 /* Pods_defaults_NotificationService.framework */, - EB9F534F3E8CBF9FEFFC4866 /* Pods_defaults_Rocket_Chat.framework */, - 595D750F5B210F6E68883689 /* Pods_defaults_RocketChatRN.framework */, + BF1F97CD8D80023897D69A96 /* Pods_defaults_NotificationService.framework */, + 9C8B6905552E89D22ECC9A59 /* Pods_defaults_Rocket_Chat.framework */, + 918F9B00E7760D7709BE6B1C /* Pods_defaults_RocketChatRN.framework */, ); name = Frameworks; sourceTree = "<group>"; @@ -1271,7 +1271,7 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RocketChatRN" */; buildPhases = ( - 962B748359DA9B9705179CCD /* [CP] Check Pods Manifest.lock */, + 096AE45E4AC4D5698CB36A66 /* [CP] Check Pods Manifest.lock */, 06C10D4F29CD7532492AD29E /* [Expo] Configure project */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, @@ -1281,8 +1281,8 @@ 1E1EA8082326CCE300E22452 /* ShellScript */, 1ED0389C2B507B4F00C007D4 /* Embed Watch Content */, 7AAE9EB32891A0D20024F559 /* Upload source maps to Bugsnag */, - BE3FE00123CFEC10E0345AF4 /* [CP] Embed Pods Frameworks */, - 95401EE136E44874208F1354 /* [CP] Copy Pods Resources */, + FCB7836D6121FF536E382FEB /* [CP] Embed Pods Frameworks */, + 8BE1065B81EC4F6547A622AF /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1350,12 +1350,12 @@ isa = PBXNativeTarget; buildConfigurationList = 1EFEB5A02493B6640072EDC0 /* Build configuration list for PBXNativeTarget "NotificationService" */; buildPhases = ( - 33BF8EE785F0FACE91B45419 /* [CP] Check Pods Manifest.lock */, + 5A59078F0CE0CB05D87ADB1A /* [CP] Check Pods Manifest.lock */, 86A998705576AFA7CE938617 /* [Expo] Configure project */, 1EFEB5912493B6640072EDC0 /* Sources */, 1EFEB5922493B6640072EDC0 /* Frameworks */, 1EFEB5932493B6640072EDC0 /* Resources */, - 38768FD2CC9FB4795F119569 /* [CP] Copy Pods Resources */, + 5F3BFF131980D9739452E956 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1370,7 +1370,7 @@ isa = PBXNativeTarget; buildConfigurationList = 7AAB3E4F257E6A6E00707CF6 /* Build configuration list for PBXNativeTarget "Rocket.Chat" */; buildPhases = ( - 960C1CE9E3B9DBC185AC91D8 /* [CP] Check Pods Manifest.lock */, + 3C2E0F6B686705FA7C73731D /* [CP] Check Pods Manifest.lock */, 6319FBDD06EF0030B48AD389 /* [Expo] Configure project */, 7AAB3E14257E6A6E00707CF6 /* Sources */, 7AAB3E32257E6A6E00707CF6 /* Frameworks */, @@ -1380,8 +1380,8 @@ 7A55BE3C2F1131C000D8744D /* ShellScript */, 1ED1ECE32B8699DD00F6620C /* Embed Watch Content */, 7A55BE3D2F11320C00D8744D /* Upload source maps to Bugsnag */, - D5D0EF64F1A7388CD16A9F46 /* [CP] Embed Pods Frameworks */, - 7639A7AEAB5CF1DC7E845A3A /* [CP] Copy Pods Resources */, + CC73A3FB774BB2359530D319 /* [CP] Embed Pods Frameworks */, + 40F7A1CBB5D1EBCF84C512F5 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1553,7 +1553,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\"\nexport NODE_BINARY=/Users/diegomello/.nvm/versions/node/v22.14.0/bin/node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; + shellScript = "export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\"\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; }; 06C10D4F29CD7532492AD29E /* [Expo] Configure project */ = { isa = PBXShellScriptBuildPhase; @@ -1574,6 +1574,28 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-RocketChatRN/expo-configure-project.sh\"\n"; }; + 096AE45E4AC4D5698CB36A66 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-defaults-RocketChatRN-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 1E1EA8082326CCE300E22452 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1591,7 +1613,7 @@ shellPath = /bin/sh; shellScript = "echo \"Target architectures: $ARCHS\"\n\nAPP_PATH=\"${TARGET_BUILD_DIR}/${WRAPPER_NAME}\"\n\nfind \"$APP_PATH\" -name '*.framework' -type d | while read -r FRAMEWORK\ndo\nFRAMEWORK_EXECUTABLE_NAME=$(defaults read \"$FRAMEWORK/Info.plist\" CFBundleExecutable)\nFRAMEWORK_EXECUTABLE_PATH=\"$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME\"\necho \"Executable is $FRAMEWORK_EXECUTABLE_PATH\"\necho $(lipo -info \"$FRAMEWORK_EXECUTABLE_PATH\")\n\nFRAMEWORK_TMP_PATH=\"$FRAMEWORK_EXECUTABLE_PATH-tmp\"\n\n# remove simulator's archs if location is not simulator's directory\ncase \"${TARGET_BUILD_DIR}\" in\n*\"iphonesimulator\")\necho \"No need to remove archs\"\n;;\n*)\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"i386\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"i386\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"i386 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"x86_64\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"x86_64\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"x86_64 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\n;;\nesac\n\necho \"Completed for executable $FRAMEWORK_EXECUTABLE_PATH\"\necho $\n\ndone\n"; }; - 33BF8EE785F0FACE91B45419 /* [CP] Check Pods Manifest.lock */ = { + 3C2E0F6B686705FA7C73731D /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1606,20 +1628,20 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-defaults-Rocket.Chat-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 38768FD2CC9FB4795F119569 /* [CP] Copy Pods Resources */ = { + 40F7A1CBB5D1EBCF84C512F5 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh", + "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/BugsnagReactNative/Bugsnag.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", @@ -1686,35 +1708,38 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 6319FBDD06EF0030B48AD389 /* [Expo] Configure project */ = { + 5A59078F0CE0CB05D87ADB1A /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); - name = "[Expo] Configure project"; + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-Rocket.Chat/expo-configure-project.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - 7639A7AEAB5CF1DC7E845A3A /* [CP] Copy Pods Resources */ = { + 5F3BFF131980D9739452E956 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh", + "${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/BugsnagReactNative/Bugsnag.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", @@ -1781,9 +1806,28 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 6319FBDD06EF0030B48AD389 /* [Expo] Configure project */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "[Expo] Configure project"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-Rocket.Chat/expo-configure-project.sh\"\n"; + }; 7A55BE3B2F11316900D8744D /* Bundle React Native code and images */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1856,7 +1900,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "#SOURCE_MAP=\"$TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh\n"; + shellScript = "SOURCE_MAP=\"$TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh\n"; showEnvVarsInLog = 0; }; 86A998705576AFA7CE938617 /* [Expo] Configure project */ = { @@ -1878,7 +1922,7 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-NotificationService/expo-configure-project.sh\"\n"; }; - 95401EE136E44874208F1354 /* [CP] Copy Pods Resources */ = { + 8BE1065B81EC4F6547A622AF /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1954,57 +1998,13 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 960C1CE9E3B9DBC185AC91D8 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-Rocket.Chat-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 962B748359DA9B9705179CCD /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-RocketChatRN-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - BE3FE00123CFEC10E0345AF4 /* [CP] Embed Pods Frameworks */ = { + CC73A3FB774BB2359530D319 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", + "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh", "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", ); @@ -2015,16 +2015,16 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - D5D0EF64F1A7388CD16A9F46 /* [CP] Embed Pods Frameworks */ = { + FCB7836D6121FF536E382FEB /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh", + "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", ); @@ -2035,7 +2035,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -2429,7 +2429,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 59533A56A22734482A5210FD /* Pods-defaults-RocketChatRN.debug.xcconfig */; + baseConfigurationReference = 8C31C00B0E14F40F0C0EA8DE /* Pods-defaults-RocketChatRN.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2494,7 +2494,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5999665FA1FBE0F403918D2A /* Pods-defaults-RocketChatRN.release.xcconfig */; + baseConfigurationReference = 544428BFD00E045285A62CD7 /* Pods-defaults-RocketChatRN.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2909,7 +2909,7 @@ }; 1EFEB59D2493B6640072EDC0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A8AB3C26BAEA809C12CB9A87 /* Pods-defaults-NotificationService.debug.xcconfig */; + baseConfigurationReference = 9919F040FC3472AAAB898030 /* Pods-defaults-NotificationService.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(EMBEDDED_CONTENT_CONTAINS_SWIFT)"; CLANG_ANALYZER_NONNULL = YES; @@ -2961,7 +2961,7 @@ }; 1EFEB59E2493B6640072EDC0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 493A01BC9ACB23394D12AFDF /* Pods-defaults-NotificationService.release.xcconfig */; + baseConfigurationReference = E34E9152D963DFA1B0E08FA4 /* Pods-defaults-NotificationService.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(EMBEDDED_CONTENT_CONTAINS_SWIFT)"; CLANG_ANALYZER_NONNULL = YES; @@ -3012,7 +3012,7 @@ }; 7AAB3E50257E6A6E00707CF6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4E0E229CA6934B9EAF0B9493 /* Pods-defaults-Rocket.Chat.debug.xcconfig */; + baseConfigurationReference = 7D58F328632F3CC231D7C525 /* Pods-defaults-Rocket.Chat.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -3077,7 +3077,7 @@ }; 7AAB3E51257E6A6E00707CF6 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E48D2153CA15F36CA164CFDC /* Pods-defaults-Rocket.Chat.release.xcconfig */; + baseConfigurationReference = A025A0274DA20DB65BC36CBA /* Pods-defaults-Rocket.Chat.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; diff --git a/patches/react-native-callkeep+4.3.16.patch b/patches/react-native-callkeep+4.3.16.patch index 41f76ed042f..c2089ec573b 100644 --- a/patches/react-native-callkeep+4.3.16.patch +++ b/patches/react-native-callkeep+4.3.16.patch @@ -1,519 +1,3 @@ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/results.bin b/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/results.bin -new file mode 100644 -index 0000000..0d259dd ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/results.bin -@@ -0,0 +1 @@ -+o/classes -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/transformed/classes/classes_dex/classes.dex b/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/transformed/classes/classes_dex/classes.dex -new file mode 100644 -index 0000000..4119e43 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/964ba535716791bf0c1177430d59c453/transformed/classes/classes_dex/classes.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/results.bin b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/results.bin -new file mode 100644 -index 0000000..7ed749e ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/results.bin -@@ -0,0 +1 @@ -+o/bundleLibRuntimeToDirDebug -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/BuildConfig.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/BuildConfig.dex -new file mode 100644 -index 0000000..778c715 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/BuildConfig.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/Constants.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/Constants.dex -new file mode 100644 -index 0000000..b455781 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/Constants.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils$1.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils$1.dex -new file mode 100644 -index 0000000..4d67548 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils$1.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils.dex -new file mode 100644 -index 0000000..cff89d7 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/MapUtils.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.dex -new file mode 100644 -index 0000000..915774b -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$1.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$1.dex -new file mode 100644 -index 0000000..f6b4e96 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$1.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$CallStateListener.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$CallStateListener.dex -new file mode 100644 -index 0000000..adb3630 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$CallStateListener.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.dex -new file mode 100644 -index 0000000..60293f2 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.dex -new file mode 100644 -index 0000000..2534446 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule.dex -new file mode 100644 -index 0000000..b430d90 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepModule.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepPackage.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepPackage.dex -new file mode 100644 -index 0000000..8ec634e -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/RNCallKeepPackage.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConference.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConference.dex -new file mode 100644 -index 0000000..6c2a20d -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConference.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection$1.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection$1.dex -new file mode 100644 -index 0000000..12f4957 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection$1.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection.dex -new file mode 100644 -index 0000000..91730a7 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnection.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$1.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$1.dex -new file mode 100644 -index 0000000..9b64aa6 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$1.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$2.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$2.dex -new file mode 100644 -index 0000000..6b69b72 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$2.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$3.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$3.dex -new file mode 100644 -index 0000000..eadb3df -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$3.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$4.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$4.dex -new file mode 100644 -index 0000000..b330051 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService$4.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService.dex b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService.dex -new file mode 100644 -index 0000000..d5dff5c -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/io/wazo/callkeep/VoiceConnectionService.dex differ -diff --git a/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin -new file mode 100644 -index 0000000..dbb49bb -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/.transforms/f6bc3c72e7dbbec700c8ebae5f9119a5/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin differ -diff --git a/node_modules/react-native-callkeep/android/build/generated/source/buildConfig/debug/io/wazo/callkeep/BuildConfig.java b/node_modules/react-native-callkeep/android/build/generated/source/buildConfig/debug/io/wazo/callkeep/BuildConfig.java -new file mode 100644 -index 0000000..af36621 ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/generated/source/buildConfig/debug/io/wazo/callkeep/BuildConfig.java -@@ -0,0 +1,10 @@ -+/** -+ * Automatically generated file. DO NOT MODIFY -+ */ -+package io.wazo.callkeep; -+ -+public final class BuildConfig { -+ public static final boolean DEBUG = Boolean.parseBoolean("true"); -+ public static final String LIBRARY_PACKAGE_NAME = "io.wazo.callkeep"; -+ public static final String BUILD_TYPE = "debug"; -+} -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml b/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml -new file mode 100644 -index 0000000..4889152 ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml -@@ -0,0 +1,14 @@ -+<?xml version="1.0" encoding="utf-8"?> -+<manifest xmlns:android="http://schemas.android.com/apk/res/android" -+ package="io.wazo.callkeep" > -+ -+ <uses-sdk android:minSdkVersion="24" /> -+ -+ <uses-permission android:name="android.permission.CALL_PHONE" /> -+ <uses-permission -+ android:name="android.permission.READ_PHONE_STATE" -+ android:maxSdkVersion="29" /> -+ <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" /> -+ <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" /> -+ -+</manifest> -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json b/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json -new file mode 100644 -index 0000000..a663f08 ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json -@@ -0,0 +1,18 @@ -+{ -+ "version": 3, -+ "artifactType": { -+ "type": "AAPT_FRIENDLY_MERGED_MANIFESTS", -+ "kind": "Directory" -+ }, -+ "applicationId": "io.wazo.callkeep", -+ "variantName": "debug", -+ "elements": [ -+ { -+ "type": "SINGLE", -+ "filters": [], -+ "attributes": [], -+ "outputFile": "AndroidManifest.xml" -+ } -+ ], -+ "elementType": "File" -+} -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties b/node_modules/react-native-callkeep/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties -new file mode 100644 -index 0000000..1211b1e ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties -@@ -0,0 +1,6 @@ -+aarFormatVersion=1.0 -+aarMetadataVersion=1.0 -+minCompileSdk=1 -+minCompileSdkExtension=0 -+minAndroidGradlePluginVersion=1.0.0 -+coreLibraryDesugaringEnabled=false -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json b/node_modules/react-native-callkeep/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json -new file mode 100644 -index 0000000..9e26dfe ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json -@@ -0,0 +1 @@ -+{} -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar b/node_modules/react-native-callkeep/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar -new file mode 100644 -index 0000000..8c54db9 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar b/node_modules/react-native-callkeep/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar -new file mode 100644 -index 0000000..169bdf6 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt b/node_modules/react-native-callkeep/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt -new file mode 100644 -index 0000000..e69de29 -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties b/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties -new file mode 100644 -index 0000000..342121f ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties -@@ -0,0 +1 @@ -+#Mon Jan 12 14:06:26 BRT 2026 -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml b/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml -new file mode 100644 -index 0000000..7344b1b ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml -@@ -0,0 +1,2 @@ -+<?xml version="1.0" encoding="utf-8"?> -+<merger version="3"><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="main" generated-set="main$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/debug/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="debug" generated-set="debug$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/debug/res"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated$Generated" generated="true" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/build/generated/res/resValues/debug"/></dataSet><dataSet aapt-namespace="http://schemas.android.com/apk/res-auto" config="generated" generated-set="generated$Generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/build/generated/res/resValues/debug"/></dataSet><mergedItems/></merger> -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml b/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml -new file mode 100644 -index 0000000..e436a6a ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml -@@ -0,0 +1,2 @@ -+<?xml version="1.0" encoding="utf-8"?> -+<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/jniLibs"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/debug/jniLibs"/></dataSet></merger> -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugShaders/merger.xml b/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugShaders/merger.xml -new file mode 100644 -index 0000000..7572f77 ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/mergeDebugShaders/merger.xml -@@ -0,0 +1,2 @@ -+<?xml version="1.0" encoding="utf-8"?> -+<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/shaders"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/debug/shaders"/></dataSet></merger> -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/incremental/packageDebugAssets/merger.xml b/node_modules/react-native-callkeep/android/build/intermediates/incremental/packageDebugAssets/merger.xml -new file mode 100644 -index 0000000..2713406 ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/incremental/packageDebugAssets/merger.xml -@@ -0,0 +1,2 @@ -+<?xml version="1.0" encoding="utf-8"?> -+<merger version="3"><dataSet config="main" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/assets"/></dataSet><dataSet config="debug" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/debug/assets"/></dataSet><dataSet config="generated" ignore_pattern="!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"><source path="/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/build/intermediates/shader_assets/debug/compileDebugShaders/out"/></dataSet></merger> -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/BuildConfig.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/BuildConfig.class -new file mode 100644 -index 0000000..eea56ab -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/BuildConfig.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/Constants.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/Constants.class -new file mode 100644 -index 0000000..1431c43 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/Constants.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils$1.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils$1.class -new file mode 100644 -index 0000000..2edfdd4 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils$1.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils.class -new file mode 100644 -index 0000000..41dc2a1 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/MapUtils.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class -new file mode 100644 -index 0000000..135262e -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$1.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$1.class -new file mode 100644 -index 0000000..5d16482 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$1.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class -new file mode 100644 -index 0000000..fac5f49 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class -new file mode 100644 -index 0000000..f96d7ff -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class -new file mode 100644 -index 0000000..7508b23 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule.class -new file mode 100644 -index 0000000..8161c41 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepModule.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepPackage.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepPackage.class -new file mode 100644 -index 0000000..a53c172 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/RNCallKeepPackage.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConference.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConference.class -new file mode 100644 -index 0000000..be38a83 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConference.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection$1.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection$1.class -new file mode 100644 -index 0000000..de9749e -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection$1.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection.class -new file mode 100644 -index 0000000..bf89219 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnection.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$1.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$1.class -new file mode 100644 -index 0000000..3af0dbe -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$1.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$2.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$2.class -new file mode 100644 -index 0000000..f0c485d -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$2.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$3.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$3.class -new file mode 100644 -index 0000000..d27d5cf -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$3.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$4.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$4.class -new file mode 100644 -index 0000000..87119b1 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService$4.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService.class b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService.class -new file mode 100644 -index 0000000..104d3e9 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/io/wazo/callkeep/VoiceConnectionService.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt b/node_modules/react-native-callkeep/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt -new file mode 100644 -index 0000000..78ac5b8 ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt -@@ -0,0 +1,2 @@ -+R_DEF: Internal format may change without notice -+local -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt b/node_modules/react-native-callkeep/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt -new file mode 100644 -index 0000000..999890d ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt -@@ -0,0 +1,23 @@ -+1<?xml version="1.0" encoding="utf-8"?> -+2<manifest xmlns:android="http://schemas.android.com/apk/res/android" -+3 package="io.wazo.callkeep" > -+4 -+5 <uses-sdk android:minSdkVersion="24" /> -+6 -+7 <uses-permission android:name="android.permission.CALL_PHONE" /> -+7-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:4:5-69 -+7-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:4:22-66 -+8 <uses-permission -+8-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:5:5-6:51 -+9 android:name="android.permission.READ_PHONE_STATE" -+9-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:5:22-72 -+10 android:maxSdkVersion="29" /> -+10-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:6:22-48 -+11 <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" /> -+11-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:7:5-77 -+11-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:7:22-74 -+12 <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" /> -+12-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:8:5-75 -+12-->/Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:8:22-72 -+13 -+14</manifest> -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml b/node_modules/react-native-callkeep/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml -new file mode 100644 -index 0000000..4889152 ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml -@@ -0,0 +1,14 @@ -+<?xml version="1.0" encoding="utf-8"?> -+<manifest xmlns:android="http://schemas.android.com/apk/res/android" -+ package="io.wazo.callkeep" > -+ -+ <uses-sdk android:minSdkVersion="24" /> -+ -+ <uses-permission android:name="android.permission.CALL_PHONE" /> -+ <uses-permission -+ android:name="android.permission.READ_PHONE_STATE" -+ android:maxSdkVersion="29" /> -+ <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" /> -+ <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" /> -+ -+</manifest> -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json b/node_modules/react-native-callkeep/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json -new file mode 100644 -index 0000000..0637a08 ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json -@@ -0,0 +1 @@ -+[] -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt b/node_modules/react-native-callkeep/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt -new file mode 100644 -index 0000000..08f4ebe ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt -@@ -0,0 +1 @@ -+0 Warning/Error -\ No newline at end of file -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/BuildConfig.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/BuildConfig.class -new file mode 100644 -index 0000000..eea56ab -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/BuildConfig.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/Constants.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/Constants.class -new file mode 100644 -index 0000000..1431c43 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/Constants.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils$1.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils$1.class -new file mode 100644 -index 0000000..2edfdd4 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils$1.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils.class -new file mode 100644 -index 0000000..41dc2a1 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/MapUtils.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class -new file mode 100644 -index 0000000..135262e -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepBackgroundMessagingService.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$1.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$1.class -new file mode 100644 -index 0000000..5d16482 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$1.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class -new file mode 100644 -index 0000000..fac5f49 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$CallStateListener.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class -new file mode 100644 -index 0000000..f96d7ff -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$LegacyCallStateListener.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class -new file mode 100644 -index 0000000..7508b23 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule$VoiceBroadcastReceiver.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule.class -new file mode 100644 -index 0000000..8161c41 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepModule.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepPackage.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepPackage.class -new file mode 100644 -index 0000000..a53c172 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/RNCallKeepPackage.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConference.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConference.class -new file mode 100644 -index 0000000..be38a83 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConference.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection$1.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection$1.class -new file mode 100644 -index 0000000..de9749e -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection$1.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection.class -new file mode 100644 -index 0000000..bf89219 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnection.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$1.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$1.class -new file mode 100644 -index 0000000..3af0dbe -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$1.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$2.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$2.class -new file mode 100644 -index 0000000..f0c485d -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$2.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$3.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$3.class -new file mode 100644 -index 0000000..d27d5cf -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$3.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$4.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$4.class -new file mode 100644 -index 0000000..87119b1 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService$4.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService.class b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService.class -new file mode 100644 -index 0000000..104d3e9 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/io/wazo/callkeep/VoiceConnectionService.class differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar -new file mode 100644 -index 0000000..1c837d1 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar differ -diff --git a/node_modules/react-native-callkeep/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt b/node_modules/react-native-callkeep/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt -new file mode 100644 -index 0000000..7612bfd ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt -@@ -0,0 +1 @@ -+io.wazo.callkeep -diff --git a/node_modules/react-native-callkeep/android/build/outputs/logs/manifest-merger-debug-report.txt b/node_modules/react-native-callkeep/android/build/outputs/logs/manifest-merger-debug-report.txt -new file mode 100644 -index 0000000..d3fde62 ---- /dev/null -+++ b/node_modules/react-native-callkeep/android/build/outputs/logs/manifest-merger-debug-report.txt -@@ -0,0 +1,35 @@ -+-- Merging decision tree log --- -+manifest -+ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:2:1-9:12 -+INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:2:1-9:12 -+ package -+ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:2:70-96 -+ INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml -+ xmlns:android -+ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:2:11-69 -+uses-permission#android.permission.CALL_PHONE -+ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:4:5-69 -+ android:name -+ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:4:22-66 -+uses-permission#android.permission.READ_PHONE_STATE -+ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:5:5-6:51 -+ android:maxSdkVersion -+ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:6:22-48 -+ android:name -+ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:5:22-72 -+uses-permission#android.permission.READ_PHONE_NUMBERS -+ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:7:5-77 -+ android:name -+ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:7:22-74 -+uses-permission#android.permission.MANAGE_OWN_CALLS -+ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:8:5-75 -+ android:name -+ ADDED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml:8:22-72 -+uses-sdk -+INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml reason: use-sdk injection requested -+INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml -+INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml -+ android:targetSdkVersion -+ INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml -+ android:minSdkVersion -+ INJECTED from /Users/diegomello/Development/Work/Rocket.Chat.ReactNative/node_modules/react-native-callkeep/android/src/main/AndroidManifest.xml -diff --git a/node_modules/react-native-callkeep/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin b/node_modules/react-native-callkeep/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin -new file mode 100644 -index 0000000..b44a073 -Binary files /dev/null and b/node_modules/react-native-callkeep/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin differ diff --git a/node_modules/react-native-callkeep/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java b/node_modules/react-native-callkeep/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java index 025480a..70a1305 100644 --- a/node_modules/react-native-callkeep/android/src/main/java/io/wazo/callkeep/RNCallKeepModule.java From 5c5e2beb41c73fcadc2733c2806e7e448f48ded2 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 20 Jan 2026 14:30:00 -0300 Subject: [PATCH 25/61] lint and format --- app/i18n/locales/en.json | 2 +- app/lib/methods/enterpriseModules.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index df2a68a2a56..e2049354e04 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -923,8 +923,8 @@ "Unfollow_thread": "Unfollow thread", "Unfollowed_thread": "Unfollowed thread", "Unhide": "Unhide", - "Unignore": "Unignore", "Unhold": "Unhold", + "Unignore": "Unignore", "Unmute": "Unmute", "Unmute_someone_in_room": "Unmute someone in the room", "unmuted": "unmuted", diff --git a/app/lib/methods/enterpriseModules.ts b/app/lib/methods/enterpriseModules.ts index 682d1a4fb1d..ac558847533 100644 --- a/app/lib/methods/enterpriseModules.ts +++ b/app/lib/methods/enterpriseModules.ts @@ -63,6 +63,6 @@ export function isOmnichannelModuleAvailable() { } export function isVoipModuleAvailable() { - const { enterpriseModules } = reduxStore.getState(); + // const { enterpriseModules } = reduxStore.getState(); return true; // enterpriseModules.includes('teams-voip'); } From 01e42e27b6c68af3736760cc4845003f8c07172e Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 20 Jan 2026 15:48:01 -0300 Subject: [PATCH 26/61] Patch callkeep ios --- package.json | 2 +- patches/react-native-callkeep+4.3.16.patch | 13 +++++++++++++ yarn.lock | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b3c8e309cbb..f63e533a825 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "react-native-animatable": "1.3.3", "react-native-background-timer": "2.4.1", "react-native-bootsplash": "^6.3.8", - "react-native-callkeep": "^4.3.16", + "react-native-callkeep": "4.3.16", "react-native-config-reader": "4.1.1", "react-native-console-time-polyfill": "1.2.3", "react-native-device-info": "11.1.0", diff --git a/patches/react-native-callkeep+4.3.16.patch b/patches/react-native-callkeep+4.3.16.patch index c2089ec573b..bd05faf9b96 100644 --- a/patches/react-native-callkeep+4.3.16.patch +++ b/patches/react-native-callkeep+4.3.16.patch @@ -26,3 +26,16 @@ index 025480a..70a1305 100644 @ReactMethod public void startCall(String uuid, String number, String callerName, boolean hasVideo) { this.startCall(uuid, number, callerName, hasVideo, null); +diff --git a/node_modules/react-native-callkeep/ios/RNCallKeep/RNCallKeep.m b/node_modules/react-native-callkeep/ios/RNCallKeep/RNCallKeep.m +index 786045f..a989d58 100644 +--- a/node_modules/react-native-callkeep/ios/RNCallKeep/RNCallKeep.m ++++ b/node_modules/react-native-callkeep/ios/RNCallKeep/RNCallKeep.m +@@ -171,6 +171,8 @@ - (void)sendEventWithNameWrapper:(NSString *)name body:(id)body { + body, @"data", + nil + ]; ++ // https://github.com/react-native-webrtc/react-native-callkeep/issues/822#issuecomment-2866354202 ++ if (_delayedEvents == nil) _delayedEvents = [NSMutableArray array]; + [_delayedEvents addObject:dictionary]; + } + } diff --git a/yarn.lock b/yarn.lock index bf8a782547f..63894135416 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12662,7 +12662,7 @@ react-native-bootsplash@^6.3.8: ts-dedent "^2.2.0" xml-formatter "^3.6.5" -react-native-callkeep@^4.3.16: +react-native-callkeep@4.3.16: version "4.3.16" resolved "https://registry.yarnpkg.com/react-native-callkeep/-/react-native-callkeep-4.3.16.tgz#56291796984b896113ef00f8b67ae3fe177baf70" integrity sha512-aIxn02T5zW4jNPyzRdFGTWv6xD3Vy/1AkBMB6iYvWZEHWnfmgNGF0hELqg03Vbc2BNUhfqpu17aIydos+5Hurg== From aa3ca889fe59bb344fb4d15a3663413a5aba9939 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 20 Jan 2026 15:57:19 -0300 Subject: [PATCH 27/61] Temp send iOS voip push token on gcm --- app/lib/services/restApi.ts | 8 ++++++++ app/lib/services/voip/getInitialEvents.ts | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/app/lib/services/restApi.ts b/app/lib/services/restApi.ts index f38c096c315..2b7754e2c8f 100644 --- a/app/lib/services/restApi.ts +++ b/app/lib/services/restApi.ts @@ -26,6 +26,7 @@ import { getDeviceToken } from '../notifications'; import { store as reduxStore } from '../store/auxStore'; import sdk from './sdk'; import fetch from '../methods/helpers/fetch'; +import { getVoipPushToken } from './voip/getInitialEvents'; export const createChannel = ({ name, @@ -1009,6 +1010,13 @@ export const registerPushToken = () => appName: getBundleId }; try { + // TODO: this is temp only for VoIP push token + await sdk.post('push.token', { + type: 'gcm', + value: getVoipPushToken() || '', + appName: getBundleId + }); + // RC 0.60.0 await sdk.post('push.token', data); } catch (error) { diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index d0ed89e1af1..6a67bd4a8d8 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -8,6 +8,9 @@ import { voipCallOpen } from '../../../actions/deepLinking'; // Store VoIP push data temporarily let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; +let voipPushToken: string | null = null; + +export const getVoipPushToken = (): string | null => voipPushToken; export const getInitialEvents = async (): Promise<boolean> => { if (!isIOS) { @@ -15,6 +18,11 @@ export const getInitialEvents = async (): Promise<boolean> => { } try { + VoipPushNotification.addEventListener('register', (token: string) => { + console.log('[VoIP][getInitialEvents] Registered VoIP push token:', token); + voipPushToken = token; + }); + VoipPushNotification.addEventListener('didLoadWithEvents', events => { if (!events || !Array.isArray(events)) return; @@ -30,6 +38,10 @@ export const getInitialEvents = async (): Promise<boolean> => { console.log('[VoIP][getInitialEvents] Stored VoIP push data:', voipPushData); } } + if (name === VoipPushNotification.RNVoipPushRemoteNotificationsRegisteredEvent) { + voipPushToken = data; + console.log('[VoIP][getInitialEvents] Registered VoIP push token:', voipPushToken); + } } }); From 548e855524cb05fd97b739c1888cc5ccc49ec6b4 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 20 Jan 2026 16:06:10 -0300 Subject: [PATCH 28/61] Temp fix require cycle --- app/lib/services/restApi.ts | 2 +- app/lib/services/voip/getInitialEvents.ts | 10 ++++------ app/lib/services/voip/pushTokenAux.ts | 8 ++++++++ 3 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 app/lib/services/voip/pushTokenAux.ts diff --git a/app/lib/services/restApi.ts b/app/lib/services/restApi.ts index 2b7754e2c8f..7ba3c61b1f6 100644 --- a/app/lib/services/restApi.ts +++ b/app/lib/services/restApi.ts @@ -26,7 +26,7 @@ import { getDeviceToken } from '../notifications'; import { store as reduxStore } from '../store/auxStore'; import sdk from './sdk'; import fetch from '../methods/helpers/fetch'; -import { getVoipPushToken } from './voip/getInitialEvents'; +import { getVoipPushToken } from './voip/pushTokenAux'; export const createChannel = ({ name, diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index 6a67bd4a8d8..5ef5752bbda 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -5,12 +5,10 @@ import { isIOS } from '../../methods/helpers'; import { CallIdUUIDModule } from '../../native/CallIdUUID'; import store from '../../store'; import { voipCallOpen } from '../../../actions/deepLinking'; +import { setVoipPushToken } from './pushTokenAux'; // Store VoIP push data temporarily let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; -let voipPushToken: string | null = null; - -export const getVoipPushToken = (): string | null => voipPushToken; export const getInitialEvents = async (): Promise<boolean> => { if (!isIOS) { @@ -20,7 +18,7 @@ export const getInitialEvents = async (): Promise<boolean> => { try { VoipPushNotification.addEventListener('register', (token: string) => { console.log('[VoIP][getInitialEvents] Registered VoIP push token:', token); - voipPushToken = token; + setVoipPushToken(token); }); VoipPushNotification.addEventListener('didLoadWithEvents', events => { @@ -39,8 +37,8 @@ export const getInitialEvents = async (): Promise<boolean> => { } } if (name === VoipPushNotification.RNVoipPushRemoteNotificationsRegisteredEvent) { - voipPushToken = data; - console.log('[VoIP][getInitialEvents] Registered VoIP push token:', voipPushToken); + setVoipPushToken(data); + console.log('[VoIP][getInitialEvents] Registered VoIP push token:', data); } } }); diff --git a/app/lib/services/voip/pushTokenAux.ts b/app/lib/services/voip/pushTokenAux.ts new file mode 100644 index 00000000000..b369f770aa1 --- /dev/null +++ b/app/lib/services/voip/pushTokenAux.ts @@ -0,0 +1,8 @@ +// TODO: find a better place for this +let voipPushToken: string | null = null; + +export const getVoipPushToken = (): string | null => voipPushToken; + +export const setVoipPushToken = (token: string): void => { + voipPushToken = token; +}; From abbb072385a18180ece4d4323c5bf35eeae0c95e Mon Sep 17 00:00:00 2001 From: diegolmello <diegolmello@users.noreply.github.com> Date: Tue, 20 Jan 2026 19:09:11 +0000 Subject: [PATCH 29/61] chore: format code and fix lint issues [skip ci] --- app/sagas/login.js | 10 +++++----- .../CallView/components/CallActionButton.test.tsx | 8 +++++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/sagas/login.js b/app/sagas/login.js index ea4665fe86c..b252a5e4ff3 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -63,7 +63,7 @@ const showSupportedVersionsWarning = function* showSupportedVersionsWarning(serv const serversDB = database.servers; yield serversDB.write(async () => { - await serverRecord.update(r => { + await serverRecord.update((r) => { r.supportedVersionsWarningAt = new Date(); }); }); @@ -110,7 +110,7 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE } // this is updating on every login just to save `updated_at` // keeping this server as the most recent on autocomplete order - await serverHistoryRecord.update(s => { + await serverHistoryRecord.update((s) => { s.username = result.username; if (iconURL) { s.iconURL = iconURL; @@ -318,12 +318,12 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) { yield serversDB.write(async () => { try { const userRecord = await usersCollection.find(user.id); - await userRecord.update(record => { + await userRecord.update((record) => { record._raw = sanitizedRaw({ id: user.id, ...record._raw }, usersCollection.schema); Object.assign(record, u); }); } catch (e) { - await usersCollection.create(record => { + await usersCollection.create((record) => { record._raw = sanitizedRaw({ id: user.id }, usersCollection.schema); Object.assign(record, u); }); @@ -400,7 +400,7 @@ const handleSetUser = function* handleSetUser({ user }) { yield serversDB.write(async () => { try { const record = await userCollections.find(userId); - await record.update(userRecord => { + await record.update((userRecord) => { if ('avatarETag' in user) { userRecord.avatarETag = user.avatarETag; } diff --git a/app/views/CallView/components/CallActionButton.test.tsx b/app/views/CallView/components/CallActionButton.test.tsx index ac8791834cc..53809927c98 100644 --- a/app/views/CallView/components/CallActionButton.test.tsx +++ b/app/views/CallView/components/CallActionButton.test.tsx @@ -44,7 +44,13 @@ describe('CallActionButton', () => { it('should render with active variant', () => { const { getByTestId } = render( - <CallActionButton icon='microphone-disabled' label='Unmute' onPress={onPressMock} variant='active' testID='call-action-button' /> + <CallActionButton + icon='microphone-disabled' + label='Unmute' + onPress={onPressMock} + variant='active' + testID='call-action-button' + /> ); expect(getByTestId('call-action-button')).toBeTruthy(); }); From 77cb36e474d20db839e7a78a12edff291801cc4a Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 21 Jan 2026 14:58:18 -0300 Subject: [PATCH 30/61] CallIDUUID module on android and voip push --- .../rocket/reactnative/MainApplication.kt | 4 + .../notification/CallIdUUIDModule.kt | 72 ++++ .../notification/CallIdUUIDTurboPackage.kt | 30 ++ .../notification/NativeCallIdUUIDSpec.kt | 19 + .../notification/NativeVoipSpec.kt | 23 ++ .../notification/NotificationIntentHandler.kt | 67 +++- .../RCFirebaseMessagingService.kt | 41 ++- .../reactnative/notification/VoipModule.kt | 144 ++++++++ .../notification/VoipNotification.kt | 345 ++++++++++++++++++ .../notification/VoipTurboPackage.kt | 32 ++ app/lib/native/CallIdUUID.ts | 22 -- app/lib/native/NativeCallIdUUID.ts | 8 + app/lib/native/NativeVoipAndroid.ts | 9 + app/lib/notifications/push.ts | 1 + app/lib/services/restApi.ts | 14 +- app/lib/services/voip/MediaSessionInstance.ts | 2 +- app/lib/services/voip/getInitialEvents.ts | 112 +++++- ios/CallIdUUID.m | 7 - ios/CallIdUUID.swift | 67 ---- 19 files changed, 893 insertions(+), 126 deletions(-) create mode 100644 android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDModule.kt create mode 100644 android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDTurboPackage.kt create mode 100644 android/app/src/main/java/chat/rocket/reactnative/notification/NativeCallIdUUIDSpec.kt create mode 100644 android/app/src/main/java/chat/rocket/reactnative/notification/NativeVoipSpec.kt create mode 100644 android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt create mode 100644 android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt create mode 100644 android/app/src/main/java/chat/rocket/reactnative/notification/VoipTurboPackage.kt delete mode 100644 app/lib/native/CallIdUUID.ts create mode 100644 app/lib/native/NativeCallIdUUID.ts create mode 100644 app/lib/native/NativeVoipAndroid.ts delete mode 100644 ios/CallIdUUID.m delete mode 100644 ios/CallIdUUID.swift diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt index 5ac2e25f483..6e0fe420c99 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt @@ -20,6 +20,8 @@ import chat.rocket.reactnative.storage.MMKVKeyManager; import chat.rocket.reactnative.storage.SecureStoragePackage; import chat.rocket.reactnative.notification.VideoConfTurboPackage import chat.rocket.reactnative.notification.PushNotificationTurboPackage +import chat.rocket.reactnative.notification.VoipTurboPackage +import chat.rocket.reactnative.notification.CallIdUUIDTurboPackage /** * Main Application class. @@ -43,6 +45,8 @@ open class MainApplication : Application(), ReactApplication { add(WatermelonDBJSIPackage()) add(VideoConfTurboPackage()) add(PushNotificationTurboPackage()) + add(VoipTurboPackage()) + add(CallIdUUIDTurboPackage()) add(SecureStoragePackage()) } diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDModule.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDModule.kt new file mode 100644 index 00000000000..c3ba835c25a --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDModule.kt @@ -0,0 +1,72 @@ +package chat.rocket.reactnative.notification + +import com.facebook.react.bridge.ReactApplicationContext +import java.security.MessageDigest + +/** + * CallIdUUID - Converts a callId string to a deterministic UUID v5. + * This is used by CallKeep which requires UUIDs, while the server sends random callId strings. + * + * The algorithm matches the iOS implementation in CallIdUUID.swift to ensure + * consistency across platforms. + */ +object CallIdUUID { + + // Fixed namespace UUID for VoIP calls (RFC 4122 URL namespace) + // Using the standard URL namespace UUID: 6ba7b811-9dad-11d1-80b4-00c04fd430c8 + private val NAMESPACE_UUID = byteArrayOf( + 0x6b.toByte(), 0xa7.toByte(), 0xb8.toByte(), 0x11.toByte(), + 0x9d.toByte(), 0xad.toByte(), + 0x11.toByte(), 0xd1.toByte(), + 0x80.toByte(), 0xb4.toByte(), + 0x00.toByte(), 0xc0.toByte(), 0x4f.toByte(), 0xd4.toByte(), 0x30.toByte(), 0xc8.toByte() + ) + + /** + * Generates a UUID v5 from a callId string. + * Uses SHA-1 hash of namespace + callId, then formats as UUID v5. + * + * @param callId The call ID string to convert + * @return A deterministic UUID string in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + */ + @JvmStatic + fun generateUUIDv5(callId: String): String { + // Concatenate namespace UUID bytes with callId UTF-8 bytes + val callIdBytes = callId.toByteArray(Charsets.UTF_8) + val data = ByteArray(NAMESPACE_UUID.size + callIdBytes.size) + System.arraycopy(NAMESPACE_UUID, 0, data, 0, NAMESPACE_UUID.size) + System.arraycopy(callIdBytes, 0, data, NAMESPACE_UUID.size, callIdBytes.size) + + // SHA-1 hash + val md = MessageDigest.getInstance("SHA-1") + val hash = md.digest(data) + + // Set version (4 bits) to 5 (0101) + hash[6] = ((hash[6].toInt() and 0x0F) or 0x50).toByte() + + // Set variant (2 bits) to 10 + hash[8] = ((hash[8].toInt() and 0x3F) or 0x80).toByte() + + // Format as UUID string (only use first 16 bytes) + return String.format( + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + hash[0].toInt() and 0xFF, hash[1].toInt() and 0xFF, hash[2].toInt() and 0xFF, hash[3].toInt() and 0xFF, + hash[4].toInt() and 0xFF, hash[5].toInt() and 0xFF, + hash[6].toInt() and 0xFF, hash[7].toInt() and 0xFF, + hash[8].toInt() and 0xFF, hash[9].toInt() and 0xFF, + hash[10].toInt() and 0xFF, hash[11].toInt() and 0xFF, hash[12].toInt() and 0xFF, + hash[13].toInt() and 0xFF, hash[14].toInt() and 0xFF, hash[15].toInt() and 0xFF + ) + } +} + +/** + * React Native TurboModule implementation for CallIdUUID. + * Exposes the CallIdUUID functionality to JavaScript. + */ +class CallIdUUIDModule(reactContext: ReactApplicationContext) : NativeCallIdUUIDSpec(reactContext) { + + override fun getName() = NativeCallIdUUIDSpec.NAME + + override fun toUUID(callId: String): String = CallIdUUID.generateUUIDv5(callId) +} \ No newline at end of file diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDTurboPackage.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDTurboPackage.kt new file mode 100644 index 00000000000..54aa0c2e22b --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDTurboPackage.kt @@ -0,0 +1,30 @@ +package chat.rocket.reactnative.notification + +import com.facebook.react.BaseReactPackage +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.module.model.ReactModuleInfo +import com.facebook.react.module.model.ReactModuleInfoProvider + +class CallIdUUIDTurboPackage : BaseReactPackage() { + + override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? = + if (name == NativeCallIdUUIDSpec.NAME) { + CallIdUUIDModule(reactContext) + } else { + null + } + + override fun getReactModuleInfoProvider() = ReactModuleInfoProvider { + mapOf( + NativeCallIdUUIDSpec.NAME to ReactModuleInfo( + name = NativeCallIdUUIDSpec.NAME, + className = NativeCallIdUUIDSpec.NAME, + canOverrideExistingModule = false, + needsEagerInit = false, + isCxxModule = false, + isTurboModule = true + ) + ) + } +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NativeCallIdUUIDSpec.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NativeCallIdUUIDSpec.kt new file mode 100644 index 00000000000..6a5d7fb0e9b --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NativeCallIdUUIDSpec.kt @@ -0,0 +1,19 @@ +package chat.rocket.reactnative.notification + +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule +import com.facebook.react.bridge.ReactMethod +import com.facebook.react.turbomodule.core.interfaces.TurboModule + +abstract class NativeCallIdUUIDSpec(reactContext: ReactApplicationContext) : + ReactContextBaseJavaModule(reactContext), TurboModule { + + companion object { + const val NAME = "CallIdUUID" + } + + override fun getName(): String = NAME + + @ReactMethod(isBlockingSynchronousMethod = true) + abstract fun toUUID(callId: String): String +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NativeVoipSpec.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NativeVoipSpec.kt new file mode 100644 index 00000000000..41ebec955dc --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NativeVoipSpec.kt @@ -0,0 +1,23 @@ +package chat.rocket.reactnative.notification + +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule +import com.facebook.react.bridge.ReactMethod +import com.facebook.react.turbomodule.core.interfaces.TurboModule + +abstract class NativeVoipSpec(reactContext: ReactApplicationContext) : + ReactContextBaseJavaModule(reactContext), TurboModule { + + companion object { + const val NAME = "VoipModule" + } + + override fun getName(): String = NAME + + @ReactMethod + abstract fun getPendingVoipCall(promise: Promise) + + @ReactMethod + abstract fun clearPendingVoipCall() +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index 9cedae3ea2d..1a4d22f5dbb 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -17,11 +17,16 @@ class NotificationIntentHandler { /** * Handles a notification Intent from MainActivity. - * Processes both video conf and regular notification intents. + * Processes VoIP, video conf, and regular notification intents. */ @JvmStatic fun handleIntent(context: Context, intent: Intent) { - // Handle video conf action first + // Handle VoIP action first + if (handleVoipIntent(context, intent)) { + return + } + + // Handle video conf action if (handleVideoConfIntent(context, intent)) { return } @@ -30,6 +35,64 @@ class NotificationIntentHandler { handleNotificationIntent(context, intent) } + /** + * Handles VoIP call notification Intent. + * @return true if this was a VoIP intent, false otherwise + */ + @JvmStatic + private fun handleVoipIntent(context: Context, intent: Intent): Boolean { + if (!intent.getBooleanExtra("voipAction", false)) { + return false + } + + val notificationId = intent.getIntExtra("notificationId", 0) + val event = intent.getStringExtra("event") ?: return true + + val callId = intent.getStringExtra("callId") ?: "" + val callUUID = intent.getStringExtra("callUUID") ?: "" + val callerName = intent.getStringExtra("callerName") ?: "" + val host = intent.getStringExtra("host") ?: "" + val ejson = intent.getStringExtra("ejson") ?: "{}" + + Log.d(TAG, "Handling VoIP intent - event: $event, callId: $callId, callUUID: $callUUID") + + // Cancel the notification if it was shown as fallback + if (notificationId != 0) { + VoipNotification.cancelById(context, notificationId) + } + + // Store action for JS to pick up + val data = mapOf( + "notificationType" to "voip", + "event" to event, + "callId" to callId, + "callUUID" to callUUID, + "callerName" to callerName, + "host" to host, + "ejson" to ejson + ) + + val gson = GsonBuilder().create() + val jsonData = gson.toJson(data) + + // Store in VoIP-specific SharedPreferences for JS to retrieve + context.getSharedPreferences("VoipCallData", Context.MODE_PRIVATE) + .edit() + .putString("pendingAction", jsonData) + .putString("callId", callId) + .putString("callUUID", callUUID) + .putString("callerName", callerName) + .putString("host", host) + .putString("event", event) + .putLong("timestamp", System.currentTimeMillis()) + .apply() + + // Clear the voip flag to prevent re-processing + intent.removeExtra("voipAction") + + return true + } + /** * Handles video conference notification Intent. * @return true if this was a video conf intent, false otherwise diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt index c8aba96e6b9..1c3755e4f18 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt @@ -4,17 +4,20 @@ import android.os.Bundle import android.util.Log import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage +import com.google.gson.Gson /** * Custom Firebase Messaging Service for Rocket.Chat. * - * Handles incoming FCM messages and routes them to CustomPushNotification - * for advanced processing (E2E decryption, MessagingStyle, direct reply, etc.) + * Handles incoming FCM messages and routes them to the appropriate handler: + * - VoipNotification for VoIP calls (notificationType: "voip") + * - CustomPushNotification for regular messages and video conferences */ class RCFirebaseMessagingService : FirebaseMessagingService() { companion object { private const val TAG = "RocketChat.FCM" + private val gson = Gson() } override fun onMessageReceived(remoteMessage: RemoteMessage) { @@ -33,7 +36,23 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { } } - // Process the notification + // Parse ejson to determine notification type + val ejsonStr = data["ejson"] + val ejson = parseEjson(ejsonStr) + + // Route VoIP notifications to VoipNotification handler + if (ejson?.notificationType == "voip") { + Log.d(TAG, "Routing to VoipNotification handler") + try { + val voipNotification = VoipNotification(this) + voipNotification.showIncomingCall(bundle, ejson) + } catch (e: Exception) { + Log.e(TAG, "Error processing VoIP notification", e) + } + return + } + + // Process regular notifications via CustomPushNotification try { val notification = CustomPushNotification(this, bundle) notification.onReceived() @@ -42,6 +61,22 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { } } + /** + * Safely parses ejson string to Ejson object. + */ + private fun parseEjson(ejsonStr: String?): Ejson? { + if (ejsonStr.isNullOrEmpty() || ejsonStr == "{}") { + return null + } + + return try { + gson.fromJson(ejsonStr, Ejson::class.java) + } catch (e: Exception) { + Log.e(TAG, "Failed to parse ejson", e) + null + } + } + override fun onNewToken(token: String) { Log.d(TAG, "FCM token refreshed") // Token handling is done by expo-notifications JS layer diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt new file mode 100644 index 00000000000..bd454dd08b9 --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt @@ -0,0 +1,144 @@ +package chat.rocket.reactnative.notification + +import android.content.Context +import android.util.Log +import com.facebook.react.bridge.Promise +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactMethod +import com.facebook.react.modules.core.DeviceEventManagerModule +import com.google.gson.GsonBuilder +import java.lang.ref.WeakReference + +/** + * Native module to expose VoIP call data to JavaScript. + * Used to retrieve pending VoIP call data when the app opens from a VoIP notification. + */ +class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactContext) { + + companion object { + private const val TAG = "RocketChat.VoipModule" + private const val PREFS_NAME = "VoipCallData" + private const val EVENT_VOIP_CALL = "VoipCallAction" + + private var reactContextRef: WeakReference<ReactApplicationContext>? = null + + /** + * Sets the React context reference for event emission. + */ + @JvmStatic + fun setReactContext(context: ReactApplicationContext) { + reactContextRef = WeakReference(context) + } + + /** + * Emits a VoIP call event to JavaScript when the app is running. + */ + @JvmStatic + fun emitVoipCallEvent(callDataJson: String) { + try { + reactContextRef?.get()?.let { context -> + if (context.hasActiveReactInstance()) { + context + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) + .emit(EVENT_VOIP_CALL, callDataJson) + Log.d(TAG, "Emitted VoIP call event to JS") + } + } + } catch (e: Exception) { + Log.e(TAG, "Failed to emit VoIP call event", e) + } + } + + /** + * Stores VoIP call data for JS to retrieve. + * Also emits an event if the app is running. + */ + @JvmStatic + fun storePendingVoipCall(context: Context, callId: String, callUUID: String, callerName: String, host: String, event: String) { + val data = mapOf( + "notificationType" to "voip", + "callId" to callId, + "callUUID" to callUUID, + "callerName" to callerName, + "host" to host, + "event" to event + ) + + val gson = GsonBuilder().create() + val jsonData = gson.toJson(data) + + context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + .edit() + .putString("pendingAction", jsonData) + .putString("callId", callId) + .putString("callUUID", callUUID) + .putString("callerName", callerName) + .putString("host", host) + .putString("event", event) + .putLong("timestamp", System.currentTimeMillis()) + .apply() + + Log.d(TAG, "Stored pending VoIP call: $callId") + + // Emit event if app is running + emitVoipCallEvent(jsonData) + } + } + + init { + // Store reference for event emission + setReactContext(reactApplicationContext) + } + + /** + * Gets any pending VoIP call data. + * Returns null if no pending call. + */ + @ReactMethod + override fun getPendingVoipCall(promise: Promise) { + try { + val prefs = reactApplicationContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + + // Check if data is stale (older than 5 minutes) + val timestamp = prefs.getLong("timestamp", 0) + if (System.currentTimeMillis() - timestamp > 5 * 60 * 1000) { + Log.d(TAG, "Pending VoIP call data is stale, clearing") + clearPendingVoipCallInternal() + promise.resolve(null) + return + } + + val pendingAction = prefs.getString("pendingAction", null) + if (pendingAction != null) { + // Clear after reading + clearPendingVoipCallInternal() + Log.d(TAG, "Retrieved and cleared pending VoIP call") + } + + promise.resolve(pendingAction) + } catch (e: Exception) { + Log.e(TAG, "Error getting pending VoIP call", e) + promise.reject("ERROR", e.message) + } + } + + /** + * Clears any pending VoIP call data. + */ + @ReactMethod + override fun clearPendingVoipCall() { + clearPendingVoipCallInternal() + } + + private fun clearPendingVoipCallInternal() { + try { + reactApplicationContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + .edit() + .clear() + .apply() + Log.d(TAG, "Cleared pending VoIP call data") + } catch (e: Exception) { + Log.e(TAG, "Error clearing pending VoIP call", e) + } + } +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt new file mode 100644 index 00000000000..2dd9eb30688 --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt @@ -0,0 +1,345 @@ +package chat.rocket.reactnative.notification + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.media.AudioAttributes +import android.media.RingtoneManager +import android.os.Build +import android.os.Bundle +import android.util.Log +import androidx.core.app.NotificationCompat +import chat.rocket.reactnative.MainActivity +import io.wazo.callkeep.RNCallKeepModule + +/** + * Handles VoIP call notifications using Android's Telecom framework via CallKeep. + * Displays incoming call UI through the system's phone app / telecom service. + * + * When CallKeep is available (app running), it uses the native telecom call UI. + * When CallKeep is not available (app killed), it shows a high-priority notification + * similar to VideoConfNotification. + */ +class VoipNotification(private val context: Context) { + + companion object { + private const val TAG = "RocketChat.VoIP" + + const val CHANNEL_ID = "voip-call" + const val CHANNEL_NAME = "VoIP Calls" + + const val ACTION_ACCEPT = "chat.rocket.reactnative.ACTION_VOIP_ACCEPT" + const val ACTION_DECLINE = "chat.rocket.reactnative.ACTION_VOIP_DECLINE" + + /** + * Cancels a VoIP call by ending it through CallKeep. + */ + @JvmStatic + fun endCall(callUUID: String) { + try { + val instance = RNCallKeepModule.instance + if (instance != null) { + instance.endCall(callUUID) + Log.d(TAG, "VoIP call ended via CallKeep with UUID: $callUUID") + } else { + Log.w(TAG, "Cannot end call: RNCallKeepModule instance not available") + } + } catch (e: Exception) { + Log.e(TAG, "Failed to end VoIP call", e) + } + } + + /** + * Static method to retrieve stored call data from any context. + */ + @JvmStatic + fun getStoredCallData(context: Context): Bundle? { + try { + val prefs = context.getSharedPreferences("VoipCallData", Context.MODE_PRIVATE) + val callId = prefs.getString("callId", null) ?: return null + val callUUID = prefs.getString("callUUID", null) ?: return null + + // Check if data is stale (older than 5 minutes) + val timestamp = prefs.getLong("timestamp", 0) + if (System.currentTimeMillis() - timestamp > 5 * 60 * 1000) { + Log.d(TAG, "Stored VoIP call data is stale, clearing") + clearStoredCallData(context) + return null + } + + return Bundle().apply { + putString("notificationType", "voip") + putString("callId", callId) + putString("callUUID", callUUID) + putString("callerName", prefs.getString("callerName", "Unknown")) + putString("host", prefs.getString("host", "")) + putString("ejson", prefs.getString("ejson", "{}")) + } + } catch (e: Exception) { + Log.e(TAG, "Failed to retrieve stored VoIP call data", e) + return null + } + } + + /** + * Static method to clear stored call data from any context. + */ + @JvmStatic + fun clearStoredCallData(context: Context) { + try { + val prefs = context.getSharedPreferences("VoipCallData", Context.MODE_PRIVATE) + prefs.edit().clear().apply() + Log.d(TAG, "Cleared stored VoIP call data") + } catch (e: Exception) { + Log.e(TAG, "Failed to clear stored VoIP call data", e) + } + } + + /** + * Cancels a VoIP notification by ID. + */ + @JvmStatic + fun cancelById(context: Context, notificationId: Int) { + val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager + manager?.cancel(notificationId) + Log.d(TAG, "VoIP notification cancelled with ID: $notificationId") + } + } + + private val notificationManager: NotificationManager? = + context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager + + init { + createNotificationChannel() + } + + /** + * Creates the notification channel for VoIP calls with high importance and ringtone sound. + */ + private fun createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel( + CHANNEL_ID, + CHANNEL_NAME, + NotificationManager.IMPORTANCE_HIGH + ).apply { + description = "Incoming VoIP calls" + enableLights(true) + enableVibration(true) + lockscreenVisibility = Notification.VISIBILITY_PUBLIC + + // Set ringtone sound + val ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE) + val audioAttributes = AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) + .build() + setSound(ringtoneUri, audioAttributes) + } + + notificationManager?.createNotificationChannel(channel) + } + } + + /** + * Displays an incoming VoIP call using CallKeep's telecom integration. + * Falls back to a notification if CallKeep is not available. + * + * @param bundle The notification data bundle + * @param ejson The parsed notification payload + */ + fun showIncomingCall(bundle: Bundle, ejson: Ejson) { + val callId = ejson.callId + if (callId.isNullOrEmpty()) { + Log.w(TAG, "Cannot show VoIP call: callId is missing") + return + } + + // Get caller information + val callerName: String = when { + !ejson.senderName.isNullOrEmpty() -> ejson.senderName + ejson.caller?.name != null -> ejson.caller.name + ejson.caller?.username != null -> ejson.caller.username + ejson.sender?.name != null -> ejson.sender.name + ejson.sender?.username != null -> ejson.sender.username + else -> "Unknown" + } + + // Generate deterministic UUID from callId (matching iOS implementation) + val callUUID = CallIdUUID.generateUUIDv5(callId) + + Log.d(TAG, "Showing incoming VoIP call - callId: $callId, callUUID: $callUUID, caller: $callerName") + + // Store call data for when the user answers + storeCallData(callId, callUUID, callerName, ejson.host, bundle.getString("ejson", "{}")) + + // Try to display incoming call through CallKeep's telecom integration + val callKeepInstance = RNCallKeepModule.instance + if (callKeepInstance != null) { + try { + callKeepInstance.displayIncomingCall(callUUID, callerName, callerName, false) + Log.d(TAG, "VoIP call displayed via CallKeep with UUID: $callUUID") + return + } catch (e: Exception) { + Log.e(TAG, "Failed to display incoming call via CallKeep", e) + } + } else { + Log.d(TAG, "RNCallKeepModule instance not available, using fallback notification") + } + + // Fallback to showing a high-priority notification + showFallbackNotification(bundle, ejson, callUUID, callerName) + } + + /** + * Stores call data in SharedPreferences for retrieval when the call is answered. + * This is needed because CallKeep's answer callback only provides the UUID, + * not the full call data. + */ + private fun storeCallData(callId: String, callUUID: String, callerName: String, host: String?, ejsonStr: String) { + try { + val prefs = context.getSharedPreferences("VoipCallData", Context.MODE_PRIVATE) + prefs.edit().apply { + putString("callId", callId) + putString("callUUID", callUUID) + putString("callerName", callerName) + putString("host", host ?: "") + putString("ejson", ejsonStr) + putLong("timestamp", System.currentTimeMillis()) + apply() + } + Log.d(TAG, "Stored VoIP call data for callUUID: $callUUID") + } catch (e: Exception) { + Log.e(TAG, "Failed to store VoIP call data", e) + } + } + + /** + * Fallback notification when CallKeep is not available (app killed). + * Shows a high-priority notification similar to VideoConfNotification. + */ + private fun showFallbackNotification(bundle: Bundle, ejson: Ejson, callUUID: String, callerName: String) { + val callId = ejson.callId ?: "" + + // Generate notification ID from callUUID + val notificationId = callUUID.replace("-", "").hashCode() + + Log.d(TAG, "Showing fallback notification for VoIP call from: $callerName") + + // Create intent data for actions + val intentData = Bundle().apply { + putString("notificationType", "voip") + putString("callId", callId) + putString("callUUID", callUUID) + putString("callerName", callerName) + putString("host", ejson.host ?: "") + putString("ejson", bundle.getString("ejson", "{}")) + putInt("notificationId", notificationId) + } + + // Full screen intent - opens app when notification is tapped + val fullScreenIntent = Intent(context, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + putExtras(intentData) + putExtra("event", "default") + } + val fullScreenPendingIntent = createPendingIntent(notificationId, fullScreenIntent) + + // Accept action + val acceptIntent = Intent(context, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + putExtras(intentData) + putExtra("event", "accept") + putExtra("voipAction", true) + action = "${ACTION_ACCEPT}_$notificationId" + } + val acceptPendingIntent = createPendingIntent(notificationId + 1, acceptIntent) + + // Decline action + val declineIntent = Intent(context, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + putExtras(intentData) + putExtra("event", "decline") + putExtra("voipAction", true) + action = "${ACTION_DECLINE}_$notificationId" + } + val declinePendingIntent = createPendingIntent(notificationId + 2, declineIntent) + + // Get icons + val packageName = context.packageName + val smallIconResId = context.resources.getIdentifier("ic_notification", "drawable", packageName) + + // Fetch caller avatar + val avatarUri = ejson.getCallerAvatarUri() + val avatarBitmap: Bitmap? = if (avatarUri != null) { + NotificationHelper.fetchAvatarBitmap(context, avatarUri, null) + } else { + null + } + + // Build notification + val builder = NotificationCompat.Builder(context, CHANNEL_ID).apply { + setSmallIcon(smallIconResId) + setContentTitle("Incoming call") + setContentText("Call from $callerName") + priority = NotificationCompat.PRIORITY_HIGH + setCategory(NotificationCompat.CATEGORY_CALL) + setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + setAutoCancel(false) + setOngoing(true) + setFullScreenIntent(fullScreenPendingIntent, true) + setContentIntent(fullScreenPendingIntent) + addAction(0, "Decline", declinePendingIntent) + addAction(0, "Accept", acceptPendingIntent) + + if (avatarBitmap != null) { + setLargeIcon(avatarBitmap) + } + } + + // Set sound for pre-O devices + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + val ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE) + builder.setSound(ringtoneUri) + } + + // Show notification + notificationManager?.notify(notificationId, builder.build()) + Log.d(TAG, "VoIP fallback notification displayed with ID: $notificationId") + } + + /** + * Creates a PendingIntent with appropriate flags for the Android version. + */ + private fun createPendingIntent(requestCode: Int, intent: Intent): PendingIntent { + val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + } else { + PendingIntent.FLAG_UPDATE_CURRENT + } + return PendingIntent.getActivity(context, requestCode, intent, flags) + } + + /** + * Cancels a VoIP call by callId. + * + * @param callId The call ID + */ + fun cancelCall(callId: String) { + val callUUID = CallIdUUID.generateUUIDv5(callId) + + // End call via CallKeep if available + endCall(callUUID) + + // Cancel fallback notification if shown + val notificationId = callUUID.replace("-", "").hashCode() + cancelById(context, notificationId) + + // Clear stored data + clearStoredCallData(context) + } +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipTurboPackage.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipTurboPackage.kt new file mode 100644 index 00000000000..ba038314176 --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipTurboPackage.kt @@ -0,0 +1,32 @@ +package chat.rocket.reactnative.notification + +import com.facebook.react.TurboReactPackage +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.module.model.ReactModuleInfo +import com.facebook.react.module.model.ReactModuleInfoProvider + +class VoipTurboPackage : TurboReactPackage() { + + override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { + return when (name) { + NativeVoipSpec.NAME -> VoipModule(reactContext) + else -> null + } + } + + override fun getReactModuleInfoProvider(): ReactModuleInfoProvider { + return ReactModuleInfoProvider { + mapOf( + NativeVoipSpec.NAME to ReactModuleInfo( + NativeVoipSpec.NAME, + NativeVoipSpec.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + false, // isCxxModule + true // isTurboModule + ) + ) + } + } +} diff --git a/app/lib/native/CallIdUUID.ts b/app/lib/native/CallIdUUID.ts deleted file mode 100644 index 3b3f77dde49..00000000000 --- a/app/lib/native/CallIdUUID.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { NativeModules, Platform } from 'react-native'; - -interface ICallIdUUIDModule { - toUUID(callId: string): string; -} - -const { CallIdUUID } = NativeModules; - -/** - * Native module to convert a callId string to a deterministic UUID v5. - * This is used by CallKit which requires UUIDs, while the server sends random callId strings. - * The same UUID v5 algorithm is used in both native (AppDelegate) and JS for consistency. - */ -export const CallIdUUIDModule: ICallIdUUIDModule = { - toUUID: (callId: string): string => { - if (Platform.OS !== 'ios') { - // Android doesn't use CallKit, return the callId as-is or implement Android equivalent - return callId; - } - return CallIdUUID.toUUID(callId); - } -}; diff --git a/app/lib/native/NativeCallIdUUID.ts b/app/lib/native/NativeCallIdUUID.ts new file mode 100644 index 00000000000..4dcaec05919 --- /dev/null +++ b/app/lib/native/NativeCallIdUUID.ts @@ -0,0 +1,8 @@ +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +export interface Spec extends TurboModule { + toUUID(callId: string): string; +} + +export default TurboModuleRegistry.getEnforcing<Spec>('CallIdUUID'); diff --git a/app/lib/native/NativeVoipAndroid.ts b/app/lib/native/NativeVoipAndroid.ts new file mode 100644 index 00000000000..95395d7a405 --- /dev/null +++ b/app/lib/native/NativeVoipAndroid.ts @@ -0,0 +1,9 @@ +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +export interface Spec extends TurboModule { + getPendingVoipCall(): Promise<string | null>; + clearPendingVoipCall(): void; +} + +export default TurboModuleRegistry.get<Spec>('VoipModule'); diff --git a/app/lib/notifications/push.ts b/app/lib/notifications/push.ts index beae1c10db6..b5c2a37afd6 100644 --- a/app/lib/notifications/push.ts +++ b/app/lib/notifications/push.ts @@ -185,6 +185,7 @@ export const pushNotificationConfigure = (onNotification: (notification: INotifi registerForPushNotifications().then(token => { if (token) { deviceToken = token; + console.log('[push.ts] Registered for push notifications:', token); } }); diff --git a/app/lib/services/restApi.ts b/app/lib/services/restApi.ts index 7ba3c61b1f6..0a949dab6bc 100644 --- a/app/lib/services/restApi.ts +++ b/app/lib/services/restApi.ts @@ -1010,12 +1010,14 @@ export const registerPushToken = () => appName: getBundleId }; try { - // TODO: this is temp only for VoIP push token - await sdk.post('push.token', { - type: 'gcm', - value: getVoipPushToken() || '', - appName: getBundleId - }); + if (isIOS) { + // TODO: this is temp only for VoIP push token + await sdk.post('push.token', { + type: 'gcm', + value: getVoipPushToken() || '', + appName: getBundleId + }); + } // RC 0.60.0 await sdk.post('push.token', data); diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index ad0f0860a64..aedaaa96c77 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -14,7 +14,7 @@ import { store } from '../../store/auxStore'; import sdk from '../sdk'; import Navigation from '../../navigation/appNavigation'; import { parseStringToIceServers } from './parseStringToIceServers'; -import { CallIdUUIDModule } from '../../native/CallIdUUID'; +import CallIdUUIDModule from '../../native/NativeCallIdUUID'; import type { IceServer } from '../../../definitions/Voip'; import type { IDDPMessage } from '../../../definitions/IDDPMessage'; diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index 5ef5752bbda..2eb7cb37850 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -2,22 +2,35 @@ import RNCallKeep from 'react-native-callkeep'; import VoipPushNotification from 'react-native-voip-push-notification'; import { isIOS } from '../../methods/helpers'; -import { CallIdUUIDModule } from '../../native/CallIdUUID'; +import CallIdUUIDModule from '../../native/NativeCallIdUUID'; +import NativeVoipModule from '../../native/NativeVoipAndroid'; import store from '../../store'; import { voipCallOpen } from '../../../actions/deepLinking'; import { setVoipPushToken } from './pushTokenAux'; -// Store VoIP push data temporarily +// Store VoIP push data temporarily (iOS only - Android uses native storage) let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; -export const getInitialEvents = async (): Promise<boolean> => { - if (!isIOS) { - return false; +/** + * Handles initial VoIP events on app startup. + * + * iOS: Uses VoipPushNotification to capture VoIP push data and CallKeep events + * Android: Uses native module to retrieve pending VoIP call data from Intent/SharedPreferences + */ +export const getInitialEvents = (): Promise<boolean> => { + if (isIOS) { + return getInitialEventsIOS(); } + return getInitialEventsAndroid(); +}; +/** + * iOS-specific implementation using VoipPushNotification and CallKeep + */ +const getInitialEventsIOS = async (): Promise<boolean> => { try { VoipPushNotification.addEventListener('register', (token: string) => { - console.log('[VoIP][getInitialEvents] Registered VoIP push token:', token); + console.log('[VoIP][iOS] Registered VoIP push token:', token); setVoipPushToken(token); }); @@ -33,21 +46,21 @@ export const getInitialEvents = async (): Promise<boolean> => { if (callId) { const callUUID = CallIdUUIDModule.toUUID(callId); voipPushData = { callId, caller: caller || 'Unknown', host, callUUID }; - console.log('[VoIP][getInitialEvents] Stored VoIP push data:', voipPushData); + console.log('[VoIP][iOS] Stored VoIP push data:', voipPushData); } } if (name === VoipPushNotification.RNVoipPushRemoteNotificationsRegisteredEvent) { setVoipPushToken(data); - console.log('[VoIP][getInitialEvents] Registered VoIP push token:', data); + console.log('[VoIP][iOS] Registered VoIP push token:', data); } } }); RNCallKeep.addEventListener('answerCall', ({ callUUID }) => { - console.log('[CallKeep][getInitialEvents] Live answerCall event received:', callUUID); + console.log('[VoIP][iOS] Live answerCall event received:', callUUID); if (voipPushData && voipPushData.callUUID.toLowerCase() === callUUID.toLowerCase()) { - console.log('[CallKeep][getInitialEvents] Matched live answer to VoIP call'); + console.log('[VoIP][iOS] Matched live answer to VoIP call'); if (voipPushData.host) { store.dispatch( voipCallOpen({ @@ -56,25 +69,25 @@ export const getInitialEvents = async (): Promise<boolean> => { host: voipPushData.host }) ); - console.log('[CallKeep][getInitialEvents] Dispatched voipCallOpen action from live listener'); + console.log('[VoIP][iOS] Dispatched voipCallOpen action from live listener'); } } else { - console.log('[CallKeep][getInitialEvents] Live answer UUID mismatch. Answer:', callUUID, 'VoIP:', voipPushData?.callUUID); + console.log('[VoIP][iOS] Live answer UUID mismatch. Answer:', callUUID, 'VoIP:', voipPushData?.callUUID); } }); const initialEvents = await RNCallKeep.getInitialEvents(); - console.log('[CallKeep][getInitialEvents] Initial events:', JSON.stringify(initialEvents, null, 2)); + console.log('[VoIP][iOS] Initial events:', JSON.stringify(initialEvents, null, 2)); for (const event of initialEvents) { const { name, data } = event; if (name === 'RNCallKeepPerformAnswerCallAction') { const { callUUID } = data; - console.log('[CallKeep][getInitialEvents] Found ANSWER event:', callUUID); + console.log('[VoIP][iOS] Found ANSWER event:', callUUID); if (voipPushData && voipPushData.callUUID.toLowerCase() === callUUID.toLowerCase()) { - console.log('[CallKeep][getInitialEvents] Matched answer to VoIP call:', voipPushData); + console.log('[VoIP][iOS] Matched answer to VoIP call:', voipPushData); if (voipPushData.host) { store.dispatch( @@ -84,13 +97,13 @@ export const getInitialEvents = async (): Promise<boolean> => { host: voipPushData.host }) ); - console.log('[CallKeep][getInitialEvents] Dispatched voipCallOpen action'); + console.log('[VoIP][iOS] Dispatched voipCallOpen action'); RNCallKeep.clearInitialEvents(); return true; } } else { - console.log('[CallKeep][getInitialEvents] Answer event UUID does not match VoIP push UUID'); + console.log('[VoIP][iOS] Answer event UUID does not match VoIP push UUID'); } } } @@ -101,7 +114,70 @@ export const getInitialEvents = async (): Promise<boolean> => { return false; } catch (error) { - console.error('[CallKeep][getInitialEvents] Error:', error); + console.error('[VoIP][iOS] Error:', error); + return false; + } +}; + +/** + * Android-specific implementation using native module to retrieve VoIP call data + */ +const getInitialEventsAndroid = async (): Promise<boolean> => { + try { + // Check for pending VoIP call from native module + if (!NativeVoipModule) { + console.log('[VoIP][Android] Native VoIP module not available'); + return false; + } + + const pendingCallJson = await NativeVoipModule.getPendingVoipCall(); + if (!pendingCallJson) { + console.log('[VoIP][Android] No pending VoIP call'); + return false; + } + + console.log('[VoIP][Android] Found pending VoIP call:', pendingCallJson); + + const pendingCall = JSON.parse(pendingCallJson) as { + notificationType: string; + callId: string; + callUUID: string; + callerName: string; + host: string; + event: string; + }; + + // Only handle 'accept' events + if (pendingCall.event !== 'accept') { + console.log('[VoIP][Android] Pending call event is not accept:', pendingCall.event); + return false; + } + + if (!pendingCall.callId || !pendingCall.host) { + console.log('[VoIP][Android] Missing required call data'); + return false; + } + + // Generate UUID if not provided + const callUUID = pendingCall.callUUID || CallIdUUIDModule.toUUID(pendingCall.callId); + + console.log('[VoIP][Android] Dispatching voipCallOpen:', { + callId: pendingCall.callId, + callUUID, + host: pendingCall.host + }); + + store.dispatch( + voipCallOpen({ + callId: pendingCall.callId, + callUUID, + host: pendingCall.host + }) + ); + + return true; + } catch (error) { + console.error('[VoIP][Android] Error:', error); return false; } }; diff --git a/ios/CallIdUUID.m b/ios/CallIdUUID.m deleted file mode 100644 index 019b69f4938..00000000000 --- a/ios/CallIdUUID.m +++ /dev/null @@ -1,7 +0,0 @@ -#import <React/RCTBridgeModule.h> - -@interface RCT_EXTERN_MODULE(CallIdUUID, NSObject) - -RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(toUUID:(NSString *)callId) - -@end diff --git a/ios/CallIdUUID.swift b/ios/CallIdUUID.swift deleted file mode 100644 index 8318e45d36b..00000000000 --- a/ios/CallIdUUID.swift +++ /dev/null @@ -1,67 +0,0 @@ -import Foundation -import CommonCrypto - -/** - * CallIdUUID - Converts a callId string to a deterministic UUID v5. - * This is used by CallKit which requires UUIDs, while the server sends random callId strings. - */ -@objc(CallIdUUID) -final class CallIdUUID: NSObject { - - // Fixed namespace UUID for VoIP calls (RFC 4122 URL namespace) - // Using the standard URL namespace UUID: 6ba7b811-9dad-11d1-80b4-00c04fd430c8 - private static let namespaceUUID: [UInt8] = [ - 0x6b, 0xa7, 0xb8, 0x11, - 0x9d, 0xad, - 0x11, 0xd1, - 0x80, 0xb4, - 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 - ] - - @objc - static func requiresMainQueueSetup() -> Bool { - return false - } - - /** - * Converts a callId string to a deterministic UUID v5 string. - * Uses SHA-1 hash of namespace + callId, then formats as UUID v5. - * This is a synchronous method for use from JavaScript. - */ - @objc - func toUUID(_ callId: String) -> String { - return CallIdUUID.generateUUIDv5(from: callId) - } - - /** - * Static method for use in AppDelegate and other native code. - * Generates a UUID v5 from a callId string. - */ - static func generateUUIDv5(from callId: String) -> String { - // Concatenate namespace UUID bytes with callId UTF-8 bytes - var data = Data(namespaceUUID) - data.append(callId.data(using: .utf8) ?? Data()) - - // SHA-1 hash - var hash = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH)) - data.withUnsafeBytes { dataBytes in - _ = CC_SHA1(dataBytes.baseAddress, CC_LONG(data.count), &hash) - } - - // Set version (4 bits) to 5 (0101) - hash[6] = (hash[6] & 0x0F) | 0x50 - - // Set variant (2 bits) to 10 - hash[8] = (hash[8] & 0x3F) | 0x80 - - // Format as UUID string (only use first 16 bytes) - let uuid = String(format: "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - hash[0], hash[1], hash[2], hash[3], - hash[4], hash[5], - hash[6], hash[7], - hash[8], hash[9], - hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]) - - return uuid - } -} From 59f25eb41edf90c6653aa2ff7ea4ec1fbbf21d73 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Thu, 22 Jan 2026 17:20:22 -0300 Subject: [PATCH 31/61] Add setCallUUID on useCallStore to persist calls accepted on native Android --- .../RCFirebaseMessagingService.kt | 37 +++++++++--- .../reactnative/notification/VoipModule.kt | 1 + .../reactnative/notification/VoipPayload.kt | 59 +++++++++++++++++++ app/lib/services/voip/MediaSessionInstance.ts | 36 +++++++---- app/lib/services/voip/getInitialEvents.ts | 5 +- app/lib/services/voip/useCallStore.ts | 5 ++ 6 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt index 1c3755e4f18..5216a667f43 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt @@ -36,14 +36,11 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { } } - // Parse ejson to determine notification type - val ejsonStr = data["ejson"] - val ejson = parseEjson(ejsonStr) - - // Route VoIP notifications to VoipNotification handler - if (ejson?.notificationType == "voip") { - Log.d(TAG, "Routing to VoipNotification handler") + val voipPayload = parseVoipPayload(data) + if (voipPayload != null && voipPayload.isVoipIncomingCall()) { + Log.d(TAG, "Detected new VoIP payload format, routing to VoipNotification handler") try { + val ejson = voipPayload.toEjson() val voipNotification = VoipNotification(this) voipNotification.showIncomingCall(bundle, ejson) } catch (e: Exception) { @@ -61,6 +58,32 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { } } + /** + * Parses the new VoIP payload format from FCM data map. + * Returns null if the payload doesn't match the new format. + */ + private fun parseVoipPayload(data: Map<String, String>): VoipPayload? { + val type = data["type"] + val hasEjson = data.containsKey("ejson") && !data["ejson"].isNullOrEmpty() + + if (type != "incoming_call" || hasEjson) { + return null + } + + return try { + VoipPayload( + callId = data["callId"], + calleeId = data["calleeId"], + caller = data["caller"], + host = data["host"], + type = data["type"] + ) + } catch (e: Exception) { + Log.e(TAG, "Failed to parse VoIP payload", e) + null + } + } + /** * Safely parses ejson string to Ejson object. */ diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt index bd454dd08b9..925fb81ef17 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt @@ -55,6 +55,7 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo */ @JvmStatic fun storePendingVoipCall(context: Context, callId: String, callUUID: String, callerName: String, host: String, event: String) { + // TODO: use VoipPayload val data = mapOf( "notificationType" to "voip", "callId" to callId, diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt new file mode 100644 index 00000000000..f12141ec5c3 --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt @@ -0,0 +1,59 @@ +package chat.rocket.reactnative.notification + +import com.google.gson.annotations.SerializedName + +data class VoipPayload( + @SerializedName("callId") + val callId: String?, + + @SerializedName("calleeId") + val calleeId: String?, + + @SerializedName("caller") + val caller: String?, + + @SerializedName("host") + val host: String?, + + @SerializedName("type") + val type: String? +) { + /** + * Converts this VoipPayload to an Ejson object for compatibility with existing VoipNotification code. + * + * Since VoipNotification.showIncomingCall() expects an Ejson object, we create a minimal + * Ejson instance with the necessary fields populated from this payload. + */ + fun toEjson(): Ejson { + val ejson = Ejson() + + // Map direct fields + ejson.callId = this.callId + ejson.host = this.host + ejson.notificationType = "incoming_call" + + // Convert caller string to Caller object + // The caller field is a string in the new format, but Ejson expects a Caller object + if (!this.caller.isNullOrEmpty()) { + val callerObj = Ejson.Caller() + // Since we only have the caller name as a string, we'll use it as both name and username + // This is a limitation - we don't have username in the new format + callerObj.name = this.caller + callerObj.username = this.caller // Use name as username fallback + ejson.caller = callerObj + } + + // Set senderName for compatibility with VoipNotification.showIncomingCall() + // which checks senderName first when determining caller name + ejson.senderName = this.caller + + return ejson + } + + /** + * Checks if this payload represents a VoIP incoming call. + */ + fun isVoipIncomingCall(): Boolean { + return type == "incoming_call" && !callId.isNullOrEmpty() + } +} diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index aedaaa96c77..3101df6a7dd 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -70,7 +70,13 @@ class MediaSessionInstance { call.emitter.on('stateChange', oldState => { console.log(`📊 ${oldState} → ${call.state}`); }); - // Use deterministic UUID v5 from callId - same as native side + + const existingCallUUID = useCallStore.getState().callUUID; + if (existingCallUUID) { + this.answerCall(existingCallUUID); + return; + } + const callUUID = CallIdUUIDModule.toUUID(call.callId); const displayName = call.contact.displayName || call.contact.username || 'Unknown'; @@ -83,19 +89,23 @@ class MediaSessionInstance { }); } + private answerCall = async (callUUID: string) => { + const mainCall = this.instance?.getMainCall(); + // Compare using deterministic UUID conversion + if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { + await mainCall.accept(); + RNCallKeep.setCurrentCallActive(callUUID); + // Set call in Zustand store and navigate to CallView + useCallStore.getState().setCall(mainCall, callUUID); + Navigation.navigate('CallView', { callUUID }); + } else { + RNCallKeep.endCall(callUUID); + } + }; + private configureRNCallKeep = () => { - this.callKeepListeners.answerCall = RNCallKeep.addEventListener('answerCall', async ({ callUUID }) => { - const mainCall = this.instance?.getMainCall(); - // Compare using deterministic UUID conversion - if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { - await mainCall.accept(); - RNCallKeep.setCurrentCallActive(callUUID); - // Set call in Zustand store and navigate to CallView - useCallStore.getState().setCall(mainCall, callUUID); - Navigation.navigate('CallView', { callUUID }); - } else { - RNCallKeep.endCall(callUUID); - } + this.callKeepListeners.answerCall = RNCallKeep.addEventListener('answerCall', ({ callUUID }) => { + this.answerCall(callUUID); }); this.callKeepListeners.endCall = RNCallKeep.addEventListener('endCall', ({ callUUID }) => { diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index 2eb7cb37850..eb1a3110d01 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -7,6 +7,7 @@ import NativeVoipModule from '../../native/NativeVoipAndroid'; import store from '../../store'; import { voipCallOpen } from '../../../actions/deepLinking'; import { setVoipPushToken } from './pushTokenAux'; +import { useCallStore } from './useCallStore'; // Store VoIP push data temporarily (iOS only - Android uses native storage) let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; @@ -141,7 +142,7 @@ const getInitialEventsAndroid = async (): Promise<boolean> => { const pendingCall = JSON.parse(pendingCallJson) as { notificationType: string; callId: string; - callUUID: string; + callUUID: string; // TODO: does it come from the native side? callerName: string; host: string; event: string; @@ -167,6 +168,8 @@ const getInitialEventsAndroid = async (): Promise<boolean> => { host: pendingCall.host }); + useCallStore.getState().setCallUUID(callUUID); + store.dispatch( voipCallOpen({ callId: pendingCall.callId, diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index 38eb606718d..95bf88bdb42 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -29,6 +29,7 @@ interface CallStoreState { } interface CallStoreActions { + setCallUUID: (callUUID: string) => void; setCall: (call: IClientMediaCall, callUUID: string) => void; updateFromCall: () => void; toggleMute: () => void; @@ -56,6 +57,10 @@ const initialState: CallStoreState = { export const useCallStore = create<CallStore>((set, get) => ({ ...initialState, + setCallUUID: (callUUID: string) => { + set({ callUUID }); + }, + setCall: (call: IClientMediaCall, callUUID: string) => { // Update state with call info set({ From cd74d436f26d6aa266a41ed6057a436fadb670eb Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Fri, 23 Jan 2026 11:13:46 -0300 Subject: [PATCH 32/61] remove callkeep from notification --- .../notification/VoipNotification.kt | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt index 2dd9eb30688..fd65ef0dd70 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt @@ -14,7 +14,6 @@ import android.os.Bundle import android.util.Log import androidx.core.app.NotificationCompat import chat.rocket.reactnative.MainActivity -import io.wazo.callkeep.RNCallKeepModule /** * Handles VoIP call notifications using Android's Telecom framework via CallKeep. @@ -35,23 +34,6 @@ class VoipNotification(private val context: Context) { const val ACTION_ACCEPT = "chat.rocket.reactnative.ACTION_VOIP_ACCEPT" const val ACTION_DECLINE = "chat.rocket.reactnative.ACTION_VOIP_DECLINE" - /** - * Cancels a VoIP call by ending it through CallKeep. - */ - @JvmStatic - fun endCall(callUUID: String) { - try { - val instance = RNCallKeepModule.instance - if (instance != null) { - instance.endCall(callUUID) - Log.d(TAG, "VoIP call ended via CallKeep with UUID: $callUUID") - } else { - Log.w(TAG, "Cannot end call: RNCallKeepModule instance not available") - } - } catch (e: Exception) { - Log.e(TAG, "Failed to end VoIP call", e) - } - } /** * Static method to retrieve stored call data from any context. @@ -177,20 +159,6 @@ class VoipNotification(private val context: Context) { // Store call data for when the user answers storeCallData(callId, callUUID, callerName, ejson.host, bundle.getString("ejson", "{}")) - // Try to display incoming call through CallKeep's telecom integration - val callKeepInstance = RNCallKeepModule.instance - if (callKeepInstance != null) { - try { - callKeepInstance.displayIncomingCall(callUUID, callerName, callerName, false) - Log.d(TAG, "VoIP call displayed via CallKeep with UUID: $callUUID") - return - } catch (e: Exception) { - Log.e(TAG, "Failed to display incoming call via CallKeep", e) - } - } else { - Log.d(TAG, "RNCallKeepModule instance not available, using fallback notification") - } - // Fallback to showing a high-priority notification showFallbackNotification(bundle, ejson, callUUID, callerName) } @@ -332,9 +300,6 @@ class VoipNotification(private val context: Context) { fun cancelCall(callId: String) { val callUUID = CallIdUUID.generateUUIDv5(callId) - // End call via CallKeep if available - endCall(callUUID) - // Cancel fallback notification if shown val notificationId = callUUID.replace("-", "").hashCode() cancelById(context, notificationId) From 9b71cf947509dbe90f5314951c57e6547315fbc7 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 27 Jan 2026 10:15:13 -0300 Subject: [PATCH 33/61] Android Incoming Call UI POC --- android/app/src/main/AndroidManifest.xml | 21 +- .../notification/NotificationIntentHandler.kt | 37 +-- .../RCFirebaseMessagingService.kt | 4 +- .../reactnative/notification/VoipModule.kt | 104 ++++++ .../notification/VoipNotification.kt | 296 ++++++++++-------- .../reactnative/notification/VoipPayload.kt | 32 -- .../reactnative/voip/IncomingCallActivity.kt | 191 +++++++++++ .../reactnative/voip/VoipForegroundService.kt | 117 +++++++ .../res/layout/activity_incoming_call.xml | 73 +++++ .../main/res/values/styles_incoming_call.xml | 12 + app/index.tsx | 6 +- app/lib/native/NativeVoipAndroid.ts | 2 +- app/lib/notifications/push.ts | 2 +- app/lib/services/voip/MediaSessionInstance.ts | 14 +- app/lib/services/voip/getInitialEvents.ts | 59 +++- app/lib/services/voip/useCallStore.ts | 4 +- app/sagas/login.js | 49 +-- index.js | 33 +- 18 files changed, 795 insertions(+), 261 deletions(-) create mode 100644 android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt create mode 100644 android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt create mode 100644 android/app/src/main/res/layout/activity_incoming_call.xml create mode 100644 android/app/src/main/res/values/styles_incoming_call.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index acb0a58bde9..2a4643d0d36 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -15,12 +15,13 @@ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" /> + <uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> - <!-- <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" /> --> - <!-- <uses-permission android:name="android.permission.CALL_PHONE" /> --> + <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> + <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" /> <uses-feature android:name="android.hardware.audio.output" /> <uses-feature android:name="android.hardware.microphone" /> @@ -116,6 +117,22 @@ android:name="com.bugsnag.android.API_KEY" android:value="${BugsnagAPIKey}" /> + <activity + android:name="chat.rocket.reactnative.voip.IncomingCallActivity" + android:exported="false" + android:launchMode="singleInstance" + android:showOnLockScreen="true" + android:turnScreenOn="true" + android:showWhenLocked="true" + android:theme="@style/Theme.IncomingCall" + android:excludeFromRecents="true" + android:taskAffinity="chat.rocket.reactnative.voip" /> + + <service + android:name="chat.rocket.reactnative.voip.VoipForegroundService" + android:exported="false" + android:foregroundServiceType="phoneCall" /> + <service android:name="io.wazo.callkeep.VoiceConnectionService" android:label="Wazo" android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index 1a4d22f5dbb..e396bb90aee 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -47,45 +47,20 @@ class NotificationIntentHandler { val notificationId = intent.getIntExtra("notificationId", 0) val event = intent.getStringExtra("event") ?: return true - val callId = intent.getStringExtra("callId") ?: "" val callUUID = intent.getStringExtra("callUUID") ?: "" val callerName = intent.getStringExtra("callerName") ?: "" val host = intent.getStringExtra("host") ?: "" - val ejson = intent.getStringExtra("ejson") ?: "{}" Log.d(TAG, "Handling VoIP intent - event: $event, callId: $callId, callUUID: $callUUID") - // Cancel the notification if it was shown as fallback - if (notificationId != 0) { - VoipNotification.cancelById(context, notificationId) - } + VoipNotification.cancelById(context, notificationId) + VoipModule.storePendingVoipCall(context, callId, callUUID, callerName, host, event) - // Store action for JS to pick up - val data = mapOf( - "notificationType" to "voip", - "event" to event, - "callId" to callId, - "callUUID" to callUUID, - "callerName" to callerName, - "host" to host, - "ejson" to ejson - ) - - val gson = GsonBuilder().create() - val jsonData = gson.toJson(data) - - // Store in VoIP-specific SharedPreferences for JS to retrieve - context.getSharedPreferences("VoipCallData", Context.MODE_PRIVATE) - .edit() - .putString("pendingAction", jsonData) - .putString("callId", callId) - .putString("callUUID", callUUID) - .putString("callerName", callerName) - .putString("host", host) - .putString("event", event) - .putLong("timestamp", System.currentTimeMillis()) - .apply() + // Emit event to JS if app is running + if (event == "accept") { + VoipModule.emitCallAnswered(callUUID) + } // Clear the voip flag to prevent re-processing intent.removeExtra("voipAction") diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt index 5216a667f43..6513fdc20a8 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt @@ -40,9 +40,9 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { if (voipPayload != null && voipPayload.isVoipIncomingCall()) { Log.d(TAG, "Detected new VoIP payload format, routing to VoipNotification handler") try { - val ejson = voipPayload.toEjson() val voipNotification = VoipNotification(this) - voipNotification.showIncomingCall(bundle, ejson) + // TODO: no need for bundle, just use voipPayload + voipNotification.showIncomingCall(bundle, voipPayload) } catch (e: Exception) { Log.e(TAG, "Error processing VoIP notification", e) } diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt index 925fb81ef17..6eb6c4fd502 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt @@ -19,6 +19,9 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo private const val TAG = "RocketChat.VoipModule" private const val PREFS_NAME = "VoipCallData" private const val EVENT_VOIP_CALL = "VoipCallAction" + private const val EVENT_CALL_ANSWERED = "VoipCallAnswered" + private const val EVENT_CALL_DECLINED = "VoipCallDeclined" + private const val EVENT_INCOMING_CALL = "VoipIncomingCall" private var reactContextRef: WeakReference<ReactApplicationContext>? = null @@ -49,6 +52,106 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo } } + /** + * Emits an incoming call event to JavaScript. + */ + // @JvmStatic + // fun emitIncomingCall(callId: String, callUUID: String, callerName: String, host: String?) { + // try { + // val data = mapOf( + // "callId" to callId, + // "callUUID" to callUUID, + // "callerName" to callerName, + // "host" to (host ?: "") + // ) + // val gson = GsonBuilder().create() + // val jsonData = gson.toJson(data) + + // reactContextRef?.get()?.let { context -> + // if (context.hasActiveReactInstance()) { + // context + // .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) + // .emit(EVENT_INCOMING_CALL, jsonData) + // Log.d(TAG, "Emitted incoming call event to JS: $callUUID") + // } + // } + // } catch (e: Exception) { + // Log.e(TAG, "Failed to emit incoming call event", e) + // } + // } + + /** + * Emits a call answered event to JavaScript. + */ + @JvmStatic + fun emitCallAnswered(callUUID: String) { + try { + reactContextRef?.get()?.let { context -> + if (context.hasActiveReactInstance()) { + context + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) + .emit(EVENT_CALL_ANSWERED, callUUID) + Log.d(TAG, "Emitted call answered event to JS: $callUUID") + } + } + } catch (e: Exception) { + Log.e(TAG, "Failed to emit call answered event", e) + } + } + + /** + * Emits a call declined event to JavaScript. + */ + @JvmStatic + fun emitCallDeclined(callUUID: String) { + try { + reactContextRef?.get()?.let { context -> + if (context.hasActiveReactInstance()) { + context + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) + .emit(EVENT_CALL_DECLINED, callUUID) + Log.d(TAG, "Emitted call declined event to JS: $callUUID") + } + } + } catch (e: Exception) { + Log.e(TAG, "Failed to emit call declined event", e) + } + } + + /** + * Clears pending VoIP call data from SharedPreferences. + * Internal method that can be called from any context. + */ + @JvmStatic + internal fun clearPendingVoipCall(context: Context) { + try { + context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + .edit() + .clear() + .apply() + Log.d(TAG, "Cleared pending VoIP call data") + } catch (e: Exception) { + Log.e(TAG, "Error clearing pending VoIP call", e) + } + } + + /** + * Cancels an incoming call notification and activity. + */ + // @JvmStatic + // fun cancelIncomingCall(callUUID: String) { + // try { + // val notificationId = callUUID.replace("-", "").hashCode() + // reactContextRef?.get()?.let { context -> + // VoipNotification.cancelById(context, notificationId) + // clearPendingVoipCall(context) + // Log.d(TAG, "Cancelled incoming call: $callUUID") + // } + // } catch (e: Exception) { + // Log.e(TAG, "Failed to cancel incoming call", e) + // } + // } + /** * Stores VoIP call data for JS to retrieve. * Also emits an event if the app is running. @@ -98,6 +201,7 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo @ReactMethod override fun getPendingVoipCall(promise: Promise) { try { + Log.d(TAG, "getPendingVoipCall") val prefs = reactApplicationContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) // Check if data is stale (older than 5 minutes) diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt index fd65ef0dd70..c6fc13d933e 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt @@ -4,6 +4,7 @@ import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent +import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.graphics.Bitmap @@ -13,7 +14,14 @@ import android.os.Build import android.os.Bundle import android.util.Log import androidx.core.app.NotificationCompat +import android.content.ComponentName +import android.net.Uri +import android.telecom.PhoneAccount +import android.telecom.PhoneAccountHandle +import android.telecom.TelecomManager import chat.rocket.reactnative.MainActivity +import chat.rocket.reactnative.voip.IncomingCallActivity +import chat.rocket.reactnative.voip.VoipForegroundService /** * Handles VoIP call notifications using Android's Telecom framework via CallKeep. @@ -34,51 +42,15 @@ class VoipNotification(private val context: Context) { const val ACTION_ACCEPT = "chat.rocket.reactnative.ACTION_VOIP_ACCEPT" const val ACTION_DECLINE = "chat.rocket.reactnative.ACTION_VOIP_DECLINE" - - /** - * Static method to retrieve stored call data from any context. - */ - @JvmStatic - fun getStoredCallData(context: Context): Bundle? { - try { - val prefs = context.getSharedPreferences("VoipCallData", Context.MODE_PRIVATE) - val callId = prefs.getString("callId", null) ?: return null - val callUUID = prefs.getString("callUUID", null) ?: return null - - // Check if data is stale (older than 5 minutes) - val timestamp = prefs.getLong("timestamp", 0) - if (System.currentTimeMillis() - timestamp > 5 * 60 * 1000) { - Log.d(TAG, "Stored VoIP call data is stale, clearing") - clearStoredCallData(context) - return null - } - - return Bundle().apply { - putString("notificationType", "voip") - putString("callId", callId) - putString("callUUID", callUUID) - putString("callerName", prefs.getString("callerName", "Unknown")) - putString("host", prefs.getString("host", "")) - putString("ejson", prefs.getString("ejson", "{}")) - } - } catch (e: Exception) { - Log.e(TAG, "Failed to retrieve stored VoIP call data", e) - return null - } - } + // react-native-callkeep's ConnectionService class name + private const val CALLKEEP_CONNECTION_SERVICE_CLASS = "io.wazo.callkeep.VoiceConnectionService" /** * Static method to clear stored call data from any context. */ @JvmStatic fun clearStoredCallData(context: Context) { - try { - val prefs = context.getSharedPreferences("VoipCallData", Context.MODE_PRIVATE) - prefs.edit().clear().apply() - Log.d(TAG, "Cleared stored VoIP call data") - } catch (e: Exception) { - Log.e(TAG, "Failed to clear stored VoIP call data", e) - } + VoipModule.clearPendingVoipCall(context) } /** @@ -90,6 +62,27 @@ class VoipNotification(private val context: Context) { manager?.cancel(notificationId) Log.d(TAG, "VoIP notification cancelled with ID: $notificationId") } + + /** + * Handles decline action for VoIP call. + * Logs the decline action and clears stored call data. + */ + @JvmStatic + fun handleDeclineAction(context: Context, callUUID: String?) { + Log.d(TAG, "Decline action triggered for callUUID: $callUUID") + // Clear stored call data + VoipModule.clearPendingVoipCall(context) + } + } + + /** + * BroadcastReceiver to handle decline actions from notification. + */ + class DeclineReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val callUUID = intent.getStringExtra("callUUID") + VoipNotification.handleDeclineAction(context, callUUID) + } } private val notificationManager: NotificationManager? = @@ -128,145 +121,196 @@ class VoipNotification(private val context: Context) { } /** - * Displays an incoming VoIP call using CallKeep's telecom integration. - * Falls back to a notification if CallKeep is not available. + * Displays an incoming VoIP call using full-screen intent for locked devices + * and heads-up notification for unlocked devices. * * @param bundle The notification data bundle - * @param ejson The parsed notification payload + * @param voipPayload The VoIP payload containing call information */ - fun showIncomingCall(bundle: Bundle, ejson: Ejson) { - val callId = ejson.callId + fun showIncomingCall(bundle: Bundle, voipPayload: VoipPayload) { + val callId = voipPayload.callId if (callId.isNullOrEmpty()) { Log.w(TAG, "Cannot show VoIP call: callId is missing") return } - // Get caller information - val callerName: String = when { - !ejson.senderName.isNullOrEmpty() -> ejson.senderName - ejson.caller?.name != null -> ejson.caller.name - ejson.caller?.username != null -> ejson.caller.username - ejson.sender?.name != null -> ejson.sender.name - ejson.sender?.username != null -> ejson.sender.username - else -> "Unknown" - } + // Get caller information - simplified since VoipPayload has caller as a string + val callerName = voipPayload.caller ?: "Unknown" - // Generate deterministic UUID from callId (matching iOS implementation) + // TODO: remove this when it comes from the server val callUUID = CallIdUUID.generateUUIDv5(callId) Log.d(TAG, "Showing incoming VoIP call - callId: $callId, callUUID: $callUUID, caller: $callerName") - // Store call data for when the user answers - storeCallData(callId, callUUID, callerName, ejson.host, bundle.getString("ejson", "{}")) + // CRITICAL: Register call with TelecomManager FIRST (required for audio focus, Bluetooth, priority, FSI exemption) + // This triggers react-native-callkeep's ConnectionService + registerCallWithTelecomManager(callUUID, callerName) - // Fallback to showing a high-priority notification - showFallbackNotification(bundle, ejson, callUUID, callerName) + // Start foreground service for Android 14/15 reliability + VoipForegroundService.start(context, callUUID, callerName) + + // Show notification with full-screen intent + showIncomingCallNotification(bundle, voipPayload, callUUID, callerName) } /** - * Stores call data in SharedPreferences for retrieval when the call is answered. - * This is needed because CallKeep's answer callback only provides the UUID, - * not the full call data. + * Registers the incoming call with TelecomManager using react-native-callkeep's ConnectionService. + * This is REQUIRED for: + * 1. Audio focus (pauses media apps) + * 2. Bluetooth headset support + * 3. Higher process priority + * 4. FSI exemption on Play Store */ - private fun storeCallData(callId: String, callUUID: String, callerName: String, host: String?, ejsonStr: String) { + private fun registerCallWithTelecomManager(callUUID: String, callerName: String) { try { - val prefs = context.getSharedPreferences("VoipCallData", Context.MODE_PRIVATE) - prefs.edit().apply { - putString("callId", callId) + // Validate inputs + if (callUUID.isNullOrEmpty()) { + Log.e(TAG, "Cannot register call with TelecomManager: callUUID is null or empty") + return + } + + val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as? TelecomManager + ?: run { + Log.w(TAG, "TelecomManager not available") + return + } + + // Get react-native-callkeep's PhoneAccountHandle + val componentName = ComponentName(context.packageName, CALLKEEP_CONNECTION_SERVICE_CLASS) + // react-native-callkeep typically uses the app package name as the account ID + val phoneAccountHandle = PhoneAccountHandle(componentName, context.packageName) + + // Check if PhoneAccount is registered + val phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle) + if (phoneAccount == null) { + Log.w(TAG, "PhoneAccount not registered by react-native-callkeep yet. Call may not have full OS integration.") + return + } + + // Create extras for the incoming call + // react-native-callkeep's VoiceConnectionService expects EXTRA_CALL_UUID constant + // which is defined as "EXTRA_CALL_UUID" (not "callUUID") + val extras = Bundle().apply { + val callerUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, callerName, null) + putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, callerUri) + // react-native-callkeep Constants.EXTRA_CALL_UUID = "EXTRA_CALL_UUID" + putString("EXTRA_CALL_UUID", callUUID) + // Also include EXTRA_CALLER_NAME for compatibility + putString("EXTRA_CALLER_NAME", callerName) + // Legacy keys for backward compatibility putString("callUUID", callUUID) - putString("callerName", callerName) - putString("host", host ?: "") - putString("ejson", ejsonStr) - putLong("timestamp", System.currentTimeMillis()) - apply() + putString("name", callerName) + putString("handle", callerName) } - Log.d(TAG, "Stored VoIP call data for callUUID: $callUUID") + + Log.d(TAG, "Registering call with TelecomManager - callUUID: $callUUID, callerName: $callerName, extras keys: ${extras.keySet()}") + + // Register the incoming call with the OS + telecomManager.addNewIncomingCall(phoneAccountHandle, extras) + Log.d(TAG, "Successfully registered incoming call with TelecomManager: $callUUID") + } catch (e: SecurityException) { + Log.e(TAG, "SecurityException registering call with TelecomManager. MANAGE_OWN_CALLS permission may be missing.", e) } catch (e: Exception) { - Log.e(TAG, "Failed to store VoIP call data", e) + Log.e(TAG, "Failed to register call with TelecomManager", e) } } /** - * Fallback notification when CallKeep is not available (app killed). - * Shows a high-priority notification similar to VideoConfNotification. + * Shows incoming call notification with full-screen intent for locked devices + * and heads-up notification for unlocked devices. + * Falls back to HUN only if full-screen intent permission is not granted (Android 14+). */ - private fun showFallbackNotification(bundle: Bundle, ejson: Ejson, callUUID: String, callerName: String) { - val callId = ejson.callId ?: "" - - // Generate notification ID from callUUID - val notificationId = callUUID.replace("-", "").hashCode() - - Log.d(TAG, "Showing fallback notification for VoIP call from: $callerName") - - // Create intent data for actions - val intentData = Bundle().apply { - putString("notificationType", "voip") - putString("callId", callId) - putString("callUUID", callUUID) - putString("callerName", callerName) - putString("host", ejson.host ?: "") - putString("ejson", bundle.getString("ejson", "{}")) - putInt("notificationId", notificationId) + private fun showIncomingCallNotification(bundle: Bundle, voipPayload: VoipPayload, callUUID: String, callerName: String) { + val callId = voipPayload.callId ?: "" + val notificationId = callId.hashCode() + + Log.d(TAG, "Showing incoming call notification for VoIP call from: $callerName") + + // Check if we can use full-screen intent (Android 14+) + val canUseFullScreen = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + notificationManager?.canUseFullScreenIntent() ?: false + } else { + true // Always available on Android 13 and below } - // Full screen intent - opens app when notification is tapped - val fullScreenIntent = Intent(context, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - putExtras(intentData) - putExtra("event", "default") + // Create full-screen intent to IncomingCallActivity + val fullScreenIntent = Intent(context, IncomingCallActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK + putExtra("callId", callId) + putExtra("callUUID", callUUID) + putExtra("callerName", callerName) + putExtra("host", voipPayload.host ?: "") } val fullScreenPendingIntent = createPendingIntent(notificationId, fullScreenIntent) - // Accept action + // Create Accept action val acceptIntent = Intent(context, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - putExtras(intentData) - putExtra("event", "accept") + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP putExtra("voipAction", true) - action = "${ACTION_ACCEPT}_$notificationId" + putExtra("event", "accept") + putExtra("callId", callId) + putExtra("callUUID", callUUID) + putExtra("callerName", callerName) + putExtra("host", voipPayload.host ?: "") + putExtra("notificationId", notificationId) } - val acceptPendingIntent = createPendingIntent(notificationId + 1, acceptIntent) + val acceptPendingIntent = createPendingIntent(notificationId + 1, acceptIntent) - // Decline action - val declineIntent = Intent(context, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - putExtras(intentData) - putExtra("event", "decline") - putExtra("voipAction", true) - action = "${ACTION_DECLINE}_$notificationId" + // Create Decline action + val declineIntent = Intent(context, DeclineReceiver::class.java).apply { + action = ACTION_DECLINE + putExtra("callUUID", callUUID) + putExtra("host", voipPayload.host ?: "") + } + val declinePendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + PendingIntent.getBroadcast( + context, + notificationId + 2, + declineIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + } else { + PendingIntent.getBroadcast( + context, + notificationId + 2, + declineIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ) } - val declinePendingIntent = createPendingIntent(notificationId + 2, declineIntent) // Get icons val packageName = context.packageName val smallIconResId = context.resources.getIdentifier("ic_notification", "drawable", packageName) - // Fetch caller avatar - val avatarUri = ejson.getCallerAvatarUri() - val avatarBitmap: Bitmap? = if (avatarUri != null) { - NotificationHelper.fetchAvatarBitmap(context, avatarUri, null) - } else { - null - } + // Avatar not available in VoipPayload format (would require caller username) + val avatarBitmap: Bitmap? = null // Build notification val builder = NotificationCompat.Builder(context, CHANNEL_ID).apply { setSmallIcon(smallIconResId) setContentTitle("Incoming call") setContentText("Call from $callerName") - priority = NotificationCompat.PRIORITY_HIGH + priority = NotificationCompat.PRIORITY_MAX setCategory(NotificationCompat.CATEGORY_CALL) setVisibility(NotificationCompat.VISIBILITY_PUBLIC) setAutoCancel(false) setOngoing(true) - setFullScreenIntent(fullScreenPendingIntent, true) - setContentIntent(fullScreenPendingIntent) addAction(0, "Decline", declinePendingIntent) addAction(0, "Accept", acceptPendingIntent) if (avatarBitmap != null) { setLargeIcon(avatarBitmap) } + + // Set full-screen intent only if permission is granted + if (canUseFullScreen) { + setFullScreenIntent(fullScreenPendingIntent, true) + Log.d(TAG, "Full-screen intent enabled - locked device will show Activity, unlocked will show HUN") + } else { + Log.w(TAG, "Full-screen intent permission not granted - showing HUN only (fallback)") + // Still set content intent so tapping notification opens the activity + setContentIntent(fullScreenPendingIntent) + } } // Set sound for pre-O devices @@ -277,7 +321,7 @@ class VoipNotification(private val context: Context) { // Show notification notificationManager?.notify(notificationId, builder.build()) - Log.d(TAG, "VoIP fallback notification displayed with ID: $notificationId") + Log.d(TAG, "VoIP notification displayed with ID: $notificationId") } /** @@ -298,13 +342,9 @@ class VoipNotification(private val context: Context) { * @param callId The call ID */ fun cancelCall(callId: String) { - val callUUID = CallIdUUID.generateUUIDv5(callId) - - // Cancel fallback notification if shown - val notificationId = callUUID.replace("-", "").hashCode() + val notificationId = callId.hashCode() cancelById(context, notificationId) - - // Clear stored data - clearStoredCallData(context) + VoipForegroundService.stop(context) + VoipModule.clearPendingVoipCall(context) } } diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt index f12141ec5c3..8f6db041f88 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt @@ -18,38 +18,6 @@ data class VoipPayload( @SerializedName("type") val type: String? ) { - /** - * Converts this VoipPayload to an Ejson object for compatibility with existing VoipNotification code. - * - * Since VoipNotification.showIncomingCall() expects an Ejson object, we create a minimal - * Ejson instance with the necessary fields populated from this payload. - */ - fun toEjson(): Ejson { - val ejson = Ejson() - - // Map direct fields - ejson.callId = this.callId - ejson.host = this.host - ejson.notificationType = "incoming_call" - - // Convert caller string to Caller object - // The caller field is a string in the new format, but Ejson expects a Caller object - if (!this.caller.isNullOrEmpty()) { - val callerObj = Ejson.Caller() - // Since we only have the caller name as a string, we'll use it as both name and username - // This is a limitation - we don't have username in the new format - callerObj.name = this.caller - callerObj.username = this.caller // Use name as username fallback - ejson.caller = callerObj - } - - // Set senderName for compatibility with VoipNotification.showIncomingCall() - // which checks senderName first when determining caller name - ejson.senderName = this.caller - - return ejson - } - /** * Checks if this payload represents a VoIP incoming call. */ diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt new file mode 100644 index 00000000000..e78b1ed4a97 --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt @@ -0,0 +1,191 @@ +package chat.rocket.reactnative.voip + +import android.app.Activity +import android.app.KeyguardManager +import android.content.Context +import android.content.Intent +import android.media.Ringtone +import android.media.RingtoneManager +import android.os.Build +import android.os.Bundle +import android.view.WindowManager +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.TextView +import android.util.Log +import androidx.core.content.ContextCompat +import chat.rocket.reactnative.MainActivity +import chat.rocket.reactnative.R +import chat.rocket.reactnative.notification.VoipNotification +import chat.rocket.reactnative.notification.VoipModule + +/** + * Full-screen Activity displayed when an incoming VoIP call arrives. + * Shows on lock screen and handles user actions (Accept/Decline). + */ +class IncomingCallActivity : Activity() { + + companion object { + private const val TAG = "RocketChat.IncomingCall" + private const val EXTRA_CALL_ID = "callId" + private const val EXTRA_CALL_UUID = "callUUID" + private const val EXTRA_CALLER_NAME = "callerName" + private const val EXTRA_HOST = "host" + } + + private var ringtone: Ringtone? = null + private var callUUID: String? = null + private var callId: String? = null + private var callerName: String? = null + private var host: String? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + // Samsung/Xiaomi fix: Request keyguard dismissal BEFORE setting content view + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager + keyguardManager.requestDismissKeyguard(this, null) + } + + // Android 14+ fix: Must call programmatically (XML attributes ignored) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + setShowWhenLocked(true) + setTurnScreenOn(true) + } + + // Enable showing on lock screen (for older Android versions) + window.addFlags( + WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or + WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD + ) + + setContentView(R.layout.activity_incoming_call) + + // Get call data from intent + callId = intent.getStringExtra(EXTRA_CALL_ID) + callUUID = intent.getStringExtra(EXTRA_CALL_UUID) + callerName = intent.getStringExtra(EXTRA_CALLER_NAME) ?: "Unknown" + host = intent.getStringExtra(EXTRA_HOST) + + Log.d(TAG, "IncomingCallActivity created - callUUID: $callUUID, caller: $callerName") + + // Update UI + updateUI() + + // Start ringtone + startRingtone() + + // Setup button listeners + setupButtons() + } + + private fun updateUI() { + val callerNameView = findViewById<TextView>(R.id.caller_name) + callerNameView?.text = callerName ?: "Unknown" + + // Try to load avatar if available + // TODO: needs username to load avatar + val avatarView = findViewById<ImageView>(R.id.caller_avatar) + // Avatar loading would require additional data - can be enhanced later + // For now, just show a placeholder or default icon + } + + private fun startRingtone() { + try { + val ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE) + ringtone = RingtoneManager.getRingtone(applicationContext, ringtoneUri) + ringtone?.play() + Log.d(TAG, "Ringtone started") + } catch (e: Exception) { + Log.e(TAG, "Failed to start ringtone", e) + } + } + + private fun stopRingtone() { + try { + ringtone?.stop() + ringtone = null + Log.d(TAG, "Ringtone stopped") + } catch (e: Exception) { + Log.e(TAG, "Failed to stop ringtone", e) + } + } + + private fun setupButtons() { + val acceptButton = findViewById<ImageButton>(R.id.btn_accept) + val declineButton = findViewById<ImageButton>(R.id.btn_decline) + + acceptButton?.setOnClickListener { + handleAccept() + } + + declineButton?.setOnClickListener { + handleDecline() + } + } + + private fun handleAccept() { + Log.d(TAG, "Call accepted - callUUID: $callUUID") + stopRingtone() + + // Cancel notification + callUUID?.let { uuid -> + val notificationId = uuid.replace("-", "").hashCode() + VoipNotification.cancelById(this, notificationId) + } + + // Store pending call data before emitting event (fixes race condition) + // if (callUUID != null && callId != null && callerName != null && host != null) { + // VoipModule.storePendingVoipCall(this, callId, callUUID, callerName, host, "accept") + // } + + // Launch MainActivity with call data + val launchIntent = Intent(this, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP + putExtra("voipAction", true) + putExtra("event", "accept") + putExtra("callId", callId) + putExtra("callUUID", callUUID) + putExtra("callerName", callerName) + putExtra("host", host) + } + startActivity(launchIntent) + + finish() + } + + private fun handleDecline() { + Log.d(TAG, "Call declined - callUUID: $callUUID") + stopRingtone() + + // Cancel notification + callUUID?.let { uuid -> + val notificationId = uuid.replace("-", "").hashCode() + VoipNotification.cancelById(this, notificationId) + } + + // Emit event to JS + // TODO: call restapi to decline the call + callUUID?.let { uuid -> + VoipModule.emitCallDeclined(uuid) + } + + // Clear stored call data + VoipModule.clearPendingVoipCall(this) + + finish() + } + + override fun onDestroy() { + super.onDestroy() + stopRingtone() + } + + override fun onBackPressed() { + // Treat back button as decline + handleDecline() + } +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt new file mode 100644 index 00000000000..ac5ab62da74 --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt @@ -0,0 +1,117 @@ +package chat.rocket.reactnative.voip + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.Service +import android.content.Context +import android.content.Intent +import android.content.pm.ServiceInfo +import android.os.Build +import android.os.IBinder +import android.util.Log +import androidx.core.app.NotificationCompat +import chat.rocket.reactnative.R +import chat.rocket.reactnative.notification.VoipNotification + +/** + * Foreground service for VoIP calls to ensure reliability on Android 14/15. + * Prevents the system from killing the call process when the app is in the background. + */ +class VoipForegroundService : Service() { + + companion object { + private const val TAG = "RocketChat.VoipService" + private const val NOTIFICATION_ID = 1001 + private const val CHANNEL_ID = "voip-foreground-service" + + /** + * Starts the foreground service for an incoming call. + */ + @JvmStatic + fun start(context: Context, callUUID: String, callerName: String) { + val intent = Intent(context, VoipForegroundService::class.java).apply { + putExtra("callUUID", callUUID) + putExtra("callerName", callerName) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(intent) + } else { + context.startService(intent) + } + } + + /** + * Stops the foreground service. + */ + @JvmStatic + fun stop(context: Context) { + val intent = Intent(context, VoipForegroundService::class.java) + context.stopService(intent) + } + } + + override fun onCreate() { + super.onCreate() + createNotificationChannel() + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + val callUUID = intent?.getStringExtra("callUUID") ?: return START_NOT_STICKY + val callerName = intent.getStringExtra("callerName") ?: "Incoming call" + + Log.d(TAG, "Starting foreground service for call: $callUUID") + + // Create notification for foreground service + val notification = createNotification(callerName) + + // Start foreground service with PHONE_CALL type (Android 14+) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL) + } else { + startForeground(NOTIFICATION_ID, notification) + } + + return START_NOT_STICKY + } + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + override fun onDestroy() { + super.onDestroy() + Log.d(TAG, "Foreground service destroyed") + } + + private fun createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel( + CHANNEL_ID, + "VoIP Call Service", + NotificationManager.IMPORTANCE_LOW + ).apply { + description = "Ongoing VoIP call service" + setShowBadge(false) + } + + val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.createNotificationChannel(channel) + } + } + + private fun createNotification(callerName: String): Notification { + val packageName = packageName + val smallIconResId = resources.getIdentifier("ic_notification", "drawable", packageName) + + return NotificationCompat.Builder(this, CHANNEL_ID) + .setContentTitle("Ongoing call") + .setContentText("Call with $callerName") + .setSmallIcon(smallIconResId) + .setOngoing(true) + .setPriority(NotificationCompat.PRIORITY_LOW) + .setCategory(NotificationCompat.CATEGORY_CALL) + .build() + } +} diff --git a/android/app/src/main/res/layout/activity_incoming_call.xml b/android/app/src/main/res/layout/activity_incoming_call.xml new file mode 100644 index 00000000000..d025d991c16 --- /dev/null +++ b/android/app/src/main/res/layout/activity_incoming_call.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:gravity="center" + android:background="#000000" + android:padding="32dp"> + + <!-- Caller Avatar --> + <ImageView + android:id="@+id/caller_avatar" + android:layout_width="120dp" + android:layout_height="120dp" + android:layout_marginBottom="24dp" + android:src="@mipmap/ic_launcher" + android:contentDescription="Caller avatar" + android:scaleType="centerCrop" + android:background="@android:drawable/dialog_holo_light_frame" /> + + <!-- Caller Name --> + <TextView + android:id="@+id/caller_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:text="Unknown" + android:textColor="#FFFFFF" + android:textSize="28sp" + android:textStyle="bold" /> + + <!-- Incoming Call Label --> + <TextView + android:id="@+id/incoming_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="48dp" + android:text="Incoming call" + android:textColor="#CCCCCC" + android:textSize="16sp" /> + + <!-- Action Buttons --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="center" + android:layout_marginTop="32dp"> + + <!-- Decline Button --> + <ImageButton + android:id="@+id/btn_decline" + android:layout_width="80dp" + android:layout_height="80dp" + android:layout_marginEnd="32dp" + android:background="@android:drawable/ic_menu_close_clear_cancel" + android:backgroundTint="#F44336" + android:contentDescription="Decline call" + android:scaleType="centerInside" /> + + <!-- Accept Button --> + <ImageButton + android:id="@+id/btn_accept" + android:layout_width="80dp" + android:layout_height="80dp" + android:background="@android:drawable/ic_menu_call" + android:backgroundTint="#4CAF50" + android:contentDescription="Accept call" + android:scaleType="centerInside" /> + + </LinearLayout> + +</LinearLayout> diff --git a/android/app/src/main/res/values/styles_incoming_call.xml b/android/app/src/main/res/values/styles_incoming_call.xml new file mode 100644 index 00000000000..a5a7484c14d --- /dev/null +++ b/android/app/src/main/res/values/styles_incoming_call.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <style name="Theme.IncomingCall" parent="Theme.AppCompat.DayNight.NoActionBar"> + <item name="android:windowNoTitle">true</item> + <item name="android:windowFullscreen">true</item> + <item name="android:windowIsTranslucent">false</item> + <item name="android:windowBackground">@android:color/black</item> + <item name="android:windowDisablePreview">true</item> + <item name="android:statusBarColor">@android:color/transparent</item> + <item name="android:navigationBarColor">@android:color/transparent</item> + </style> +</resources> diff --git a/app/index.tsx b/app/index.tsx index ef40551600e..4c412c4bf1b 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -33,7 +33,7 @@ import { } from './lib/methods/helpers/theme'; import { initializePushNotifications, onNotification } from './lib/notifications'; import { getInitialNotification, setupVideoConfActionListener } from './lib/notifications/videoConf/getInitialNotification'; -import { getInitialEvents } from './lib/services/voip/getInitialEvents'; +import { getInitialEvents, setupVoipEventListeners } from './lib/services/voip/getInitialEvents'; import store from './lib/store'; import { initStore } from './lib/store/auxStore'; import { type TSupportedThemes, ThemeContext } from './theme'; @@ -87,6 +87,7 @@ export default class Root extends React.Component<{}, IState> { private listenerTimeout!: any; private dimensionsListener?: EmitterSubscription; private videoConfActionCleanup?: () => void; + private voipEventCleanup?: () => void; constructor(props: any) { super(props); @@ -121,12 +122,15 @@ export default class Root extends React.Component<{}, IState> { // Set up video conf action listener for background accept/decline this.videoConfActionCleanup = setupVideoConfActionListener(); + // Set up VoIP event listeners for Android native call UI + this.voipEventCleanup = setupVoipEventListeners(); } componentWillUnmount() { clearTimeout(this.listenerTimeout); this.dimensionsListener?.remove?.(); this.videoConfActionCleanup?.(); + this.voipEventCleanup?.(); unsubscribeTheme(); } diff --git a/app/lib/native/NativeVoipAndroid.ts b/app/lib/native/NativeVoipAndroid.ts index 95395d7a405..a5915bb70a5 100644 --- a/app/lib/native/NativeVoipAndroid.ts +++ b/app/lib/native/NativeVoipAndroid.ts @@ -6,4 +6,4 @@ export interface Spec extends TurboModule { clearPendingVoipCall(): void; } -export default TurboModuleRegistry.get<Spec>('VoipModule'); +export default TurboModuleRegistry.getEnforcing<Spec>('VoipModule'); diff --git a/app/lib/notifications/push.ts b/app/lib/notifications/push.ts index b5c2a37afd6..dc6858b25c2 100644 --- a/app/lib/notifications/push.ts +++ b/app/lib/notifications/push.ts @@ -130,7 +130,7 @@ const setupNotificationCategories = async (): Promise<void> => { * Request notification permissions and register for push notifications */ const registerForPushNotifications = async (): Promise<string | null> => { - if (!Device.isDevice) { + if (!Device.isDevice && isIOS) { console.log('Push notifications require a physical device'); return null; } diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 3101df6a7dd..40388598c2a 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -72,15 +72,18 @@ class MediaSessionInstance { }); const existingCallUUID = useCallStore.getState().callUUID; + console.log('[VoIP][Android] Existing call UUID:', existingCallUUID); + // // TODO: need to answer the call here? if (existingCallUUID) { this.answerCall(existingCallUUID); return; } const callUUID = CallIdUUIDModule.toUUID(call.callId); + console.log('[VoIP][Android] New call UUID:', callUUID); - const displayName = call.contact.displayName || call.contact.username || 'Unknown'; - RNCallKeep.displayIncomingCall(callUUID, displayName, displayName, 'generic', false); + // const displayName = call.contact.displayName || call.contact.username || 'Unknown'; + // RNCallKeep.displayIncomingCall(callUUID, displayName, displayName, 'generic', false); call.emitter.on('ended', () => { RNCallKeep.endCall(callUUID); @@ -89,13 +92,16 @@ class MediaSessionInstance { }); } - private answerCall = async (callUUID: string) => { + public answerCall = async (callUUID: string) => { + console.log('[VoIP][Android] Answering call:', callUUID); const mainCall = this.instance?.getMainCall(); + console.log('[VoIP][Android] Main call:', mainCall); // Compare using deterministic UUID conversion if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { + console.log('[VoIP][Android] Accepting call:', callUUID); await mainCall.accept(); + console.log('[VoIP][Android] Setting current call active:', callUUID); RNCallKeep.setCurrentCallActive(callUUID); - // Set call in Zustand store and navigate to CallView useCallStore.getState().setCall(mainCall, callUUID); Navigation.navigate('CallView', { callUUID }); } else { diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index eb1a3110d01..a48c1de7cf2 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -1,5 +1,6 @@ import RNCallKeep from 'react-native-callkeep'; import VoipPushNotification from 'react-native-voip-push-notification'; +import { DeviceEventEmitter, Platform } from 'react-native'; import { isIOS } from '../../methods/helpers'; import CallIdUUIDModule from '../../native/NativeCallIdUUID'; @@ -8,6 +9,7 @@ import store from '../../store'; import { voipCallOpen } from '../../../actions/deepLinking'; import { setVoipPushToken } from './pushTokenAux'; import { useCallStore } from './useCallStore'; +import { mediaSessionInstance } from './MediaSessionInstance'; // Store VoIP push data temporarily (iOS only - Android uses native storage) let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; @@ -25,6 +27,46 @@ export const getInitialEvents = (): Promise<boolean> => { return getInitialEventsAndroid(); }; +/** + * Sets up listeners for Android VoIP call events from native side. + * @returns Cleanup function to remove listeners + */ +export const setupVoipEventListeners = (): (() => void) | undefined => { + if (Platform.OS !== 'android') { + return undefined; + } + + const subscriptions = [ + DeviceEventEmitter.addListener('VoipCallAction', async (dataJson: string) => { + try { + const data = JSON.parse(dataJson); + console.log('[VoIP][Android] Call action event:', data); + await NativeVoipModule.clearPendingVoipCall(); + + if (data.event === 'accept') { + useCallStore.getState().setCallUUID(data.callUUID); + // TODO: how to make sure the call comes from the same workspace? dispatch is just a saga trigger + store.dispatch( + voipCallOpen({ + callId: data.callId, + callUUID: data.callUUID, + host: data.host + }) + ); + await mediaSessionInstance.answerCall(data.callUUID); + } + } catch (error) { + console.error('[VoIP][Android] Error handling call action event:', error); + } + }) + ]; + + // Return cleanup function + return () => { + subscriptions.forEach(sub => sub.remove()); + }; +}; + /** * iOS-specific implementation using VoipPushNotification and CallKeep */ @@ -137,12 +179,14 @@ const getInitialEventsAndroid = async (): Promise<boolean> => { return false; } + await NativeVoipModule.clearPendingVoipCall(); + console.log('[VoIP][Android] Found pending VoIP call:', pendingCallJson); const pendingCall = JSON.parse(pendingCallJson) as { notificationType: string; callId: string; - callUUID: string; // TODO: does it come from the native side? + callUUID: string; callerName: string; host: string; event: string; @@ -159,21 +203,12 @@ const getInitialEventsAndroid = async (): Promise<boolean> => { return false; } - // Generate UUID if not provided - const callUUID = pendingCall.callUUID || CallIdUUIDModule.toUUID(pendingCall.callId); - - console.log('[VoIP][Android] Dispatching voipCallOpen:', { - callId: pendingCall.callId, - callUUID, - host: pendingCall.host - }); - - useCallStore.getState().setCallUUID(callUUID); + useCallStore.getState().setCallUUID(pendingCall.callUUID); store.dispatch( voipCallOpen({ callId: pendingCall.callId, - callUUID, + callUUID: pendingCall.callUUID, host: pendingCall.host }) ); diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index 95bf88bdb42..effa08ba00c 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -29,7 +29,7 @@ interface CallStoreState { } interface CallStoreActions { - setCallUUID: (callUUID: string) => void; + setCallUUID: (callUUID: string | null) => void; setCall: (call: IClientMediaCall, callUUID: string) => void; updateFromCall: () => void; toggleMute: () => void; @@ -57,7 +57,7 @@ const initialState: CallStoreState = { export const useCallStore = create<CallStore>((set, get) => ({ ...initialState, - setCallUUID: (callUUID: string) => { + setCallUUID: (callUUID: string | null) => { set({ callUUID }); }, diff --git a/app/sagas/login.js b/app/sagas/login.js index b252a5e4ff3..6e7737a854c 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -2,8 +2,6 @@ import React from 'react'; import { call, cancel, delay, fork, put, race, select, take, takeLatest } from 'redux-saga/effects'; import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import { Q } from '@nozbe/watermelondb'; -import RNCallKeep from 'react-native-callkeep'; -import { PermissionsAndroid } from 'react-native'; import dayjs from '../lib/dayjs'; import * as types from '../actions/actionsTypes'; @@ -43,7 +41,6 @@ import { showActionSheetRef } from '../containers/ActionSheet'; import { SupportedVersionsWarning } from '../containers/SupportedVersions'; import { mediaSessionInstance } from '../lib/services/voip/MediaSessionInstance'; import { hasPermission } from '../lib/methods/helpers/helpers'; -// import { simulateCall } from '../lib/services/voip/simulateCall'; const getServer = state => state.server.server; const loginWithPasswordCall = args => loginWithPassword(args); @@ -63,7 +60,7 @@ const showSupportedVersionsWarning = function* showSupportedVersionsWarning(serv const serversDB = database.servers; yield serversDB.write(async () => { - await serverRecord.update((r) => { + await serverRecord.update(r => { r.supportedVersionsWarningAt = new Date(); }); }); @@ -110,7 +107,7 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE } // this is updating on every login just to save `updated_at` // keeping this server as the most recent on autocomplete order - await serverHistoryRecord.update((s) => { + await serverHistoryRecord.update(s => { s.username = result.username; if (iconURL) { s.iconURL = iconURL; @@ -228,40 +225,6 @@ const fetchUsersRoles = function* fetchRoomsFork() { } }; -function* initCallKeep() { - try { - const options = { - ios: { - appName: 'Rocket.Chat', - includesCallsInRecents: false - }, - android: { - alertTitle: 'Permissions required', - alertDescription: 'This application needs to access your phone accounts', - cancelButton: 'Cancel', - okButton: 'Ok', - imageName: 'phone_account_icon', - additionalPermissions: [ - PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE, - PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, - PermissionsAndroid.PERMISSIONS.CALL_PHONE - ], - // Required to get audio in background when using Android 11 - foregroundService: { - channelId: 'chat.rocket.reactnative', - channelName: 'Rocket.Chat', - notificationTitle: 'Voice call is running on background' - } - } - }; - - RNCallKeep.setup(options); - RNCallKeep.canMakeMultipleCalls(false); - } catch (e) { - log(e); - } -} - const startVoipFork = function* startVoipFork() { try { const allowInternalVoiceCallRoles = yield select(state => state.permissions['allow-internal-voice-calls']); @@ -269,10 +232,8 @@ const startVoipFork = function* startVoipFork() { const hasPermissions = yield hasPermission([allowInternalVoiceCallRoles, allowExternalVoiceCallRoles]); if (isVoipModuleAvailable() && (hasPermissions[0] || hasPermissions[1])) { - yield call(initCallKeep); const userId = yield select(state => state.login.user.id); mediaSessionInstance.init(userId); - // simulateCall(); } } catch (e) { log(e); @@ -318,12 +279,12 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) { yield serversDB.write(async () => { try { const userRecord = await usersCollection.find(user.id); - await userRecord.update((record) => { + await userRecord.update(record => { record._raw = sanitizedRaw({ id: user.id, ...record._raw }, usersCollection.schema); Object.assign(record, u); }); } catch (e) { - await usersCollection.create((record) => { + await usersCollection.create(record => { record._raw = sanitizedRaw({ id: user.id }, usersCollection.schema); Object.assign(record, u); }); @@ -400,7 +361,7 @@ const handleSetUser = function* handleSetUser({ user }) { yield serversDB.write(async () => { try { const record = await userCollections.find(userId); - await record.update((userRecord) => { + await record.update(userRecord => { if ('avatarETag' in user) { userRecord.avatarETag = user.avatarETag; } diff --git a/index.js b/index.js index 626e7082141..a59c08135ce 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ import 'react-native-gesture-handler'; import 'react-native-console-time-polyfill'; -import { AppRegistry, LogBox } from 'react-native'; +import { AppRegistry, LogBox, PermissionsAndroid, Platform } from 'react-native'; +import RNCallKeep from 'react-native-callkeep'; import { name as appName } from './app.json'; @@ -21,5 +22,35 @@ if (process.env.USE_STORYBOOK) { LogBox.ignoreAllLogs(); + if (Platform.OS === 'android') { + const options = { + android: { + // TODO: i18n + alertTitle: 'Permissions required', + alertDescription: 'This application needs to access your phone accounts', + cancelButton: 'Cancel', + okButton: 'Ok', + imageName: 'phone_account_icon', + additionalPermissions: [PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE, PermissionsAndroid.PERMISSIONS.RECORD_AUDIO], + // Required to get audio in background when using Android 11 + foregroundService: { + channelId: 'chat.rocket.reactnative', + channelName: 'Rocket.Chat', + notificationTitle: 'Voice call is running on background' + }, + selfManaged: true + } + }; + + RNCallKeep.setup(options) + .then(() => { + console.log('RNCallKeep setup successful'); + RNCallKeep.canMakeMultipleCalls(false); + }) + .catch(error => { + console.error('Error setting up RNCallKeep:', error); + }); + } + AppRegistry.registerComponent(appName, () => require('./app/index').default); } From b1f81f449b14caae8a2bd4eca19a27275b3e1b2e Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 28 Jan 2026 15:37:33 -0300 Subject: [PATCH 34/61] Refactor VoIP handling: Migrate VoIP-related classes to a new package structure, removing deprecated modules and consolidating functionality. Update imports in MainApplication and NotificationIntentHandler to reflect changes. This cleanup enhances code organization and prepares for future VoIP feature enhancements. --- .../rocket/reactnative/MainApplication.kt | 4 ++-- .../notification/NotificationIntentHandler.kt | 2 ++ .../RCFirebaseMessagingService.kt | 3 ++- .../CallIdUUIDModule.kt | 2 +- .../CallIdUUIDTurboPackage.kt | 2 +- .../NativeCallIdUUIDSpec.kt | 2 +- .../reactnative/voip/IncomingCallActivity.kt | 20 +++++++++---------- .../{notification => voip}/NativeVoipSpec.kt | 2 +- .../reactnative/voip/VoipForegroundService.kt | 1 - .../{notification => voip}/VoipModule.kt | 2 +- .../VoipNotification.kt | 5 ++--- .../{notification => voip}/VoipPayload.kt | 5 +---- .../VoipTurboPackage.kt | 6 +++--- 13 files changed, 27 insertions(+), 29 deletions(-) rename android/app/src/main/java/chat/rocket/reactnative/{notification => utils}/CallIdUUIDModule.kt (98%) rename android/app/src/main/java/chat/rocket/reactnative/{notification => utils}/CallIdUUIDTurboPackage.kt (95%) rename android/app/src/main/java/chat/rocket/reactnative/{notification => utils}/NativeCallIdUUIDSpec.kt (92%) rename android/app/src/main/java/chat/rocket/reactnative/{notification => voip}/NativeVoipSpec.kt (93%) rename android/app/src/main/java/chat/rocket/reactnative/{notification => voip}/VoipModule.kt (99%) rename android/app/src/main/java/chat/rocket/reactnative/{notification => voip}/VoipNotification.kt (98%) rename android/app/src/main/java/chat/rocket/reactnative/{notification => voip}/VoipPayload.kt (82%) rename android/app/src/main/java/chat/rocket/reactnative/{notification => voip}/VoipTurboPackage.kt (87%) diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt index 6e0fe420c99..9a6ac9dac3f 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt @@ -20,8 +20,8 @@ import chat.rocket.reactnative.storage.MMKVKeyManager; import chat.rocket.reactnative.storage.SecureStoragePackage; import chat.rocket.reactnative.notification.VideoConfTurboPackage import chat.rocket.reactnative.notification.PushNotificationTurboPackage -import chat.rocket.reactnative.notification.VoipTurboPackage -import chat.rocket.reactnative.notification.CallIdUUIDTurboPackage +import chat.rocket.reactnative.voip.VoipTurboPackage +import chat.rocket.reactnative.utils.CallIdUUIDTurboPackage /** * Main Application class. diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index e396bb90aee..5b1c9bc8330 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -5,6 +5,8 @@ import android.content.Intent import android.os.Bundle import android.util.Log import com.google.gson.GsonBuilder +import chat.rocket.reactnative.voip.VoipNotification +import chat.rocket.reactnative.voip.VoipModule /** * Handles notification Intent processing from MainActivity. diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt index 6513fdc20a8..e7768875686 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt @@ -5,6 +5,8 @@ import android.util.Log import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import com.google.gson.Gson +import chat.rocket.reactnative.voip.VoipNotification +import chat.rocket.reactnative.voip.VoipPayload /** * Custom Firebase Messaging Service for Rocket.Chat. @@ -73,7 +75,6 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { return try { VoipPayload( callId = data["callId"], - calleeId = data["calleeId"], caller = data["caller"], host = data["host"], type = data["type"] diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDModule.kt b/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDModule.kt similarity index 98% rename from android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDModule.kt rename to android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDModule.kt index c3ba835c25a..aeb86eba722 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDModule.kt @@ -1,4 +1,4 @@ -package chat.rocket.reactnative.notification +package chat.rocket.reactnative.utils import com.facebook.react.bridge.ReactApplicationContext import java.security.MessageDigest diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDTurboPackage.kt b/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDTurboPackage.kt similarity index 95% rename from android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDTurboPackage.kt rename to android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDTurboPackage.kt index 54aa0c2e22b..33ef27b99b7 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/CallIdUUIDTurboPackage.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDTurboPackage.kt @@ -1,4 +1,4 @@ -package chat.rocket.reactnative.notification +package chat.rocket.reactnative.utils import com.facebook.react.BaseReactPackage import com.facebook.react.bridge.NativeModule diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NativeCallIdUUIDSpec.kt b/android/app/src/main/java/chat/rocket/reactnative/utils/NativeCallIdUUIDSpec.kt similarity index 92% rename from android/app/src/main/java/chat/rocket/reactnative/notification/NativeCallIdUUIDSpec.kt rename to android/app/src/main/java/chat/rocket/reactnative/utils/NativeCallIdUUIDSpec.kt index 6a5d7fb0e9b..9da6aa0fe58 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NativeCallIdUUIDSpec.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/utils/NativeCallIdUUIDSpec.kt @@ -1,4 +1,4 @@ -package chat.rocket.reactnative.notification +package chat.rocket.reactnative.utils import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt index e78b1ed4a97..fd3363856ea 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt @@ -16,8 +16,6 @@ import android.util.Log import androidx.core.content.ContextCompat import chat.rocket.reactnative.MainActivity import chat.rocket.reactnative.R -import chat.rocket.reactnative.notification.VoipNotification -import chat.rocket.reactnative.notification.VoipModule /** * Full-screen Activity displayed when an incoming VoIP call arrives. @@ -52,15 +50,17 @@ class IncomingCallActivity : Activity() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { setShowWhenLocked(true) setTurnScreenOn(true) + } else { + // Enable showing on lock screen (for older Android versions) + @Suppress("DEPRECATION") + window.addFlags( + WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or + WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD + ) } - - // Enable showing on lock screen (for older Android versions) - window.addFlags( - WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or - WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or - WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or - WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD - ) + + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) setContentView(R.layout.activity_incoming_call) diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NativeVoipSpec.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt similarity index 93% rename from android/app/src/main/java/chat/rocket/reactnative/notification/NativeVoipSpec.kt rename to android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt index 41ebec955dc..40a7735ed45 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NativeVoipSpec.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt @@ -1,4 +1,4 @@ -package chat.rocket.reactnative.notification +package chat.rocket.reactnative.voip import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt index ac5ab62da74..bd92cbdc4db 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt @@ -12,7 +12,6 @@ import android.os.IBinder import android.util.Log import androidx.core.app.NotificationCompat import chat.rocket.reactnative.R -import chat.rocket.reactnative.notification.VoipNotification /** * Foreground service for VoIP calls to ensure reliability on Android 14/15. diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt similarity index 99% rename from android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt rename to android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt index 6eb6c4fd502..e9fbbe4a4fc 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt @@ -1,4 +1,4 @@ -package chat.rocket.reactnative.notification +package chat.rocket.reactnative.voip import android.content.Context import android.util.Log diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt similarity index 98% rename from android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt rename to android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt index c6fc13d933e..6948d6d1fe5 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipNotification.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt @@ -1,4 +1,4 @@ -package chat.rocket.reactnative.notification +package chat.rocket.reactnative.voip import android.app.Notification import android.app.NotificationChannel @@ -20,8 +20,7 @@ import android.telecom.PhoneAccount import android.telecom.PhoneAccountHandle import android.telecom.TelecomManager import chat.rocket.reactnative.MainActivity -import chat.rocket.reactnative.voip.IncomingCallActivity -import chat.rocket.reactnative.voip.VoipForegroundService +import chat.rocket.reactnative.utils.CallIdUUID /** * Handles VoIP call notifications using Android's Telecom framework via CallKeep. diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt similarity index 82% rename from android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt rename to android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt index 8f6db041f88..56c77eb7c14 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipPayload.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt @@ -1,4 +1,4 @@ -package chat.rocket.reactnative.notification +package chat.rocket.reactnative.voip import com.google.gson.annotations.SerializedName @@ -6,9 +6,6 @@ data class VoipPayload( @SerializedName("callId") val callId: String?, - @SerializedName("calleeId") - val calleeId: String?, - @SerializedName("caller") val caller: String?, diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipTurboPackage.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipTurboPackage.kt similarity index 87% rename from android/app/src/main/java/chat/rocket/reactnative/notification/VoipTurboPackage.kt rename to android/app/src/main/java/chat/rocket/reactnative/voip/VoipTurboPackage.kt index ba038314176..6c3b27b5ee5 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/VoipTurboPackage.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipTurboPackage.kt @@ -1,12 +1,12 @@ -package chat.rocket.reactnative.notification +package chat.rocket.reactnative.voip -import com.facebook.react.TurboReactPackage +import com.facebook.react.BaseReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.model.ReactModuleInfo import com.facebook.react.module.model.ReactModuleInfoProvider -class VoipTurboPackage : TurboReactPackage() { +class VoipTurboPackage : BaseReactPackage() { override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { return when (name) { From 089f91bdd4e70f412087f115123ca238010364a8 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 28 Jan 2026 17:21:12 -0300 Subject: [PATCH 35/61] Remove VoipForegroundService --- .../reactnative/voip/VoipForegroundService.kt | 116 ------------------ .../reactnative/voip/VoipNotification.kt | 4 - 2 files changed, 120 deletions(-) delete mode 100644 android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt deleted file mode 100644 index bd92cbdc4db..00000000000 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipForegroundService.kt +++ /dev/null @@ -1,116 +0,0 @@ -package chat.rocket.reactnative.voip - -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.app.Service -import android.content.Context -import android.content.Intent -import android.content.pm.ServiceInfo -import android.os.Build -import android.os.IBinder -import android.util.Log -import androidx.core.app.NotificationCompat -import chat.rocket.reactnative.R - -/** - * Foreground service for VoIP calls to ensure reliability on Android 14/15. - * Prevents the system from killing the call process when the app is in the background. - */ -class VoipForegroundService : Service() { - - companion object { - private const val TAG = "RocketChat.VoipService" - private const val NOTIFICATION_ID = 1001 - private const val CHANNEL_ID = "voip-foreground-service" - - /** - * Starts the foreground service for an incoming call. - */ - @JvmStatic - fun start(context: Context, callUUID: String, callerName: String) { - val intent = Intent(context, VoipForegroundService::class.java).apply { - putExtra("callUUID", callUUID) - putExtra("callerName", callerName) - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - context.startForegroundService(intent) - } else { - context.startService(intent) - } - } - - /** - * Stops the foreground service. - */ - @JvmStatic - fun stop(context: Context) { - val intent = Intent(context, VoipForegroundService::class.java) - context.stopService(intent) - } - } - - override fun onCreate() { - super.onCreate() - createNotificationChannel() - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - val callUUID = intent?.getStringExtra("callUUID") ?: return START_NOT_STICKY - val callerName = intent.getStringExtra("callerName") ?: "Incoming call" - - Log.d(TAG, "Starting foreground service for call: $callUUID") - - // Create notification for foreground service - val notification = createNotification(callerName) - - // Start foreground service with PHONE_CALL type (Android 14+) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL) - } else { - startForeground(NOTIFICATION_ID, notification) - } - - return START_NOT_STICKY - } - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onDestroy() { - super.onDestroy() - Log.d(TAG, "Foreground service destroyed") - } - - private fun createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val channel = NotificationChannel( - CHANNEL_ID, - "VoIP Call Service", - NotificationManager.IMPORTANCE_LOW - ).apply { - description = "Ongoing VoIP call service" - setShowBadge(false) - } - - val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - notificationManager.createNotificationChannel(channel) - } - } - - private fun createNotification(callerName: String): Notification { - val packageName = packageName - val smallIconResId = resources.getIdentifier("ic_notification", "drawable", packageName) - - return NotificationCompat.Builder(this, CHANNEL_ID) - .setContentTitle("Ongoing call") - .setContentText("Call with $callerName") - .setSmallIcon(smallIconResId) - .setOngoing(true) - .setPriority(NotificationCompat.PRIORITY_LOW) - .setCategory(NotificationCompat.CATEGORY_CALL) - .build() - } -} diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt index 6948d6d1fe5..fb2fc24b0aa 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt @@ -145,9 +145,6 @@ class VoipNotification(private val context: Context) { // This triggers react-native-callkeep's ConnectionService registerCallWithTelecomManager(callUUID, callerName) - // Start foreground service for Android 14/15 reliability - VoipForegroundService.start(context, callUUID, callerName) - // Show notification with full-screen intent showIncomingCallNotification(bundle, voipPayload, callUUID, callerName) } @@ -343,7 +340,6 @@ class VoipNotification(private val context: Context) { fun cancelCall(callId: String) { val notificationId = callId.hashCode() cancelById(context, notificationId) - VoipForegroundService.stop(context) VoipModule.clearPendingVoipCall(context) } } From 6ac2f7691bb03fac0e346e3d2507bb18c2d0161d Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 28 Jan 2026 17:44:05 -0300 Subject: [PATCH 36/61] cleanup and use caller instead of callerName --- .../notification/NotificationIntentHandler.kt | 8 ++-- .../reactnative/voip/IncomingCallActivity.kt | 18 +++---- .../rocket/reactnative/voip/VoipModule.kt | 34 ++------------ .../reactnative/voip/VoipNotification.kt | 47 +++++++------------ .../CallHeader/components/Title.tsx | 6 +-- app/lib/services/voip/getInitialEvents.ts | 1 - app/views/CallView/components/CallerInfo.tsx | 4 +- app/views/CallView/styles.ts | 4 +- 8 files changed, 41 insertions(+), 81 deletions(-) diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index 5b1c9bc8330..145efddb40f 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -51,13 +51,13 @@ class NotificationIntentHandler { val event = intent.getStringExtra("event") ?: return true val callId = intent.getStringExtra("callId") ?: "" val callUUID = intent.getStringExtra("callUUID") ?: "" - val callerName = intent.getStringExtra("callerName") ?: "" + val caller = intent.getStringExtra("caller") ?: "" val host = intent.getStringExtra("host") ?: "" Log.d(TAG, "Handling VoIP intent - event: $event, callId: $callId, callUUID: $callUUID") VoipNotification.cancelById(context, notificationId) - VoipModule.storePendingVoipCall(context, callId, callUUID, callerName, host, event) + VoipModule.storePendingVoipCall(context, callId, callUUID, caller, host, event) // Emit event to JS if app is running if (event == "accept") { @@ -85,7 +85,7 @@ class NotificationIntentHandler { val rid = intent.getStringExtra("rid") ?: "" val callerId = intent.getStringExtra("callerId") ?: "" - val callerName = intent.getStringExtra("callerName") ?: "" + val caller = intent.getStringExtra("caller") ?: "" val host = intent.getStringExtra("host") ?: "" val callId = intent.getStringExtra("callId") ?: "" @@ -103,7 +103,7 @@ class NotificationIntentHandler { "callId" to callId, "caller" to mapOf( "_id" to callerId, - "name" to callerName + "name" to caller ) ) diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt index fd3363856ea..dc57b92e6a4 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt @@ -27,14 +27,14 @@ class IncomingCallActivity : Activity() { private const val TAG = "RocketChat.IncomingCall" private const val EXTRA_CALL_ID = "callId" private const val EXTRA_CALL_UUID = "callUUID" - private const val EXTRA_CALLER_NAME = "callerName" + private const val EXTRA_CALLER = "caller" private const val EXTRA_HOST = "host" } private var ringtone: Ringtone? = null private var callUUID: String? = null private var callId: String? = null - private var callerName: String? = null + private var caller: String? = null private var host: String? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -67,10 +67,10 @@ class IncomingCallActivity : Activity() { // Get call data from intent callId = intent.getStringExtra(EXTRA_CALL_ID) callUUID = intent.getStringExtra(EXTRA_CALL_UUID) - callerName = intent.getStringExtra(EXTRA_CALLER_NAME) ?: "Unknown" + caller = intent.getStringExtra(EXTRA_CALLER) host = intent.getStringExtra(EXTRA_HOST) - Log.d(TAG, "IncomingCallActivity created - callUUID: $callUUID, caller: $callerName") + Log.d(TAG, "IncomingCallActivity created - callUUID: $callUUID, caller: $caller") // Update UI updateUI() @@ -83,8 +83,8 @@ class IncomingCallActivity : Activity() { } private fun updateUI() { - val callerNameView = findViewById<TextView>(R.id.caller_name) - callerNameView?.text = callerName ?: "Unknown" + val callerView = findViewById<TextView>(R.id.caller_name) + callerView?.text = caller // Try to load avatar if available // TODO: needs username to load avatar @@ -138,8 +138,8 @@ class IncomingCallActivity : Activity() { } // Store pending call data before emitting event (fixes race condition) - // if (callUUID != null && callId != null && callerName != null && host != null) { - // VoipModule.storePendingVoipCall(this, callId, callUUID, callerName, host, "accept") + // if (callUUID != null && callId != null && caller != null && host != null) { + // VoipModule.storePendingVoipCall(this, callId, callUUID, caller, host, "accept") // } // Launch MainActivity with call data @@ -149,7 +149,7 @@ class IncomingCallActivity : Activity() { putExtra("event", "accept") putExtra("callId", callId) putExtra("callUUID", callUUID) - putExtra("callerName", callerName) + putExtra("caller", caller) putExtra("host", host) } startActivity(launchIntent) diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt index e9fbbe4a4fc..4f740745432 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt @@ -52,34 +52,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo } } - /** - * Emits an incoming call event to JavaScript. - */ - // @JvmStatic - // fun emitIncomingCall(callId: String, callUUID: String, callerName: String, host: String?) { - // try { - // val data = mapOf( - // "callId" to callId, - // "callUUID" to callUUID, - // "callerName" to callerName, - // "host" to (host ?: "") - // ) - // val gson = GsonBuilder().create() - // val jsonData = gson.toJson(data) - - // reactContextRef?.get()?.let { context -> - // if (context.hasActiveReactInstance()) { - // context - // .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) - // .emit(EVENT_INCOMING_CALL, jsonData) - // Log.d(TAG, "Emitted incoming call event to JS: $callUUID") - // } - // } - // } catch (e: Exception) { - // Log.e(TAG, "Failed to emit incoming call event", e) - // } - // } - /** * Emits a call answered event to JavaScript. */ @@ -157,13 +129,13 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Also emits an event if the app is running. */ @JvmStatic - fun storePendingVoipCall(context: Context, callId: String, callUUID: String, callerName: String, host: String, event: String) { + fun storePendingVoipCall(context: Context, callId: String, callUUID: String, caller: String, host: String, event: String) { // TODO: use VoipPayload val data = mapOf( "notificationType" to "voip", "callId" to callId, "callUUID" to callUUID, - "callerName" to callerName, + "caller" to caller, "host" to host, "event" to event ) @@ -176,7 +148,7 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo .putString("pendingAction", jsonData) .putString("callId", callId) .putString("callUUID", callUUID) - .putString("callerName", callerName) + .putString("caller", caller) .putString("host", host) .putString("event", event) .putLong("timestamp", System.currentTimeMillis()) diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt index fb2fc24b0aa..c10f76bef69 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt @@ -71,6 +71,7 @@ class VoipNotification(private val context: Context) { Log.d(TAG, "Decline action triggered for callUUID: $callUUID") // Clear stored call data VoipModule.clearPendingVoipCall(context) + // TODO: call restapi to decline the call } } @@ -128,25 +129,24 @@ class VoipNotification(private val context: Context) { */ fun showIncomingCall(bundle: Bundle, voipPayload: VoipPayload) { val callId = voipPayload.callId - if (callId.isNullOrEmpty()) { + val caller = voipPayload.caller + if (callId.isNullOrEmpty() || caller.isNullOrEmpty()) { Log.w(TAG, "Cannot show VoIP call: callId is missing") return } - // Get caller information - simplified since VoipPayload has caller as a string - val callerName = voipPayload.caller ?: "Unknown" // TODO: remove this when it comes from the server val callUUID = CallIdUUID.generateUUIDv5(callId) - Log.d(TAG, "Showing incoming VoIP call - callId: $callId, callUUID: $callUUID, caller: $callerName") + Log.d(TAG, "Showing incoming VoIP call - callId: $callId, callUUID: $callUUID, caller: $caller") // CRITICAL: Register call with TelecomManager FIRST (required for audio focus, Bluetooth, priority, FSI exemption) // This triggers react-native-callkeep's ConnectionService - registerCallWithTelecomManager(callUUID, callerName) + registerCallWithTelecomManager(callUUID, caller) // Show notification with full-screen intent - showIncomingCallNotification(bundle, voipPayload, callUUID, callerName) + showIncomingCallNotification(bundle, voipPayload, callUUID, caller) } /** @@ -157,10 +157,10 @@ class VoipNotification(private val context: Context) { * 3. Higher process priority * 4. FSI exemption on Play Store */ - private fun registerCallWithTelecomManager(callUUID: String, callerName: String) { + private fun registerCallWithTelecomManager(callUUID: String, caller: String) { try { // Validate inputs - if (callUUID.isNullOrEmpty()) { + if (callUUID.isNullOrEmpty() || caller.isNullOrEmpty()) { Log.e(TAG, "Cannot register call with TelecomManager: callUUID is null or empty") return } @@ -187,19 +187,19 @@ class VoipNotification(private val context: Context) { // react-native-callkeep's VoiceConnectionService expects EXTRA_CALL_UUID constant // which is defined as "EXTRA_CALL_UUID" (not "callUUID") val extras = Bundle().apply { - val callerUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, callerName, null) + val callerUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, caller, null) putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, callerUri) // react-native-callkeep Constants.EXTRA_CALL_UUID = "EXTRA_CALL_UUID" putString("EXTRA_CALL_UUID", callUUID) // Also include EXTRA_CALLER_NAME for compatibility - putString("EXTRA_CALLER_NAME", callerName) + putString("EXTRA_CALLER_NAME", caller) // Legacy keys for backward compatibility putString("callUUID", callUUID) - putString("name", callerName) - putString("handle", callerName) + putString("name", caller) + putString("handle", caller) } - Log.d(TAG, "Registering call with TelecomManager - callUUID: $callUUID, callerName: $callerName, extras keys: ${extras.keySet()}") + Log.d(TAG, "Registering call with TelecomManager - callUUID: $callUUID, caller: $caller, extras keys: ${extras.keySet()}") // Register the incoming call with the OS telecomManager.addNewIncomingCall(phoneAccountHandle, extras) @@ -216,11 +216,11 @@ class VoipNotification(private val context: Context) { * and heads-up notification for unlocked devices. * Falls back to HUN only if full-screen intent permission is not granted (Android 14+). */ - private fun showIncomingCallNotification(bundle: Bundle, voipPayload: VoipPayload, callUUID: String, callerName: String) { + private fun showIncomingCallNotification(bundle: Bundle, voipPayload: VoipPayload, callUUID: String, caller: String) { val callId = voipPayload.callId ?: "" val notificationId = callId.hashCode() - Log.d(TAG, "Showing incoming call notification for VoIP call from: $callerName") + Log.d(TAG, "Showing incoming call notification for VoIP call from: $caller") // Check if we can use full-screen intent (Android 14+) val canUseFullScreen = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { @@ -234,7 +234,7 @@ class VoipNotification(private val context: Context) { flags = Intent.FLAG_ACTIVITY_NEW_TASK putExtra("callId", callId) putExtra("callUUID", callUUID) - putExtra("callerName", callerName) + putExtra("caller", caller) putExtra("host", voipPayload.host ?: "") } val fullScreenPendingIntent = createPendingIntent(notificationId, fullScreenIntent) @@ -246,7 +246,7 @@ class VoipNotification(private val context: Context) { putExtra("event", "accept") putExtra("callId", callId) putExtra("callUUID", callUUID) - putExtra("callerName", callerName) + putExtra("caller", caller) putExtra("host", voipPayload.host ?: "") putExtra("notificationId", notificationId) } @@ -285,7 +285,7 @@ class VoipNotification(private val context: Context) { val builder = NotificationCompat.Builder(context, CHANNEL_ID).apply { setSmallIcon(smallIconResId) setContentTitle("Incoming call") - setContentText("Call from $callerName") + setContentText("Call from $caller") priority = NotificationCompat.PRIORITY_MAX setCategory(NotificationCompat.CATEGORY_CALL) setVisibility(NotificationCompat.VISIBILITY_PUBLIC) @@ -331,15 +331,4 @@ class VoipNotification(private val context: Context) { } return PendingIntent.getActivity(context, requestCode, intent, flags) } - - /** - * Cancels a VoIP call by callId. - * - * @param callId The call ID - */ - fun cancelCall(callId: String) { - val notificationId = callId.hashCode() - cancelById(context, notificationId) - VoipModule.clearPendingVoipCall(context) - } } diff --git a/app/containers/CallHeader/components/Title.tsx b/app/containers/CallHeader/components/Title.tsx index 9ed5e46a661..36885607bbe 100644 --- a/app/containers/CallHeader/components/Title.tsx +++ b/app/containers/CallHeader/components/Title.tsx @@ -22,7 +22,7 @@ const Title = () => { const callStartTime = useCallStore(state => state.callStartTime); const contact = useCallStore(state => state.contact); - const callerName = contact.displayName || contact.username || I18n.t('Unknown'); + const caller = contact.displayName || contact.username; const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; const isConnected = callState === 'active'; @@ -31,9 +31,9 @@ const Title = () => { return I18n.t('Connecting'); } if (isConnected && callStartTime) { - return `${callerName} – `; + return `${caller} – `; } - return callerName; + return caller; }; return ( diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index a48c1de7cf2..ea4f3b7a98f 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -187,7 +187,6 @@ const getInitialEventsAndroid = async (): Promise<boolean> => { notificationType: string; callId: string; callUUID: string; - callerName: string; host: string; event: string; }; diff --git a/app/views/CallView/components/CallerInfo.tsx b/app/views/CallView/components/CallerInfo.tsx index cb9231ad0bc..c212e454435 100644 --- a/app/views/CallView/components/CallerInfo.tsx +++ b/app/views/CallView/components/CallerInfo.tsx @@ -31,8 +31,8 @@ const CallerInfo = ({ isMuted = false }: ICallerInfo): React.ReactElement => { </View> </AvatarContainer> </View> - <View style={styles.callerNameRow}> - <Text style={[styles.callerName, { color: colors.fontDefault }]} numberOfLines={1} testID='caller-info-name'> + <View style={styles.callerRow}> + <Text style={[styles.caller, { color: colors.fontDefault }]} numberOfLines={1} testID='caller-info-name'> {name} </Text> {isMuted && ( diff --git a/app/views/CallView/styles.ts b/app/views/CallView/styles.ts index 1b8261d7cd8..484af08e061 100644 --- a/app/views/CallView/styles.ts +++ b/app/views/CallView/styles.ts @@ -21,14 +21,14 @@ export const styles = StyleSheet.create({ marginBottom: 16, position: 'relative' }, - callerName: { + caller: { ...sharedStyles.textBold, fontSize: 24, lineHeight: 32, textAlign: 'center', marginBottom: 4 }, - callerNameRow: { + callerRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center' From d81e67eb33233ac95f88c912b8413f37b95fd784 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 28 Jan 2026 18:01:42 -0300 Subject: [PATCH 37/61] Cleanup and make iOS build again --- ...ativeVoipAndroid.ts => NativeVoip.android.ts} | 0 app/lib/services/voip/getInitialEvents.ts | 16 +++++++++++----- ios/AppDelegate.swift | 1 + 3 files changed, 12 insertions(+), 5 deletions(-) rename app/lib/native/{NativeVoipAndroid.ts => NativeVoip.android.ts} (100%) diff --git a/app/lib/native/NativeVoipAndroid.ts b/app/lib/native/NativeVoip.android.ts similarity index 100% rename from app/lib/native/NativeVoipAndroid.ts rename to app/lib/native/NativeVoip.android.ts diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index ea4f3b7a98f..8a4d296e282 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -1,16 +1,22 @@ import RNCallKeep from 'react-native-callkeep'; import VoipPushNotification from 'react-native-voip-push-notification'; -import { DeviceEventEmitter, Platform } from 'react-native'; +import { DeviceEventEmitter } from 'react-native'; import { isIOS } from '../../methods/helpers'; import CallIdUUIDModule from '../../native/NativeCallIdUUID'; -import NativeVoipModule from '../../native/NativeVoipAndroid'; import store from '../../store'; import { voipCallOpen } from '../../../actions/deepLinking'; import { setVoipPushToken } from './pushTokenAux'; import { useCallStore } from './useCallStore'; import { mediaSessionInstance } from './MediaSessionInstance'; +let NativeVoipModule: any; +if (!isIOS) { + NativeVoipModule = require('../../native/NativeVoip.android'); +} else { + NativeVoipModule = null; +} + // Store VoIP push data temporarily (iOS only - Android uses native storage) let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; @@ -31,9 +37,9 @@ export const getInitialEvents = (): Promise<boolean> => { * Sets up listeners for Android VoIP call events from native side. * @returns Cleanup function to remove listeners */ -export const setupVoipEventListeners = (): (() => void) | undefined => { - if (Platform.OS !== 'android') { - return undefined; +export const setupVoipEventListeners = (): (() => void) => { + if (isIOS) { + return () => {}; } const subscriptions = [ diff --git a/ios/AppDelegate.swift b/ios/AppDelegate.swift index 3bd831b45e0..2549712d1b1 100644 --- a/ios/AppDelegate.swift +++ b/ios/AppDelegate.swift @@ -108,6 +108,7 @@ extension AppDelegate: PKPushRegistryDelegate { // The system calls this method when a previously provided push token is no longer valid for use. // No action is necessary on your part to reregister the push type. // Instead, use this method to notify your server not to send push notifications using the matching push token. + // TODO: call restapi to unregister the push token } public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { From 2b3e96a1d4aa3dfb91bdc439f7a15864a9fcedbe Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Thu, 29 Jan 2026 10:25:12 -0300 Subject: [PATCH 38/61] Refactor VoIP handling: Remove unused event emissions for call answered and declined, switch from SharedPreferences to in-memory storage for pending VoIP call data, and update method signatures for better clarity. This cleanup enhances performance and prepares for future VoIP feature improvements. --- .../notification/NotificationIntentHandler.kt | 5 - .../reactnative/voip/IncomingCallActivity.kt | 6 - .../rocket/reactnative/voip/NativeVoipSpec.kt | 2 +- .../rocket/reactnative/voip/VoipModule.kt | 144 ++++-------------- .../reactnative/voip/VoipNotification.kt | 15 -- app/lib/native/NativeVoip.android.ts | 2 +- app/lib/services/voip/getInitialEvents.ts | 8 +- 7 files changed, 32 insertions(+), 150 deletions(-) diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index 145efddb40f..8a1208b95a9 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -59,11 +59,6 @@ class NotificationIntentHandler { VoipNotification.cancelById(context, notificationId) VoipModule.storePendingVoipCall(context, callId, callUUID, caller, host, event) - // Emit event to JS if app is running - if (event == "accept") { - VoipModule.emitCallAnswered(callUUID) - } - // Clear the voip flag to prevent re-processing intent.removeExtra("voipAction") diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt index dc57b92e6a4..5e7e8acb93a 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt @@ -169,12 +169,6 @@ class IncomingCallActivity : Activity() { // Emit event to JS // TODO: call restapi to decline the call - callUUID?.let { uuid -> - VoipModule.emitCallDeclined(uuid) - } - - // Clear stored call data - VoipModule.clearPendingVoipCall(this) finish() } diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt index 40a7735ed45..3574f3f3c56 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt @@ -16,7 +16,7 @@ abstract class NativeVoipSpec(reactContext: ReactApplicationContext) : override fun getName(): String = NAME @ReactMethod - abstract fun getPendingVoipCall(promise: Promise) + abstract fun getPendingVoipCall(): String? @ReactMethod abstract fun clearPendingVoipCall() diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt index 4f740745432..34d293e4a58 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt @@ -17,13 +17,11 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo companion object { private const val TAG = "RocketChat.VoipModule" - private const val PREFS_NAME = "VoipCallData" private const val EVENT_VOIP_CALL = "VoipCallAction" - private const val EVENT_CALL_ANSWERED = "VoipCallAnswered" - private const val EVENT_CALL_DECLINED = "VoipCallDeclined" - private const val EVENT_INCOMING_CALL = "VoipIncomingCall" private var reactContextRef: WeakReference<ReactApplicationContext>? = null + private var pendingVoipCallData: String? = null + private var pendingVoipCallTimestamp: Long = 0 /** * Sets the React context reference for event emission. @@ -52,78 +50,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo } } - /** - * Emits a call answered event to JavaScript. - */ - @JvmStatic - fun emitCallAnswered(callUUID: String) { - try { - reactContextRef?.get()?.let { context -> - if (context.hasActiveReactInstance()) { - context - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) - .emit(EVENT_CALL_ANSWERED, callUUID) - Log.d(TAG, "Emitted call answered event to JS: $callUUID") - } - } - } catch (e: Exception) { - Log.e(TAG, "Failed to emit call answered event", e) - } - } - - /** - * Emits a call declined event to JavaScript. - */ - @JvmStatic - fun emitCallDeclined(callUUID: String) { - try { - reactContextRef?.get()?.let { context -> - if (context.hasActiveReactInstance()) { - context - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) - .emit(EVENT_CALL_DECLINED, callUUID) - Log.d(TAG, "Emitted call declined event to JS: $callUUID") - } - } - } catch (e: Exception) { - Log.e(TAG, "Failed to emit call declined event", e) - } - } - - /** - * Clears pending VoIP call data from SharedPreferences. - * Internal method that can be called from any context. - */ - @JvmStatic - internal fun clearPendingVoipCall(context: Context) { - try { - context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) - .edit() - .clear() - .apply() - Log.d(TAG, "Cleared pending VoIP call data") - } catch (e: Exception) { - Log.e(TAG, "Error clearing pending VoIP call", e) - } - } - - /** - * Cancels an incoming call notification and activity. - */ - // @JvmStatic - // fun cancelIncomingCall(callUUID: String) { - // try { - // val notificationId = callUUID.replace("-", "").hashCode() - // reactContextRef?.get()?.let { context -> - // VoipNotification.cancelById(context, notificationId) - // clearPendingVoipCall(context) - // Log.d(TAG, "Cancelled incoming call: $callUUID") - // } - // } catch (e: Exception) { - // Log.e(TAG, "Failed to cancel incoming call", e) - // } - // } - /** * Stores VoIP call data for JS to retrieve. * Also emits an event if the app is running. @@ -143,22 +69,26 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo val gson = GsonBuilder().create() val jsonData = gson.toJson(data) - context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) - .edit() - .putString("pendingAction", jsonData) - .putString("callId", callId) - .putString("callUUID", callUUID) - .putString("caller", caller) - .putString("host", host) - .putString("event", event) - .putLong("timestamp", System.currentTimeMillis()) - .apply() + // Store in local variable instead of SharedPreferences + pendingVoipCallData = jsonData + pendingVoipCallTimestamp = System.currentTimeMillis() Log.d(TAG, "Stored pending VoIP call: $callId") // Emit event if app is running emitVoipCallEvent(jsonData) } + + @JvmStatic + fun clearPendingVoipCallInternal() { + try { + pendingVoipCallData = null + pendingVoipCallTimestamp = 0 + Log.d(TAG, "Cleared pending VoIP call data") + } catch (e: Exception) { + Log.e(TAG, "Error clearing pending VoIP call", e) + } + } } init { @@ -171,31 +101,21 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Returns null if no pending call. */ @ReactMethod - override fun getPendingVoipCall(promise: Promise) { - try { - Log.d(TAG, "getPendingVoipCall") - val prefs = reactApplicationContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) - + override fun getPendingVoipCall(): String? { + return try { // Check if data is stale (older than 5 minutes) - val timestamp = prefs.getLong("timestamp", 0) - if (System.currentTimeMillis() - timestamp > 5 * 60 * 1000) { - Log.d(TAG, "Pending VoIP call data is stale, clearing") - clearPendingVoipCallInternal() - promise.resolve(null) - return - } - - val pendingAction = prefs.getString("pendingAction", null) - if (pendingAction != null) { - // Clear after reading + if (System.currentTimeMillis() - pendingVoipCallTimestamp > 5 * 60 * 1000) { clearPendingVoipCallInternal() - Log.d(TAG, "Retrieved and cleared pending VoIP call") + null + } else { + if (pendingVoipCallData != null) { + clearPendingVoipCallInternal() + } + pendingVoipCallData } - - promise.resolve(pendingAction) } catch (e: Exception) { Log.e(TAG, "Error getting pending VoIP call", e) - promise.reject("ERROR", e.message) + null } } @@ -206,16 +126,4 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo override fun clearPendingVoipCall() { clearPendingVoipCallInternal() } - - private fun clearPendingVoipCallInternal() { - try { - reactApplicationContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) - .edit() - .clear() - .apply() - Log.d(TAG, "Cleared pending VoIP call data") - } catch (e: Exception) { - Log.e(TAG, "Error clearing pending VoIP call", e) - } - } } diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt index c10f76bef69..d49135197d7 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt @@ -44,14 +44,6 @@ class VoipNotification(private val context: Context) { // react-native-callkeep's ConnectionService class name private const val CALLKEEP_CONNECTION_SERVICE_CLASS = "io.wazo.callkeep.VoiceConnectionService" - /** - * Static method to clear stored call data from any context. - */ - @JvmStatic - fun clearStoredCallData(context: Context) { - VoipModule.clearPendingVoipCall(context) - } - /** * Cancels a VoIP notification by ID. */ @@ -69,8 +61,6 @@ class VoipNotification(private val context: Context) { @JvmStatic fun handleDeclineAction(context: Context, callUUID: String?) { Log.d(TAG, "Decline action triggered for callUUID: $callUUID") - // Clear stored call data - VoipModule.clearPendingVoipCall(context) // TODO: call restapi to decline the call } } @@ -135,7 +125,6 @@ class VoipNotification(private val context: Context) { return } - // TODO: remove this when it comes from the server val callUUID = CallIdUUID.generateUUIDv5(callId) @@ -184,14 +173,10 @@ class VoipNotification(private val context: Context) { } // Create extras for the incoming call - // react-native-callkeep's VoiceConnectionService expects EXTRA_CALL_UUID constant - // which is defined as "EXTRA_CALL_UUID" (not "callUUID") val extras = Bundle().apply { val callerUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, caller, null) putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, callerUri) - // react-native-callkeep Constants.EXTRA_CALL_UUID = "EXTRA_CALL_UUID" putString("EXTRA_CALL_UUID", callUUID) - // Also include EXTRA_CALLER_NAME for compatibility putString("EXTRA_CALLER_NAME", caller) // Legacy keys for backward compatibility putString("callUUID", callUUID) diff --git a/app/lib/native/NativeVoip.android.ts b/app/lib/native/NativeVoip.android.ts index a5915bb70a5..da2c3081bef 100644 --- a/app/lib/native/NativeVoip.android.ts +++ b/app/lib/native/NativeVoip.android.ts @@ -2,7 +2,7 @@ import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { - getPendingVoipCall(): Promise<string | null>; + getPendingVoipCall(): string | null; clearPendingVoipCall(): void; } diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index 8a4d296e282..e8c0d29227b 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -12,7 +12,7 @@ import { mediaSessionInstance } from './MediaSessionInstance'; let NativeVoipModule: any; if (!isIOS) { - NativeVoipModule = require('../../native/NativeVoip.android'); + NativeVoipModule = require('../../native/NativeVoip.android').default; } else { NativeVoipModule = null; } @@ -47,7 +47,7 @@ export const setupVoipEventListeners = (): (() => void) => { try { const data = JSON.parse(dataJson); console.log('[VoIP][Android] Call action event:', data); - await NativeVoipModule.clearPendingVoipCall(); + NativeVoipModule.clearPendingVoipCall(); if (data.event === 'accept') { useCallStore.getState().setCallUUID(data.callUUID); @@ -179,13 +179,13 @@ const getInitialEventsAndroid = async (): Promise<boolean> => { return false; } - const pendingCallJson = await NativeVoipModule.getPendingVoipCall(); + const pendingCallJson = NativeVoipModule.getPendingVoipCall(); if (!pendingCallJson) { console.log('[VoIP][Android] No pending VoIP call'); return false; } - await NativeVoipModule.clearPendingVoipCall(); + NativeVoipModule.clearPendingVoipCall(); console.log('[VoIP][Android] Found pending VoIP call:', pendingCallJson); From ad89658f85a9f32f3e0d199eca34d0da8b1f47e4 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Thu, 29 Jan 2026 16:21:33 -0300 Subject: [PATCH 39/61] Refactor VoIP handling: Introduce a new VoipPayload class to encapsulate call data, streamline notification processing, and enhance method signatures across the VoIP module. This update improves code clarity and prepares for future feature enhancements. --- .../notification/NotificationIntentHandler.kt | 18 ++--- .../RCFirebaseMessagingService.kt | 39 +--------- .../reactnative/voip/IncomingCallActivity.kt | 77 ++++++------------- .../rocket/reactnative/voip/NativeVoipSpec.kt | 6 +- .../rocket/reactnative/voip/VoipModule.kt | 63 +++++---------- .../reactnative/voip/VoipNotification.kt | 45 ++++------- .../rocket/reactnative/voip/VoipPayload.kt | 70 ++++++++++++++--- app/definitions/Voip.ts | 8 ++ app/lib/native/NativeVoip.android.ts | 2 +- app/lib/services/voip/getInitialEvents.ts | 59 +++++--------- 10 files changed, 162 insertions(+), 225 deletions(-) diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index 8a1208b95a9..0882c0f5b35 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -7,6 +7,7 @@ import android.util.Log import com.google.gson.GsonBuilder import chat.rocket.reactnative.voip.VoipNotification import chat.rocket.reactnative.voip.VoipModule +import chat.rocket.reactnative.voip.VoipPayload /** * Handles notification Intent processing from MainActivity. @@ -46,18 +47,15 @@ class NotificationIntentHandler { if (!intent.getBooleanExtra("voipAction", false)) { return false } + val voipPayload = VoipPayload.fromBundle(intent.extras) + if (voipPayload == null || !voipPayload.isVoipIncomingCall()) { + return false + } - val notificationId = intent.getIntExtra("notificationId", 0) - val event = intent.getStringExtra("event") ?: return true - val callId = intent.getStringExtra("callId") ?: "" - val callUUID = intent.getStringExtra("callUUID") ?: "" - val caller = intent.getStringExtra("caller") ?: "" - val host = intent.getStringExtra("host") ?: "" - - Log.d(TAG, "Handling VoIP intent - event: $event, callId: $callId, callUUID: $callUUID") + Log.d(TAG, "Handling VoIP intent - voipPayload: $voipPayload") - VoipNotification.cancelById(context, notificationId) - VoipModule.storePendingVoipCall(context, callId, callUUID, caller, host, event) + VoipNotification.cancelById(context, voipPayload.notificationId) + VoipModule.storePendingVoipCall(voipPayload) // Clear the voip flag to prevent re-processing intent.removeExtra("voipAction") diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt index e7768875686..417028e659e 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt @@ -38,16 +38,10 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { } } - val voipPayload = parseVoipPayload(data) - if (voipPayload != null && voipPayload.isVoipIncomingCall()) { - Log.d(TAG, "Detected new VoIP payload format, routing to VoipNotification handler") - try { - val voipNotification = VoipNotification(this) - // TODO: no need for bundle, just use voipPayload - voipNotification.showIncomingCall(bundle, voipPayload) - } catch (e: Exception) { - Log.e(TAG, "Error processing VoIP notification", e) - } + val voipPayload = VoipPayload.fromMap(data) + if (voipPayload != null) { + Log.d(TAG, "Detected VoIP incoming call payload, routing to VoipNotification handler") + VoipNotification(this).showIncomingCall(voipPayload) return } @@ -60,31 +54,6 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { } } - /** - * Parses the new VoIP payload format from FCM data map. - * Returns null if the payload doesn't match the new format. - */ - private fun parseVoipPayload(data: Map<String, String>): VoipPayload? { - val type = data["type"] - val hasEjson = data.containsKey("ejson") && !data["ejson"].isNullOrEmpty() - - if (type != "incoming_call" || hasEjson) { - return null - } - - return try { - VoipPayload( - callId = data["callId"], - caller = data["caller"], - host = data["host"], - type = data["type"] - ) - } catch (e: Exception) { - Log.e(TAG, "Failed to parse VoIP payload", e) - null - } - } - /** * Safely parses ejson string to Ejson object. */ diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt index 5e7e8acb93a..82da05741c3 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt @@ -25,17 +25,10 @@ class IncomingCallActivity : Activity() { companion object { private const val TAG = "RocketChat.IncomingCall" - private const val EXTRA_CALL_ID = "callId" - private const val EXTRA_CALL_UUID = "callUUID" - private const val EXTRA_CALLER = "caller" - private const val EXTRA_HOST = "host" } private var ringtone: Ringtone? = null - private var callUUID: String? = null - private var callId: String? = null - private var caller: String? = null - private var host: String? = null + private var voipPayload: VoipPayload? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -64,27 +57,24 @@ class IncomingCallActivity : Activity() { setContentView(R.layout.activity_incoming_call) - // Get call data from intent - callId = intent.getStringExtra(EXTRA_CALL_ID) - callUUID = intent.getStringExtra(EXTRA_CALL_UUID) - caller = intent.getStringExtra(EXTRA_CALLER) - host = intent.getStringExtra(EXTRA_HOST) - - Log.d(TAG, "IncomingCallActivity created - callUUID: $callUUID, caller: $caller") + val voipPayload = VoipPayload.fromBundle(intent.extras) + if (voipPayload == null || !voipPayload.isVoipIncomingCall()) { + Log.e(TAG, "Invalid VoIP payload, finishing activity") + finish() + return + } + this.voipPayload = voipPayload - // Update UI - updateUI() + Log.d(TAG, "IncomingCallActivity created - callUUID: ${voipPayload.callUUID}, caller: ${voipPayload.caller}") - // Start ringtone + updateUI(voipPayload) startRingtone() - - // Setup button listeners - setupButtons() + setupButtons(voipPayload) } - private fun updateUI() { + private fun updateUI(payload: VoipPayload) { val callerView = findViewById<TextView>(R.id.caller_name) - callerView?.text = caller + callerView?.text = payload.caller // Try to load avatar if available // TODO: needs username to load avatar @@ -114,58 +104,38 @@ class IncomingCallActivity : Activity() { } } - private fun setupButtons() { + private fun setupButtons(payload: VoipPayload) { val acceptButton = findViewById<ImageButton>(R.id.btn_accept) val declineButton = findViewById<ImageButton>(R.id.btn_decline) acceptButton?.setOnClickListener { - handleAccept() + handleAccept(payload) } declineButton?.setOnClickListener { - handleDecline() + handleDecline(payload) } } - private fun handleAccept() { - Log.d(TAG, "Call accepted - callUUID: $callUUID") + private fun handleAccept(payload: VoipPayload) { + Log.d(TAG, "Call accepted - callUUID: ${payload.callUUID}") stopRingtone() - // Cancel notification - callUUID?.let { uuid -> - val notificationId = uuid.replace("-", "").hashCode() - VoipNotification.cancelById(this, notificationId) - } - - // Store pending call data before emitting event (fixes race condition) - // if (callUUID != null && callId != null && caller != null && host != null) { - // VoipModule.storePendingVoipCall(this, callId, callUUID, caller, host, "accept") - // } - // Launch MainActivity with call data val launchIntent = Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - putExtra("voipAction", true) - putExtra("event", "accept") - putExtra("callId", callId) - putExtra("callUUID", callUUID) - putExtra("caller", caller) - putExtra("host", host) + putExtras(payload.toBundle()) } startActivity(launchIntent) finish() } - private fun handleDecline() { - Log.d(TAG, "Call declined - callUUID: $callUUID") + private fun handleDecline(payload: VoipPayload) { + Log.d(TAG, "Call declined - callUUID: ${payload.callUUID}") stopRingtone() - // Cancel notification - callUUID?.let { uuid -> - val notificationId = uuid.replace("-", "").hashCode() - VoipNotification.cancelById(this, notificationId) - } + VoipNotification.cancelById(this, payload.notificationId) // Emit event to JS // TODO: call restapi to decline the call @@ -179,7 +149,6 @@ class IncomingCallActivity : Activity() { } override fun onBackPressed() { - // Treat back button as decline - handleDecline() + voipPayload?.let { handleDecline(it) } ?: finish() } } diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt index 3574f3f3c56..79ea12dd389 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt @@ -1,10 +1,10 @@ package chat.rocket.reactnative.voip -import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.facebook.react.turbomodule.core.interfaces.TurboModule +import com.facebook.react.bridge.WritableMap abstract class NativeVoipSpec(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext), TurboModule { @@ -15,8 +15,8 @@ abstract class NativeVoipSpec(reactContext: ReactApplicationContext) : override fun getName(): String = NAME - @ReactMethod - abstract fun getPendingVoipCall(): String? + @ReactMethod(isBlockingSynchronousMethod = true) + abstract fun getPendingVoipCall(): WritableMap? @ReactMethod abstract fun clearPendingVoipCall() diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt index 34d293e4a58..03859540c49 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt @@ -2,11 +2,11 @@ package chat.rocket.reactnative.voip import android.content.Context import android.util.Log -import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactMethod +import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.WritableMap import com.facebook.react.modules.core.DeviceEventManagerModule -import com.google.gson.GsonBuilder import java.lang.ref.WeakReference /** @@ -17,10 +17,10 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo companion object { private const val TAG = "RocketChat.VoipModule" - private const val EVENT_VOIP_CALL = "VoipCallAction" + private const val EVENT_VOIP_CALL = "VoipCallAccepted" private var reactContextRef: WeakReference<ReactApplicationContext>? = null - private var pendingVoipCallData: String? = null + private var pendingVoipCallData: VoipPayload? = null private var pendingVoipCallTimestamp: Long = 0 /** @@ -35,14 +35,13 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Emits a VoIP call event to JavaScript when the app is running. */ @JvmStatic - fun emitVoipCallEvent(callDataJson: String) { + fun emitVoipCallEvent(voipPayload: VoipPayload) { try { reactContextRef?.get()?.let { context -> if (context.hasActiveReactInstance()) { context .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) - .emit(EVENT_VOIP_CALL, callDataJson) - Log.d(TAG, "Emitted VoIP call event to JS") + .emit(EVENT_VOIP_CALL, voipPayload.toWritableMap()) } } } catch (e: Exception) { @@ -55,28 +54,10 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Also emits an event if the app is running. */ @JvmStatic - fun storePendingVoipCall(context: Context, callId: String, callUUID: String, caller: String, host: String, event: String) { - // TODO: use VoipPayload - val data = mapOf( - "notificationType" to "voip", - "callId" to callId, - "callUUID" to callUUID, - "caller" to caller, - "host" to host, - "event" to event - ) - - val gson = GsonBuilder().create() - val jsonData = gson.toJson(data) - - // Store in local variable instead of SharedPreferences - pendingVoipCallData = jsonData + fun storePendingVoipCall(voipPayload: VoipPayload) { + pendingVoipCallData = voipPayload pendingVoipCallTimestamp = System.currentTimeMillis() - - Log.d(TAG, "Stored pending VoIP call: $callId") - - // Emit event if app is running - emitVoipCallEvent(jsonData) + emitVoipCallEvent(voipPayload) } @JvmStatic @@ -101,22 +82,18 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Returns null if no pending call. */ @ReactMethod - override fun getPendingVoipCall(): String? { - return try { - // Check if data is stale (older than 5 minutes) - if (System.currentTimeMillis() - pendingVoipCallTimestamp > 5 * 60 * 1000) { - clearPendingVoipCallInternal() - null - } else { - if (pendingVoipCallData != null) { - clearPendingVoipCallInternal() - } - pendingVoipCallData - } - } catch (e: Exception) { - Log.e(TAG, "Error getting pending VoIP call", e) - null + override fun getPendingVoipCall(): WritableMap? { + val data = pendingVoipCallData ?: return null + + if (System.currentTimeMillis() - pendingVoipCallTimestamp > 5 * 60 * 1000) { + clearPendingVoipCallInternal() + return null } + + val result = data.toWritableMap() + clearPendingVoipCallInternal() + + return result } /** diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt index d49135197d7..644d912a51e 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt @@ -20,7 +20,6 @@ import android.telecom.PhoneAccount import android.telecom.PhoneAccountHandle import android.telecom.TelecomManager import chat.rocket.reactnative.MainActivity -import chat.rocket.reactnative.utils.CallIdUUID /** * Handles VoIP call notifications using Android's Telecom framework via CallKeep. @@ -59,8 +58,8 @@ class VoipNotification(private val context: Context) { * Logs the decline action and clears stored call data. */ @JvmStatic - fun handleDeclineAction(context: Context, callUUID: String?) { - Log.d(TAG, "Decline action triggered for callUUID: $callUUID") + fun handleDeclineAction(context: Context, payload: VoipPayload) { + Log.d(TAG, "Decline action triggered for callUUID: ${payload.callUUID}") // TODO: call restapi to decline the call } } @@ -70,8 +69,8 @@ class VoipNotification(private val context: Context) { */ class DeclineReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - val callUUID = intent.getStringExtra("callUUID") - VoipNotification.handleDeclineAction(context, callUUID) + val voipPayload = VoipPayload.fromBundle(intent.extras) + voipPayload?.let { VoipNotification.handleDeclineAction(context, it) } } } @@ -117,16 +116,10 @@ class VoipNotification(private val context: Context) { * @param bundle The notification data bundle * @param voipPayload The VoIP payload containing call information */ - fun showIncomingCall(bundle: Bundle, voipPayload: VoipPayload) { + fun showIncomingCall(voipPayload: VoipPayload) { val callId = voipPayload.callId val caller = voipPayload.caller - if (callId.isNullOrEmpty() || caller.isNullOrEmpty()) { - Log.w(TAG, "Cannot show VoIP call: callId is missing") - return - } - - // TODO: remove this when it comes from the server - val callUUID = CallIdUUID.generateUUIDv5(callId) + val callUUID = voipPayload.callUUID Log.d(TAG, "Showing incoming VoIP call - callId: $callId, callUUID: $callUUID, caller: $caller") @@ -135,7 +128,7 @@ class VoipNotification(private val context: Context) { registerCallWithTelecomManager(callUUID, caller) // Show notification with full-screen intent - showIncomingCallNotification(bundle, voipPayload, callUUID, caller) + showIncomingCallNotification(voipPayload) } /** @@ -201,9 +194,9 @@ class VoipNotification(private val context: Context) { * and heads-up notification for unlocked devices. * Falls back to HUN only if full-screen intent permission is not granted (Android 14+). */ - private fun showIncomingCallNotification(bundle: Bundle, voipPayload: VoipPayload, callUUID: String, caller: String) { - val callId = voipPayload.callId ?: "" - val notificationId = callId.hashCode() + private fun showIncomingCallNotification(voipPayload: VoipPayload) { + val caller = voipPayload.caller + val notificationId = voipPayload.notificationId Log.d(TAG, "Showing incoming call notification for VoIP call from: $caller") @@ -217,31 +210,21 @@ class VoipNotification(private val context: Context) { // Create full-screen intent to IncomingCallActivity val fullScreenIntent = Intent(context, IncomingCallActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK - putExtra("callId", callId) - putExtra("callUUID", callUUID) - putExtra("caller", caller) - putExtra("host", voipPayload.host ?: "") + putExtras(voipPayload.toBundle()) } val fullScreenPendingIntent = createPendingIntent(notificationId, fullScreenIntent) // Create Accept action val acceptIntent = Intent(context, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP - putExtra("voipAction", true) - putExtra("event", "accept") - putExtra("callId", callId) - putExtra("callUUID", callUUID) - putExtra("caller", caller) - putExtra("host", voipPayload.host ?: "") - putExtra("notificationId", notificationId) + putExtras(voipPayload.toBundle()) } - val acceptPendingIntent = createPendingIntent(notificationId + 1, acceptIntent) + val acceptPendingIntent = createPendingIntent(notificationId + 1, acceptIntent) // Create Decline action val declineIntent = Intent(context, DeclineReceiver::class.java).apply { action = ACTION_DECLINE - putExtra("callUUID", callUUID) - putExtra("host", voipPayload.host ?: "") + putExtras(voipPayload.toBundle()) } val declinePendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { PendingIntent.getBroadcast( diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt index 56c77eb7c14..d1ffa2e53d7 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt @@ -1,24 +1,76 @@ package chat.rocket.reactnative.voip +import android.os.Bundle import com.google.gson.annotations.SerializedName +import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.WritableMap +import chat.rocket.reactnative.utils.CallIdUUID +import android.util.Log data class VoipPayload( @SerializedName("callId") - val callId: String?, + val callId: String, @SerializedName("caller") - val caller: String?, + val caller: String, @SerializedName("host") - val host: String?, + val host: String, @SerializedName("type") - val type: String? + val type: String ) { - /** - * Checks if this payload represents a VoIP incoming call. - */ + val notificationId: Int = callId.hashCode() + val callUUID: String = CallIdUUID.generateUUIDv5(callId) + fun isVoipIncomingCall(): Boolean { - return type == "incoming_call" && !callId.isNullOrEmpty() + return type == "incoming_call" && callId.isNotEmpty() && caller.isNotEmpty() && host.isNotEmpty() + } + + fun toBundle(): Bundle { + return Bundle().apply { + putString("callId", callId) + putString("caller", caller) + putString("host", host) + putString("type", type) + putString("callUUID", callUUID) + putInt("notificationId", notificationId) + // Useful flag for MainActivity to know it's handling a VoIP action + putBoolean("voipAction", true) + } + } + + fun toWritableMap(): WritableMap { + return Arguments.createMap().apply { + putString("callId", callId) + putString("caller", caller) + putString("host", host) + putString("type", type) + putString("callUUID", callUUID) + putInt("notificationId", notificationId) + } + } + + companion object { + fun fromMap(data: Map<String, String>): VoipPayload? { + Log.d("RocketChat.VoipPayload", "Parsing VoIP payload from map: $data") + val type = data["type"] ?: return null + val callId = data["callId"] ?: return null + val caller = data["caller"] ?: return null + val host = data["host"] ?: return null + if (type != "incoming_call") return null + + return VoipPayload(callId, caller, host, type) + } + + fun fromBundle(bundle: Bundle?): VoipPayload? { + if (bundle == null) return null + val callId = bundle.getString("callId") ?: return null + val caller = bundle.getString("caller") ?: "" + val host = bundle.getString("host") ?: "" + val type = bundle.getString("type") ?: "" + + return VoipPayload(callId, caller, host, type) + } } -} +} \ No newline at end of file diff --git a/app/definitions/Voip.ts b/app/definitions/Voip.ts index 1f13d16e56f..203d8701849 100644 --- a/app/definitions/Voip.ts +++ b/app/definitions/Voip.ts @@ -3,3 +3,11 @@ export type IceServer = { username?: string; credential?: string; }; + +export interface VoipPayload { + readonly callId: string; + readonly caller: string; + readonly host: string; + readonly type: string; + readonly callUUID: string; +} diff --git a/app/lib/native/NativeVoip.android.ts b/app/lib/native/NativeVoip.android.ts index da2c3081bef..7c00e154986 100644 --- a/app/lib/native/NativeVoip.android.ts +++ b/app/lib/native/NativeVoip.android.ts @@ -2,7 +2,7 @@ import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { - getPendingVoipCall(): string | null; + getPendingVoipCall(): Object | null; clearPendingVoipCall(): void; } diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index e8c0d29227b..cf62dee6bee 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -9,15 +9,17 @@ import { voipCallOpen } from '../../../actions/deepLinking'; import { setVoipPushToken } from './pushTokenAux'; import { useCallStore } from './useCallStore'; import { mediaSessionInstance } from './MediaSessionInstance'; +import type { VoipPayload } from '../../../definitions/Voip'; +import type { Spec as NativeVoipSpec } from '../../native/NativeVoip.android'; -let NativeVoipModule: any; +let NativeVoipModule: NativeVoipSpec | null = null; if (!isIOS) { NativeVoipModule = require('../../native/NativeVoip.android').default; } else { NativeVoipModule = null; } -// Store VoIP push data temporarily (iOS only - Android uses native storage) +// Store VoIP push data temporarily (iOS only) let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; /** @@ -30,7 +32,7 @@ export const getInitialEvents = (): Promise<boolean> => { if (isIOS) { return getInitialEventsIOS(); } - return getInitialEventsAndroid(); + return Promise.resolve(getInitialEventsAndroid()); }; /** @@ -43,24 +45,20 @@ export const setupVoipEventListeners = (): (() => void) => { } const subscriptions = [ - DeviceEventEmitter.addListener('VoipCallAction', async (dataJson: string) => { + DeviceEventEmitter.addListener('VoipCallAccepted', async (data: VoipPayload) => { try { - const data = JSON.parse(dataJson); console.log('[VoIP][Android] Call action event:', data); - NativeVoipModule.clearPendingVoipCall(); - - if (data.event === 'accept') { - useCallStore.getState().setCallUUID(data.callUUID); - // TODO: how to make sure the call comes from the same workspace? dispatch is just a saga trigger - store.dispatch( - voipCallOpen({ - callId: data.callId, - callUUID: data.callUUID, - host: data.host - }) - ); - await mediaSessionInstance.answerCall(data.callUUID); - } + NativeVoipModule?.clearPendingVoipCall(); + useCallStore.getState().setCallUUID(data.callUUID); + // TODO: how to make sure the call comes from the same workspace? dispatch is just a saga trigger + store.dispatch( + voipCallOpen({ + callId: data.callId, + callUUID: data.callUUID, + host: data.host + }) + ); + await mediaSessionInstance.answerCall(data.callUUID); } catch (error) { console.error('[VoIP][Android] Error handling call action event:', error); } @@ -171,38 +169,21 @@ const getInitialEventsIOS = async (): Promise<boolean> => { /** * Android-specific implementation using native module to retrieve VoIP call data */ -const getInitialEventsAndroid = async (): Promise<boolean> => { +const getInitialEventsAndroid = (): boolean => { try { - // Check for pending VoIP call from native module if (!NativeVoipModule) { console.log('[VoIP][Android] Native VoIP module not available'); return false; } - const pendingCallJson = NativeVoipModule.getPendingVoipCall(); - if (!pendingCallJson) { + const pendingCall = NativeVoipModule.getPendingVoipCall() as VoipPayload; + if (!pendingCall) { console.log('[VoIP][Android] No pending VoIP call'); return false; } NativeVoipModule.clearPendingVoipCall(); - console.log('[VoIP][Android] Found pending VoIP call:', pendingCallJson); - - const pendingCall = JSON.parse(pendingCallJson) as { - notificationType: string; - callId: string; - callUUID: string; - host: string; - event: string; - }; - - // Only handle 'accept' events - if (pendingCall.event !== 'accept') { - console.log('[VoIP][Android] Pending call event is not accept:', pendingCall.event); - return false; - } - if (!pendingCall.callId || !pendingCall.host) { console.log('[VoIP][Android] Missing required call data'); return false; From c936ae9e6b860a8110df6a5d6fe7616f7d81eb42 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Fri, 30 Jan 2026 11:21:26 -0300 Subject: [PATCH 40/61] Migrate react-native-voip-push-notifications to VoipModule --- .../rocket/reactnative/voip/NativeVoipSpec.kt | 22 ++ .../rocket/reactnative/voip/VoipModule.kt | 30 ++ app/lib/native/NativeVoip.android.ts | 9 - app/lib/native/NativeVoip.ts | 37 +++ app/lib/services/restApi.ts | 15 +- app/lib/services/voip/getInitialEvents.ts | 217 +++++++------ ios/AppDelegate.swift | 7 +- ios/Libraries/VoipModule.mm | 117 +++++++ ios/Libraries/VoipService.swift | 216 +++++++++++++ ios/Podfile.lock | 10 +- ios/RocketChatRN-Bridging-Header.h | 1 - ios/RocketChatRN.xcodeproj/project.pbxproj | 294 +++++++++--------- package.json | 5 +- yarn.lock | 5 - 14 files changed, 698 insertions(+), 287 deletions(-) delete mode 100644 app/lib/native/NativeVoip.android.ts create mode 100644 app/lib/native/NativeVoip.ts create mode 100644 ios/Libraries/VoipModule.mm create mode 100644 ios/Libraries/VoipService.swift diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt index 79ea12dd389..0c3f5bb41e2 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt @@ -15,9 +15,31 @@ abstract class NativeVoipSpec(reactContext: ReactApplicationContext) : override fun getName(): String = NAME + /** + * Registers for VoIP push token. + * iOS: Triggers PushKit registration. + * Android: No-op (uses FCM for push notifications). + */ + @ReactMethod + abstract fun registerVoipToken() + @ReactMethod(isBlockingSynchronousMethod = true) abstract fun getPendingVoipCall(): WritableMap? @ReactMethod abstract fun clearPendingVoipCall() + + /** + * Required for NativeEventEmitter in TurboModules. + * Called when JS starts listening to events. + */ + @ReactMethod + abstract fun addListener(eventName: String) + + /** + * Required for NativeEventEmitter in TurboModules. + * Called when JS stops listening to events. + */ + @ReactMethod + abstract fun removeListeners(count: Double) } diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt index 03859540c49..8eb2f0c137b 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt @@ -103,4 +103,34 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo override fun clearPendingVoipCall() { clearPendingVoipCallInternal() } + + /** + * Registers for VoIP push token. + * No-op on Android - uses FCM for push notifications. + */ + @ReactMethod + override fun registerVoipToken() { + // No-op on Android - FCM handles push notifications + Log.d(TAG, "registerVoipToken called (no-op on Android)") + } + + /** + * Required for NativeEventEmitter in TurboModules. + * Called when JS starts listening to events. + */ + @ReactMethod + override fun addListener(eventName: String) { + // Keep track of listeners if needed + Log.d(TAG, "addListener: $eventName") + } + + /** + * Required for NativeEventEmitter in TurboModules. + * Called when JS stops listening to events. + */ + @ReactMethod + override fun removeListeners(count: Double) { + // Remove listeners if needed + Log.d(TAG, "removeListeners: $count") + } } diff --git a/app/lib/native/NativeVoip.android.ts b/app/lib/native/NativeVoip.android.ts deleted file mode 100644 index 7c00e154986..00000000000 --- a/app/lib/native/NativeVoip.android.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { TurboModule } from 'react-native'; -import { TurboModuleRegistry } from 'react-native'; - -export interface Spec extends TurboModule { - getPendingVoipCall(): Object | null; - clearPendingVoipCall(): void; -} - -export default TurboModuleRegistry.getEnforcing<Spec>('VoipModule'); diff --git a/app/lib/native/NativeVoip.ts b/app/lib/native/NativeVoip.ts new file mode 100644 index 00000000000..115cad31c15 --- /dev/null +++ b/app/lib/native/NativeVoip.ts @@ -0,0 +1,37 @@ +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; + +export interface Spec extends TurboModule { + /** + * Registers for VoIP push notifications via PushKit. + * iOS: Triggers the system to request a VoIP push token. + * Android: No-op (uses FCM for push notifications). + */ + registerVoipToken(): void; + + /** + * Gets any pending VoIP call data. + * Returns null if no pending call or if data is older than 5 minutes. + * Clears the pending data after retrieval. + */ + getPendingVoipCall(): Object | null; + + /** + * Clears any pending VoIP call data. + */ + clearPendingVoipCall(): void; + + /** + * Required for NativeEventEmitter in TurboModules. + * Called when JS starts listening to events. + */ + addListener(eventName: string): void; + + /** + * Required for NativeEventEmitter in TurboModules. + * Called when JS stops listening to events. + */ + removeListeners(count: number): void; +} + +export default TurboModuleRegistry.getEnforcing<Spec>('VoipModule'); diff --git a/app/lib/services/restApi.ts b/app/lib/services/restApi.ts index 0a949dab6bc..9f543c0bbbf 100644 --- a/app/lib/services/restApi.ts +++ b/app/lib/services/restApi.ts @@ -1011,12 +1011,15 @@ export const registerPushToken = () => }; try { if (isIOS) { - // TODO: this is temp only for VoIP push token - await sdk.post('push.token', { - type: 'gcm', - value: getVoipPushToken() || '', - appName: getBundleId - }); + const voipToken = getVoipPushToken(); + if (voipToken) { + // TODO: this is temp only for VoIP push token + await sdk.post('push.token', { + type: 'gcm', + value: voipToken, + appName: getBundleId + }); + } } // RC 0.60.0 diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index cf62dee6bee..1a80b0f695a 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -1,32 +1,21 @@ import RNCallKeep from 'react-native-callkeep'; -import VoipPushNotification from 'react-native-voip-push-notification'; -import { DeviceEventEmitter } from 'react-native'; +import { DeviceEventEmitter, NativeEventEmitter } from 'react-native'; import { isIOS } from '../../methods/helpers'; -import CallIdUUIDModule from '../../native/NativeCallIdUUID'; import store from '../../store'; import { voipCallOpen } from '../../../actions/deepLinking'; import { setVoipPushToken } from './pushTokenAux'; import { useCallStore } from './useCallStore'; import { mediaSessionInstance } from './MediaSessionInstance'; import type { VoipPayload } from '../../../definitions/Voip'; -import type { Spec as NativeVoipSpec } from '../../native/NativeVoip.android'; - -let NativeVoipModule: NativeVoipSpec | null = null; -if (!isIOS) { - NativeVoipModule = require('../../native/NativeVoip.android').default; -} else { - NativeVoipModule = null; -} - -// Store VoIP push data temporarily (iOS only) -let voipPushData: { callId: string; caller: string; host?: string; callUUID: string } | null = null; +import NativeVoipModule from '../../native/NativeVoip'; /** * Handles initial VoIP events on app startup. * - * iOS: Uses VoipPushNotification to capture VoIP push data and CallKeep events - * Android: Uses native module to retrieve pending VoIP call data from Intent/SharedPreferences + * Both platforms now use native module to retrieve pending VoIP call data. + * iOS: VoipModule stores pending call data from PushKit callbacks + * Android: VoipModule stores pending call data from Intent/SharedPreferences */ export const getInitialEvents = (): Promise<boolean> => { if (isIOS) { @@ -36,34 +25,66 @@ export const getInitialEvents = (): Promise<boolean> => { }; /** - * Sets up listeners for Android VoIP call events from native side. + * Sets up listeners for VoIP call events from native side. * @returns Cleanup function to remove listeners */ export const setupVoipEventListeners = (): (() => void) => { + const subscriptions: { remove: () => void }[] = []; + const platform = isIOS ? 'iOS' : 'Android'; + if (isIOS) { - return () => {}; - } + // iOS: Use NativeEventEmitter with direct TurboModule import + const voipModuleEmitter = new NativeEventEmitter(NativeVoipModule); + + // Listen for VoIP push token registration + subscriptions.push( + voipModuleEmitter.addListener('VoipPushTokenRegistered', (token: string) => { + console.log(`[VoIP][${platform}] Registered VoIP push token:`, token); + setVoipPushToken(token); + }) + ); - const subscriptions = [ - DeviceEventEmitter.addListener('VoipCallAccepted', async (data: VoipPayload) => { - try { - console.log('[VoIP][Android] Call action event:', data); - NativeVoipModule?.clearPendingVoipCall(); - useCallStore.getState().setCallUUID(data.callUUID); - // TODO: how to make sure the call comes from the same workspace? dispatch is just a saga trigger - store.dispatch( - voipCallOpen({ - callId: data.callId, - callUUID: data.callUUID, - host: data.host - }) - ); - await mediaSessionInstance.answerCall(data.callUUID); - } catch (error) { - console.error('[VoIP][Android] Error handling call action event:', error); - } - }) - ]; + // Listen for VoIP call events (when app is already running) + subscriptions.push( + voipModuleEmitter.addListener('VoipCallAccepted', async (data: VoipPayload) => { + try { + console.log(`[VoIP][${platform}] Call action event:`, data); + NativeVoipModule.clearPendingVoipCall(); + useCallStore.getState().setCallUUID(data.callUUID); + store.dispatch( + voipCallOpen({ + callId: data.callId, + callUUID: data.callUUID, + host: data.host + }) + ); + } catch (error) { + console.error(`[VoIP][${platform}] Error handling call action event:`, error); + } + }) + ); + } else { + // Android: Use DeviceEventEmitter + subscriptions.push( + DeviceEventEmitter.addListener('VoipCallAccepted', async (data: VoipPayload) => { + try { + console.log(`[VoIP][${platform}] Call action event:`, data); + NativeVoipModule.clearPendingVoipCall(); + useCallStore.getState().setCallUUID(data.callUUID); + store.dispatch( + voipCallOpen({ + callId: data.callId, + callUUID: data.callUUID, + host: data.host + }) + ); + await mediaSessionInstance.answerCall(data.callUUID); + } catch (error) { + console.error(`[VoIP][${platform}] Error handling call action event:`, error); + } + }) + ); + } // Return cleanup function return () => { @@ -72,94 +93,73 @@ export const setupVoipEventListeners = (): (() => void) => { }; /** - * iOS-specific implementation using VoipPushNotification and CallKeep + * iOS-specific implementation using native VoipModule and CallKeep. + * The native module stores pending VoIP call data from PushKit callbacks. + * CallKeep is still used for the CallKit UI integration. */ const getInitialEventsIOS = async (): Promise<boolean> => { try { - VoipPushNotification.addEventListener('register', (token: string) => { - console.log('[VoIP][iOS] Registered VoIP push token:', token); - setVoipPushToken(token); - }); - - VoipPushNotification.addEventListener('didLoadWithEvents', events => { - if (!events || !Array.isArray(events)) return; - - for (const event of events) { - const { name, data } = event; - - if (name === VoipPushNotification.RNVoipPushRemoteNotificationReceivedEvent) { - const voipData = data as { callId?: string; caller?: string; host?: string }; - const { callId, caller, host } = voipData; - if (callId) { - const callUUID = CallIdUUIDModule.toUUID(callId); - voipPushData = { callId, caller: caller || 'Unknown', host, callUUID }; - console.log('[VoIP][iOS] Stored VoIP push data:', voipPushData); - } - } - if (name === VoipPushNotification.RNVoipPushRemoteNotificationsRegisteredEvent) { - setVoipPushToken(data); - console.log('[VoIP][iOS] Registered VoIP push token:', data); - } - } - }); + // Get pending VoIP call from native module (stored by AppDelegate when VoIP push received) + const pendingCall = NativeVoipModule.getPendingVoipCall() as VoipPayload | null; - RNCallKeep.addEventListener('answerCall', ({ callUUID }) => { - console.log('[VoIP][iOS] Live answerCall event received:', callUUID); + if (!pendingCall) { + console.log('[VoIP][iOS] No pending VoIP call from native module'); - if (voipPushData && voipPushData.callUUID.toLowerCase() === callUUID.toLowerCase()) { - console.log('[VoIP][iOS] Matched live answer to VoIP call'); - if (voipPushData.host) { - store.dispatch( - voipCallOpen({ - callId: voipPushData.callId, - callUUID: voipPushData.callUUID, - host: voipPushData.host - }) - ); - console.log('[VoIP][iOS] Dispatched voipCallOpen action from live listener'); - } - } else { - console.log('[VoIP][iOS] Live answer UUID mismatch. Answer:', callUUID, 'VoIP:', voipPushData?.callUUID); + // Still check CallKeep initial events for any answer actions + const initialEvents = await RNCallKeep.getInitialEvents(); + if (initialEvents.length > 0) { + console.log('[VoIP][iOS] Found CallKeep initial events but no pending call data'); + RNCallKeep.clearInitialEvents(); } - }); + return false; + } + + console.log('[VoIP][iOS] Found pending VoIP call:', pendingCall); + + if (!pendingCall.callId || !pendingCall.host) { + console.log('[VoIP][iOS] Missing required call data'); + NativeVoipModule.clearPendingVoipCall(); + return false; + } + + // Check if user already answered the call via CallKit const initialEvents = await RNCallKeep.getInitialEvents(); - console.log('[VoIP][iOS] Initial events:', JSON.stringify(initialEvents, null, 2)); + console.log('[VoIP][iOS] CallKeep initial events:', JSON.stringify(initialEvents, null, 2)); + let wasAnswered = false; for (const event of initialEvents) { const { name, data } = event; - if (name === 'RNCallKeepPerformAnswerCallAction') { const { callUUID } = data; - console.log('[VoIP][iOS] Found ANSWER event:', callUUID); - - if (voipPushData && voipPushData.callUUID.toLowerCase() === callUUID.toLowerCase()) { - console.log('[VoIP][iOS] Matched answer to VoIP call:', voipPushData); - - if (voipPushData.host) { - store.dispatch( - voipCallOpen({ - callId: voipPushData.callId, - callUUID: voipPushData.callUUID, - host: voipPushData.host - }) - ); - console.log('[VoIP][iOS] Dispatched voipCallOpen action'); - - RNCallKeep.clearInitialEvents(); - return true; - } - } else { - console.log('[VoIP][iOS] Answer event UUID does not match VoIP push UUID'); + if (pendingCall.callUUID.toLowerCase() === callUUID.toLowerCase()) { + wasAnswered = true; + console.log('[VoIP][iOS] Call was already answered via CallKit'); + break; } } } + if (wasAnswered) { + useCallStore.getState().setCallUUID(pendingCall.callUUID); + + store.dispatch( + voipCallOpen({ + callId: pendingCall.callId, + callUUID: pendingCall.callUUID, + host: pendingCall.host + }) + ); + console.log('[VoIP][iOS] Dispatched voipCallOpen action'); + } + + // Clear the data + NativeVoipModule.clearPendingVoipCall(); if (initialEvents.length > 0) { RNCallKeep.clearInitialEvents(); } - return false; + return wasAnswered; } catch (error) { console.error('[VoIP][iOS] Error:', error); return false; @@ -171,11 +171,6 @@ const getInitialEventsIOS = async (): Promise<boolean> => { */ const getInitialEventsAndroid = (): boolean => { try { - if (!NativeVoipModule) { - console.log('[VoIP][Android] Native VoIP module not available'); - return false; - } - const pendingCall = NativeVoipModule.getPendingVoipCall() as VoipPayload; if (!pendingCall) { console.log('[VoIP][Android] No pending VoIP call'); diff --git a/ios/AppDelegate.swift b/ios/AppDelegate.swift index 2549712d1b1..3b3d464809d 100644 --- a/ios/AppDelegate.swift +++ b/ios/AppDelegate.swift @@ -26,7 +26,7 @@ public class AppDelegate: ExpoAppDelegate { FirebaseApp.configure() Bugsnag.start() ReplyNotification.configure() - RNVoipPushNotificationManager.voipRegistration() + VoipService.voipRegistration() RNCallKeep.setup(["appName": "Rocket.Chat"]) let delegate = ReactNativeDelegate() @@ -101,7 +101,7 @@ extension AppDelegate: PKPushRegistryDelegate { // Handle updated push credentials public func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { // Register VoIP push token (a property of PKPushCredentials) with server - RNVoipPushNotificationManager.didUpdate(credentials, forType: type.rawValue) + VoipService.didUpdatePushCredentials(credentials, forType: type.rawValue) } public func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { @@ -123,7 +123,8 @@ extension AppDelegate: PKPushRegistryDelegate { // Convert callId to deterministic UUID v5 for CallKit let callIdUUID = CallIdUUID.generateUUIDv5(from: callId) - RNVoipPushNotificationManager.didReceiveIncomingPush(with: payload, forType: type.rawValue) + // Store pending call data in our native module (replaces RNVoipPushNotificationManager) + VoipService.didReceiveIncomingPush(with: payload, forType: type.rawValue) RNCallKeep.reportNewIncomingCall( callIdUUID, diff --git a/ios/Libraries/VoipModule.mm b/ios/Libraries/VoipModule.mm new file mode 100644 index 00000000000..3b6aa5594a4 --- /dev/null +++ b/ios/Libraries/VoipModule.mm @@ -0,0 +1,117 @@ +#import <React/RCTBridgeModule.h> +#import <React/RCTEventEmitter.h> +#import <PushKit/PushKit.h> + +#import <RocketChatSpecs/RocketChatSpecs.h> + +@interface VoipModule : RCTEventEmitter <NativeVoipSpec> +@end + +@interface VoipService : NSObject ++ (void)voipRegistration; ++ (NSDictionary * _Nullable)getPendingVoipCall; ++ (void)clearPendingVoipCall; +@end + +@implementation VoipModule { + BOOL _hasListeners; + NSMutableArray *_delayedEvents; +} + +RCT_EXPORT_MODULE() + ++ (BOOL)requiresMainQueueSetup { + return YES; +} + +- (instancetype)init { + if (self = [super init]) { + _hasListeners = NO; + _delayedEvents = [NSMutableArray array]; + } + return self; +} + +- (NSArray<NSString *> *)supportedEvents { + return @[@"VoipCallAccepted", @"VoipPushTokenRegistered"]; +} + +- (void)startObserving { + _hasListeners = YES; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleVoipCallAccepted:) + name:@"VoipCallAccepted" + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleVoipTokenRegistered:) + name:@"VoipPushTokenRegistered" + object:nil]; + + // Send any delayed events + for (NSDictionary *event in _delayedEvents) { + NSString *name = event[@"name"]; + id data = event[@"data"]; + if (name && data) { + [self sendEventWithName:name body:data]; + } + } + [_delayedEvents removeAllObjects]; +} + +- (void)stopObserving { + _hasListeners = NO; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +// Handler for Call Accepted +- (void)handleVoipCallAccepted:(NSNotification *)notification { + [self sendEventWrapper:@"VoipCallAccepted" body:notification.userInfo]; +} + +// Handler for Token Registration +- (void)handleVoipTokenRegistered:(NSNotification *)notification { + [self sendEventWrapper:@"VoipPushTokenRegistered" body:notification.userInfo]; +} + +- (void)sendEventWrapper:(NSString *)name body:(id)body { + if (_hasListeners) { + [self sendEventWithName:name body:body]; + } else { + [_delayedEvents addObject:@{@"name": name, @"data": body ?: [NSNull null]}]; + } +} + +#pragma mark - NativeVoipSpec methods + +- (void)registerVoipToken { + dispatch_async(dispatch_get_main_queue(), ^{ + [VoipService voipRegistration]; + }); +} + +- (NSDictionary * _Nullable)getPendingVoipCall { + return [VoipService getPendingVoipCall]; +} + +- (void)clearPendingVoipCall { + [VoipService clearPendingVoipCall]; +} + +- (void)addListener:(NSString *)eventName { + // Required for NativeEventEmitter - starts observing +} + +- (void)removeListeners:(double)count { + // Required for NativeEventEmitter - stops observing +} + +#pragma mark - TurboModule + +- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params { + return std::make_shared<facebook::react::NativeVoipSpecJSI>(params); +} + +@end diff --git a/ios/Libraries/VoipService.swift b/ios/Libraries/VoipService.swift new file mode 100644 index 00000000000..b7d1a123f77 --- /dev/null +++ b/ios/Libraries/VoipService.swift @@ -0,0 +1,216 @@ +import Foundation +import PushKit + +/** + * VoipModuleSwift - Swift implementation for VoIP push notifications and pending call data. + * This class provides static methods called by VoipModule.mm (the TurboModule bridge). + * + * This module: + * - Manages PushKit VoIP registration + * - Tracks VoIP push tokens + * - Stores pending VoIP call data for retrieval by JavaScript + */ +@objc(VoipService) +public final class VoipService: NSObject { + + // MARK: - Constants + + private static let TAG = "RocketChat.VoipModule" + + // MARK: - Static Properties + + private static var pendingVoipCallData: VoipPayload? + private static var pendingVoipCallTimestamp: TimeInterval = 0 + private static var isVoipRegistered = false + private static var lastVoipToken: String = "" + private static var voipRegistry: PKPushRegistry? + + // MARK: - Static Methods (Called from VoipModule.mm and AppDelegate) + + /// Registers for VoIP push notifications via PushKit + @objc + public static func voipRegistration() { + if isVoipRegistered { + #if DEBUG + print("[\(TAG)] voipRegistration already registered. Returning lastVoipToken: \(lastVoipToken)") + #endif + return + } + + isVoipRegistered = true + #if DEBUG + print("[\(TAG)] voipRegistration starting") + #endif + + DispatchQueue.main.async { + let registry = PKPushRegistry(queue: .main) + registry.delegate = UIApplication.shared.delegate as? PKPushRegistryDelegate + registry.desiredPushTypes = [.voIP] + voipRegistry = registry + } + } + + /// Called from AppDelegate when push credentials are updated + @objc + public static func didUpdatePushCredentials(_ credentials: PKPushCredentials, forType type: String) { + #if DEBUG + print("[\(TAG)] didUpdatePushCredentials type: \(type)") + #endif + + let tokenLength = credentials.token.count + if tokenLength == 0 { + return + } + + // Convert token data to hex string + let token = credentials.token.map { String(format: "%02x", $0) }.joined() + lastVoipToken = token + + #if DEBUG + print("[\(TAG)] VoIP token: \(token)") + #endif + + // Token will be emitted to JS via the ObjC++ bridge's event emitter + NotificationCenter.default.post( + name: NSNotification.Name("VoipPushTokenRegistered"), + object: nil, + userInfo: ["token": token] + ) + } + + /// Called from AppDelegate when a VoIP push is received + @objc + public static func didReceiveIncomingPush(with payload: PKPushPayload, forType type: String) { + #if DEBUG + print("[\(TAG)] didReceiveIncomingPush payload: \(payload.dictionaryPayload)") + #endif + + guard let voipPayload = VoipPayload.fromDictionary(payload.dictionaryPayload) else { + #if DEBUG + print("[\(TAG)] Failed to parse VoIP payload") + #endif + return + } + + storePendingVoipCall(voipPayload) + } + + /// Stores VoIP call data for JS to retrieve. + @objc + public static func storePendingVoipCall(_ payload: VoipPayload) { + pendingVoipCallData = payload + pendingVoipCallTimestamp = Date().timeIntervalSince1970 + + #if DEBUG + print("[\(TAG)] Stored pending VoIP call: \(payload.callId)") + #endif + + // Emit event via notification (the ObjC++ bridge observes this) + NotificationCenter.default.post( + name: NSNotification.Name("VoipCallAccepted"), + object: nil, + userInfo: payload.toDictionary() + ) + } + + /// Gets any pending VoIP call data. Returns nil if no pending call. + @objc + public static func getPendingVoipCall() -> [String: Any]? { + guard let data = pendingVoipCallData else { + return nil + } + + // Check if data is older than 5 minutes + let now = Date().timeIntervalSince1970 + if now - pendingVoipCallTimestamp > 5 * 60 { + clearPendingVoipCallInternal() + return nil + } + + let result = data.toDictionary() + clearPendingVoipCallInternal() + + return result + } + + /// Clears any pending VoIP call data + @objc + public static func clearPendingVoipCall() { + clearPendingVoipCallInternal() + } + + /// Clears pending VoIP call data (internal) + private static func clearPendingVoipCallInternal() { + pendingVoipCallData = nil + pendingVoipCallTimestamp = 0 + #if DEBUG + print("[\(TAG)] Cleared pending VoIP call data") + #endif + } + + /// Returns the last registered VoIP token + @objc + public static func getLastVoipToken() -> String { + return lastVoipToken + } +} + +// MARK: - VoipPayload + +/// Data structure for VoIP call payload +@objc(VoipPayload) +public class VoipPayload: NSObject { + @objc public let callId: String + @objc public let caller: String + @objc public let host: String + @objc public let type: String + + @objc public var notificationId: Int { + return callId.hashValue + } + + @objc public var callUUID: String { + return CallIdUUID.generateUUIDv5(from: callId) + } + + @objc + public init(callId: String, caller: String, host: String, type: String) { + self.callId = callId + self.caller = caller + self.host = host + self.type = type + super.init() + } + + @objc + public func isVoipIncomingCall() -> Bool { + return type == "incoming_call" && !callId.isEmpty && !caller.isEmpty && !host.isEmpty + } + + @objc + public func toDictionary() -> [String: Any] { + return [ + "callId": callId, + "caller": caller, + "host": host, + "type": type, + "callUUID": callUUID, + "notificationId": notificationId + ] + } + + @objc + public static func fromDictionary(_ dict: [AnyHashable: Any]) -> VoipPayload? { + guard let type = dict["type"] as? String, + let callId = dict["callId"] as? String, + type == "incoming_call", + !callId.isEmpty else { + return nil + } + + let caller = dict["caller"] as? String ?? "" + let host = dict["host"] as? String ?? "" + + return VoipPayload(callId: callId, caller: caller, host: host, type: type) + } +} diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1fe52e8bac8..974116a738f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2612,8 +2612,6 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - RNVoipPushNotification (3.3.3): - - React-Core - SDWebImage (5.21.0): - SDWebImage/Core (= 5.21.0) - SDWebImage/Core (5.21.0) @@ -2764,7 +2762,6 @@ DEPENDENCIES: - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) - RNSVG (from `../node_modules/react-native-svg`) - - RNVoipPushNotification (from `../node_modules/react-native-voip-push-notification`) - "simdjson (from `../node_modules/@nozbe/simdjson`)" - "WatermelonDB (from `../node_modules/@nozbe/watermelondb`)" - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -3046,8 +3043,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-screens" RNSVG: :path: "../node_modules/react-native-svg" - RNVoipPushNotification: - :path: "../node_modules/react-native-voip-push-notification" simdjson: :path: "../node_modules/@nozbe/simdjson" WatermelonDB: @@ -3177,7 +3172,7 @@ SPEC CHECKSUMS: React-timing: 2d07431f1c1203c5b0aaa6dc7b5f503704519218 React-utils: 67cf7dcfc18aa4c56bec19e11886033bb057d9fa ReactAppDependencyProvider: bf62814e0fde923f73fc64b7e82d76c63c284da9 - ReactCodegen: 2f22969ab54e1aace69c9b5d3085e0a3b405a9a6 + ReactCodegen: 5c6b68a6cfdfce6b69a8b12d2eb93e1117d96113 ReactCommon: 177fca841e97b2c0e288e86097b8be04c6e7ae36 RNBootSplash: 1280eeb18d887de0a45bb4923d4fc56f25c8b99c RNCallKeep: 1930a01d8caf48f018be4f2db0c9f03405c2f977 @@ -3198,7 +3193,6 @@ SPEC CHECKSUMS: RNReanimated: f52ccd5ceea2bae48d7421eec89b3f0c10d7b642 RNScreens: b13e4c45f0406f33986a39c0d8da0324bff94435 RNSVG: 680e961f640e381aab730a04b2371969686ed9f7 - RNVoipPushNotification: 4998fe6724d421da616dca765da7dc421ff54c4e SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90 SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c @@ -3210,6 +3204,6 @@ SPEC CHECKSUMS: Yoga: dfabf1234ccd5ac41d1b1d43179f024366ae9831 ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5 -PODFILE CHECKSUM: 5d562fbb33c24fb71c5fe4ab560e854f7a165148 +PODFILE CHECKSUM: 199f6fbbe6fb415c822cca992e6152000ac55b3e COCOAPODS: 1.15.2 diff --git a/ios/RocketChatRN-Bridging-Header.h b/ios/RocketChatRN-Bridging-Header.h index 3e55fda6b58..a4434b7fd77 100644 --- a/ios/RocketChatRN-Bridging-Header.h +++ b/ios/RocketChatRN-Bridging-Header.h @@ -2,7 +2,6 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // -#import <RNVoipPushNotification/RNVoipPushNotificationManager.h> #import <RNCallKeep/RNCallKeep.h> #import "SecureStorage.h" #import "MMKVKeyManager.h" diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index 9c14e1eabd3..a87645d11ae 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -273,11 +273,11 @@ 1EFEB5982493B6640072EDC0 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EFEB5972493B6640072EDC0 /* NotificationService.swift */; }; 1EFEB59C2493B6640072EDC0 /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 1EFEB5952493B6640072EDC0 /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 06BB44DD4855498082A744AD /* libz.tbd */; }; + 307FA80AF7CCE3A179785329 /* Pods_defaults_RocketChatRN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B8C48663583BBD95FBC7EB7 /* Pods_defaults_RocketChatRN.framework */; }; 3F56D232A9EBA1C9C749F15D /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A42CFB843397273C7EA /* SecureStorage.m */; }; 3F56D232A9EBA1C9C749F15E /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; 3F56D232A9EBA1C9C749F15F /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; 3F56D232A9EBA1C9C749F160 /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; - 48A421BADAE0581090F73A31 /* Pods_defaults_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C8B6905552E89D22ECC9A59 /* Pods_defaults_Rocket_Chat.framework */; }; 4C4C8603EF082F0A33A95522 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45D5C142B655F8EFD006792C /* ExpoModulesProvider.swift */; }; 65AD38372BFBDF4A00271B39 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */; }; 65AD38392BFBDF4A00271B39 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */; }; @@ -289,7 +289,12 @@ 66C2701B2EBBCB570062725F /* MMKVKeyManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */; }; 66C2701C2EBBCB570062725F /* MMKVKeyManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */; }; 66C2701D2EBBCB570062725F /* MMKVKeyManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */; }; + 67709318BC12F95CFE0FD019 /* Pods_defaults_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6C0223D4301331E4D2C432A /* Pods_defaults_Rocket_Chat.framework */; }; 79D8C97F8CE2EC1B6882826B /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A42CFB843397273C7EA /* SecureStorage.m */; }; + 7A0000012F1BAFA700B6B4BD /* VoipService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0000032F1BAFA700B6B4BD /* VoipService.swift */; }; + 7A0000022F1BAFA700B6B4BD /* VoipModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A0000042F1BAFA700B6B4BD /* VoipModule.mm */; }; + 7A0000052F1BAFA700B6B4BD /* VoipService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0000032F1BAFA700B6B4BD /* VoipService.swift */; }; + 7A0000062F1BAFA700B6B4BD /* VoipModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A0000042F1BAFA700B6B4BD /* VoipModule.mm */; }; 7A006F14229C83B600803143 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7A006F13229C83B600803143 /* GoogleService-Info.plist */; }; 7A0129D42C6E8EC800F84A97 /* ShareRocketChatRN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0129D22C6E8B5900F84A97 /* ShareRocketChatRN.swift */; }; 7A0129D62C6E8F0700F84A97 /* ShareRocketChatRN.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = 1EC6AD6022CBA20C00A41C61 /* ShareRocketChatRN.entitlements */; }; @@ -365,9 +370,8 @@ A2C6E2DD38F8BEE19BFB2E1D /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A42CFB843397273C7EA /* SecureStorage.m */; }; A48B46D92D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; A48B46DA2D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; - BA8D65FC401BDCF46BC4A430 /* Pods_defaults_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF1F97CD8D80023897D69A96 /* Pods_defaults_NotificationService.framework */; }; BC404914E86821389EEB543D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */; }; - CC12B307799B2349A98FFD79 /* Pods_defaults_RocketChatRN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 918F9B00E7760D7709BE6B1C /* Pods_defaults_RocketChatRN.framework */; }; + BE62F5275DDCF37207935378 /* Pods_defaults_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B914156975421F5AF8D982B /* Pods_defaults_NotificationService.framework */; }; DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA7E862283664608B3894E34 /* libWatermelonDB.a */; }; /* End PBXBuildFile section */ @@ -468,6 +472,7 @@ /* Begin PBXFileReference section */ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file; path = main.jsbundle; sourceTree = "<group>"; }; 06BB44DD4855498082A744AD /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 0B914156975421F5AF8D982B /* Pods_defaults_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* Rocket.Chat Experimental.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Rocket.Chat Experimental.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RocketChatRN/Images.xcassets; sourceTree = "<group>"; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RocketChatRN/Info.plist; sourceTree = "<group>"; }; @@ -615,13 +620,16 @@ 1EFEB5992493B6640072EDC0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 1EFEB5A12493B67D0072EDC0 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = "<group>"; }; 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-Rocket.Chat/ExpoModulesProvider.swift"; sourceTree = "<group>"; }; + 3B8C48663583BBD95FBC7EB7 /* Pods_defaults_RocketChatRN.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_RocketChatRN.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 45D5C142B655F8EFD006792C /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-RocketChatRN/ExpoModulesProvider.swift"; sourceTree = "<group>"; }; - 544428BFD00E045285A62CD7 /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; }; + 57DFA6D849BD9281E6E50D40 /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = "<group>"; }; 60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = RocketChatRN.entitlements; path = RocketChatRN/RocketChatRN.entitlements; sourceTree = "<group>"; }; 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 65B9A7192AFC24190088956F /* ringtone.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ringtone.mp3; sourceTree = "<group>"; }; 66C270192EBBCB570062725F /* MMKVKeyManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMKVKeyManager.h; sourceTree = "<group>"; }; 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MMKVKeyManager.mm; sourceTree = "<group>"; }; + 7A0000032F1BAFA700B6B4BD /* VoipService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoipService.swift; sourceTree = "<group>"; }; + 7A0000042F1BAFA700B6B4BD /* VoipModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = VoipModule.mm; sourceTree = "<group>"; }; 7A006F13229C83B600803143 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; }; 7A0129D22C6E8B5900F84A97 /* ShareRocketChatRN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareRocketChatRN.swift; sourceTree = "<group>"; }; 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; }; @@ -639,21 +647,19 @@ 7ACD4853222860DE00442C55 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 7ACFE7D82DDE48760090D9BC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 7AE10C0528A59530003593CB /* Inter.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Inter.ttf; sourceTree = "<group>"; }; - 7D58F328632F3CC231D7C525 /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = "<group>"; }; - 8C31C00B0E14F40F0C0EA8DE /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = "<group>"; }; - 918F9B00E7760D7709BE6B1C /* Pods_defaults_RocketChatRN.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_RocketChatRN.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9919F040FC3472AAAB898030 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = "<group>"; }; + 7DC5F24E96CE93D8C5FFE9BF /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = "<group>"; }; + 8230DCE68AB8DE26A960AA9D /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; }; 9B215A42CFB843397273C7EA /* SecureStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = SecureStorage.m; sourceTree = "<group>"; }; 9B215A44CFB843397273C7EC /* MMKVBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MMKVBridge.mm; path = Shared/RocketChat/MMKVBridge.mm; sourceTree = "<group>"; }; - 9C8B6905552E89D22ECC9A59 /* Pods_defaults_Rocket_Chat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_Rocket_Chat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - A025A0274DA20DB65BC36CBA /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = "<group>"; }; A48B46D72D3FFBD200945489 /* A11yFlowModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = A11yFlowModule.h; sourceTree = "<group>"; }; A48B46D82D3FFBD200945489 /* A11yFlowModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = A11yFlowModule.m; sourceTree = "<group>"; }; + A9D34C919F230A78C65B84D5 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = "<group>"; }; B179038FDD7AAF285047814B /* SecureStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = SecureStorage.h; sourceTree = "<group>"; }; B37C79D9BD0742CE936B6982 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; BA7E862283664608B3894E34 /* libWatermelonDB.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libWatermelonDB.a; sourceTree = "<group>"; }; - BF1F97CD8D80023897D69A96 /* Pods_defaults_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E34E9152D963DFA1B0E08FA4 /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = "<group>"; }; + C6C0223D4301331E4D2C432A /* Pods_defaults_Rocket_Chat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_Rocket_Chat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C80C46CC53976257D922AA93 /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = "<group>"; }; + F4E678964EBBF99E850F1D6B /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -674,7 +680,7 @@ 7ACD4897222860DE00442C55 /* JavaScriptCore.framework in Frameworks */, 24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */, DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */, - CC12B307799B2349A98FFD79 /* Pods_defaults_RocketChatRN.framework in Frameworks */, + 307FA80AF7CCE3A179785329 /* Pods_defaults_RocketChatRN.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -696,7 +702,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BA8D65FC401BDCF46BC4A430 /* Pods_defaults_NotificationService.framework in Frameworks */, + BE62F5275DDCF37207935378 /* Pods_defaults_NotificationService.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -717,7 +723,7 @@ 7AAB3E3D257E6A6E00707CF6 /* JavaScriptCore.framework in Frameworks */, 7AAB3E3E257E6A6E00707CF6 /* libz.tbd in Frameworks */, 7AAB3E3F257E6A6E00707CF6 /* libWatermelonDB.a in Frameworks */, - 48A421BADAE0581090F73A31 /* Pods_defaults_Rocket_Chat.framework in Frameworks */, + 67709318BC12F95CFE0FD019 /* Pods_defaults_Rocket_Chat.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1139,6 +1145,8 @@ children = ( 7A3F4C692F1AAFA700B6B4BD /* CallIdUUID.m */, 7A3F4C6A2F1AAFA700B6B4BD /* CallIdUUID.swift */, + 7A0000042F1BAFA700B6B4BD /* VoipModule.mm */, + 7A0000032F1BAFA700B6B4BD /* VoipService.swift */, B179038FDD7AAF285047814B /* SecureStorage.h */, 9B215A42CFB843397273C7EA /* SecureStorage.m */, A48B46D72D3FFBD200945489 /* A11yFlowModule.h */, @@ -1154,12 +1162,12 @@ 7AC2B09613AA7C3FEBAC9F57 /* Pods */ = { isa = PBXGroup; children = ( - 9919F040FC3472AAAB898030 /* Pods-defaults-NotificationService.debug.xcconfig */, - E34E9152D963DFA1B0E08FA4 /* Pods-defaults-NotificationService.release.xcconfig */, - 7D58F328632F3CC231D7C525 /* Pods-defaults-Rocket.Chat.debug.xcconfig */, - A025A0274DA20DB65BC36CBA /* Pods-defaults-Rocket.Chat.release.xcconfig */, - 8C31C00B0E14F40F0C0EA8DE /* Pods-defaults-RocketChatRN.debug.xcconfig */, - 544428BFD00E045285A62CD7 /* Pods-defaults-RocketChatRN.release.xcconfig */, + A9D34C919F230A78C65B84D5 /* Pods-defaults-NotificationService.debug.xcconfig */, + 7DC5F24E96CE93D8C5FFE9BF /* Pods-defaults-NotificationService.release.xcconfig */, + C80C46CC53976257D922AA93 /* Pods-defaults-Rocket.Chat.debug.xcconfig */, + 57DFA6D849BD9281E6E50D40 /* Pods-defaults-Rocket.Chat.release.xcconfig */, + F4E678964EBBF99E850F1D6B /* Pods-defaults-RocketChatRN.debug.xcconfig */, + 8230DCE68AB8DE26A960AA9D /* Pods-defaults-RocketChatRN.release.xcconfig */, ); path = Pods; sourceTree = "<group>"; @@ -1249,9 +1257,9 @@ 7ACD4853222860DE00442C55 /* JavaScriptCore.framework */, B37C79D9BD0742CE936B6982 /* libc++.tbd */, 06BB44DD4855498082A744AD /* libz.tbd */, - BF1F97CD8D80023897D69A96 /* Pods_defaults_NotificationService.framework */, - 9C8B6905552E89D22ECC9A59 /* Pods_defaults_Rocket_Chat.framework */, - 918F9B00E7760D7709BE6B1C /* Pods_defaults_RocketChatRN.framework */, + 0B914156975421F5AF8D982B /* Pods_defaults_NotificationService.framework */, + C6C0223D4301331E4D2C432A /* Pods_defaults_Rocket_Chat.framework */, + 3B8C48663583BBD95FBC7EB7 /* Pods_defaults_RocketChatRN.framework */, ); name = Frameworks; sourceTree = "<group>"; @@ -1271,7 +1279,7 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RocketChatRN" */; buildPhases = ( - 096AE45E4AC4D5698CB36A66 /* [CP] Check Pods Manifest.lock */, + 93EF7975E0C4C603BD18F87C /* [CP] Check Pods Manifest.lock */, 06C10D4F29CD7532492AD29E /* [Expo] Configure project */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, @@ -1281,8 +1289,8 @@ 1E1EA8082326CCE300E22452 /* ShellScript */, 1ED0389C2B507B4F00C007D4 /* Embed Watch Content */, 7AAE9EB32891A0D20024F559 /* Upload source maps to Bugsnag */, - FCB7836D6121FF536E382FEB /* [CP] Embed Pods Frameworks */, - 8BE1065B81EC4F6547A622AF /* [CP] Copy Pods Resources */, + 1840C56D2D066F638B2A748B /* [CP] Embed Pods Frameworks */, + 1199CD71D36A54C2713FCD3E /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1350,12 +1358,12 @@ isa = PBXNativeTarget; buildConfigurationList = 1EFEB5A02493B6640072EDC0 /* Build configuration list for PBXNativeTarget "NotificationService" */; buildPhases = ( - 5A59078F0CE0CB05D87ADB1A /* [CP] Check Pods Manifest.lock */, + 480C35381BCFF59C9015726E /* [CP] Check Pods Manifest.lock */, 86A998705576AFA7CE938617 /* [Expo] Configure project */, 1EFEB5912493B6640072EDC0 /* Sources */, 1EFEB5922493B6640072EDC0 /* Frameworks */, 1EFEB5932493B6640072EDC0 /* Resources */, - 5F3BFF131980D9739452E956 /* [CP] Copy Pods Resources */, + 28340DD974173F56DB07A9FC /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1370,7 +1378,7 @@ isa = PBXNativeTarget; buildConfigurationList = 7AAB3E4F257E6A6E00707CF6 /* Build configuration list for PBXNativeTarget "Rocket.Chat" */; buildPhases = ( - 3C2E0F6B686705FA7C73731D /* [CP] Check Pods Manifest.lock */, + FBF64C5737C1CD5B1ECC58DC /* [CP] Check Pods Manifest.lock */, 6319FBDD06EF0030B48AD389 /* [Expo] Configure project */, 7AAB3E14257E6A6E00707CF6 /* Sources */, 7AAB3E32257E6A6E00707CF6 /* Frameworks */, @@ -1380,8 +1388,8 @@ 7A55BE3C2F1131C000D8744D /* ShellScript */, 1ED1ECE32B8699DD00F6620C /* Embed Watch Content */, 7A55BE3D2F11320C00D8744D /* Upload source maps to Bugsnag */, - CC73A3FB774BB2359530D319 /* [CP] Embed Pods Frameworks */, - 40F7A1CBB5D1EBCF84C512F5 /* [CP] Copy Pods Resources */, + 265F5F7FE4FE17B65751C48D /* [CP] Embed Pods Frameworks */, + 9C5D6D7D9D5E936CB1720CA9 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1553,7 +1561,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\"\nexport NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; + shellScript = "export EXTRA_PACKAGER_ARGS=\"--sourcemap-output $TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\"\nexport NODE_BINARY=/Users/diegomello/.nvm/versions/node/v22.14.0/bin/node\n../node_modules/react-native/scripts/react-native-xcode.sh\n"; }; 06C10D4F29CD7532492AD29E /* [Expo] Configure project */ = { isa = PBXShellScriptBuildPhase; @@ -1574,74 +1582,13 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-RocketChatRN/expo-configure-project.sh\"\n"; }; - 096AE45E4AC4D5698CB36A66 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-RocketChatRN-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 1E1EA8082326CCE300E22452 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"Target architectures: $ARCHS\"\n\nAPP_PATH=\"${TARGET_BUILD_DIR}/${WRAPPER_NAME}\"\n\nfind \"$APP_PATH\" -name '*.framework' -type d | while read -r FRAMEWORK\ndo\nFRAMEWORK_EXECUTABLE_NAME=$(defaults read \"$FRAMEWORK/Info.plist\" CFBundleExecutable)\nFRAMEWORK_EXECUTABLE_PATH=\"$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME\"\necho \"Executable is $FRAMEWORK_EXECUTABLE_PATH\"\necho $(lipo -info \"$FRAMEWORK_EXECUTABLE_PATH\")\n\nFRAMEWORK_TMP_PATH=\"$FRAMEWORK_EXECUTABLE_PATH-tmp\"\n\n# remove simulator's archs if location is not simulator's directory\ncase \"${TARGET_BUILD_DIR}\" in\n*\"iphonesimulator\")\necho \"No need to remove archs\"\n;;\n*)\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"i386\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"i386\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"i386 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"x86_64\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"x86_64\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"x86_64 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\n;;\nesac\n\necho \"Completed for executable $FRAMEWORK_EXECUTABLE_PATH\"\necho $\n\ndone\n"; - }; - 3C2E0F6B686705FA7C73731D /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-Rocket.Chat-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 40F7A1CBB5D1EBCF84C512F5 /* [CP] Copy Pods Resources */ = { + 1199CD71D36A54C2713FCD3E /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh", + "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/BugsnagReactNative/Bugsnag.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", @@ -1708,10 +1655,30 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 5A59078F0CE0CB05D87ADB1A /* [CP] Check Pods Manifest.lock */ = { + 1840C56D2D066F638B2A748B /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 1E1EA8082326CCE300E22452 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1719,21 +1686,36 @@ inputFileListPaths = ( ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "echo \"Target architectures: $ARCHS\"\n\nAPP_PATH=\"${TARGET_BUILD_DIR}/${WRAPPER_NAME}\"\n\nfind \"$APP_PATH\" -name '*.framework' -type d | while read -r FRAMEWORK\ndo\nFRAMEWORK_EXECUTABLE_NAME=$(defaults read \"$FRAMEWORK/Info.plist\" CFBundleExecutable)\nFRAMEWORK_EXECUTABLE_PATH=\"$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME\"\necho \"Executable is $FRAMEWORK_EXECUTABLE_PATH\"\necho $(lipo -info \"$FRAMEWORK_EXECUTABLE_PATH\")\n\nFRAMEWORK_TMP_PATH=\"$FRAMEWORK_EXECUTABLE_PATH-tmp\"\n\n# remove simulator's archs if location is not simulator's directory\ncase \"${TARGET_BUILD_DIR}\" in\n*\"iphonesimulator\")\necho \"No need to remove archs\"\n;;\n*)\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"i386\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"i386\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"i386 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"x86_64\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"x86_64\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"x86_64 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\n;;\nesac\n\necho \"Completed for executable $FRAMEWORK_EXECUTABLE_PATH\"\necho $\n\ndone\n"; + }; + 265F5F7FE4FE17B65751C48D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 5F3BFF131980D9739452E956 /* [CP] Copy Pods Resources */ = { + 28340DD974173F56DB07A9FC /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1809,6 +1791,28 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 480C35381BCFF59C9015726E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 6319FBDD06EF0030B48AD389 /* [Expo] Configure project */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -1900,7 +1904,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "SOURCE_MAP=\"$TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh\n"; + shellScript = "#SOURCE_MAP=\"$TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh\n"; showEnvVarsInLog = 0; }; 86A998705576AFA7CE938617 /* [Expo] Configure project */ = { @@ -1922,13 +1926,35 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-NotificationService/expo-configure-project.sh\"\n"; }; - 8BE1065B81EC4F6547A622AF /* [CP] Copy Pods Resources */ = { + 93EF7975E0C4C603BD18F87C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-defaults-RocketChatRN-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9C5D6D7D9D5E936CB1720CA9 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/BugsnagReactNative/Bugsnag.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", @@ -1995,47 +2021,29 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh\"\n"; showEnvVarsInLog = 0; }; - CC73A3FB774BB2359530D319 /* [CP] Embed Pods Frameworks */ = { + FBF64C5737C1CD5B1ECC58DC /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - FCB7836D6121FF536E382FEB /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( + inputFileListPaths = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", + "$(DERIVED_FILE_DIR)/Pods-defaults-Rocket.Chat-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -2053,6 +2061,8 @@ 66C2701B2EBBCB570062725F /* MMKVKeyManager.mm in Sources */, 7A3F4C6B2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */, 7A3F4C6C2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */, + 7A0000012F1BAFA700B6B4BD /* VoipService.swift in Sources */, + 7A0000022F1BAFA700B6B4BD /* VoipModule.mm in Sources */, 1ED00BB12513E04400A1331F /* ReplyNotification.swift in Sources */, 1E76CBC2251529560067298C /* Storage.swift in Sources */, 1E76CBD925152C8C0067298C /* Push.swift in Sources */, @@ -2329,6 +2339,8 @@ 66C2701C2EBBCB570062725F /* MMKVKeyManager.mm in Sources */, 7A3F4C6D2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */, 7A3F4C6E2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */, + 7A0000052F1BAFA700B6B4BD /* VoipService.swift in Sources */, + 7A0000062F1BAFA700B6B4BD /* VoipModule.mm in Sources */, 7AAB3E17257E6A6E00707CF6 /* ReplyNotification.swift in Sources */, 7AAB3E18257E6A6E00707CF6 /* Storage.swift in Sources */, 7AAB3E19257E6A6E00707CF6 /* Push.swift in Sources */, @@ -2429,7 +2441,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8C31C00B0E14F40F0C0EA8DE /* Pods-defaults-RocketChatRN.debug.xcconfig */; + baseConfigurationReference = F4E678964EBBF99E850F1D6B /* Pods-defaults-RocketChatRN.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2494,7 +2506,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 544428BFD00E045285A62CD7 /* Pods-defaults-RocketChatRN.release.xcconfig */; + baseConfigurationReference = 8230DCE68AB8DE26A960AA9D /* Pods-defaults-RocketChatRN.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2909,7 +2921,7 @@ }; 1EFEB59D2493B6640072EDC0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9919F040FC3472AAAB898030 /* Pods-defaults-NotificationService.debug.xcconfig */; + baseConfigurationReference = A9D34C919F230A78C65B84D5 /* Pods-defaults-NotificationService.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(EMBEDDED_CONTENT_CONTAINS_SWIFT)"; CLANG_ANALYZER_NONNULL = YES; @@ -2961,7 +2973,7 @@ }; 1EFEB59E2493B6640072EDC0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E34E9152D963DFA1B0E08FA4 /* Pods-defaults-NotificationService.release.xcconfig */; + baseConfigurationReference = 7DC5F24E96CE93D8C5FFE9BF /* Pods-defaults-NotificationService.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(EMBEDDED_CONTENT_CONTAINS_SWIFT)"; CLANG_ANALYZER_NONNULL = YES; @@ -3012,7 +3024,7 @@ }; 7AAB3E50257E6A6E00707CF6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7D58F328632F3CC231D7C525 /* Pods-defaults-Rocket.Chat.debug.xcconfig */; + baseConfigurationReference = C80C46CC53976257D922AA93 /* Pods-defaults-Rocket.Chat.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -3077,7 +3089,7 @@ }; 7AAB3E51257E6A6E00707CF6 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A025A0274DA20DB65BC36CBA /* Pods-defaults-Rocket.Chat.release.xcconfig */; + baseConfigurationReference = 57DFA6D849BD9281E6E50D40 /* Pods-defaults-Rocket.Chat.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; diff --git a/package.json b/package.json index f63e533a825..930d35be551 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,6 @@ "react-native-slowlog": "1.0.2", "react-native-svg": "^15.12.1", "react-native-url-polyfill": "2.0.0", - "react-native-voip-push-notification": "^3.3.3", "react-native-webrtc": "^124.0.7", "react-native-webview": "^13.15.0", "react-redux": "8.0.5", @@ -216,11 +215,11 @@ "node": ">=18" }, "codegenConfig": { - "name": "SSLPinning", + "name": "RocketChatSpecs", "type": "modules", "jsSrcsDir": "./app/lib/native", "android": { - "javaPackageName": "chat.rocket.reactnative.networking" + "javaPackageName": "chat.rocket.reactnative" } } } diff --git a/yarn.lock b/yarn.lock index 63894135416..ec569a30add 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12893,11 +12893,6 @@ react-native-url-polyfill@2.0.0, react-native-url-polyfill@^2.0.0: dependencies: whatwg-url-without-unicode "8.0.0-3" -react-native-voip-push-notification@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/react-native-voip-push-notification/-/react-native-voip-push-notification-3.3.3.tgz#60169cc4083fc619383ab081f330e42a995c0dfa" - integrity sha512-cyWuI9//T1IQIq4RPq0QQe0NuEwIpnE0L98H2sUH4MjFsNMD/yNE4EJzEZN4cIwfPMZaASa0gQw6B1a7VwnkMA== - react-native-webrtc@^124.0.7: version "124.0.7" resolved "https://registry.yarnpkg.com/react-native-webrtc/-/react-native-webrtc-124.0.7.tgz#f50647a8eb3fae0ef29843eb1b5fe2c4ff75a56e" From 3914562647be1e7e67318e85767292779b30f0d0 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 4 Feb 2026 10:59:05 -0300 Subject: [PATCH 41/61] Refactor VoIP module: Update package structure by moving VoipTurboPackage to the main package and removing the obsolete NativeVoipSpec class. Adjust imports in MainApplication and VoipModule to reflect these changes, enhancing code organization and maintainability. --- .../rocket/reactnative/MainApplication.kt | 2 +- .../rocket/reactnative/voip/NativeVoipSpec.kt | 45 ------------------- .../rocket/reactnative/voip/VoipModule.kt | 8 +--- .../reactnative/voip/VoipTurboPackage.kt | 4 +- 4 files changed, 5 insertions(+), 54 deletions(-) delete mode 100644 android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt index 9a6ac9dac3f..1035e46107a 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt @@ -20,7 +20,7 @@ import chat.rocket.reactnative.storage.MMKVKeyManager; import chat.rocket.reactnative.storage.SecureStoragePackage; import chat.rocket.reactnative.notification.VideoConfTurboPackage import chat.rocket.reactnative.notification.PushNotificationTurboPackage -import chat.rocket.reactnative.voip.VoipTurboPackage +import chat.rocket.reactnative.VoipTurboPackage import chat.rocket.reactnative.utils.CallIdUUIDTurboPackage /** diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt deleted file mode 100644 index 0c3f5bb41e2..00000000000 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/NativeVoipSpec.kt +++ /dev/null @@ -1,45 +0,0 @@ -package chat.rocket.reactnative.voip - -import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactContextBaseJavaModule -import com.facebook.react.bridge.ReactMethod -import com.facebook.react.turbomodule.core.interfaces.TurboModule -import com.facebook.react.bridge.WritableMap - -abstract class NativeVoipSpec(reactContext: ReactApplicationContext) : - ReactContextBaseJavaModule(reactContext), TurboModule { - - companion object { - const val NAME = "VoipModule" - } - - override fun getName(): String = NAME - - /** - * Registers for VoIP push token. - * iOS: Triggers PushKit registration. - * Android: No-op (uses FCM for push notifications). - */ - @ReactMethod - abstract fun registerVoipToken() - - @ReactMethod(isBlockingSynchronousMethod = true) - abstract fun getPendingVoipCall(): WritableMap? - - @ReactMethod - abstract fun clearPendingVoipCall() - - /** - * Required for NativeEventEmitter in TurboModules. - * Called when JS starts listening to events. - */ - @ReactMethod - abstract fun addListener(eventName: String) - - /** - * Required for NativeEventEmitter in TurboModules. - * Called when JS stops listening to events. - */ - @ReactMethod - abstract fun removeListeners(count: Double) -} diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt index 8eb2f0c137b..ee929d625f1 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt @@ -1,13 +1,12 @@ package chat.rocket.reactnative.voip -import android.content.Context import android.util.Log import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.WritableMap import com.facebook.react.modules.core.DeviceEventManagerModule import java.lang.ref.WeakReference +import chat.rocket.reactnative.NativeVoipSpec /** * Native module to expose VoIP call data to JavaScript. @@ -81,7 +80,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Gets any pending VoIP call data. * Returns null if no pending call. */ - @ReactMethod override fun getPendingVoipCall(): WritableMap? { val data = pendingVoipCallData ?: return null @@ -99,7 +97,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo /** * Clears any pending VoIP call data. */ - @ReactMethod override fun clearPendingVoipCall() { clearPendingVoipCallInternal() } @@ -108,7 +105,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Registers for VoIP push token. * No-op on Android - uses FCM for push notifications. */ - @ReactMethod override fun registerVoipToken() { // No-op on Android - FCM handles push notifications Log.d(TAG, "registerVoipToken called (no-op on Android)") @@ -118,7 +114,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Required for NativeEventEmitter in TurboModules. * Called when JS starts listening to events. */ - @ReactMethod override fun addListener(eventName: String) { // Keep track of listeners if needed Log.d(TAG, "addListener: $eventName") @@ -128,7 +123,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Required for NativeEventEmitter in TurboModules. * Called when JS stops listening to events. */ - @ReactMethod override fun removeListeners(count: Double) { // Remove listeners if needed Log.d(TAG, "removeListeners: $count") diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipTurboPackage.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipTurboPackage.kt index 6c3b27b5ee5..c4e483e4af2 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipTurboPackage.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipTurboPackage.kt @@ -1,10 +1,12 @@ -package chat.rocket.reactnative.voip +package chat.rocket.reactnative import com.facebook.react.BaseReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.module.model.ReactModuleInfo import com.facebook.react.module.model.ReactModuleInfoProvider +import chat.rocket.reactnative.NativeVoipSpec +import chat.rocket.reactnative.voip.VoipModule class VoipTurboPackage : BaseReactPackage() { From 7986af455c72c4cbe0f2406bf14e5779ac40adbe Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 10 Feb 2026 13:08:07 -0300 Subject: [PATCH 42/61] Unify emitters --- app/lib/services/voip/getInitialEvents.ts | 81 ++++++++--------------- 1 file changed, 26 insertions(+), 55 deletions(-) diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index 1a80b0f695a..b44522c5386 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -24,6 +24,8 @@ export const getInitialEvents = (): Promise<boolean> => { return Promise.resolve(getInitialEventsAndroid()); }; +const Emitter = isIOS ? new NativeEventEmitter(NativeVoipModule) : DeviceEventEmitter; + /** * Sets up listeners for VoIP call events from native side. * @returns Cleanup function to remove listeners @@ -32,60 +34,37 @@ export const setupVoipEventListeners = (): (() => void) => { const subscriptions: { remove: () => void }[] = []; const platform = isIOS ? 'iOS' : 'Android'; + // Listen for VoIP push token registration if (isIOS) { - // iOS: Use NativeEventEmitter with direct TurboModule import - const voipModuleEmitter = new NativeEventEmitter(NativeVoipModule); - - // Listen for VoIP push token registration subscriptions.push( - voipModuleEmitter.addListener('VoipPushTokenRegistered', (token: string) => { + Emitter.addListener('VoipPushTokenRegistered', (token: string) => { console.log(`[VoIP][${platform}] Registered VoIP push token:`, token); setVoipPushToken(token); }) ); - - // Listen for VoIP call events (when app is already running) - subscriptions.push( - voipModuleEmitter.addListener('VoipCallAccepted', async (data: VoipPayload) => { - try { - console.log(`[VoIP][${platform}] Call action event:`, data); - NativeVoipModule.clearPendingVoipCall(); - useCallStore.getState().setCallUUID(data.callUUID); - store.dispatch( - voipCallOpen({ - callId: data.callId, - callUUID: data.callUUID, - host: data.host - }) - ); - } catch (error) { - console.error(`[VoIP][${platform}] Error handling call action event:`, error); - } - }) - ); - } else { - // Android: Use DeviceEventEmitter - subscriptions.push( - DeviceEventEmitter.addListener('VoipCallAccepted', async (data: VoipPayload) => { - try { - console.log(`[VoIP][${platform}] Call action event:`, data); - NativeVoipModule.clearPendingVoipCall(); - useCallStore.getState().setCallUUID(data.callUUID); - store.dispatch( - voipCallOpen({ - callId: data.callId, - callUUID: data.callUUID, - host: data.host - }) - ); - await mediaSessionInstance.answerCall(data.callUUID); - } catch (error) { - console.error(`[VoIP][${platform}] Error handling call action event:`, error); - } - }) - ); } + // Listen for VoIP call events (when app is already running) + subscriptions.push( + Emitter.addListener('VoipCallAccepted', async (data: VoipPayload) => { + try { + console.log(`[VoIP][${platform}] Call action event:`, data); + NativeVoipModule.clearPendingVoipCall(); + useCallStore.getState().setCallUUID(data.callUUID); + store.dispatch( + voipCallOpen({ + callId: data.callId, + callUUID: data.callUUID, + host: data.host + }) + ); + // await mediaSessionInstance.answerCall(data.callUUID); + } catch (error) { + console.error(`[VoIP][${platform}] Error handling call action event:`, error); + } + }) + ); + // Return cleanup function return () => { subscriptions.forEach(sub => sub.remove()); @@ -104,14 +83,6 @@ const getInitialEventsIOS = async (): Promise<boolean> => { if (!pendingCall) { console.log('[VoIP][iOS] No pending VoIP call from native module'); - - // Still check CallKeep initial events for any answer actions - const initialEvents = await RNCallKeep.getInitialEvents(); - if (initialEvents.length > 0) { - console.log('[VoIP][iOS] Found CallKeep initial events but no pending call data'); - RNCallKeep.clearInitialEvents(); - } - return false; } @@ -120,10 +91,10 @@ const getInitialEventsIOS = async (): Promise<boolean> => { if (!pendingCall.callId || !pendingCall.host) { console.log('[VoIP][iOS] Missing required call data'); NativeVoipModule.clearPendingVoipCall(); + RNCallKeep.clearInitialEvents(); return false; } - // Check if user already answered the call via CallKit const initialEvents = await RNCallKeep.getInitialEvents(); console.log('[VoIP][iOS] CallKeep initial events:', JSON.stringify(initialEvents, null, 2)); From 746738181f35d2dec47584bc5e297d8973aa9417 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 10 Feb 2026 14:10:14 -0300 Subject: [PATCH 43/61] Move CallKeep listeners from MediaSessionInstance to getInitialEvents --- app/lib/services/voip/MediaSessionInstance.ts | 71 +++++-------------- app/lib/services/voip/getInitialEvents.ts | 15 +++- ios/AppDelegate.swift | 2 +- 3 files changed, 33 insertions(+), 55 deletions(-) diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 40388598c2a..98ccc817eb2 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -5,7 +5,7 @@ import { type MediaSignalingSession, type WebRTCProcessorConfig } from '@rocket.chat/media-signaling'; -import RNCallKeep, { type EventListener } from 'react-native-callkeep'; +import RNCallKeep from 'react-native-callkeep'; import { registerGlobals } from 'react-native-webrtc'; import { mediaSessionStore } from './MediaSessionStore'; @@ -26,17 +26,10 @@ class MediaSessionInstance { private instance: MediaSignalingSession | null = null; private storeTimeoutUnsubscribe: (() => void) | null = null; private storeIceServersUnsubscribe: (() => void) | null = null; - private callKeepListeners: { - answerCall?: EventListener; - endCall?: EventListener; - didPerformSetMutedCallAction?: EventListener; - didPerformDTMFAction?: EventListener; - } = {}; public init(userId: string): void { this.stop(); registerGlobals(); - this.configureRNCallKeep(); this.configureIceServers(); mediaSessionStore.setWebRTCProcessorFactory( @@ -72,7 +65,7 @@ class MediaSessionInstance { }); const existingCallUUID = useCallStore.getState().callUUID; - console.log('[VoIP][Android] Existing call UUID:', existingCallUUID); + console.log('[VoIP] Existing call UUID:', existingCallUUID); // // TODO: need to answer the call here? if (existingCallUUID) { this.answerCall(existingCallUUID); @@ -80,7 +73,7 @@ class MediaSessionInstance { } const callUUID = CallIdUUIDModule.toUUID(call.callId); - console.log('[VoIP][Android] New call UUID:', callUUID); + console.log('[VoIP] New call UUID:', callUUID); // const displayName = call.contact.displayName || call.contact.username || 'Unknown'; // RNCallKeep.displayIncomingCall(callUUID, displayName, displayName, 'generic', false); @@ -93,14 +86,14 @@ class MediaSessionInstance { } public answerCall = async (callUUID: string) => { - console.log('[VoIP][Android] Answering call:', callUUID); + console.log('[VoIP] Answering call:', callUUID); const mainCall = this.instance?.getMainCall(); - console.log('[VoIP][Android] Main call:', mainCall); + console.log('[VoIP] Main call:', mainCall); // Compare using deterministic UUID conversion if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { - console.log('[VoIP][Android] Accepting call:', callUUID); + console.log('[VoIP] Accepting call:', callUUID); await mainCall.accept(); - console.log('[VoIP][Android] Setting current call active:', callUUID); + console.log('[VoIP] Setting current call active:', callUUID); RNCallKeep.setCurrentCallActive(callUUID); useCallStore.getState().setCall(mainCall, callUUID); Navigation.navigate('CallView', { callUUID }); @@ -109,45 +102,18 @@ class MediaSessionInstance { } }; - private configureRNCallKeep = () => { - this.callKeepListeners.answerCall = RNCallKeep.addEventListener('answerCall', ({ callUUID }) => { - this.answerCall(callUUID); - }); - - this.callKeepListeners.endCall = RNCallKeep.addEventListener('endCall', ({ callUUID }) => { - const mainCall = this.instance?.getMainCall(); - // Compare using deterministic UUID conversion - if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { - if (mainCall.state === 'ringing') { - mainCall.reject(); - } else { - mainCall.hangup(); - } - } - // Reset Zustand store - useCallStore.getState().reset(); - }); - - this.callKeepListeners.didPerformSetMutedCallAction = RNCallKeep.addEventListener( - 'didPerformSetMutedCallAction', - ({ muted, callUUID }) => { - const mainCall = this.instance?.getMainCall(); - // Compare using deterministic UUID conversion - if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { - mainCall.setMuted(muted); - // Sync with Zustand store - useCallStore.getState().updateFromCall(); - } - } - ); - - this.callKeepListeners.didPerformDTMFAction = RNCallKeep.addEventListener('didPerformDTMFAction', ({ digits, callUUID }) => { - const mainCall = this.instance?.getMainCall(); - // Compare using deterministic UUID conversion - if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { - mainCall.sendDTMF(digits); + public endCall = (callUUID: string) => { + const mainCall = this.instance?.getMainCall(); + // Compare using deterministic UUID conversion + if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { + if (mainCall.state === 'ringing') { + mainCall.reject(); + } else { + mainCall.hangup(); } - }); + } + // Reset Zustand store + useCallStore.getState().reset(); }; private getIceServers() { @@ -192,7 +158,6 @@ class MediaSessionInstance { if (this.instance) { this.instance.endSession(); } - Object.values(this.callKeepListeners).forEach(listener => listener?.remove()); } } diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index b44522c5386..df8a17d8b45 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -42,6 +42,19 @@ export const setupVoipEventListeners = (): (() => void) => { setVoipPushToken(token); }) ); + + subscriptions.push( + RNCallKeep.addEventListener('answerCall', ({ callUUID }) => { + console.log(`[VoIP][${platform}] Answer call event listener:`, callUUID); + mediaSessionInstance.answerCall(callUUID); + }) + ); + subscriptions.push( + RNCallKeep.addEventListener('endCall', ({ callUUID }) => { + console.log(`[VoIP][${platform}] End call event listener:`, callUUID); + mediaSessionInstance.endCall(callUUID); + }) + ); } // Listen for VoIP call events (when app is already running) @@ -58,7 +71,7 @@ export const setupVoipEventListeners = (): (() => void) => { host: data.host }) ); - // await mediaSessionInstance.answerCall(data.callUUID); + await mediaSessionInstance.answerCall(data.callUUID); } catch (error) { console.error(`[VoIP][${platform}] Error handling call action event:`, error); } diff --git a/ios/AppDelegate.swift b/ios/AppDelegate.swift index 3b3d464809d..6bdaefb7b45 100644 --- a/ios/AppDelegate.swift +++ b/ios/AppDelegate.swift @@ -123,7 +123,7 @@ extension AppDelegate: PKPushRegistryDelegate { // Convert callId to deterministic UUID v5 for CallKit let callIdUUID = CallIdUUID.generateUUIDv5(from: callId) - // Store pending call data in our native module (replaces RNVoipPushNotificationManager) + // Store pending call data in our native module VoipService.didReceiveIncomingPush(with: payload, forType: type.rawValue) RNCallKeep.reportNewIncomingCall( From e72c0f90527b83a768a763f23042286a3de8b821 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 10 Feb 2026 14:27:16 -0300 Subject: [PATCH 44/61] Clear callkeep on endcall --- app/lib/services/voip/MediaSessionInstance.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 98ccc817eb2..efc4c9ecec5 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -112,6 +112,9 @@ class MediaSessionInstance { mainCall.hangup(); } } + RNCallKeep.endCall(callUUID); + RNCallKeep.setCurrentCallActive(''); + RNCallKeep.setAvailable(true); // Reset Zustand store useCallStore.getState().reset(); }; From 0b87d35132f24655f946381e38823fb45cd4e2d0 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 10 Feb 2026 15:52:41 -0300 Subject: [PATCH 45/61] Unify getInitialEvents logic --- .../notification/NotificationIntentHandler.kt | 2 +- .../rocket/reactnative/voip/VoipModule.kt | 48 ++--- app/index.tsx | 2 +- app/lib/native/NativeVoip.ts | 14 +- app/lib/services/voip/getInitialEvents.ts | 183 +++++++----------- app/sagas/deepLinking.js | 62 +----- ios/Libraries/VoipModule.mm | 24 +-- ios/Libraries/VoipService.swift | 59 +++--- 8 files changed, 139 insertions(+), 255 deletions(-) diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index 0882c0f5b35..1b5307ac4ce 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -55,7 +55,7 @@ class NotificationIntentHandler { Log.d(TAG, "Handling VoIP intent - voipPayload: $voipPayload") VoipNotification.cancelById(context, voipPayload.notificationId) - VoipModule.storePendingVoipCall(voipPayload) + VoipModule.storeInitialEvents(voipPayload) // Clear the voip flag to prevent re-processing intent.removeExtra("voipAction") diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt index ee929d625f1..099238129c0 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt @@ -16,11 +16,11 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo companion object { private const val TAG = "RocketChat.VoipModule" - private const val EVENT_VOIP_CALL = "VoipCallAccepted" + private const val EVENT_INITIAL_EVENTS = "VoipPushInitialEvents" private var reactContextRef: WeakReference<ReactApplicationContext>? = null - private var pendingVoipCallData: VoipPayload? = null - private var pendingVoipCallTimestamp: Long = 0 + private var initialEventsData: VoipPayload? = null + private var initialEventsTimestamp: Long = 0 /** * Sets the React context reference for event emission. @@ -34,13 +34,13 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Emits a VoIP call event to JavaScript when the app is running. */ @JvmStatic - fun emitVoipCallEvent(voipPayload: VoipPayload) { + fun emitInitialEventsEvent(voipPayload: VoipPayload) { try { reactContextRef?.get()?.let { context -> if (context.hasActiveReactInstance()) { context .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) - .emit(EVENT_VOIP_CALL, voipPayload.toWritableMap()) + .emit(EVENT_INITIAL_EVENTS, voipPayload.toWritableMap()) } } } catch (e: Exception) { @@ -53,20 +53,20 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo * Also emits an event if the app is running. */ @JvmStatic - fun storePendingVoipCall(voipPayload: VoipPayload) { - pendingVoipCallData = voipPayload - pendingVoipCallTimestamp = System.currentTimeMillis() - emitVoipCallEvent(voipPayload) + fun storeInitialEvents(voipPayload: VoipPayload) { + initialEventsData = voipPayload + initialEventsTimestamp = System.currentTimeMillis() + emitInitialEventsEvent(voipPayload) } @JvmStatic - fun clearPendingVoipCallInternal() { + fun clearInitialEventsInternal() { try { - pendingVoipCallData = null - pendingVoipCallTimestamp = 0 - Log.d(TAG, "Cleared pending VoIP call data") + initialEventsData = null + initialEventsTimestamp = 0 + Log.d(TAG, "Cleared initial events") } catch (e: Exception) { - Log.e(TAG, "Error clearing pending VoIP call", e) + Log.e(TAG, "Error clearing initial events", e) } } } @@ -77,28 +77,28 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo } /** - * Gets any pending VoIP call data. - * Returns null if no pending call. + * Gets any initial events. + * Returns null if no initial events. */ - override fun getPendingVoipCall(): WritableMap? { - val data = pendingVoipCallData ?: return null + override fun getInitialEvents(): WritableMap? { + val data = initialEventsData ?: return null - if (System.currentTimeMillis() - pendingVoipCallTimestamp > 5 * 60 * 1000) { - clearPendingVoipCallInternal() + if (System.currentTimeMillis() - initialEventsTimestamp > 5 * 60 * 1000) { + clearInitialEventsInternal() return null } val result = data.toWritableMap() - clearPendingVoipCallInternal() + clearInitialEventsInternal() return result } /** - * Clears any pending VoIP call data. + * Clears any initial events. */ - override fun clearPendingVoipCall() { - clearPendingVoipCallInternal() + override fun clearInitialEvents() { + clearInitialEventsInternal() } /** diff --git a/app/index.tsx b/app/index.tsx index 4c412c4bf1b..c0884729dba 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -122,7 +122,7 @@ export default class Root extends React.Component<{}, IState> { // Set up video conf action listener for background accept/decline this.videoConfActionCleanup = setupVideoConfActionListener(); - // Set up VoIP event listeners for Android native call UI + // Set up VoIP event listeners for incoming calls this.voipEventCleanup = setupVoipEventListeners(); } diff --git a/app/lib/native/NativeVoip.ts b/app/lib/native/NativeVoip.ts index 115cad31c15..2b39ea631dd 100644 --- a/app/lib/native/NativeVoip.ts +++ b/app/lib/native/NativeVoip.ts @@ -10,26 +10,28 @@ export interface Spec extends TurboModule { registerVoipToken(): void; /** - * Gets any pending VoIP call data. - * Returns null if no pending call or if data is older than 5 minutes. - * Clears the pending data after retrieval. + * Gets any initial events. + * Returns null if no initial events. + * Clears the initial events after retrieval. */ - getPendingVoipCall(): Object | null; + getInitialEvents(): Object | null; /** - * Clears any pending VoIP call data. + * Clears any initial events. */ - clearPendingVoipCall(): void; + clearInitialEvents(): void; /** * Required for NativeEventEmitter in TurboModules. * Called when JS starts listening to events. + * @platform android */ addListener(eventName: string): void; /** * Required for NativeEventEmitter in TurboModules. * Called when JS stops listening to events. + * @platform android */ removeListeners(count: number): void; } diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/getInitialEvents.ts index df8a17d8b45..d201a79f42a 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/getInitialEvents.ts @@ -10,21 +10,9 @@ import { mediaSessionInstance } from './MediaSessionInstance'; import type { VoipPayload } from '../../../definitions/Voip'; import NativeVoipModule from '../../native/NativeVoip'; -/** - * Handles initial VoIP events on app startup. - * - * Both platforms now use native module to retrieve pending VoIP call data. - * iOS: VoipModule stores pending call data from PushKit callbacks - * Android: VoipModule stores pending call data from Intent/SharedPreferences - */ -export const getInitialEvents = (): Promise<boolean> => { - if (isIOS) { - return getInitialEventsIOS(); - } - return Promise.resolve(getInitialEventsAndroid()); -}; - const Emitter = isIOS ? new NativeEventEmitter(NativeVoipModule) : DeviceEventEmitter; +const platform = isIOS ? 'iOS' : 'Android'; +const TAG = `[getInitialEvents][${platform}]`; /** * Sets up listeners for VoIP call events from native side. @@ -32,52 +20,57 @@ const Emitter = isIOS ? new NativeEventEmitter(NativeVoipModule) : DeviceEventEm */ export const setupVoipEventListeners = (): (() => void) => { const subscriptions: { remove: () => void }[] = []; - const platform = isIOS ? 'iOS' : 'Android'; - // Listen for VoIP push token registration + // iOS listens for VoIP push token registration and CallKeep events if (isIOS) { subscriptions.push( Emitter.addListener('VoipPushTokenRegistered', (token: string) => { - console.log(`[VoIP][${platform}] Registered VoIP push token:`, token); + console.log(`${TAG} Registered VoIP push token:`, token); setVoipPushToken(token); }) ); subscriptions.push( RNCallKeep.addEventListener('answerCall', ({ callUUID }) => { - console.log(`[VoIP][${platform}] Answer call event listener:`, callUUID); + console.log(`${TAG} Answer call event listener:`, callUUID); mediaSessionInstance.answerCall(callUUID); + NativeVoipModule.clearInitialEvents(); + RNCallKeep.clearInitialEvents(); }) ); subscriptions.push( RNCallKeep.addEventListener('endCall', ({ callUUID }) => { - console.log(`[VoIP][${platform}] End call event listener:`, callUUID); + console.log(`${TAG} End call event listener:`, callUUID); mediaSessionInstance.endCall(callUUID); }) ); + } else { + // Android listens for VoIP call events from VoipModule + subscriptions.push( + Emitter.addListener('VoipPushInitialEvents', async (data: VoipPayload) => { + try { + if (data.type !== 'incoming_call') { + console.log(`${TAG} Not an incoming call`); + return; + } + console.log(`${TAG} Initial events event:`, data); + NativeVoipModule.clearInitialEvents(); + useCallStore.getState().setCallUUID(data.callUUID); + store.dispatch( + voipCallOpen({ + callId: data.callId, + callUUID: data.callUUID, + host: data.host + }) + ); + await mediaSessionInstance.answerCall(data.callUUID); + } catch (error) { + console.error(`${TAG} Error handling initial events event:`, error); + } + }) + ); } - // Listen for VoIP call events (when app is already running) - subscriptions.push( - Emitter.addListener('VoipCallAccepted', async (data: VoipPayload) => { - try { - console.log(`[VoIP][${platform}] Call action event:`, data); - NativeVoipModule.clearPendingVoipCall(); - useCallStore.getState().setCallUUID(data.callUUID); - store.dispatch( - voipCallOpen({ - callId: data.callId, - callUUID: data.callUUID, - host: data.host - }) - ); - await mediaSessionInstance.answerCall(data.callUUID); - } catch (error) { - console.error(`[VoIP][${platform}] Error handling call action event:`, error); - } - }) - ); - // Return cleanup function return () => { subscriptions.forEach(sub => sub.remove()); @@ -85,102 +78,66 @@ export const setupVoipEventListeners = (): (() => void) => { }; /** - * iOS-specific implementation using native VoipModule and CallKeep. - * The native module stores pending VoIP call data from PushKit callbacks. - * CallKeep is still used for the CallKit UI integration. + * Handles initial VoIP events from native module. + * @returns true if the call was answered, false otherwise */ -const getInitialEventsIOS = async (): Promise<boolean> => { +export const getInitialEvents = async (): Promise<boolean> => { try { - // Get pending VoIP call from native module (stored by AppDelegate when VoIP push received) - const pendingCall = NativeVoipModule.getPendingVoipCall() as VoipPayload | null; - - if (!pendingCall) { - console.log('[VoIP][iOS] No pending VoIP call from native module'); + // Get initial events from native module + const initialEvents = NativeVoipModule.getInitialEvents() as VoipPayload | null; + if (!initialEvents) { + console.log(`${TAG} No initial events from native module`); + RNCallKeep.clearInitialEvents(); return false; } + console.log(`${TAG} Found initial events:`, initialEvents); - console.log('[VoIP][iOS] Found pending VoIP call:', pendingCall); - - if (!pendingCall.callId || !pendingCall.host) { - console.log('[VoIP][iOS] Missing required call data'); - NativeVoipModule.clearPendingVoipCall(); + if (!initialEvents.callId || !initialEvents.host || initialEvents.type !== 'incoming_call') { + console.log(`${TAG} Missing required call data`); RNCallKeep.clearInitialEvents(); return false; } - const initialEvents = await RNCallKeep.getInitialEvents(); - console.log('[VoIP][iOS] CallKeep initial events:', JSON.stringify(initialEvents, null, 2)); - let wasAnswered = false; - for (const event of initialEvents) { - const { name, data } = event; - if (name === 'RNCallKeepPerformAnswerCallAction') { - const { callUUID } = data; - if (pendingCall.callUUID.toLowerCase() === callUUID.toLowerCase()) { - wasAnswered = true; - console.log('[VoIP][iOS] Call was already answered via CallKit'); - break; + + if (isIOS) { + const callKeepInitialEvents = await RNCallKeep.getInitialEvents(); + RNCallKeep.clearInitialEvents(); + console.log(`${TAG} CallKeep initial events:`, JSON.stringify(callKeepInitialEvents, null, 2)); + + // iOS loops through the events and checks if the call was already answered + for (const event of callKeepInitialEvents) { + const { name, data } = event; + if (name === 'RNCallKeepPerformAnswerCallAction') { + const { callUUID } = data; + if (initialEvents.callUUID.toLowerCase() === callUUID.toLowerCase()) { + wasAnswered = true; + console.log(`${TAG} Call was already answered via CallKit`); + break; + } } } + } else { + // Android only sends answered event, so we can assume the call was answered + wasAnswered = true; } if (wasAnswered) { - useCallStore.getState().setCallUUID(pendingCall.callUUID); + useCallStore.getState().setCallUUID(initialEvents.callUUID); store.dispatch( voipCallOpen({ - callId: pendingCall.callId, - callUUID: pendingCall.callUUID, - host: pendingCall.host + callId: initialEvents.callId, + callUUID: initialEvents.callUUID, + host: initialEvents.host }) ); - console.log('[VoIP][iOS] Dispatched voipCallOpen action'); - } - - // Clear the data - NativeVoipModule.clearPendingVoipCall(); - if (initialEvents.length > 0) { - RNCallKeep.clearInitialEvents(); - } - - return wasAnswered; - } catch (error) { - console.error('[VoIP][iOS] Error:', error); - return false; - } -}; - -/** - * Android-specific implementation using native module to retrieve VoIP call data - */ -const getInitialEventsAndroid = (): boolean => { - try { - const pendingCall = NativeVoipModule.getPendingVoipCall() as VoipPayload; - if (!pendingCall) { - console.log('[VoIP][Android] No pending VoIP call'); - return false; - } - - NativeVoipModule.clearPendingVoipCall(); - - if (!pendingCall.callId || !pendingCall.host) { - console.log('[VoIP][Android] Missing required call data'); - return false; + console.log(`${TAG} Dispatched voipCallOpen action`); } - useCallStore.getState().setCallUUID(pendingCall.callUUID); - - store.dispatch( - voipCallOpen({ - callId: pendingCall.callId, - callUUID: pendingCall.callUUID, - host: pendingCall.host - }) - ); - - return true; + return Promise.resolve(wasAnswered); } catch (error) { - console.error('[VoIP][Android] Error:', error); + console.error(`${TAG} Error:`, error); return false; } }; diff --git a/app/sagas/deepLinking.js b/app/sagas/deepLinking.js index d6033693698..d57f47e7fa1 100644 --- a/app/sagas/deepLinking.js +++ b/app/sagas/deepLinking.js @@ -46,7 +46,7 @@ const waitForNavigation = () => { if (Navigation.navigationRef.current) { return Promise.resolve(); } - return new Promise((resolve) => { + return new Promise(resolve => { const listener = () => { emitter.off('navigationReady', listener); resolve(); @@ -303,65 +303,7 @@ const handleClickCallPush = function* handleClickCallPush({ params }) { * The actual call handling is done by MediaSessionInstance via the pending call store. */ const handleVoipCall = function* handleVoipCall({ params }) { - let { host } = params; - - console.log('[VoIP] handleVoipCall:', params); - - if (!host) { - // No host specified, assume current server - console.log('[VoIP] No host specified, using current server'); - return; - } - - // Normalize host URL - if (!/^(http|https)/.test(host)) { - if (/^localhost(:\d+)?/.test(host)) { - host = `http://${host}`; - } else { - host = `https://${host}`; - } - } else { - host = host.replace('http://', 'https://'); - } - if (host.slice(-1) === '/') { - host = host.slice(0, host.length - 1); - } - - const [server, user] = yield all([ - UserPreferences.getString(CURRENT_SERVER), - UserPreferences.getString(`${TOKEN_KEY}-${host}`) - ]); - - const serverRecord = yield getServerById(host); - - // If already connected to the correct server, nothing to do - // MediaSessionInstance will handle the call via pending store - if (server === host && user && serverRecord) { - const connected = yield select(state => state.server.connected); - if (!connected) { - console.log('[VoIP] Connecting to server:', host); - yield localAuthenticate(host); - yield put(selectServerRequest(host, serverRecord.version, true)); - yield take(types.LOGIN.SUCCESS); - console.log('[VoIP] Connected to server:', host); - } else { - console.log('[VoIP] Already connected to server:', host); - } - return; - } - - // Need to switch to a different server - if (user && serverRecord) { - console.log('[VoIP] Switching to server:', host); - yield localAuthenticate(host); - yield put(selectServerRequest(host, serverRecord.version, true, true)); - yield take(types.LOGIN.SUCCESS); - console.log('[VoIP] Switched to server:', host); - return; - } - - // Server not registered - can't handle this call - console.log('[VoIP] Server not registered, cannot handle call:', host); + yield handleOpen({ params }); }; const root = function* root() { diff --git a/ios/Libraries/VoipModule.mm b/ios/Libraries/VoipModule.mm index 3b6aa5594a4..2c3ff8cda89 100644 --- a/ios/Libraries/VoipModule.mm +++ b/ios/Libraries/VoipModule.mm @@ -9,8 +9,8 @@ @interface VoipModule : RCTEventEmitter <NativeVoipSpec> @interface VoipService : NSObject + (void)voipRegistration; -+ (NSDictionary * _Nullable)getPendingVoipCall; -+ (void)clearPendingVoipCall; ++ (NSDictionary * _Nullable)getInitialEvents; ++ (void)clearInitialEvents; @end @implementation VoipModule { @@ -33,16 +33,11 @@ - (instancetype)init { } - (NSArray<NSString *> *)supportedEvents { - return @[@"VoipCallAccepted", @"VoipPushTokenRegistered"]; + return @[@"VoipPushTokenRegistered"]; } - (void)startObserving { _hasListeners = YES; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleVoipCallAccepted:) - name:@"VoipCallAccepted" - object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleVoipTokenRegistered:) @@ -65,11 +60,6 @@ - (void)stopObserving { [[NSNotificationCenter defaultCenter] removeObserver:self]; } -// Handler for Call Accepted -- (void)handleVoipCallAccepted:(NSNotification *)notification { - [self sendEventWrapper:@"VoipCallAccepted" body:notification.userInfo]; -} - // Handler for Token Registration - (void)handleVoipTokenRegistered:(NSNotification *)notification { [self sendEventWrapper:@"VoipPushTokenRegistered" body:notification.userInfo]; @@ -91,12 +81,12 @@ - (void)registerVoipToken { }); } -- (NSDictionary * _Nullable)getPendingVoipCall { - return [VoipService getPendingVoipCall]; +- (NSDictionary * _Nullable)getInitialEvents { + return [VoipService getInitialEvents]; } -- (void)clearPendingVoipCall { - [VoipService clearPendingVoipCall]; +- (void)clearInitialEvents { + [VoipService clearInitialEvents]; } - (void)addListener:(NSString *)eventName { diff --git a/ios/Libraries/VoipService.swift b/ios/Libraries/VoipService.swift index b7d1a123f77..05510d27a83 100644 --- a/ios/Libraries/VoipService.swift +++ b/ios/Libraries/VoipService.swift @@ -2,13 +2,13 @@ import Foundation import PushKit /** - * VoipModuleSwift - Swift implementation for VoIP push notifications and pending call data. + * VoipModuleSwift - Swift implementation for VoIP push notifications and initial events data. * This class provides static methods called by VoipModule.mm (the TurboModule bridge). * * This module: * - Manages PushKit VoIP registration * - Tracks VoIP push tokens - * - Stores pending VoIP call data for retrieval by JavaScript + * - Stores initial events data for retrieval by JavaScript */ @objc(VoipService) public final class VoipService: NSObject { @@ -19,8 +19,8 @@ public final class VoipService: NSObject { // MARK: - Static Properties - private static var pendingVoipCallData: VoipPayload? - private static var pendingVoipCallTimestamp: TimeInterval = 0 + private static var initialEventsData: VoipPayload? + private static var initialEventsTimestamp: TimeInterval = 0 private static var isVoipRegistered = false private static var lastVoipToken: String = "" private static var voipRegistry: PKPushRegistry? @@ -78,7 +78,7 @@ public final class VoipService: NSObject { ) } - /// Called from AppDelegate when a VoIP push is received + /// Called from AppDelegate when a VoIP push initial events are received @objc public static func didReceiveIncomingPush(with payload: PKPushPayload, forType type: String) { #if DEBUG @@ -92,59 +92,52 @@ public final class VoipService: NSObject { return } - storePendingVoipCall(voipPayload) + storeInitialEvents(voipPayload) } - /// Stores VoIP call data for JS to retrieve. + /// Stores initial events for JS to retrieve. @objc - public static func storePendingVoipCall(_ payload: VoipPayload) { - pendingVoipCallData = payload - pendingVoipCallTimestamp = Date().timeIntervalSince1970 + public static func storeInitialEvents(_ payload: VoipPayload) { + initialEventsData = payload + initialEventsTimestamp = Date().timeIntervalSince1970 #if DEBUG - print("[\(TAG)] Stored pending VoIP call: \(payload.callId)") + print("[\(TAG)] Stored initial events: \(payload.callId)") #endif - - // Emit event via notification (the ObjC++ bridge observes this) - NotificationCenter.default.post( - name: NSNotification.Name("VoipCallAccepted"), - object: nil, - userInfo: payload.toDictionary() - ) } - /// Gets any pending VoIP call data. Returns nil if no pending call. + /// Gets any initial events. Returns nil if no initial events. @objc - public static func getPendingVoipCall() -> [String: Any]? { - guard let data = pendingVoipCallData else { + public static func getInitialEvents() -> [String: Any]? { + guard let data = initialEventsData else { return nil } // Check if data is older than 5 minutes let now = Date().timeIntervalSince1970 - if now - pendingVoipCallTimestamp > 5 * 60 { - clearPendingVoipCallInternal() + if now - initialEventsTimestamp > 5 * 60 { + clearInitialEventsInternal() return nil } let result = data.toDictionary() - clearPendingVoipCallInternal() + clearInitialEventsInternal() return result } - /// Clears any pending VoIP call data + /// Clears any initial events @objc - public static func clearPendingVoipCall() { - clearPendingVoipCallInternal() + public static func clearInitialEvents() { + clearInitialEventsInternal() } - /// Clears pending VoIP call data (internal) - private static func clearPendingVoipCallInternal() { - pendingVoipCallData = nil - pendingVoipCallTimestamp = 0 + /// Clears initial events (internal) + private static func clearInitialEventsInternal() { + initialEventsData = nil + initialEventsTimestamp = 0 #if DEBUG - print("[\(TAG)] Cleared pending VoIP call data") + print("[\(TAG)] Cleared initial events") #endif } @@ -157,7 +150,7 @@ public final class VoipService: NSObject { // MARK: - VoipPayload -/// Data structure for VoIP call payload +/// Data structure for initial events payload @objc(VoipPayload) public class VoipPayload: NSObject { @objc public let callId: String From 2cbd7ecf1d1e6bcf752eb1b0a287cdc39b60dd18 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 10 Feb 2026 15:54:57 -0300 Subject: [PATCH 46/61] getInitialEvents -> MediaCallEvents --- app/index.tsx | 12 ++++++------ .../voip/{getInitialEvents.ts => MediaCallEvents.ts} | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) rename app/lib/services/voip/{getInitialEvents.ts => MediaCallEvents.ts} (92%) diff --git a/app/index.tsx b/app/index.tsx index c0884729dba..87ee0fb5c82 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -33,7 +33,7 @@ import { } from './lib/methods/helpers/theme'; import { initializePushNotifications, onNotification } from './lib/notifications'; import { getInitialNotification, setupVideoConfActionListener } from './lib/notifications/videoConf/getInitialNotification'; -import { getInitialEvents, setupVoipEventListeners } from './lib/services/voip/getInitialEvents'; +import { getInitialMediaCallEvents, setupMediaCallEvents } from './lib/services/voip/MediaCallEvents'; import store from './lib/store'; import { initStore } from './lib/store/auxStore'; import { type TSupportedThemes, ThemeContext } from './theme'; @@ -87,7 +87,7 @@ export default class Root extends React.Component<{}, IState> { private listenerTimeout!: any; private dimensionsListener?: EmitterSubscription; private videoConfActionCleanup?: () => void; - private voipEventCleanup?: () => void; + private mediaCallEventCleanup?: () => void; constructor(props: any) { super(props); @@ -122,15 +122,15 @@ export default class Root extends React.Component<{}, IState> { // Set up video conf action listener for background accept/decline this.videoConfActionCleanup = setupVideoConfActionListener(); - // Set up VoIP event listeners for incoming calls - this.voipEventCleanup = setupVoipEventListeners(); + // Set up media call event listeners for incoming calls + this.mediaCallEventCleanup = setupMediaCallEvents(); } componentWillUnmount() { clearTimeout(this.listenerTimeout); this.dimensionsListener?.remove?.(); this.videoConfActionCleanup?.(); - this.voipEventCleanup?.(); + this.mediaCallEventCleanup?.(); unsubscribeTheme(); } @@ -154,7 +154,7 @@ export default class Root extends React.Component<{}, IState> { } // TODO: change name - const handledVoipCall = await getInitialEvents(); + const handledVoipCall = await getInitialMediaCallEvents(); if (handledVoipCall) { return; } diff --git a/app/lib/services/voip/getInitialEvents.ts b/app/lib/services/voip/MediaCallEvents.ts similarity index 92% rename from app/lib/services/voip/getInitialEvents.ts rename to app/lib/services/voip/MediaCallEvents.ts index d201a79f42a..d04733c33d4 100644 --- a/app/lib/services/voip/getInitialEvents.ts +++ b/app/lib/services/voip/MediaCallEvents.ts @@ -12,13 +12,13 @@ import NativeVoipModule from '../../native/NativeVoip'; const Emitter = isIOS ? new NativeEventEmitter(NativeVoipModule) : DeviceEventEmitter; const platform = isIOS ? 'iOS' : 'Android'; -const TAG = `[getInitialEvents][${platform}]`; +const TAG = `[MediaCallEvents][${platform}]`; /** - * Sets up listeners for VoIP call events from native side. + * Sets up listeners for media call events. * @returns Cleanup function to remove listeners */ -export const setupVoipEventListeners = (): (() => void) => { +export const setupMediaCallEvents = (): (() => void) => { const subscriptions: { remove: () => void }[] = []; // iOS listens for VoIP push token registration and CallKeep events @@ -45,7 +45,7 @@ export const setupVoipEventListeners = (): (() => void) => { }) ); } else { - // Android listens for VoIP call events from VoipModule + // Android listens for media call events from VoipModule subscriptions.push( Emitter.addListener('VoipPushInitialEvents', async (data: VoipPayload) => { try { @@ -78,10 +78,10 @@ export const setupVoipEventListeners = (): (() => void) => { }; /** - * Handles initial VoIP events from native module. + * Handles initial media call events. * @returns true if the call was answered, false otherwise */ -export const getInitialEvents = async (): Promise<boolean> => { +export const getInitialMediaCallEvents = async (): Promise<boolean> => { try { // Get initial events from native module const initialEvents = NativeVoipModule.getInitialEvents() as VoipPayload | null; From 0d40944555bd1e30b95c1cfe1e805bff6f70e1f5 Mon Sep 17 00:00:00 2001 From: diegolmello <diegolmello@users.noreply.github.com> Date: Tue, 10 Feb 2026 18:58:29 +0000 Subject: [PATCH 47/61] chore: format code and fix lint issues [skip ci] --- app/sagas/deepLinking.js | 2 +- app/sagas/login.js | 10 +++++----- index.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/sagas/deepLinking.js b/app/sagas/deepLinking.js index d57f47e7fa1..6b0aca2235a 100644 --- a/app/sagas/deepLinking.js +++ b/app/sagas/deepLinking.js @@ -46,7 +46,7 @@ const waitForNavigation = () => { if (Navigation.navigationRef.current) { return Promise.resolve(); } - return new Promise(resolve => { + return new Promise((resolve) => { const listener = () => { emitter.off('navigationReady', listener); resolve(); diff --git a/app/sagas/login.js b/app/sagas/login.js index 6e7737a854c..d3c52a6b9a8 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -60,7 +60,7 @@ const showSupportedVersionsWarning = function* showSupportedVersionsWarning(serv const serversDB = database.servers; yield serversDB.write(async () => { - await serverRecord.update(r => { + await serverRecord.update((r) => { r.supportedVersionsWarningAt = new Date(); }); }); @@ -107,7 +107,7 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE } // this is updating on every login just to save `updated_at` // keeping this server as the most recent on autocomplete order - await serverHistoryRecord.update(s => { + await serverHistoryRecord.update((s) => { s.username = result.username; if (iconURL) { s.iconURL = iconURL; @@ -279,12 +279,12 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) { yield serversDB.write(async () => { try { const userRecord = await usersCollection.find(user.id); - await userRecord.update(record => { + await userRecord.update((record) => { record._raw = sanitizedRaw({ id: user.id, ...record._raw }, usersCollection.schema); Object.assign(record, u); }); } catch (e) { - await usersCollection.create(record => { + await usersCollection.create((record) => { record._raw = sanitizedRaw({ id: user.id }, usersCollection.schema); Object.assign(record, u); }); @@ -361,7 +361,7 @@ const handleSetUser = function* handleSetUser({ user }) { yield serversDB.write(async () => { try { const record = await userCollections.find(userId); - await record.update(userRecord => { + await record.update((userRecord) => { if ('avatarETag' in user) { userRecord.avatarETag = user.avatarETag; } diff --git a/index.js b/index.js index a59c08135ce..a8ca1d5a6a0 100644 --- a/index.js +++ b/index.js @@ -47,7 +47,7 @@ if (process.env.USE_STORYBOOK) { console.log('RNCallKeep setup successful'); RNCallKeep.canMakeMultipleCalls(false); }) - .catch(error => { + .catch((error) => { console.error('Error setting up RNCallKeep:', error); }); } From 18b0b0a1fa2e24a48e5e365a120d1398eef08f71 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 17 Feb 2026 13:47:04 -0300 Subject: [PATCH 48/61] feat(Android): Add full screen incoming call (#6977) --- .github/workflows/prettier.yml | 2 +- android/app/build.gradle | 1 + .../reactnative/notification/Ejson.java | 34 ++- .../notification/NotificationIntentHandler.kt | 12 + .../reactnative/voip/IncomingCallActivity.kt | 145 ++++++++++-- .../rocket/reactnative/voip/VoipPayload.kt | 28 ++- .../res/drawable/bg_avatar_incoming_call.xml | 6 + .../src/main/res/drawable/bg_btn_accept.xml | 6 + .../src/main/res/drawable/bg_btn_reject.xml | 6 + android/app/src/main/res/drawable/ic_call.xml | 9 + .../app/src/main/res/drawable/ic_call_end.xml | 9 + .../res/layout/activity_incoming_call.xml | 219 +++++++++++++----- .../res/values-night/colors_incoming_call.xml | 15 ++ .../res/values-night/styles_incoming_call.xml | 12 + .../main/res/values/colors_incoming_call.xml | 15 ++ .../main/res/values/strings_incoming_call.xml | 9 + .../main/res/values/styles_incoming_call.xml | 8 +- .../rocket.chat-media-signaling-0.1.0.tgz | Bin 56685 -> 62589 bytes 18 files changed, 445 insertions(+), 91 deletions(-) create mode 100644 android/app/src/main/res/drawable/bg_avatar_incoming_call.xml create mode 100644 android/app/src/main/res/drawable/bg_btn_accept.xml create mode 100644 android/app/src/main/res/drawable/bg_btn_reject.xml create mode 100644 android/app/src/main/res/drawable/ic_call.xml create mode 100644 android/app/src/main/res/drawable/ic_call_end.xml create mode 100644 android/app/src/main/res/values-night/colors_incoming_call.xml create mode 100644 android/app/src/main/res/values-night/styles_incoming_call.xml create mode 100644 android/app/src/main/res/values/colors_incoming_call.xml create mode 100644 android/app/src/main/res/values/strings_incoming_call.xml diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml index 3e5a93039c8..c49c60afe60 100644 --- a/.github/workflows/prettier.yml +++ b/.github/workflows/prettier.yml @@ -46,5 +46,5 @@ jobs: git config user.name "${{ github.actor }}" git config user.email "${{ github.actor }}@users.noreply.github.com" git add . - git commit -m "chore: format code and fix lint issues [skip ci]" + git commit -m "chore: format code and fix lint issues" git push origin ${{ github.ref_name }} \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index f0f06675f4c..f47eee7bc95 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -148,6 +148,7 @@ dependencies { implementation "com.google.code.gson:gson:2.8.9" implementation "com.tencent:mmkv-static:1.2.10" + implementation "com.github.bumptech.glide:glide:${rootProject.ext.glideVersion}" implementation 'com.facebook.soloader:soloader:0.10.4' // For SecureKeystore (EncryptedSharedPreferences) diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/Ejson.java b/android/app/src/main/java/chat/rocket/reactnative/notification/Ejson.java index e9998ff8231..43489b5dd2f 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/Ejson.java +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/Ejson.java @@ -57,7 +57,7 @@ private MMKV getMMKV() { * Helper method to build avatar URI from avatar path. * Validates server URL and credentials, then constructs the full URI. */ - private String buildAvatarUri(String avatarPath, String errorContext) { + private String buildAvatarUri(String avatarPath, String errorContext, int sizePx) { String server = serverURL(); if (server == null || server.isEmpty()) { Log.w(TAG, "Cannot generate " + errorContext + " avatar URI: serverURL is null"); @@ -67,7 +67,7 @@ private String buildAvatarUri(String avatarPath, String errorContext) { String userToken = token(); String uid = userId(); - String finalUri = server + avatarPath + "?format=png&size=100"; + String finalUri = server + avatarPath + "?format=png&size=" + sizePx; if (!userToken.isEmpty() && !uid.isEmpty()) { finalUri += "&rc_token=" + userToken + "&rc_uid=" + uid; } @@ -102,15 +102,37 @@ public String getAvatarUri() { } } - return buildAvatarUri(avatarPath, ""); + return buildAvatarUri(avatarPath, "", 100); } /** - * Generates avatar URI for video conference caller. + * Factory for building caller avatar URIs from host + username (e.g. VoIP payload). + * Caller is package-private, so this is the only way to get avatar URI from outside the package. + */ + public static Ejson forCallerAvatar(String host, String username) { + if (host == null || host.isEmpty() || username == null || username.isEmpty()) { + return null; + } + Ejson ejson = new Ejson(); + ejson.host = host; + ejson.caller = new Caller(); + ejson.caller.username = username; + return ejson; + } + + /** + * Generates avatar URI for video conference caller (default size 100). * Returns null if caller username is not available (username is required for avatar endpoint). */ public String getCallerAvatarUri() { - // Check if caller exists and has username (required - /avatar/{userId} endpoint doesn't exist) + return getCallerAvatarUri(100); + } + + /** + * Generates avatar URI for video conference caller with custom size. + * Returns null if caller username is not available. + */ + public String getCallerAvatarUri(int sizePx) { if (caller == null || caller.username == null || caller.username.isEmpty()) { Log.w(TAG, "Cannot generate caller avatar URI: caller or username is null"); return null; @@ -118,7 +140,7 @@ public String getCallerAvatarUri() { try { String avatarPath = "/avatar/" + URLEncoder.encode(caller.username, "UTF-8"); - return buildAvatarUri(avatarPath, "caller"); + return buildAvatarUri(avatarPath, "caller", sizePx); } catch (UnsupportedEncodingException e) { Log.e(TAG, "Failed to encode caller username", e); return null; diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index 1b5307ac4ce..2a3a19187e3 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -8,6 +8,9 @@ import com.google.gson.GsonBuilder import chat.rocket.reactnative.voip.VoipNotification import chat.rocket.reactnative.voip.VoipModule import chat.rocket.reactnative.voip.VoipPayload +import android.os.Build +import android.app.KeyguardManager +import android.app.Activity /** * Handles notification Intent processing from MainActivity. @@ -57,6 +60,15 @@ class NotificationIntentHandler { VoipNotification.cancelById(context, voipPayload.notificationId) VoipModule.storeInitialEvents(voipPayload) + if (context is Activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + context.setShowWhenLocked(true) + context.setTurnScreenOn(true) + val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager + keyguardManager.requestDismissKeyguard(context, null) + } + } + // Clear the voip flag to prevent re-processing intent.removeExtra("voipAction") diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt index 82da05741c3..0cf6b64a9d8 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt @@ -4,18 +4,25 @@ import android.app.Activity import android.app.KeyguardManager import android.content.Context import android.content.Intent +import android.graphics.drawable.GradientDrawable import android.media.Ringtone import android.media.RingtoneManager import android.os.Build import android.os.Bundle import android.view.WindowManager -import android.widget.ImageButton +import android.view.View import android.widget.ImageView +import androidx.core.content.ContextCompat +import android.widget.LinearLayout import android.widget.TextView +import android.widget.FrameLayout import android.util.Log -import androidx.core.content.ContextCompat +import android.view.ViewOutlineProvider +import com.bumptech.glide.Glide import chat.rocket.reactnative.MainActivity import chat.rocket.reactnative.R +import chat.rocket.reactnative.notification.Ejson +import android.graphics.Typeface /** * Full-screen Activity displayed when an incoming VoIP call arrives. @@ -56,6 +63,9 @@ class IncomingCallActivity : Activity() { window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) setContentView(R.layout.activity_incoming_call) + applyNavigationBar() + applyButtonBackgrounds() + applyInterFont() val voipPayload = VoipPayload.fromBundle(intent.extras) if (voipPayload == null || !voipPayload.isVoipIncomingCall()) { @@ -72,15 +82,123 @@ class IncomingCallActivity : Activity() { setupButtons(voipPayload) } + private fun applyNavigationBar() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + val bgColor = ContextCompat.getColor(this, R.color.incoming_call_background) + window.navigationBarColor = bgColor + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val isDarkTheme = (resources.configuration.uiMode and android.content.res.Configuration.UI_MODE_NIGHT_MASK) == + android.content.res.Configuration.UI_MODE_NIGHT_YES + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isDarkTheme) { + @Suppress("DEPRECATION") + window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR + } + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + window.isNavigationBarContrastEnforced = false + } + } + + /** + * Applies button background colors programmatically. Required on some devices (e.g. Samsung + * lock screen) where XML @color references may not resolve correctly in full-screen intent context. + */ + private fun applyButtonBackgrounds() { + val cornerRadiusPx = 8 * resources.displayMetrics.density + findViewById<FrameLayout>(R.id.btn_reject_bg)?.apply { + background = GradientDrawable().apply { + setColor(ContextCompat.getColor(this@IncomingCallActivity, R.color.incoming_call_reject_bg)) + cornerRadius = cornerRadiusPx + } + } + findViewById<FrameLayout>(R.id.btn_accept_bg)?.apply { + background = GradientDrawable().apply { + setColor(ContextCompat.getColor(this@IncomingCallActivity, R.color.incoming_call_accept_bg)) + cornerRadius = cornerRadiusPx + } + } + } + + private fun applyInterFont() { + val interRegular = try { + Typeface.createFromAsset(assets, "fonts/Inter-Regular.otf") + } catch (e: Exception) { + Log.e(TAG, "Failed to load Inter-Regular font", e) + return + } + val interBold = try { + Typeface.createFromAsset(assets, "fonts/Inter-Bold.otf") + } catch (e: Exception) { + Log.e(TAG, "Failed to load Inter-Bold font", e) + interRegular + } + listOf( + R.id.header_text, + R.id.host_name, + R.id.incoming_call_reject_label, + R.id.incoming_call_accept_label + ).forEach { id -> + findViewById<TextView>(id)?.setTypeface(interRegular) + } + findViewById<TextView>(R.id.caller_name)?.setTypeface(interBold) + } + private fun updateUI(payload: VoipPayload) { - val callerView = findViewById<TextView>(R.id.caller_name) - callerView?.text = payload.caller - - // Try to load avatar if available - // TODO: needs username to load avatar - val avatarView = findViewById<ImageView>(R.id.caller_avatar) - // Avatar loading would require additional data - can be enhanced later - // For now, just show a placeholder or default icon + findViewById<TextView>(R.id.caller_name)?.text = payload.caller.ifEmpty { getString(R.string.incoming_call_unknown_caller) } + findViewById<TextView>(R.id.host_name)?.text = payload.hostName.ifEmpty { getString(R.string.incoming_call_unknown_host) } + + loadAvatar(payload) + } + + private fun loadAvatar(payload: VoipPayload) { + if (payload.host.isBlank() || payload.username.isBlank()) return + + val container = findViewById<FrameLayout>(R.id.avatar_container) + val imageView = findViewById<ImageView>(R.id.avatar) + val sizePx = (120 * resources.displayMetrics.density).toInt().coerceIn(120, 480) + val avatarUrl = Ejson.forCallerAvatar(payload.host, payload.username)?.getCallerAvatarUri(sizePx) + ?: return + val cornerRadiusPx = (8 * resources.displayMetrics.density).toFloat() + + Glide.with(this) + .load(avatarUrl) + .into(object : com.bumptech.glide.request.target.CustomTarget<android.graphics.drawable.Drawable>(sizePx, sizePx) { + override fun onResourceReady( + resource: android.graphics.drawable.Drawable, + transition: com.bumptech.glide.request.transition.Transition<in android.graphics.drawable.Drawable>? + ) { + container.visibility = View.VISIBLE + imageView.setImageDrawable(resource) + applyAvatarRoundCorners(imageView, cornerRadiusPx) + } + + override fun onLoadFailed(errorDrawable: android.graphics.drawable.Drawable?) { + container.visibility = View.GONE + } + + override fun onLoadCleared(placeholder: android.graphics.drawable.Drawable?) { + container.visibility = View.GONE + } + }) + } + + /** + * Applies rounded corners via view-level clipping. + * Works for both PNG (BitmapDrawable) and SVG (vector/PictureDrawable) since + * Glide's RoundedCorners bitmap transform only applies to bitmaps. + */ + private fun applyAvatarRoundCorners(imageView: ImageView, cornerRadiusPx: Float) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return + imageView.post { + val radius = cornerRadiusPx + imageView.outlineProvider = object : ViewOutlineProvider() { + override fun getOutline(view: View, outline: android.graphics.Outline) { + outline.setRoundRect(0, 0, view.width, view.height, radius) + } + } + imageView.clipToOutline = true + } } private fun startRingtone() { @@ -105,14 +223,11 @@ class IncomingCallActivity : Activity() { } private fun setupButtons(payload: VoipPayload) { - val acceptButton = findViewById<ImageButton>(R.id.btn_accept) - val declineButton = findViewById<ImageButton>(R.id.btn_decline) - - acceptButton?.setOnClickListener { + findViewById<LinearLayout>(R.id.btn_accept)?.setOnClickListener { handleAccept(payload) } - declineButton?.setOnClickListener { + findViewById<LinearLayout>(R.id.btn_decline)?.setOnClickListener { handleDecline(payload) } } diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt index d1ffa2e53d7..e9971eca91a 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt @@ -5,7 +5,6 @@ import com.google.gson.annotations.SerializedName import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.WritableMap import chat.rocket.reactnative.utils.CallIdUUID -import android.util.Log data class VoipPayload( @SerializedName("callId") @@ -13,12 +12,18 @@ data class VoipPayload( @SerializedName("caller") val caller: String, + + @SerializedName("username") + val username: String, @SerializedName("host") val host: String, @SerializedName("type") - val type: String + val type: String, + + @SerializedName("hostName") + val hostName: String, ) { val notificationId: Int = callId.hashCode() val callUUID: String = CallIdUUID.generateUUIDv5(callId) @@ -31,8 +36,10 @@ data class VoipPayload( return Bundle().apply { putString("callId", callId) putString("caller", caller) + putString("username", username) putString("host", host) putString("type", type) + putString("hostName", hostName) putString("callUUID", callUUID) putInt("notificationId", notificationId) // Useful flag for MainActivity to know it's handling a VoIP action @@ -44,8 +51,10 @@ data class VoipPayload( return Arguments.createMap().apply { putString("callId", callId) putString("caller", caller) + putString("username", username) putString("host", host) putString("type", type) + putString("hostName", hostName) putString("callUUID", callUUID) putInt("notificationId", notificationId) } @@ -53,24 +62,27 @@ data class VoipPayload( companion object { fun fromMap(data: Map<String, String>): VoipPayload? { - Log.d("RocketChat.VoipPayload", "Parsing VoIP payload from map: $data") val type = data["type"] ?: return null val callId = data["callId"] ?: return null val caller = data["caller"] ?: return null + val username = data["username"] ?: return null val host = data["host"] ?: return null + val hostName = data["hostName"] ?: return null if (type != "incoming_call") return null - return VoipPayload(callId, caller, host, type) + return VoipPayload(callId, caller, username, host, type, hostName) } fun fromBundle(bundle: Bundle?): VoipPayload? { if (bundle == null) return null val callId = bundle.getString("callId") ?: return null - val caller = bundle.getString("caller") ?: "" - val host = bundle.getString("host") ?: "" - val type = bundle.getString("type") ?: "" + val caller = bundle.getString("caller") ?: return null + val username = bundle.getString("username") ?: return null + val host = bundle.getString("host") ?: return null + val type = bundle.getString("type") ?: return null + val hostName = bundle.getString("hostName") ?: return null - return VoipPayload(callId, caller, host, type) + return VoipPayload(callId, caller, username, host, type, hostName) } } } \ No newline at end of file diff --git a/android/app/src/main/res/drawable/bg_avatar_incoming_call.xml b/android/app/src/main/res/drawable/bg_avatar_incoming_call.xml new file mode 100644 index 00000000000..15b9de09786 --- /dev/null +++ b/android/app/src/main/res/drawable/bg_avatar_incoming_call.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@color/incoming_call_avatar_bg"/> + <corners android:radius="8dp"/> +</shape> diff --git a/android/app/src/main/res/drawable/bg_btn_accept.xml b/android/app/src/main/res/drawable/bg_btn_accept.xml new file mode 100644 index 00000000000..e6f8ea9891c --- /dev/null +++ b/android/app/src/main/res/drawable/bg_btn_accept.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@color/incoming_call_accept_bg"/> + <corners android:radius="8dp"/> +</shape> diff --git a/android/app/src/main/res/drawable/bg_btn_reject.xml b/android/app/src/main/res/drawable/bg_btn_reject.xml new file mode 100644 index 00000000000..8f9083b8279 --- /dev/null +++ b/android/app/src/main/res/drawable/bg_btn_reject.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@color/incoming_call_reject_bg"/> + <corners android:radius="8dp"/> +</shape> diff --git a/android/app/src/main/res/drawable/ic_call.xml b/android/app/src/main/res/drawable/ic_call.xml new file mode 100644 index 00000000000..6d6192d7ca1 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_call.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportWidth="32" + android:viewportHeight="32"> + <path + android:pathData="M11.157,6.042C11.936,5.94 12.696,6.304 13.109,6.961L13.186,7.096L15.026,10.606C15.124,10.793 15.192,10.994 15.227,11.202C15.259,11.393 15.263,11.58 15.246,11.751L15.244,11.762C15.2,12.173 15.038,12.535 14.821,12.821L14.693,12.992C14.649,13.053 14.609,13.113 14.574,13.171L14.477,13.342C14.465,13.368 14.455,13.392 14.446,13.413L14.526,13.556C14.587,13.655 14.664,13.764 14.752,13.884L15.049,14.266C15.484,14.802 16.006,15.359 16.348,15.702C16.605,15.959 16.982,16.316 17.381,16.662L17.782,17C18.053,17.219 18.296,17.401 18.492,17.523C18.547,17.558 18.596,17.583 18.636,17.604L18.707,17.572C18.81,17.522 18.931,17.448 19.057,17.357L19.227,17.227L19.228,17.229C19.511,17.014 19.875,16.848 20.293,16.804L20.302,16.803C20.484,16.785 20.631,16.796 20.706,16.803C20.749,16.808 20.787,16.812 20.818,16.817C20.833,16.819 20.848,16.823 20.861,16.825C20.868,16.826 20.875,16.828 20.882,16.829C20.885,16.829 20.887,16.83 20.89,16.831C20.892,16.831 20.894,16.831 20.895,16.832H20.898C21.088,16.869 21.273,16.933 21.444,17.023L24.953,18.863C25.695,19.252 26.116,20.062 26.007,20.892C25.877,21.894 25.464,23.215 24.68,24.263L24.518,24.469C24.049,25.037 23.415,25.559 22.601,25.814L22.444,25.86C21.659,26.067 20.831,25.993 20.004,25.65L19.699,25.518C18.175,24.834 16.567,23.738 15.234,22.714L14.71,22.302C13.514,21.349 12.538,20.462 12.062,19.986L11.563,19.463C10.978,18.83 10.162,17.89 9.336,16.815L8.923,16.267C7.957,14.961 6.985,13.457 6.4,12.046L6.277,11.715C6.042,10.997 6.01,10.285 6.189,9.605L6.234,9.448L6.342,9.15C6.581,8.573 6.955,8.097 7.37,7.715L7.581,7.531C8.657,6.642 10.089,6.181 11.157,6.042ZM11.415,8.025C10.657,8.124 9.693,8.443 8.991,8.966L8.854,9.072C8.494,9.37 8.251,9.7 8.142,10.047C8.051,10.337 8.04,10.679 8.178,11.095L8.248,11.279C8.744,12.476 9.606,13.826 10.525,15.07L10.922,15.595C11.976,16.967 13,18.096 13.477,18.573C13.954,19.05 15.083,20.073 16.454,21.128L16.979,21.523C18.222,22.442 19.573,23.305 20.769,23.802C21.271,24.01 21.671,24.011 22.003,23.907C22.35,23.798 22.679,23.555 22.976,23.195C23.489,22.575 23.826,21.698 23.973,20.948L24.024,20.635L20.514,18.795L20.499,18.794C20.49,18.795 20.479,18.798 20.468,18.802L20.433,18.824L20.245,18.965C20.097,19.073 19.933,19.181 19.76,19.277L19.585,19.368C19.287,19.513 18.878,19.662 18.437,19.621L18.298,19.6C17.974,19.535 17.661,19.36 17.433,19.219C17.285,19.126 17.132,19.021 16.979,18.908L16.522,18.552C15.92,18.064 15.312,17.495 14.934,17.117C14.556,16.739 13.985,16.13 13.496,15.527C13.252,15.227 13.015,14.91 12.831,14.615C12.689,14.388 12.514,14.075 12.449,13.752L12.428,13.612C12.387,13.171 12.535,12.762 12.68,12.465C12.796,12.227 12.94,12.002 13.084,11.804L13.225,11.616C13.243,11.593 13.253,11.568 13.255,11.55C13.256,11.543 13.256,11.537 13.255,11.535L11.415,8.025Z" + android:fillColor="#ffffff"/> +</vector> diff --git a/android/app/src/main/res/drawable/ic_call_end.xml b/android/app/src/main/res/drawable/ic_call_end.xml new file mode 100644 index 00000000000..443ec5c0aeb --- /dev/null +++ b/android/app/src/main/res/drawable/ic_call_end.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportWidth="32" + android:viewportHeight="32"> + <path + android:pathData="M15.999,11L16.723,11.017C17.584,11.05 18.826,11.139 20.17,11.314L20.849,11.41C22.456,11.651 24.207,12.026 25.619,12.61L25.94,12.758C26.613,13.099 27.139,13.58 27.494,14.188L27.573,14.33L27.706,14.617C27.945,15.194 28.018,15.795 27.996,16.359L27.976,16.638C27.844,18.027 27.157,19.366 26.5,20.22C26.021,20.842 25.226,21.123 24.47,20.95L24.32,20.909L20.537,19.729C20.335,19.666 20.145,19.571 19.973,19.449C19.815,19.337 19.682,19.207 19.573,19.074L19.565,19.065C19.305,18.743 19.164,18.372 19.116,18.017L19.115,18.018L19.085,17.806C19.073,17.731 19.059,17.66 19.043,17.595L18.99,17.405C18.98,17.378 18.971,17.354 18.962,17.333L18.804,17.289C18.691,17.263 18.56,17.239 18.413,17.217L17.932,17.156C17.245,17.085 16.483,17.06 15.998,17.06C15.635,17.06 15.116,17.074 14.59,17.111L14.067,17.156C13.72,17.192 13.42,17.236 13.195,17.288L13.196,17.289C13.132,17.304 13.079,17.32 13.036,17.333L13.009,17.405C12.972,17.514 12.938,17.651 12.913,17.806L12.884,18.018L12.882,18.017C12.834,18.369 12.695,18.743 12.43,19.069L12.423,19.077C12.307,19.219 12.197,19.315 12.139,19.362C12.105,19.39 12.075,19.413 12.049,19.432C12.036,19.441 12.024,19.449 12.013,19.457C12.007,19.461 12.002,19.465 11.997,19.469C11.994,19.471 11.991,19.472 11.989,19.474L11.985,19.477L11.983,19.479C11.823,19.586 11.646,19.671 11.461,19.729L7.679,20.909C6.88,21.159 6.009,20.883 5.498,20.22C4.883,19.419 4.24,18.192 4.053,16.897L4.023,16.638C3.953,15.904 4.031,15.087 4.426,14.331L4.505,14.188C4.914,13.487 5.551,12.953 6.379,12.61L6.688,12.488C8.249,11.894 10.161,11.533 11.828,11.314L12.491,11.234C14.01,11.062 15.326,11 15.999,11ZM15.998,13C15.324,13 13.802,13.074 12.087,13.298L11.436,13.39C9.907,13.619 8.342,13.964 7.145,14.459C6.643,14.667 6.36,14.949 6.199,15.257C6.03,15.579 5.969,15.983 6.013,16.448C6.09,17.249 6.471,18.108 6.898,18.742L7.083,19L10.866,17.819L10.877,17.809C10.883,17.802 10.888,17.792 10.893,17.781L10.903,17.741L10.936,17.508C10.965,17.327 11.004,17.135 11.058,16.944L11.118,16.756C11.225,16.443 11.409,16.048 11.75,15.766L11.864,15.682C12.138,15.499 12.483,15.401 12.745,15.341C12.914,15.302 13.097,15.268 13.286,15.239L13.86,15.167C14.631,15.087 15.464,15.06 15.998,15.06C16.533,15.06 17.367,15.087 18.139,15.167C18.524,15.207 18.915,15.262 19.254,15.341C19.515,15.401 19.861,15.499 20.135,15.682L20.249,15.766C20.59,16.048 20.774,16.443 20.881,16.756C20.967,17.006 21.025,17.267 21.063,17.508L21.096,17.741C21.1,17.771 21.111,17.795 21.122,17.809C21.126,17.815 21.131,17.818 21.132,17.819L24.916,19C25.381,18.395 25.837,17.487 25.964,16.621L25.986,16.448C26.03,15.983 25.969,15.579 25.8,15.257C25.659,14.987 25.425,14.737 25.033,14.54L24.854,14.459C23.657,13.964 22.092,13.619 20.563,13.39L19.912,13.298C18.196,13.074 16.673,13 15.998,13Z" + android:fillColor="#ffffff"/> +</vector> diff --git a/android/app/src/main/res/layout/activity_incoming_call.xml b/android/app/src/main/res/layout/activity_incoming_call.xml index d025d991c16..051011e0e8e 100644 --- a/android/app/src/main/res/layout/activity_incoming_call.xml +++ b/android/app/src/main/res/layout/activity_incoming_call.xml @@ -1,72 +1,177 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical" - android:gravity="center" - android:background="#000000" - android:padding="32dp"> - - <!-- Caller Avatar --> - <ImageView - android:id="@+id/caller_avatar" - android:layout_width="120dp" - android:layout_height="120dp" - android:layout_marginBottom="24dp" - android:src="@mipmap/ic_launcher" - android:contentDescription="Caller avatar" - android:scaleType="centerCrop" - android:background="@android:drawable/dialog_holo_light_frame" /> - - <!-- Caller Name --> - <TextView - android:id="@+id/caller_name" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="8dp" - android:text="Unknown" - android:textColor="#FFFFFF" - android:textSize="28sp" - android:textStyle="bold" /> - - <!-- Incoming Call Label --> - <TextView - android:id="@+id/incoming_label" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="48dp" - android:text="Incoming call" - android:textColor="#CCCCCC" - android:textSize="16sp" /> + android:background="@color/incoming_call_background" + android:orientation="vertical"> - <!-- Action Buttons --> + <!-- Top: Incoming call status with icon --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal" android:gravity="center" - android:layout_marginTop="32dp"> + android:orientation="horizontal" + android:paddingTop="108dp"> + + <ImageView + android:id="@+id/header_icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_marginEnd="8dp" + android:src="@drawable/ic_notification" + android:tint="@color/incoming_call_header_icon" /> + + <TextView + android:id="@+id/header_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:fontFamily="sans-serif" + android:text="@string/incoming_call_status" + android:textColor="@color/incoming_call_header_text" + android:textSize="18sp" /> + + </LinearLayout> + + <!-- Center: Avatar, caller name, host name --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:gravity="center_horizontal" + android:layout_marginTop="56dp" + android:orientation="vertical"> + + <FrameLayout + android:id="@+id/avatar_container" + android:layout_width="120dp" + android:layout_height="120dp" + android:layout_marginBottom="24dp"> + + <ImageView + android:id="@+id/avatar" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:contentDescription="@string/incoming_call_avatar_description" + android:scaleType="centerCrop" /> + + </FrameLayout> + + <!-- Caller name --> + <TextView + android:id="@+id/caller_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:textColor="@color/incoming_call_name" + android:textSize="22sp" + android:textStyle="bold" + tools:text="Unknown caller" /> + + <!-- Host name --> + <TextView + android:id="@+id/host_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:text="Unknown host" + android:textColor="@color/incoming_call_host_name" + android:textSize="18sp" /> + + </LinearLayout> - <!-- Decline Button --> - <ImageButton + <!-- Bottom: Action buttons - Reject 44dp from left, Accept 44dp from right --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="24dp" + android:layout_marginBottom="48dp" + android:orientation="horizontal"> + + <!-- Reject button - 44dp from left --> + <LinearLayout android:id="@+id/btn_decline" - android:layout_width="80dp" - android:layout_height="80dp" - android:layout_marginEnd="32dp" - android:background="@android:drawable/ic_menu_close_clear_cancel" - android:backgroundTint="#F44336" - android:contentDescription="Decline call" - android:scaleType="centerInside" /> - - <!-- Accept Button --> - <ImageButton + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="44dp" + android:background="?attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:gravity="center" + android:orientation="vertical" + android:padding="16dp"> + + <FrameLayout + android:id="@+id/btn_reject_bg" + android:layout_width="64dp" + android:layout_height="64dp" + android:background="@drawable/bg_btn_reject" + android:gravity="center"> + + <ImageView + android:layout_width="36dp" + android:layout_height="36dp" + android:layout_gravity="center" + android:contentDescription="@string/incoming_call_reject" + android:src="@drawable/ic_call_end" /> + + </FrameLayout> + + <TextView + android:id="@+id/incoming_call_reject_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/incoming_call_reject" + android:textColor="@color/incoming_call_button_label" + android:textSize="14sp" /> + + </LinearLayout> + + <!-- Spacer to push buttons to opposite sides --> + <View + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="1" /> + + <!-- Accept button - 44dp from right --> + <LinearLayout android:id="@+id/btn_accept" - android:layout_width="80dp" - android:layout_height="80dp" - android:background="@android:drawable/ic_menu_call" - android:backgroundTint="#4CAF50" - android:contentDescription="Accept call" - android:scaleType="centerInside" /> + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="44dp" + android:background="?attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" + android:gravity="center" + android:orientation="vertical" + android:padding="16dp"> + + <FrameLayout + android:id="@+id/btn_accept_bg" + android:layout_width="64dp" + android:layout_height="64dp" + android:background="@drawable/bg_btn_accept" + android:gravity="center"> + + <ImageView + android:layout_width="36dp" + android:layout_height="36dp" + android:layout_gravity="center" + android:contentDescription="@string/incoming_call_accept" + android:src="@drawable/ic_call" /> + + </FrameLayout> + + <TextView + android:id="@+id/incoming_call_accept_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/incoming_call_accept" + android:textColor="@color/incoming_call_button_label" + android:textSize="14sp" /> + + </LinearLayout> </LinearLayout> diff --git a/android/app/src/main/res/values-night/colors_incoming_call.xml b/android/app/src/main/res/values-night/colors_incoming_call.xml new file mode 100644 index 00000000000..4e1b5e4533f --- /dev/null +++ b/android/app/src/main/res/values-night/colors_incoming_call.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Dark theme - mapped from app/lib/constants/colors.ts --> + <color name="incoming_call_background">#1F2329</color> + <color name="incoming_call_header_text">#9EA2A8</color> + <color name="incoming_call_header_icon">#9EA2A8</color> + <color name="incoming_call_name">#F2F3F5</color> + <color name="incoming_call_host_name">#9EA2A8</color> + <color name="incoming_call_avatar_bg">#5F1477</color> + <color name="incoming_call_avatar_text">#FFFFFF</color> + <color name="incoming_call_reject_bg">#BB3E4E</color> + <color name="incoming_call_accept_bg">#1D7256</color> + <color name="incoming_call_button_label">#F2F3F5</color> + <color name="incoming_call_button_icon">#FFFFFF</color> +</resources> diff --git a/android/app/src/main/res/values-night/styles_incoming_call.xml b/android/app/src/main/res/values-night/styles_incoming_call.xml new file mode 100644 index 00000000000..ba0e5185440 --- /dev/null +++ b/android/app/src/main/res/values-night/styles_incoming_call.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <style name="Theme.IncomingCall" parent="Theme.AppCompat.DayNight.NoActionBar"> + <item name="android:windowNoTitle">true</item> + <item name="android:windowIsTranslucent">false</item> + <item name="android:windowBackground">@color/incoming_call_background</item> + <item name="android:windowDisablePreview">true</item> + <item name="android:windowDrawsSystemBarBackgrounds">true</item> + <item name="android:statusBarColor">@color/incoming_call_background</item> + <item name="android:navigationBarColor">@color/incoming_call_background</item> + </style> +</resources> diff --git a/android/app/src/main/res/values/colors_incoming_call.xml b/android/app/src/main/res/values/colors_incoming_call.xml new file mode 100644 index 00000000000..14984e230a4 --- /dev/null +++ b/android/app/src/main/res/values/colors_incoming_call.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Light theme - mapped from app/lib/constants/colors.ts --> + <color name="incoming_call_background">#FFFFFF</color> + <color name="incoming_call_header_text">#6C727A</color> + <color name="incoming_call_header_icon">#6C727A</color> + <color name="incoming_call_name">#1F2329</color> + <color name="incoming_call_host_name">#6C727A</color> + <color name="incoming_call_avatar_bg">#5F1477</color> + <color name="incoming_call_avatar_text">#FFFFFF</color> + <color name="incoming_call_reject_bg">#EC0D2A</color> + <color name="incoming_call_accept_bg">#158D65</color> + <color name="incoming_call_button_label">#1F2329</color> + <color name="incoming_call_button_icon">#FFFFFF</color> +</resources> diff --git a/android/app/src/main/res/values/strings_incoming_call.xml b/android/app/src/main/res/values/strings_incoming_call.xml new file mode 100644 index 00000000000..bb4905d72da --- /dev/null +++ b/android/app/src/main/res/values/strings_incoming_call.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="incoming_call_status">Incoming call…</string> + <string name="incoming_call_reject">Reject</string> + <string name="incoming_call_accept">Accept</string> + <string name="incoming_call_avatar_description">Caller avatar</string> + <string name="incoming_call_unknown_caller">Unknown caller</string> + <string name="incoming_call_unknown_host">Unknown host</string> +</resources> diff --git a/android/app/src/main/res/values/styles_incoming_call.xml b/android/app/src/main/res/values/styles_incoming_call.xml index a5a7484c14d..ba0e5185440 100644 --- a/android/app/src/main/res/values/styles_incoming_call.xml +++ b/android/app/src/main/res/values/styles_incoming_call.xml @@ -2,11 +2,11 @@ <resources> <style name="Theme.IncomingCall" parent="Theme.AppCompat.DayNight.NoActionBar"> <item name="android:windowNoTitle">true</item> - <item name="android:windowFullscreen">true</item> <item name="android:windowIsTranslucent">false</item> - <item name="android:windowBackground">@android:color/black</item> + <item name="android:windowBackground">@color/incoming_call_background</item> <item name="android:windowDisablePreview">true</item> - <item name="android:statusBarColor">@android:color/transparent</item> - <item name="android:navigationBarColor">@android:color/transparent</item> + <item name="android:windowDrawsSystemBarBackgrounds">true</item> + <item name="android:statusBarColor">@color/incoming_call_background</item> + <item name="android:navigationBarColor">@color/incoming_call_background</item> </style> </resources> diff --git a/packages/rocket.chat-media-signaling-0.1.0.tgz b/packages/rocket.chat-media-signaling-0.1.0.tgz index 59bca49a746265a489a48276cff4b6018a873f6b..52ffe0f9308c843b85ce5f4f652b1ebbf36b929a 100644 GIT binary patch literal 62589 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%0AF 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 OKK~DB$<4$7C<g$o<y@%% literal 56685 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%0DVkzpMP?g%Za}Vg*F; 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 From fc9aca694eef7e35a1a67cb365399b41f6afd9bc Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 18 Feb 2026 16:31:57 -0300 Subject: [PATCH 49/61] feat: Update call UI (#6990) --- app/AppContainer.tsx | 4 +- .../MediaCallHeader.stories.tsx | 104 + .../MediaCallHeader/MediaCallHeader.test.tsx | 172 ++ .../MediaCallHeader.tsx} | 19 +- .../MediaCallHeader.test.tsx.snap | 2094 +++++++++++++++++ .../components/Collapse.tsx | 2 + .../MediaCallHeader/components/Content.tsx | 26 + .../components/EndCall.tsx | 8 +- .../MediaCallHeader/components/Subtitle.tsx | 51 + .../components/Timer.tsx | 2 +- .../components/Title.tsx | 33 +- app/lib/services/voip/useCallStore.ts | 80 +- app/views/CallView/CallView.stories.tsx | 15 +- .../__snapshots__/index.test.tsx.snap | 447 +--- app/views/CallView/components/CallButtons.tsx | 83 + .../CallView/components/CallStatusText.tsx | 34 - .../components/CallerInfo.stories.tsx | 12 +- .../CallView/components/CallerInfo.test.tsx | 52 +- app/views/CallView/components/CallerInfo.tsx | 30 +- .../__snapshots__/CallerInfo.test.tsx.snap | 533 +---- app/views/CallView/index.test.tsx | 11 +- app/views/CallView/index.tsx | 85 +- app/views/CallView/styles.ts | 3 +- 23 files changed, 2686 insertions(+), 1214 deletions(-) create mode 100644 app/containers/MediaCallHeader/MediaCallHeader.stories.tsx create mode 100644 app/containers/MediaCallHeader/MediaCallHeader.test.tsx rename app/containers/{CallHeader/CallHeader.tsx => MediaCallHeader/MediaCallHeader.tsx} (65%) create mode 100644 app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap rename app/containers/{CallHeader => MediaCallHeader}/components/Collapse.tsx (94%) create mode 100644 app/containers/MediaCallHeader/components/Content.tsx rename app/containers/{CallHeader => MediaCallHeader}/components/EndCall.tsx (71%) create mode 100644 app/containers/MediaCallHeader/components/Subtitle.tsx rename app/containers/{CallHeader => MediaCallHeader}/components/Timer.tsx (95%) rename app/containers/{CallHeader => MediaCallHeader}/components/Title.tsx (56%) create mode 100644 app/views/CallView/components/CallButtons.tsx delete mode 100644 app/views/CallView/components/CallStatusText.tsx diff --git a/app/AppContainer.tsx b/app/AppContainer.tsx index 8200dcb773f..53701f36def 100644 --- a/app/AppContainer.tsx +++ b/app/AppContainer.tsx @@ -19,7 +19,7 @@ import { ThemeContext } from './theme'; import { setCurrentScreen } from './lib/methods/helpers/log'; import { themes } from './lib/constants/colors'; import { emitter } from './lib/methods/helpers'; -import CallHeader from './containers/CallHeader/CallHeader'; +import MediaCallHeader from './containers/MediaCallHeader/MediaCallHeader'; const createStackNavigator = createNativeStackNavigator; @@ -53,7 +53,7 @@ const App = memo(({ root, isMasterDetail }: { root: string; isMasterDetail: bool return ( <> - <CallHeader /> + <MediaCallHeader /> <NavigationContainer theme={navTheme} ref={Navigation.navigationRef} diff --git a/app/containers/MediaCallHeader/MediaCallHeader.stories.tsx b/app/containers/MediaCallHeader/MediaCallHeader.stories.tsx new file mode 100644 index 00000000000..ea8b5618ae2 --- /dev/null +++ b/app/containers/MediaCallHeader/MediaCallHeader.stories.tsx @@ -0,0 +1,104 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; + +import MediaCallHeader from './MediaCallHeader'; +import { useCallStore } from '../../lib/services/voip/useCallStore'; + +const styles = StyleSheet.create({ + container: { + flex: 1 + } +}); + +const mockCallStartTime = 1713340800000; + +// Helper to set store state for stories +const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getState>> = {}) => { + const mockCall = { + state: 'active', + muted: false, + held: false, + contact: { + displayName: 'Bob Burnquist', + username: 'bob.burnquist', + sipExtension: '2244' + }, + setMuted: () => {}, + setHeld: () => {}, + hangup: () => {}, + reject: () => {}, + emitter: { + on: () => {}, + off: () => {} + } + } as any; + + useCallStore.setState({ + call: mockCall, + callUUID: 'test-uuid', + callState: 'active', + isMuted: false, + isOnHold: false, + isSpeakerOn: false, + callStartTime: mockCallStartTime, + contact: { + id: 'user-1', + displayName: 'Bob Burnquist', + username: 'bob.burnquist', + sipExtension: '2244' + }, + focused: true, + remoteMute: false, + remoteHeld: false, + ...overrides + }); +}; + +const Wrapper = ({ children }: { children: React.ReactNode }) => <View style={styles.container}>{children}</View>; + +export default { + title: 'MediaCallHeader', + component: MediaCallHeader, + decorators: [ + (Story: React.ComponentType) => ( + <Wrapper> + <Story /> + </Wrapper> + ) + ] +}; + +export const NoCall = () => { + useCallStore.setState({ call: null }); + return <MediaCallHeader />; +}; + +export const ActiveCall = () => { + setStoreState({ callState: 'active', callStartTime: mockCallStartTime }); + return <MediaCallHeader />; +}; + +export const ConnectingCall = () => { + setStoreState({ callState: 'accepted', callStartTime: null }); + return <MediaCallHeader />; +}; + +export const Focused = () => { + setStoreState({ focused: true }); + return <MediaCallHeader />; +}; + +export const Collapsed = () => { + setStoreState({ focused: false }); + return <MediaCallHeader />; +}; + +export const WithRemoteHeld = () => { + setStoreState({ callState: 'active', remoteHeld: true }); + return <MediaCallHeader />; +}; + +export const WithRemoteMuted = () => { + setStoreState({ callState: 'active', remoteMute: true }); + return <MediaCallHeader />; +}; diff --git a/app/containers/MediaCallHeader/MediaCallHeader.test.tsx b/app/containers/MediaCallHeader/MediaCallHeader.test.tsx new file mode 100644 index 00000000000..c63e829ac9e --- /dev/null +++ b/app/containers/MediaCallHeader/MediaCallHeader.test.tsx @@ -0,0 +1,172 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import MediaCallHeader from './MediaCallHeader'; +import { useCallStore } from '../../lib/services/voip/useCallStore'; +import { mockedStore } from '../../reducers/mockedStore'; +import * as stories from './MediaCallHeader.stories'; +import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; + +// Mock alert +global.alert = jest.fn(); + +// Helper to create a mock call +const createMockCall = (overrides: Record<string, unknown> = {}) => ({ + state: 'active', + muted: false, + held: false, + contact: { + displayName: 'Bob Burnquist', + username: 'bob.burnquist', + sipExtension: '2244' + }, + setMuted: jest.fn(), + setHeld: jest.fn(), + hangup: jest.fn(), + reject: jest.fn(), + emitter: { + on: jest.fn(), + off: jest.fn() + }, + ...overrides +}); + +// Helper to set store state for tests +const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getState>> = {}) => { + const mockCall = createMockCall(); + useCallStore.setState({ + call: mockCall as any, + callUUID: 'test-uuid', + callState: 'active', + isMuted: false, + isOnHold: false, + isSpeakerOn: false, + callStartTime: Date.now(), + contact: { + id: 'user-1', + displayName: 'Bob Burnquist', + username: 'bob.burnquist', + sipExtension: '2244' + }, + focused: true, + remoteMute: false, + remoteHeld: false, + ...overrides + }); +}; + +const Wrapper = ({ children }: { children: React.ReactNode }) => ( + <Provider store={mockedStore}>{children}</Provider> +); + +describe('MediaCallHeader', () => { + beforeEach(() => { + useCallStore.getState().reset(); + jest.clearAllMocks(); + }); + + it('should render empty placeholder when there is no call', () => { + useCallStore.setState({ call: null }); + const { getByTestId, queryByTestId } = render( + <Wrapper> + <MediaCallHeader /> + </Wrapper> + ); + + expect(getByTestId('media-call-header-empty')).toBeTruthy(); + expect(queryByTestId('media-call-header')).toBeNull(); + expect(queryByTestId('media-call-header-collapse')).toBeNull(); + expect(queryByTestId('media-call-header-content')).toBeNull(); + expect(queryByTestId('media-call-header-end')).toBeNull(); + }); + + it('should render full header when call exists', () => { + setStoreState(); + const { getByTestId } = render( + <Wrapper> + <MediaCallHeader /> + </Wrapper> + ); + + expect(getByTestId('media-call-header')).toBeTruthy(); + expect(getByTestId('media-call-header-collapse')).toBeTruthy(); + expect(getByTestId('media-call-header-content')).toBeTruthy(); + expect(getByTestId('media-call-header-end')).toBeTruthy(); + }); + + it('should show caller name in Title', () => { + setStoreState({ + contact: { + id: 'user-1', + displayName: 'Alice Smith', + username: 'alice.smith', + sipExtension: '1234' + } + }); + const { getByTestId, getByText } = render( + <Wrapper> + <MediaCallHeader /> + </Wrapper> + ); + + expect(getByTestId('call-view-header-title')).toBeTruthy(); + // Title renders name plus optional Timer in nested Text; match by regex + expect(getByText(/Alice Smith/)).toBeTruthy(); + }); + + it('should show subtitle when connecting', () => { + setStoreState({ callState: 'ringing' }); + const { getByTestId } = render( + <Wrapper> + <MediaCallHeader /> + </Wrapper> + ); + + expect(getByTestId('call-view-header-subtitle')).toBeTruthy(); + }); + + it('should call toggleFocus when collapse button is pressed', () => { + setStoreState(); + const toggleFocus = jest.fn(); + useCallStore.setState({ toggleFocus }); + + const { getByTestId } = render( + <Wrapper> + <MediaCallHeader /> + </Wrapper> + ); + + fireEvent.press(getByTestId('media-call-header-collapse')); + expect(toggleFocus).toHaveBeenCalledTimes(1); + }); + + it('should call endCall when end button is pressed', () => { + setStoreState(); + const endCall = jest.fn(); + useCallStore.setState({ endCall }); + + const { getByTestId } = render( + <Wrapper> + <MediaCallHeader /> + </Wrapper> + ); + + fireEvent.press(getByTestId('media-call-header-end')); + expect(endCall).toHaveBeenCalledTimes(1); + }); + + it('should show alert when content is pressed', () => { + setStoreState(); + const { getByTestId } = render( + <Wrapper> + <MediaCallHeader /> + </Wrapper> + ); + + fireEvent.press(getByTestId('media-call-header-content')); + expect(global.alert).toHaveBeenCalledWith('nav to call room'); + }); +}); + +generateSnapshots(stories); diff --git a/app/containers/CallHeader/CallHeader.tsx b/app/containers/MediaCallHeader/MediaCallHeader.tsx similarity index 65% rename from app/containers/CallHeader/CallHeader.tsx rename to app/containers/MediaCallHeader/MediaCallHeader.tsx index 37f4f2d61ed..a3a0fa3ad14 100644 --- a/app/containers/CallHeader/CallHeader.tsx +++ b/app/containers/MediaCallHeader/MediaCallHeader.tsx @@ -1,11 +1,12 @@ import { StyleSheet, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import { useShallow } from 'zustand/react/shallow'; import { useTheme } from '../../theme'; import Collapse from './components/Collapse'; -import Title from './components/Title'; import EndCall from './components/EndCall'; import { useCallStore } from '../../lib/services/voip/useCallStore'; +import { Content } from './components/Content'; const styles = StyleSheet.create({ header: { @@ -13,34 +14,34 @@ const styles = StyleSheet.create({ justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 12, - paddingBottom: 4, borderBottomWidth: StyleSheet.hairlineWidth } }); -const CallHeader = () => { +const MediaCallHeader = () => { 'use memo'; const { colors } = useTheme(); const insets = useSafeAreaInsets(); + const call = useCallStore(useShallow(state => state.call)); const defaultHeaderStyle = { backgroundColor: colors.surfaceNeutral, - paddingTop: insets.top + paddingTop: insets.top + 12, + paddingBottom: 12 }; - const call = useCallStore(state => state.call); if (!call) { - return <View style={defaultHeaderStyle} />; + return <View style={defaultHeaderStyle} testID='media-call-header-empty' />; } return ( - <View style={[styles.header, { ...defaultHeaderStyle, borderBottomColor: colors.strokeLight }]}> + <View style={[styles.header, { ...defaultHeaderStyle, borderBottomColor: colors.strokeLight }]} testID='media-call-header'> <Collapse /> - <Title /> + <Content /> <EndCall /> </View> ); }; -export default CallHeader; +export default MediaCallHeader; diff --git a/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap new file mode 100644 index 00000000000..46805f06c9a --- /dev/null +++ b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap @@ -0,0 +1,2094 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: ActiveCall should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "alignItems": "center", + "borderBottomWidth": 0.5, + "flexDirection": "row", + "justifyContent": "space-between", + "paddingHorizontal": 12, + }, + { + "backgroundColor": "#E4E7EA", + "borderBottomColor": "#CBCED1", + "paddingBottom": 12, + "paddingTop": 12, + }, + ] + } + testID="media-call-header" + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginLeft": -5, + "marginRight": 0, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={13} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-collapse" + > + <View + accessibilityLabel="[missing "en.Minimize" translation]" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "flex": 1, + "paddingHorizontal": 4, + } + } + testID="media-call-header-content" + > + <View + style={ + { + "alignItems": "flex-start", + "flex": 1, + "flexDirection": "column", + "justifyContent": "space-evenly", + } + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "gap": 4, + } + } + testID="call-view-header-title" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 12, + }, + [ + { + "lineHeight": 12, + }, + [ + { + "height": 12, + "textAlignVertical": "center", + "width": 12, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "lineHeight": 24, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Bob Burnquist + <Text> + - + 16117:18:53 + </Text> + </Text> + </View> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "lineHeight": 16, + "textAlign": "left", + }, + { + "color": "#6C727A", + }, + ] + } + testID="call-view-header-subtitle" + > + 2244 + </Text> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginRight": -5, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={14} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-end" + > + <View + accessibilityLabel="End" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: Collapsed should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "alignItems": "center", + "borderBottomWidth": 0.5, + "flexDirection": "row", + "justifyContent": "space-between", + "paddingHorizontal": 12, + }, + { + "backgroundColor": "#E4E7EA", + "borderBottomColor": "#CBCED1", + "paddingBottom": 12, + "paddingTop": 12, + }, + ] + } + testID="media-call-header" + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginLeft": -5, + "marginRight": 0, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={15} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-collapse" + > + <View + accessibilityLabel="[missing "en.Minimize" translation]" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "flex": 1, + "paddingHorizontal": 4, + } + } + testID="media-call-header-content" + > + <View + style={ + { + "alignItems": "flex-start", + "flex": 1, + "flexDirection": "column", + "justifyContent": "space-evenly", + } + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "gap": 4, + } + } + testID="call-view-header-title" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 12, + }, + [ + { + "lineHeight": 12, + }, + [ + { + "height": 12, + "textAlignVertical": "center", + "width": 12, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "lineHeight": 24, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Bob Burnquist + <Text> + - + 16117:18:53 + </Text> + </Text> + </View> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "lineHeight": 16, + "textAlign": "left", + }, + { + "color": "#6C727A", + }, + ] + } + testID="call-view-header-subtitle" + > + 2244 + </Text> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginRight": -5, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={16} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-end" + > + <View + accessibilityLabel="End" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "alignItems": "center", + "borderBottomWidth": 0.5, + "flexDirection": "row", + "justifyContent": "space-between", + "paddingHorizontal": 12, + }, + { + "backgroundColor": "#E4E7EA", + "borderBottomColor": "#CBCED1", + "paddingBottom": 12, + "paddingTop": 12, + }, + ] + } + testID="media-call-header" + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginLeft": -5, + "marginRight": 0, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={17} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-collapse" + > + <View + accessibilityLabel="[missing "en.Minimize" translation]" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "flex": 1, + "paddingHorizontal": 4, + } + } + testID="media-call-header-content" + > + <View + style={ + { + "alignItems": "flex-start", + "flex": 1, + "flexDirection": "column", + "justifyContent": "space-evenly", + } + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "gap": 4, + } + } + testID="call-view-header-title" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 12, + }, + [ + { + "lineHeight": 12, + }, + [ + { + "height": 12, + "textAlignVertical": "center", + "width": 12, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "lineHeight": 24, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Bob Burnquist + </Text> + </View> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "lineHeight": 16, + "textAlign": "left", + }, + { + "color": "#6C727A", + }, + ] + } + testID="call-view-header-subtitle" + > + Connecting... + </Text> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginRight": -5, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={18} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-end" + > + <View + accessibilityLabel="End" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: Focused should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "alignItems": "center", + "borderBottomWidth": 0.5, + "flexDirection": "row", + "justifyContent": "space-between", + "paddingHorizontal": 12, + }, + { + "backgroundColor": "#E4E7EA", + "borderBottomColor": "#CBCED1", + "paddingBottom": 12, + "paddingTop": 12, + }, + ] + } + testID="media-call-header" + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginLeft": -5, + "marginRight": 0, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={19} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-collapse" + > + <View + accessibilityLabel="[missing "en.Minimize" translation]" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "flex": 1, + "paddingHorizontal": 4, + } + } + testID="media-call-header-content" + > + <View + style={ + { + "alignItems": "flex-start", + "flex": 1, + "flexDirection": "column", + "justifyContent": "space-evenly", + } + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "gap": 4, + } + } + testID="call-view-header-title" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 12, + }, + [ + { + "lineHeight": 12, + }, + [ + { + "height": 12, + "textAlignVertical": "center", + "width": 12, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "lineHeight": 24, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Bob Burnquist + <Text> + - + 16117:18:53 + </Text> + </Text> + </View> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "lineHeight": 16, + "textAlign": "left", + }, + { + "color": "#6C727A", + }, + ] + } + testID="call-view-header-subtitle" + > + 2244 + </Text> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginRight": -5, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={20} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-end" + > + <View + accessibilityLabel="End" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: NoCall should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + { + "backgroundColor": "#E4E7EA", + "paddingBottom": 12, + "paddingTop": 12, + } + } + testID="media-call-header-empty" + /> +</View> +`; + +exports[`Story Snapshots: WithRemoteHeld should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "alignItems": "center", + "borderBottomWidth": 0.5, + "flexDirection": "row", + "justifyContent": "space-between", + "paddingHorizontal": 12, + }, + { + "backgroundColor": "#E4E7EA", + "borderBottomColor": "#CBCED1", + "paddingBottom": 12, + "paddingTop": 12, + }, + ] + } + testID="media-call-header" + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginLeft": -5, + "marginRight": 0, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={21} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-collapse" + > + <View + accessibilityLabel="[missing "en.Minimize" translation]" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "flex": 1, + "paddingHorizontal": 4, + } + } + testID="media-call-header-content" + > + <View + style={ + { + "alignItems": "flex-start", + "flex": 1, + "flexDirection": "column", + "justifyContent": "space-evenly", + } + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "gap": 4, + } + } + testID="call-view-header-title" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 12, + }, + [ + { + "lineHeight": 12, + }, + [ + { + "height": 12, + "textAlignVertical": "center", + "width": 12, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "lineHeight": 24, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Bob Burnquist + <Text> + - + 16117:18:53 + </Text> + </Text> + </View> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "lineHeight": 16, + "textAlign": "left", + }, + { + "color": "#6C727A", + }, + ] + } + testID="call-view-header-subtitle" + > + 2244 - On hold + </Text> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginRight": -5, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={22} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-end" + > + <View + accessibilityLabel="End" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: WithRemoteMuted should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + style={ + [ + { + "alignItems": "center", + "borderBottomWidth": 0.5, + "flexDirection": "row", + "justifyContent": "space-between", + "paddingHorizontal": 12, + }, + { + "backgroundColor": "#E4E7EA", + "borderBottomColor": "#CBCED1", + "paddingBottom": 12, + "paddingTop": 12, + }, + ] + } + testID="media-call-header" + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginLeft": -5, + "marginRight": 0, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={23} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-collapse" + > + <View + accessibilityLabel="[missing "en.Minimize" translation]" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "flex": 1, + "paddingHorizontal": 4, + } + } + testID="media-call-header-content" + > + <View + style={ + { + "alignItems": "flex-start", + "flex": 1, + "flexDirection": "column", + "justifyContent": "space-evenly", + } + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "gap": 4, + } + } + testID="call-view-header-title" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 12, + }, + [ + { + "lineHeight": 12, + }, + [ + { + "height": 12, + "textAlignVertical": "center", + "width": 12, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "lineHeight": 24, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Bob Burnquist + <Text> + - + 16117:18:53 + </Text> + </Text> + </View> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "lineHeight": 16, + "textAlign": "left", + }, + { + "color": "#6C727A", + }, + ] + } + testID="call-view-header-subtitle" + > + 2244 - Muted + </Text> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "justifyContent": "center", + }, + { + "marginRight": -5, + }, + {}, + ] + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={24} + handlerType="NativeViewGestureHandler" + hitSlop={ + { + "bottom": 5, + "left": 5, + "right": 5, + "top": 5, + } + } + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "opacity": 1, + "padding": 6, + }, + { + "cursor": undefined, + }, + ] + } + testID="media-call-header-end" + > + <View + accessibilityLabel="End" + accessible={true} + style={ + { + "opacity": 1, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; diff --git a/app/containers/CallHeader/components/Collapse.tsx b/app/containers/MediaCallHeader/components/Collapse.tsx similarity index 94% rename from app/containers/CallHeader/components/Collapse.tsx rename to app/containers/MediaCallHeader/components/Collapse.tsx index 6332df73287..1ad769c30c4 100644 --- a/app/containers/CallHeader/components/Collapse.tsx +++ b/app/containers/MediaCallHeader/components/Collapse.tsx @@ -9,9 +9,11 @@ const Collapse = () => { const { colors } = useTheme(); const focused = useCallStore(state => state.focused); const toggleFocus = useCallStore(state => state.toggleFocus); + return ( <HeaderButton.Container left> <HeaderButton.Item + testID='media-call-header-collapse' accessibilityLabel={I18n.t('Minimize')} onPress={toggleFocus} iconName={focused ? 'arrow-collapse' : 'arrow-expand'} diff --git a/app/containers/MediaCallHeader/components/Content.tsx b/app/containers/MediaCallHeader/components/Content.tsx new file mode 100644 index 00000000000..566918a42c2 --- /dev/null +++ b/app/containers/MediaCallHeader/components/Content.tsx @@ -0,0 +1,26 @@ +import { Pressable, StyleSheet, View } from 'react-native'; + +import Title from './Title'; +import Subtitle from './Subtitle'; + +const styles = StyleSheet.create({ + button: { + flex: 1, + paddingHorizontal: 4 + }, + container: { + flex: 1, + flexDirection: 'column', + justifyContent: 'space-evenly', + alignItems: 'flex-start' + } +}); + +export const Content = () => ( + <Pressable testID='media-call-header-content' onPress={() => alert('nav to call room')} style={styles.button}> + <View style={styles.container}> + <Title /> + <Subtitle /> + </View> + </Pressable> +); diff --git a/app/containers/CallHeader/components/EndCall.tsx b/app/containers/MediaCallHeader/components/EndCall.tsx similarity index 71% rename from app/containers/CallHeader/components/EndCall.tsx rename to app/containers/MediaCallHeader/components/EndCall.tsx index 09f4caa10b3..9ba0968a3d0 100644 --- a/app/containers/CallHeader/components/EndCall.tsx +++ b/app/containers/MediaCallHeader/components/EndCall.tsx @@ -10,7 +10,13 @@ const EndCall = () => { const endCall = useCallStore(state => state.endCall); return ( <HeaderButton.Container> - <HeaderButton.Item accessibilityLabel={I18n.t('End')} onPress={endCall} iconName='phone-end' color={colors.fontDanger} /> + <HeaderButton.Item + testID='media-call-header-end' + accessibilityLabel={I18n.t('End')} + onPress={endCall} + iconName='phone-end' + color={colors.fontDanger} + /> </HeaderButton.Container> ); }; diff --git a/app/containers/MediaCallHeader/components/Subtitle.tsx b/app/containers/MediaCallHeader/components/Subtitle.tsx new file mode 100644 index 00000000000..364886e31b6 --- /dev/null +++ b/app/containers/MediaCallHeader/components/Subtitle.tsx @@ -0,0 +1,51 @@ +import { StyleSheet, Text } from 'react-native'; + +import { useTheme } from '../../../theme'; +import { useCallStore } from '../../../lib/services/voip/useCallStore'; +import I18n from '../../../i18n'; +import sharedStyles from '../../../views/Styles'; + +const styles = StyleSheet.create({ + headerTitle: { + ...sharedStyles.textRegular, + fontSize: 12, + lineHeight: 16 + } +}); + +const Subtitle = () => { + 'use memo'; + + const { colors } = useTheme(); + const contact = useCallStore(state => state.contact); + const extension = contact.sipExtension; + const remoteHeld = useCallStore(state => state.remoteHeld); + const remoteMute = useCallStore(state => state.remoteMute); + const callState = useCallStore(state => state.callState); + const isConnected = callState === 'active'; + + let subtitle = ''; + + if (!isConnected) { + subtitle = I18n.t('Connecting'); + } else { + subtitle = extension ? `${extension}` : ''; + const remoteState = []; + remoteState.push(remoteHeld ? I18n.t('On_hold') : null); + remoteState.push(remoteMute ? I18n.t('Muted') : null); + subtitle += remoteState.filter(Boolean).length > 0 && extension ? ' - ' : ''; + subtitle += remoteState.filter(Boolean).join(', '); + } + + if (!subtitle) { + return null; + } + + return ( + <Text style={[styles.headerTitle, { color: colors.fontSecondaryInfo }]} testID='call-view-header-subtitle' numberOfLines={1}> + {subtitle} + </Text> + ); +}; + +export default Subtitle; diff --git a/app/containers/CallHeader/components/Timer.tsx b/app/containers/MediaCallHeader/components/Timer.tsx similarity index 95% rename from app/containers/CallHeader/components/Timer.tsx rename to app/containers/MediaCallHeader/components/Timer.tsx index fa784cf864e..56981c57da6 100644 --- a/app/containers/CallHeader/components/Timer.tsx +++ b/app/containers/MediaCallHeader/components/Timer.tsx @@ -29,7 +29,7 @@ const Timer = () => { return () => clearInterval(interval); }, [callStartTime]); - return <Text>{formatDuration(duration)}</Text>; + return <Text> - {formatDuration(duration)}</Text>; }; export default Timer; diff --git a/app/containers/CallHeader/components/Title.tsx b/app/containers/MediaCallHeader/components/Title.tsx similarity index 56% rename from app/containers/CallHeader/components/Title.tsx rename to app/containers/MediaCallHeader/components/Title.tsx index 36885607bbe..216c466e4f6 100644 --- a/app/containers/CallHeader/components/Title.tsx +++ b/app/containers/MediaCallHeader/components/Title.tsx @@ -1,13 +1,18 @@ -import { StyleSheet, Text } from 'react-native'; +import { StyleSheet, Text, View } from 'react-native'; import { useTheme } from '../../../theme'; import { useCallStore } from '../../../lib/services/voip/useCallStore'; -import I18n from '../../../i18n'; import sharedStyles from '../../../views/Styles'; import Timer from './Timer'; +import Status from '../../Status'; const styles = StyleSheet.create({ - headerTitle: { + headerTitleContainer: { + flexDirection: 'row', + alignItems: 'center', + gap: 4 + }, + headerTitleText: { ...sharedStyles.textSemibold, fontSize: 16, lineHeight: 24 @@ -23,24 +28,16 @@ const Title = () => { const contact = useCallStore(state => state.contact); const caller = contact.displayName || contact.username; - const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; const isConnected = callState === 'active'; - const getHeaderTitle = () => { - if (isConnecting) { - return I18n.t('Connecting'); - } - if (isConnected && callStartTime) { - return `${caller} – `; - } - return caller; - }; - return ( - <Text style={[styles.headerTitle, { color: colors.fontDefault }]} testID='call-view-header-title'> - {getHeaderTitle()} - <Timer /> - </Text> + <View style={styles.headerTitleContainer} testID='call-view-header-title'> + <Status id={contact.id || ''} size={12} /> + <Text style={[styles.headerTitleText, { color: colors.fontDefault }]} numberOfLines={1}> + {caller} + {isConnected && callStartTime ? <Timer /> : null} + </Text> + </View> ); }; diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index effa08ba00c..b374b5d30aa 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -1,16 +1,9 @@ import { create } from 'zustand'; -import { useShallow } from 'zustand/react/shallow'; -import type { CallState, IClientMediaCall } from '@rocket.chat/media-signaling'; +import type { CallState, CallContact, IClientMediaCall } from '@rocket.chat/media-signaling'; import RNCallKeep from 'react-native-callkeep'; import Navigation from '../../navigation/appNavigation'; -interface CallContact { - displayName?: string; - username?: string; - sipExtension?: string; -} - interface CallStoreState { // Call reference call: IClientMediaCall | null; @@ -20,6 +13,8 @@ interface CallStoreState { callState: CallState; isMuted: boolean; isOnHold: boolean; + remoteMute: boolean; + remoteHeld: boolean; isSpeakerOn: boolean; callStartTime: number | null; focused: boolean; @@ -31,7 +26,6 @@ interface CallStoreState { interface CallStoreActions { setCallUUID: (callUUID: string | null) => void; setCall: (call: IClientMediaCall, callUUID: string) => void; - updateFromCall: () => void; toggleMute: () => void; toggleHold: () => void; toggleSpeaker: () => void; @@ -48,10 +42,12 @@ const initialState: CallStoreState = { callState: 'none', isMuted: false, isOnHold: false, + remoteMute: false, + remoteHeld: false, isSpeakerOn: false, callStartTime: null, contact: {}, - focused: false + focused: true }; export const useCallStore = create<CallStore>((set, get) => ({ @@ -69,8 +65,11 @@ export const useCallStore = create<CallStore>((set, get) => ({ callState: call.state, isMuted: call.muted, isOnHold: call.held, + remoteMute: call.remoteMute, + remoteHeld: call.remoteHeld, // isSpeakerOn: call. contact: { + id: call.contact.id, displayName: call.contact.displayName, username: call.contact.username, sipExtension: call.contact.sipExtension @@ -98,7 +97,9 @@ export const useCallStore = create<CallStore>((set, get) => ({ set({ isMuted: currentCall.muted, - isOnHold: currentCall.held + isOnHold: currentCall.held, + remoteMute: currentCall.remoteMute, + remoteHeld: currentCall.remoteHeld }); }; @@ -112,22 +113,6 @@ export const useCallStore = create<CallStore>((set, get) => ({ call.emitter.on('ended', handleEnded); }, - updateFromCall: () => { - const { call } = get(); - if (!call) return; - - set({ - callState: call.state, - isMuted: call.muted, - isOnHold: call.held, - contact: { - displayName: call.contact.displayName, - username: call.contact.username, - sipExtension: call.contact.sipExtension - } - }); - }, - toggleMute: () => { const { call, isMuted } = get(); if (!call) return; @@ -184,21 +169,28 @@ export const useCallStore = create<CallStore>((set, get) => ({ } })); -// Selector hooks for better performance -export const useCallState = () => useCallStore(state => state.callState); +// const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; +// const isConnected = callState === 'active'; +export const useCallState = () => { + const callState = useCallStore(state => state.callState); + return callState === 'none' || callState === 'ringing' || callState === 'accepted'; +}; + +// // Selector hooks for better performance +// export const useCallState = () => useCallStore(state => state.callState); export const useCallContact = () => useCallStore(state => state.contact); -export const useCallControls = () => - useCallStore( - useShallow(state => ({ - isMuted: state.isMuted, - isOnHold: state.isOnHold, - isSpeakerOn: state.isSpeakerOn - })) - ); -export const useCallActions = () => - useCallStore(state => ({ - toggleMute: state.toggleMute, - toggleHold: state.toggleHold, - toggleSpeaker: state.toggleSpeaker, - endCall: state.endCall - })); +// export const useCallControls = () => +// useCallStore( +// useShallow(state => ({ +// isMuted: state.isMuted, +// isOnHold: state.isOnHold, +// isSpeakerOn: state.isSpeakerOn +// })) +// ); +// export const useCallActions = () => +// useCallStore(state => ({ +// toggleMute: state.toggleMute, +// toggleHold: state.toggleHold, +// toggleSpeaker: state.toggleSpeaker, +// endCall: state.endCall +// })); diff --git a/app/views/CallView/CallView.stories.tsx b/app/views/CallView/CallView.stories.tsx index d7bbaed81a4..1fe80b664df 100644 --- a/app/views/CallView/CallView.stories.tsx +++ b/app/views/CallView/CallView.stories.tsx @@ -16,16 +16,7 @@ const styles = StyleSheet.create({ } }); -// Mock navigation -// jest.mock('@react-navigation/native', () => ({ -// ...jest.requireActual('@react-navigation/native'), -// useNavigation: () => ({ -// goBack: () => {} -// }), -// useRoute: () => ({ -// params: { callUUID: 'test-uuid' } -// }) -// })); +const mockCallStartTime = 1713340800000; // Helper to set store state for stories const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getState>> = {}) => { @@ -55,7 +46,7 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat isMuted: false, isOnHold: false, isSpeakerOn: false, - callStartTime: Date.now(), + callStartTime: mockCallStartTime, contact: { displayName: 'Bob Burnquist', username: 'bob.burnquist', @@ -94,7 +85,7 @@ export default { }; export const ConnectedCall = () => { - setStoreState({ callState: 'active', callStartTime: new Date().getTime() - 61000 }); + setStoreState({ callState: 'active', callStartTime: mockCallStartTime - 61000 }); return <CallView />; }; diff --git a/app/views/CallView/__snapshots__/index.test.tsx.snap b/app/views/CallView/__snapshots__/index.test.tsx.snap index b0404418151..703e4a6d0c6 100644 --- a/app/views/CallView/__snapshots__/index.test.tsx.snap +++ b/app/views/CallView/__snapshots__/index.test.tsx.snap @@ -46,7 +46,7 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` style={ [ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, }, @@ -56,7 +56,7 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` testID="avatar" > <ViewManagerAdapter_ExpoImage - borderRadius={16} + borderRadius={2} containerViewRef={"[React.ref]"} contentFit="cover" contentPosition={ @@ -83,7 +83,7 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` } style={ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, } @@ -91,21 +91,6 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` transition={null} width={120} /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> </View> </View> <View @@ -140,47 +125,18 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` Bob Burnquist </Text> </View> - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "marginBottom": 8, - "textAlign": "center", - }, - { - "color": "#6C727A", - }, - ] - } - testID="caller-info-extension" - > - 2244 - </Text> </View> - <Text - style={ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "textAlign": "center", - } - } - > -   - </Text> <View style={ - { - "padding": 24, - } + [ + { + "borderTopWidth": 0.5, + "padding": 24, + }, + { + "borderTopColor": "#EBECEF", + }, + ] } > <View @@ -842,7 +798,7 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` style={ [ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, }, @@ -852,7 +808,7 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` testID="avatar" > <ViewManagerAdapter_ExpoImage - borderRadius={16} + borderRadius={2} containerViewRef={"[React.ref]"} contentFit="cover" contentPosition={ @@ -879,7 +835,7 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` } style={ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, } @@ -887,21 +843,6 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` transition={null} width={120} /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> </View> </View> <View @@ -936,33 +877,18 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` Bob Burnquist </Text> </View> - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "marginBottom": 8, - "textAlign": "center", - }, - { - "color": "#6C727A", - }, - ] - } - testID="caller-info-extension" - > - 2244 - </Text> </View> <View style={ - { - "padding": 24, - } + [ + { + "borderTopWidth": 0.5, + "padding": 24, + }, + { + "borderTopColor": "#EBECEF", + }, + ] } > <View @@ -1628,7 +1554,7 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` style={ [ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, }, @@ -1638,7 +1564,7 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` testID="avatar" > <ViewManagerAdapter_ExpoImage - borderRadius={16} + borderRadius={2} containerViewRef={"[React.ref]"} contentFit="cover" contentPosition={ @@ -1665,7 +1591,7 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` } style={ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, } @@ -1673,21 +1599,6 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` transition={null} width={120} /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> </View> </View> <View @@ -1721,93 +1632,20 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` > Bob Burnquist </Text> - <Text - allowFontScaling={false} - selectable={false} - style={ - [ - { - "color": "#D40C26", - "fontSize": NaN, - }, - [ - { - "lineHeight": NaN, - }, - { - "marginLeft": 8, - }, - ], - { - "fontFamily": "custom", - "fontStyle": "normal", - "fontWeight": "normal", - }, - {}, - ] - } - testID="caller-info-muted" - > -  - </Text> </View> - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "marginBottom": 8, - "textAlign": "center", - }, - { - "color": "#6C727A", - }, - ] - } - testID="caller-info-extension" - > - 2244 - </Text> </View> - <Text + <View style={ [ { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "textAlign": "center", + "borderTopWidth": 0.5, + "padding": 24, }, { - "color": "#2F343D", + "borderTopColor": "#EBECEF", }, ] } - > - On hold - , - <Text - style={ - { - "color": "#8E6300", - } - } - > - Muted - </Text> - </Text> - <View - style={ - { - "padding": 24, - } - } > <View style={ @@ -2468,7 +2306,7 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` style={ [ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, }, @@ -2478,7 +2316,7 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` testID="avatar" > <ViewManagerAdapter_ExpoImage - borderRadius={16} + borderRadius={2} containerViewRef={"[React.ref]"} contentFit="cover" contentPosition={ @@ -2505,7 +2343,7 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` } style={ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, } @@ -2513,21 +2351,6 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` transition={null} width={120} /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> </View> </View> <View @@ -2561,83 +2384,20 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` > Bob Burnquist </Text> - <Text - allowFontScaling={false} - selectable={false} - style={ - [ - { - "color": "#D40C26", - "fontSize": NaN, - }, - [ - { - "lineHeight": NaN, - }, - { - "marginLeft": 8, - }, - ], - { - "fontFamily": "custom", - "fontStyle": "normal", - "fontWeight": "normal", - }, - {}, - ] - } - testID="caller-info-muted" - > -  - </Text> </View> - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "marginBottom": 8, - "textAlign": "center", - }, - { - "color": "#6C727A", - }, - ] - } - testID="caller-info-extension" - > - 2244 - </Text> </View> - <Text + <View style={ [ { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "textAlign": "center", + "borderTopWidth": 0.5, + "padding": 24, }, { - "color": "#8E6300", + "borderTopColor": "#EBECEF", }, ] } - > - Muted - </Text> - <View - style={ - { - "padding": 24, - } - } > <View style={ @@ -3298,7 +3058,7 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` style={ [ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, }, @@ -3308,7 +3068,7 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` testID="avatar" > <ViewManagerAdapter_ExpoImage - borderRadius={16} + borderRadius={2} containerViewRef={"[React.ref]"} contentFit="cover" contentPosition={ @@ -3335,7 +3095,7 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` } style={ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, } @@ -3343,21 +3103,6 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` transition={null} width={120} /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> </View> </View> <View @@ -3392,53 +3137,19 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` Bob Burnquist </Text> </View> - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "marginBottom": 8, - "textAlign": "center", - }, - { - "color": "#6C727A", - }, - ] - } - testID="caller-info-extension" - > - 2244 - </Text> </View> - <Text + <View style={ [ { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "textAlign": "center", + "borderTopWidth": 0.5, + "padding": 24, }, { - "color": "#2F343D", + "borderTopColor": "#EBECEF", }, ] } - > - On hold - </Text> - <View - style={ - { - "padding": 24, - } - } > <View style={ @@ -4099,7 +3810,7 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` style={ [ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, }, @@ -4109,7 +3820,7 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` testID="avatar" > <ViewManagerAdapter_ExpoImage - borderRadius={16} + borderRadius={2} containerViewRef={"[React.ref]"} contentFit="cover" contentPosition={ @@ -4136,7 +3847,7 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` } style={ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, } @@ -4144,21 +3855,6 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` transition={null} width={120} /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> </View> </View> <View @@ -4193,47 +3889,18 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` Bob Burnquist </Text> </View> - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "marginBottom": 8, - "textAlign": "center", - }, - { - "color": "#6C727A", - }, - ] - } - testID="caller-info-extension" - > - 2244 - </Text> </View> - <Text - style={ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "textAlign": "center", - } - } - > -   - </Text> <View style={ - { - "padding": 24, - } + [ + { + "borderTopWidth": 0.5, + "padding": 24, + }, + { + "borderTopColor": "#EBECEF", + }, + ] } > <View diff --git a/app/views/CallView/components/CallButtons.tsx b/app/views/CallView/components/CallButtons.tsx new file mode 100644 index 00000000000..5eddb2b786d --- /dev/null +++ b/app/views/CallView/components/CallButtons.tsx @@ -0,0 +1,83 @@ +import React from 'react'; +import { View } from 'react-native'; + +import I18n from '../../../i18n'; +import { useCallStore } from '../../../lib/services/voip/useCallStore'; +import CallActionButton from './CallActionButton'; +import { styles } from '../styles'; +import { useTheme } from '../../../theme'; + +export const CallButtons = () => { + 'use memo'; + + const { colors } = useTheme(); + + const callState = useCallStore(state => state.callState); + const isMuted = useCallStore(state => state.isMuted); + const isOnHold = useCallStore(state => state.isOnHold); + const isSpeakerOn = useCallStore(state => state.isSpeakerOn); + + const toggleMute = useCallStore(state => state.toggleMute); + const toggleHold = useCallStore(state => state.toggleHold); + const toggleSpeaker = useCallStore(state => state.toggleSpeaker); + const endCall = useCallStore(state => state.endCall); + + const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; + + const handleMessage = () => { + // TODO: Navigate to chat with caller + // Navigation.navigate('RoomView', { rid, t: 'd' }); + alert('Message'); + }; + + const handleMore = () => { + // TODO: Show action sheet with more options (DTMF, transfer, etc.) + alert('More'); + }; + + const handleEndCall = () => { + endCall(); + }; + + return ( + <View style={[styles.buttonsContainer, { borderTopColor: colors.strokeExtraLight }]}> + <View style={styles.buttonsRow}> + <CallActionButton + icon={isSpeakerOn ? 'audio' : 'audio-disabled'} + label={I18n.t('Speaker')} + onPress={toggleSpeaker} + variant={isSpeakerOn ? 'active' : 'default'} + testID='call-view-speaker' + /> + <CallActionButton + icon={'pause-shape-unfilled'} + label={isOnHold ? I18n.t('Unhold') : I18n.t('Hold')} + onPress={toggleHold} + variant={isOnHold ? 'active' : 'default'} + disabled={isConnecting} + testID='call-view-hold' + /> + <CallActionButton + icon={isMuted ? 'microphone-disabled' : 'microphone'} + label={isMuted ? I18n.t('Unmute') : I18n.t('Mute')} + onPress={toggleMute} + variant={isMuted ? 'active' : 'default'} + disabled={isConnecting} + testID='call-view-mute' + /> + </View> + + <View style={styles.buttonsRow}> + <CallActionButton icon='message' label={I18n.t('Message')} onPress={handleMessage} testID='call-view-message' /> + <CallActionButton + icon='phone-end' + label={isConnecting ? I18n.t('Cancel') : I18n.t('End')} + onPress={handleEndCall} + variant='danger' + testID='call-view-end' + /> + <CallActionButton icon='kebab' label={I18n.t('More')} onPress={handleMore} testID='call-view-more' /> + </View> + </View> + ); +}; diff --git a/app/views/CallView/components/CallStatusText.tsx b/app/views/CallView/components/CallStatusText.tsx deleted file mode 100644 index 305c4b66ea1..00000000000 --- a/app/views/CallView/components/CallStatusText.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { Text } from 'react-native'; - -import I18n from '../../../i18n'; -import { styles } from '../styles'; -import { useCallControls } from '../../../lib/services/voip/useCallStore'; -import { useTheme } from '../../../theme'; - -const CallStatusText = (): React.ReactElement => { - 'use memo'; - - const { isMuted, isOnHold } = useCallControls(); - const { colors } = useTheme(); - - if (isOnHold && isMuted) { - return ( - <> - <Text style={[styles.statusText, { color: colors.fontDefault }]}> - {I18n.t('On_hold')}, <Text style={{ color: colors.statusFontWarning }}>{I18n.t('Muted')}</Text> - </Text> - </> - ); - } - if (isOnHold) { - return <Text style={[styles.statusText, { color: colors.fontDefault }]}>{I18n.t('On_hold')}</Text>; - } - if (isMuted) { - return <Text style={[styles.statusText, { color: colors.statusFontWarning }]}>{I18n.t('Muted')}</Text>; - } - - return <Text style={styles.statusText}> </Text>; -}; - -export default CallStatusText; diff --git a/app/views/CallView/components/CallerInfo.stories.tsx b/app/views/CallView/components/CallerInfo.stories.tsx index 595229ac548..c24c3ac1184 100644 --- a/app/views/CallView/components/CallerInfo.stories.tsx +++ b/app/views/CallView/components/CallerInfo.stories.tsx @@ -23,8 +23,7 @@ const setStoreState = (contact: { displayName?: string; username?: string; sipEx callState: 'active', isMuted: false, isOnHold: false, - isSpeakerOn: false, - callStartTime: Date.now() + isSpeakerOn: false }); }; @@ -45,15 +44,6 @@ export default { export const Default = () => <CallerInfo />; -export const WithOnlineStatus = () => <CallerInfo />; - -export const WithMutedIndicator = () => <CallerInfo isMuted />; - -export const NoExtension = () => { - setStoreState({ displayName: 'Alice Attali', username: 'alice.attali' }); - return <CallerInfo />; -}; - export const UsernameOnly = () => { setStoreState({ username: 'john.doe' }); return <CallerInfo />; diff --git a/app/views/CallView/components/CallerInfo.test.tsx b/app/views/CallView/components/CallerInfo.test.tsx index 7bd8bd55586..c411cfa5a3d 100644 --- a/app/views/CallView/components/CallerInfo.test.tsx +++ b/app/views/CallView/components/CallerInfo.test.tsx @@ -8,6 +8,8 @@ import { mockedStore } from '../../../reducers/mockedStore'; import * as stories from './CallerInfo.stories'; import { generateSnapshots } from '../../../../.rnstorybook/generateSnapshots'; +const mockCallStartTime = 1713340800000; + // Helper to set store state for tests const setStoreState = (contact: { displayName?: string; username?: string; sipExtension?: string }) => { useCallStore.setState({ @@ -18,7 +20,7 @@ const setStoreState = (contact: { displayName?: string; username?: string; sipEx isMuted: false, isOnHold: false, isSpeakerOn: false, - callStartTime: Date.now() + callStartTime: mockCallStartTime }); }; @@ -39,7 +41,6 @@ describe('CallerInfo', () => { expect(getByTestId('caller-info')).toBeTruthy(); expect(getByText('Bob Burnquist')).toBeTruthy(); - expect(getByText('2244')).toBeTruthy(); }); it('should render with username when no display name', () => { @@ -52,53 +53,6 @@ describe('CallerInfo', () => { expect(getByText('john.doe')).toBeTruthy(); }); - - it('should render status container (Status component is currently commented out)', () => { - setStoreState({ displayName: 'Test User' }); - const { getByTestId } = render( - <Wrapper> - <CallerInfo /> - </Wrapper> - ); - - // The status container exists but Status component is commented out - // Verify the component renders correctly - expect(getByTestId('caller-info')).toBeTruthy(); - expect(getByTestId('avatar')).toBeTruthy(); - }); - - it('should show muted indicator when isMuted is true', () => { - setStoreState({ displayName: 'Test User' }); - const { getByTestId } = render( - <Wrapper> - <CallerInfo isMuted /> - </Wrapper> - ); - - expect(getByTestId('caller-info-muted')).toBeTruthy(); - }); - - it('should not show muted indicator when isMuted is false', () => { - setStoreState({ displayName: 'Test User' }); - const { queryByTestId } = render( - <Wrapper> - <CallerInfo isMuted={false} /> - </Wrapper> - ); - - expect(queryByTestId('caller-info-muted')).toBeNull(); - }); - - it('should not show extension when not provided', () => { - setStoreState({ displayName: 'Test User' }); - const { queryByTestId } = render( - <Wrapper> - <CallerInfo /> - </Wrapper> - ); - - expect(queryByTestId('caller-info-extension')).toBeNull(); - }); }); generateSnapshots(stories); diff --git a/app/views/CallView/components/CallerInfo.tsx b/app/views/CallView/components/CallerInfo.tsx index c212e454435..32b5d856b7a 100644 --- a/app/views/CallView/components/CallerInfo.tsx +++ b/app/views/CallView/components/CallerInfo.tsx @@ -2,54 +2,28 @@ import React from 'react'; import { Text, View } from 'react-native'; import AvatarContainer from '../../../containers/Avatar'; -import { CustomIcon } from '../../../containers/CustomIcon'; import I18n from '../../../i18n'; import { useCallContact } from '../../../lib/services/voip/useCallStore'; import { styles } from '../styles'; import { useTheme } from '../../../theme'; -// import Status from '../../../containers/Status'; -import sharedStyles from '../../Styles'; -interface ICallerInfo { - isMuted?: boolean; -} - -const CallerInfo = ({ isMuted = false }: ICallerInfo): React.ReactElement => { +const CallerInfo = (): React.ReactElement => { const { colors } = useTheme(); const contact = useCallContact(); const name = contact.displayName || contact.username || I18n.t('Unknown'); - const extension = contact.sipExtension; const avatarText = contact.username || name; return ( <View style={styles.callerInfoContainer} testID='caller-info'> <View style={styles.avatarContainer}> - <AvatarContainer text={avatarText} size={120} borderRadius={16}> - <View style={[sharedStyles.status, { backgroundColor: colors.surfaceHover }]}> - {/* <Status size={20} id={contact.username} /> */} - </View> - </AvatarContainer> + <AvatarContainer text={avatarText} size={120} borderRadius={2} /> </View> <View style={styles.callerRow}> <Text style={[styles.caller, { color: colors.fontDefault }]} numberOfLines={1} testID='caller-info-name'> {name} </Text> - {isMuted && ( - <CustomIcon - name='microphone-disabled' - size={20} - color={colors.fontDanger} - style={styles.mutedIndicator} - testID='caller-info-muted' - /> - )} </View> - {extension ? ( - <Text style={[styles.callerExtension, { color: colors.fontSecondaryInfo }]} testID='caller-info-extension'> - {extension} - </Text> - ) : null} </View> ); }; diff --git a/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap b/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap index a4633b97130..145e5f98944 100644 --- a/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap +++ b/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap @@ -35,7 +35,7 @@ exports[`Story Snapshots: Default should match snapshot 1`] = ` style={ [ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, }, @@ -45,7 +45,7 @@ exports[`Story Snapshots: Default should match snapshot 1`] = ` testID="avatar" > <ViewManagerAdapter_ExpoImage - borderRadius={16} + borderRadius={2} containerViewRef={"[React.ref]"} contentFit="cover" contentPosition={ @@ -72,7 +72,7 @@ exports[`Story Snapshots: Default should match snapshot 1`] = ` } style={ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, } @@ -80,21 +80,6 @@ exports[`Story Snapshots: Default should match snapshot 1`] = ` transition={null} width={120} /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> </View> </View> <View @@ -129,160 +114,6 @@ exports[`Story Snapshots: Default should match snapshot 1`] = ` Bob Burnquist </Text> </View> - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "marginBottom": 8, - "textAlign": "center", - }, - { - "color": "#6C727A", - }, - ] - } - testID="caller-info-extension" - > - 2244 - </Text> - </View> -</View> -`; - -exports[`Story Snapshots: NoExtension should match snapshot 1`] = ` -<View - style={ - { - "flex": 1, - "minHeight": 300, - "padding": 24, - } - } -> - <View - style={ - { - "alignItems": "center", - "flex": 1, - "justifyContent": "center", - "paddingHorizontal": 24, - } - } - testID="caller-info" - > - <View - style={ - { - "marginBottom": 16, - "position": "relative", - } - } - > - <View - accessibilityLabel="alice.attali's avatar" - accessible={true} - style={ - [ - { - "borderRadius": 16, - "height": 120, - "width": 120, - }, - undefined, - ] - } - testID="avatar" - > - <ViewManagerAdapter_ExpoImage - borderRadius={16} - containerViewRef={"[React.ref]"} - contentFit="cover" - contentPosition={ - { - "left": "50%", - "top": "50%", - } - } - height={120} - nativeViewRef={"[React.ref]"} - onError={[Function]} - onLoad={[Function]} - onLoadStart={[Function]} - onProgress={[Function]} - placeholder={[]} - priority="high" - source={ - [ - { - "headers": undefined, - "uri": "https://open.rocket.chat/avatar/alice.attali?format=png&size=240", - }, - ] - } - style={ - { - "borderRadius": 16, - "height": 120, - "width": 120, - } - } - transition={null} - width={120} - /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> - </View> - </View> - <View - style={ - { - "alignItems": "center", - "flexDirection": "row", - "justifyContent": "center", - } - } - > - <Text - numberOfLines={1} - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 24, - "fontWeight": "700", - "lineHeight": 32, - "marginBottom": 4, - "textAlign": "center", - }, - { - "color": "#2F343D", - }, - ] - } - testID="caller-info-name" - > - Alice Attali - </Text> - </View> </View> </View> `; @@ -322,7 +153,7 @@ exports[`Story Snapshots: UsernameOnly should match snapshot 1`] = ` style={ [ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, }, @@ -332,7 +163,7 @@ exports[`Story Snapshots: UsernameOnly should match snapshot 1`] = ` testID="avatar" > <ViewManagerAdapter_ExpoImage - borderRadius={16} + borderRadius={2} containerViewRef={"[React.ref]"} contentFit="cover" contentPosition={ @@ -359,7 +190,7 @@ exports[`Story Snapshots: UsernameOnly should match snapshot 1`] = ` } style={ { - "borderRadius": 16, + "borderRadius": 2, "height": 120, "width": 120, } @@ -367,21 +198,6 @@ exports[`Story Snapshots: UsernameOnly should match snapshot 1`] = ` transition={null} width={120} /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> </View> </View> <View @@ -419,340 +235,3 @@ exports[`Story Snapshots: UsernameOnly should match snapshot 1`] = ` </View> </View> `; - -exports[`Story Snapshots: WithMutedIndicator should match snapshot 1`] = ` -<View - style={ - { - "flex": 1, - "minHeight": 300, - "padding": 24, - } - } -> - <View - style={ - { - "alignItems": "center", - "flex": 1, - "justifyContent": "center", - "paddingHorizontal": 24, - } - } - testID="caller-info" - > - <View - style={ - { - "marginBottom": 16, - "position": "relative", - } - } - > - <View - accessibilityLabel="bob.burnquist's avatar" - accessible={true} - style={ - [ - { - "borderRadius": 16, - "height": 120, - "width": 120, - }, - undefined, - ] - } - testID="avatar" - > - <ViewManagerAdapter_ExpoImage - borderRadius={16} - containerViewRef={"[React.ref]"} - contentFit="cover" - contentPosition={ - { - "left": "50%", - "top": "50%", - } - } - height={120} - nativeViewRef={"[React.ref]"} - onError={[Function]} - onLoad={[Function]} - onLoadStart={[Function]} - onProgress={[Function]} - placeholder={[]} - priority="high" - source={ - [ - { - "headers": undefined, - "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", - }, - ] - } - style={ - { - "borderRadius": 16, - "height": 120, - "width": 120, - } - } - transition={null} - width={120} - /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> - </View> - </View> - <View - style={ - { - "alignItems": "center", - "flexDirection": "row", - "justifyContent": "center", - } - } - > - <Text - numberOfLines={1} - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 24, - "fontWeight": "700", - "lineHeight": 32, - "marginBottom": 4, - "textAlign": "center", - }, - { - "color": "#2F343D", - }, - ] - } - testID="caller-info-name" - > - Bob Burnquist - </Text> - <Text - allowFontScaling={false} - selectable={false} - style={ - [ - { - "color": "#D40C26", - "fontSize": 20, - }, - [ - { - "lineHeight": 20, - }, - { - "marginLeft": 8, - }, - ], - { - "fontFamily": "custom", - "fontStyle": "normal", - "fontWeight": "normal", - }, - {}, - ] - } - testID="caller-info-muted" - > -  - </Text> - </View> - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "marginBottom": 8, - "textAlign": "center", - }, - { - "color": "#6C727A", - }, - ] - } - testID="caller-info-extension" - > - 2244 - </Text> - </View> -</View> -`; - -exports[`Story Snapshots: WithOnlineStatus should match snapshot 1`] = ` -<View - style={ - { - "flex": 1, - "minHeight": 300, - "padding": 24, - } - } -> - <View - style={ - { - "alignItems": "center", - "flex": 1, - "justifyContent": "center", - "paddingHorizontal": 24, - } - } - testID="caller-info" - > - <View - style={ - { - "marginBottom": 16, - "position": "relative", - } - } - > - <View - accessibilityLabel="bob.burnquist's avatar" - accessible={true} - style={ - [ - { - "borderRadius": 16, - "height": 120, - "width": 120, - }, - undefined, - ] - } - testID="avatar" - > - <ViewManagerAdapter_ExpoImage - borderRadius={16} - containerViewRef={"[React.ref]"} - contentFit="cover" - contentPosition={ - { - "left": "50%", - "top": "50%", - } - } - height={120} - nativeViewRef={"[React.ref]"} - onError={[Function]} - onLoad={[Function]} - onLoadStart={[Function]} - onProgress={[Function]} - placeholder={[]} - priority="high" - source={ - [ - { - "headers": undefined, - "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", - }, - ] - } - style={ - { - "borderRadius": 16, - "height": 120, - "width": 120, - } - } - transition={null} - width={120} - /> - <View - style={ - [ - { - "borderRadius": 10, - "bottom": -2, - "position": "absolute", - "right": -2, - }, - { - "backgroundColor": "#F2F3F5", - }, - ] - } - /> - </View> - </View> - <View - style={ - { - "alignItems": "center", - "flexDirection": "row", - "justifyContent": "center", - } - } - > - <Text - numberOfLines={1} - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 24, - "fontWeight": "700", - "lineHeight": 32, - "marginBottom": 4, - "textAlign": "center", - }, - { - "color": "#2F343D", - }, - ] - } - testID="caller-info-name" - > - Bob Burnquist - </Text> - </View> - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 18, - "fontWeight": "400", - "lineHeight": 26, - "marginBottom": 8, - "textAlign": "center", - }, - { - "color": "#6C727A", - }, - ] - } - testID="caller-info-extension" - > - 2244 - </Text> - </View> -</View> -`; diff --git a/app/views/CallView/index.test.tsx b/app/views/CallView/index.test.tsx index 66316d13e3e..f4e12d61268 100644 --- a/app/views/CallView/index.test.tsx +++ b/app/views/CallView/index.test.tsx @@ -287,7 +287,7 @@ describe('CallView', () => { expect(getByText('End')).toBeTruthy(); }); - it('should show muted indicator when call is muted and active', () => { + it('should render call view when call is muted and active', () => { setStoreState({ callState: 'active', isMuted: true }); const { getByTestId } = render( <Wrapper> @@ -295,18 +295,19 @@ describe('CallView', () => { </Wrapper> ); - expect(getByTestId('caller-info-muted')).toBeTruthy(); + expect(getByTestId('caller-info')).toBeTruthy(); + expect(getByTestId('call-view-mute')).toBeTruthy(); }); - it('should not show muted indicator when call is muted but not active', () => { + it('should render call view when call is muted but not yet active', () => { setStoreState({ callState: 'ringing', isMuted: true }); - const { queryByTestId } = render( + const { getByTestId } = render( <Wrapper> <CallView /> </Wrapper> ); - expect(queryByTestId('caller-info-muted')).toBeNull(); + expect(getByTestId('caller-info')).toBeTruthy(); }); it('should show correct icon for speaker button when speaker is on', () => { diff --git a/app/views/CallView/index.tsx b/app/views/CallView/index.tsx index 5c455897fad..a6d13848c89 100644 --- a/app/views/CallView/index.tsx +++ b/app/views/CallView/index.tsx @@ -2,33 +2,18 @@ import React, { useEffect } from 'react'; import { View } from 'react-native'; import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake'; -import I18n from '../../i18n'; import { useCallStore } from '../../lib/services/voip/useCallStore'; import CallerInfo from './components/CallerInfo'; -import CallActionButton from './components/CallActionButton'; -import CallStatusText from './components/CallStatusText'; import { styles } from './styles'; import { useTheme } from '../../theme'; +import { CallButtons } from './components/CallButtons'; const CallView = (): React.ReactElement | null => { 'use memo'; const { colors } = useTheme(); - - // Get state from store const call = useCallStore(state => state.call); - const callState = useCallStore(state => state.callState); - const isMuted = useCallStore(state => state.isMuted); - const isOnHold = useCallStore(state => state.isOnHold); - const isSpeakerOn = useCallStore(state => state.isSpeakerOn); - - // Get actions from store - const toggleMute = useCallStore(state => state.toggleMute); - const toggleHold = useCallStore(state => state.toggleHold); - const toggleSpeaker = useCallStore(state => state.toggleSpeaker); - const endCall = useCallStore(state => state.endCall); - // Keep screen awake during call useEffect(() => { activateKeepAwakeAsync(); return () => { @@ -36,78 +21,14 @@ const CallView = (): React.ReactElement | null => { }; }, []); - const handleMessage = () => { - // TODO: Navigate to chat with caller - // Navigation.navigate('RoomView', { rid, t: 'd' }); - alert('Message'); - }; - - const handleMore = () => { - // TODO: Show action sheet with more options (DTMF, transfer, etc.) - alert('More'); - }; - - const handleEndCall = () => { - endCall(); - }; - if (!call) { return null; } - const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; - const isConnected = callState === 'active'; - return ( <View style={[styles.contentContainer, { backgroundColor: colors.surfaceLight }]}> - {/* Caller Info */} - <CallerInfo isMuted={isMuted && isConnected} /> - - {/* Status Text */} - {isConnected && <CallStatusText />} - - {/* Action Buttons */} - <View style={styles.buttonsContainer}> - {/* First row of buttons */} - <View style={styles.buttonsRow}> - <CallActionButton - icon={isSpeakerOn ? 'audio' : 'audio-disabled'} - label={I18n.t('Speaker')} - onPress={toggleSpeaker} - variant={isSpeakerOn ? 'active' : 'default'} - testID='call-view-speaker' - /> - <CallActionButton - icon={'pause-shape-unfilled'} - label={isOnHold ? I18n.t('Unhold') : I18n.t('Hold')} - onPress={toggleHold} - variant={isOnHold ? 'active' : 'default'} - disabled={isConnecting} - testID='call-view-hold' - /> - <CallActionButton - icon={isMuted ? 'microphone-disabled' : 'microphone'} - label={isMuted ? I18n.t('Unmute') : I18n.t('Mute')} - onPress={toggleMute} - variant={isMuted ? 'active' : 'default'} - disabled={isConnecting} - testID='call-view-mute' - /> - </View> - - {/* Second row of buttons */} - <View style={styles.buttonsRow}> - <CallActionButton icon='message' label={I18n.t('Message')} onPress={handleMessage} testID='call-view-message' /> - <CallActionButton - icon='phone-end' - label={isConnecting ? I18n.t('Cancel') : I18n.t('End')} - onPress={handleEndCall} - variant='danger' - testID='call-view-end' - /> - <CallActionButton icon='kebab' label={I18n.t('More')} onPress={handleMore} testID='call-view-more' /> - </View> - </View> + <CallerInfo /> + <CallButtons /> </View> ); }; diff --git a/app/views/CallView/styles.ts b/app/views/CallView/styles.ts index 484af08e061..a22cd8ab119 100644 --- a/app/views/CallView/styles.ts +++ b/app/views/CallView/styles.ts @@ -50,7 +50,8 @@ export const styles = StyleSheet.create({ textAlign: 'center' }, buttonsContainer: { - padding: 24 + padding: 24, + borderTopWidth: StyleSheet.hairlineWidth }, buttonsRow: { flexDirection: 'row', From 7f5efb1092b5fa91daa5008b241211f7c8040b2c Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 18 Feb 2026 17:04:15 -0300 Subject: [PATCH 50/61] feat: Handle audio routing, e.g., Bluetooth headset vs. internal speaker switching (#6992) --- app/lib/services/voip/useCallStore.ts | 28 +- ios/Podfile.lock | 6 + ios/RocketChatRN.xcodeproj/project.pbxproj | 320 +++++++++++---------- package.json | 1 + yarn.lock | 5 + 5 files changed, 199 insertions(+), 161 deletions(-) diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index b374b5d30aa..c0b9a7568f8 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -1,6 +1,7 @@ import { create } from 'zustand'; import type { CallState, CallContact, IClientMediaCall } from '@rocket.chat/media-signaling'; import RNCallKeep from 'react-native-callkeep'; +import InCallManager from 'react-native-incall-manager'; import Navigation from '../../navigation/appNavigation'; @@ -77,6 +78,12 @@ export const useCallStore = create<CallStore>((set, get) => ({ callStartTime: call.state === 'active' ? Date.now() : null }); + try { + InCallManager.start({ media: 'audio' }); + } catch (error) { + console.error('[VoIP] InCallManager.start failed:', error); + } + // Subscribe to call events const handleStateChange = () => { const currentCall = get().call; @@ -129,10 +136,18 @@ export const useCallStore = create<CallStore>((set, get) => ({ set({ isOnHold: !isOnHold }); }, - toggleSpeaker: () => { - const { isSpeakerOn } = get(); - // TODO: Implement actual speaker toggle via RNCallKeep or WebRTC audio routing - set({ isSpeakerOn: !isSpeakerOn }); + toggleSpeaker: async () => { + const { callUUID, isSpeakerOn } = get(); + if (!callUUID) return; + + const newSpeakerOn = !isSpeakerOn; + + try { + await InCallManager.setForceSpeakerphoneOn(newSpeakerOn); + set({ isSpeakerOn: newSpeakerOn }); + } catch (error) { + console.error('[VoIP] Failed to toggle speaker:', error); + } }, toggleFocus: () => { @@ -165,6 +180,11 @@ export const useCallStore = create<CallStore>((set, get) => ({ }, reset: () => { + try { + InCallManager.stop(); + } catch (error) { + console.error('[VoIP] InCallManager.stop failed:', error); + } set(initialState); } })); diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 974116a738f..3c31f0c4908 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2166,6 +2166,8 @@ PODS: - React-logger (= 0.79.4) - React-perflogger (= 0.79.4) - React-utils (= 0.79.4) + - ReactNativeIncallManager (4.2.1): + - React-Core - RNBootSplash (6.3.8): - DoubleConversion - glog @@ -2743,6 +2745,7 @@ DEPENDENCIES: - ReactAppDependencyProvider (from `build/generated/ios`) - ReactCodegen (from `build/generated/ios`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - ReactNativeIncallManager (from `../node_modules/react-native-incall-manager`) - RNBootSplash (from `../node_modules/react-native-bootsplash`) - RNCallKeep (from `../node_modules/react-native-callkeep`) - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" @@ -3005,6 +3008,8 @@ EXTERNAL SOURCES: :path: build/generated/ios ReactCommon: :path: "../node_modules/react-native/ReactCommon" + ReactNativeIncallManager: + :path: "../node_modules/react-native-incall-manager" RNBootSplash: :path: "../node_modules/react-native-bootsplash" RNCallKeep: @@ -3174,6 +3179,7 @@ SPEC CHECKSUMS: ReactAppDependencyProvider: bf62814e0fde923f73fc64b7e82d76c63c284da9 ReactCodegen: 5c6b68a6cfdfce6b69a8b12d2eb93e1117d96113 ReactCommon: 177fca841e97b2c0e288e86097b8be04c6e7ae36 + ReactNativeIncallManager: dccd3e7499caa3bb73d3acfedf4fb0360f1a87d5 RNBootSplash: 1280eeb18d887de0a45bb4923d4fc56f25c8b99c RNCallKeep: 1930a01d8caf48f018be4f2db0c9f03405c2f977 RNCAsyncStorage: edb872909c88d8541c0bfade3f86cd7784a7c6b3 diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index a87645d11ae..8e0336f1f18 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -273,7 +273,6 @@ 1EFEB5982493B6640072EDC0 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EFEB5972493B6640072EDC0 /* NotificationService.swift */; }; 1EFEB59C2493B6640072EDC0 /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 1EFEB5952493B6640072EDC0 /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 06BB44DD4855498082A744AD /* libz.tbd */; }; - 307FA80AF7CCE3A179785329 /* Pods_defaults_RocketChatRN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B8C48663583BBD95FBC7EB7 /* Pods_defaults_RocketChatRN.framework */; }; 3F56D232A9EBA1C9C749F15D /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A42CFB843397273C7EA /* SecureStorage.m */; }; 3F56D232A9EBA1C9C749F15E /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; 3F56D232A9EBA1C9C749F15F /* MMKVBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A44CFB843397273C7EC /* MMKVBridge.mm */; }; @@ -289,7 +288,7 @@ 66C2701B2EBBCB570062725F /* MMKVKeyManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */; }; 66C2701C2EBBCB570062725F /* MMKVKeyManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */; }; 66C2701D2EBBCB570062725F /* MMKVKeyManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */; }; - 67709318BC12F95CFE0FD019 /* Pods_defaults_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6C0223D4301331E4D2C432A /* Pods_defaults_Rocket_Chat.framework */; }; + 6C4CE0816C17C8809A449508 /* Pods_defaults_Rocket_Chat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01825CC7557A559FA7F295DA /* Pods_defaults_Rocket_Chat.framework */; }; 79D8C97F8CE2EC1B6882826B /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A42CFB843397273C7EA /* SecureStorage.m */; }; 7A0000012F1BAFA700B6B4BD /* VoipService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0000032F1BAFA700B6B4BD /* VoipService.swift */; }; 7A0000022F1BAFA700B6B4BD /* VoipModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A0000042F1BAFA700B6B4BD /* VoipModule.mm */; }; @@ -367,11 +366,12 @@ 7AE10C0628A59530003593CB /* Inter.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7AE10C0528A59530003593CB /* Inter.ttf */; }; 7AE10C0828A59530003593CB /* Inter.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7AE10C0528A59530003593CB /* Inter.ttf */; }; 85160EB6C143E0493FE5F014 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194D9A8897F4A486C2C6F89A /* ExpoModulesProvider.swift */; }; + 8E665E13D412E2A8E55F6E33 /* Pods_defaults_RocketChatRN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E92D6258140274C6B2562E7C /* Pods_defaults_RocketChatRN.framework */; }; A2C6E2DD38F8BEE19BFB2E1D /* SecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B215A42CFB843397273C7EA /* SecureStorage.m */; }; A48B46D92D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; A48B46DA2D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; + AC6086DB073443D98330ED08 /* Pods_defaults_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 112EC394C611BEEA2867A6D3 /* Pods_defaults_NotificationService.framework */; }; BC404914E86821389EEB543D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */; }; - BE62F5275DDCF37207935378 /* Pods_defaults_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B914156975421F5AF8D982B /* Pods_defaults_NotificationService.framework */; }; DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA7E862283664608B3894E34 /* libWatermelonDB.a */; }; /* End PBXBuildFile section */ @@ -471,8 +471,9 @@ /* Begin PBXFileReference section */ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file; path = main.jsbundle; sourceTree = "<group>"; }; + 01825CC7557A559FA7F295DA /* Pods_defaults_Rocket_Chat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_Rocket_Chat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 06BB44DD4855498082A744AD /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; - 0B914156975421F5AF8D982B /* Pods_defaults_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 112EC394C611BEEA2867A6D3 /* Pods_defaults_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* Rocket.Chat Experimental.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Rocket.Chat Experimental.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = RocketChatRN/Images.xcassets; sourceTree = "<group>"; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RocketChatRN/Info.plist; sourceTree = "<group>"; }; @@ -620,14 +621,14 @@ 1EFEB5992493B6640072EDC0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 1EFEB5A12493B67D0072EDC0 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = "<group>"; }; 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-Rocket.Chat/ExpoModulesProvider.swift"; sourceTree = "<group>"; }; - 3B8C48663583BBD95FBC7EB7 /* Pods_defaults_RocketChatRN.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_RocketChatRN.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 45D5C142B655F8EFD006792C /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-defaults-RocketChatRN/ExpoModulesProvider.swift"; sourceTree = "<group>"; }; - 57DFA6D849BD9281E6E50D40 /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = "<group>"; }; + 502EF0FB778C0E7F43E5F002 /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = "<group>"; }; 60B2A6A31FC4588700BD58E5 /* RocketChatRN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = RocketChatRN.entitlements; path = RocketChatRN/RocketChatRN.entitlements; sourceTree = "<group>"; }; 65AD38362BFBDF4A00271B39 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 65B9A7192AFC24190088956F /* ringtone.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = ringtone.mp3; sourceTree = "<group>"; }; 66C270192EBBCB570062725F /* MMKVKeyManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MMKVKeyManager.h; sourceTree = "<group>"; }; 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MMKVKeyManager.mm; sourceTree = "<group>"; }; + 6D1EBBAC4E3123CB93511A8B /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = "<group>"; }; 7A0000032F1BAFA700B6B4BD /* VoipService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoipService.swift; sourceTree = "<group>"; }; 7A0000042F1BAFA700B6B4BD /* VoipModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = VoipModule.mm; sourceTree = "<group>"; }; 7A006F13229C83B600803143 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; }; @@ -647,19 +648,18 @@ 7ACD4853222860DE00442C55 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 7ACFE7D82DDE48760090D9BC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 7AE10C0528A59530003593CB /* Inter.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Inter.ttf; sourceTree = "<group>"; }; - 7DC5F24E96CE93D8C5FFE9BF /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = "<group>"; }; - 8230DCE68AB8DE26A960AA9D /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; }; + 88E80C594F039C8B1DCC5B26 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = "<group>"; }; 9B215A42CFB843397273C7EA /* SecureStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = SecureStorage.m; sourceTree = "<group>"; }; 9B215A44CFB843397273C7EC /* MMKVBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MMKVBridge.mm; path = Shared/RocketChat/MMKVBridge.mm; sourceTree = "<group>"; }; + 9BD1145A1612F5D6A655D75A /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; }; + A3FFA83FC7CA4F1C7C42F2A8 /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = "<group>"; }; A48B46D72D3FFBD200945489 /* A11yFlowModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = A11yFlowModule.h; sourceTree = "<group>"; }; A48B46D82D3FFBD200945489 /* A11yFlowModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = A11yFlowModule.m; sourceTree = "<group>"; }; - A9D34C919F230A78C65B84D5 /* Pods-defaults-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.debug.xcconfig"; sourceTree = "<group>"; }; B179038FDD7AAF285047814B /* SecureStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = SecureStorage.h; sourceTree = "<group>"; }; B37C79D9BD0742CE936B6982 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; BA7E862283664608B3894E34 /* libWatermelonDB.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libWatermelonDB.a; sourceTree = "<group>"; }; - C6C0223D4301331E4D2C432A /* Pods_defaults_Rocket_Chat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_Rocket_Chat.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C80C46CC53976257D922AA93 /* Pods-defaults-Rocket.Chat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.debug.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.debug.xcconfig"; sourceTree = "<group>"; }; - F4E678964EBBF99E850F1D6B /* Pods-defaults-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.debug.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.debug.xcconfig"; sourceTree = "<group>"; }; + C51A99C4635C7A2000B0AE81 /* Pods-defaults-Rocket.Chat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-Rocket.Chat.release.xcconfig"; path = "Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat.release.xcconfig"; sourceTree = "<group>"; }; + E92D6258140274C6B2562E7C /* Pods_defaults_RocketChatRN.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_defaults_RocketChatRN.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -680,7 +680,7 @@ 7ACD4897222860DE00442C55 /* JavaScriptCore.framework in Frameworks */, 24A2AEF2383D44B586D31C01 /* libz.tbd in Frameworks */, DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */, - 307FA80AF7CCE3A179785329 /* Pods_defaults_RocketChatRN.framework in Frameworks */, + 8E665E13D412E2A8E55F6E33 /* Pods_defaults_RocketChatRN.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -702,7 +702,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BE62F5275DDCF37207935378 /* Pods_defaults_NotificationService.framework in Frameworks */, + AC6086DB073443D98330ED08 /* Pods_defaults_NotificationService.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -723,7 +723,7 @@ 7AAB3E3D257E6A6E00707CF6 /* JavaScriptCore.framework in Frameworks */, 7AAB3E3E257E6A6E00707CF6 /* libz.tbd in Frameworks */, 7AAB3E3F257E6A6E00707CF6 /* libWatermelonDB.a in Frameworks */, - 67709318BC12F95CFE0FD019 /* Pods_defaults_Rocket_Chat.framework in Frameworks */, + 6C4CE0816C17C8809A449508 /* Pods_defaults_Rocket_Chat.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1162,12 +1162,12 @@ 7AC2B09613AA7C3FEBAC9F57 /* Pods */ = { isa = PBXGroup; children = ( - A9D34C919F230A78C65B84D5 /* Pods-defaults-NotificationService.debug.xcconfig */, - 7DC5F24E96CE93D8C5FFE9BF /* Pods-defaults-NotificationService.release.xcconfig */, - C80C46CC53976257D922AA93 /* Pods-defaults-Rocket.Chat.debug.xcconfig */, - 57DFA6D849BD9281E6E50D40 /* Pods-defaults-Rocket.Chat.release.xcconfig */, - F4E678964EBBF99E850F1D6B /* Pods-defaults-RocketChatRN.debug.xcconfig */, - 8230DCE68AB8DE26A960AA9D /* Pods-defaults-RocketChatRN.release.xcconfig */, + 88E80C594F039C8B1DCC5B26 /* Pods-defaults-NotificationService.debug.xcconfig */, + A3FFA83FC7CA4F1C7C42F2A8 /* Pods-defaults-NotificationService.release.xcconfig */, + 502EF0FB778C0E7F43E5F002 /* Pods-defaults-Rocket.Chat.debug.xcconfig */, + C51A99C4635C7A2000B0AE81 /* Pods-defaults-Rocket.Chat.release.xcconfig */, + 6D1EBBAC4E3123CB93511A8B /* Pods-defaults-RocketChatRN.debug.xcconfig */, + 9BD1145A1612F5D6A655D75A /* Pods-defaults-RocketChatRN.release.xcconfig */, ); path = Pods; sourceTree = "<group>"; @@ -1257,9 +1257,9 @@ 7ACD4853222860DE00442C55 /* JavaScriptCore.framework */, B37C79D9BD0742CE936B6982 /* libc++.tbd */, 06BB44DD4855498082A744AD /* libz.tbd */, - 0B914156975421F5AF8D982B /* Pods_defaults_NotificationService.framework */, - C6C0223D4301331E4D2C432A /* Pods_defaults_Rocket_Chat.framework */, - 3B8C48663583BBD95FBC7EB7 /* Pods_defaults_RocketChatRN.framework */, + 112EC394C611BEEA2867A6D3 /* Pods_defaults_NotificationService.framework */, + 01825CC7557A559FA7F295DA /* Pods_defaults_Rocket_Chat.framework */, + E92D6258140274C6B2562E7C /* Pods_defaults_RocketChatRN.framework */, ); name = Frameworks; sourceTree = "<group>"; @@ -1279,7 +1279,7 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "RocketChatRN" */; buildPhases = ( - 93EF7975E0C4C603BD18F87C /* [CP] Check Pods Manifest.lock */, + 504592CD551433A983430EBF /* [CP] Check Pods Manifest.lock */, 06C10D4F29CD7532492AD29E /* [Expo] Configure project */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, @@ -1289,8 +1289,8 @@ 1E1EA8082326CCE300E22452 /* ShellScript */, 1ED0389C2B507B4F00C007D4 /* Embed Watch Content */, 7AAE9EB32891A0D20024F559 /* Upload source maps to Bugsnag */, - 1840C56D2D066F638B2A748B /* [CP] Embed Pods Frameworks */, - 1199CD71D36A54C2713FCD3E /* [CP] Copy Pods Resources */, + 8F4AF0F46C8A7237DF8C16FA /* [CP] Embed Pods Frameworks */, + 8DEAC14DF3433A2019536C64 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1358,12 +1358,12 @@ isa = PBXNativeTarget; buildConfigurationList = 1EFEB5A02493B6640072EDC0 /* Build configuration list for PBXNativeTarget "NotificationService" */; buildPhases = ( - 480C35381BCFF59C9015726E /* [CP] Check Pods Manifest.lock */, + 8411AC317FC27278C916B5E8 /* [CP] Check Pods Manifest.lock */, 86A998705576AFA7CE938617 /* [Expo] Configure project */, 1EFEB5912493B6640072EDC0 /* Sources */, 1EFEB5922493B6640072EDC0 /* Frameworks */, 1EFEB5932493B6640072EDC0 /* Resources */, - 28340DD974173F56DB07A9FC /* [CP] Copy Pods Resources */, + 3DF9C309C5E980B085E69887 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1378,7 +1378,7 @@ isa = PBXNativeTarget; buildConfigurationList = 7AAB3E4F257E6A6E00707CF6 /* Build configuration list for PBXNativeTarget "Rocket.Chat" */; buildPhases = ( - FBF64C5737C1CD5B1ECC58DC /* [CP] Check Pods Manifest.lock */, + F7C5B37C9876312B8B0E5AD9 /* [CP] Check Pods Manifest.lock */, 6319FBDD06EF0030B48AD389 /* [Expo] Configure project */, 7AAB3E14257E6A6E00707CF6 /* Sources */, 7AAB3E32257E6A6E00707CF6 /* Frameworks */, @@ -1388,8 +1388,8 @@ 7A55BE3C2F1131C000D8744D /* ShellScript */, 1ED1ECE32B8699DD00F6620C /* Embed Watch Content */, 7A55BE3D2F11320C00D8744D /* Upload source maps to Bugsnag */, - 265F5F7FE4FE17B65751C48D /* [CP] Embed Pods Frameworks */, - 9C5D6D7D9D5E936CB1720CA9 /* [CP] Copy Pods Resources */, + 249DAF3363A5963431094167 /* [CP] Embed Pods Frameworks */, + 8CF4DBF996133696144F02A2 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1582,102 +1582,6 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-RocketChatRN/expo-configure-project.sh\"\n"; }; - 1199CD71D36A54C2713FCD3E /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/BugsnagReactNative/Bugsnag.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications/ExpoNotifications_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/ExpoDevice/ExpoDevice_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreExtension/FirebaseCoreExtension_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreInternal/FirebaseCoreInternal_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCrashlytics/FirebaseCrashlytics_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/PromisesSwift/Promises_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo/RNDeviceInfoPrivacyInfo.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/RNImageCropPickerPrivacyInfo.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb_Privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/react-native-cameraroll/RNCameraRollPrivacyInfo.bundle", - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Bugsnag.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoApplication_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoNotifications_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoDevice_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCore_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCoreExtension_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCoreInternal_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCrashlytics_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseInstallations_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleDataTransport_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleUtilities_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FBLPromises_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Promises_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNDeviceInfoPrivacyInfo.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNImageCropPickerPrivacyInfo.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/nanopb_Privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNCameraRollPrivacyInfo.bundle", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 1840C56D2D066F638B2A748B /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 1E1EA8082326CCE300E22452 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1695,7 +1599,7 @@ shellPath = /bin/sh; shellScript = "echo \"Target architectures: $ARCHS\"\n\nAPP_PATH=\"${TARGET_BUILD_DIR}/${WRAPPER_NAME}\"\n\nfind \"$APP_PATH\" -name '*.framework' -type d | while read -r FRAMEWORK\ndo\nFRAMEWORK_EXECUTABLE_NAME=$(defaults read \"$FRAMEWORK/Info.plist\" CFBundleExecutable)\nFRAMEWORK_EXECUTABLE_PATH=\"$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME\"\necho \"Executable is $FRAMEWORK_EXECUTABLE_PATH\"\necho $(lipo -info \"$FRAMEWORK_EXECUTABLE_PATH\")\n\nFRAMEWORK_TMP_PATH=\"$FRAMEWORK_EXECUTABLE_PATH-tmp\"\n\n# remove simulator's archs if location is not simulator's directory\ncase \"${TARGET_BUILD_DIR}\" in\n*\"iphonesimulator\")\necho \"No need to remove archs\"\n;;\n*)\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"i386\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"i386\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"i386 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\nif $(lipo \"$FRAMEWORK_EXECUTABLE_PATH\" -verify_arch \"x86_64\") ; then\nlipo -output \"$FRAMEWORK_TMP_PATH\" -remove \"x86_64\" \"$FRAMEWORK_EXECUTABLE_PATH\"\necho \"x86_64 architecture removed\"\nrm \"$FRAMEWORK_EXECUTABLE_PATH\"\nmv \"$FRAMEWORK_TMP_PATH\" \"$FRAMEWORK_EXECUTABLE_PATH\"\nfi\n;;\nesac\n\necho \"Completed for executable $FRAMEWORK_EXECUTABLE_PATH\"\necho $\n\ndone\n"; }; - 265F5F7FE4FE17B65751C48D /* [CP] Embed Pods Frameworks */ = { + 249DAF3363A5963431094167 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1715,7 +1619,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 28340DD974173F56DB07A9FC /* [CP] Copy Pods Resources */ = { + 3DF9C309C5E980B085E69887 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1791,7 +1695,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 480C35381BCFF59C9015726E /* [CP] Check Pods Manifest.lock */ = { + 504592CD551433A983430EBF /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -1806,7 +1710,7 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-defaults-RocketChatRN-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -1875,7 +1779,7 @@ inputFileListPaths = ( ); inputPaths = ( - $TARGET_BUILD_DIR/$INFOPLIST_PATH, + "$TARGET_BUILD_DIR/$INFOPLIST_PATH", ); name = "Upload source maps to Bugsnag"; outputFileListPaths = ( @@ -1895,7 +1799,7 @@ inputFileListPaths = ( ); inputPaths = ( - $TARGET_BUILD_DIR/$INFOPLIST_PATH, + "$TARGET_BUILD_DIR/$INFOPLIST_PATH", ); name = "Upload source maps to Bugsnag"; outputFileListPaths = ( @@ -1907,48 +1811,48 @@ shellScript = "#SOURCE_MAP=\"$TMPDIR/$(md5 -qs \"$CONFIGURATION_BUILD_DIR\")-main.jsbundle.map\" ../node_modules/@bugsnag/react-native/bugsnag-react-native-xcode.sh\n"; showEnvVarsInLog = 0; }; - 86A998705576AFA7CE938617 /* [Expo] Configure project */ = { + 8411AC317FC27278C916B5E8 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); - name = "[Expo] Configure project"; + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-defaults-NotificationService-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-NotificationService/expo-configure-project.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - 93EF7975E0C4C603BD18F87C /* [CP] Check Pods Manifest.lock */ = { + 86A998705576AFA7CE938617 /* [Expo] Configure project */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Check Pods Manifest.lock"; + name = "[Expo] Configure project"; outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-defaults-RocketChatRN-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-defaults-NotificationService/expo-configure-project.sh\"\n"; }; - 9C5D6D7D9D5E936CB1720CA9 /* [CP] Copy Pods Resources */ = { + 8CF4DBF996133696144F02A2 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2024,7 +1928,103 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-Rocket.Chat/Pods-defaults-Rocket.Chat-resources.sh\"\n"; showEnvVarsInLog = 0; }; - FBF64C5737C1CD5B1ECC58DC /* [CP] Check Pods Manifest.lock */ = { + 8DEAC14DF3433A2019536C64 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/BugsnagReactNative/Bugsnag.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications/ExpoNotifications_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/ExpoDevice/ExpoDevice_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreExtension/FirebaseCoreExtension_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreInternal/FirebaseCoreInternal_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCrashlytics/FirebaseCrashlytics_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/PromisesSwift/Promises_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo/RNDeviceInfoPrivacyInfo.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/RNImageCropPickerPrivacyInfo.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker/QBImagePicker.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/TOCropViewController/TOCropViewControllerBundle.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb_Privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/react-native-cameraroll/RNCameraRollPrivacyInfo.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Bugsnag.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoApplication_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoNotifications_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoDevice_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCore_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCoreExtension_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCoreInternal_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCrashlytics_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseInstallations_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleDataTransport_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleUtilities_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FBLPromises_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Promises_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNDeviceInfoPrivacyInfo.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNImageCropPickerPrivacyInfo.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/QBImagePicker.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TOCropViewControllerBundle.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/nanopb_Privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNCameraRollPrivacyInfo.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 8F4AF0F46C8A7237DF8C16FA /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/JitsiWebRTC/WebRTC.framework/WebRTC", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F7C5B37C9876312B8B0E5AD9 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -2441,7 +2441,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F4E678964EBBF99E850F1D6B /* Pods-defaults-RocketChatRN.debug.xcconfig */; + baseConfigurationReference = 6D1EBBAC4E3123CB93511A8B /* Pods-defaults-RocketChatRN.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2506,7 +2506,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8230DCE68AB8DE26A960AA9D /* Pods-defaults-RocketChatRN.release.xcconfig */; + baseConfigurationReference = 9BD1145A1612F5D6A655D75A /* Pods-defaults-RocketChatRN.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -2613,7 +2613,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/rn-extensions-share/ios/**", "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - $PODS_CONFIGURATION_BUILD_DIR/Firebase, + "$PODS_CONFIGURATION_BUILD_DIR/Firebase", ); INFOPLIST_FILE = ShareRocketChatRN/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.1; @@ -2689,7 +2689,7 @@ "$(inherited)", "$(SRCROOT)/../node_modules/rn-extensions-share/ios/**", "$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**", - $PODS_CONFIGURATION_BUILD_DIR/Firebase, + "$PODS_CONFIGURATION_BUILD_DIR/Firebase", ); INFOPLIST_FILE = ShareRocketChatRN/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.1; @@ -2921,7 +2921,7 @@ }; 1EFEB59D2493B6640072EDC0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A9D34C919F230A78C65B84D5 /* Pods-defaults-NotificationService.debug.xcconfig */; + baseConfigurationReference = 88E80C594F039C8B1DCC5B26 /* Pods-defaults-NotificationService.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(EMBEDDED_CONTENT_CONTAINS_SWIFT)"; CLANG_ANALYZER_NONNULL = YES; @@ -2973,7 +2973,7 @@ }; 1EFEB59E2493B6640072EDC0 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7DC5F24E96CE93D8C5FFE9BF /* Pods-defaults-NotificationService.release.xcconfig */; + baseConfigurationReference = A3FFA83FC7CA4F1C7C42F2A8 /* Pods-defaults-NotificationService.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(EMBEDDED_CONTENT_CONTAINS_SWIFT)"; CLANG_ANALYZER_NONNULL = YES; @@ -3024,7 +3024,7 @@ }; 7AAB3E50257E6A6E00707CF6 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C80C46CC53976257D922AA93 /* Pods-defaults-Rocket.Chat.debug.xcconfig */; + baseConfigurationReference = 502EF0FB778C0E7F43E5F002 /* Pods-defaults-Rocket.Chat.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -3089,7 +3089,7 @@ }; 7AAB3E51257E6A6E00707CF6 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 57DFA6D849BD9281E6E50D40 /* Pods-defaults-Rocket.Chat.release.xcconfig */; + baseConfigurationReference = C51A99C4635C7A2000B0AE81 /* Pods-defaults-Rocket.Chat.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; APPLICATION_EXTENSION_API_ONLY = NO; @@ -3214,7 +3214,10 @@ ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited) "; + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; @@ -3278,7 +3281,10 @@ MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = "$(inherited)"; - OTHER_LDFLAGS = "$(inherited) "; + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/package.json b/package.json index 930d35be551..7a5f6c31b4f 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "react-native-file-viewer": "2.1.4", "react-native-gesture-handler": "2.24.0", "react-native-image-crop-picker": "RocketChat/react-native-image-crop-picker#5346870b0be10d300dc53924309dc6adc9946d50", + "react-native-incall-manager": "^4.2.1", "react-native-katex": "git+https://github.com/RocketChat/react-native-katex.git", "react-native-keyboard-controller": "^1.17.1", "react-native-linear-gradient": "2.6.2", diff --git a/yarn.lock b/yarn.lock index ec569a30add..f64c8f247ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12734,6 +12734,11 @@ react-native-image-crop-picker@RocketChat/react-native-image-crop-picker#5346870 version "0.50.1" resolved "https://codeload.github.com/RocketChat/react-native-image-crop-picker/tar.gz/5346870b0be10d300dc53924309dc6adc9946d50" +react-native-incall-manager@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/react-native-incall-manager/-/react-native-incall-manager-4.2.1.tgz#6a261693d8906f6e69c79356e5048e95d0e3e239" + integrity sha512-HTdtzQ/AswUbuNhcL0gmyZLAXo8VqBO7SIh+BwbeeM1YMXXlR+Q2MvKxhD4yanjJPeyqMfuRhryCQCJhPlsdAw== + react-native-is-edge-to-edge@1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.1.6.tgz#69ec13f70d76e9245e275eed4140d0873a78f902" From 9abbdd5ce4df764ce7e61eb878fa1b2365807818 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 18 Feb 2026 17:19:55 -0300 Subject: [PATCH 51/61] fix: empty space when not on call (#6993) --- .../MediaCallHeader/MediaCallHeader.tsx | 8 ++-- .../MediaCallHeader.test.tsx.snap | 37 +++++++++---------- .../MediaCallHeader/components/Content.tsx | 2 +- .../MediaCallHeader/components/Subtitle.tsx | 7 +++- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/app/containers/MediaCallHeader/MediaCallHeader.tsx b/app/containers/MediaCallHeader/MediaCallHeader.tsx index a3a0fa3ad14..2e7d508d793 100644 --- a/app/containers/MediaCallHeader/MediaCallHeader.tsx +++ b/app/containers/MediaCallHeader/MediaCallHeader.tsx @@ -14,6 +14,7 @@ const styles = StyleSheet.create({ justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 12, + paddingBottom: 12, borderBottomWidth: StyleSheet.hairlineWidth } }); @@ -27,8 +28,7 @@ const MediaCallHeader = () => { const defaultHeaderStyle = { backgroundColor: colors.surfaceNeutral, - paddingTop: insets.top + 12, - paddingBottom: 12 + paddingTop: insets.top }; if (!call) { @@ -36,7 +36,9 @@ const MediaCallHeader = () => { } return ( - <View style={[styles.header, { ...defaultHeaderStyle, borderBottomColor: colors.strokeLight }]} testID='media-call-header'> + <View + style={[styles.header, { ...defaultHeaderStyle, borderBottomColor: colors.strokeLight, paddingTop: insets.top + 12 }]} + testID='media-call-header'> <Collapse /> <Content /> <EndCall /> diff --git a/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap index 46805f06c9a..c4641321457 100644 --- a/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap +++ b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap @@ -16,12 +16,12 @@ exports[`Story Snapshots: ActiveCall should match snapshot 1`] = ` "borderBottomWidth": 0.5, "flexDirection": "row", "justifyContent": "space-between", + "paddingBottom": 12, "paddingHorizontal": 12, }, { "backgroundColor": "#E4E7EA", "borderBottomColor": "#CBCED1", - "paddingBottom": 12, "paddingTop": 12, }, ] @@ -158,8 +158,8 @@ exports[`Story Snapshots: ActiveCall should match snapshot 1`] = ` style={ { "alignItems": "flex-start", - "flex": 1, "flexDirection": "column", + "flexGrow": 1, "justifyContent": "space-evenly", } } @@ -228,7 +228,7 @@ exports[`Story Snapshots: ActiveCall should match snapshot 1`] = ` Bob Burnquist <Text> - - 16117:18:53 + 16140:16:32 </Text> </Text> </View> @@ -362,12 +362,12 @@ exports[`Story Snapshots: Collapsed should match snapshot 1`] = ` "borderBottomWidth": 0.5, "flexDirection": "row", "justifyContent": "space-between", + "paddingBottom": 12, "paddingHorizontal": 12, }, { "backgroundColor": "#E4E7EA", "borderBottomColor": "#CBCED1", - "paddingBottom": 12, "paddingTop": 12, }, ] @@ -504,8 +504,8 @@ exports[`Story Snapshots: Collapsed should match snapshot 1`] = ` style={ { "alignItems": "flex-start", - "flex": 1, "flexDirection": "column", + "flexGrow": 1, "justifyContent": "space-evenly", } } @@ -574,7 +574,7 @@ exports[`Story Snapshots: Collapsed should match snapshot 1`] = ` Bob Burnquist <Text> - - 16117:18:53 + 16140:16:32 </Text> </Text> </View> @@ -708,12 +708,12 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` "borderBottomWidth": 0.5, "flexDirection": "row", "justifyContent": "space-between", + "paddingBottom": 12, "paddingHorizontal": 12, }, { "backgroundColor": "#E4E7EA", "borderBottomColor": "#CBCED1", - "paddingBottom": 12, "paddingTop": 12, }, ] @@ -850,8 +850,8 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` style={ { "alignItems": "flex-start", - "flex": 1, "flexDirection": "column", + "flexGrow": 1, "justifyContent": "space-evenly", } } @@ -1050,12 +1050,12 @@ exports[`Story Snapshots: Focused should match snapshot 1`] = ` "borderBottomWidth": 0.5, "flexDirection": "row", "justifyContent": "space-between", + "paddingBottom": 12, "paddingHorizontal": 12, }, { "backgroundColor": "#E4E7EA", "borderBottomColor": "#CBCED1", - "paddingBottom": 12, "paddingTop": 12, }, ] @@ -1192,8 +1192,8 @@ exports[`Story Snapshots: Focused should match snapshot 1`] = ` style={ { "alignItems": "flex-start", - "flex": 1, "flexDirection": "column", + "flexGrow": 1, "justifyContent": "space-evenly", } } @@ -1262,7 +1262,7 @@ exports[`Story Snapshots: Focused should match snapshot 1`] = ` Bob Burnquist <Text> - - 16117:18:53 + 16140:16:32 </Text> </Text> </View> @@ -1392,8 +1392,7 @@ exports[`Story Snapshots: NoCall should match snapshot 1`] = ` style={ { "backgroundColor": "#E4E7EA", - "paddingBottom": 12, - "paddingTop": 12, + "paddingTop": 0, } } testID="media-call-header-empty" @@ -1417,12 +1416,12 @@ exports[`Story Snapshots: WithRemoteHeld should match snapshot 1`] = ` "borderBottomWidth": 0.5, "flexDirection": "row", "justifyContent": "space-between", + "paddingBottom": 12, "paddingHorizontal": 12, }, { "backgroundColor": "#E4E7EA", "borderBottomColor": "#CBCED1", - "paddingBottom": 12, "paddingTop": 12, }, ] @@ -1559,8 +1558,8 @@ exports[`Story Snapshots: WithRemoteHeld should match snapshot 1`] = ` style={ { "alignItems": "flex-start", - "flex": 1, "flexDirection": "column", + "flexGrow": 1, "justifyContent": "space-evenly", } } @@ -1629,7 +1628,7 @@ exports[`Story Snapshots: WithRemoteHeld should match snapshot 1`] = ` Bob Burnquist <Text> - - 16117:18:53 + 16140:16:32 </Text> </Text> </View> @@ -1763,12 +1762,12 @@ exports[`Story Snapshots: WithRemoteMuted should match snapshot 1`] = ` "borderBottomWidth": 0.5, "flexDirection": "row", "justifyContent": "space-between", + "paddingBottom": 12, "paddingHorizontal": 12, }, { "backgroundColor": "#E4E7EA", "borderBottomColor": "#CBCED1", - "paddingBottom": 12, "paddingTop": 12, }, ] @@ -1905,8 +1904,8 @@ exports[`Story Snapshots: WithRemoteMuted should match snapshot 1`] = ` style={ { "alignItems": "flex-start", - "flex": 1, "flexDirection": "column", + "flexGrow": 1, "justifyContent": "space-evenly", } } @@ -1975,7 +1974,7 @@ exports[`Story Snapshots: WithRemoteMuted should match snapshot 1`] = ` Bob Burnquist <Text> - - 16117:18:53 + 16140:16:32 </Text> </Text> </View> diff --git a/app/containers/MediaCallHeader/components/Content.tsx b/app/containers/MediaCallHeader/components/Content.tsx index 566918a42c2..d6d3c079d7f 100644 --- a/app/containers/MediaCallHeader/components/Content.tsx +++ b/app/containers/MediaCallHeader/components/Content.tsx @@ -9,7 +9,7 @@ const styles = StyleSheet.create({ paddingHorizontal: 4 }, container: { - flex: 1, + flexGrow: 1, flexDirection: 'column', justifyContent: 'space-evenly', alignItems: 'flex-start' diff --git a/app/containers/MediaCallHeader/components/Subtitle.tsx b/app/containers/MediaCallHeader/components/Subtitle.tsx index 364886e31b6..41c11486d3e 100644 --- a/app/containers/MediaCallHeader/components/Subtitle.tsx +++ b/app/containers/MediaCallHeader/components/Subtitle.tsx @@ -6,7 +6,7 @@ import I18n from '../../../i18n'; import sharedStyles from '../../../views/Styles'; const styles = StyleSheet.create({ - headerTitle: { + headerSubtitle: { ...sharedStyles.textRegular, fontSize: 12, lineHeight: 16 @@ -42,7 +42,10 @@ const Subtitle = () => { } return ( - <Text style={[styles.headerTitle, { color: colors.fontSecondaryInfo }]} testID='call-view-header-subtitle' numberOfLines={1}> + <Text + style={[styles.headerSubtitle, { color: colors.fontSecondaryInfo }]} + testID='call-view-header-subtitle' + numberOfLines={1}> {subtitle} </Text> ); From 11809f1a3944d7d629de7a9368791da8bcddb493 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Mon, 23 Feb 2026 14:39:08 -0300 Subject: [PATCH 52/61] feat: Dialpad (#7000) --- .../MediaCallHeader/MediaCallHeader.test.tsx | 4 +- .../MediaCallHeader.test.tsx.snap | 10 +- app/i18n/locales/en.json | 1 + app/lib/services/voip/MediaSessionInstance.ts | 1 + app/lib/services/voip/useCallStore.ts | 37 +- .../__snapshots__/index.test.tsx.snap | 84 +- .../CallView/components/CallActionButton.tsx | 8 +- app/views/CallView/components/CallButtons.tsx | 16 +- .../components/Dialpad/Dialpad.stories.tsx | 57 + .../components/Dialpad/Dialpad.test.tsx | 121 + .../CallView/components/Dialpad/Dialpad.tsx | 67 + .../components/Dialpad/DialpadButton.tsx | 40 + .../__snapshots__/Dialpad.test.tsx.snap | 2519 +++++++++++++++++ .../CallView/components/Dialpad/styles.ts | 45 + .../__snapshots__/CallerInfo.test.tsx.snap | 8 +- app/views/CallView/index.test.tsx | 49 +- app/views/CallView/index.tsx | 10 +- jest.setup.js | 12 +- package.json | 2 +- ... => rocket.chat-media-signaling-0.1.1.tgz} | Bin yarn.lock | 22 +- 21 files changed, 2985 insertions(+), 128 deletions(-) create mode 100644 app/views/CallView/components/Dialpad/Dialpad.stories.tsx create mode 100644 app/views/CallView/components/Dialpad/Dialpad.test.tsx create mode 100644 app/views/CallView/components/Dialpad/Dialpad.tsx create mode 100644 app/views/CallView/components/Dialpad/DialpadButton.tsx create mode 100644 app/views/CallView/components/Dialpad/__snapshots__/Dialpad.test.tsx.snap create mode 100644 app/views/CallView/components/Dialpad/styles.ts rename packages/{rocket.chat-media-signaling-0.1.0.tgz => rocket.chat-media-signaling-0.1.1.tgz} (100%) diff --git a/app/containers/MediaCallHeader/MediaCallHeader.test.tsx b/app/containers/MediaCallHeader/MediaCallHeader.test.tsx index c63e829ac9e..f145f038d7e 100644 --- a/app/containers/MediaCallHeader/MediaCallHeader.test.tsx +++ b/app/containers/MediaCallHeader/MediaCallHeader.test.tsx @@ -56,9 +56,7 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat }); }; -const Wrapper = ({ children }: { children: React.ReactNode }) => ( - <Provider store={mockedStore}>{children}</Provider> -); +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; describe('MediaCallHeader', () => { beforeEach(() => { diff --git a/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap index c4641321457..12728940a37 100644 --- a/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap +++ b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap @@ -228,7 +228,7 @@ exports[`Story Snapshots: ActiveCall should match snapshot 1`] = ` Bob Burnquist <Text> - - 16140:16:32 + 16254:59:32 </Text> </Text> </View> @@ -574,7 +574,7 @@ exports[`Story Snapshots: Collapsed should match snapshot 1`] = ` Bob Burnquist <Text> - - 16140:16:32 + 16254:59:32 </Text> </Text> </View> @@ -1262,7 +1262,7 @@ exports[`Story Snapshots: Focused should match snapshot 1`] = ` Bob Burnquist <Text> - - 16140:16:32 + 16254:59:32 </Text> </Text> </View> @@ -1628,7 +1628,7 @@ exports[`Story Snapshots: WithRemoteHeld should match snapshot 1`] = ` Bob Burnquist <Text> - - 16140:16:32 + 16254:59:32 </Text> </Text> </View> @@ -1974,7 +1974,7 @@ exports[`Story Snapshots: WithRemoteMuted should match snapshot 1`] = ` Bob Burnquist <Text> - - 16140:16:32 + 16254:59:32 </Text> </Text> </View> diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index e2049354e04..925cec10b89 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -241,6 +241,7 @@ "Device_notification_settings": "Device notification settings", "Device_notifications_alert_description": "Please go to your settings app and enable notifications for Rocket.Chat", "Device_notifications_alert_title": "Notifications disabled", + "Dialpad": "Dialpad", "Direct_message": "Direct message", "Direct_message_someone": "Direct message someone", "Direct_Messages": "Direct messages", diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index efc4c9ecec5..16d08e696a3 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -99,6 +99,7 @@ class MediaSessionInstance { Navigation.navigate('CallView', { callUUID }); } else { RNCallKeep.endCall(callUUID); + alert('Call not found'); // TODO: Show error message? } }; diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index c0b9a7568f8..e9c9c9cff98 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -4,6 +4,7 @@ import RNCallKeep from 'react-native-callkeep'; import InCallManager from 'react-native-incall-manager'; import Navigation from '../../navigation/appNavigation'; +import { hideActionSheetRef } from '../../../containers/ActionSheet'; interface CallStoreState { // Call reference @@ -19,6 +20,7 @@ interface CallStoreState { isSpeakerOn: boolean; callStartTime: number | null; focused: boolean; + dialpadValue: string; // Contact info contact: CallContact; @@ -33,6 +35,7 @@ interface CallStoreActions { toggleFocus: () => void; endCall: () => void; reset: () => void; + setDialpadValue: (value: string) => void; } export type CallStore = CallStoreState & CallStoreActions; @@ -48,7 +51,8 @@ const initialState: CallStoreState = { isSpeakerOn: false, callStartTime: null, contact: {}, - focused: true + focused: true, + dialpadValue: '' }; export const useCallStore = create<CallStore>((set, get) => ({ @@ -68,7 +72,6 @@ export const useCallStore = create<CallStore>((set, get) => ({ isOnHold: call.held, remoteMute: call.remoteMute, remoteHeld: call.remoteHeld, - // isSpeakerOn: call. contact: { id: call.contact.id, displayName: call.contact.displayName, @@ -160,6 +163,15 @@ export const useCallStore = create<CallStore>((set, get) => ({ } }, + setDialpadValue: (value: string) => { + const { call } = get(); + if (!call) return; + + call.sendDTMF(value); + const newValue = get().dialpadValue + value; + set({ dialpadValue: newValue }); + }, + endCall: () => { const { call, callState, callUUID } = get(); @@ -186,31 +198,14 @@ export const useCallStore = create<CallStore>((set, get) => ({ console.error('[VoIP] InCallManager.stop failed:', error); } set(initialState); + hideActionSheetRef(); } })); -// const isConnecting = callState === 'none' || callState === 'ringing' || callState === 'accepted'; -// const isConnected = callState === 'active'; export const useCallState = () => { const callState = useCallStore(state => state.callState); return callState === 'none' || callState === 'ringing' || callState === 'accepted'; }; -// // Selector hooks for better performance -// export const useCallState = () => useCallStore(state => state.callState); export const useCallContact = () => useCallStore(state => state.contact); -// export const useCallControls = () => -// useCallStore( -// useShallow(state => ({ -// isMuted: state.isMuted, -// isOnHold: state.isOnHold, -// isSpeakerOn: state.isSpeakerOn -// })) -// ); -// export const useCallActions = () => -// useCallStore(state => ({ -// toggleMute: state.toggleMute, -// toggleHold: state.toggleHold, -// toggleSpeaker: state.toggleSpeaker, -// endCall: state.endCall -// })); +export const useDialpadValue = () => useCallStore(state => state.dialpadValue); diff --git a/app/views/CallView/__snapshots__/index.test.tsx.snap b/app/views/CallView/__snapshots__/index.test.tsx.snap index 703e4a6d0c6..3ba17f50b68 100644 --- a/app/views/CallView/__snapshots__/index.test.tsx.snap +++ b/app/views/CallView/__snapshots__/index.test.tsx.snap @@ -76,7 +76,9 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` source={ [ { - "headers": undefined, + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", }, ] @@ -650,7 +652,7 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` </View> <View> <View - accessibilityLabel="More" + accessibilityLabel="Dialpad" accessibilityRole="button" accessibilityState={ { @@ -697,7 +699,7 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` }, ] } - testID="call-view-more" + testID="call-view-dialpad" > <Text allowFontScaling={false} @@ -723,7 +725,7 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -743,7 +745,7 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` ] } > - More + Dialpad </Text> </View> </View> @@ -828,7 +830,9 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` source={ [ { - "headers": undefined, + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", }, ] @@ -908,7 +912,7 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` { "busy": undefined, "checked": undefined, - "disabled": false, + "disabled": true, "expanded": undefined, "selected": undefined, } @@ -943,7 +947,9 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` "marginBottom": 8, "width": 64, }, - false, + { + "opacity": 0.5, + }, { "backgroundColor": "#E4E7EA", }, @@ -1406,13 +1412,13 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` </View> <View> <View - accessibilityLabel="More" + accessibilityLabel="Dialpad" accessibilityRole="button" accessibilityState={ { "busy": undefined, "checked": undefined, - "disabled": false, + "disabled": true, "expanded": undefined, "selected": undefined, } @@ -1447,13 +1453,15 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` "marginBottom": 8, "width": 64, }, - false, + { + "opacity": 0.5, + }, { "backgroundColor": "#E4E7EA", }, ] } - testID="call-view-more" + testID="call-view-dialpad" > <Text allowFontScaling={false} @@ -1479,7 +1487,7 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -1499,7 +1507,7 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` ] } > - More + Dialpad </Text> </View> </View> @@ -1584,7 +1592,9 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` source={ [ { - "headers": undefined, + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", }, ] @@ -2158,7 +2168,7 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` </View> <View> <View - accessibilityLabel="More" + accessibilityLabel="Dialpad" accessibilityRole="button" accessibilityState={ { @@ -2205,7 +2215,7 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` }, ] } - testID="call-view-more" + testID="call-view-dialpad" > <Text allowFontScaling={false} @@ -2231,7 +2241,7 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -2251,7 +2261,7 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` ] } > - More + Dialpad </Text> </View> </View> @@ -2336,7 +2346,9 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` source={ [ { - "headers": undefined, + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", }, ] @@ -2910,7 +2922,7 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` </View> <View> <View - accessibilityLabel="More" + accessibilityLabel="Dialpad" accessibilityRole="button" accessibilityState={ { @@ -2957,7 +2969,7 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` }, ] } - testID="call-view-more" + testID="call-view-dialpad" > <Text allowFontScaling={false} @@ -2983,7 +2995,7 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -3003,7 +3015,7 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` ] } > - More + Dialpad </Text> </View> </View> @@ -3088,7 +3100,9 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` source={ [ { - "headers": undefined, + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", }, ] @@ -3662,7 +3676,7 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` </View> <View> <View - accessibilityLabel="More" + accessibilityLabel="Dialpad" accessibilityRole="button" accessibilityState={ { @@ -3709,7 +3723,7 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` }, ] } - testID="call-view-more" + testID="call-view-dialpad" > <Text allowFontScaling={false} @@ -3735,7 +3749,7 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -3755,7 +3769,7 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` ] } > - More + Dialpad </Text> </View> </View> @@ -3840,7 +3854,9 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` source={ [ { - "headers": undefined, + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", }, ] @@ -4414,7 +4430,7 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` </View> <View> <View - accessibilityLabel="More" + accessibilityLabel="Dialpad" accessibilityRole="button" accessibilityState={ { @@ -4461,7 +4477,7 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` }, ] } - testID="call-view-more" + testID="call-view-dialpad" > <Text allowFontScaling={false} @@ -4487,7 +4503,7 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -4507,7 +4523,7 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` ] } > - More + Dialpad </Text> </View> </View> diff --git a/app/views/CallView/components/CallActionButton.tsx b/app/views/CallView/components/CallActionButton.tsx index b67d6ee725d..4be41697d11 100644 --- a/app/views/CallView/components/CallActionButton.tsx +++ b/app/views/CallView/components/CallActionButton.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { Text, View, Pressable } from 'react-native'; +import * as Haptics from 'expo-haptics'; import { CustomIcon, type TIconsName } from '../../../containers/CustomIcon'; import { styles } from '../styles'; @@ -51,10 +52,15 @@ const CallActionButton = ({ return variant === 'danger' ? colors.buttonBackgroundDangerDefault : colors.buttonBackgroundSecondaryDefault; }; + const handlePress = () => { + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); + onPress(); + }; + return ( <View> <Pressable - onPress={onPress} + onPress={handlePress} disabled={disabled} style={({ pressed }) => [ styles.actionButton, diff --git a/app/views/CallView/components/CallButtons.tsx b/app/views/CallView/components/CallButtons.tsx index 5eddb2b786d..bd707f286e7 100644 --- a/app/views/CallView/components/CallButtons.tsx +++ b/app/views/CallView/components/CallButtons.tsx @@ -6,6 +6,8 @@ import { useCallStore } from '../../../lib/services/voip/useCallStore'; import CallActionButton from './CallActionButton'; import { styles } from '../styles'; import { useTheme } from '../../../theme'; +import { showActionSheetRef } from '../../../containers/ActionSheet'; +import Dialpad from './Dialpad/Dialpad'; export const CallButtons = () => { 'use memo'; @@ -30,9 +32,8 @@ export const CallButtons = () => { alert('Message'); }; - const handleMore = () => { - // TODO: Show action sheet with more options (DTMF, transfer, etc.) - alert('More'); + const handleDialpad = () => { + showActionSheetRef({ children: <Dialpad /> }); }; const handleEndCall = () => { @@ -47,6 +48,7 @@ export const CallButtons = () => { label={I18n.t('Speaker')} onPress={toggleSpeaker} variant={isSpeakerOn ? 'active' : 'default'} + disabled={isConnecting} testID='call-view-speaker' /> <CallActionButton @@ -76,7 +78,13 @@ export const CallButtons = () => { variant='danger' testID='call-view-end' /> - <CallActionButton icon='kebab' label={I18n.t('More')} onPress={handleMore} testID='call-view-more' /> + <CallActionButton + icon='dialpad' + label={I18n.t('Dialpad')} + onPress={handleDialpad} + disabled={isConnecting} + testID='call-view-dialpad' + /> </View> </View> ); diff --git a/app/views/CallView/components/Dialpad/Dialpad.stories.tsx b/app/views/CallView/components/Dialpad/Dialpad.stories.tsx new file mode 100644 index 00000000000..5060a0a804e --- /dev/null +++ b/app/views/CallView/components/Dialpad/Dialpad.stories.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; + +import Dialpad from './Dialpad'; +import { useCallStore } from '../../../../lib/services/voip/useCallStore'; + +const styles = StyleSheet.create({ + container: { + padding: 24, + alignItems: 'center', + minHeight: 500 + } +}); + +const Wrapper = ({ children }: { children: React.ReactNode }) => <View style={styles.container}>{children}</View>; + +// Helper to set store state for stories - call with sendDTMF so dialpad buttons work +const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getState>> = {}) => { + const mockCall = { + state: 'active', + muted: false, + held: false, + contact: {}, + sendDTMF: () => {}, + emitter: { on: () => {}, off: () => {} } + } as any; + + useCallStore.setState({ + call: mockCall, + callUUID: 'test-uuid', + callState: 'active', + dialpadValue: '', + ...overrides + }); +}; + +export default { + title: 'Dialpad', + component: Dialpad, + decorators: [ + (Story: React.ComponentType) => { + setStoreState(); + return ( + <Wrapper> + <Story /> + </Wrapper> + ); + } + ] +}; + +export const Default = () => <Dialpad testID='dialpad' />; + +export const WithValue = () => { + setStoreState({ dialpadValue: '123' }); + return <Dialpad testID='dialpad' />; +}; diff --git a/app/views/CallView/components/Dialpad/Dialpad.test.tsx b/app/views/CallView/components/Dialpad/Dialpad.test.tsx new file mode 100644 index 00000000000..557c0b0a464 --- /dev/null +++ b/app/views/CallView/components/Dialpad/Dialpad.test.tsx @@ -0,0 +1,121 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import Dialpad from './Dialpad'; +import { useCallStore } from '../../../../lib/services/voip/useCallStore'; +import { mockedStore } from '../../../../reducers/mockedStore'; +import * as stories from './Dialpad.stories'; +import { generateSnapshots } from '../../../../../.rnstorybook/generateSnapshots'; + +jest.mock('react-native-incall-manager', () => ({ + start: jest.fn(), + stop: jest.fn(), + setForceSpeakerphoneOn: jest.fn(() => Promise.resolve()) +})); + +const sendDTMFMock = jest.fn(); + +// Helper to set store state for tests +const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getState>> = {}) => { + const mockCall = { + state: 'active', + muted: false, + held: false, + contact: {}, + sendDTMF: sendDTMFMock, + emitter: { on: jest.fn(), off: jest.fn() } + } as any; + + useCallStore.setState({ + call: mockCall, + callUUID: 'test-uuid', + callState: 'active', + dialpadValue: '', + ...overrides + }); +}; + +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; + +describe('Dialpad', () => { + beforeEach(() => { + useCallStore.getState().reset(); + sendDTMFMock.mockClear(); + }); + + it('should render correctly', () => { + setStoreState(); + const { getByTestId } = render( + <Wrapper> + <Dialpad testID='dialpad' /> + </Wrapper> + ); + expect(getByTestId('dialpad-input')).toBeTruthy(); + }); + + it('should display the input field', () => { + setStoreState(); + const { getByTestId } = render( + <Wrapper> + <Dialpad testID='dialpad' /> + </Wrapper> + ); + expect(getByTestId('dialpad-input')).toBeTruthy(); + }); + + it('should display dialpad buttons', () => { + setStoreState(); + const { getByText } = render( + <Wrapper> + <Dialpad testID='dialpad' /> + </Wrapper> + ); + expect(getByText('1')).toBeTruthy(); + expect(getByText('2')).toBeTruthy(); + expect(getByText('0')).toBeTruthy(); + expect(getByText('*')).toBeTruthy(); + expect(getByText('#')).toBeTruthy(); + }); + + it('should call sendDTMF and update value when digit is pressed', () => { + setStoreState(); + const { getByText } = render( + <Wrapper> + <Dialpad testID='dialpad' /> + </Wrapper> + ); + + fireEvent.press(getByText('5')); + expect(sendDTMFMock).toHaveBeenCalledWith('5'); + expect(sendDTMFMock).toHaveBeenCalledTimes(1); + + fireEvent.press(getByText('2')); + expect(sendDTMFMock).toHaveBeenCalledWith('2'); + expect(sendDTMFMock).toHaveBeenCalledTimes(2); + }); + + it('should display letters on keys that have them', () => { + setStoreState(); + const { getByText } = render( + <Wrapper> + <Dialpad testID='dialpad' /> + </Wrapper> + ); + expect(getByText('ABC')).toBeTruthy(); + expect(getByText('DEF')).toBeTruthy(); + expect(getByText('WXYZ')).toBeTruthy(); + }); + + it('should render with custom testID', () => { + setStoreState(); + const { getByTestId } = render( + <Wrapper> + <Dialpad testID='custom-dialpad' /> + </Wrapper> + ); + expect(getByTestId('custom-dialpad-input')).toBeTruthy(); + }); +}); + +generateSnapshots(stories); diff --git a/app/views/CallView/components/Dialpad/Dialpad.tsx b/app/views/CallView/components/Dialpad/Dialpad.tsx new file mode 100644 index 00000000000..6b1a9065258 --- /dev/null +++ b/app/views/CallView/components/Dialpad/Dialpad.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { View } from 'react-native'; + +import { useDialpadValue } from '../../../../lib/services/voip/useCallStore'; +import { FormTextInput } from '../../../../containers/TextInput'; +import { useTheme } from '../../../../theme'; +import { styles } from './styles'; +import DialpadButton from './DialpadButton'; + +const DIALPAD_KEYS: { digit: string; letters: string }[][] = [ + [ + { digit: '1', letters: '' }, + { digit: '2', letters: 'ABC' }, + { digit: '3', letters: 'DEF' } + ], + [ + { digit: '4', letters: 'GHI' }, + { digit: '5', letters: 'JKL' }, + { digit: '6', letters: 'MNO' } + ], + [ + { digit: '7', letters: 'PQRS' }, + { digit: '8', letters: 'TUV' }, + { digit: '9', letters: 'WXYZ' } + ], + [ + { digit: '*', letters: '' }, + { digit: '0', letters: '+' }, + { digit: '#', letters: '' } + ] +]; + +interface IDialpad { + testID?: string; +} + +const Dialpad = ({ testID }: IDialpad): React.ReactElement => { + const { colors } = useTheme(); + const dialpadValue = useDialpadValue(); + + return ( + <View style={[styles.container, { backgroundColor: colors.surfaceLight }]}> + <FormTextInput + value={dialpadValue} + placeholder='' + keyboardType='phone-pad' + containerStyle={styles.inputContainer} + showErrorMessage={false} + bottomSheet + testID={testID ? `${testID}-input` : 'dialpad-input'} + editable={false} + multiline + /> + <View style={styles.grid}> + {DIALPAD_KEYS.map((row, rowIndex) => ( + <View key={rowIndex} style={styles.row}> + {row.map(({ digit, letters }) => ( + <DialpadButton key={digit} digit={digit} letters={letters} /> + ))} + </View> + ))} + </View> + </View> + ); +}; + +export default Dialpad; diff --git a/app/views/CallView/components/Dialpad/DialpadButton.tsx b/app/views/CallView/components/Dialpad/DialpadButton.tsx new file mode 100644 index 00000000000..05860e56cae --- /dev/null +++ b/app/views/CallView/components/Dialpad/DialpadButton.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { Pressable, Text, View } from 'react-native'; +import * as Haptics from 'expo-haptics'; + +import { useCallStore } from '../../../../lib/services/voip/useCallStore'; +import { useTheme } from '../../../../theme'; +import { styles } from './styles'; + +interface IDialpadButton { + digit: string; + letters: string; +} + +const DialpadButton = ({ digit, letters }: IDialpadButton): React.ReactElement => { + 'use memo'; + + const { colors } = useTheme(); + const setDialpadValue = useCallStore(state => state.setDialpadValue); + + const handleDigitPress = () => { + setDialpadValue(digit); + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); + }; + + return ( + <Pressable + onPress={handleDigitPress} + style={({ pressed }) => [ + styles.button, + { backgroundColor: pressed ? colors.buttonBackgroundSecondaryPress : colors.buttonBackgroundSecondaryDefault } + ]}> + <View style={styles.digitContainer}> + <Text style={[styles.digit, { color: colors.fontDefault }]}>{digit}</Text> + <Text style={[styles.letters, { color: colors.fontSecondaryInfo }]}>{letters || ''}</Text> + </View> + </Pressable> + ); +}; + +export default DialpadButton; diff --git a/app/views/CallView/components/Dialpad/__snapshots__/Dialpad.test.tsx.snap b/app/views/CallView/components/Dialpad/__snapshots__/Dialpad.test.tsx.snap new file mode 100644 index 00000000000..5b48701b66a --- /dev/null +++ b/app/views/CallView/components/Dialpad/__snapshots__/Dialpad.test.tsx.snap @@ -0,0 +1,2519 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: Default should match snapshot 1`] = ` +<View + style={ + { + "alignItems": "center", + "minHeight": 500, + "padding": 24, + } + } +> + <View + style={ + [ + { + "padding": 32, + "paddingBottom": 32, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <A11yOrderView + orderKey=":r6:" + > + <A11yIndexView + importantForAccessibility="yes" + orderFocusType={0} + orderIndex={1} + orderKey=":r6:" + > + <View + style={ + [ + { + "gap": 4, + "marginBottom": 10, + }, + { + "marginBottom": 24, + }, + ] + } + > + <View + accessible={false} + style={ + { + "justifyContent": "center", + "position": "relative", + } + } + > + <TextInput + accessibilityLabel="" + accessible={true} + autoCapitalize="none" + autoCorrect={false} + editable={false} + keyboardType="phone-pad" + multiline={true} + placeholder="" + placeholderTextColor="#9EA2A8" + style={ + [ + { + "backgroundColor": "transparent", + "borderRadius": 4, + "borderWidth": 1, + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "paddingHorizontal": 16, + "paddingVertical": 14, + "textAlign": "left", + }, + undefined, + {}, + { + "backgroundColor": "#FFFFFF", + "borderColor": "#9EA2A8", + "color": "#1F2329", + }, + {}, + undefined, + ] + } + testID="dialpad-input" + underlineColorAndroid="transparent" + value="" + /> + </View> + </View> + </A11yIndexView> + </A11yOrderView> + <View + style={ + { + "gap": 28, + "padding": 10, + } + } + > + <View + style={ + { + "flexDirection": "row", + "gap": 40, + "justifyContent": "space-between", + } + } + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 1 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + /> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 2 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + ABC + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 3 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + DEF + </Text> + </View> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "gap": 40, + "justifyContent": "space-between", + } + } + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 4 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + GHI + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 5 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + JKL + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 6 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + MNO + </Text> + </View> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "gap": 40, + "justifyContent": "space-between", + } + } + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 7 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + PQRS + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 8 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + TUV + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 9 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + WXYZ + </Text> + </View> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "gap": 40, + "justifyContent": "space-between", + } + } + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + * + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + /> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 0 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + + + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + # + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + /> + </View> + </View> + </View> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: WithValue should match snapshot 1`] = ` +<View + style={ + { + "alignItems": "center", + "minHeight": 500, + "padding": 24, + } + } +> + <View + style={ + [ + { + "padding": 32, + "paddingBottom": 32, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <A11yOrderView + orderKey=":r7:" + > + <A11yIndexView + importantForAccessibility="yes" + orderFocusType={0} + orderIndex={1} + orderKey=":r7:" + > + <View + style={ + [ + { + "gap": 4, + "marginBottom": 10, + }, + { + "marginBottom": 24, + }, + ] + } + > + <View + accessible={false} + style={ + { + "justifyContent": "center", + "position": "relative", + } + } + > + <TextInput + accessibilityLabel="123." + accessible={true} + autoCapitalize="none" + autoCorrect={false} + editable={false} + keyboardType="phone-pad" + multiline={true} + placeholder="" + placeholderTextColor="#9EA2A8" + style={ + [ + { + "backgroundColor": "transparent", + "borderRadius": 4, + "borderWidth": 1, + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "paddingHorizontal": 16, + "paddingVertical": 14, + "textAlign": "left", + }, + undefined, + {}, + { + "backgroundColor": "#FFFFFF", + "borderColor": "#9EA2A8", + "color": "#1F2329", + }, + {}, + undefined, + ] + } + testID="dialpad-input" + underlineColorAndroid="transparent" + value="123" + /> + </View> + </View> + </A11yIndexView> + </A11yOrderView> + <View + style={ + { + "gap": 28, + "padding": 10, + } + } + > + <View + style={ + { + "flexDirection": "row", + "gap": 40, + "justifyContent": "space-between", + } + } + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 1 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + /> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 2 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + ABC + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 3 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + DEF + </Text> + </View> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "gap": 40, + "justifyContent": "space-between", + } + } + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 4 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + GHI + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 5 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + JKL + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 6 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + MNO + </Text> + </View> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "gap": 40, + "justifyContent": "space-between", + } + } + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 7 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + PQRS + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 8 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + TUV + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 9 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + WXYZ + </Text> + </View> + </View> + </View> + <View + style={ + { + "flexDirection": "row", + "gap": 40, + "justifyContent": "space-between", + } + } + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + * + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + /> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + 0 + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + > + + + </Text> + </View> + </View> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "aspectRatio": 1, + "borderRadius": 8, + "flex": 1, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "justifyContent": "center", + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 32, + "fontWeight": "400", + "lineHeight": 36, + "textAlign": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + # + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 12, + "fontWeight": "400", + "letterSpacing": 0, + "lineHeight": 18, + "textAlign": "center", + }, + { + "color": "#6C727A", + }, + ] + } + /> + </View> + </View> + </View> + </View> + </View> +</View> +`; diff --git a/app/views/CallView/components/Dialpad/styles.ts b/app/views/CallView/components/Dialpad/styles.ts new file mode 100644 index 00000000000..314ffd5d0b5 --- /dev/null +++ b/app/views/CallView/components/Dialpad/styles.ts @@ -0,0 +1,45 @@ +import { StyleSheet } from 'react-native'; + +import sharedStyles from '../../../Styles'; + +export const styles = StyleSheet.create({ + container: { + padding: 32, + paddingBottom: 32 + }, + inputContainer: { + marginBottom: 24 + }, + grid: { + padding: 10, + gap: 28 + }, + row: { + flexDirection: 'row', + justifyContent: 'space-between', + gap: 40 + }, + button: { + flex: 1, + aspectRatio: 1, + borderRadius: 8 + }, + digitContainer: { + alignItems: 'center', + justifyContent: 'center', + flex: 1 + }, + digit: { + ...sharedStyles.textRegular, + fontSize: 32, + lineHeight: 36, + textAlign: 'center' + }, + letters: { + ...sharedStyles.textRegular, + fontSize: 12, + lineHeight: 18, + textAlign: 'center', + letterSpacing: 0 + } +}); diff --git a/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap b/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap index 145e5f98944..4803ed73af8 100644 --- a/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap +++ b/app/views/CallView/components/__snapshots__/CallerInfo.test.tsx.snap @@ -65,7 +65,9 @@ exports[`Story Snapshots: Default should match snapshot 1`] = ` source={ [ { - "headers": undefined, + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, "uri": "https://open.rocket.chat/avatar/bob.burnquist?format=png&size=240", }, ] @@ -183,7 +185,9 @@ exports[`Story Snapshots: UsernameOnly should match snapshot 1`] = ` source={ [ { - "headers": undefined, + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, "uri": "https://open.rocket.chat/avatar/john.doe?format=png&size=240", }, ] diff --git a/app/views/CallView/index.test.tsx b/app/views/CallView/index.test.tsx index f4e12d61268..e303ef3741c 100644 --- a/app/views/CallView/index.test.tsx +++ b/app/views/CallView/index.test.tsx @@ -8,12 +8,6 @@ import { mockedStore } from '../../reducers/mockedStore'; import * as stories from './CallView.stories'; import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; -// Mock expo-keep-awake -jest.mock('expo-keep-awake', () => ({ - activateKeepAwakeAsync: jest.fn(() => Promise.resolve()), - deactivateKeepAwake: jest.fn() -})); - // Mock ResponsiveLayoutContext for snapshots jest.mock('../../lib/hooks/useResponsiveLayout/useResponsiveLayout', () => { const React = require('react'); @@ -35,6 +29,12 @@ jest.mock('../../lib/hooks/useResponsiveLayout/useResponsiveLayout', () => { // Mock alert global.alert = jest.fn(); +const mockShowActionSheetRef = jest.fn(); +jest.mock('../../containers/ActionSheet', () => ({ + ...jest.requireActual('../../containers/ActionSheet'), + showActionSheetRef: (options: any) => mockShowActionSheetRef(options) +})); + // Helper to create a mock call const createMockCall = (overrides: any = {}) => ({ state: 'active', @@ -108,7 +108,7 @@ describe('CallView', () => { expect(getByTestId('call-view-mute')).toBeTruthy(); expect(getByTestId('call-view-message')).toBeTruthy(); expect(getByTestId('call-view-end')).toBeTruthy(); - expect(getByTestId('call-view-more')).toBeTruthy(); + expect(getByTestId('call-view-dialpad')).toBeTruthy(); }); it('should show CallStatusText when call is active', () => { @@ -253,7 +253,7 @@ describe('CallView', () => { expect(global.alert).toHaveBeenCalledWith('Message'); }); - it('should show alert when more button is pressed', () => { + it('should show action sheet with dialpad when dialpad button is pressed', () => { setStoreState({ callState: 'active' }); const { getByTestId } = render( <Wrapper> @@ -261,8 +261,12 @@ describe('CallView', () => { </Wrapper> ); - fireEvent.press(getByTestId('call-view-more')); - expect(global.alert).toHaveBeenCalledWith('More'); + fireEvent.press(getByTestId('call-view-dialpad')); + expect(mockShowActionSheetRef).toHaveBeenCalledWith( + expect.objectContaining({ + children: expect.anything() + }) + ); }); it('should show "Cancel" label when call is connecting', () => { @@ -383,31 +387,6 @@ describe('CallView', () => { expect(getByText('Unmute')).toBeTruthy(); }); - - it('should activate keep awake on mount', () => { - const { activateKeepAwakeAsync } = require('expo-keep-awake'); - setStoreState(); - render( - <Wrapper> - <CallView /> - </Wrapper> - ); - - expect(activateKeepAwakeAsync).toHaveBeenCalled(); - }); - - it('should deactivate keep awake on unmount', () => { - const { deactivateKeepAwake } = require('expo-keep-awake'); - setStoreState(); - const { unmount } = render( - <Wrapper> - <CallView /> - </Wrapper> - ); - - unmount(); - expect(deactivateKeepAwake).toHaveBeenCalled(); - }); }); generateSnapshots(stories); diff --git a/app/views/CallView/index.tsx b/app/views/CallView/index.tsx index a6d13848c89..3a8dd191a4c 100644 --- a/app/views/CallView/index.tsx +++ b/app/views/CallView/index.tsx @@ -1,6 +1,5 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import { View } from 'react-native'; -import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake'; import { useCallStore } from '../../lib/services/voip/useCallStore'; import CallerInfo from './components/CallerInfo'; @@ -14,13 +13,6 @@ const CallView = (): React.ReactElement | null => { const { colors } = useTheme(); const call = useCallStore(state => state.call); - useEffect(() => { - activateKeepAwakeAsync(); - return () => { - deactivateKeepAwake(); - }; - }, []); - if (!call) { return null; } diff --git a/jest.setup.js b/jest.setup.js index 774f02d2527..d4cb05917ac 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -38,7 +38,14 @@ jest.mock('react-native-file-viewer', () => ({ open: jest.fn(() => null) })); -jest.mock('expo-haptics', () => jest.fn(() => null)); +jest.mock('expo-haptics', () => ({ + impactAsync: jest.fn(), + ImpactFeedbackStyle: { + Light: 'light', + Medium: 'medium', + Heavy: 'heavy' + } +})); jest.mock('expo-font', () => ({ isLoaded: jest.fn(() => true), @@ -160,7 +167,8 @@ jest.mock('@discord/bottom-sheet', () => { return { __esModule: true, default: react.View, - BottomSheetScrollView: react.ScrollView + BottomSheetScrollView: react.ScrollView, + BottomSheetTextInput: react.TextInput }; }); diff --git a/package.json b/package.json index 7a5f6c31b4f..f263e21bcc3 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@react-navigation/elements": "^2.6.1", "@react-navigation/native": "^7.1.16", "@react-navigation/native-stack": "^7.3.23", - "@rocket.chat/media-signaling": "file:./packages/rocket.chat-media-signaling-0.1.0.tgz", + "@rocket.chat/media-signaling": "file:./packages/rocket.chat-media-signaling-0.1.1.tgz", "@rocket.chat/message-parser": "^0.31.31", "@rocket.chat/mobile-crypto": "RocketChat/rocket.chat-mobile-crypto", "@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#mobile", diff --git a/packages/rocket.chat-media-signaling-0.1.0.tgz b/packages/rocket.chat-media-signaling-0.1.1.tgz similarity index 100% rename from packages/rocket.chat-media-signaling-0.1.0.tgz rename to packages/rocket.chat-media-signaling-0.1.1.tgz diff --git a/yarn.lock b/yarn.lock index f64c8f247ef..47c478e3563 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5004,10 +5004,10 @@ resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.2.1.tgz#9403f51c17cae37edf870c6bc0c81c1ece5ccef8" integrity sha512-1dgmkh+3so0+LlBWRhGA33ua4MYr7tUOj+a9Si28vUi0IUFNbff1T3sgpeDJI/LaC75bBYnQ0A3wXjn0OrRNBA== -"@rocket.chat/emitter@~0.31.25": - version "0.31.25" - resolved "https://registry.yarnpkg.com/@rocket.chat/emitter/-/emitter-0.31.25.tgz#17dd7838dc988ebc5fcd96343c4431d5cef45845" - integrity sha512-hw5BpDlNwpYSb+K5X3DNMNUVEVXxmXugUPetGZGCWvntSVFsOjYuVEypoKW6vBBXSfqCBb0kN1npYcKEb4NFBw== +"@rocket.chat/emitter@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@rocket.chat/emitter/-/emitter-0.32.0.tgz#6fe39474684ad6c97109df160cdd9c18a6beebbc" + integrity sha512-QCXNGDm5xjJPePMeP9GknMAZne5xhNmLLD/ZVVqNgOyeWdfQKddwBUqtMiWDaFCRq1bC22kNf3WQLqt89CO6fg== "@rocket.chat/eslint-config@^0.4.0": version "0.4.0" @@ -5016,11 +5016,11 @@ dependencies: eslint-plugin-import "^2.17.2" -"@rocket.chat/media-signaling@file:./packages/rocket.chat-media-signaling-0.1.0.tgz": - version "0.1.0" - resolved "file:./packages/rocket.chat-media-signaling-0.1.0.tgz#b73f0c2a642b65ecce4df8da2f44b22f93cd75fb" +"@rocket.chat/media-signaling@file:./packages/rocket.chat-media-signaling-0.1.1.tgz": + version "0.1.1" + resolved "file:./packages/rocket.chat-media-signaling-0.1.1.tgz#b9859941d78af41e1fd82d2e0cf53d119aeaac9b" dependencies: - "@rocket.chat/emitter" "~0.31.25" + "@rocket.chat/emitter" "^0.32.0" ajv "^8.17.1" "@rocket.chat/message-parser@^0.31.31": @@ -5992,9 +5992,9 @@ ajv@^8.0.0, ajv@^8.9.0: uri-js "^4.2.2" ajv@^8.17.1: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" - integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + version "8.18.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.18.0.tgz#8864186b6738d003eb3a933172bb3833e10cefbc" + integrity sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A== dependencies: fast-deep-equal "^3.1.3" fast-uri "^3.0.1" From 104471c24defaf5b803ed2b4b26a92c5c3fb0014 Mon Sep 17 00:00:00 2001 From: diegolmello <diegolmello@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:39:57 +0000 Subject: [PATCH 53/61] action: organized translations --- app/i18n/locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index 925cec10b89..6f85cc0a4ca 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -562,8 +562,8 @@ "Move_to_Team_Warning": "After reading the previous instructions about this behavior, do you still want to move this channel to the selected team?", "moving_channel_to_team": "moving channel to team", "Mute": "Mute", - "Muted": "Muted", "Mute_someone_in_room": "Mute someone in the room", + "Muted": "Muted", "muted": "muted", "N_channels": "{{n}} channels", "N_people_reacted": "{{n}} people reacted", From 10a8b196ed8edc83060a6a49ee622147bd577a9b Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 3 Mar 2026 13:54:49 -0300 Subject: [PATCH 54/61] feat: start call (#7024) --- .../MediaCallHeader.test.tsx.snap | 58 +- .../MediaCallHeader/components/Subtitle.tsx | 6 +- .../MediaCallHeader/components/Title.tsx | 2 +- .../__snapshots__/SearchBox.test.tsx.snap | 3 +- app/containers/SearchBox/index.tsx | 4 +- app/i18n/locales/en.json | 3 +- app/lib/hooks/useMediaCallPermission/index.ts | 1 + .../useMediaCallPermission.test.ts | 69 + .../useMediaCallPermission.ts | 12 + app/lib/services/voip/MediaSessionInstance.ts | 21 +- app/lib/services/voip/MediaSessionStore.ts | 3 +- app/lib/services/voip/useCallStore.ts | 8 +- app/views/NewMessageView/ButtonCreate.tsx | 1 + app/views/NewMessageView/HeaderNewMessage.tsx | 63 +- app/views/NewMessageView/Item.stories.tsx | 72 + app/views/NewMessageView/Item.test.tsx | 182 ++ app/views/NewMessageView/Item.tsx | 92 + .../__snapshots__/Item.test.tsx.snap | 628 ++++++ app/views/NewMessageView/index.tsx | 9 +- .../components/CallSection.tsx | 71 +- app/views/RoomActionsView/index.tsx | 2 +- .../components/RoomInfoABAC.stories.tsx | 2 +- .../components/RoomInfoButtons.stories.tsx | 181 ++ .../components/RoomInfoButtons.test.tsx | 172 ++ .../components/RoomInfoButtons.tsx | 128 +- .../RoomInfoButtons.test.tsx.snap | 1760 +++++++++++++++++ app/views/RoomView/RightButtons.tsx | 1 + .../RoomView/components/HeaderCallButton.tsx | 68 +- app/views/RoomsListView/hooks/useHeader.tsx | 2 +- 29 files changed, 3467 insertions(+), 157 deletions(-) create mode 100644 app/lib/hooks/useMediaCallPermission/index.ts create mode 100644 app/lib/hooks/useMediaCallPermission/useMediaCallPermission.test.ts create mode 100644 app/lib/hooks/useMediaCallPermission/useMediaCallPermission.ts create mode 100644 app/views/NewMessageView/Item.stories.tsx create mode 100644 app/views/NewMessageView/Item.test.tsx create mode 100644 app/views/NewMessageView/Item.tsx create mode 100644 app/views/NewMessageView/__snapshots__/Item.test.tsx.snap create mode 100644 app/views/RoomInfoView/components/RoomInfoButtons.stories.tsx create mode 100644 app/views/RoomInfoView/components/RoomInfoButtons.test.tsx create mode 100644 app/views/RoomInfoView/components/__snapshots__/RoomInfoButtons.test.tsx.snap diff --git a/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap index 12728940a37..77beb9effca 100644 --- a/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap +++ b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap @@ -181,17 +181,17 @@ exports[`Story Snapshots: ActiveCall should match snapshot 1`] = ` [ { "color": "#6C727A", - "fontSize": 12, + "fontSize": 16, }, [ { - "lineHeight": 12, + "lineHeight": 16, }, [ { - "height": 12, + "height": 16, "textAlignVertical": "center", - "width": 12, + "width": 16, }, undefined, ], @@ -228,7 +228,7 @@ exports[`Story Snapshots: ActiveCall should match snapshot 1`] = ` Bob Burnquist <Text> - - 16254:59:32 + 16448:41:15 </Text> </Text> </View> @@ -527,17 +527,17 @@ exports[`Story Snapshots: Collapsed should match snapshot 1`] = ` [ { "color": "#6C727A", - "fontSize": 12, + "fontSize": 16, }, [ { - "lineHeight": 12, + "lineHeight": 16, }, [ { - "height": 12, + "height": 16, "textAlignVertical": "center", - "width": 12, + "width": 16, }, undefined, ], @@ -574,7 +574,7 @@ exports[`Story Snapshots: Collapsed should match snapshot 1`] = ` Bob Burnquist <Text> - - 16254:59:32 + 16448:41:15 </Text> </Text> </View> @@ -873,17 +873,17 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` [ { "color": "#6C727A", - "fontSize": 12, + "fontSize": 16, }, [ { - "lineHeight": 12, + "lineHeight": 16, }, [ { - "height": 12, + "height": 16, "textAlignVertical": "center", - "width": 12, + "width": 16, }, undefined, ], @@ -1215,17 +1215,17 @@ exports[`Story Snapshots: Focused should match snapshot 1`] = ` [ { "color": "#6C727A", - "fontSize": 12, + "fontSize": 16, }, [ { - "lineHeight": 12, + "lineHeight": 16, }, [ { - "height": 12, + "height": 16, "textAlignVertical": "center", - "width": 12, + "width": 16, }, undefined, ], @@ -1262,7 +1262,7 @@ exports[`Story Snapshots: Focused should match snapshot 1`] = ` Bob Burnquist <Text> - - 16254:59:32 + 16448:41:15 </Text> </Text> </View> @@ -1581,17 +1581,17 @@ exports[`Story Snapshots: WithRemoteHeld should match snapshot 1`] = ` [ { "color": "#6C727A", - "fontSize": 12, + "fontSize": 16, }, [ { - "lineHeight": 12, + "lineHeight": 16, }, [ { - "height": 12, + "height": 16, "textAlignVertical": "center", - "width": 12, + "width": 16, }, undefined, ], @@ -1628,7 +1628,7 @@ exports[`Story Snapshots: WithRemoteHeld should match snapshot 1`] = ` Bob Burnquist <Text> - - 16254:59:32 + 16448:41:15 </Text> </Text> </View> @@ -1927,17 +1927,17 @@ exports[`Story Snapshots: WithRemoteMuted should match snapshot 1`] = ` [ { "color": "#6C727A", - "fontSize": 12, + "fontSize": 16, }, [ { - "lineHeight": 12, + "lineHeight": 16, }, [ { - "height": 12, + "height": 16, "textAlignVertical": "center", - "width": 12, + "width": 16, }, undefined, ], @@ -1974,7 +1974,7 @@ exports[`Story Snapshots: WithRemoteMuted should match snapshot 1`] = ` Bob Burnquist <Text> - - 16254:59:32 + 16448:41:15 </Text> </Text> </View> diff --git a/app/containers/MediaCallHeader/components/Subtitle.tsx b/app/containers/MediaCallHeader/components/Subtitle.tsx index 41c11486d3e..f3a1cd438b3 100644 --- a/app/containers/MediaCallHeader/components/Subtitle.tsx +++ b/app/containers/MediaCallHeader/components/Subtitle.tsx @@ -22,11 +22,11 @@ const Subtitle = () => { const remoteHeld = useCallStore(state => state.remoteHeld); const remoteMute = useCallStore(state => state.remoteMute); const callState = useCallStore(state => state.callState); - const isConnected = callState === 'active'; let subtitle = ''; - - if (!isConnected) { + if (callState === 'ringing') { + subtitle = I18n.t('Calling'); + } else if (callState !== 'active') { subtitle = I18n.t('Connecting'); } else { subtitle = extension ? `${extension}` : ''; diff --git a/app/containers/MediaCallHeader/components/Title.tsx b/app/containers/MediaCallHeader/components/Title.tsx index 216c466e4f6..60df2de936e 100644 --- a/app/containers/MediaCallHeader/components/Title.tsx +++ b/app/containers/MediaCallHeader/components/Title.tsx @@ -32,7 +32,7 @@ const Title = () => { return ( <View style={styles.headerTitleContainer} testID='call-view-header-title'> - <Status id={contact.id || ''} size={12} /> + <Status id={contact.id || ''} size={16} /> <Text style={[styles.headerTitleText, { color: colors.fontDefault }]} numberOfLines={1}> {caller} {isConnected && callStartTime ? <Timer /> : null} diff --git a/app/containers/SearchBox/__snapshots__/SearchBox.test.tsx.snap b/app/containers/SearchBox/__snapshots__/SearchBox.test.tsx.snap index 351aaeaae51..bc494d6df7f 100644 --- a/app/containers/SearchBox/__snapshots__/SearchBox.test.tsx.snap +++ b/app/containers/SearchBox/__snapshots__/SearchBox.test.tsx.snap @@ -26,8 +26,9 @@ exports[`Story Snapshots: Basic should match snapshot 1`] = ` "marginBottom": 10, }, { - "margin": 16, "marginBottom": 16, + "marginHorizontal": 12, + "marginTop": 16, }, ] } diff --git a/app/containers/SearchBox/index.tsx b/app/containers/SearchBox/index.tsx index 75ee7e2c6d2..9ba3439b411 100644 --- a/app/containers/SearchBox/index.tsx +++ b/app/containers/SearchBox/index.tsx @@ -7,7 +7,9 @@ import { FormTextInput } from '../TextInput'; const styles = StyleSheet.create({ inputContainer: { - margin: 16, + marginHorizontal: 12, + marginTop: 16, + // override the default margin bottom of the FormTextInput marginBottom: 16 } }); diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index 6f85cc0a4ca..34fdb91f4e3 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -114,7 +114,7 @@ "Call_started": "Call started", "Call_was_canceled_before_being_answered": "Call was canceled before being answered", "Call_was_not_answered": "Call was not answered", - "Calling": "Calling", + "Calling": "Calling...", "Cancel": "Cancel", "Cancel_and_delete_recording": "Cancel and delete recording", "Cancel_editing": "Cancel editing", @@ -976,6 +976,7 @@ "Version_no": "App version: {{version}}", "Vibrate": "Vibrate", "Video": "Video", + "Video_call": "Video call", "video-conf-provider-not-configured-body": "A workspace admin needs to enable the conference calls feature first.", "video-conf-provider-not-configured-header": "Conference call not enabled", "View_Original": "View original", diff --git a/app/lib/hooks/useMediaCallPermission/index.ts b/app/lib/hooks/useMediaCallPermission/index.ts new file mode 100644 index 00000000000..90eca86bb18 --- /dev/null +++ b/app/lib/hooks/useMediaCallPermission/index.ts @@ -0,0 +1 @@ +export * from './useMediaCallPermission'; diff --git a/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.test.ts b/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.test.ts new file mode 100644 index 00000000000..1999711152a --- /dev/null +++ b/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.test.ts @@ -0,0 +1,69 @@ +import { renderHook } from '@testing-library/react-native'; + +import { useMediaCallPermission } from './useMediaCallPermission'; + +const mockUseAppSelector = jest.fn(); +const mockUsePermissions = jest.fn(); + +jest.mock('../useAppSelector', () => ({ + useAppSelector: (selector: (state: any) => any) => mockUseAppSelector(selector) +})); + +jest.mock('../usePermissions', () => ({ + usePermissions: (permissions: string[]) => mockUsePermissions(permissions) +})); + +describe('useMediaCallPermission', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return false when teams-voip is not in enterpriseModules', () => { + mockUseAppSelector.mockReturnValue([]); + mockUsePermissions.mockReturnValue([true, true]); + + const { result } = renderHook(() => useMediaCallPermission()); + + expect(result.current).toBe(false); + expect(mockUsePermissions).toHaveBeenCalledWith([ + 'allow-internal-voice-calls', + 'allow-external-voice-calls' + ]); + }); + + it('should return false when voip module exists but no voice call permissions', () => { + mockUseAppSelector.mockReturnValue(['teams-voip']); + mockUsePermissions.mockReturnValue([false, false]); + + const { result } = renderHook(() => useMediaCallPermission()); + + expect(result.current).toBe(false); + }); + + it('should return true when voip module exists and internal voice call allowed', () => { + mockUseAppSelector.mockReturnValue(['teams-voip']); + mockUsePermissions.mockReturnValue([true, false]); + + const { result } = renderHook(() => useMediaCallPermission()); + + expect(result.current).toBe(true); + }); + + it('should return true when voip module exists and external voice call allowed', () => { + mockUseAppSelector.mockReturnValue(['teams-voip']); + mockUsePermissions.mockReturnValue([false, true]); + + const { result } = renderHook(() => useMediaCallPermission()); + + expect(result.current).toBe(true); + }); + + it('should return true when voip module exists and both permissions allowed', () => { + mockUseAppSelector.mockReturnValue(['teams-voip']); + mockUsePermissions.mockReturnValue([true, true]); + + const { result } = renderHook(() => useMediaCallPermission()); + + expect(result.current).toBe(true); + }); +}); diff --git a/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.ts b/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.ts new file mode 100644 index 00000000000..15e039bcf9f --- /dev/null +++ b/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.ts @@ -0,0 +1,12 @@ +import { useAppSelector } from '../useAppSelector'; +import { usePermissions } from '../usePermissions'; + +export const useMediaCallPermission = () => { + const enterpriseModules = useAppSelector(state => state.enterpriseModules); + const isVoipModuleAvailable = enterpriseModules.includes('teams-voip'); + const [allowInternalVoiceCall, allowExternalVoiceCall] = usePermissions([ + 'allow-internal-voice-calls', + 'allow-external-voice-calls' + ]); + return isVoipModuleAvailable && (allowInternalVoiceCall || allowExternalVoiceCall); +}; diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 16d08e696a3..7b01092196b 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -2,6 +2,7 @@ import { MediaCallWebRTCProcessor, type ClientMediaSignal, type IClientMediaCall, + type CallActorType, type MediaSignalingSession, type WebRTCProcessorConfig } from '@rocket.chat/media-signaling'; @@ -17,6 +18,8 @@ import { parseStringToIceServers } from './parseStringToIceServers'; import CallIdUUIDModule from '../../native/NativeCallIdUUID'; import type { IceServer } from '../../../definitions/Voip'; import type { IDDPMessage } from '../../../definitions/IDDPMessage'; +import type { ISubscription, TSubscriptionModel } from '../../../definitions'; +import { getUidDirectMessage } from '../../methods/helpers/helpers'; class MediaSessionInstance { private iceServers: IceServer[] = []; @@ -75,8 +78,10 @@ class MediaSessionInstance { const callUUID = CallIdUUIDModule.toUUID(call.callId); console.log('[VoIP] New call UUID:', callUUID); - // const displayName = call.contact.displayName || call.contact.username || 'Unknown'; - // RNCallKeep.displayIncomingCall(callUUID, displayName, displayName, 'generic', false); + if (call.role === 'caller') { + useCallStore.getState().setCall(call, callUUID); + Navigation.navigate('CallView', { callUUID }); + } call.emitter.on('ended', () => { RNCallKeep.endCall(callUUID); @@ -103,6 +108,18 @@ class MediaSessionInstance { } }; + public startCallByRoom = (room: TSubscriptionModel | ISubscription) => { + const otherUserId = getUidDirectMessage(room); + if (otherUserId) { + this.startCall(otherUserId, 'user'); + } + }; + + public startCall = (userId: string, actor: CallActorType) => { + console.log('[VoIP] Starting call:', userId); + this.instance?.startCall(actor, userId); + }; + public endCall = (callUUID: string) => { const mainCall = this.instance?.getMainCall(); // Compare using deterministic UUID conversion diff --git a/app/lib/services/voip/MediaSessionStore.ts b/app/lib/services/voip/MediaSessionStore.ts index 8fabe247350..dfb4719176a 100644 --- a/app/lib/services/voip/MediaSessionStore.ts +++ b/app/lib/services/voip/MediaSessionStore.ts @@ -60,7 +60,8 @@ class MediaSessionStore extends Emitter<{ change: void }> { }, mediaStreamFactory: (constraints: any) => mediaDevices.getUserMedia(constraints) as unknown as Promise<MediaStream>, randomStringFactory, - logger: new MediaCallLogger() + logger: new MediaCallLogger(), + features: ['audio'] }); this.change(); diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index e9c9c9cff98..56bb1c19717 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -173,14 +173,10 @@ export const useCallStore = create<CallStore>((set, get) => ({ }, endCall: () => { - const { call, callState, callUUID } = get(); + const { call, callUUID } = get(); if (call) { - if (callState === 'ringing') { - call.reject(); - } else { - call.hangup(); - } + call.hangup(); } if (callUUID) { diff --git a/app/views/NewMessageView/ButtonCreate.tsx b/app/views/NewMessageView/ButtonCreate.tsx index df612e04959..c6ca5d9fdb7 100644 --- a/app/views/NewMessageView/ButtonCreate.tsx +++ b/app/views/NewMessageView/ButtonCreate.tsx @@ -23,6 +23,7 @@ const ButtonCreate = ({ onPress, testID, title, icon }: IButton) => { left={() => <CustomIcon name={icon} size={24} color={themes[theme].fontDefault} />} right={() => <CustomIcon name={'chevron-right'} size={24} color={themes[theme].fontDefault} />} title={title} + backgroundColor={themes[theme].surfaceLight} /> <List.Separator /> </> diff --git a/app/views/NewMessageView/HeaderNewMessage.tsx b/app/views/NewMessageView/HeaderNewMessage.tsx index 10d29d11bd6..a8de6524457 100644 --- a/app/views/NewMessageView/HeaderNewMessage.tsx +++ b/app/views/NewMessageView/HeaderNewMessage.tsx @@ -20,9 +20,6 @@ import ButtonCreate from './ButtonCreate'; const styles = StyleSheet.create({ container: { paddingTop: 16 - }, - buttonContainer: { - paddingBottom: 16 } }); @@ -73,38 +70,36 @@ const HeaderNewMessage = ({ maxUsers, onChangeText }: { maxUsers: number; onChan return ( <> - <View style={[styles.container, { backgroundColor: themes[theme].surfaceHover }]}> - <View style={styles.buttonContainer}> - {createPublicChannelPermission || createPrivateChannelPermission ? ( - <ButtonCreate - onPress={createChannel} - title={'Channel'} - icon={'channel-public'} - testID={'new-message-view-create-channel'} - /> - ) : null} - {compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '3.13.0') && createTeamPermission ? ( - <ButtonCreate onPress={createTeam} title={'Team'} icon={'teams'} testID={'new-message-view-create-team'} /> - ) : null} - {maxUsers > 2 && createDirectMessagePermission ? ( - <ButtonCreate - onPress={createGroupChat} - title={'Direct_message'} - icon={'message'} - testID={'new-message-view-create-direct-message'} - /> - ) : null} - {createDiscussionPermission ? ( - <ButtonCreate - onPress={createDiscussion} - title={'Discussion'} - icon={'discussions'} - testID={'new-message-view-create-discussion'} - /> - ) : null} - </View> + <View style={[styles.container, { backgroundColor: themes[theme].surfaceTint }]}> + {createPublicChannelPermission || createPrivateChannelPermission ? ( + <ButtonCreate + onPress={createChannel} + title={'Channel'} + icon={'channel-public'} + testID={'new-message-view-create-channel'} + /> + ) : null} + {compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '3.13.0') && createTeamPermission ? ( + <ButtonCreate onPress={createTeam} title={'Team'} icon={'teams'} testID={'new-message-view-create-team'} /> + ) : null} + {maxUsers > 2 && createDirectMessagePermission ? ( + <ButtonCreate + onPress={createGroupChat} + title={'Direct_message'} + icon={'message'} + testID={'new-message-view-create-direct-message'} + /> + ) : null} + {createDiscussionPermission ? ( + <ButtonCreate + onPress={createDiscussion} + title={'Discussion'} + icon={'discussions'} + testID={'new-message-view-create-discussion'} + /> + ) : null} + <SearchBox onChangeText={(text: string) => onChangeText(text)} testID='new-message-view-search' /> </View> - <SearchBox onChangeText={(text: string) => onChangeText(text)} testID='new-message-view-search' /> </> ); }; diff --git a/app/views/NewMessageView/Item.stories.tsx b/app/views/NewMessageView/Item.stories.tsx new file mode 100644 index 00000000000..3a5eebe850d --- /dev/null +++ b/app/views/NewMessageView/Item.stories.tsx @@ -0,0 +1,72 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; + +import Item from './Item'; +import { mockedStore } from '../../reducers/mockedStore'; +import { setUser } from '../../actions/login'; +import { setPermissions } from '../../actions/permissions'; +import { setEnterpriseModules } from '../../actions/enterpriseModules'; + +const styles = StyleSheet.create({ + container: { + padding: 24, + flex: 1, + minHeight: 100 + } +}); + +const Wrapper = ({ children }: { children: React.ReactNode }) => <View style={styles.container}>{children}</View>; + +const withVoiceCallEnabled = (Story: React.ComponentType) => { + mockedStore.dispatch(setEnterpriseModules(['teams-voip'])); + mockedStore.dispatch(setPermissions({ 'allow-internal-voice-calls': ['user'], 'allow-external-voice-calls': ['user'] })); + mockedStore.dispatch(setUser({ roles: ['user'] })); + return <Story />; +}; + +const withVoiceCallDisabled = (Story: React.ComponentType) => { + mockedStore.dispatch(setEnterpriseModules([])); + mockedStore.dispatch(setPermissions({ 'allow-internal-voice-calls': [], 'allow-external-voice-calls': [] })); + mockedStore.dispatch(setUser({ roles: ['user'] })); + return <Story />; +}; + +export default { + title: 'NewMessageView/Item', + component: Item, + decorators: [withVoiceCallEnabled] +}; + +export const Default = () => ( + <Wrapper> + <Item + userId='user123' + name='John Doe' + username='john.doe' + onPress={() => {}} + onLongPress={() => {}} + testID='new-message-view-item-john.doe' + /> + </Wrapper> +); + +export const LongName = () => ( + <Wrapper> + <Item + userId='user123' + name='Very Long Display Name That Might Get Truncated' + username='long.name' + onPress={() => {}} + testID='new-message-view-item-long.name' + /> + </Wrapper> +); + +export const NoVoiceCallPermission = { + render: () => ( + <Wrapper> + <Item userId='user123' name='John Doe' username='john.doe' onPress={() => {}} testID='new-message-view-item-john.doe' /> + </Wrapper> + ), + decorators: [withVoiceCallDisabled] +}; diff --git a/app/views/NewMessageView/Item.test.tsx b/app/views/NewMessageView/Item.test.tsx new file mode 100644 index 00000000000..80af27bf1b2 --- /dev/null +++ b/app/views/NewMessageView/Item.test.tsx @@ -0,0 +1,182 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import Item from './Item'; +import { mockedStore } from '../../reducers/mockedStore'; +import { setUser } from '../../actions/login'; +import * as stories from './Item.stories'; +import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; + +const mockStartCall = jest.fn(); + +jest.mock('../../lib/services/voip/MediaSessionInstance', () => ({ + mediaSessionInstance: { + startCall: (userId: string, actor: string) => mockStartCall(userId, actor) + } +})); + +const mockUseMediaCallPermission = jest.fn(() => true); + +jest.mock('../../lib/hooks/useMediaCallPermission', () => ({ + useMediaCallPermission: () => mockUseMediaCallPermission() +})); + +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; + +describe('NewMessageView Item', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockedStore.dispatch(setUser({ id: 'abc', username: 'rocket.cat', name: 'Rocket Cat' })); + mockUseMediaCallPermission.mockReturnValue(true); + }); + + it('should render correctly', () => { + const { getByTestId } = render( + <Wrapper> + <Item + userId='user123' + name='John Doe' + username='john.doe' + onPress={() => {}} + testID='new-message-view-item-john.doe' + /> + </Wrapper> + ); + expect(getByTestId('new-message-view-item-john.doe')).toBeTruthy(); + }); + + it('should display the name', () => { + const { getByText } = render( + <Wrapper> + <Item + userId='user123' + name='John Doe' + username='john.doe' + onPress={() => {}} + testID='new-message-view-item-john.doe' + /> + </Wrapper> + ); + expect(getByText('John Doe')).toBeTruthy(); + }); + + it('should call onPress when main item is pressed', () => { + const onPressMock = jest.fn(); + const { getByTestId } = render( + <Wrapper> + <Item + userId='user123' + name='John Doe' + username='john.doe' + onPress={onPressMock} + testID='new-message-view-item-john.doe' + /> + </Wrapper> + ); + fireEvent.press(getByTestId('new-message-view-item-john.doe')); + expect(onPressMock).toHaveBeenCalledTimes(1); + }); + + it('should call onLongPress when main item is long pressed', () => { + const onLongPressMock = jest.fn(); + const { getByTestId } = render( + <Wrapper> + <Item + userId='user123' + name='John Doe' + username='john.doe' + onPress={() => {}} + onLongPress={onLongPressMock} + testID='new-message-view-item-john.doe' + /> + </Wrapper> + ); + fireEvent(getByTestId('new-message-view-item-john.doe'), 'longPress'); + expect(onLongPressMock).toHaveBeenCalledTimes(1); + }); + + it('should render call button and call startCall when hasMediaCallPermission is true', () => { + mockUseMediaCallPermission.mockReturnValue(true); + const { getByTestId } = render( + <Wrapper> + <Item + userId='user123' + name='John Doe' + username='john.doe' + onPress={() => {}} + testID='new-message-view-item-john.doe' + /> + </Wrapper> + ); + fireEvent.press(getByTestId('new-message-view-item-john.doe-call')); + expect(mockStartCall).toHaveBeenCalledTimes(1); + expect(mockStartCall).toHaveBeenCalledWith('user123', 'user'); + }); + + it('should not render call button when hasMediaCallPermission is false', () => { + mockUseMediaCallPermission.mockReturnValue(false); + const { queryByTestId } = render( + <Wrapper> + <Item + userId='user123' + name='John Doe' + username='john.doe' + onPress={() => {}} + testID='new-message-view-item-john.doe' + /> + </Wrapper> + ); + expect(queryByTestId('new-message-view-item-john.doe-call')).toBeNull(); + }); + + it('should not call startCall when userId is falsy and call button is pressed', () => { + mockUseMediaCallPermission.mockReturnValue(true); + const { getByTestId } = render( + <Wrapper> + <Item + userId={''} + name='John Doe' + username='john.doe' + onPress={() => {}} + testID='new-message-view-item-john.doe' + /> + </Wrapper> + ); + fireEvent.press(getByTestId('new-message-view-item-john.doe-call')); + expect(mockStartCall).not.toHaveBeenCalled(); + }); + + it('should have correct accessibility label', () => { + const { getByLabelText } = render( + <Wrapper> + <Item + userId='user123' + name='John Doe' + username='john.doe' + onPress={() => {}} + testID='new-message-view-item-john.doe' + /> + </Wrapper> + ); + expect(getByLabelText('John Doe')).toBeTruthy(); + }); + + it('should match snapshot when hasMediaCallPermission is false', () => { + mockUseMediaCallPermission.mockReturnValue(false); + const { toJSON } = render( + <Wrapper> + <Item + userId='user123' + name='John Doe' + username='john.doe' + onPress={() => {}} + testID='new-message-view-item-john.doe' + /> + </Wrapper> + ); + expect(toJSON()).toMatchSnapshot(); + }); +}); + +generateSnapshots(stories); diff --git a/app/views/NewMessageView/Item.tsx b/app/views/NewMessageView/Item.tsx new file mode 100644 index 00000000000..0228b22b7d0 --- /dev/null +++ b/app/views/NewMessageView/Item.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; +import { BorderlessButton, RectButton } from 'react-native-gesture-handler'; + +import Avatar from '../../containers/Avatar'; +import { CustomIcon } from '../../containers/CustomIcon'; +import sharedStyles from '../Styles'; +import { useTheme } from '../../theme'; +import { mediaSessionInstance } from '../../lib/services/voip/MediaSessionInstance'; +import I18n from '../../i18n'; +import { useMediaCallPermission } from '../../lib/hooks/useMediaCallPermission'; + +const styles = StyleSheet.create({ + button: { + height: 54 + }, + container: { + flexDirection: 'row' + }, + avatar: { + marginHorizontal: 12, + marginVertical: 12 + }, + textContainer: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + marginRight: 12 + }, + name: { + fontSize: 18, + lineHeight: 26, + ...sharedStyles.textMedium + }, + iconContainer: { + paddingHorizontal: 15, + alignSelf: 'center' + } +}); + +interface IItem { + userId: string; + name: string; + username: string; + onPress(): void; + testID: string; + onLongPress?: () => void; +} + +const Item = ({ userId, name, username, onPress, testID, onLongPress }: IItem) => { + const { colors } = useTheme(); + const hasMediaCallPermission = useMediaCallPermission(); + + const handleCallPress = () => { + if (!userId) return; + mediaSessionInstance.startCall(userId, 'user'); + }; + + return ( + <RectButton + onPress={onPress} + onLongPress={onLongPress} + testID={testID} + underlayColor={colors.surfaceSelected} + rippleColor={colors.surfaceSelected} + style={{ backgroundColor: colors.surfaceLight }} + accessibilityLabel={name} + accessibilityRole='button'> + <View style={[styles.container, styles.button]}> + <Avatar text={username} size={30} style={styles.avatar} /> + <View style={styles.textContainer}> + <Text style={[styles.name, { color: colors.fontDefault }]} numberOfLines={1}> + {name} + </Text> + </View> + {hasMediaCallPermission ? ( + <BorderlessButton + onPress={handleCallPress} + testID={`${testID}-call`} + rippleColor={colors.surfaceSelected} + style={styles.iconContainer} + accessibilityLabel={I18n.t('Voice_call')} + accessibilityRole='button'> + <CustomIcon name={'phone'} size={22} color={colors.fontDefault} /> + </BorderlessButton> + ) : null} + </View> + </RectButton> + ); +}; + +export default Item; diff --git a/app/views/NewMessageView/__snapshots__/Item.test.tsx.snap b/app/views/NewMessageView/__snapshots__/Item.test.tsx.snap new file mode 100644 index 00000000000..276eb5a1ec4 --- /dev/null +++ b/app/views/NewMessageView/__snapshots__/Item.test.tsx.snap @@ -0,0 +1,628 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`NewMessageView Item should match snapshot when hasMediaCallPermission is false 1`] = ` +<RNGestureHandlerButton + accessibilityLabel="John Doe" + accessibilityRole="button" + activeOpacity={0.105} + collapsable={false} + delayLongPress={600} + handlerTag={16} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + rippleColor="#D7DBE0" + style={ + [ + { + "backgroundColor": "#FFFFFF", + }, + { + "cursor": undefined, + }, + ] + } + testID="new-message-view-item-john.doe" + underlayColor="#D7DBE0" +> + <View + collapsable={false} + style={ + { + "backgroundColor": "#D7DBE0", + "borderBottomLeftRadius": undefined, + "borderBottomRightRadius": undefined, + "borderRadius": undefined, + "borderTopLeftRadius": undefined, + "borderTopRightRadius": undefined, + "bottom": 0, + "left": 0, + "opacity": 0, + "position": "absolute", + "right": 0, + "top": 0, + } + } + /> + <View + style={ + [ + { + "flexDirection": "row", + }, + { + "height": 54, + }, + ] + } + > + <View + accessibilityLabel="john.doe's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 30, + "width": 30, + }, + { + "marginHorizontal": 12, + "marginVertical": 12, + }, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={30} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/john.doe?format=png&size=60", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 30, + "width": 30, + } + } + transition={null} + width={30} + /> + </View> + <View + style={ + { + "flex": 1, + "flexDirection": "column", + "justifyContent": "center", + "marginRight": 12, + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + John Doe + </Text> + </View> + </View> +</RNGestureHandlerButton> +`; + +exports[`Story Snapshots: Default should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "minHeight": 100, + "padding": 24, + } + } +> + <RNGestureHandlerButton + accessibilityLabel="John Doe" + accessibilityRole="button" + activeOpacity={0.105} + collapsable={false} + delayLongPress={600} + handlerTag={17} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onLongPress={[Function]} + onPress={[Function]} + rippleColor="#D7DBE0" + style={ + [ + { + "backgroundColor": "#FFFFFF", + }, + { + "cursor": undefined, + }, + ] + } + testID="new-message-view-item-john.doe" + underlayColor="#D7DBE0" + > + <View + collapsable={false} + style={ + { + "backgroundColor": "#D7DBE0", + "borderBottomLeftRadius": undefined, + "borderBottomRightRadius": undefined, + "borderRadius": undefined, + "borderTopLeftRadius": undefined, + "borderTopRightRadius": undefined, + "bottom": 0, + "left": 0, + "opacity": 0, + "position": "absolute", + "right": 0, + "top": 0, + } + } + /> + <View + style={ + [ + { + "flexDirection": "row", + }, + { + "height": 54, + }, + ] + } + > + <View + accessibilityLabel="john.doe's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 30, + "width": 30, + }, + { + "marginHorizontal": 12, + "marginVertical": 12, + }, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={30} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/john.doe?format=png&size=60", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 30, + "width": 30, + } + } + transition={null} + width={30} + /> + </View> + <View + style={ + { + "flex": 1, + "flexDirection": "column", + "justifyContent": "center", + "marginRight": 12, + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + John Doe + </Text> + </View> + </View> + </RNGestureHandlerButton> +</View> +`; + +exports[`Story Snapshots: LongName should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "minHeight": 100, + "padding": 24, + } + } +> + <RNGestureHandlerButton + accessibilityLabel="Very Long Display Name That Might Get Truncated" + accessibilityRole="button" + activeOpacity={0.105} + collapsable={false} + delayLongPress={600} + handlerTag={18} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + rippleColor="#D7DBE0" + style={ + [ + { + "backgroundColor": "#FFFFFF", + }, + { + "cursor": undefined, + }, + ] + } + testID="new-message-view-item-long.name" + underlayColor="#D7DBE0" + > + <View + collapsable={false} + style={ + { + "backgroundColor": "#D7DBE0", + "borderBottomLeftRadius": undefined, + "borderBottomRightRadius": undefined, + "borderRadius": undefined, + "borderTopLeftRadius": undefined, + "borderTopRightRadius": undefined, + "bottom": 0, + "left": 0, + "opacity": 0, + "position": "absolute", + "right": 0, + "top": 0, + } + } + /> + <View + style={ + [ + { + "flexDirection": "row", + }, + { + "height": 54, + }, + ] + } + > + <View + accessibilityLabel="long.name's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 30, + "width": 30, + }, + { + "marginHorizontal": 12, + "marginVertical": 12, + }, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={30} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/long.name?format=png&size=60", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 30, + "width": 30, + } + } + transition={null} + width={30} + /> + </View> + <View + style={ + { + "flex": 1, + "flexDirection": "column", + "justifyContent": "center", + "marginRight": 12, + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Very Long Display Name That Might Get Truncated + </Text> + </View> + </View> + </RNGestureHandlerButton> +</View> +`; + +exports[`Story Snapshots: NoVoiceCallPermission should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "minHeight": 100, + "padding": 24, + } + } +> + <RNGestureHandlerButton + accessibilityLabel="John Doe" + accessibilityRole="button" + activeOpacity={0.105} + collapsable={false} + delayLongPress={600} + handlerTag={19} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + rippleColor="#D7DBE0" + style={ + [ + { + "backgroundColor": "#FFFFFF", + }, + { + "cursor": undefined, + }, + ] + } + testID="new-message-view-item-john.doe" + underlayColor="#D7DBE0" + > + <View + collapsable={false} + style={ + { + "backgroundColor": "#D7DBE0", + "borderBottomLeftRadius": undefined, + "borderBottomRightRadius": undefined, + "borderRadius": undefined, + "borderTopLeftRadius": undefined, + "borderTopRightRadius": undefined, + "bottom": 0, + "left": 0, + "opacity": 0, + "position": "absolute", + "right": 0, + "top": 0, + } + } + /> + <View + style={ + [ + { + "flexDirection": "row", + }, + { + "height": 54, + }, + ] + } + > + <View + accessibilityLabel="john.doe's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 30, + "width": 30, + }, + { + "marginHorizontal": 12, + "marginVertical": 12, + }, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={30} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": undefined, + "uri": "https://open.rocket.chat/avatar/john.doe?format=png&size=60", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 30, + "width": 30, + } + } + transition={null} + width={30} + /> + </View> + <View + style={ + { + "flex": 1, + "flexDirection": "column", + "justifyContent": "center", + "marginRight": 12, + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + John Doe + </Text> + </View> + </View> + </RNGestureHandlerButton> +</View> +`; diff --git a/app/views/NewMessageView/index.tsx b/app/views/NewMessageView/index.tsx index 375e5d4d4e2..d007f4c6c74 100644 --- a/app/views/NewMessageView/index.tsx +++ b/app/views/NewMessageView/index.tsx @@ -17,8 +17,9 @@ import log, { events, logEvent } from '../../lib/methods/helpers/log'; import { type NewMessageStackParamList } from '../../stacks/types'; import { search as searchMethod } from '../../lib/methods/search'; import { useAppSelector } from '../../lib/hooks/useAppSelector'; -import UserItem from '../../containers/UserItem'; +import Item from './Item'; import HeaderNewMessage from './HeaderNewMessage'; +import { getUidDirectMessage } from '../../lib/methods/helpers/helpers'; const QUERY_SIZE = 50; @@ -88,9 +89,11 @@ const NewMessageView = () => { renderItem={({ item }) => { const itemSearch = item as ISearch; const itemModel = item as TSubscriptionModel; + const userId = itemSearch.search ? itemSearch._id : getUidDirectMessage(itemModel); return ( - <UserItem + <Item + userId={userId} name={useRealName && itemSearch.fname ? itemSearch.fname : itemModel.name} username={itemSearch.search ? itemSearch.username : itemModel.name} onPress={() => goRoom(itemModel)} @@ -100,7 +103,7 @@ const NewMessageView = () => { }} ItemSeparatorComponent={List.Separator} ListFooterComponent={List.Separator} - contentContainerStyle={{ backgroundColor: colors.surfaceRoom }} + style={{ backgroundColor: colors.surfaceTint }} keyboardShouldPersistTaps='always' /> </SafeAreaView> diff --git a/app/views/RoomActionsView/components/CallSection.tsx b/app/views/RoomActionsView/components/CallSection.tsx index 3f7d8408ed9..4d0707a52d5 100644 --- a/app/views/RoomActionsView/components/CallSection.tsx +++ b/app/views/RoomActionsView/components/CallSection.tsx @@ -2,23 +2,58 @@ import React from 'react'; import * as List from '../../../containers/List'; import { useVideoConf } from '../../../lib/hooks/useVideoConf'; +import { mediaSessionInstance } from '../../../lib/services/voip/MediaSessionInstance'; +import type { TSubscriptionModel } from '../../../definitions'; +import { useMediaCallPermission } from '../../../lib/hooks/useMediaCallPermission'; -export default function CallSection({ rid, disabled }: { rid: string; disabled: boolean }): React.ReactElement | null { - const { callEnabled, showInitCallActionSheet, disabledTooltip } = useVideoConf(rid); - if (callEnabled) - return ( - <List.Section> - <List.Separator /> - <List.Item - title={'Call'} - onPress={showInitCallActionSheet} - testID='room-actions-call' - left={() => <List.Icon name='phone' />} - showActionIndicator - disabled={disabledTooltip || disabled} - /> - <List.Separator /> - </List.Section> - ); - return null; +export default function CallSection({ + room, + disabled +}: { + room: TSubscriptionModel; + disabled: boolean; +}): React.ReactElement | null { + const { callEnabled, showInitCallActionSheet, disabledTooltip } = useVideoConf(room.rid); + const hasMediaCallPermission = useMediaCallPermission(); + + const handleVoiceCallPress = () => { + if (!room) return; + mediaSessionInstance.startCallByRoom(room); + }; + + if (!hasMediaCallPermission && !callEnabled) { + return null; + } + + return ( + <List.Section> + <List.Separator /> + {hasMediaCallPermission ? ( + <> + <List.Item + title={'Voice_call'} + onPress={handleVoiceCallPress} + testID='room-actions-voice-call' + left={() => <List.Icon name='phone' />} + showActionIndicator + disabled={disabledTooltip || disabled} + /> + <List.Separator /> + </> + ) : null} + {callEnabled ? ( + <> + <List.Item + title={'Video_call'} + onPress={showInitCallActionSheet} + testID='room-actions-call' + left={() => <List.Icon name='camera' />} + showActionIndicator + disabled={disabledTooltip || disabled} + /> + <List.Separator /> + </> + ) : null} + </List.Section> + ); } diff --git a/app/views/RoomActionsView/index.tsx b/app/views/RoomActionsView/index.tsx index 70d06e16fd9..d4db91e0325 100644 --- a/app/views/RoomActionsView/index.tsx +++ b/app/views/RoomActionsView/index.tsx @@ -1089,7 +1089,7 @@ class RoomActionsView extends React.Component<IRoomActionsViewProps, IRoomAction <SafeAreaView testID='room-actions-view'> <List.Container testID='room-actions-scrollview'> {this.renderRoomInfo()} - <CallSection rid={rid} disabled={hasE2EEWarning} /> + <CallSection room={room} disabled={hasE2EEWarning} /> {this.renderE2EEncryption()} <List.Section> <List.Separator /> diff --git a/app/views/RoomInfoView/components/RoomInfoABAC.stories.tsx b/app/views/RoomInfoView/components/RoomInfoABAC.stories.tsx index 56e79d09175..573ff297751 100644 --- a/app/views/RoomInfoView/components/RoomInfoABAC.stories.tsx +++ b/app/views/RoomInfoView/components/RoomInfoABAC.stories.tsx @@ -7,7 +7,7 @@ import { ThemeContext } from '../../../theme'; import { colors } from '../../../lib/constants/colors'; export default { - title: 'RoomInfoABAC', + title: 'RoomInfoView/RoomInfoABAC', component: RoomInfoABAC, decorators: [ (Story: any) => ( diff --git a/app/views/RoomInfoView/components/RoomInfoButtons.stories.tsx b/app/views/RoomInfoView/components/RoomInfoButtons.stories.tsx new file mode 100644 index 00000000000..c47238fca4c --- /dev/null +++ b/app/views/RoomInfoView/components/RoomInfoButtons.stories.tsx @@ -0,0 +1,181 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; + +import { RoomInfoButtons } from './RoomInfoButtons'; +import type { ISubscription } from '../../../definitions'; +import { SubscriptionType } from '../../../definitions'; +import { clearEnterpriseModules, setEnterpriseModules } from '../../../actions/enterpriseModules'; +import { setPermissions } from '../../../actions/permissions'; +import { setUser } from '../../../actions/login'; +import { mockedStore } from '../../../reducers/mockedStore'; +import { addSettings } from '../../../actions/settings'; + +const styles = StyleSheet.create({ + container: { + padding: 24, + minHeight: 200 + } +}); + +const Wrapper = ({ children }: { children: React.ReactNode }) => <View style={styles.container}>{children}</View>; + +const createMockRoom = (overrides: Partial<ISubscription> = {}): ISubscription => + ({ + _id: 'room1', + rid: 'room1', + id: 'room1', + t: SubscriptionType.DIRECT, + name: 'john.doe', + fname: 'John Doe', + uids: ['abc', 'user123'], + ls: new Date(), + ts: new Date(), + lm: '', + lr: '', + unread: 0, + userMentions: 0, + groupMentions: 0, + tunread: [], + open: true, + alert: false, + f: false, + archived: false, + roomUpdatedAt: new Date(), + ro: false, + ...overrides + } as ISubscription); + +const defaultHandlers = { + handleCreateDirectMessage: () => {}, + handleIgnoreUser: () => {}, + handleBlockUser: () => {}, + handleReportUser: () => {}, + showActionSheet: () => {} +}; + +const withVoiceAndVideoCallEnabled = (Story: React.ComponentType) => { + mockedStore.dispatch(setEnterpriseModules(['teams-voip'])); + mockedStore.dispatch(addSettings({ VideoConf_Enable_DMs: true })); + mockedStore.dispatch( + setPermissions({ + 'allow-internal-voice-calls': ['user'], + 'allow-external-voice-calls': ['user'], + 'call-management': ['user'] + }) + ); + mockedStore.dispatch(setUser({ roles: ['user'] })); + return <Story />; +}; + +export default { + title: 'RoomInfoView/RoomInfoButtons', + component: RoomInfoButtons, + decorators: [withVoiceAndVideoCallEnabled] +}; + +export const Default = () => ( + <Wrapper> + <RoomInfoButtons + rid='room1' + room={createMockRoom()} + roomUserId='user123' + isDirect={true} + fromRid='room1' + roomFromRid={undefined} + serverVersion='8.0.0' + itsMe={false} + {...defaultHandlers} + /> + </Wrapper> +); + +export const ItsMe = () => ( + <Wrapper> + <RoomInfoButtons + rid='room1' + room={createMockRoom()} + roomUserId='abc' + isDirect={true} + fromRid='room1' + roomFromRid={undefined} + serverVersion='7.0.0' + itsMe={true} + {...defaultHandlers} + /> + </Wrapper> +); + +export const WithRoomFromRid = () => ( + <Wrapper> + <RoomInfoButtons + rid='room1' + room={createMockRoom()} + roomUserId='user123' + isDirect={true} + fromRid='room1' + roomFromRid={createMockRoom()} + serverVersion='7.0.0' + itsMe={false} + {...defaultHandlers} + /> + </Wrapper> +); + +export const WithBlockedUser = () => ( + <Wrapper> + <RoomInfoButtons + rid='room1' + room={createMockRoom({ blocker: true })} + roomUserId='user123' + isDirect={true} + fromRid='room1' + roomFromRid={undefined} + serverVersion='7.0.0' + itsMe={false} + {...defaultHandlers} + /> + </Wrapper> +); + +const withVoiceCallDisabled = (Story: React.ComponentType) => { + mockedStore.dispatch(clearEnterpriseModules()); + return <Story />; +}; + +export const OlderServer = { + render: () => ( + <Wrapper> + <RoomInfoButtons + rid='room1' + room={createMockRoom()} + roomUserId='user123' + isDirect={true} + fromRid='room1' + roomFromRid={undefined} + serverVersion='5.0.0' + itsMe={false} + {...defaultHandlers} + /> + </Wrapper> + ), + decorators: [withVoiceCallDisabled] +}; + +export const NoVoiceCall = { + render: () => ( + <Wrapper> + <RoomInfoButtons + rid='room1' + room={createMockRoom()} + roomUserId='user123' + isDirect={true} + fromRid='room1' + roomFromRid={undefined} + serverVersion='7.0.0' + itsMe={false} + {...defaultHandlers} + /> + </Wrapper> + ), + decorators: [withVoiceCallDisabled] +}; diff --git a/app/views/RoomInfoView/components/RoomInfoButtons.test.tsx b/app/views/RoomInfoView/components/RoomInfoButtons.test.tsx new file mode 100644 index 00000000000..877f3e97eb3 --- /dev/null +++ b/app/views/RoomInfoView/components/RoomInfoButtons.test.tsx @@ -0,0 +1,172 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import { RoomInfoButtons } from './RoomInfoButtons'; +import { mockedStore } from '../../../reducers/mockedStore'; +import * as stories from './RoomInfoButtons.stories'; +import { generateSnapshots } from '../../../../.rnstorybook/generateSnapshots'; +import type { ISubscription } from '../../../definitions'; +import { SubscriptionType } from '../../../definitions'; + +const mockShowInitCallActionSheet = jest.fn(); +const mockShowActionSheet = jest.fn(); +const mockStartCallByRoom = jest.fn(); + +const mockUseVideoConf = jest.fn(); +const mockUseMediaCallPermission = jest.fn(); + +jest.mock('../../../lib/hooks/useVideoConf', () => ({ + useVideoConf: (...args: unknown[]) => mockUseVideoConf(...args) +})); + +jest.mock('../../../lib/hooks/useMediaCallPermission', () => ({ + useMediaCallPermission: (...args: unknown[]) => mockUseMediaCallPermission(...args) +})); + +jest.mock('../hooks', () => ({ + useE2EEWarning: () => false +})); + +jest.mock('../../../containers/ActionSheet', () => ({ + ...jest.requireActual('../../../containers/ActionSheet'), + useActionSheet: () => ({ showActionSheet: mockShowActionSheet }) +})); + +jest.mock('../../../lib/services/voip/MediaSessionInstance', () => ({ + mediaSessionInstance: { + startCallByRoom: (room: ISubscription) => mockStartCallByRoom(room) + } +})); + +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; + +const createMockRoom = (overrides: Partial<ISubscription> = {}): ISubscription => + ({ + _id: 'room1', + rid: 'room1', + id: 'room1', + t: SubscriptionType.DIRECT, + name: 'john.doe', + fname: 'John Doe', + uids: ['abc', 'user123'], + ls: new Date(), + ts: new Date(), + lm: '', + lr: '', + unread: 0, + userMentions: 0, + groupMentions: 0, + tunread: [], + open: true, + alert: false, + f: false, + archived: false, + roomUpdatedAt: new Date(), + ro: false, + ...overrides + } as ISubscription); + +const defaultProps = { + rid: 'room1', + room: createMockRoom(), + roomUserId: 'user123', + isDirect: true, + fromRid: 'room1', + roomFromRid: undefined as ISubscription | undefined, + serverVersion: '7.0.0' as string | null, + itsMe: false, + handleCreateDirectMessage: jest.fn(), + handleIgnoreUser: jest.fn(), + handleBlockUser: jest.fn(), + handleReportUser: jest.fn() +}; + +describe('RoomInfoButtons', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockUseVideoConf.mockReturnValue({ + callEnabled: true, + disabledTooltip: false, + showInitCallActionSheet: mockShowInitCallActionSheet + }); + mockUseMediaCallPermission.mockReturnValue(true); + }); + + it('should render Message button', () => { + const { getByText } = render( + <Wrapper> + <RoomInfoButtons {...defaultProps} /> + </Wrapper> + ); + expect(getByText('Message')).toBeTruthy(); + }); + + it('should call handleCreateDirectMessage when Message is pressed', () => { + const handleCreateDirectMessage = jest.fn(); + const { getByTestId } = render( + <Wrapper> + <RoomInfoButtons {...defaultProps} handleCreateDirectMessage={handleCreateDirectMessage} /> + </Wrapper> + ); + fireEvent.press(getByTestId('room-info-view-message')); + expect(handleCreateDirectMessage).toHaveBeenCalledTimes(1); + }); + + it('should call mediaSessionInstance.startCallByRoom when Voice call is pressed', () => { + const mockRoom = createMockRoom(); + const { getByTestId } = render( + <Wrapper> + <RoomInfoButtons {...defaultProps} room={mockRoom} /> + </Wrapper> + ); + fireEvent.press(getByTestId('room-info-view-phone')); + expect(mockStartCallByRoom).toHaveBeenCalledTimes(1); + expect(mockStartCallByRoom).toHaveBeenCalledWith(mockRoom); + }); + + it('should call showInitCallActionSheet when Video call is pressed', () => { + const { getByTestId } = render( + <Wrapper> + <RoomInfoButtons {...defaultProps} /> + </Wrapper> + ); + fireEvent.press(getByTestId('room-info-view-camera')); + expect(mockShowInitCallActionSheet).toHaveBeenCalledTimes(1); + }); + + it('should not render Voice call when useMediaCallPermission returns false', () => { + mockUseMediaCallPermission.mockReturnValue(false); + const { queryByTestId } = render( + <Wrapper> + <RoomInfoButtons {...defaultProps} /> + </Wrapper> + ); + expect(queryByTestId('room-info-view-phone')).toBeNull(); + }); + + it('should not render Video call when useVideoConf returns callEnabled false', () => { + mockUseVideoConf.mockReturnValue({ + callEnabled: false, + disabledTooltip: false, + showInitCallActionSheet: mockShowInitCallActionSheet + }); + const { queryByTestId } = render( + <Wrapper> + <RoomInfoButtons {...defaultProps} /> + </Wrapper> + ); + expect(queryByTestId('room-info-view-camera')).toBeNull(); + }); + + it('should render More button when more than 4 items are visible', () => { + const { getByTestId } = render( + <Wrapper> + <RoomInfoButtons {...defaultProps} /> + </Wrapper> + ); + expect(getByTestId('room-info-view-kebab')).toBeTruthy(); + }); +}); + +generateSnapshots(stories); diff --git a/app/views/RoomInfoView/components/RoomInfoButtons.tsx b/app/views/RoomInfoView/components/RoomInfoButtons.tsx index 1f5ae188c15..d04b966b9aa 100644 --- a/app/views/RoomInfoView/components/RoomInfoButtons.tsx +++ b/app/views/RoomInfoView/components/RoomInfoButtons.tsx @@ -10,6 +10,19 @@ import { useTheme } from '../../../theme'; import styles from '../styles'; import { compareServerVersion } from '../../../lib/methods/helpers'; import { useE2EEWarning } from '../hooks'; +import { useActionSheet } from '../../../containers/ActionSheet'; +import type { TActionSheetOptionsItem } from '../../../containers/ActionSheet'; +import { mediaSessionInstance } from '../../../lib/services/voip/MediaSessionInstance'; +import { useMediaCallPermission } from '../../../lib/hooks/useMediaCallPermission'; + +type ButtonConfig = { + label: string; + iconName: TIconsName; + onPress: () => void; + danger?: boolean; + enabled?: boolean; + show: boolean; +}; function BaseButton({ danger, @@ -41,19 +54,6 @@ function BaseButton({ return null; } -function CallButton({ rid, roomFromRid }: { rid: string; isDirect: boolean; roomFromRid: boolean }): React.ReactElement | null { - const { callEnabled, disabledTooltip, showInitCallActionSheet } = useVideoConf(rid); - return ( - <BaseButton - onPress={showInitCallActionSheet} - iconName='phone' - label={i18n.t('Call')} - enabled={!disabledTooltip} - showIcon={callEnabled && !roomFromRid} - /> - ); -} - interface IRoomInfoButtons { rid: string; room: ISubscription | undefined; @@ -83,7 +83,13 @@ export const RoomInfoButtons = ({ serverVersion, itsMe }: IRoomInfoButtons): React.ReactElement => { + 'use memo'; + const room = roomFromRid || roomFromProps; + const { showActionSheet } = useActionSheet(); + const { callEnabled, disabledTooltip, showInitCallActionSheet } = useVideoConf(rid); + const hasMediaCallPermission = useMediaCallPermission(); + // Following the web behavior, when is a DM with myself, shouldn't appear block or ignore option const isDmWithMyself = room?.uids?.filter((uid: string) => uid !== roomUserId).length === 0; const isFromDm = room?.t === SubscriptionType.DIRECT; @@ -96,24 +102,90 @@ export const RoomInfoButtons = ({ const renderBlockUser = !itsMe && isDirectFromSaved && isFromDm && !isDmWithMyself; const renderReportUser = !itsMe && isDirectFromSaved && !isDmWithMyself && compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '6.4.0'); + const renderVideoCall = !hasE2EEWarning && callEnabled && !roomFromRid; + + const handleVoiceCall = () => { + if (!room) return; + mediaSessionInstance.startCallByRoom(room); + }; + + const allItems: ButtonConfig[] = [ + { + label: i18n.t('Message'), + iconName: 'message', + onPress: handleCreateDirectMessage, + enabled: true, + show: true + }, + { + label: i18n.t('Voice_call'), + iconName: 'phone', + onPress: handleVoiceCall, + enabled: true, + show: hasMediaCallPermission + }, + { + label: i18n.t('Video_call'), + iconName: 'camera', + onPress: showInitCallActionSheet, + enabled: !disabledTooltip, + show: renderVideoCall + }, + { + label: i18n.t(isIgnored ? 'Unignore' : 'Ignore'), + iconName: 'ignore', + onPress: handleIgnoreUser, + enabled: true, + show: !!renderIgnoreUser + }, + { + label: i18n.t(isBlocked ? 'Unblock' : 'Block'), + iconName: 'ignore', + onPress: handleBlockUser, + enabled: true, + show: !!renderBlockUser + }, + { + label: i18n.t('Report'), + iconName: 'warning', + onPress: handleReportUser, + danger: true, + enabled: true, + show: !!renderReportUser + } + ]; + + const visibleItems = allItems.filter(i => i.show); + const hasOverflow = visibleItems.length > 4; + const primaryItems = hasOverflow ? visibleItems.slice(0, 3) : visibleItems; + const overflowItems = hasOverflow ? visibleItems.slice(3) : []; + + const overflowOptions: TActionSheetOptionsItem[] = overflowItems.map(item => ({ + title: item.label, + icon: item.iconName, + onPress: item.onPress, + danger: item.danger, + enabled: item.enabled ?? true + })); + + const handleMore = () => { + showActionSheet({ options: overflowOptions }); + }; return ( <View style={styles.roomButtonsContainer}> - <BaseButton onPress={handleCreateDirectMessage} label={i18n.t('Message')} iconName='message' /> - {hasE2EEWarning ? null : <CallButton isDirect={isDirect} rid={rid} roomFromRid={!!roomFromRid} />} - <BaseButton - onPress={handleIgnoreUser} - label={i18n.t(isIgnored ? 'Unignore' : 'Ignore')} - iconName='ignore' - showIcon={!!renderIgnoreUser} - /> - <BaseButton - onPress={handleBlockUser} - label={i18n.t(`${isBlocked ? 'Unblock' : 'Block'}`)} - iconName='ignore' - showIcon={!!renderBlockUser} - /> - <BaseButton onPress={handleReportUser} label={i18n.t('Report')} iconName='warning' showIcon={!!renderReportUser} danger /> + {primaryItems.map(item => ( + <BaseButton + key={item.label} + onPress={item.onPress} + label={item.label} + iconName={item.iconName} + danger={item.danger} + enabled={item.enabled ?? true} + showIcon={true} + /> + ))} + {hasOverflow && <BaseButton onPress={handleMore} label={i18n.t('More')} iconName='kebab' showIcon={true} enabled={true} />} </View> ); }; diff --git a/app/views/RoomInfoView/components/__snapshots__/RoomInfoButtons.test.tsx.snap b/app/views/RoomInfoView/components/__snapshots__/RoomInfoButtons.test.tsx.snap new file mode 100644 index 00000000000..9816e4a6477 --- /dev/null +++ b/app/views/RoomInfoView/components/__snapshots__/RoomInfoButtons.test.tsx.snap @@ -0,0 +1,1760 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: Default should match snapshot 1`] = ` +<View + style={ + { + "minHeight": 200, + "padding": 24, + } + } +> + <View + style={ + { + "flexDirection": "row", + "paddingTop": 16, + } + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={29} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Message + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={30} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-phone" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Voice call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={31} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-camera" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Video call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={32} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-kebab" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + More + </Text> + </RNGestureHandlerButton> + </View> +</View> +`; + +exports[`Story Snapshots: ItsMe should match snapshot 1`] = ` +<View + style={ + { + "minHeight": 200, + "padding": 24, + } + } +> + <View + style={ + { + "flexDirection": "row", + "paddingTop": 16, + } + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={33} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Message + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={34} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-phone" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Voice call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={35} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-camera" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Video call + </Text> + </RNGestureHandlerButton> + </View> +</View> +`; + +exports[`Story Snapshots: NoVoiceCall should match snapshot 1`] = ` +<View + style={ + { + "minHeight": 200, + "padding": 24, + } + } +> + <View + style={ + { + "flexDirection": "row", + "paddingTop": 16, + } + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={36} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Message + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={37} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-phone" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Voice call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={38} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-camera" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Video call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={39} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-kebab" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + More + </Text> + </RNGestureHandlerButton> + </View> +</View> +`; + +exports[`Story Snapshots: OlderServer should match snapshot 1`] = ` +<View + style={ + { + "minHeight": 200, + "padding": 24, + } + } +> + <View + style={ + { + "flexDirection": "row", + "paddingTop": 16, + } + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={40} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Message + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={41} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-phone" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Voice call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={42} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-camera" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Video call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={43} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-ignore" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Block + </Text> + </RNGestureHandlerButton> + </View> +</View> +`; + +exports[`Story Snapshots: WithBlockedUser should match snapshot 1`] = ` +<View + style={ + { + "minHeight": 200, + "padding": 24, + } + } +> + <View + style={ + { + "flexDirection": "row", + "paddingTop": 16, + } + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={44} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Message + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={45} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-phone" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Voice call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={46} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[MockFunction]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-camera" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Video call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={47} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-kebab" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + More + </Text> + </RNGestureHandlerButton> + </View> +</View> +`; + +exports[`Story Snapshots: WithRoomFromRid should match snapshot 1`] = ` +<View + style={ + { + "minHeight": 200, + "padding": 24, + } + } +> + <View + style={ + { + "flexDirection": "row", + "paddingTop": 16, + } + } + > + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={48} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-message" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Message + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={49} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-phone" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Voice call + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={50} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-ignore" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#6C727A", + }, + ] + } + > + Block + </Text> + </RNGestureHandlerButton> + <RNGestureHandlerButton + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + enabled={true} + handlerTag={51} + handlerType="NativeViewGestureHandler" + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={[Function]} + style={ + [ + { + "alignItems": "center", + "justifyContent": "space-between", + "marginHorizontal": 4, + "opacity": 1, + "width": 80, + }, + { + "cursor": undefined, + }, + ] + } + testID="room-info-view-warning" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#EC0D2A", + "fontSize": 30, + }, + [ + { + "lineHeight": 30, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "marginTop": 4, + }, + { + "color": "#EC0D2A", + }, + ] + } + > + Report + </Text> + </RNGestureHandlerButton> + </View> +</View> +`; diff --git a/app/views/RoomView/RightButtons.tsx b/app/views/RoomView/RightButtons.tsx index 2ad9a83367e..a389453ff6b 100644 --- a/app/views/RoomView/RightButtons.tsx +++ b/app/views/RoomView/RightButtons.tsx @@ -528,6 +528,7 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS accessibilityLabel={i18n.t('Call_room_name', { roomName: accessibilityRoomName })} rid={rid} disabled={hasE2EEWarning} + room={this.room} /> {threadsEnabled ? ( <HeaderButton.Item diff --git a/app/views/RoomView/components/HeaderCallButton.tsx b/app/views/RoomView/components/HeaderCallButton.tsx index f0fb0663992..fc530f102e8 100644 --- a/app/views/RoomView/components/HeaderCallButton.tsx +++ b/app/views/RoomView/components/HeaderCallButton.tsx @@ -1,39 +1,55 @@ import React from 'react'; import * as HeaderButton from '../../../containers/Header/components/HeaderButton'; -// import { useVideoConf } from '../../../lib/hooks/useVideoConf'; -import { useCallStore } from '../../../lib/services/voip/useCallStore'; +import { useVideoConf } from '../../../lib/hooks/useVideoConf'; +import { mediaSessionInstance } from '../../../lib/services/voip/MediaSessionInstance'; +import type { TSubscriptionModel } from '../../../definitions'; +import { useMediaCallPermission } from '../../../lib/hooks/useMediaCallPermission'; export const HeaderCallButton = ({ - // rid, + rid, disabled, - accessibilityLabel + accessibilityLabel, + room }: { rid: string; disabled: boolean; accessibilityLabel: string; + room?: TSubscriptionModel; }): React.ReactElement | null => { - // const { showInitCallActionSheet, callEnabled, disabledTooltip } = useVideoConf(rid); + 'use memo'; - // if (callEnabled) - // return ( - // <HeaderButton.Item - // accessibilityLabel={accessibilityLabel} - // disabled={disabledTooltip || disabled} - // iconName='phone' - // onPress={showInitCallActionSheet} - // testID='room-view-header-call' - // /> - // ); - // return null; - const toggleFocus = useCallStore(state => state.toggleFocus); - return ( - <HeaderButton.Item - accessibilityLabel={accessibilityLabel} - disabled={disabled} - iconName='phone' - onPress={() => toggleFocus()} - testID='room-view-header-call' - /> - ); + const { showInitCallActionSheet, callEnabled, disabledTooltip } = useVideoConf(rid); + const hasMediaCallPermission = useMediaCallPermission(); + + if (hasMediaCallPermission) { + const handlePress = () => { + if (!room) return; + mediaSessionInstance.startCallByRoom(room); + }; + + return ( + <HeaderButton.Item + accessibilityLabel={accessibilityLabel} + disabled={disabled} + iconName='phone' + onPress={handlePress} + testID='room-view-header-call' + /> + ); + } + + if (callEnabled) { + return ( + <HeaderButton.Item + accessibilityLabel={accessibilityLabel} + disabled={disabledTooltip || disabled} + iconName='phone' + onPress={showInitCallActionSheet} + testID='room-view-header-call' + /> + ); + } + + return null; }; diff --git a/app/views/RoomsListView/hooks/useHeader.tsx b/app/views/RoomsListView/hooks/useHeader.tsx index cccc32456fa..f3444507498 100644 --- a/app/views/RoomsListView/hooks/useHeader.tsx +++ b/app/views/RoomsListView/hooks/useHeader.tsx @@ -124,7 +124,7 @@ export const useHeader = () => { ) : null} {canCreateRoom ? ( <HeaderButton.Item - iconName='create' + iconName='add' accessibilityLabel={i18n.t('Create_new_channel_team_dm_discussion')} onPress={goToNewMessage} testID='rooms-list-view-create-channel' From b1e1a80b125701a7c0749da0a763bd41e71cd218 Mon Sep 17 00:00:00 2001 From: diegolmello <diegolmello@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:02:23 +0000 Subject: [PATCH 55/61] chore: format code and fix lint issues --- .../useMediaCallPermission.test.ts | 5 +- app/views/NewMessageView/Item.test.tsx | 56 +++---------------- 2 files changed, 8 insertions(+), 53 deletions(-) diff --git a/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.test.ts b/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.test.ts index 1999711152a..bce46a27bdd 100644 --- a/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.test.ts +++ b/app/lib/hooks/useMediaCallPermission/useMediaCallPermission.test.ts @@ -25,10 +25,7 @@ describe('useMediaCallPermission', () => { const { result } = renderHook(() => useMediaCallPermission()); expect(result.current).toBe(false); - expect(mockUsePermissions).toHaveBeenCalledWith([ - 'allow-internal-voice-calls', - 'allow-external-voice-calls' - ]); + expect(mockUsePermissions).toHaveBeenCalledWith(['allow-internal-voice-calls', 'allow-external-voice-calls']); }); it('should return false when voip module exists but no voice call permissions', () => { diff --git a/app/views/NewMessageView/Item.test.tsx b/app/views/NewMessageView/Item.test.tsx index 80af27bf1b2..737968e9b34 100644 --- a/app/views/NewMessageView/Item.test.tsx +++ b/app/views/NewMessageView/Item.test.tsx @@ -34,13 +34,7 @@ describe('NewMessageView Item', () => { it('should render correctly', () => { const { getByTestId } = render( <Wrapper> - <Item - userId='user123' - name='John Doe' - username='john.doe' - onPress={() => {}} - testID='new-message-view-item-john.doe' - /> + <Item userId='user123' name='John Doe' username='john.doe' onPress={() => {}} testID='new-message-view-item-john.doe' /> </Wrapper> ); expect(getByTestId('new-message-view-item-john.doe')).toBeTruthy(); @@ -49,13 +43,7 @@ describe('NewMessageView Item', () => { it('should display the name', () => { const { getByText } = render( <Wrapper> - <Item - userId='user123' - name='John Doe' - username='john.doe' - onPress={() => {}} - testID='new-message-view-item-john.doe' - /> + <Item userId='user123' name='John Doe' username='john.doe' onPress={() => {}} testID='new-message-view-item-john.doe' /> </Wrapper> ); expect(getByText('John Doe')).toBeTruthy(); @@ -100,13 +88,7 @@ describe('NewMessageView Item', () => { mockUseMediaCallPermission.mockReturnValue(true); const { getByTestId } = render( <Wrapper> - <Item - userId='user123' - name='John Doe' - username='john.doe' - onPress={() => {}} - testID='new-message-view-item-john.doe' - /> + <Item userId='user123' name='John Doe' username='john.doe' onPress={() => {}} testID='new-message-view-item-john.doe' /> </Wrapper> ); fireEvent.press(getByTestId('new-message-view-item-john.doe-call')); @@ -118,13 +100,7 @@ describe('NewMessageView Item', () => { mockUseMediaCallPermission.mockReturnValue(false); const { queryByTestId } = render( <Wrapper> - <Item - userId='user123' - name='John Doe' - username='john.doe' - onPress={() => {}} - testID='new-message-view-item-john.doe' - /> + <Item userId='user123' name='John Doe' username='john.doe' onPress={() => {}} testID='new-message-view-item-john.doe' /> </Wrapper> ); expect(queryByTestId('new-message-view-item-john.doe-call')).toBeNull(); @@ -134,13 +110,7 @@ describe('NewMessageView Item', () => { mockUseMediaCallPermission.mockReturnValue(true); const { getByTestId } = render( <Wrapper> - <Item - userId={''} - name='John Doe' - username='john.doe' - onPress={() => {}} - testID='new-message-view-item-john.doe' - /> + <Item userId={''} name='John Doe' username='john.doe' onPress={() => {}} testID='new-message-view-item-john.doe' /> </Wrapper> ); fireEvent.press(getByTestId('new-message-view-item-john.doe-call')); @@ -150,13 +120,7 @@ describe('NewMessageView Item', () => { it('should have correct accessibility label', () => { const { getByLabelText } = render( <Wrapper> - <Item - userId='user123' - name='John Doe' - username='john.doe' - onPress={() => {}} - testID='new-message-view-item-john.doe' - /> + <Item userId='user123' name='John Doe' username='john.doe' onPress={() => {}} testID='new-message-view-item-john.doe' /> </Wrapper> ); expect(getByLabelText('John Doe')).toBeTruthy(); @@ -166,13 +130,7 @@ describe('NewMessageView Item', () => { mockUseMediaCallPermission.mockReturnValue(false); const { toJSON } = render( <Wrapper> - <Item - userId='user123' - name='John Doe' - username='john.doe' - onPress={() => {}} - testID='new-message-view-item-john.doe' - /> + <Item userId='user123' name='John Doe' username='john.doe' onPress={() => {}} testID='new-message-view-item-john.doe' /> </Wrapper> ); expect(toJSON()).toMatchSnapshot(); From 6fcf8049e05e78f9ae851b48a4d0f3af6fcaaecb Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Mon, 9 Mar 2026 10:59:59 -0300 Subject: [PATCH 56/61] feat: Pre flight (#7038) --- .../Avatar/__snapshots__/Avatar.test.tsx.snap | 1 + .../__snapshots__/HeaderButtons.test.tsx.snap | 8 +- .../List/__snapshots__/List.test.tsx.snap | 24 +- .../MediaCallHeader/MediaCallHeader.test.tsx | 13 +- .../MediaCallHeader.test.tsx.snap | 16 +- .../NewMediaCall/Container.stories.tsx | 54 + app/containers/NewMediaCall/Container.tsx | 18 + .../NewMediaCall/CreateCall.stories.tsx | 46 + .../NewMediaCall/CreateCall.test.tsx | 131 ++ app/containers/NewMediaCall/CreateCall.tsx | 65 + .../NewMediaCall/FilterHeader.stories.tsx | 55 + .../NewMediaCall/FilterHeader.test.tsx | 72 + app/containers/NewMediaCall/FilterHeader.tsx | 70 + .../NewMediaCall/NewMediaCall.stories.tsx | 133 ++ app/containers/NewMediaCall/NewMediaCall.tsx | 23 + .../NewMediaCall/PeerItem.stories.tsx | 57 + app/containers/NewMediaCall/PeerItem.test.tsx | 80 + app/containers/NewMediaCall/PeerItem.tsx | 29 + app/containers/NewMediaCall/PeerItemInner.tsx | 57 + .../NewMediaCall/PeerList.stories.tsx | 60 + app/containers/NewMediaCall/PeerList.test.tsx | 124 ++ app/containers/NewMediaCall/PeerList.tsx | 42 + .../NewMediaCall/SelectedPeer.stories.tsx | 90 ++ .../NewMediaCall/SelectedPeer.test.tsx | 87 + app/containers/NewMediaCall/SelectedPeer.tsx | 59 + .../__snapshots__/CreateCall.test.tsx.snap | 199 +++ .../__snapshots__/FilterHeader.test.tsx.snap | 383 +++++ .../__snapshots__/PeerItem.test.tsx.snap | 534 +++++++ .../__snapshots__/PeerList.test.tsx.snap | 810 ++++++++++ .../__snapshots__/SelectedPeer.test.tsx.snap | 1411 +++++++++++++++++ app/containers/NewMediaCall/index.tsx | 1 + .../__snapshots__/RoomHeader.test.tsx.snap | 2 +- .../__snapshots__/RoomItem.test.tsx.snap | 3 + .../__snapshots__/RoomTypeIcon.test.tsx.snap | 2 + app/containers/Status/Status.tsx | 3 +- .../Status/__snapshots__/Status.test.tsx.snap | 8 + app/i18n/locales/en.json | 2 + app/lib/constants/colors.ts | 2 +- app/lib/constants/defaultSettings.ts | 3 + app/lib/hooks/useNewMediaCall/index.ts | 1 + .../useNewMediaCall/useNewMediaCall.test.tsx | 106 ++ .../hooks/useNewMediaCall/useNewMediaCall.tsx | 27 + app/lib/hooks/useSubscription.test.ts | 109 ++ app/lib/hooks/useSubscription.ts | 28 + .../voip/getPeerAutocompleteOptions.ts | 91 ++ .../voip/usePeerAutocompleteStore.test.ts | 150 ++ .../services/voip/usePeerAutocompleteStore.ts | 61 + .../__snapshots__/Item.test.tsx.snap | 2 +- app/views/NewMessageView/Item.test.tsx | 40 +- app/views/NewMessageView/Item.tsx | 65 +- .../components/CallSection.tsx | 12 +- .../RoomInfoView/components/BaseButton.tsx | 37 + .../components/RoomInfoButtons.test.tsx | 39 +- .../components/RoomInfoButtons.tsx | 49 +- .../__snapshots__/RoomInfoABAC.test.tsx.snap | 10 +- .../__snapshots__/LoadMore.test.tsx.snap | 28 +- app/views/RoomView/RightButtons.tsx | 1 - .../RoomView/components/HeaderCallButton.tsx | 17 +- app/views/SidebarView/components/Stacks.tsx | 27 +- .../__snapshots__/Item.test.tsx.snap | 8 +- 60 files changed, 5499 insertions(+), 186 deletions(-) create mode 100644 app/containers/NewMediaCall/Container.stories.tsx create mode 100644 app/containers/NewMediaCall/Container.tsx create mode 100644 app/containers/NewMediaCall/CreateCall.stories.tsx create mode 100644 app/containers/NewMediaCall/CreateCall.test.tsx create mode 100644 app/containers/NewMediaCall/CreateCall.tsx create mode 100644 app/containers/NewMediaCall/FilterHeader.stories.tsx create mode 100644 app/containers/NewMediaCall/FilterHeader.test.tsx create mode 100644 app/containers/NewMediaCall/FilterHeader.tsx create mode 100644 app/containers/NewMediaCall/NewMediaCall.stories.tsx create mode 100644 app/containers/NewMediaCall/NewMediaCall.tsx create mode 100644 app/containers/NewMediaCall/PeerItem.stories.tsx create mode 100644 app/containers/NewMediaCall/PeerItem.test.tsx create mode 100644 app/containers/NewMediaCall/PeerItem.tsx create mode 100644 app/containers/NewMediaCall/PeerItemInner.tsx create mode 100644 app/containers/NewMediaCall/PeerList.stories.tsx create mode 100644 app/containers/NewMediaCall/PeerList.test.tsx create mode 100644 app/containers/NewMediaCall/PeerList.tsx create mode 100644 app/containers/NewMediaCall/SelectedPeer.stories.tsx create mode 100644 app/containers/NewMediaCall/SelectedPeer.test.tsx create mode 100644 app/containers/NewMediaCall/SelectedPeer.tsx create mode 100644 app/containers/NewMediaCall/__snapshots__/CreateCall.test.tsx.snap create mode 100644 app/containers/NewMediaCall/__snapshots__/FilterHeader.test.tsx.snap create mode 100644 app/containers/NewMediaCall/__snapshots__/PeerItem.test.tsx.snap create mode 100644 app/containers/NewMediaCall/__snapshots__/PeerList.test.tsx.snap create mode 100644 app/containers/NewMediaCall/__snapshots__/SelectedPeer.test.tsx.snap create mode 100644 app/containers/NewMediaCall/index.tsx create mode 100644 app/lib/hooks/useNewMediaCall/index.ts create mode 100644 app/lib/hooks/useNewMediaCall/useNewMediaCall.test.tsx create mode 100644 app/lib/hooks/useNewMediaCall/useNewMediaCall.tsx create mode 100644 app/lib/hooks/useSubscription.test.ts create mode 100644 app/lib/hooks/useSubscription.ts create mode 100644 app/lib/services/voip/getPeerAutocompleteOptions.ts create mode 100644 app/lib/services/voip/usePeerAutocompleteStore.test.ts create mode 100644 app/lib/services/voip/usePeerAutocompleteStore.ts create mode 100644 app/views/RoomInfoView/components/BaseButton.tsx diff --git a/app/containers/Avatar/__snapshots__/Avatar.test.tsx.snap b/app/containers/Avatar/__snapshots__/Avatar.test.tsx.snap index 97d9de5ea35..44cdc296b6f 100644 --- a/app/containers/Avatar/__snapshots__/Avatar.test.tsx.snap +++ b/app/containers/Avatar/__snapshots__/Avatar.test.tsx.snap @@ -398,6 +398,7 @@ exports[`Story Snapshots: Children should match snapshot 1`] = ` [ { "height": 24, + "textAlign": "center", "textAlignVertical": "center", "width": 24, }, diff --git a/app/containers/Header/components/HeaderButton/__snapshots__/HeaderButtons.test.tsx.snap b/app/containers/Header/components/HeaderButton/__snapshots__/HeaderButtons.test.tsx.snap index 938b20fc972..1c917ed5c7d 100644 --- a/app/containers/Header/components/HeaderButton/__snapshots__/HeaderButtons.test.tsx.snap +++ b/app/containers/Header/components/HeaderButton/__snapshots__/HeaderButtons.test.tsx.snap @@ -3923,7 +3923,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -4012,7 +4012,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -4164,7 +4164,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -4219,7 +4219,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ diff --git a/app/containers/List/__snapshots__/List.test.tsx.snap b/app/containers/List/__snapshots__/List.test.tsx.snap index 6414017d4fd..5fdf697d887 100644 --- a/app/containers/List/__snapshots__/List.test.tsx.snap +++ b/app/containers/List/__snapshots__/List.test.tsx.snap @@ -6150,7 +6150,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -6202,7 +6202,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` }, undefined, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -6257,7 +6257,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -6398,7 +6398,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -6450,7 +6450,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` }, undefined, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -6505,7 +6505,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -6721,7 +6721,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -6773,7 +6773,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` }, undefined, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -6828,7 +6828,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -6969,7 +6969,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -7021,7 +7021,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` }, undefined, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -7076,7 +7076,7 @@ exports[`Story Snapshots: WithDarkTheme should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ diff --git a/app/containers/MediaCallHeader/MediaCallHeader.test.tsx b/app/containers/MediaCallHeader/MediaCallHeader.test.tsx index f145f038d7e..d4229750e97 100644 --- a/app/containers/MediaCallHeader/MediaCallHeader.test.tsx +++ b/app/containers/MediaCallHeader/MediaCallHeader.test.tsx @@ -11,6 +11,8 @@ import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; // Mock alert global.alert = jest.fn(); +const mockCallStartTime = 1713340800000; + // Helper to create a mock call const createMockCall = (overrides: Record<string, unknown> = {}) => ({ state: 'active', @@ -42,7 +44,7 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat isMuted: false, isOnHold: false, isSpeakerOn: false, - callStartTime: Date.now(), + callStartTime: mockCallStartTime, contact: { id: 'user-1', displayName: 'Bob Burnquist', @@ -58,6 +60,15 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; +beforeAll(() => { + jest.useFakeTimers(); + jest.setSystemTime(mockCallStartTime); +}); + +afterAll(() => { + jest.useRealTimers(); +}); + describe('MediaCallHeader', () => { beforeEach(() => { useCallStore.getState().reset(); diff --git a/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap index 77beb9effca..86f5b4ca9d3 100644 --- a/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap +++ b/app/containers/MediaCallHeader/__snapshots__/MediaCallHeader.test.tsx.snap @@ -190,6 +190,7 @@ exports[`Story Snapshots: ActiveCall should match snapshot 1`] = ` [ { "height": 16, + "textAlign": "center", "textAlignVertical": "center", "width": 16, }, @@ -228,7 +229,7 @@ exports[`Story Snapshots: ActiveCall should match snapshot 1`] = ` Bob Burnquist <Text> - - 16448:41:15 + 00:00 </Text> </Text> </View> @@ -536,6 +537,7 @@ exports[`Story Snapshots: Collapsed should match snapshot 1`] = ` [ { "height": 16, + "textAlign": "center", "textAlignVertical": "center", "width": 16, }, @@ -574,7 +576,7 @@ exports[`Story Snapshots: Collapsed should match snapshot 1`] = ` Bob Burnquist <Text> - - 16448:41:15 + 00:00 </Text> </Text> </View> @@ -882,6 +884,7 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` [ { "height": 16, + "textAlign": "center", "textAlignVertical": "center", "width": 16, }, @@ -1224,6 +1227,7 @@ exports[`Story Snapshots: Focused should match snapshot 1`] = ` [ { "height": 16, + "textAlign": "center", "textAlignVertical": "center", "width": 16, }, @@ -1262,7 +1266,7 @@ exports[`Story Snapshots: Focused should match snapshot 1`] = ` Bob Burnquist <Text> - - 16448:41:15 + 00:00 </Text> </Text> </View> @@ -1590,6 +1594,7 @@ exports[`Story Snapshots: WithRemoteHeld should match snapshot 1`] = ` [ { "height": 16, + "textAlign": "center", "textAlignVertical": "center", "width": 16, }, @@ -1628,7 +1633,7 @@ exports[`Story Snapshots: WithRemoteHeld should match snapshot 1`] = ` Bob Burnquist <Text> - - 16448:41:15 + 00:00 </Text> </Text> </View> @@ -1936,6 +1941,7 @@ exports[`Story Snapshots: WithRemoteMuted should match snapshot 1`] = ` [ { "height": 16, + "textAlign": "center", "textAlignVertical": "center", "width": 16, }, @@ -1974,7 +1980,7 @@ exports[`Story Snapshots: WithRemoteMuted should match snapshot 1`] = ` Bob Burnquist <Text> - - 16448:41:15 + 00:00 </Text> </Text> </View> diff --git a/app/containers/NewMediaCall/Container.stories.tsx b/app/containers/NewMediaCall/Container.stories.tsx new file mode 100644 index 00000000000..0d460e15853 --- /dev/null +++ b/app/containers/NewMediaCall/Container.stories.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; +import BottomSheet from '@discord/bottom-sheet'; + +import { Container } from './Container'; + +const styles = StyleSheet.create({ + root: { + flex: 1 + }, + placeholder: { + marginTop: 8, + padding: 12, + borderRadius: 6, + backgroundColor: '#efefef' + } +}); + +const PlaceholderChildren = () => ( + <View style={styles.placeholder}> + <Text>Mock children placeholder</Text> + </View> +); + +const BottomSheetWrapper = ({ children }: { children: React.ReactNode }) => ( + <View style={styles.root}> + <BottomSheet + index={0} + snapPoints={['95%']} + handleComponent={null} + enablePanDownToClose={false} + backgroundStyle={{ backgroundColor: 'transparent' }}> + <View style={styles.root}>{children}</View> + </BottomSheet> + </View> +); + +export default { + title: 'NewMediaCall/Container', + component: Container, + decorators: [ + (Story: React.ComponentType) => ( + <BottomSheetWrapper> + <Story /> + </BottomSheetWrapper> + ) + ] +}; + +export const Default = () => ( + <Container> + <PlaceholderChildren /> + </Container> +); diff --git a/app/containers/NewMediaCall/Container.tsx b/app/containers/NewMediaCall/Container.tsx new file mode 100644 index 00000000000..94724e34b2f --- /dev/null +++ b/app/containers/NewMediaCall/Container.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; + +import { useTheme } from '../../theme'; + +export const Container = ({ children }: { children: React.ReactElement[] | React.ReactElement }) => { + const { colors } = useTheme(); + + return <View style={[styles.container, { backgroundColor: colors.surfaceLight }]}>{children}</View>; +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + paddingHorizontal: 16, + paddingTop: 16 + } +}); diff --git a/app/containers/NewMediaCall/CreateCall.stories.tsx b/app/containers/NewMediaCall/CreateCall.stories.tsx new file mode 100644 index 00000000000..690d3eeb825 --- /dev/null +++ b/app/containers/NewMediaCall/CreateCall.stories.tsx @@ -0,0 +1,46 @@ +import React from 'react'; + +import * as ActionSheetModule from '../ActionSheet'; +import { mediaSessionInstance } from '../../lib/services/voip/MediaSessionInstance'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { CreateCall } from './CreateCall'; +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; + +const mediaSession = mediaSessionInstance as unknown as { startCall: (...args: unknown[]) => void }; +mediaSession.startCall = () => {}; + +try { + Object.defineProperty(ActionSheetModule, 'hideActionSheetRef', { + value: () => {}, + writable: true + }); +} catch { + // noop: in environments where export is not re-definable, + // the original hideActionSheetRef is already safe with optional chaining. +} + +const setStoreState = (selectedPeer: ReturnType<typeof usePeerAutocompleteStore.getState>['selectedPeer']) => { + usePeerAutocompleteStore.setState({ selectedPeer }); +}; + +const userPeer: TPeerItem = { + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' +}; + +export default { + title: 'NewMediaCall/CreateCall', + component: CreateCall +}; + +export const Disabled = () => { + setStoreState(null); + return <CreateCall />; +}; + +export const Enabled = () => { + setStoreState(userPeer); + return <CreateCall />; +}; diff --git a/app/containers/NewMediaCall/CreateCall.test.tsx b/app/containers/NewMediaCall/CreateCall.test.tsx new file mode 100644 index 00000000000..e6514083daf --- /dev/null +++ b/app/containers/NewMediaCall/CreateCall.test.tsx @@ -0,0 +1,131 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import { CreateCall } from './CreateCall'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { mockedStore } from '../../reducers/mockedStore'; +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; +import * as stories from './CreateCall.stories'; +import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; + +const mockStartCall = jest.fn(); +const mockHideActionSheet = jest.fn(); + +jest.mock('../../lib/services/voip/MediaSessionInstance', () => { + const instance = {}; + Object.defineProperty(instance, 'startCall', { + value: (...args: unknown[]) => mockStartCall(...args), + writable: false, + configurable: false + }); + return { mediaSessionInstance: instance }; +}); + +jest.mock('../ActionSheet', () => ({ + ...jest.requireActual('../ActionSheet'), + hideActionSheetRef: () => mockHideActionSheet() +})); + +const setStoreState = (selectedPeer: TPeerItem | null) => { + usePeerAutocompleteStore.setState({ selectedPeer }); +}; + +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; + +const userPeer: TPeerItem = { + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' +}; + +const sipPeer: TPeerItem = { + type: 'sip', + value: '+5511999999999', + label: '+55 11 99999-9999' +}; + +describe('CreateCall', () => { + beforeEach(() => { + jest.clearAllMocks(); + usePeerAutocompleteStore.setState({ selectedPeer: null }); + }); + + it('should render the call button', () => { + const { getByTestId } = render( + <Wrapper> + <CreateCall /> + </Wrapper> + ); + + expect(getByTestId('new-media-call-button')).toBeTruthy(); + }); + + it('should be disabled when no peer is selected', () => { + setStoreState(null); + const { getByTestId } = render( + <Wrapper> + <CreateCall /> + </Wrapper> + ); + + const button = getByTestId('new-media-call-button'); + expect(button.props.accessibilityState?.disabled).toBe(true); + }); + + it('should not call startCall or hideActionSheet when disabled and pressed', () => { + setStoreState(null); + const { getByTestId } = render( + <Wrapper> + <CreateCall /> + </Wrapper> + ); + + fireEvent.press(getByTestId('new-media-call-button')); + expect(mockStartCall).not.toHaveBeenCalled(); + expect(mockHideActionSheet).not.toHaveBeenCalled(); + }); + + it('should be enabled when user peer is selected', () => { + setStoreState(userPeer); + const { getByTestId } = render( + <Wrapper> + <CreateCall /> + </Wrapper> + ); + + const button = getByTestId('new-media-call-button'); + expect(button.props.accessibilityState?.disabled).toBe(false); + }); + + it('should call startCall with user type when user peer is selected and pressed', () => { + setStoreState(userPeer); + const { getByTestId } = render( + <Wrapper> + <CreateCall /> + </Wrapper> + ); + + fireEvent.press(getByTestId('new-media-call-button')); + expect(mockStartCall).toHaveBeenCalledTimes(1); + expect(mockStartCall).toHaveBeenCalledWith('user-1', 'user'); + expect(mockHideActionSheet).toHaveBeenCalledTimes(1); + }); + + it('should call startCall when SIP peer is selected and pressed', () => { + setStoreState(sipPeer); + const { getByTestId } = render( + <Wrapper> + <CreateCall /> + </Wrapper> + ); + + fireEvent.press(getByTestId('new-media-call-button')); + expect(mockStartCall).toHaveBeenCalledTimes(1); + expect(mockStartCall).toHaveBeenCalledWith('+5511999999999', 'sip'); + expect(mockHideActionSheet).toHaveBeenCalledTimes(1); + }); +}); + +generateSnapshots(stories); diff --git a/app/containers/NewMediaCall/CreateCall.tsx b/app/containers/NewMediaCall/CreateCall.tsx new file mode 100644 index 00000000000..3cbfa1e1916 --- /dev/null +++ b/app/containers/NewMediaCall/CreateCall.tsx @@ -0,0 +1,65 @@ +import React from 'react'; +import { Pressable, StyleSheet, Text } from 'react-native'; + +import I18n from '../../i18n'; +import { useTheme } from '../../theme'; +import { CustomIcon } from '../CustomIcon'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { mediaSessionInstance } from '../../lib/services/voip/MediaSessionInstance'; +import { hideActionSheetRef } from '../ActionSheet'; +import sharedStyles from '../../views/Styles'; + +export const CreateCall = () => { + const { colors } = useTheme(); + + const selectedPeer = usePeerAutocompleteStore(state => state.selectedPeer); + + const handleCall = () => { + if (!selectedPeer) { + return; + } + + mediaSessionInstance.startCall(selectedPeer.value, selectedPeer.type); + hideActionSheetRef(); + }; + + const isCallDisabled = !selectedPeer; + + return ( + <Pressable + style={[ + styles.callButton, + { + backgroundColor: isCallDisabled ? colors.buttonBackgroundSuccessDisabled : colors.buttonBackgroundSuccessDefault + } + ]} + disabled={isCallDisabled} + onPress={handleCall} + accessibilityRole='button' + accessibilityLabel={I18n.t('Call')} + testID='new-media-call-button' + android_ripple={{ color: colors.buttonBackgroundSuccessPress }}> + <CustomIcon name='phone' size={24} color={isCallDisabled ? colors.buttonPrimaryDisabled : colors.fontWhite} /> + <Text style={[styles.callText, { color: isCallDisabled ? colors.buttonPrimaryDisabled : colors.fontWhite }]}> + {I18n.t('Call')} + </Text> + </Pressable> + ); +}; + +const styles = StyleSheet.create({ + callButton: { + height: 52, + marginTop: 32, + borderRadius: 4, + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'row', + gap: 4 + }, + callText: { + fontSize: 16, + lineHeight: 24, + ...sharedStyles.textMedium + } +}); diff --git a/app/containers/NewMediaCall/FilterHeader.stories.tsx b/app/containers/NewMediaCall/FilterHeader.stories.tsx new file mode 100644 index 00000000000..a375668bd4a --- /dev/null +++ b/app/containers/NewMediaCall/FilterHeader.stories.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; +import BottomSheet from '@discord/bottom-sheet'; + +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { FilterHeader } from './FilterHeader'; + +const styles = StyleSheet.create({ + root: { + flex: 1 + } +}); + +const setStoreState = (filter: string) => { + usePeerAutocompleteStore.setState({ + filter, + selectedPeer: null, + options: [] + }); +}; + +const BottomSheetWrapper = ({ children }: { children: React.ReactNode }) => ( + <View style={styles.root}> + <BottomSheet + index={0} + snapPoints={['95%']} + handleComponent={null} + enablePanDownToClose={false} + backgroundStyle={{ backgroundColor: 'transparent' }}> + <View style={styles.root}>{children}</View> + </BottomSheet> + </View> +); + +export default { + title: 'NewMediaCall/FilterHeader', + component: FilterHeader, + decorators: [ + (Story: React.ComponentType) => ( + <BottomSheetWrapper> + <Story /> + </BottomSheetWrapper> + ) + ] +}; + +export const Default = () => { + setStoreState(''); + return <FilterHeader />; +}; + +export const WithFilter = () => { + setStoreState('alice'); + return <FilterHeader />; +}; diff --git a/app/containers/NewMediaCall/FilterHeader.test.tsx b/app/containers/NewMediaCall/FilterHeader.test.tsx new file mode 100644 index 00000000000..434a90a548d --- /dev/null +++ b/app/containers/NewMediaCall/FilterHeader.test.tsx @@ -0,0 +1,72 @@ +import React from 'react'; +import { act, fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import I18n from '../../i18n'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { mockedStore } from '../../reducers/mockedStore'; +import { textInputDebounceTime } from '../../lib/constants/debounceConfig'; +import { FilterHeader } from './FilterHeader'; +import * as stories from './FilterHeader.stories'; +import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; + +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; + +describe('FilterHeader', () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.useFakeTimers(); + usePeerAutocompleteStore.getState().reset(); + }); + + afterEach(() => { + jest.runOnlyPendingTimers(); + jest.useRealTimers(); + }); + + it('should render title, label and search input', () => { + const { getByText, getByTestId } = render( + <Wrapper> + <FilterHeader /> + </Wrapper> + ); + + expect(getByText(I18n.t('New_call'))).toBeTruthy(); + expect(getByText(I18n.t('Enter_username_or_number'))).toBeTruthy(); + expect(getByTestId('new-media-call-search-input')).toBeTruthy(); + }); + + it('should update filter, clear selection and fetch options after debounce', () => { + const setFilter = jest.fn(); + const clearSelection = jest.fn(); + const fetchOptions = jest.fn(); + usePeerAutocompleteStore.setState({ + filter: '', + selectedPeer: null, + options: [], + setFilter, + clearSelection, + fetchOptions + }); + + const { getByTestId } = render( + <Wrapper> + <FilterHeader /> + </Wrapper> + ); + + fireEvent.changeText(getByTestId('new-media-call-search-input'), 'alice'); + + expect(setFilter).toHaveBeenCalledWith('alice'); + expect(clearSelection).toHaveBeenCalledTimes(1); + expect(fetchOptions).not.toHaveBeenCalled(); + + act(() => { + jest.advanceTimersByTime(textInputDebounceTime); + }); + + expect(fetchOptions).toHaveBeenCalledWith('alice'); + }); +}); + +generateSnapshots(stories); diff --git a/app/containers/NewMediaCall/FilterHeader.tsx b/app/containers/NewMediaCall/FilterHeader.tsx new file mode 100644 index 00000000000..ab86283d6d3 --- /dev/null +++ b/app/containers/NewMediaCall/FilterHeader.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +import I18n from '../../i18n'; +import { useTheme } from '../../theme'; +import { FormTextInput } from '../TextInput'; +import sharedStyles from '../../views/Styles'; +import { textInputDebounceTime } from '../../lib/constants/debounceConfig'; +import { useDebounce } from '../../lib/methods/helpers'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; + +export const FilterHeader = (): React.ReactElement => { + const { colors } = useTheme(); + + const filter = usePeerAutocompleteStore(state => state.filter); + const setFilter = usePeerAutocompleteStore(state => state.setFilter); + const fetchOptions = usePeerAutocompleteStore(state => state.fetchOptions); + const clearSelection = usePeerAutocompleteStore(state => state.clearSelection); + + const debouncedFetchOptions = useDebounce((value: string) => { + fetchOptions(value); + }, textInputDebounceTime); + + const handleChangeText = (value: string) => { + setFilter(value); + clearSelection(); + debouncedFetchOptions(value); + }; + + return ( + <> + <Text style={[styles.title, { color: colors.fontTitlesLabels }]}>{I18n.t('New_call')}</Text> + + <View style={styles.searchContainer}> + <FormTextInput + containerStyle={styles.searchInputContainer} + iconRight='search' + bottomSheet + showErrorMessage={false} + testID='new-media-call-search-input' + onChangeText={handleChangeText} + value={filter} + /> + </View> + <Text style={[styles.inputLabel, { color: colors.fontDefault }]}>{I18n.t('Enter_username_or_number')}</Text> + </> + ); +}; + +const styles = StyleSheet.create({ + title: { + fontSize: 20, + lineHeight: 28, + marginTop: 4, + ...sharedStyles.textBold + }, + searchContainer: { + marginTop: 28, + marginBottom: 8 + }, + searchInputContainer: { + marginBottom: 0 + }, + inputLabel: { + fontSize: 16, + lineHeight: 24, + marginBottom: 16, + ...sharedStyles.textRegular + } +}); diff --git a/app/containers/NewMediaCall/NewMediaCall.stories.tsx b/app/containers/NewMediaCall/NewMediaCall.stories.tsx new file mode 100644 index 00000000000..89daf4e4d39 --- /dev/null +++ b/app/containers/NewMediaCall/NewMediaCall.stories.tsx @@ -0,0 +1,133 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; +import BottomSheet from '@discord/bottom-sheet'; + +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { NewMediaCall } from './NewMediaCall'; + +const styles = StyleSheet.create({ + root: { + flex: 1, + backgroundColor: '#ccc' + }, + container: { + flex: 1, + padding: 16 + } +}); + +const mockUserOptions = [ + { + type: 'user' as const, + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' + }, + { + type: 'user' as const, + value: 'user-2', + label: 'Bob Smith', + username: 'bob.smith' + } +]; + +const setStoreByVariant = (variant: 'empty' | 'searching' | 'userSelected' | 'sipSelected') => { + if (variant === 'empty') { + usePeerAutocompleteStore.setState({ + filter: '', + options: [], + selectedPeer: null + }); + return; + } + + if (variant === 'searching') { + usePeerAutocompleteStore.setState({ + filter: 'al', + options: mockUserOptions, + selectedPeer: null + }); + return; + } + + if (variant === 'userSelected') { + usePeerAutocompleteStore.setState({ + filter: '', + options: [], + selectedPeer: { + type: 'user', + value: 'alice.johnson', + label: 'Alice Johnson', + username: 'alice.johnson' + } + }); + return; + } + + usePeerAutocompleteStore.setState({ + filter: '', + options: [], + selectedPeer: { type: 'sip', value: '+5511999999999', label: '+55 11 99999-9999' } + }); +}; + +const BottomSheetWrapper = ({ children }: { children: React.ReactNode }) => ( + <View style={styles.root}> + <BottomSheet + index={0} + snapPoints={['50%']} + handleComponent={null} + enablePanDownToClose={false} + backgroundStyle={{ backgroundColor: 'transparent' }}> + <View style={styles.root}>{children}</View> + </BottomSheet> + </View> +); + +export default { + title: 'NewMediaCall/NewMediaCall', + component: NewMediaCall, + decorators: [ + (Story: React.ComponentType) => ( + <BottomSheetWrapper> + <Story /> + </BottomSheetWrapper> + ) + ] +}; + +export const Empty = () => { + setStoreByVariant('empty'); + return ( + <View style={styles.container}> + <NewMediaCall /> + </View> + ); +}; + +export const Searching = () => { + setStoreByVariant('searching'); + return ( + <View style={styles.container}> + <NewMediaCall /> + </View> + ); +}; + +export const UserSelected = () => { + setStoreByVariant('userSelected'); + return ( + <View style={styles.container}> + <NewMediaCall /> + </View> + ); +}; + +export const SipSelected = () => { + setStoreByVariant('sipSelected'); + return ( + <View style={styles.container}> + <NewMediaCall /> + </View> + ); +}; diff --git a/app/containers/NewMediaCall/NewMediaCall.tsx b/app/containers/NewMediaCall/NewMediaCall.tsx new file mode 100644 index 00000000000..d4da5e70db7 --- /dev/null +++ b/app/containers/NewMediaCall/NewMediaCall.tsx @@ -0,0 +1,23 @@ +import React, { useEffect } from 'react'; + +import { PeerList } from './PeerList'; +import { SelectedPeer } from './SelectedPeer'; +import { Container } from './Container'; +import { CreateCall } from './CreateCall'; +import { FilterHeader } from './FilterHeader'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; + +export const NewMediaCall = (): React.ReactElement => { + // reset the store when the action sheet is closed + const reset = usePeerAutocompleteStore(state => state.reset); + useEffect(() => () => reset(), [reset]); + + return ( + <Container> + <FilterHeader /> + <SelectedPeer /> + <PeerList /> + <CreateCall /> + </Container> + ); +}; diff --git a/app/containers/NewMediaCall/PeerItem.stories.tsx b/app/containers/NewMediaCall/PeerItem.stories.tsx new file mode 100644 index 00000000000..7193a1aa78f --- /dev/null +++ b/app/containers/NewMediaCall/PeerItem.stories.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; +import { PeerItem } from './PeerItem'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 16, + gap: 8 + }, + label: { + fontSize: 13, + opacity: 0.6 + } +}); + +const onSelectOption = () => {}; + +const userItem: TPeerItem = { + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' +}; + +const sipItem: TPeerItem = { + type: 'sip', + value: '+5511999999999', + label: '+55 11 99999-9999' +}; + +const longLabelItem: TPeerItem = { + type: 'user', + value: 'user-2', + label: 'Long display name to validate text truncation behavior for PeerItem in narrow widths', + username: 'very.long.username' +}; + +export default { + title: 'NewMediaCall/PeerItem', + component: PeerItem +}; + +export const All = () => ( + <View style={styles.container}> + <Text style={styles.label}>User</Text> + <PeerItem item={userItem} onSelectOption={onSelectOption} /> + + <Text style={styles.label}>SIP</Text> + <PeerItem item={sipItem} onSelectOption={onSelectOption} /> + + <Text style={styles.label}>Long label</Text> + <PeerItem item={longLabelItem} onSelectOption={onSelectOption} /> + </View> +); diff --git a/app/containers/NewMediaCall/PeerItem.test.tsx b/app/containers/NewMediaCall/PeerItem.test.tsx new file mode 100644 index 00000000000..560fb8e1d6f --- /dev/null +++ b/app/containers/NewMediaCall/PeerItem.test.tsx @@ -0,0 +1,80 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import { PeerItem } from './PeerItem'; +import { mockedStore } from '../../reducers/mockedStore'; +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; +import * as stories from './PeerItem.stories'; +import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; + +const onSelectOptionMock = jest.fn(); + +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; + +const userItem: TPeerItem = { + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' +}; + +const sipItem: TPeerItem = { + type: 'sip', + value: '+5511999999999', + label: '+55 11 99999-9999' +}; + +describe('PeerItem', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render user option with correct testID', () => { + const { getByTestId, getByText } = render( + <Wrapper> + <PeerItem item={userItem} onSelectOption={onSelectOptionMock} /> + </Wrapper> + ); + + expect(getByTestId('new-media-call-option-user-1')).toBeTruthy(); + expect(getByText('Alice Johnson')).toBeTruthy(); + }); + + it('should render SIP option with correct testID', () => { + const { getByTestId, getByText } = render( + <Wrapper> + <PeerItem item={sipItem} onSelectOption={onSelectOptionMock} /> + </Wrapper> + ); + + expect(getByTestId('new-media-call-option-+5511999999999')).toBeTruthy(); + expect(getByText('+55 11 99999-9999')).toBeTruthy(); + }); + + it('should call onSelectOption with item when pressed', () => { + const { getByTestId } = render( + <Wrapper> + <PeerItem item={userItem} onSelectOption={onSelectOptionMock} /> + </Wrapper> + ); + + fireEvent.press(getByTestId('new-media-call-option-user-1')); + expect(onSelectOptionMock).toHaveBeenCalledTimes(1); + expect(onSelectOptionMock).toHaveBeenCalledWith(userItem); + }); + + it('should call onSelectOption with SIP item when pressed', () => { + const { getByTestId } = render( + <Wrapper> + <PeerItem item={sipItem} onSelectOption={onSelectOptionMock} /> + </Wrapper> + ); + + fireEvent.press(getByTestId('new-media-call-option-+5511999999999')); + expect(onSelectOptionMock).toHaveBeenCalledTimes(1); + expect(onSelectOptionMock).toHaveBeenCalledWith(sipItem); + }); +}); + +generateSnapshots(stories); diff --git a/app/containers/NewMediaCall/PeerItem.tsx b/app/containers/NewMediaCall/PeerItem.tsx new file mode 100644 index 00000000000..d316c86a3c4 --- /dev/null +++ b/app/containers/NewMediaCall/PeerItem.tsx @@ -0,0 +1,29 @@ +import { Pressable, StyleSheet } from 'react-native'; + +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; +import { PeerItemInner } from './PeerItemInner'; +import { useTheme } from '../../theme'; +import { isIOS } from '../../lib/methods/helpers'; + +export const PeerItem = ({ item, onSelectOption }: { item: TPeerItem; onSelectOption: (item: TPeerItem) => void }) => { + const { colors } = useTheme(); + return ( + <Pressable + style={({ pressed }) => [ + styles.container, + { backgroundColor: pressed && isIOS ? colors.surfaceSelected : colors.surfaceLight } + ]} + onPress={() => onSelectOption(item)} + testID={`new-media-call-option-${item.value}`} + android_ripple={{ color: colors.surfaceSelected }}> + <PeerItemInner item={item} /> + </Pressable> + ); +}; + +const styles = StyleSheet.create({ + container: { + paddingVertical: 10, + paddingHorizontal: 12 + } +}); diff --git a/app/containers/NewMediaCall/PeerItemInner.tsx b/app/containers/NewMediaCall/PeerItemInner.tsx new file mode 100644 index 00000000000..ac5c86e48e7 --- /dev/null +++ b/app/containers/NewMediaCall/PeerItemInner.tsx @@ -0,0 +1,57 @@ +import { View, Text, StyleSheet } from 'react-native'; + +import { useTheme } from '../../theme'; +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; +import { CustomIcon } from '../CustomIcon'; +import Avatar from '../Avatar'; +import Status from '../Status'; +import sharedStyles from '../../views/Styles'; + +export const PeerItemInner = ({ item }: { item: TPeerItem }) => { + const { colors } = useTheme(); + + const isSip = item.type === 'sip'; + + return ( + <View style={styles.container}> + <View style={styles.icon}> + {isSip ? ( + <CustomIcon name='phone-in' size={20} color={colors.fontSecondaryInfo} /> + ) : ( + <Avatar text={item.username || item.label} size={28} /> + )} + </View> + <View style={styles.nameContainer}> + {!isSip ? <Status id={item.value} size={20} /> : null} + <Text style={[styles.name, { color: colors.fontDefault }]} numberOfLines={1}> + {item.label} + </Text> + </View> + </View> + ); +}; + +const styles = StyleSheet.create({ + container: { + flexShrink: 1, + flexDirection: 'row', + alignItems: 'center', + gap: 4 + }, + icon: { + width: 28, + alignItems: 'center' + }, + nameContainer: { + flexShrink: 1, + flexDirection: 'row', + alignItems: 'center', + gap: 4 + }, + name: { + flexShrink: 1, + fontSize: 18, + lineHeight: 26, + ...sharedStyles.textMedium + } +}); diff --git a/app/containers/NewMediaCall/PeerList.stories.tsx b/app/containers/NewMediaCall/PeerList.stories.tsx new file mode 100644 index 00000000000..16e253e21e4 --- /dev/null +++ b/app/containers/NewMediaCall/PeerList.stories.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; + +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { PeerList } from './PeerList'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 16 + } +}); + +const mixedOptions: TPeerItem[] = [ + { + type: 'sip', + value: '+5511988887777', + label: '+55 11 98888-7777' + }, + { + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' + }, + { + type: 'user', + value: 'user-2', + label: 'Long display name to validate text truncation behavior for PeerItem in narrow widths', + username: 'very.long.username' + }, + { + type: 'user', + value: 'user-3', + label: 'Bob Smith', + username: 'bob.smith' + } +]; + +const setStoreState = (options: TPeerItem[]) => { + usePeerAutocompleteStore.setState({ + options, + selectedPeer: null + }); +}; + +export default { + title: 'NewMediaCall/PeerList', + component: PeerList +}; + +export const All = () => { + setStoreState(mixedOptions); + return ( + <View style={styles.container}> + <PeerList /> + </View> + ); +}; diff --git a/app/containers/NewMediaCall/PeerList.test.tsx b/app/containers/NewMediaCall/PeerList.test.tsx new file mode 100644 index 00000000000..76ea517fe82 --- /dev/null +++ b/app/containers/NewMediaCall/PeerList.test.tsx @@ -0,0 +1,124 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import { PeerList } from './PeerList'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { mockedStore } from '../../reducers/mockedStore'; +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; +import * as stories from './PeerList.stories'; +import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; + +const setStoreState = (options: TPeerItem[], selectedPeer: TPeerItem | null = null) => { + usePeerAutocompleteStore.setState({ options, selectedPeer }); +}; + +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; + +const mockOptions: TPeerItem[] = [ + { + type: 'sip', + value: '+5511988887777', + label: '+55 11 98888-7777' + }, + { + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' + }, + { + type: 'user', + value: 'user-2', + label: 'Bob Smith', + username: 'bob.smith' + } +]; + +describe('PeerList', () => { + beforeEach(() => { + jest.clearAllMocks(); + usePeerAutocompleteStore.setState({ options: [], selectedPeer: null }); + }); + + it('should render options when no peer selected', () => { + setStoreState(mockOptions); + const { getByTestId, getByText } = render( + <Wrapper> + <PeerList /> + </Wrapper> + ); + + expect(getByTestId('new-media-call-option-+5511988887777')).toBeTruthy(); + expect(getByTestId('new-media-call-option-user-1')).toBeTruthy(); + expect(getByTestId('new-media-call-option-user-2')).toBeTruthy(); + expect(getByText('Alice Johnson')).toBeTruthy(); + expect(getByText('Bob Smith')).toBeTruthy(); + }); + + it('should return null when peer is selected', () => { + setStoreState(mockOptions, mockOptions[1]); + const { queryByTestId } = render( + <Wrapper> + <PeerList /> + </Wrapper> + ); + + expect(queryByTestId('new-media-call-option-user-1')).toBeNull(); + }); + + it('should set selected peer, clear filter and fetch options when option is pressed', () => { + usePeerAutocompleteStore.setState({ + options: mockOptions, + selectedPeer: null, + filter: 'Alice' + }); + + const { getByTestId } = render( + <Wrapper> + <PeerList /> + </Wrapper> + ); + + fireEvent.press(getByTestId('new-media-call-option-user-1')); + + expect(usePeerAutocompleteStore.getState().selectedPeer).toEqual( + expect.objectContaining({ + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' + }) + ); + expect(usePeerAutocompleteStore.getState().filter).toBe(''); + expect(usePeerAutocompleteStore.getState().options).toEqual([]); + }); + + it('should pass sip item correctly when SIP option is pressed', () => { + usePeerAutocompleteStore.setState({ + options: mockOptions, + selectedPeer: null, + filter: '+55 11 98888-7777' + }); + + const { getByTestId } = render( + <Wrapper> + <PeerList /> + </Wrapper> + ); + + fireEvent.press(getByTestId('new-media-call-option-+5511988887777')); + + expect(usePeerAutocompleteStore.getState().selectedPeer).toEqual( + expect.objectContaining({ + type: 'sip', + value: '+5511988887777', + label: '+55 11 98888-7777' + }) + ); + expect(usePeerAutocompleteStore.getState().filter).toBe(''); + expect(usePeerAutocompleteStore.getState().options).toEqual([]); + }); +}); + +generateSnapshots(stories); diff --git a/app/containers/NewMediaCall/PeerList.tsx b/app/containers/NewMediaCall/PeerList.tsx new file mode 100644 index 00000000000..68470b8903f --- /dev/null +++ b/app/containers/NewMediaCall/PeerList.tsx @@ -0,0 +1,42 @@ +import { FlatList } from 'react-native'; + +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; +import { PeerItem } from './PeerItem'; +import * as List from '../List'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; + +export const PeerList = () => { + const setSelectedPeer = usePeerAutocompleteStore(state => state.setSelectedPeer); + const selectedPeer = usePeerAutocompleteStore(state => state.selectedPeer); + const options = usePeerAutocompleteStore(state => state.options); + + if (selectedPeer) return null; + + const handleSelectOption = (option: TPeerItem) => { + const peerItem: TPeerItem = + option.type === 'sip' + ? { type: 'sip', value: option.value, label: option.label } + : { + type: 'user', + value: option.value, + label: option.label, + username: option.username, + callerId: option.callerId + }; + + setSelectedPeer(peerItem); + }; + + const renderItem = ({ item }: { item: TPeerItem }) => <PeerItem item={item} onSelectOption={handleSelectOption} />; + + return ( + <FlatList + data={options} + contentContainerStyle={{ flexShrink: 1 }} + keyExtractor={item => item.value} + keyboardShouldPersistTaps='always' + renderItem={renderItem} + ItemSeparatorComponent={List.Separator} + /> + ); +}; diff --git a/app/containers/NewMediaCall/SelectedPeer.stories.tsx b/app/containers/NewMediaCall/SelectedPeer.stories.tsx new file mode 100644 index 00000000000..db095b3cc15 --- /dev/null +++ b/app/containers/NewMediaCall/SelectedPeer.stories.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; + +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { SelectedPeerInner } from './SelectedPeer'; +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 16, + gap: 12 + }, + sectionLabel: { + fontSize: 13, + opacity: 0.6 + } +}); + +const setStoreState = (selectedPeer: ReturnType<typeof usePeerAutocompleteStore.getState>['selectedPeer']) => { + usePeerAutocompleteStore.setState({ + selectedPeer + }); +}; + +const userPeer: TPeerItem = { + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' +}; + +const sipPeer: TPeerItem = { + type: 'sip', + value: '+5511999999999', + label: '+55 11 99999-9999' +}; + +const longUsernamePeer: TPeerItem = { + type: 'user', + value: 'user-2', + label: 'Long display name to validate text truncation behavior for SelectedPeer in narrow widths', + username: 'this.is.a.very.long.username.for.storybook.preview' +}; + +export default { + title: 'NewMediaCall/SelectedPeer', + component: SelectedPeerInner +}; + +export const All = () => ( + <View style={styles.container}> + <Text style={styles.sectionLabel}>User variant</Text> + <SelectedPeerInner selectedPeer={userPeer} /> + <Text style={styles.sectionLabel}>SIP variant</Text> + <SelectedPeerInner selectedPeer={sipPeer} /> + <Text style={styles.sectionLabel}>Long username variant</Text> + <SelectedPeerInner selectedPeer={longUsernamePeer} /> + </View> +); + +export const User = () => { + setStoreState(userPeer); + return ( + <View style={styles.container}> + <Text style={styles.sectionLabel}>User variant</Text> + <SelectedPeerInner selectedPeer={userPeer} /> + </View> + ); +}; + +export const Sip = () => { + setStoreState(sipPeer); + return ( + <View style={styles.container}> + <Text style={styles.sectionLabel}>SIP variant</Text> + <SelectedPeerInner selectedPeer={sipPeer} /> + </View> + ); +}; + +export const LongUsername = () => { + setStoreState(longUsernamePeer); + return ( + <View style={styles.container}> + <Text style={styles.sectionLabel}>Long username variant</Text> + <SelectedPeerInner selectedPeer={longUsernamePeer} /> + </View> + ); +}; diff --git a/app/containers/NewMediaCall/SelectedPeer.test.tsx b/app/containers/NewMediaCall/SelectedPeer.test.tsx new file mode 100644 index 00000000000..2b58fffae8c --- /dev/null +++ b/app/containers/NewMediaCall/SelectedPeer.test.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; +import { Provider } from 'react-redux'; + +import { SelectedPeer } from './SelectedPeer'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { mockedStore } from '../../reducers/mockedStore'; +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; +import * as stories from './SelectedPeer.stories'; +import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; + +const setStoreState = (selectedPeer: TPeerItem | null) => { + usePeerAutocompleteStore.setState({ selectedPeer }); +}; + +const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; + +const userPeer: TPeerItem = { + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' +}; + +const sipPeer: TPeerItem = { + type: 'sip', + value: '+5511999999999', + label: '+55 11 99999-9999' +}; + +describe('SelectedPeer', () => { + beforeEach(() => { + jest.clearAllMocks(); + usePeerAutocompleteStore.setState({ selectedPeer: null }); + }); + + it('should return null when no peer is selected', () => { + setStoreState(null); + const { queryByTestId } = render( + <Wrapper> + <SelectedPeer /> + </Wrapper> + ); + + expect(queryByTestId('new-media-call-clear-selected-peer')).toBeNull(); + }); + + it('should render selected user peer with label', () => { + setStoreState(userPeer); + const { getByTestId, getByText } = render( + <Wrapper> + <SelectedPeer /> + </Wrapper> + ); + + expect(getByTestId('new-media-call-clear-selected-peer')).toBeTruthy(); + expect(getByText('Alice Johnson')).toBeTruthy(); + }); + + it('should render selected SIP peer with label', () => { + setStoreState(sipPeer); + const { getByTestId, getByText } = render( + <Wrapper> + <SelectedPeer /> + </Wrapper> + ); + + expect(getByTestId('new-media-call-clear-selected-peer')).toBeTruthy(); + expect(getByText('+55 11 99999-9999')).toBeTruthy(); + }); + + it('should call clearSelection when clear button is pressed', () => { + const clearSelection = jest.fn(); + usePeerAutocompleteStore.setState({ selectedPeer: userPeer, clearSelection }); + + const { getByTestId } = render( + <Wrapper> + <SelectedPeer /> + </Wrapper> + ); + + fireEvent.press(getByTestId('new-media-call-clear-selected-peer')); + expect(clearSelection).toHaveBeenCalledTimes(1); + }); +}); + +generateSnapshots(stories); diff --git a/app/containers/NewMediaCall/SelectedPeer.tsx b/app/containers/NewMediaCall/SelectedPeer.tsx new file mode 100644 index 00000000000..e3faee6caa9 --- /dev/null +++ b/app/containers/NewMediaCall/SelectedPeer.tsx @@ -0,0 +1,59 @@ +import { View, StyleSheet } from 'react-native'; +import { BorderlessButton } from 'react-native-gesture-handler'; + +import { useTheme } from '../../theme'; +import { CustomIcon } from '../CustomIcon'; +import I18n from '../../i18n'; +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { PeerItemInner } from './PeerItemInner'; +import type { TPeerItem } from '../../lib/services/voip/getPeerAutocompleteOptions'; + +export const SelectedPeer = () => { + const selectedPeer = usePeerAutocompleteStore(state => state.selectedPeer); + return <SelectedPeerInner selectedPeer={selectedPeer} />; +}; + +export const SelectedPeerInner = ({ selectedPeer }: { selectedPeer: TPeerItem | null }) => { + const { colors } = useTheme(); + const clearSelection = usePeerAutocompleteStore(state => state.clearSelection); + + if (!selectedPeer) return null; + + return ( + <View style={styles.container}> + <View style={[styles.selectedTag, { backgroundColor: colors.buttonBackgroundSecondaryDefault }]}> + <PeerItemInner item={selectedPeer} /> + <BorderlessButton + onPress={clearSelection} + testID='new-media-call-clear-selected-peer' + rippleColor={colors.buttonBackgroundSecondaryPress} + foreground + style={styles.removeButton} + accessibilityLabel={I18n.t('Remove')} + accessibilityRole='button' + hitSlop={10}> + <CustomIcon name={'close'} size={16} color={colors.buttonFontSecondary} /> + </BorderlessButton> + </View> + </View> + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + alignItems: 'center' + }, + selectedTag: { + flexShrink: 1, + minHeight: 48, + borderRadius: 4, + paddingHorizontal: 10, + flexDirection: 'row', + alignItems: 'center', + gap: 10 + }, + removeButton: { + padding: 2 + } +}); diff --git a/app/containers/NewMediaCall/__snapshots__/CreateCall.test.tsx.snap b/app/containers/NewMediaCall/__snapshots__/CreateCall.test.tsx.snap new file mode 100644 index 00000000000..75b24385227 --- /dev/null +++ b/app/containers/NewMediaCall/__snapshots__/CreateCall.test.tsx.snap @@ -0,0 +1,199 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: Disabled should match snapshot 1`] = ` +<View + accessibilityLabel="Call" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": true, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "flexDirection": "row", + "gap": 4, + "height": 52, + "justifyContent": "center", + "marginTop": 32, + }, + { + "backgroundColor": "#C0F6E4", + }, + ] + } + testID="new-media-call-button" +> + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "500", + "lineHeight": 24, + "textAlign": "left", + }, + { + "color": "#FFFFFF", + }, + ] + } + > + Call + </Text> +</View> +`; + +exports[`Story Snapshots: Enabled should match snapshot 1`] = ` +<View + accessibilityLabel="Call" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "flexDirection": "row", + "gap": 4, + "height": 52, + "justifyContent": "center", + "marginTop": 32, + }, + { + "backgroundColor": "#158D65", + }, + ] + } + testID="new-media-call-button" +> + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#FFFFFF", + "fontSize": 24, + }, + [ + { + "lineHeight": 24, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "500", + "lineHeight": 24, + "textAlign": "left", + }, + { + "color": "#FFFFFF", + }, + ] + } + > + Call + </Text> +</View> +`; diff --git a/app/containers/NewMediaCall/__snapshots__/FilterHeader.test.tsx.snap b/app/containers/NewMediaCall/__snapshots__/FilterHeader.test.tsx.snap new file mode 100644 index 00000000000..6ab5db2b71b --- /dev/null +++ b/app/containers/NewMediaCall/__snapshots__/FilterHeader.test.tsx.snap @@ -0,0 +1,383 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: Default should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + backgroundStyle={ + { + "backgroundColor": "transparent", + } + } + enablePanDownToClose={false} + handleComponent={null} + index={0} + snapPoints={ + [ + "95%", + ] + } + > + <View + style={ + { + "flex": 1, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 20, + "fontWeight": "700", + "lineHeight": 28, + "marginTop": 4, + "textAlign": "left", + }, + { + "color": "#1F2329", + }, + ] + } + > + New call + </Text> + <View + style={ + { + "marginBottom": 8, + "marginTop": 28, + } + } + > + <A11yOrderView + orderKey=":r2:" + > + <A11yIndexView + importantForAccessibility="yes" + orderFocusType={0} + orderIndex={1} + orderKey=":r2:" + > + <View + style={ + [ + { + "gap": 4, + "marginBottom": 10, + }, + { + "marginBottom": 0, + }, + ] + } + > + <View + accessible={false} + style={ + { + "justifyContent": "center", + "position": "relative", + } + } + > + <TextInput + accessibilityLabel="" + accessible={true} + autoCapitalize="none" + autoCorrect={false} + onChangeText={[Function]} + placeholderTextColor="#9EA2A8" + style={ + [ + { + "backgroundColor": "transparent", + "borderRadius": 4, + "borderWidth": 1, + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "paddingHorizontal": 16, + "paddingVertical": 14, + "textAlign": "left", + }, + undefined, + { + "paddingRight": 45, + }, + { + "backgroundColor": "#FFFFFF", + "borderColor": "#9EA2A8", + "color": "#1F2329", + }, + {}, + undefined, + ] + } + testID="new-media-call-search-input" + underlineColorAndroid="transparent" + value="" + /> + <Text + accessible={false} + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "position": "absolute", + }, + { + "right": 12, + }, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + testID="new-media-call-search-input-icon-right" + > +  + </Text> + </View> + </View> + </A11yIndexView> + </A11yOrderView> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 24, + "marginBottom": 16, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Enter username or number + </Text> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: WithFilter should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + } + } +> + <View + backgroundStyle={ + { + "backgroundColor": "transparent", + } + } + enablePanDownToClose={false} + handleComponent={null} + index={0} + snapPoints={ + [ + "95%", + ] + } + > + <View + style={ + { + "flex": 1, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 20, + "fontWeight": "700", + "lineHeight": 28, + "marginTop": 4, + "textAlign": "left", + }, + { + "color": "#1F2329", + }, + ] + } + > + New call + </Text> + <View + style={ + { + "marginBottom": 8, + "marginTop": 28, + } + } + > + <A11yOrderView + orderKey=":r3:" + > + <A11yIndexView + importantForAccessibility="yes" + orderFocusType={0} + orderIndex={1} + orderKey=":r3:" + > + <View + style={ + [ + { + "gap": 4, + "marginBottom": 10, + }, + { + "marginBottom": 0, + }, + ] + } + > + <View + accessible={false} + style={ + { + "justifyContent": "center", + "position": "relative", + } + } + > + <TextInput + accessibilityLabel="alice." + accessible={true} + autoCapitalize="none" + autoCorrect={false} + onChangeText={[Function]} + placeholderTextColor="#9EA2A8" + style={ + [ + { + "backgroundColor": "transparent", + "borderRadius": 4, + "borderWidth": 1, + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "paddingHorizontal": 16, + "paddingVertical": 14, + "textAlign": "left", + }, + undefined, + { + "paddingRight": 45, + }, + { + "backgroundColor": "#FFFFFF", + "borderColor": "#9EA2A8", + "color": "#1F2329", + }, + {}, + undefined, + ] + } + testID="new-media-call-search-input" + underlineColorAndroid="transparent" + value="alice" + /> + <Text + accessible={false} + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "position": "absolute", + }, + { + "right": 12, + }, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + testID="new-media-call-search-input-icon-right" + > +  + </Text> + </View> + </View> + </A11yIndexView> + </A11yOrderView> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 24, + "marginBottom": 16, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Enter username or number + </Text> + </View> + </View> +</View> +`; diff --git a/app/containers/NewMediaCall/__snapshots__/PeerItem.test.tsx.snap b/app/containers/NewMediaCall/__snapshots__/PeerItem.test.tsx.snap new file mode 100644 index 00000000000..627400c6caf --- /dev/null +++ b/app/containers/NewMediaCall/__snapshots__/PeerItem.test.tsx.snap @@ -0,0 +1,534 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: All should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "gap": 8, + "padding": 16, + } + } +> + <Text + style={ + { + "fontSize": 13, + "opacity": 0.6, + } + } + > + User + </Text> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "paddingHorizontal": 12, + "paddingVertical": 10, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + testID="new-media-call-option-user-1" + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <View + accessibilityLabel="alice.johnson's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 28, + "width": 28, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={28} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, + "uri": "https://open.rocket.chat/avatar/alice.johnson?format=png&size=56", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 28, + "width": 28, + } + } + transition={null} + width={28} + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "height": 20, + "textAlign": "center", + "textAlignVertical": "center", + "width": 20, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Alice Johnson + </Text> + </View> + </View> + </View> + <Text + style={ + { + "fontSize": 13, + "opacity": 0.6, + } + } + > + SIP + </Text> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "paddingHorizontal": 12, + "paddingVertical": 10, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + testID="new-media-call-option-+5511999999999" + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + +55 11 99999-9999 + </Text> + </View> + </View> + </View> + <Text + style={ + { + "fontSize": 13, + "opacity": 0.6, + } + } + > + Long label + </Text> + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "paddingHorizontal": 12, + "paddingVertical": 10, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + testID="new-media-call-option-user-2" + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <View + accessibilityLabel="very.long.username's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 28, + "width": 28, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={28} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, + "uri": "https://open.rocket.chat/avatar/very.long.username?format=png&size=56", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 28, + "width": 28, + } + } + transition={null} + width={28} + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "height": 20, + "textAlign": "center", + "textAlignVertical": "center", + "width": 20, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Long display name to validate text truncation behavior for PeerItem in narrow widths + </Text> + </View> + </View> + </View> +</View> +`; diff --git a/app/containers/NewMediaCall/__snapshots__/PeerList.test.tsx.snap b/app/containers/NewMediaCall/__snapshots__/PeerList.test.tsx.snap new file mode 100644 index 00000000000..1bb3e59ba2f --- /dev/null +++ b/app/containers/NewMediaCall/__snapshots__/PeerList.test.tsx.snap @@ -0,0 +1,810 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: All should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "padding": 16, + } + } +> + <RCTScrollView + ItemSeparatorComponent={ + { + "$$typeof": Symbol(react.memo), + "compare": null, + "type": [Function], + } + } + contentContainerStyle={ + { + "flexShrink": 1, + } + } + data={ + [ + { + "label": "+55 11 98888-7777", + "type": "sip", + "value": "+5511988887777", + }, + { + "label": "Alice Johnson", + "type": "user", + "username": "alice.johnson", + "value": "user-1", + }, + { + "label": "Long display name to validate text truncation behavior for PeerItem in narrow widths", + "type": "user", + "username": "very.long.username", + "value": "user-2", + }, + { + "label": "Bob Smith", + "type": "user", + "username": "bob.smith", + "value": "user-3", + }, + ] + } + getItem={[Function]} + getItemCount={[Function]} + keyExtractor={[Function]} + keyboardShouldPersistTaps="always" + onContentSizeChange={[Function]} + onLayout={[Function]} + onMomentumScrollBegin={[Function]} + onMomentumScrollEnd={[Function]} + onScroll={[Function]} + onScrollBeginDrag={[Function]} + onScrollEndDrag={[Function]} + removeClippedSubviews={false} + renderItem={[Function]} + scrollEventThrottle={0.0001} + stickyHeaderIndices={[]} + viewabilityConfigCallbackPairs={[]} + > + <View> + <View + onFocusCapture={[Function]} + onLayout={[Function]} + style={null} + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "paddingHorizontal": 12, + "paddingVertical": 10, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + testID="new-media-call-option-+5511988887777" + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + +55 11 98888-7777 + </Text> + </View> + </View> + </View> + <View + style={ + [ + { + "height": 0.5, + }, + undefined, + { + "backgroundColor": "#CBCED1", + }, + ] + } + /> + </View> + <View + onFocusCapture={[Function]} + onLayout={[Function]} + style={null} + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "paddingHorizontal": 12, + "paddingVertical": 10, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + testID="new-media-call-option-user-1" + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <View + accessibilityLabel="alice.johnson's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 28, + "width": 28, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={28} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, + "uri": "https://open.rocket.chat/avatar/alice.johnson?format=png&size=56", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 28, + "width": 28, + } + } + transition={null} + width={28} + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "height": 20, + "textAlign": "center", + "textAlignVertical": "center", + "width": 20, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Alice Johnson + </Text> + </View> + </View> + </View> + <View + style={ + [ + { + "height": 0.5, + }, + undefined, + { + "backgroundColor": "#CBCED1", + }, + ] + } + /> + </View> + <View + onFocusCapture={[Function]} + onLayout={[Function]} + style={null} + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "paddingHorizontal": 12, + "paddingVertical": 10, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + testID="new-media-call-option-user-2" + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <View + accessibilityLabel="very.long.username's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 28, + "width": 28, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={28} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, + "uri": "https://open.rocket.chat/avatar/very.long.username?format=png&size=56", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 28, + "width": 28, + } + } + transition={null} + width={28} + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "height": 20, + "textAlign": "center", + "textAlignVertical": "center", + "width": 20, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Long display name to validate text truncation behavior for PeerItem in narrow widths + </Text> + </View> + </View> + </View> + <View + style={ + [ + { + "height": 0.5, + }, + undefined, + { + "backgroundColor": "#CBCED1", + }, + ] + } + /> + </View> + <View + onFocusCapture={[Function]} + onLayout={[Function]} + style={null} + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onBlur={[Function]} + onClick={[Function]} + onFocus={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + [ + { + "paddingHorizontal": 12, + "paddingVertical": 10, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + testID="new-media-call-option-user-3" + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <View + accessibilityLabel="bob.smith's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 28, + "width": 28, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={28} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, + "uri": "https://open.rocket.chat/avatar/bob.smith?format=png&size=56", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 28, + "width": 28, + } + } + transition={null} + width={28} + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "height": 20, + "textAlign": "center", + "textAlignVertical": "center", + "width": 20, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Bob Smith + </Text> + </View> + </View> + </View> + </View> + </View> + </RCTScrollView> +</View> +`; diff --git a/app/containers/NewMediaCall/__snapshots__/SelectedPeer.test.tsx.snap b/app/containers/NewMediaCall/__snapshots__/SelectedPeer.test.tsx.snap new file mode 100644 index 00000000000..bc87d2db65c --- /dev/null +++ b/app/containers/NewMediaCall/__snapshots__/SelectedPeer.test.tsx.snap @@ -0,0 +1,1411 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Story Snapshots: All should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "gap": 12, + "padding": 16, + } + } +> + <Text + style={ + { + "fontSize": 13, + "opacity": 0.6, + } + } + > + User variant + </Text> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "flexDirection": "row", + "flexShrink": 1, + "gap": 10, + "minHeight": 48, + "paddingHorizontal": 10, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <View + accessibilityLabel="alice.johnson's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 28, + "width": 28, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={28} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, + "uri": "https://open.rocket.chat/avatar/alice.johnson?format=png&size=56", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 28, + "width": 28, + } + } + transition={null} + width={28} + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "height": 20, + "textAlign": "center", + "textAlignVertical": "center", + "width": 20, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Alice Johnson + </Text> + </View> + </View> + <RNGestureHandlerButton + accessibilityLabel="Remove" + accessibilityRole="button" + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + foreground={true} + handlerTag={4} + handlerType="NativeViewGestureHandler" + hitSlop={10} + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={ + [MockFunction] { + "calls": [ + [], + ], + "results": [ + { + "type": "return", + "value": undefined, + }, + ], + } + } + rippleColor="#9EA2A8" + style={ + [ + { + "opacity": 1, + "padding": 2, + }, + { + "cursor": undefined, + }, + ] + } + testID="new-media-call-clear-selected-peer" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 16, + }, + [ + { + "lineHeight": 16, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </RNGestureHandlerButton> + </View> + </View> + <Text + style={ + { + "fontSize": 13, + "opacity": 0.6, + } + } + > + SIP variant + </Text> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "flexDirection": "row", + "flexShrink": 1, + "gap": 10, + "minHeight": 48, + "paddingHorizontal": 10, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + +55 11 99999-9999 + </Text> + </View> + </View> + <RNGestureHandlerButton + accessibilityLabel="Remove" + accessibilityRole="button" + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + foreground={true} + handlerTag={5} + handlerType="NativeViewGestureHandler" + hitSlop={10} + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={ + [MockFunction] { + "calls": [ + [], + ], + "results": [ + { + "type": "return", + "value": undefined, + }, + ], + } + } + rippleColor="#9EA2A8" + style={ + [ + { + "opacity": 1, + "padding": 2, + }, + { + "cursor": undefined, + }, + ] + } + testID="new-media-call-clear-selected-peer" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 16, + }, + [ + { + "lineHeight": 16, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </RNGestureHandlerButton> + </View> + </View> + <Text + style={ + { + "fontSize": 13, + "opacity": 0.6, + } + } + > + Long username variant + </Text> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "flexDirection": "row", + "flexShrink": 1, + "gap": 10, + "minHeight": 48, + "paddingHorizontal": 10, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <View + accessibilityLabel="this.is.a.very.long.username.for.storybook.preview's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 28, + "width": 28, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={28} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, + "uri": "https://open.rocket.chat/avatar/this.is.a.very.long.username.for.storybook.preview?format=png&size=56", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 28, + "width": 28, + } + } + transition={null} + width={28} + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "height": 20, + "textAlign": "center", + "textAlignVertical": "center", + "width": 20, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Long display name to validate text truncation behavior for SelectedPeer in narrow widths + </Text> + </View> + </View> + <RNGestureHandlerButton + accessibilityLabel="Remove" + accessibilityRole="button" + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + foreground={true} + handlerTag={6} + handlerType="NativeViewGestureHandler" + hitSlop={10} + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={ + [MockFunction] { + "calls": [ + [], + ], + "results": [ + { + "type": "return", + "value": undefined, + }, + ], + } + } + rippleColor="#9EA2A8" + style={ + [ + { + "opacity": 1, + "padding": 2, + }, + { + "cursor": undefined, + }, + ] + } + testID="new-media-call-clear-selected-peer" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 16, + }, + [ + { + "lineHeight": 16, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: LongUsername should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "gap": 12, + "padding": 16, + } + } +> + <Text + style={ + { + "fontSize": 13, + "opacity": 0.6, + } + } + > + Long username variant + </Text> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "flexDirection": "row", + "flexShrink": 1, + "gap": 10, + "minHeight": 48, + "paddingHorizontal": 10, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <View + accessibilityLabel="this.is.a.very.long.username.for.storybook.preview's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 28, + "width": 28, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={28} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, + "uri": "https://open.rocket.chat/avatar/this.is.a.very.long.username.for.storybook.preview?format=png&size=56", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 28, + "width": 28, + } + } + transition={null} + width={28} + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "height": 20, + "textAlign": "center", + "textAlignVertical": "center", + "width": 20, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Long display name to validate text truncation behavior for SelectedPeer in narrow widths + </Text> + </View> + </View> + <RNGestureHandlerButton + accessibilityLabel="Remove" + accessibilityRole="button" + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + foreground={true} + handlerTag={7} + handlerType="NativeViewGestureHandler" + hitSlop={10} + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={ + [MockFunction] { + "calls": [ + [], + ], + "results": [ + { + "type": "return", + "value": undefined, + }, + ], + } + } + rippleColor="#9EA2A8" + style={ + [ + { + "opacity": 1, + "padding": 2, + }, + { + "cursor": undefined, + }, + ] + } + testID="new-media-call-clear-selected-peer" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 16, + }, + [ + { + "lineHeight": 16, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: Sip should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "gap": 12, + "padding": 16, + } + } +> + <Text + style={ + { + "fontSize": 13, + "opacity": 0.6, + } + } + > + SIP variant + </Text> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "flexDirection": "row", + "flexShrink": 1, + "gap": 10, + "minHeight": 48, + "paddingHorizontal": 10, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + +55 11 99999-9999 + </Text> + </View> + </View> + <RNGestureHandlerButton + accessibilityLabel="Remove" + accessibilityRole="button" + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + foreground={true} + handlerTag={8} + handlerType="NativeViewGestureHandler" + hitSlop={10} + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={ + [MockFunction] { + "calls": [ + [], + ], + "results": [ + { + "type": "return", + "value": undefined, + }, + ], + } + } + rippleColor="#9EA2A8" + style={ + [ + { + "opacity": 1, + "padding": 2, + }, + { + "cursor": undefined, + }, + ] + } + testID="new-media-call-clear-selected-peer" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 16, + }, + [ + { + "lineHeight": 16, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: User should match snapshot 1`] = ` +<View + style={ + { + "flex": 1, + "gap": 12, + "padding": 16, + } + } +> + <Text + style={ + { + "fontSize": 13, + "opacity": 0.6, + } + } + > + User variant + </Text> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "flexDirection": "row", + "flexShrink": 1, + "gap": 10, + "minHeight": 48, + "paddingHorizontal": 10, + }, + { + "backgroundColor": "#E4E7EA", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <View + style={ + { + "alignItems": "center", + "width": 28, + } + } + > + <View + accessibilityLabel="alice.johnson's avatar" + accessible={true} + style={ + [ + { + "borderRadius": 4, + "height": 28, + "width": 28, + }, + undefined, + ] + } + testID="avatar" + > + <ViewManagerAdapter_ExpoImage + borderRadius={4} + containerViewRef={"[React.ref]"} + contentFit="cover" + contentPosition={ + { + "left": "50%", + "top": "50%", + } + } + height={28} + nativeViewRef={"[React.ref]"} + onError={[Function]} + onLoad={[Function]} + onLoadStart={[Function]} + onProgress={[Function]} + placeholder={[]} + priority="high" + source={ + [ + { + "headers": { + "User-Agent": "RC Mobile; ios unknown; vunknown (unknown)", + }, + "uri": "https://open.rocket.chat/avatar/alice.johnson?format=png&size=56", + }, + ] + } + style={ + { + "borderRadius": 4, + "height": 28, + "width": 28, + } + } + transition={null} + width={28} + /> + </View> + </View> + <View + style={ + { + "alignItems": "center", + "flexDirection": "row", + "flexShrink": 1, + "gap": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + [ + { + "height": 20, + "textAlign": "center", + "textAlignVertical": "center", + "width": 20, + }, + undefined, + ], + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + <Text + numberOfLines={1} + style={ + [ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontSize": 18, + "fontWeight": "500", + "lineHeight": 26, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + Alice Johnson + </Text> + </View> + </View> + <RNGestureHandlerButton + accessibilityLabel="Remove" + accessibilityRole="button" + activeOpacity={0.3} + borderless={true} + collapsable={false} + delayLongPress={600} + foreground={true} + handlerTag={9} + handlerType="NativeViewGestureHandler" + hitSlop={10} + innerRef={null} + onActiveStateChange={[Function]} + onGestureHandlerEvent={[Function]} + onGestureHandlerStateChange={[Function]} + onPress={ + [MockFunction] { + "calls": [ + [], + ], + "results": [ + { + "type": "return", + "value": undefined, + }, + ], + } + } + rippleColor="#9EA2A8" + style={ + [ + { + "opacity": 1, + "padding": 2, + }, + { + "cursor": undefined, + }, + ] + } + testID="new-media-call-clear-selected-peer" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#1F2329", + "fontSize": 16, + }, + [ + { + "lineHeight": 16, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </RNGestureHandlerButton> + </View> + </View> +</View> +`; diff --git a/app/containers/NewMediaCall/index.tsx b/app/containers/NewMediaCall/index.tsx new file mode 100644 index 00000000000..1c1029bbf48 --- /dev/null +++ b/app/containers/NewMediaCall/index.tsx @@ -0,0 +1 @@ +export * from './NewMediaCall'; diff --git a/app/containers/RoomHeader/__snapshots__/RoomHeader.test.tsx.snap b/app/containers/RoomHeader/__snapshots__/RoomHeader.test.tsx.snap index 089fa4625c8..efcdbeefd5d 100644 --- a/app/containers/RoomHeader/__snapshots__/RoomHeader.test.tsx.snap +++ b/app/containers/RoomHeader/__snapshots__/RoomHeader.test.tsx.snap @@ -2142,7 +2142,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", "lineHeight": undefined, }, { diff --git a/app/containers/RoomItem/__snapshots__/RoomItem.test.tsx.snap b/app/containers/RoomItem/__snapshots__/RoomItem.test.tsx.snap index 971e7b8dc59..3cc914b4690 100644 --- a/app/containers/RoomItem/__snapshots__/RoomItem.test.tsx.snap +++ b/app/containers/RoomItem/__snapshots__/RoomItem.test.tsx.snap @@ -30023,6 +30023,7 @@ exports[`Story Snapshots: Type should match snapshot 1`] = ` [ { "height": 22, + "textAlign": "center", "textAlignVertical": "center", "width": 22, }, @@ -35642,6 +35643,7 @@ exports[`Story Snapshots: User should match snapshot 1`] = ` [ { "height": 22, + "textAlign": "center", "textAlignVertical": "center", "width": 22, }, @@ -36272,6 +36274,7 @@ exports[`Story Snapshots: User should match snapshot 1`] = ` [ { "height": 22, + "textAlign": "center", "textAlignVertical": "center", "width": 22, }, diff --git a/app/containers/RoomTypeIcon/__snapshots__/RoomTypeIcon.test.tsx.snap b/app/containers/RoomTypeIcon/__snapshots__/RoomTypeIcon.test.tsx.snap index d3f054edc7a..2852f4ea73c 100644 --- a/app/containers/RoomTypeIcon/__snapshots__/RoomTypeIcon.test.tsx.snap +++ b/app/containers/RoomTypeIcon/__snapshots__/RoomTypeIcon.test.tsx.snap @@ -18,6 +18,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 30, + "textAlign": "center", "textAlignVertical": "center", "width": 30, }, @@ -56,6 +57,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 30, + "textAlign": "center", "textAlignVertical": "center", "width": 30, }, diff --git a/app/containers/Status/Status.tsx b/app/containers/Status/Status.tsx index cb85da5e68f..bd479e6e84c 100644 --- a/app/containers/Status/Status.tsx +++ b/app/containers/Status/Status.tsx @@ -20,7 +20,8 @@ const Status = React.memo(({ style, status = 'offline', size = 32, ...props }: I { width: size * fontScale, height: size * fontScale, - textAlignVertical: 'center' + textAlignVertical: 'center', + textAlign: 'center' }, style ]; diff --git a/app/containers/Status/__snapshots__/Status.test.tsx.snap b/app/containers/Status/__snapshots__/Status.test.tsx.snap index e49ab566e73..85198cb740f 100644 --- a/app/containers/Status/__snapshots__/Status.test.tsx.snap +++ b/app/containers/Status/__snapshots__/Status.test.tsx.snap @@ -18,6 +18,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 32, + "textAlign": "center", "textAlignVertical": "center", "width": 32, }, @@ -51,6 +52,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 32, + "textAlign": "center", "textAlignVertical": "center", "width": 32, }, @@ -84,6 +86,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 32, + "textAlign": "center", "textAlignVertical": "center", "width": 32, }, @@ -117,6 +120,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 32, + "textAlign": "center", "textAlignVertical": "center", "width": 32, }, @@ -150,6 +154,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 32, + "textAlign": "center", "textAlignVertical": "center", "width": 32, }, @@ -183,6 +188,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 32, + "textAlign": "center", "textAlignVertical": "center", "width": 32, }, @@ -216,6 +222,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 32, + "textAlign": "center", "textAlignVertical": "center", "width": 32, }, @@ -249,6 +256,7 @@ exports[`Story Snapshots: All should match snapshot 1`] = ` [ { "height": 60, + "textAlign": "center", "textAlignVertical": "center", "width": 60, }, diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index 34fdb91f4e3..7ca335bb0e4 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -329,6 +329,7 @@ "Enter_E2EE_Password_description": "Enter your E2EE password to view and send encrypted messages.\n\nPassword need to be entered on each device.", "Enter_manually": "Enter manually", "Enter_the_code": "Enter the code we just emailed you.", + "Enter_username_or_number": "Enter username or number", "Error_Download_file": "Error while downloading file", "Error_incorrect_password": "Incorrect password", "Error_play_video": "There was an error while playing this video", @@ -573,6 +574,7 @@ "Name_required": "Name required", "Never": "Never", "New_chat_transfer": "New chat transfer: {{agent}} returned the chat to the queue", + "New_call": "New call", "New_Message": "New message", "New_Password": "New password", "Next": "Next", diff --git a/app/lib/constants/colors.ts b/app/lib/constants/colors.ts index 2db1dbc6807..b36fe19de57 100644 --- a/app/lib/constants/colors.ts +++ b/app/lib/constants/colors.ts @@ -120,7 +120,7 @@ const dark = { fontAnnotation: '#9EA2A8', fontHint: '#9EA2A8', fontSecondaryInfo: '#9EA2A8', - fontDefault: '#E4E7EA', + fontDefault: '#C1C7D0', fontTitlesLabels: '#F2F3F5', fontInfo: '#739EDE', fontDanger: '#CF6E7A', diff --git a/app/lib/constants/defaultSettings.ts b/app/lib/constants/defaultSettings.ts index be63b56c559..d137e23905b 100644 --- a/app/lib/constants/defaultSettings.ts +++ b/app/lib/constants/defaultSettings.ts @@ -312,5 +312,8 @@ export const defaultSettings = { VoIP_TeamCollab_Ice_Gathering_Timeout: { type: 'valueAsNumber' }, + VoIP_TeamCollab_SIP_Integration_For_Internal_Calls: { + type: 'valueAsBoolean' + }, ...deprecatedSettings } as const; diff --git a/app/lib/hooks/useNewMediaCall/index.ts b/app/lib/hooks/useNewMediaCall/index.ts new file mode 100644 index 00000000000..c34af4de557 --- /dev/null +++ b/app/lib/hooks/useNewMediaCall/index.ts @@ -0,0 +1 @@ +export * from './useNewMediaCall'; diff --git a/app/lib/hooks/useNewMediaCall/useNewMediaCall.test.tsx b/app/lib/hooks/useNewMediaCall/useNewMediaCall.test.tsx new file mode 100644 index 00000000000..aa49510bd8a --- /dev/null +++ b/app/lib/hooks/useNewMediaCall/useNewMediaCall.test.tsx @@ -0,0 +1,106 @@ +import { act, renderHook } from '@testing-library/react-native'; +import React from 'react'; + +import { NewMediaCall } from '../../../containers/NewMediaCall'; +import { useNewMediaCall } from './useNewMediaCall'; + +const mockUseSubscription = jest.fn(); +const mockUseMediaCallPermission = jest.fn(); +const mockShowActionSheetRef = jest.fn(); +const mockGetUidDirectMessage = jest.fn(); +const mockSetSelectedPeer = jest.fn(); +const mockGetState = jest.fn(() => ({ + setSelectedPeer: mockSetSelectedPeer +})); + +jest.mock('../useSubscription', () => ({ + useSubscription: (rid?: string) => mockUseSubscription(rid) +})); + +jest.mock('../useMediaCallPermission', () => ({ + useMediaCallPermission: () => mockUseMediaCallPermission() +})); + +jest.mock('../../../containers/ActionSheet', () => ({ + showActionSheetRef: (params: unknown) => mockShowActionSheetRef(params) +})); + +jest.mock('../../methods/helpers/helpers', () => ({ + getUidDirectMessage: (room: unknown) => mockGetUidDirectMessage(room) +})); + +jest.mock('../../services/voip/usePeerAutocompleteStore', () => ({ + usePeerAutocompleteStore: { + getState: () => mockGetState() + } +})); + +jest.mock('../../../containers/NewMediaCall', () => ({ + NewMediaCall: jest.fn(() => null) +})); + +describe('useNewMediaCall', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + const expectNewMediaCallActionSheet = () => { + expect(mockShowActionSheetRef).toHaveBeenCalledTimes(1); + const [actionSheetArgs] = mockShowActionSheetRef.mock.calls[0]; + expect(React.isValidElement(actionSheetArgs.children)).toBe(true); + expect(actionSheetArgs.children.type).toBe(NewMediaCall); + }; + + it('should set selected peer and open action sheet when room has a direct message peer', () => { + const room = { name: 'Alice' }; + mockUseSubscription.mockReturnValue(room); + mockUseMediaCallPermission.mockReturnValue(true); + mockGetUidDirectMessage.mockReturnValue('user-id'); + + const { result } = renderHook(() => useNewMediaCall('room-id')); + + act(() => { + result.current.openNewMediaCall(); + }); + + expect(mockGetUidDirectMessage).toHaveBeenCalledWith(room); + expect(mockSetSelectedPeer).toHaveBeenCalledWith({ + type: 'user', + value: 'user-id', + label: 'Alice' + }); + expectNewMediaCallActionSheet(); + }); + + it('should open action sheet without setting selected peer when room has no direct message peer', () => { + const room = { name: 'Alice' }; + mockUseSubscription.mockReturnValue(room); + mockUseMediaCallPermission.mockReturnValue(true); + mockGetUidDirectMessage.mockReturnValue(undefined); + + const { result } = renderHook(() => useNewMediaCall('room-id')); + + act(() => { + result.current.openNewMediaCall(); + }); + + expect(mockGetUidDirectMessage).toHaveBeenCalledWith(room); + expect(mockSetSelectedPeer).not.toHaveBeenCalled(); + expectNewMediaCallActionSheet(); + }); + + it('should open action sheet without resolving direct message peer when room is missing', () => { + mockUseSubscription.mockReturnValue(undefined); + mockUseMediaCallPermission.mockReturnValue(false); + + const { result } = renderHook(() => useNewMediaCall('room-id')); + + act(() => { + result.current.openNewMediaCall(); + }); + + expect(mockGetUidDirectMessage).not.toHaveBeenCalled(); + expect(mockSetSelectedPeer).not.toHaveBeenCalled(); + expectNewMediaCallActionSheet(); + }); +}); diff --git a/app/lib/hooks/useNewMediaCall/useNewMediaCall.tsx b/app/lib/hooks/useNewMediaCall/useNewMediaCall.tsx new file mode 100644 index 00000000000..abc96721cb8 --- /dev/null +++ b/app/lib/hooks/useNewMediaCall/useNewMediaCall.tsx @@ -0,0 +1,27 @@ +import React from 'react'; + +import { NewMediaCall } from '../../../containers/NewMediaCall'; +import { showActionSheetRef } from '../../../containers/ActionSheet'; +import { getUidDirectMessage } from '../../methods/helpers/helpers'; +import { usePeerAutocompleteStore } from '../../services/voip/usePeerAutocompleteStore'; +import { useSubscription } from '../useSubscription'; +import { useMediaCallPermission } from '../useMediaCallPermission'; + +export const useNewMediaCall = (rid?: string) => { + const room = useSubscription(rid); + const hasMediaCallPermission = useMediaCallPermission(); + + const openNewMediaCall = () => { + if (room) { + const otherUserId = getUidDirectMessage(room); + if (otherUserId) { + usePeerAutocompleteStore.getState().setSelectedPeer({ type: 'user', value: otherUserId, label: room.name }); + } + } + showActionSheetRef({ + children: <NewMediaCall /> + }); + }; + + return { openNewMediaCall, hasMediaCallPermission }; +}; diff --git a/app/lib/hooks/useSubscription.test.ts b/app/lib/hooks/useSubscription.test.ts new file mode 100644 index 00000000000..4d93b1a6164 --- /dev/null +++ b/app/lib/hooks/useSubscription.test.ts @@ -0,0 +1,109 @@ +import { act, renderHook, waitFor } from '@testing-library/react-native'; + +import { useSubscription } from './useSubscription'; +import { getSubscriptionByRoomId } from '../database/services/Subscription'; + +jest.mock('../database/services/Subscription', () => ({ + getSubscriptionByRoomId: jest.fn() +})); + +const mockedGetSubscriptionByRoomId = jest.mocked(getSubscriptionByRoomId); + +const createDeferred = <T,>() => { + let resolve!: (value: T) => void; + const promise = new Promise<T>(res => { + resolve = res; + }); + + return { promise, resolve }; +}; + +describe('useSubscription', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return undefined and skip loading when rid is missing', () => { + const { result } = renderHook(() => useSubscription()); + + expect(result.current).toBeUndefined(); + expect(mockedGetSubscriptionByRoomId).not.toHaveBeenCalled(); + }); + + it('should load subscription for the provided rid', async () => { + const subscription = { id: 'sub-1', rid: 'room-1' } as any; + mockedGetSubscriptionByRoomId.mockResolvedValue(subscription); + + const { result } = renderHook(() => useSubscription('room-1')); + + await waitFor(() => expect(result.current).toBe(subscription)); + expect(mockedGetSubscriptionByRoomId).toHaveBeenCalledWith('room-1'); + }); + + it('should keep the current subscription while loading the next rid', async () => { + const firstSubscription = { id: 'sub-1', rid: 'room-1' } as any; + const secondSubscription = { id: 'sub-2', rid: 'room-2' } as any; + const secondRequest = createDeferred<typeof secondSubscription | null>(); + + mockedGetSubscriptionByRoomId + .mockResolvedValueOnce(firstSubscription) + .mockImplementationOnce(() => secondRequest.promise); + + const { result, rerender } = renderHook(({ rid }: { rid?: string }) => useSubscription(rid), { + initialProps: { rid: 'room-1' } + }); + + await waitFor(() => expect(result.current).toBe(firstSubscription)); + + rerender({ rid: 'room-2' }); + + expect(result.current).toBe(firstSubscription); + + await act(async () => { + secondRequest.resolve(secondSubscription); + await secondRequest.promise; + }); + + await waitFor(() => expect(result.current).toBe(secondSubscription)); + }); + + it('should return undefined when the lookup does not find a subscription', async () => { + mockedGetSubscriptionByRoomId.mockResolvedValue(null); + + const { result } = renderHook(() => useSubscription('room-1')); + + await waitFor(() => expect(mockedGetSubscriptionByRoomId).toHaveBeenCalledWith('room-1')); + expect(result.current).toBeUndefined(); + }); + + it('should ignore stale requests when rid changes', async () => { + const firstSubscription = { id: 'sub-1', rid: 'room-1' } as any; + const secondSubscription = { id: 'sub-2', rid: 'room-2' } as any; + const firstRequest = createDeferred<typeof firstSubscription | null>(); + const secondRequest = createDeferred<typeof secondSubscription | null>(); + + mockedGetSubscriptionByRoomId + .mockImplementationOnce(() => firstRequest.promise) + .mockImplementationOnce(() => secondRequest.promise); + + const { result, rerender } = renderHook(({ rid }: { rid?: string }) => useSubscription(rid), { + initialProps: { rid: 'room-1' } + }); + + rerender({ rid: 'room-2' }); + + await act(async () => { + firstRequest.resolve(firstSubscription); + await firstRequest.promise; + }); + + expect(result.current).toBeUndefined(); + + await act(async () => { + secondRequest.resolve(secondSubscription); + await secondRequest.promise; + }); + + await waitFor(() => expect(result.current).toBe(secondSubscription)); + }); +}); diff --git a/app/lib/hooks/useSubscription.ts b/app/lib/hooks/useSubscription.ts new file mode 100644 index 00000000000..c48683eee31 --- /dev/null +++ b/app/lib/hooks/useSubscription.ts @@ -0,0 +1,28 @@ +import { useEffect, useState } from 'react'; + +import { type TSubscriptionModel } from '../../definitions'; +import { getSubscriptionByRoomId } from '../database/services/Subscription'; + +export const useSubscription = (rid?: string): TSubscriptionModel | undefined => { + 'use memo'; + + const [subscription, setSubscription] = useState<TSubscriptionModel>(); + useEffect(() => { + let isActive = true; + + const load = async () => { + if (!rid) return; + const result = await getSubscriptionByRoomId(rid); + if (isActive) { + setSubscription(result ?? undefined); + } + }; + load(); + + return () => { + isActive = false; + }; + }, [rid]); + + return subscription; +}; diff --git a/app/lib/services/voip/getPeerAutocompleteOptions.ts b/app/lib/services/voip/getPeerAutocompleteOptions.ts new file mode 100644 index 00000000000..e54d2c78efc --- /dev/null +++ b/app/lib/services/voip/getPeerAutocompleteOptions.ts @@ -0,0 +1,91 @@ +import { usersAutoComplete } from '../restApi'; +import { store as reduxStore } from '../../store/auxStore'; + +export type TPeerItem = + | { type: 'user'; value: string; label: string; username?: string; callerId?: string } + | { type: 'sip'; value: string; label: string }; + +type TUserAutocompleteResponse = { + success?: boolean; + items?: Array<{ + _id: string; + name?: string; + username?: string; + freeSwitchExtension?: string; + }>; +}; + +const getExtensionFromPeerInfo = (peerInfo?: TPeerItem | null): string | undefined => { + if (!peerInfo || !('callerId' in peerInfo)) { + return undefined; + } + + return peerInfo.callerId; +}; + +const getPeerUsername = (peerInfo?: TPeerItem | null): string | undefined => { + if (!peerInfo || !('username' in peerInfo)) { + return undefined; + } + + return peerInfo.username; +}; + +// TODO: hook? +export const getPeerAutocompleteOptions = async ({ + filter, + peerInfo +}: { + filter: string; + peerInfo?: TPeerItem | null; +}): Promise<TPeerItem[]> => { + const term = filter.trim(); + if (!term) { + return []; + } + + const currentUsername = reduxStore.getState().login.user.username as string | undefined; + const peerUsername = getPeerUsername(peerInfo); + const peerExtension = getExtensionFromPeerInfo(peerInfo); + const forceSIPRouting = Boolean(reduxStore.getState().settings.VoIP_TeamCollab_SIP_Integration_For_Internal_Calls); + + const conditions = + peerExtension || forceSIPRouting + ? { + $and: [ + forceSIPRouting ? { freeSwitchExtension: { $exists: true } } : null, + peerExtension ? { freeSwitchExtension: { $ne: peerExtension } } : null + ].filter(Boolean) + } + : undefined; + + const exceptions = [currentUsername, peerUsername].filter(Boolean); + const selector = { + term, + exceptions, + ...(conditions && { conditions }) + }; + + const response = (await usersAutoComplete(selector)) as TUserAutocompleteResponse; + const canUseItems = response?.success ?? true; + + const userOptions: TPeerItem[] = canUseItems + ? (response?.items || []) + .filter(item => !!item?._id && !!(item.name || item.username)) + .map(item => ({ + type: 'user', + value: item._id, + label: item.name || item.username || '', + username: item.username, + callerId: item.freeSwitchExtension + })) + : []; + + const sipOption: TPeerItem = { + type: 'sip', + value: term, + label: term + }; + + return [sipOption, ...userOptions]; +}; diff --git a/app/lib/services/voip/usePeerAutocompleteStore.test.ts b/app/lib/services/voip/usePeerAutocompleteStore.test.ts new file mode 100644 index 00000000000..b0e2e6e01bd --- /dev/null +++ b/app/lib/services/voip/usePeerAutocompleteStore.test.ts @@ -0,0 +1,150 @@ +import { renderHook, act } from '@testing-library/react-native'; + +import { usePeerAutocompleteStore } from './usePeerAutocompleteStore'; +import type { TPeerItem } from './getPeerAutocompleteOptions'; + +const mockGetPeerAutocompleteOptions = jest.fn(); + +jest.mock('./getPeerAutocompleteOptions', () => ({ + getPeerAutocompleteOptions: (args: unknown) => mockGetPeerAutocompleteOptions(args) +})); + +const userPeer: TPeerItem = { + type: 'user', + value: 'user-1', + label: 'Alice Johnson', + username: 'alice.johnson' +}; + +const mockOptions: TPeerItem[] = [ + userPeer, + { + type: 'sip', + value: '+5511999999999', + label: '+55 11 99999-9999' + } +]; + +describe('usePeerAutocompleteStore', () => { + beforeEach(() => { + jest.clearAllMocks(); + usePeerAutocompleteStore.setState({ + options: [], + selectedPeer: null, + filter: '' + }); + mockGetPeerAutocompleteOptions.mockResolvedValue(mockOptions); + }); + + describe('setSelectedPeer', () => { + it('should set selected peer', () => { + const { result } = renderHook(() => usePeerAutocompleteStore()); + + act(() => { + result.current.setSelectedPeer(userPeer); + }); + + expect(usePeerAutocompleteStore.getState().selectedPeer).toEqual(userPeer); + }); + + it('should clear selected peer when null is passed', () => { + usePeerAutocompleteStore.setState({ selectedPeer: userPeer }); + const { result } = renderHook(() => usePeerAutocompleteStore()); + + act(() => { + result.current.setSelectedPeer(null); + }); + + expect(usePeerAutocompleteStore.getState().selectedPeer).toBeNull(); + }); + }); + + describe('setFilter', () => { + it('should set filter value', () => { + const { result } = renderHook(() => usePeerAutocompleteStore()); + + act(() => { + result.current.setFilter('alice'); + }); + + expect(usePeerAutocompleteStore.getState().filter).toBe('alice'); + }); + }); + + describe('clearSelection', () => { + it('should clear selected peer', () => { + usePeerAutocompleteStore.setState({ selectedPeer: userPeer }); + const { result } = renderHook(() => usePeerAutocompleteStore()); + + act(() => { + result.current.clearSelection(); + }); + + expect(usePeerAutocompleteStore.getState().selectedPeer).toBeNull(); + }); + }); + + describe('fetchOptions', () => { + it('should set empty options when filter is empty', async () => { + const { result } = renderHook(() => usePeerAutocompleteStore()); + + await act(async () => { + await result.current.fetchOptions(''); + }); + + expect(usePeerAutocompleteStore.getState().options).toEqual([]); + expect(mockGetPeerAutocompleteOptions).not.toHaveBeenCalled(); + }); + + it('should set empty options when filter is only whitespace', async () => { + const { result } = renderHook(() => usePeerAutocompleteStore()); + + await act(async () => { + await result.current.fetchOptions(' '); + }); + + expect(usePeerAutocompleteStore.getState().options).toEqual([]); + expect(mockGetPeerAutocompleteOptions).not.toHaveBeenCalled(); + }); + + it('should fetch and set options when filter has value', async () => { + const { result } = renderHook(() => usePeerAutocompleteStore()); + + await act(async () => { + await result.current.fetchOptions('alice'); + }); + + expect(mockGetPeerAutocompleteOptions).toHaveBeenCalledWith({ + filter: 'alice', + peerInfo: null + }); + expect(usePeerAutocompleteStore.getState().options).toEqual(mockOptions); + }); + + it('should pass selected peer to getPeerAutocompleteOptions', async () => { + usePeerAutocompleteStore.setState({ selectedPeer: userPeer }); + const { result } = renderHook(() => usePeerAutocompleteStore()); + + await act(async () => { + await result.current.fetchOptions('bob'); + }); + + expect(mockGetPeerAutocompleteOptions).toHaveBeenCalledWith({ + filter: 'bob', + peerInfo: userPeer + }); + }); + + it('should set empty options on fetch error', async () => { + mockGetPeerAutocompleteOptions.mockRejectedValue(new Error('API error')); + + const { result } = renderHook(() => usePeerAutocompleteStore()); + + await act(async () => { + await result.current.fetchOptions('alice'); + }); + + expect(usePeerAutocompleteStore.getState().options).toEqual([]); + }); + }); +}); diff --git a/app/lib/services/voip/usePeerAutocompleteStore.ts b/app/lib/services/voip/usePeerAutocompleteStore.ts new file mode 100644 index 00000000000..e34ead9f56d --- /dev/null +++ b/app/lib/services/voip/usePeerAutocompleteStore.ts @@ -0,0 +1,61 @@ +import { create } from 'zustand'; + +import { getPeerAutocompleteOptions, type TPeerItem } from './getPeerAutocompleteOptions'; + +type TPeerAutocompleteState = { + options: TPeerItem[]; + selectedPeer: TPeerItem | null; + filter: string; +}; + +type TPeerAutocompleteActions = { + fetchOptions: (filter: string) => Promise<void>; + setSelectedPeer: (peer: TPeerItem | null) => void; + setFilter: (filter: string) => void; + clearSelection: () => void; + reset: () => void; +}; + +export type TPeerAutocompleteStore = TPeerAutocompleteState & TPeerAutocompleteActions; + +export const usePeerAutocompleteStore = create<TPeerAutocompleteStore>((set, get) => ({ + options: [], + selectedPeer: null, + filter: '', + + fetchOptions: async (filter: string) => { + const term = filter.trim(); + if (!term) { + set({ options: [] }); + return; + } + + try { + const currentPeer = get().selectedPeer; + const options = await getPeerAutocompleteOptions({ + filter: term, + peerInfo: currentPeer + }); + + set({ options }); + } catch { + set({ options: [] }); + } + }, + + setSelectedPeer: (peer: TPeerItem | null) => { + set({ selectedPeer: peer, filter: '', options: [] }); + }, + + setFilter: (filter: string) => { + set({ filter }); + }, + + clearSelection: () => { + set({ selectedPeer: null }); + }, + + reset: () => { + set({ options: [], selectedPeer: null, filter: '' }); + } +})); diff --git a/app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap b/app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap index dcca4852073..8bf4dd5d733 100644 --- a/app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap +++ b/app/views/DiscussionsView/__snapshots__/Item.test.tsx.snap @@ -2237,7 +2237,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", "lineHeight": undefined, }, { diff --git a/app/views/NewMessageView/Item.test.tsx b/app/views/NewMessageView/Item.test.tsx index 737968e9b34..11e834246f7 100644 --- a/app/views/NewMessageView/Item.test.tsx +++ b/app/views/NewMessageView/Item.test.tsx @@ -7,12 +7,20 @@ import { mockedStore } from '../../reducers/mockedStore'; import { setUser } from '../../actions/login'; import * as stories from './Item.stories'; import { generateSnapshots } from '../../../.rnstorybook/generateSnapshots'; +import { NewMediaCall } from '../../containers/NewMediaCall'; -const mockStartCall = jest.fn(); +const mockShowActionSheetRef = jest.fn(); +const mockSetSelectedPeer = jest.fn(); -jest.mock('../../lib/services/voip/MediaSessionInstance', () => ({ - mediaSessionInstance: { - startCall: (userId: string, actor: string) => mockStartCall(userId, actor) +jest.mock('../../containers/ActionSheet', () => ({ + showActionSheetRef: (params: unknown) => mockShowActionSheetRef(params) +})); + +jest.mock('../../lib/services/voip/usePeerAutocompleteStore', () => ({ + usePeerAutocompleteStore: { + getState: () => ({ + setSelectedPeer: mockSetSelectedPeer + }) } })); @@ -22,6 +30,10 @@ jest.mock('../../lib/hooks/useMediaCallPermission', () => ({ useMediaCallPermission: () => mockUseMediaCallPermission() })); +jest.mock('../../containers/NewMediaCall', () => ({ + NewMediaCall: jest.fn(() => null) +})); + const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; describe('NewMessageView Item', () => { @@ -84,7 +96,7 @@ describe('NewMessageView Item', () => { expect(onLongPressMock).toHaveBeenCalledTimes(1); }); - it('should render call button and call startCall when hasMediaCallPermission is true', () => { + it('should render call button and open new media call flow when hasMediaCallPermission is true', () => { mockUseMediaCallPermission.mockReturnValue(true); const { getByTestId } = render( <Wrapper> @@ -92,8 +104,17 @@ describe('NewMessageView Item', () => { </Wrapper> ); fireEvent.press(getByTestId('new-message-view-item-john.doe-call')); - expect(mockStartCall).toHaveBeenCalledTimes(1); - expect(mockStartCall).toHaveBeenCalledWith('user123', 'user'); + expect(mockSetSelectedPeer).toHaveBeenCalledTimes(1); + expect(mockSetSelectedPeer).toHaveBeenCalledWith({ + type: 'user', + value: 'user123', + username: 'john.doe', + label: 'John Doe' + }); + expect(mockShowActionSheetRef).toHaveBeenCalledTimes(1); + const [actionSheetArgs] = mockShowActionSheetRef.mock.calls[0]; + expect(React.isValidElement(actionSheetArgs.children)).toBe(true); + expect(actionSheetArgs.children.type).toBe(NewMediaCall); }); it('should not render call button when hasMediaCallPermission is false', () => { @@ -106,7 +127,7 @@ describe('NewMessageView Item', () => { expect(queryByTestId('new-message-view-item-john.doe-call')).toBeNull(); }); - it('should not call startCall when userId is falsy and call button is pressed', () => { + it('should not open call flow when userId is falsy and call button is pressed', () => { mockUseMediaCallPermission.mockReturnValue(true); const { getByTestId } = render( <Wrapper> @@ -114,7 +135,8 @@ describe('NewMessageView Item', () => { </Wrapper> ); fireEvent.press(getByTestId('new-message-view-item-john.doe-call')); - expect(mockStartCall).not.toHaveBeenCalled(); + expect(mockSetSelectedPeer).not.toHaveBeenCalled(); + expect(mockShowActionSheetRef).not.toHaveBeenCalled(); }); it('should have correct accessibility label', () => { diff --git a/app/views/NewMessageView/Item.tsx b/app/views/NewMessageView/Item.tsx index 0228b22b7d0..7af100e119e 100644 --- a/app/views/NewMessageView/Item.tsx +++ b/app/views/NewMessageView/Item.tsx @@ -6,37 +6,11 @@ import Avatar from '../../containers/Avatar'; import { CustomIcon } from '../../containers/CustomIcon'; import sharedStyles from '../Styles'; import { useTheme } from '../../theme'; -import { mediaSessionInstance } from '../../lib/services/voip/MediaSessionInstance'; import I18n from '../../i18n'; import { useMediaCallPermission } from '../../lib/hooks/useMediaCallPermission'; - -const styles = StyleSheet.create({ - button: { - height: 54 - }, - container: { - flexDirection: 'row' - }, - avatar: { - marginHorizontal: 12, - marginVertical: 12 - }, - textContainer: { - flex: 1, - flexDirection: 'column', - justifyContent: 'center', - marginRight: 12 - }, - name: { - fontSize: 18, - lineHeight: 26, - ...sharedStyles.textMedium - }, - iconContainer: { - paddingHorizontal: 15, - alignSelf: 'center' - } -}); +import { usePeerAutocompleteStore } from '../../lib/services/voip/usePeerAutocompleteStore'; +import { showActionSheetRef } from '../../containers/ActionSheet'; +import { NewMediaCall } from '../../containers/NewMediaCall'; interface IItem { userId: string; @@ -53,7 +27,10 @@ const Item = ({ userId, name, username, onPress, testID, onLongPress }: IItem) = const handleCallPress = () => { if (!userId) return; - mediaSessionInstance.startCall(userId, 'user'); + usePeerAutocompleteStore.getState().setSelectedPeer({ type: 'user', value: userId, label: name, username }); + showActionSheetRef({ + children: <NewMediaCall /> + }); }; return ( @@ -90,3 +67,31 @@ const Item = ({ userId, name, username, onPress, testID, onLongPress }: IItem) = }; export default Item; + +const styles = StyleSheet.create({ + button: { + height: 54 + }, + container: { + flexDirection: 'row' + }, + avatar: { + marginHorizontal: 12, + marginVertical: 12 + }, + textContainer: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + marginRight: 12 + }, + name: { + fontSize: 18, + lineHeight: 26, + ...sharedStyles.textMedium + }, + iconContainer: { + paddingHorizontal: 15, + alignSelf: 'center' + } +}); diff --git a/app/views/RoomActionsView/components/CallSection.tsx b/app/views/RoomActionsView/components/CallSection.tsx index 4d0707a52d5..2d385e44b8a 100644 --- a/app/views/RoomActionsView/components/CallSection.tsx +++ b/app/views/RoomActionsView/components/CallSection.tsx @@ -2,9 +2,8 @@ import React from 'react'; import * as List from '../../../containers/List'; import { useVideoConf } from '../../../lib/hooks/useVideoConf'; -import { mediaSessionInstance } from '../../../lib/services/voip/MediaSessionInstance'; import type { TSubscriptionModel } from '../../../definitions'; -import { useMediaCallPermission } from '../../../lib/hooks/useMediaCallPermission'; +import { useNewMediaCall } from '../../../lib/hooks/useNewMediaCall'; export default function CallSection({ room, @@ -14,12 +13,7 @@ export default function CallSection({ disabled: boolean; }): React.ReactElement | null { const { callEnabled, showInitCallActionSheet, disabledTooltip } = useVideoConf(room.rid); - const hasMediaCallPermission = useMediaCallPermission(); - - const handleVoiceCallPress = () => { - if (!room) return; - mediaSessionInstance.startCallByRoom(room); - }; + const { openNewMediaCall, hasMediaCallPermission } = useNewMediaCall(room.rid); if (!hasMediaCallPermission && !callEnabled) { return null; @@ -32,7 +26,7 @@ export default function CallSection({ <> <List.Item title={'Voice_call'} - onPress={handleVoiceCallPress} + onPress={openNewMediaCall} testID='room-actions-voice-call' left={() => <List.Icon name='phone' />} showActionIndicator diff --git a/app/views/RoomInfoView/components/BaseButton.tsx b/app/views/RoomInfoView/components/BaseButton.tsx new file mode 100644 index 00000000000..7174012a8ab --- /dev/null +++ b/app/views/RoomInfoView/components/BaseButton.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { Text } from 'react-native'; +import { BorderlessButton } from 'react-native-gesture-handler'; + +import { CustomIcon, type TIconsName } from '../../../containers/CustomIcon'; +import { useTheme } from '../../../theme'; +import styles from '../styles'; + +export function BaseButton({ + danger, + iconName, + onPress, + label, + showIcon = true, + enabled = true +}: { + danger?: boolean; + iconName: TIconsName; + onPress?: (prop: any) => void; + label: string; + showIcon?: boolean; + enabled?: boolean; +}): React.ReactElement | null { + const { colors } = useTheme(); + const color = danger ? colors.buttonBackgroundDangerDefault : colors.fontHint; + + if (showIcon) + return ( + <BorderlessButton enabled={enabled} testID={`room-info-view-${iconName}`} onPress={onPress} style={styles.roomButton}> + <CustomIcon name={iconName} size={30} color={color} /> + <Text numberOfLines={1} style={[styles.roomButtonText, { color }]}> + {label} + </Text> + </BorderlessButton> + ); + return null; +} diff --git a/app/views/RoomInfoView/components/RoomInfoButtons.test.tsx b/app/views/RoomInfoView/components/RoomInfoButtons.test.tsx index 877f3e97eb3..00740c9171a 100644 --- a/app/views/RoomInfoView/components/RoomInfoButtons.test.tsx +++ b/app/views/RoomInfoView/components/RoomInfoButtons.test.tsx @@ -11,17 +11,18 @@ import { SubscriptionType } from '../../../definitions'; const mockShowInitCallActionSheet = jest.fn(); const mockShowActionSheet = jest.fn(); -const mockStartCallByRoom = jest.fn(); +const mockOpenNewMediaCall = jest.fn(); +const noopOpenNewMediaCall = () => undefined; const mockUseVideoConf = jest.fn(); -const mockUseMediaCallPermission = jest.fn(); +const mockUseNewMediaCall = jest.fn(); jest.mock('../../../lib/hooks/useVideoConf', () => ({ useVideoConf: (...args: unknown[]) => mockUseVideoConf(...args) })); -jest.mock('../../../lib/hooks/useMediaCallPermission', () => ({ - useMediaCallPermission: (...args: unknown[]) => mockUseMediaCallPermission(...args) +jest.mock('../../../lib/hooks/useNewMediaCall', () => ({ + useNewMediaCall: (...args: unknown[]) => mockUseNewMediaCall(...args) })); jest.mock('../hooks', () => ({ @@ -33,12 +34,6 @@ jest.mock('../../../containers/ActionSheet', () => ({ useActionSheet: () => ({ showActionSheet: mockShowActionSheet }) })); -jest.mock('../../../lib/services/voip/MediaSessionInstance', () => ({ - mediaSessionInstance: { - startCallByRoom: (room: ISubscription) => mockStartCallByRoom(room) - } -})); - const Wrapper = ({ children }: { children: React.ReactNode }) => <Provider store={mockedStore}>{children}</Provider>; const createMockRoom = (overrides: Partial<ISubscription> = {}): ISubscription => @@ -90,7 +85,10 @@ describe('RoomInfoButtons', () => { disabledTooltip: false, showInitCallActionSheet: mockShowInitCallActionSheet }); - mockUseMediaCallPermission.mockReturnValue(true); + mockUseNewMediaCall.mockReturnValue({ + openNewMediaCall: noopOpenNewMediaCall, + hasMediaCallPermission: true + }); }); it('should render Message button', () => { @@ -113,16 +111,18 @@ describe('RoomInfoButtons', () => { expect(handleCreateDirectMessage).toHaveBeenCalledTimes(1); }); - it('should call mediaSessionInstance.startCallByRoom when Voice call is pressed', () => { - const mockRoom = createMockRoom(); + it('should call openNewMediaCall when Voice call is pressed', () => { + mockUseNewMediaCall.mockReturnValue({ + openNewMediaCall: mockOpenNewMediaCall, + hasMediaCallPermission: true + }); const { getByTestId } = render( <Wrapper> - <RoomInfoButtons {...defaultProps} room={mockRoom} /> + <RoomInfoButtons {...defaultProps} /> </Wrapper> ); fireEvent.press(getByTestId('room-info-view-phone')); - expect(mockStartCallByRoom).toHaveBeenCalledTimes(1); - expect(mockStartCallByRoom).toHaveBeenCalledWith(mockRoom); + expect(mockOpenNewMediaCall).toHaveBeenCalledTimes(1); }); it('should call showInitCallActionSheet when Video call is pressed', () => { @@ -135,8 +135,11 @@ describe('RoomInfoButtons', () => { expect(mockShowInitCallActionSheet).toHaveBeenCalledTimes(1); }); - it('should not render Voice call when useMediaCallPermission returns false', () => { - mockUseMediaCallPermission.mockReturnValue(false); + it('should not render Voice call when hasMediaCallPermission is false', () => { + mockUseNewMediaCall.mockReturnValue({ + openNewMediaCall: noopOpenNewMediaCall, + hasMediaCallPermission: false + }); const { queryByTestId } = render( <Wrapper> <RoomInfoButtons {...defaultProps} /> diff --git a/app/views/RoomInfoView/components/RoomInfoButtons.tsx b/app/views/RoomInfoView/components/RoomInfoButtons.tsx index d04b966b9aa..33396816579 100644 --- a/app/views/RoomInfoView/components/RoomInfoButtons.tsx +++ b/app/views/RoomInfoView/components/RoomInfoButtons.tsx @@ -1,19 +1,17 @@ import React from 'react'; -import { Text, View } from 'react-native'; -import { BorderlessButton } from 'react-native-gesture-handler'; +import { View } from 'react-native'; -import { CustomIcon, type TIconsName } from '../../../containers/CustomIcon'; +import { type TIconsName } from '../../../containers/CustomIcon'; import { type ISubscription, SubscriptionType } from '../../../definitions'; import i18n from '../../../i18n'; import { useVideoConf } from '../../../lib/hooks/useVideoConf'; -import { useTheme } from '../../../theme'; import styles from '../styles'; import { compareServerVersion } from '../../../lib/methods/helpers'; import { useE2EEWarning } from '../hooks'; import { useActionSheet } from '../../../containers/ActionSheet'; import type { TActionSheetOptionsItem } from '../../../containers/ActionSheet'; -import { mediaSessionInstance } from '../../../lib/services/voip/MediaSessionInstance'; -import { useMediaCallPermission } from '../../../lib/hooks/useMediaCallPermission'; +import { BaseButton } from './BaseButton'; +import { useNewMediaCall } from '../../../lib/hooks/useNewMediaCall'; type ButtonConfig = { label: string; @@ -24,36 +22,6 @@ type ButtonConfig = { show: boolean; }; -function BaseButton({ - danger, - iconName, - onPress, - label, - showIcon = true, - enabled = true -}: { - danger?: boolean; - iconName: TIconsName; - onPress?: (prop: any) => void; - label: string; - showIcon?: boolean; - enabled?: boolean; -}): React.ReactElement | null { - const { colors } = useTheme(); - const color = danger ? colors.buttonBackgroundDangerDefault : colors.fontHint; - - if (showIcon) - return ( - <BorderlessButton enabled={enabled} testID={`room-info-view-${iconName}`} onPress={onPress} style={styles.roomButton}> - <CustomIcon name={iconName} size={30} color={color} /> - <Text numberOfLines={1} style={[styles.roomButtonText, { color }]}> - {label} - </Text> - </BorderlessButton> - ); - return null; -} - interface IRoomInfoButtons { rid: string; room: ISubscription | undefined; @@ -88,7 +56,7 @@ export const RoomInfoButtons = ({ const room = roomFromRid || roomFromProps; const { showActionSheet } = useActionSheet(); const { callEnabled, disabledTooltip, showInitCallActionSheet } = useVideoConf(rid); - const hasMediaCallPermission = useMediaCallPermission(); + const { openNewMediaCall, hasMediaCallPermission } = useNewMediaCall(rid); // Following the web behavior, when is a DM with myself, shouldn't appear block or ignore option const isDmWithMyself = room?.uids?.filter((uid: string) => uid !== roomUserId).length === 0; @@ -104,11 +72,6 @@ export const RoomInfoButtons = ({ !itsMe && isDirectFromSaved && !isDmWithMyself && compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '6.4.0'); const renderVideoCall = !hasE2EEWarning && callEnabled && !roomFromRid; - const handleVoiceCall = () => { - if (!room) return; - mediaSessionInstance.startCallByRoom(room); - }; - const allItems: ButtonConfig[] = [ { label: i18n.t('Message'), @@ -120,7 +83,7 @@ export const RoomInfoButtons = ({ { label: i18n.t('Voice_call'), iconName: 'phone', - onPress: handleVoiceCall, + onPress: openNewMediaCall, enabled: true, show: hasMediaCallPermission }, diff --git a/app/views/RoomInfoView/components/__snapshots__/RoomInfoABAC.test.tsx.snap b/app/views/RoomInfoView/components/__snapshots__/RoomInfoABAC.test.tsx.snap index 50b4c7d7237..d6ddfd9eef4 100644 --- a/app/views/RoomInfoView/components/__snapshots__/RoomInfoABAC.test.tsx.snap +++ b/app/views/RoomInfoView/components/__snapshots__/RoomInfoABAC.test.tsx.snap @@ -991,7 +991,7 @@ exports[`Story Snapshots: Dark should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 16, }, [ @@ -1089,7 +1089,7 @@ exports[`Story Snapshots: Dark should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -1244,7 +1244,7 @@ exports[`Story Snapshots: Dark should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 16, }, [ @@ -1342,7 +1342,7 @@ exports[`Story Snapshots: Dark should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -1739,7 +1739,7 @@ exports[`Story Snapshots: Dark should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } diff --git a/app/views/RoomView/LoadMore/__snapshots__/LoadMore.test.tsx.snap b/app/views/RoomView/LoadMore/__snapshots__/LoadMore.test.tsx.snap index 642a5d044af..d2bdb8a706a 100644 --- a/app/views/RoomView/LoadMore/__snapshots__/LoadMore.test.tsx.snap +++ b/app/views/RoomView/LoadMore/__snapshots__/LoadMore.test.tsx.snap @@ -2794,7 +2794,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -2820,7 +2820,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "lineHeight": 22, }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -2966,7 +2966,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -2992,7 +2992,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "lineHeight": 22, }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -3145,7 +3145,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -3171,7 +3171,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "lineHeight": 22, }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -3680,7 +3680,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -3706,7 +3706,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "lineHeight": 22, }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -3852,7 +3852,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -3878,7 +3878,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "lineHeight": 22, }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -4031,7 +4031,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -4057,7 +4057,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "lineHeight": 22, }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -4400,7 +4400,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } @@ -4426,7 +4426,7 @@ exports[`Story Snapshots: DarkTheme should match snapshot 1`] = ` "lineHeight": 22, }, { - "color": "#E4E7EA", + "color": "#C1C7D0", }, ] } diff --git a/app/views/RoomView/RightButtons.tsx b/app/views/RoomView/RightButtons.tsx index a389453ff6b..2ad9a83367e 100644 --- a/app/views/RoomView/RightButtons.tsx +++ b/app/views/RoomView/RightButtons.tsx @@ -528,7 +528,6 @@ class RightButtonsContainer extends Component<IRightButtonsProps, IRigthButtonsS accessibilityLabel={i18n.t('Call_room_name', { roomName: accessibilityRoomName })} rid={rid} disabled={hasE2EEWarning} - room={this.room} /> {threadsEnabled ? ( <HeaderButton.Item diff --git a/app/views/RoomView/components/HeaderCallButton.tsx b/app/views/RoomView/components/HeaderCallButton.tsx index fc530f102e8..8aba69242c9 100644 --- a/app/views/RoomView/components/HeaderCallButton.tsx +++ b/app/views/RoomView/components/HeaderCallButton.tsx @@ -2,38 +2,29 @@ import React from 'react'; import * as HeaderButton from '../../../containers/Header/components/HeaderButton'; import { useVideoConf } from '../../../lib/hooks/useVideoConf'; -import { mediaSessionInstance } from '../../../lib/services/voip/MediaSessionInstance'; -import type { TSubscriptionModel } from '../../../definitions'; -import { useMediaCallPermission } from '../../../lib/hooks/useMediaCallPermission'; +import { useNewMediaCall } from '../../../lib/hooks/useNewMediaCall'; export const HeaderCallButton = ({ rid, disabled, - accessibilityLabel, - room + accessibilityLabel }: { rid: string; disabled: boolean; accessibilityLabel: string; - room?: TSubscriptionModel; }): React.ReactElement | null => { 'use memo'; const { showInitCallActionSheet, callEnabled, disabledTooltip } = useVideoConf(rid); - const hasMediaCallPermission = useMediaCallPermission(); + const { openNewMediaCall, hasMediaCallPermission } = useNewMediaCall(rid); if (hasMediaCallPermission) { - const handlePress = () => { - if (!room) return; - mediaSessionInstance.startCallByRoom(room); - }; - return ( <HeaderButton.Item accessibilityLabel={accessibilityLabel} disabled={disabled} iconName='phone' - onPress={handlePress} + onPress={openNewMediaCall} testID='room-view-header-call' /> ); diff --git a/app/views/SidebarView/components/Stacks.tsx b/app/views/SidebarView/components/Stacks.tsx index 556c74d6921..78bab8fe79d 100644 --- a/app/views/SidebarView/components/Stacks.tsx +++ b/app/views/SidebarView/components/Stacks.tsx @@ -2,15 +2,14 @@ import { useTheme } from '../../../theme'; import * as List from '../../../containers/List'; import { sidebarNavigate } from '../methods/sidebarNavigate'; import { useAppSelector } from '../../../lib/hooks/useAppSelector'; -import { simulateCall } from '../../../lib/services/voip/simulateCall'; -import { useCallStore } from '../../../lib/services/voip/useCallStore'; +import { useNewMediaCall } from '../../../lib/hooks/useNewMediaCall'; const Stacks = ({ currentScreen }: { currentScreen: string | null }) => { 'use memo'; const { colors } = useTheme(); const isMasterDetail = useAppSelector(state => state.app.isMasterDetail); - const toggleFocus = useCallStore(state => state.toggleFocus); + const { openNewMediaCall, hasMediaCallPermission } = useNewMediaCall(); if (isMasterDetail) { return null; @@ -26,17 +25,17 @@ const Stacks = ({ currentScreen }: { currentScreen: string | null }) => { testID='sidebar-chats' /> <List.Separator /> - <List.Item - title={'Voice_call'} - left={() => <List.Icon name='phone' />} - onPress={() => { - simulateCall(); - toggleFocus(); - }} - // backgroundColor={currentScreen === 'ChatsStackNavigator' ? colors.strokeLight : undefined} - testID='sidebar-voice-call' - /> - <List.Separator /> + {hasMediaCallPermission ? ( + <> + <List.Item + title={'Voice_call'} + left={() => <List.Icon name='phone' />} + onPress={openNewMediaCall} + testID='sidebar-media-call' + /> + <List.Separator /> + </> + ) : null} <List.Item title={'Profile'} left={() => <List.Icon name='user' />} diff --git a/app/views/ThreadMessagesView/__snapshots__/Item.test.tsx.snap b/app/views/ThreadMessagesView/__snapshots__/Item.test.tsx.snap index abad0d4166c..608ca055fdf 100644 --- a/app/views/ThreadMessagesView/__snapshots__/Item.test.tsx.snap +++ b/app/views/ThreadMessagesView/__snapshots__/Item.test.tsx.snap @@ -4438,7 +4438,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` "textAlign": "left", }, { - "color": "#E4E7EA", + "color": "#C1C7D0", "lineHeight": undefined, }, { @@ -4504,7 +4504,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -4561,7 +4561,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ @@ -4652,7 +4652,7 @@ exports[`Story Snapshots: Themes should match snapshot 1`] = ` style={ [ { - "color": "#E4E7EA", + "color": "#C1C7D0", "fontSize": 24, }, [ From 0715e8989f3836a7ea120b37a6ce9b06ad13ecd9 Mon Sep 17 00:00:00 2001 From: diegolmello <diegolmello@users.noreply.github.com> Date: Mon, 9 Mar 2026 14:00:33 +0000 Subject: [PATCH 57/61] action: organized translations --- app/i18n/locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index 7ca335bb0e4..9aa2c054952 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -573,8 +573,8 @@ "Name": "Name", "Name_required": "Name required", "Never": "Never", - "New_chat_transfer": "New chat transfer: {{agent}} returned the chat to the queue", "New_call": "New call", + "New_chat_transfer": "New chat transfer: {{agent}} returned the chat to the queue", "New_Message": "New message", "New_Password": "New password", "Next": "Next", From 827408316cc007b2d4d62869eb249a82cbc0c325 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Fri, 13 Mar 2026 18:07:12 -0300 Subject: [PATCH 58/61] feat: Receive voip push notifications from backend (#7045) --- android/app/src/main/AndroidManifest.xml | 5 + .../rocket/reactnative/MainApplication.kt | 2 - .../reactnative/notification/Ejson.java | 4 +- .../notification/NotificationIntentHandler.kt | 1 + .../RCFirebaseMessagingService.kt | 19 +- .../reactnative/utils/CallIdUUIDModule.kt | 72 --- .../utils/CallIdUUIDTurboPackage.kt | 30 -- .../reactnative/utils/NativeCallIdUUIDSpec.kt | 19 - .../chat/rocket/reactnative/voip/DDPClient.kt | 308 ++++++++++++ .../reactnative/voip/IncomingCallActivity.kt | 73 ++- .../rocket/reactnative/voip/VoipModule.kt | 14 +- .../reactnative/voip/VoipNotification.kt | 348 +++++++++++++- .../rocket/reactnative/voip/VoipPayload.kt | 174 ++++++- app/actions/deepLinking.ts | 1 - .../MediaCallHeader.stories.tsx | 1 - .../MediaCallHeader/MediaCallHeader.test.tsx | 1 - app/definitions/Voip.ts | 6 +- app/definitions/rest/v1/push.ts | 2 +- app/lib/hooks/useSubscription.test.ts | 6 +- app/lib/native/NativeCallIdUUID.ts | 8 - app/lib/native/NativeVoip.ts | 28 +- app/lib/notifications/push.ts | 14 +- app/lib/services/restApi.ts | 94 ++-- app/lib/services/voip/MediaCallEvents.ts | 18 +- app/lib/services/voip/MediaSessionInstance.ts | 55 ++- app/lib/services/voip/pushTokenAux.ts | 8 - app/lib/services/voip/simulateCall.ts | 106 ----- app/lib/services/voip/useCallStore.ts | 29 +- app/stacks/types.ts | 4 +- app/views/CallView/CallView.stories.tsx | 2 +- .../components/CallerInfo.stories.tsx | 2 +- .../CallView/components/CallerInfo.test.tsx | 2 +- .../components/Dialpad/Dialpad.stories.tsx | 2 +- .../components/Dialpad/Dialpad.test.tsx | 2 +- app/views/CallView/index.test.tsx | 2 +- ios/AppDelegate.swift | 50 -- ios/Libraries/AppDelegate+Voip.swift | 59 +++ ios/Libraries/CallIdUUID.m | 7 - ios/Libraries/CallIdUUID.swift | 67 --- ios/Libraries/DDPClient.swift | 391 +++++++++++++++ ios/Libraries/VoipModule.mm | 10 + ios/Libraries/VoipPayload.swift | 210 +++++++++ ios/Libraries/VoipService.swift | 444 +++++++++++++++--- ios/Podfile.lock | 2 +- ios/RocketChatRN-Bridging-Header.h | 1 + ios/RocketChatRN.xcodeproj/project.pbxproj | 30 +- 46 files changed, 2114 insertions(+), 619 deletions(-) delete mode 100644 android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDModule.kt delete mode 100644 android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDTurboPackage.kt delete mode 100644 android/app/src/main/java/chat/rocket/reactnative/utils/NativeCallIdUUIDSpec.kt create mode 100644 android/app/src/main/java/chat/rocket/reactnative/voip/DDPClient.kt delete mode 100644 app/lib/native/NativeCallIdUUID.ts delete mode 100644 app/lib/services/voip/pushTokenAux.ts delete mode 100644 app/lib/services/voip/simulateCall.ts create mode 100644 ios/Libraries/AppDelegate+Voip.swift delete mode 100644 ios/Libraries/CallIdUUID.m delete mode 100644 ios/Libraries/CallIdUUID.swift create mode 100644 ios/Libraries/DDPClient.swift create mode 100644 ios/Libraries/VoipPayload.swift diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 2a4643d0d36..ca983f7a6e1 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -128,6 +128,11 @@ android:excludeFromRecents="true" android:taskAffinity="chat.rocket.reactnative.voip" /> + <receiver + android:name="chat.rocket.reactnative.voip.VoipNotification$DeclineReceiver" + android:enabled="true" + android:exported="false" /> + <service android:name="chat.rocket.reactnative.voip.VoipForegroundService" android:exported="false" diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt index 1035e46107a..c90ea649c0e 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.kt @@ -21,7 +21,6 @@ import chat.rocket.reactnative.storage.SecureStoragePackage; import chat.rocket.reactnative.notification.VideoConfTurboPackage import chat.rocket.reactnative.notification.PushNotificationTurboPackage import chat.rocket.reactnative.VoipTurboPackage -import chat.rocket.reactnative.utils.CallIdUUIDTurboPackage /** * Main Application class. @@ -46,7 +45,6 @@ open class MainApplication : Application(), ReactApplication { add(VideoConfTurboPackage()) add(PushNotificationTurboPackage()) add(VoipTurboPackage()) - add(CallIdUUIDTurboPackage()) add(SecureStoragePackage()) } diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/Ejson.java b/android/app/src/main/java/chat/rocket/reactnative/notification/Ejson.java index 43489b5dd2f..eb180312a1b 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/Ejson.java +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/Ejson.java @@ -25,7 +25,7 @@ public class Ejson { private static final String TAG = "RocketChat.Ejson"; private static final String TOKEN_KEY = "reactnativemeteor_usertoken-"; - String host; + public String host; String rid; String type; Sender sender; @@ -264,4 +264,4 @@ static class Content { String kid; String iv; } -} +} \ No newline at end of file diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index 2a3a19187e3..060d4792077 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -58,6 +58,7 @@ class NotificationIntentHandler { Log.d(TAG, "Handling VoIP intent - voipPayload: $voipPayload") VoipNotification.cancelById(context, voipPayload.notificationId) + VoipNotification.cancelTimeout(voipPayload.callId) VoipModule.storeInitialEvents(voipPayload) if (context is Activity) { diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt index 417028e659e..46253da2788 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt @@ -23,7 +23,8 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { } override fun onMessageReceived(remoteMessage: RemoteMessage) { - Log.d(TAG, "FCM message received from: ${remoteMessage.from}") + // TODO: remove data + Log.d(TAG, "FCM message received from: ${remoteMessage.from} data: ${remoteMessage.data}") val data = remoteMessage.data if (data.isEmpty()) { @@ -31,22 +32,20 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { return } - // Convert FCM data to Bundle for processing - val bundle = Bundle().apply { - data.forEach { (key, value) -> - putString(key, value) - } - } - val voipPayload = VoipPayload.fromMap(data) if (voipPayload != null) { - Log.d(TAG, "Detected VoIP incoming call payload, routing to VoipNotification handler") - VoipNotification(this).showIncomingCall(voipPayload) + Log.d(TAG, "Detected VoIP payload of type ${voipPayload.type}, routing to VoipNotification handler") + VoipNotification(this).onMessageReceived(voipPayload) return } // Process regular notifications via CustomPushNotification try { + val bundle = Bundle().apply { + data.forEach { (key, value) -> + putString(key, value) + } + } val notification = CustomPushNotification(this, bundle) notification.onReceived() } catch (e: Exception) { diff --git a/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDModule.kt b/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDModule.kt deleted file mode 100644 index aeb86eba722..00000000000 --- a/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDModule.kt +++ /dev/null @@ -1,72 +0,0 @@ -package chat.rocket.reactnative.utils - -import com.facebook.react.bridge.ReactApplicationContext -import java.security.MessageDigest - -/** - * CallIdUUID - Converts a callId string to a deterministic UUID v5. - * This is used by CallKeep which requires UUIDs, while the server sends random callId strings. - * - * The algorithm matches the iOS implementation in CallIdUUID.swift to ensure - * consistency across platforms. - */ -object CallIdUUID { - - // Fixed namespace UUID for VoIP calls (RFC 4122 URL namespace) - // Using the standard URL namespace UUID: 6ba7b811-9dad-11d1-80b4-00c04fd430c8 - private val NAMESPACE_UUID = byteArrayOf( - 0x6b.toByte(), 0xa7.toByte(), 0xb8.toByte(), 0x11.toByte(), - 0x9d.toByte(), 0xad.toByte(), - 0x11.toByte(), 0xd1.toByte(), - 0x80.toByte(), 0xb4.toByte(), - 0x00.toByte(), 0xc0.toByte(), 0x4f.toByte(), 0xd4.toByte(), 0x30.toByte(), 0xc8.toByte() - ) - - /** - * Generates a UUID v5 from a callId string. - * Uses SHA-1 hash of namespace + callId, then formats as UUID v5. - * - * @param callId The call ID string to convert - * @return A deterministic UUID string in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - */ - @JvmStatic - fun generateUUIDv5(callId: String): String { - // Concatenate namespace UUID bytes with callId UTF-8 bytes - val callIdBytes = callId.toByteArray(Charsets.UTF_8) - val data = ByteArray(NAMESPACE_UUID.size + callIdBytes.size) - System.arraycopy(NAMESPACE_UUID, 0, data, 0, NAMESPACE_UUID.size) - System.arraycopy(callIdBytes, 0, data, NAMESPACE_UUID.size, callIdBytes.size) - - // SHA-1 hash - val md = MessageDigest.getInstance("SHA-1") - val hash = md.digest(data) - - // Set version (4 bits) to 5 (0101) - hash[6] = ((hash[6].toInt() and 0x0F) or 0x50).toByte() - - // Set variant (2 bits) to 10 - hash[8] = ((hash[8].toInt() and 0x3F) or 0x80).toByte() - - // Format as UUID string (only use first 16 bytes) - return String.format( - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - hash[0].toInt() and 0xFF, hash[1].toInt() and 0xFF, hash[2].toInt() and 0xFF, hash[3].toInt() and 0xFF, - hash[4].toInt() and 0xFF, hash[5].toInt() and 0xFF, - hash[6].toInt() and 0xFF, hash[7].toInt() and 0xFF, - hash[8].toInt() and 0xFF, hash[9].toInt() and 0xFF, - hash[10].toInt() and 0xFF, hash[11].toInt() and 0xFF, hash[12].toInt() and 0xFF, - hash[13].toInt() and 0xFF, hash[14].toInt() and 0xFF, hash[15].toInt() and 0xFF - ) - } -} - -/** - * React Native TurboModule implementation for CallIdUUID. - * Exposes the CallIdUUID functionality to JavaScript. - */ -class CallIdUUIDModule(reactContext: ReactApplicationContext) : NativeCallIdUUIDSpec(reactContext) { - - override fun getName() = NativeCallIdUUIDSpec.NAME - - override fun toUUID(callId: String): String = CallIdUUID.generateUUIDv5(callId) -} \ No newline at end of file diff --git a/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDTurboPackage.kt b/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDTurboPackage.kt deleted file mode 100644 index 33ef27b99b7..00000000000 --- a/android/app/src/main/java/chat/rocket/reactnative/utils/CallIdUUIDTurboPackage.kt +++ /dev/null @@ -1,30 +0,0 @@ -package chat.rocket.reactnative.utils - -import com.facebook.react.BaseReactPackage -import com.facebook.react.bridge.NativeModule -import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.module.model.ReactModuleInfo -import com.facebook.react.module.model.ReactModuleInfoProvider - -class CallIdUUIDTurboPackage : BaseReactPackage() { - - override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? = - if (name == NativeCallIdUUIDSpec.NAME) { - CallIdUUIDModule(reactContext) - } else { - null - } - - override fun getReactModuleInfoProvider() = ReactModuleInfoProvider { - mapOf( - NativeCallIdUUIDSpec.NAME to ReactModuleInfo( - name = NativeCallIdUUIDSpec.NAME, - className = NativeCallIdUUIDSpec.NAME, - canOverrideExistingModule = false, - needsEagerInit = false, - isCxxModule = false, - isTurboModule = true - ) - ) - } -} diff --git a/android/app/src/main/java/chat/rocket/reactnative/utils/NativeCallIdUUIDSpec.kt b/android/app/src/main/java/chat/rocket/reactnative/utils/NativeCallIdUUIDSpec.kt deleted file mode 100644 index 9da6aa0fe58..00000000000 --- a/android/app/src/main/java/chat/rocket/reactnative/utils/NativeCallIdUUIDSpec.kt +++ /dev/null @@ -1,19 +0,0 @@ -package chat.rocket.reactnative.utils - -import com.facebook.react.bridge.ReactApplicationContext -import com.facebook.react.bridge.ReactContextBaseJavaModule -import com.facebook.react.bridge.ReactMethod -import com.facebook.react.turbomodule.core.interfaces.TurboModule - -abstract class NativeCallIdUUIDSpec(reactContext: ReactApplicationContext) : - ReactContextBaseJavaModule(reactContext), TurboModule { - - companion object { - const val NAME = "CallIdUUID" - } - - override fun getName(): String = NAME - - @ReactMethod(isBlockingSynchronousMethod = true) - abstract fun toUUID(callId: String): String -} diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/DDPClient.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/DDPClient.kt new file mode 100644 index 00000000000..66511265fe3 --- /dev/null +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/DDPClient.kt @@ -0,0 +1,308 @@ +package chat.rocket.reactnative.voip + +import android.os.Handler +import android.os.Looper +import android.util.Log +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import okhttp3.WebSocket +import okhttp3.WebSocketListener +import org.json.JSONArray +import org.json.JSONObject +import java.util.concurrent.TimeUnit + +class DDPClient { + private data class QueuedMethodCall( + val method: String, + val params: JSONArray, + val callback: (Boolean) -> Unit + ) + + companion object { + private const val TAG = "RocketChat.DDPClient" + } + + private var webSocket: WebSocket? = null + private var client: OkHttpClient? = null + private var sendCounter = 0 + private var isConnected = false + private val mainHandler = Handler(Looper.getMainLooper()) + + private val pendingCallbacks = mutableMapOf<String, (JSONObject) -> Unit>() + private val queuedMethodCalls = mutableListOf<QueuedMethodCall>() + private var connectedCallback: ((Boolean) -> Unit)? = null + + var onCollectionMessage: ((JSONObject) -> Unit)? = null + + fun connect(host: String, callback: (Boolean) -> Unit) { + val wsUrl = buildWebSocketURL(host) + + Log.d(TAG, "Connecting to $wsUrl") + + val httpClient = OkHttpClient.Builder() + .pingInterval(30, TimeUnit.SECONDS) + .build() + client = httpClient + + val request = Request.Builder().url(wsUrl).build() + + webSocket = httpClient.newWebSocket(request, object : WebSocketListener() { + override fun onOpen(webSocket: WebSocket, response: Response) { + Log.d(TAG, "WebSocket opened") + val connectMsg = JSONObject().apply { + put("msg", "connect") + put("version", "1") + put("support", JSONArray().apply { + put("1"); put("pre2"); put("pre1") + }) + } + webSocket.send(connectMsg.toString()) + waitForConnected(10_000L, callback) + } + + override fun onMessage(webSocket: WebSocket, text: String) { + handleMessage(text) + } + + override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { + Log.e(TAG, "WebSocket failure: ${t.message}") + isConnected = false + mainHandler.post { callback(false) } + } + + override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { + Log.d(TAG, "WebSocket closed: $code $reason") + isConnected = false + } + }) + } + + fun login(token: String, callback: (Boolean) -> Unit) { + val msg = nextMessage("method").apply { + put("method", "login") + put("params", JSONArray().apply { + put(JSONObject().apply { put("resume", token) }) + }) + } + + val msgId = msg.getString("id") + + synchronized(pendingCallbacks) { + pendingCallbacks[msgId] = { data -> + synchronized(pendingCallbacks) { pendingCallbacks.remove(msgId) } + val hasError = data.has("error") + if (hasError) { + Log.e(TAG, "Login failed: ${data.opt("error")}") + } else { + Log.d(TAG, "Login succeeded") + } + mainHandler.post { callback(!hasError) } + } + } + + if (!send(msg)) { + mainHandler.post { callback(false) } + } + } + + fun subscribe(name: String, params: JSONArray, callback: (Boolean) -> Unit) { + val msg = nextMessage("sub").apply { + put("name", name) + put("params", params) + } + + val msgId = msg.getString("id") + + synchronized(pendingCallbacks) { + pendingCallbacks[msgId] = { data -> + synchronized(pendingCallbacks) { pendingCallbacks.remove(msgId) } + val didSubscribe = data.optString("msg") == "ready" && !data.has("error") + if (didSubscribe) { + Log.d(TAG, "Subscribed to $name") + } else { + Log.e(TAG, "Failed to subscribe to $name: ${data.opt("error") ?: "nosub"}") + } + mainHandler.post { callback(didSubscribe) } + } + } + + if (!send(msg)) { + synchronized(pendingCallbacks) { pendingCallbacks.remove(msgId) } + mainHandler.post { callback(false) } + } + } + + fun disconnect() { + Log.d(TAG, "Disconnecting") + isConnected = false + synchronized(pendingCallbacks) { pendingCallbacks.clear() } + clearQueuedMethodCalls() + connectedCallback = null + onCollectionMessage = null + webSocket?.close(1000, null) + webSocket = null + client?.dispatcher?.executorService?.shutdown() + client = null + } + + private fun nextMessage(msg: String): JSONObject { + sendCounter++ + return JSONObject().apply { + put("msg", msg) + put("id", "ddp-$sendCounter") + } + } + + private fun send(json: JSONObject): Boolean { + val ws = webSocket ?: return false + return ws.send(json.toString()) + } + + fun callMethod(method: String, params: JSONArray, callback: (Boolean) -> Unit) { + val msg = nextMessage("method").apply { + put("method", method) + put("params", params) + } + + val msgId = msg.getString("id") + + synchronized(pendingCallbacks) { + pendingCallbacks[msgId] = { data -> + synchronized(pendingCallbacks) { pendingCallbacks.remove(msgId) } + val hasError = data.has("error") + if (hasError) { + Log.e(TAG, "Method $method failed: ${data.opt("error")}") + } + mainHandler.post { callback(!hasError) } + } + } + + if (!send(msg)) { + synchronized(pendingCallbacks) { pendingCallbacks.remove(msgId) } + mainHandler.post { callback(false) } + } + } + + fun queueMethodCall(method: String, params: JSONArray, callback: (Boolean) -> Unit = {}) { + synchronized(queuedMethodCalls) { + queuedMethodCalls.add( + QueuedMethodCall( + method = method, + params = params, + callback = callback + ) + ) + } + } + + fun hasQueuedMethodCalls(): Boolean = + synchronized(queuedMethodCalls) { queuedMethodCalls.isNotEmpty() } + + fun flushQueuedMethodCalls() { + val queuedCalls = synchronized(queuedMethodCalls) { + queuedMethodCalls.toList().also { queuedMethodCalls.clear() } + } + + queuedCalls.forEach { queuedCall -> + callMethod(queuedCall.method, queuedCall.params, queuedCall.callback) + } + } + + fun clearQueuedMethodCalls() { + synchronized(queuedMethodCalls) { + queuedMethodCalls.clear() + } + } + + private fun waitForConnected(timeoutMs: Long, callback: (Boolean) -> Unit) { + connectedCallback = callback + mainHandler.postDelayed({ + val cb = connectedCallback ?: return@postDelayed + connectedCallback = null + Log.e(TAG, "Connect timeout") + cb(false) + }, timeoutMs) + } + + private fun handleMessage(text: String) { + val json = try { + JSONObject(text) + } catch (e: Exception) { + return + } + + when (json.optString("msg")) { + "connected" -> { + isConnected = true + mainHandler.removeCallbacksAndMessages(null) + val cb = connectedCallback + connectedCallback = null + cb?.let { mainHandler.post { it(true) } } + } + + "ping" -> { + send(JSONObject().apply { put("msg", "pong") }) + } + + "result" -> { + val id = json.optString("id") + val cb = synchronized(pendingCallbacks) { pendingCallbacks[id] } + cb?.invoke(json) + } + + "ready" -> { + val subs = json.optJSONArray("subs") + if (subs != null) { + for (index in 0 until subs.length()) { + val subId = subs.optString(index) + if (subId.isEmpty()) { + continue + } + + val cb = synchronized(pendingCallbacks) { pendingCallbacks[subId] } + cb?.invoke(json) + } + } + } + + "changed", "added", "removed" -> { + onCollectionMessage?.invoke(json) + } + + "nosub" -> { + val id = json.optString("id") + val cb = synchronized(pendingCallbacks) { pendingCallbacks[id] } + cb?.invoke(json) + } + + else -> { + if (json.has("collection")) { + onCollectionMessage?.invoke(json) + } + } + } + } + + private fun buildWebSocketURL(host: String): String { + var normalizedHost = host.trimEnd('/') + + val useSsl: Boolean + when { + normalizedHost.startsWith("https://") -> { + useSsl = true + normalizedHost = normalizedHost.removePrefix("https://") + } + normalizedHost.startsWith("http://") -> { + useSsl = false + normalizedHost = normalizedHost.removePrefix("http://") + } + else -> { + useSsl = true + } + } + + val scheme = if (useSsl) "wss" else "ws" + return "$scheme://$normalizedHost/websocket" + } +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt index 0cf6b64a9d8..f74d24a06b7 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt @@ -2,17 +2,22 @@ package chat.rocket.reactnative.voip import android.app.Activity import android.app.KeyguardManager +import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.content.IntentFilter import android.graphics.drawable.GradientDrawable import android.media.Ringtone import android.media.RingtoneManager import android.os.Build import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.view.WindowManager import android.view.View import android.widget.ImageView import androidx.core.content.ContextCompat +import androidx.localbroadcastmanager.content.LocalBroadcastManager import android.widget.LinearLayout import android.widget.TextView import android.widget.FrameLayout @@ -21,8 +26,8 @@ import android.view.ViewOutlineProvider import com.bumptech.glide.Glide import chat.rocket.reactnative.MainActivity import chat.rocket.reactnative.R -import chat.rocket.reactnative.notification.Ejson import android.graphics.Typeface +import chat.rocket.reactnative.notification.Ejson /** * Full-screen Activity displayed when an incoming VoIP call arrives. @@ -36,6 +41,21 @@ class IncomingCallActivity : Activity() { private var ringtone: Ringtone? = null private var voipPayload: VoipPayload? = null + private var isCallStateReceiverRegistered = false + private val timeoutHandler = Handler(Looper.getMainLooper()) + private var timeoutRunnable: Runnable? = null + private val callStateReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + val payload = VoipPayload.fromBundle(intent?.extras) ?: return + if (payload.callId != voipPayload?.callId) { + return + } + + clearTimeout() + stopRingtone() + finish() + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -75,11 +95,18 @@ class IncomingCallActivity : Activity() { } this.voipPayload = voipPayload - Log.d(TAG, "IncomingCallActivity created - callUUID: ${voipPayload.callUUID}, caller: ${voipPayload.caller}") + Log.d(TAG, "IncomingCallActivity created - callId: ${voipPayload.callId}, caller: ${voipPayload.caller}") updateUI(voipPayload) startRingtone() setupButtons(voipPayload) + scheduleTimeout(voipPayload) + val intentFilter = IntentFilter().apply { + addAction(VoipNotification.ACTION_TIMEOUT) + addAction(VoipNotification.ACTION_DISMISS) + } + LocalBroadcastManager.getInstance(this).registerReceiver(callStateReceiver, intentFilter) + isCallStateReceiverRegistered = true } private fun applyNavigationBar() { @@ -152,8 +179,6 @@ class IncomingCallActivity : Activity() { } private fun loadAvatar(payload: VoipPayload) { - if (payload.host.isBlank() || payload.username.isBlank()) return - val container = findViewById<FrameLayout>(R.id.avatar_container) val imageView = findViewById<ImageView>(R.id.avatar) val sizePx = (120 * resources.displayMetrics.density).toInt().coerceIn(120, 480) @@ -232,8 +257,31 @@ class IncomingCallActivity : Activity() { } } + private fun scheduleTimeout(payload: VoipPayload) { + val remainingLifetimeMs = payload.getRemainingLifetimeMs() + if (remainingLifetimeMs == null || remainingLifetimeMs <= 0L) { + stopRingtone() + finish() + return + } + + clearTimeout() + timeoutRunnable = Runnable { + stopRingtone() + VoipNotification.handleTimeout(this, payload) + finish() + }.also { timeoutHandler.postDelayed(it, remainingLifetimeMs) } + } + + private fun clearTimeout() { + timeoutRunnable?.let(timeoutHandler::removeCallbacks) + timeoutRunnable = null + } + private fun handleAccept(payload: VoipPayload) { - Log.d(TAG, "Call accepted - callUUID: ${payload.callUUID}") + Log.d(TAG, "Call accepted - callId: ${payload.callId}") + clearTimeout() + VoipNotification.cancelTimeout(payload.callId) stopRingtone() // Launch MainActivity with call data @@ -247,19 +295,22 @@ class IncomingCallActivity : Activity() { } private fun handleDecline(payload: VoipPayload) { - Log.d(TAG, "Call declined - callUUID: ${payload.callUUID}") + Log.d(TAG, "Call declined - callId: ${payload.callId}") + clearTimeout() + VoipNotification.cancelTimeout(payload.callId) stopRingtone() - - VoipNotification.cancelById(this, payload.notificationId) - - // Emit event to JS - // TODO: call restapi to decline the call + VoipNotification.handleDeclineAction(this, payload) finish() } override fun onDestroy() { super.onDestroy() + clearTimeout() + if (isCallStateReceiverRegistered) { + LocalBroadcastManager.getInstance(this).unregisterReceiver(callStateReceiver) + isCallStateReceiverRegistered = false + } stopRingtone() } diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt index 099238129c0..0862c42a9df 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt @@ -20,7 +20,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo private var reactContextRef: WeakReference<ReactApplicationContext>? = null private var initialEventsData: VoipPayload? = null - private var initialEventsTimestamp: Long = 0 /** * Sets the React context reference for event emission. @@ -55,7 +54,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo @JvmStatic fun storeInitialEvents(voipPayload: VoipPayload) { initialEventsData = voipPayload - initialEventsTimestamp = System.currentTimeMillis() emitInitialEventsEvent(voipPayload) } @@ -63,7 +61,6 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo fun clearInitialEventsInternal() { try { initialEventsData = null - initialEventsTimestamp = 0 Log.d(TAG, "Cleared initial events") } catch (e: Exception) { Log.e(TAG, "Error clearing initial events", e) @@ -83,7 +80,8 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo override fun getInitialEvents(): WritableMap? { val data = initialEventsData ?: return null - if (System.currentTimeMillis() - initialEventsTimestamp > 5 * 60 * 1000) { + if (data.isExpired()) { + Log.d(TAG, "Discarding expired VoIP initial event: ${data.callId}") clearInitialEventsInternal() return null } @@ -101,6 +99,9 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo clearInitialEventsInternal() } + // No-op on Android - FCM handles push notifications + override fun getLastVoipToken(): String = "" + /** * Registers for VoIP push token. * No-op on Android - uses FCM for push notifications. @@ -110,6 +111,11 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo Log.d(TAG, "registerVoipToken called (no-op on Android)") } + override fun stopNativeDDPClient() { + Log.d(TAG, "stopNativeDDPClient called, stopping native DDP client") + VoipNotification.stopDDPClient() + } + /** * Required for NativeEventEmitter in TurboModules. * Called when JS starts listening to events. diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt index 644d912a51e..96a0d5e1bcd 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt @@ -12,14 +12,23 @@ import android.media.AudioAttributes import android.media.RingtoneManager import android.os.Build import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.provider.Settings import android.util.Log import androidx.core.app.NotificationCompat +import androidx.localbroadcastmanager.content.LocalBroadcastManager import android.content.ComponentName import android.net.Uri import android.telecom.PhoneAccount import android.telecom.PhoneAccountHandle import android.telecom.TelecomManager +import io.wazo.callkeep.VoiceConnection +import io.wazo.callkeep.VoiceConnectionService import chat.rocket.reactnative.MainActivity +import chat.rocket.reactnative.notification.Ejson +import org.json.JSONArray +import org.json.JSONObject /** * Handles VoIP call notifications using Android's Telecom framework via CallKeep. @@ -39,9 +48,16 @@ class VoipNotification(private val context: Context) { const val ACTION_ACCEPT = "chat.rocket.reactnative.ACTION_VOIP_ACCEPT" const val ACTION_DECLINE = "chat.rocket.reactnative.ACTION_VOIP_DECLINE" + const val ACTION_TIMEOUT = "chat.rocket.reactnative.ACTION_VOIP_TIMEOUT" + const val ACTION_DISMISS = "chat.rocket.reactnative.ACTION_VOIP_DISMISS" // react-native-callkeep's ConnectionService class name private const val CALLKEEP_CONNECTION_SERVICE_CLASS = "io.wazo.callkeep.VoiceConnectionService" + private const val DISCONNECT_REASON_MISSED = 6 + private val timeoutHandler = Handler(Looper.getMainLooper()) + private val timeoutCallbacks = mutableMapOf<String, Runnable>() + private var ddpClient: DDPClient? = null + private var isDdpLoggedIn = false /** * Cancels a VoIP notification by ID. @@ -53,14 +69,298 @@ class VoipNotification(private val context: Context) { Log.d(TAG, "VoIP notification cancelled with ID: $notificationId") } + @JvmStatic + fun scheduleTimeout(context: Context, payload: VoipPayload) { + val delayMs = payload.getRemainingLifetimeMs() + if (delayMs == null || delayMs <= 0L) { + Log.d(TAG, "Skipping timeout scheduling for expired or invalid call: ${payload.callId}") + return + } + + cancelTimeout(payload.callId) + + val applicationContext = context.applicationContext + val timeoutRunnable = Runnable { + synchronized(timeoutCallbacks) { + timeoutCallbacks.remove(payload.callId) + } + handleTimeout(applicationContext, payload) + } + + synchronized(timeoutCallbacks) { + timeoutCallbacks[payload.callId] = timeoutRunnable + } + timeoutHandler.postDelayed(timeoutRunnable, delayMs) + Log.d(TAG, "Scheduled VoIP timeout for ${payload.callId} in ${delayMs}ms") + } + + @JvmStatic + fun cancelTimeout(callId: String) { + val timeoutRunnable = synchronized(timeoutCallbacks) { + timeoutCallbacks.remove(callId) + } + if (timeoutRunnable != null) { + timeoutHandler.removeCallbacks(timeoutRunnable) + Log.d(TAG, "Cancelled VoIP timeout for $callId") + } + } + + @JvmStatic + fun handleTimeout(context: Context, payload: VoipPayload) { + cancelTimeout(payload.callId) + disconnectTimedOutCall(payload.callId) + cancelById(context, payload.notificationId) + LocalBroadcastManager.getInstance(context).sendBroadcast( + Intent(ACTION_TIMEOUT).apply { + putExtras(payload.toBundle()) + } + ) + stopDDPClientInternal() + Log.d(TAG, "Timed out incoming VoIP call: ${payload.callId}") + } + /** * Handles decline action for VoIP call. * Logs the decline action and clears stored call data. */ @JvmStatic fun handleDeclineAction(context: Context, payload: VoipPayload) { - Log.d(TAG, "Decline action triggered for callUUID: ${payload.callUUID}") - // TODO: call restapi to decline the call + Log.d(TAG, "Decline action triggered for callId: ${payload.callId}") + cancelTimeout(payload.callId) + if (isDdpLoggedIn) { + sendRejectSignal(context, payload) + } else { + queueRejectSignal(context, payload) + } + rejectIncomingCall(payload.callId) + cancelById(context, payload.notificationId) + LocalBroadcastManager.getInstance(context).sendBroadcast( + Intent(ACTION_DISMISS).apply { + putExtras(payload.toBundle()) + } + ) + } + + // TODO: unify these three functions and check VoiceConnectionService + private fun disconnectTimedOutCall(callId: String) { + val connection = VoiceConnectionService.getConnection(callId) + when (connection) { + is VoiceConnection -> connection.reportDisconnect(DISCONNECT_REASON_MISSED) + null -> Log.d(TAG, "No active VoiceConnection found for timed out call: $callId") + else -> connection.onDisconnect() + } + } + + private fun rejectIncomingCall(callId: String) { + val connection = VoiceConnectionService.getConnection(callId) + when (connection) { + is VoiceConnection -> connection.onReject() + null -> Log.d(TAG, "No active VoiceConnection found for declined call: $callId") + else -> connection.onDisconnect() + } + } + + private fun disconnectIncomingCall(callId: String, reportAsMissed: Boolean) { + val connection = VoiceConnectionService.getConnection(callId) + when (connection) { + is VoiceConnection -> { + if (reportAsMissed) { + connection.reportDisconnect(DISCONNECT_REASON_MISSED) + } else { + connection.onDisconnect() + } + } + null -> Log.d(TAG, "No active VoiceConnection found for dismissed call: $callId") + else -> connection.onDisconnect() + } + } + + private fun sendRejectSignal(context: Context, payload: VoipPayload) { + val client = ddpClient + if (client == null) { + Log.d(TAG, "Native DDP client unavailable, cannot send reject for ${payload.callId}") + return + } + + val params = buildRejectSignalParams(context, payload) ?: return + + client.callMethod("stream-notify-user", params) { success -> + Log.d(TAG, "Native reject signal result for ${payload.callId}: $success") + stopDDPClientInternal() + } + } + + private fun queueRejectSignal(context: Context, payload: VoipPayload) { + val client = ddpClient + if (client == null) { + Log.d(TAG, "Native DDP client unavailable, cannot queue reject for ${payload.callId}") + return + } + + val params = buildRejectSignalParams(context, payload) ?: return + + client.queueMethodCall("stream-notify-user", params) { success -> + Log.d(TAG, "Queued native reject signal result for ${payload.callId}: $success") + stopDDPClientInternal() + } + Log.d(TAG, "Queued native reject signal for ${payload.callId}") + } + + private fun flushPendingRejectSignalIfNeeded(): Boolean { + val client = ddpClient ?: return false + if (!client.hasQueuedMethodCalls()) { + return false + } + + client.flushQueuedMethodCalls() + return true + } + + private fun buildRejectSignalParams(context: Context, payload: VoipPayload): JSONArray? { + val ejson = Ejson().apply { + host = payload.host + } + val userId = ejson.userId() + if (userId.isNullOrEmpty()) { + Log.d(TAG, "Missing userId, cannot send reject for ${payload.callId}") + stopDDPClientInternal() + return null + } + + val deviceId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) + if (deviceId.isNullOrEmpty()) { + Log.d(TAG, "Missing deviceId, cannot send reject for ${payload.callId}") + stopDDPClientInternal() + return null + } + + val signal = JSONObject().apply { + put("callId", payload.callId) + put("contractId", deviceId) + put("type", "answer") + put("answer", "reject") + } + + return JSONArray().apply { + put("$userId/media-calls") + put(signal.toString()) + } + } + + // -- Native DDP Listener (Call End Detection) -- + + @JvmStatic + fun startListeningForCallEnd(context: Context, payload: VoipPayload) { + stopDDPClientInternal() + + val ejson = Ejson() + ejson.host = payload.host + val userId = ejson.userId() + val token = ejson.token() + + if (userId.isNullOrEmpty() || token.isNullOrEmpty()) { + Log.d(TAG, "No credentials for ${payload.host}, skipping DDP listener") + return + } + + val deviceId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) + val callId = payload.callId + val client = DDPClient() + ddpClient = client + isDdpLoggedIn = false + + Log.d(TAG, "Starting DDP listener for call $callId") + + client.onCollectionMessage = { message -> + Log.d(TAG, "DDP received message: $message") + val fields = message.optJSONObject("fields") + if (fields != null) { + val eventName = fields.optString("eventName") + if (eventName.endsWith("/media-signal")) { + val args = fields.optJSONArray("args") + val firstArg = args?.optJSONObject(0) + if (firstArg != null) { + val signalType = firstArg.optString("type") + val signalCallId = firstArg.optString("callId") + val signalNotification = firstArg.optString("notification") + val signedContractId = firstArg.optString("signedContractId") + + if (signalCallId == callId) { + if (signalType == "notification" && + ( + // accepted from other device + (!signedContractId.isNullOrEmpty() && signedContractId != deviceId) || + // hung up by other device + (signalNotification == "hangup") + )) { + val appContext = context.applicationContext + Handler(Looper.getMainLooper()).post { + cancelTimeout(callId) + disconnectIncomingCall(callId, false) + cancelById(appContext, payload.notificationId) + LocalBroadcastManager.getInstance(appContext).sendBroadcast( + Intent(ACTION_DISMISS).apply { + putExtras(payload.toBundle()) + } + ) + stopDDPClientInternal() + } + } + } + } + } + } + } + + client.connect(payload.host) { connected -> + if (!connected) { + Log.d(TAG, "DDP connection failed") + stopDDPClientInternal() + return@connect + } + + client.login(token) { loggedIn -> + if (!loggedIn) { + Log.d(TAG, "DDP login failed") + stopDDPClientInternal() + return@login + } + + isDdpLoggedIn = true + if (flushPendingRejectSignalIfNeeded()) { + return@login + } + + val params = JSONArray().apply { + put("$userId/media-signal") + put(JSONObject().apply { + put("useCollection", false) + put("args", JSONArray().apply { put(false) }) + }) + } + + client.subscribe("stream-notify-user", params) { subscribed -> + Log.d(TAG, "DDP subscribe result: $subscribed") + if (!subscribed) { + stopDDPClientInternal() + } + } + } + } + + } + + @JvmStatic + fun stopDDPClient() { + Log.d(TAG, "stopDDPClient called from JS") + stopDDPClientInternal() + } + + private fun stopDDPClientInternal() { + isDdpLoggedIn = false + ddpClient?.clearQueuedMethodCalls() + ddpClient?.disconnect() + ddpClient = null } } @@ -81,6 +381,13 @@ class VoipNotification(private val context: Context) { createNotificationChannel() } + fun onMessageReceived(voipPayload: VoipPayload) { + when { + voipPayload.isVoipIncomingCall() -> showIncomingCall(voipPayload) + else -> Log.w(TAG, "Ignoring unsupported VoIP payload type: ${voipPayload.type}") + } + } + /** * Creates the notification channel for VoIP calls with high importance and ringtone sound. */ @@ -91,6 +398,7 @@ class VoipNotification(private val context: Context) { CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH ).apply { + // TODO: i18n description = "Incoming VoIP calls" enableLights(true) enableVibration(true) @@ -119,16 +427,26 @@ class VoipNotification(private val context: Context) { fun showIncomingCall(voipPayload: VoipPayload) { val callId = voipPayload.callId val caller = voipPayload.caller - val callUUID = voipPayload.callUUID + if (voipPayload.getRemainingLifetimeMs() == null) { + Log.w(TAG, "Skipping incoming VoIP call without a valid createdAt timestamp - callId: $callId") + return + } - Log.d(TAG, "Showing incoming VoIP call - callId: $callId, callUUID: $callUUID, caller: $caller") + if (voipPayload.isExpired()) { + Log.d(TAG, "Skipping expired incoming VoIP call - callId: $callId") + return + } + + Log.d(TAG, "Showing incoming VoIP call - callId: $callId, caller: $caller") // CRITICAL: Register call with TelecomManager FIRST (required for audio focus, Bluetooth, priority, FSI exemption) // This triggers react-native-callkeep's ConnectionService - registerCallWithTelecomManager(callUUID, caller) + registerCallWithTelecomManager(callId, caller) // Show notification with full-screen intent showIncomingCallNotification(voipPayload) + scheduleTimeout(context, voipPayload) + startListeningForCallEnd(context, voipPayload) } /** @@ -139,11 +457,11 @@ class VoipNotification(private val context: Context) { * 3. Higher process priority * 4. FSI exemption on Play Store */ - private fun registerCallWithTelecomManager(callUUID: String, caller: String) { + private fun registerCallWithTelecomManager(callId: String, caller: String) { try { // Validate inputs - if (callUUID.isNullOrEmpty() || caller.isNullOrEmpty()) { - Log.e(TAG, "Cannot register call with TelecomManager: callUUID is null or empty") + if (callId.isNullOrEmpty() || caller.isNullOrEmpty()) { + Log.e(TAG, "Cannot register call with TelecomManager: callId is null or empty") return } @@ -169,19 +487,17 @@ class VoipNotification(private val context: Context) { val extras = Bundle().apply { val callerUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, caller, null) putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, callerUri) - putString("EXTRA_CALL_UUID", callUUID) + putString("EXTRA_CALL_UUID", callId) putString("EXTRA_CALLER_NAME", caller) - // Legacy keys for backward compatibility - putString("callUUID", callUUID) putString("name", caller) putString("handle", caller) } - Log.d(TAG, "Registering call with TelecomManager - callUUID: $callUUID, caller: $caller, extras keys: ${extras.keySet()}") + Log.d(TAG, "Registering call with TelecomManager - callId: $callId, caller: $caller, extras keys: ${extras.keySet()}") // Register the incoming call with the OS telecomManager.addNewIncomingCall(phoneAccountHandle, extras) - Log.d(TAG, "Successfully registered incoming call with TelecomManager: $callUUID") + Log.d(TAG, "Successfully registered incoming call with TelecomManager: $callId") } catch (e: SecurityException) { Log.e(TAG, "SecurityException registering call with TelecomManager. MANAGE_OWN_CALLS permission may be missing.", e) } catch (e: Exception) { @@ -197,6 +513,11 @@ class VoipNotification(private val context: Context) { private fun showIncomingCallNotification(voipPayload: VoipPayload) { val caller = voipPayload.caller val notificationId = voipPayload.notificationId + val remainingLifetimeMs = voipPayload.getRemainingLifetimeMs() + if (remainingLifetimeMs == null || remainingLifetimeMs <= 0L) { + Log.d(TAG, "Skipping notification for expired or invalid call: ${voipPayload.callId}") + return + } Log.d(TAG, "Showing incoming call notification for VoIP call from: $caller") @@ -259,6 +580,7 @@ class VoipNotification(private val context: Context) { setVisibility(NotificationCompat.VISIBILITY_PUBLIC) setAutoCancel(false) setOngoing(true) + setTimeoutAfter(remainingLifetimeMs) addAction(0, "Decline", declinePendingIntent) addAction(0, "Accept", acceptPendingIntent) diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt index e9971eca91a..d361f711f30 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt @@ -1,10 +1,21 @@ package chat.rocket.reactnative.voip import android.os.Bundle +import com.google.gson.Gson import com.google.gson.annotations.SerializedName import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.WritableMap -import chat.rocket.reactnative.utils.CallIdUUID +import java.text.SimpleDateFormat +import java.util.Locale +import java.util.TimeZone + +enum class VoipPushType(val value: String) { + INCOMING_CALL("incoming_call"); + + companion object { + fun from(value: String?): VoipPushType? = entries.firstOrNull { it.value == value } + } +} data class VoipPayload( @SerializedName("callId") @@ -24,12 +35,28 @@ data class VoipPayload( @SerializedName("hostName") val hostName: String, + + @SerializedName("avatarUrl") + val avatarUrl: String?, + + @SerializedName("createdAt") + val createdAt: String?, ) { val notificationId: Int = callId.hashCode() - val callUUID: String = CallIdUUID.generateUUIDv5(callId) + val pushType: VoipPushType? + get() = VoipPushType.from(type) + + private val createdAtMs: Long? + get() = parseCreatedAtMs(createdAt) + + private val expiresAtMs: Long? + get() = createdAtMs?.plus(INCOMING_CALL_LIFETIME_MS) fun isVoipIncomingCall(): Boolean { - return type == "incoming_call" && callId.isNotEmpty() && caller.isNotEmpty() && host.isNotEmpty() + return pushType == VoipPushType.INCOMING_CALL && + callId.isNotBlank() && + caller.isNotBlank() && + host.isNotBlank() } fun toBundle(): Bundle { @@ -40,7 +67,8 @@ data class VoipPayload( putString("host", host) putString("type", type) putString("hostName", hostName) - putString("callUUID", callUUID) + putString("avatarUrl", avatarUrl) + putString("createdAt", createdAt) putInt("notificationId", notificationId) // Useful flag for MainActivity to know it's handling a VoIP action putBoolean("voipAction", true) @@ -55,34 +83,142 @@ data class VoipPayload( putString("host", host) putString("type", type) putString("hostName", hostName) - putString("callUUID", callUUID) + putString("avatarUrl", avatarUrl) + putString("createdAt", createdAt) putInt("notificationId", notificationId) } } + fun getRemainingLifetimeMs(): Long? { + val expiresAtMs = expiresAtMs ?: return null + val nowMs = System.currentTimeMillis() + return (expiresAtMs - nowMs).coerceAtLeast(0L) + } + + fun isExpired(): Boolean { + val remainingLifetimeMs = getRemainingLifetimeMs() + return remainingLifetimeMs?.let { it <= 0L } ?: true + } + companion object { + private val gson = Gson() + private const val VOIP_NOTIFICATION_TYPE = "voip" + // the amount of time in milliseconds that an incoming call will be kept alive + private const val INCOMING_CALL_LIFETIME_MS = 60_000L + private val isoDateFormats = listOf( + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US), + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.US), + ).onEach { formatter -> + formatter.timeZone = TimeZone.getTimeZone("UTC") + formatter.isLenient = false + } + + private data class RemoteCaller( + @SerializedName("name") + val name: String? = null, + + @SerializedName("username") + val username: String? = null, + + @SerializedName("avatarUrl") + val avatarUrl: String? = null, + ) + + private data class RemoteVoipPayload( + @SerializedName("callId") + val callId: String? = null, + + @SerializedName("caller") + val caller: RemoteCaller? = null, + + @SerializedName("username") + val username: String? = null, + + @SerializedName("host") + val host: String? = null, + + @SerializedName("type") + val type: String? = null, + + @SerializedName("hostName") + val hostName: String? = null, + + @SerializedName("notificationType") + val notificationType: String? = null, + + @SerializedName("createdAt") + val createdAt: String? = null, + ) { + fun toVoipPayload(): VoipPayload? { + if (notificationType != VOIP_NOTIFICATION_TYPE) return null + + val payloadType = VoipPushType.from(type)?.value ?: return null + val payloadCreatedAt = createdAt?.takeUnless { it.isBlank() } ?: return null + + return VoipPayload( + callId = callId ?: return null, + caller = caller?.name.orEmpty(), + username = caller?.username ?: username.orEmpty(), + host = host.orEmpty(), + type = payloadType, + hostName = hostName.orEmpty(), + avatarUrl = caller?.avatarUrl, + createdAt = payloadCreatedAt, + ) + } + } + fun fromMap(data: Map<String, String>): VoipPayload? { - val type = data["type"] ?: return null - val callId = data["callId"] ?: return null - val caller = data["caller"] ?: return null - val username = data["username"] ?: return null - val host = data["host"] ?: return null - val hostName = data["hostName"] ?: return null - if (type != "incoming_call") return null - - return VoipPayload(callId, caller, username, host, type, hostName) + val payload = parseRemotePayload(data) ?: return null + return payload.toVoipPayload() } fun fromBundle(bundle: Bundle?): VoipPayload? { if (bundle == null) return null val callId = bundle.getString("callId") ?: return null - val caller = bundle.getString("caller") ?: return null - val username = bundle.getString("username") ?: return null - val host = bundle.getString("host") ?: return null + val caller = bundle.getString("caller").orEmpty() + val username = bundle.getString("username").orEmpty() + val host = bundle.getString("host").orEmpty() + val hostName = bundle.getString("hostName").orEmpty() val type = bundle.getString("type") ?: return null - val hostName = bundle.getString("hostName") ?: return null + val avatarUrl = bundle.getString("avatarUrl") + val createdAt = bundle.getString("createdAt")?.takeUnless { it.isBlank() } ?: return null + + if (VoipPushType.from(type) == null) { + return null + } + + return VoipPayload(callId, caller, username, host, type, hostName, avatarUrl, createdAt) + } + + private fun parseRemotePayload(data: Map<String, String>): RemoteVoipPayload? { + val rawPayload = data["ejson"] + if (rawPayload.isNullOrBlank() || rawPayload == "{}") { + return null + } + + return try { + gson.fromJson(rawPayload, RemoteVoipPayload::class.java) + } catch (_: Exception) { + null + } + } + + private fun parseCreatedAtMs(value: String?): Long? { + if (value.isNullOrBlank()) { + return null + } + + for (formatter in isoDateFormats) { + val parsed = synchronized(formatter) { + runCatching { formatter.parse(value) }.getOrNull() + } + if (parsed != null) { + return parsed.time + } + } - return VoipPayload(callId, caller, username, host, type, hostName) + return null } } } \ No newline at end of file diff --git a/app/actions/deepLinking.ts b/app/actions/deepLinking.ts index 548aad8769a..d55de045aa3 100644 --- a/app/actions/deepLinking.ts +++ b/app/actions/deepLinking.ts @@ -18,7 +18,6 @@ interface IDeepLinkingOpen extends Action { interface IVoipCallParams { callId: string; - callUUID: string; host: string; } diff --git a/app/containers/MediaCallHeader/MediaCallHeader.stories.tsx b/app/containers/MediaCallHeader/MediaCallHeader.stories.tsx index ea8b5618ae2..4b3e9519fb4 100644 --- a/app/containers/MediaCallHeader/MediaCallHeader.stories.tsx +++ b/app/containers/MediaCallHeader/MediaCallHeader.stories.tsx @@ -35,7 +35,6 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat useCallStore.setState({ call: mockCall, - callUUID: 'test-uuid', callState: 'active', isMuted: false, isOnHold: false, diff --git a/app/containers/MediaCallHeader/MediaCallHeader.test.tsx b/app/containers/MediaCallHeader/MediaCallHeader.test.tsx index d4229750e97..de7659ac1b6 100644 --- a/app/containers/MediaCallHeader/MediaCallHeader.test.tsx +++ b/app/containers/MediaCallHeader/MediaCallHeader.test.tsx @@ -39,7 +39,6 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat const mockCall = createMockCall(); useCallStore.setState({ call: mockCall as any, - callUUID: 'test-uuid', callState: 'active', isMuted: false, isOnHold: false, diff --git a/app/definitions/Voip.ts b/app/definitions/Voip.ts index 203d8701849..72df8d1a870 100644 --- a/app/definitions/Voip.ts +++ b/app/definitions/Voip.ts @@ -7,7 +7,11 @@ export type IceServer = { export interface VoipPayload { readonly callId: string; readonly caller: string; + readonly username: string; readonly host: string; + readonly hostName: string; readonly type: string; - readonly callUUID: string; + readonly avatarUrl?: string | null; + readonly createdAt?: string | null; + readonly notificationId: number; } diff --git a/app/definitions/rest/v1/push.ts b/app/definitions/rest/v1/push.ts index f00f737bb0d..fce3e86cd02 100644 --- a/app/definitions/rest/v1/push.ts +++ b/app/definitions/rest/v1/push.ts @@ -6,7 +6,7 @@ type TPushInfo = { export type PushEndpoints = { 'push.token': { - POST: (params: { value: string; type: string; appName: string }) => { + POST: (params: { id: string; value: string; type: string; appName: string; voipToken?: string }) => { result: { id: string; token: string; diff --git a/app/lib/hooks/useSubscription.test.ts b/app/lib/hooks/useSubscription.test.ts index 4d93b1a6164..94711d391ff 100644 --- a/app/lib/hooks/useSubscription.test.ts +++ b/app/lib/hooks/useSubscription.test.ts @@ -9,7 +9,7 @@ jest.mock('../database/services/Subscription', () => ({ const mockedGetSubscriptionByRoomId = jest.mocked(getSubscriptionByRoomId); -const createDeferred = <T,>() => { +const createDeferred = <T>() => { let resolve!: (value: T) => void; const promise = new Promise<T>(res => { resolve = res; @@ -45,9 +45,7 @@ describe('useSubscription', () => { const secondSubscription = { id: 'sub-2', rid: 'room-2' } as any; const secondRequest = createDeferred<typeof secondSubscription | null>(); - mockedGetSubscriptionByRoomId - .mockResolvedValueOnce(firstSubscription) - .mockImplementationOnce(() => secondRequest.promise); + mockedGetSubscriptionByRoomId.mockResolvedValueOnce(firstSubscription).mockImplementationOnce(() => secondRequest.promise); const { result, rerender } = renderHook(({ rid }: { rid?: string }) => useSubscription(rid), { initialProps: { rid: 'room-1' } diff --git a/app/lib/native/NativeCallIdUUID.ts b/app/lib/native/NativeCallIdUUID.ts deleted file mode 100644 index 4dcaec05919..00000000000 --- a/app/lib/native/NativeCallIdUUID.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { TurboModule } from 'react-native'; -import { TurboModuleRegistry } from 'react-native'; - -export interface Spec extends TurboModule { - toUUID(callId: string): string; -} - -export default TurboModuleRegistry.getEnforcing<Spec>('CallIdUUID'); diff --git a/app/lib/native/NativeVoip.ts b/app/lib/native/NativeVoip.ts index 2b39ea631dd..d47ba83ec0c 100644 --- a/app/lib/native/NativeVoip.ts +++ b/app/lib/native/NativeVoip.ts @@ -21,6 +21,20 @@ export interface Spec extends TurboModule { */ clearInitialEvents(): void; + /** + * Gets the last known VoIP push token. + * iOS: Returns the cached PushKit token. + * Android: Returns an empty string. + */ + getLastVoipToken(): string; + + /** + * Stops the native DDP WebSocket listener used for early call-end detection. + * iOS: Disconnects the native DDP client that monitors media-signal hangup events. + * Android: No-op. + */ + stopNativeDDPClient(): void; + /** * Required for NativeEventEmitter in TurboModules. * Called when JS starts listening to events. @@ -36,4 +50,16 @@ export interface Spec extends TurboModule { removeListeners(count: number): void; } -export default TurboModuleRegistry.getEnforcing<Spec>('VoipModule'); +const NativeVoipModule = + TurboModuleRegistry.get<Spec>('VoipModule') ?? + ({ + registerVoipToken: () => undefined, + getInitialEvents: () => null, + clearInitialEvents: () => undefined, + getLastVoipToken: () => '', + stopNativeDDPClient: () => undefined, + addListener: () => undefined, + removeListeners: () => undefined + } as Spec); + +export default NativeVoipModule; diff --git a/app/lib/notifications/push.ts b/app/lib/notifications/push.ts index dc6858b25c2..95207db2724 100644 --- a/app/lib/notifications/push.ts +++ b/app/lib/notifications/push.ts @@ -186,19 +186,19 @@ export const pushNotificationConfigure = (onNotification: (notification: INotifi if (token) { deviceToken = token; console.log('[push.ts] Registered for push notifications:', token); + + registerPushToken().catch(e => { + console.log('[push.ts] Failed to register push token after initial acquisition:', e); + }); } }); // Listen for token updates (FCM can refresh tokens at any time) Notifications.addPushTokenListener(tokenData => { deviceToken = tokenData.data; - // Re-register with server if user is logged in - const { isAuthenticated } = reduxStore.getState().login; - if (isAuthenticated) { - registerPushToken().catch(e => { - console.log('Failed to re-register push token after refresh:', e); - }); - } + registerPushToken().catch(e => { + console.log('[push.ts] Failed to re-register push token after refresh:', e); + }); }); // Listen for notification responses (when user taps on notification) diff --git a/app/lib/services/restApi.ts b/app/lib/services/restApi.ts index 9f543c0bbbf..cc529d0a6b4 100644 --- a/app/lib/services/restApi.ts +++ b/app/lib/services/restApi.ts @@ -1,3 +1,5 @@ +import { getUniqueId } from 'react-native-device-info'; + import { type IAvatarSuggestion, type IMessage, @@ -23,10 +25,11 @@ import { type RoomTypes, roomTypeToApiType } from '../methods/roomTypeToApiType' import { unsubscribeRooms } from '../methods/subscribeRooms'; import { compareServerVersion, getBundleId, isIOS } from '../methods/helpers'; import { getDeviceToken } from '../notifications'; +import NativeVoipModule from '../native/NativeVoip'; import { store as reduxStore } from '../store/auxStore'; import sdk from './sdk'; import fetch from '../methods/helpers/fetch'; -import { getVoipPushToken } from './voip/pushTokenAux'; +import log from '../methods/helpers/log'; export const createChannel = ({ name, @@ -999,41 +1002,68 @@ export const editMessage = async (message: Pick<IMessage, 'id' | 'msg' | 'rid' | }); }; -export const registerPushToken = () => - new Promise<void>(async resolve => { - const token = getDeviceToken(); - if (token) { - const type = isIOS ? 'apn' : 'gcm'; - const data = { - value: token, - type, - appName: getBundleId - }; - try { - if (isIOS) { - const voipToken = getVoipPushToken(); - if (voipToken) { - // TODO: this is temp only for VoIP push token - await sdk.post('push.token', { - type: 'gcm', - value: voipToken, - appName: getBundleId - }); - } - } - - // RC 0.60.0 - await sdk.post('push.token', data); - } catch (error) { - console.log(error); - } - } - return resolve(); - }); +let lastToken = ''; +let lastVoipToken = ''; + +type TRegisterPushTokenData = { + id: string; + value: string; + type: string; + appName: string; + voipToken?: string; +}; +export const registerPushToken = async (): Promise<void> => { + const token = getDeviceToken(); + // Always returns an empty string on Android + const voipToken = NativeVoipModule.getLastVoipToken(); + + if (!token) { + return; + } + + if (token === lastToken && voipToken === lastVoipToken) { + return; + } + + // TODO: voice permission check and retry to avoid race condition + if (isIOS && (!token || !voipToken)) { + return; + } + + let data: TRegisterPushTokenData = { + id: await getUniqueId(), + value: '', + type: '', + appName: getBundleId + }; + if (token) { + const type = isIOS ? 'apn' : 'gcm'; + data = { + ...data, + value: token, + type + }; + } + if (voipToken) { + data.voipToken = voipToken; + } + + try { + // RC 0.60.0 + await sdk.post('push.token', data); + lastToken = token; + lastVoipToken = voipToken; + } catch (e) { + log(e); + } +}; +// TODO: add voip token removal export const removePushToken = (): Promise<boolean | void> => { const token = getDeviceToken(); if (token) { + lastToken = ''; + lastVoipToken = ''; // RC 0.60.0 return sdk.current.del('push.token', { token }); } diff --git a/app/lib/services/voip/MediaCallEvents.ts b/app/lib/services/voip/MediaCallEvents.ts index d04733c33d4..141dcbfdd24 100644 --- a/app/lib/services/voip/MediaCallEvents.ts +++ b/app/lib/services/voip/MediaCallEvents.ts @@ -4,11 +4,11 @@ import { DeviceEventEmitter, NativeEventEmitter } from 'react-native'; import { isIOS } from '../../methods/helpers'; import store from '../../store'; import { voipCallOpen } from '../../../actions/deepLinking'; -import { setVoipPushToken } from './pushTokenAux'; import { useCallStore } from './useCallStore'; import { mediaSessionInstance } from './MediaSessionInstance'; import type { VoipPayload } from '../../../definitions/Voip'; import NativeVoipModule from '../../native/NativeVoip'; +import { registerPushToken } from '../restApi'; const Emitter = isIOS ? new NativeEventEmitter(NativeVoipModule) : DeviceEventEmitter; const platform = isIOS ? 'iOS' : 'Android'; @@ -24,9 +24,11 @@ export const setupMediaCallEvents = (): (() => void) => { // iOS listens for VoIP push token registration and CallKeep events if (isIOS) { subscriptions.push( - Emitter.addListener('VoipPushTokenRegistered', (token: string) => { + Emitter.addListener('VoipPushTokenRegistered', ({ token }: { token: string }) => { console.log(`${TAG} Registered VoIP push token:`, token); - setVoipPushToken(token); + registerPushToken().catch(error => { + console.log(`${TAG} Failed to register push token after VoIP update:`, error); + }); }) ); @@ -55,15 +57,14 @@ export const setupMediaCallEvents = (): (() => void) => { } console.log(`${TAG} Initial events event:`, data); NativeVoipModule.clearInitialEvents(); - useCallStore.getState().setCallUUID(data.callUUID); + useCallStore.getState().setCallId(data.callId); store.dispatch( voipCallOpen({ callId: data.callId, - callUUID: data.callUUID, host: data.host }) ); - await mediaSessionInstance.answerCall(data.callUUID); + await mediaSessionInstance.answerCall(data.callId); } catch (error) { console.error(`${TAG} Error handling initial events event:`, error); } @@ -110,7 +111,7 @@ export const getInitialMediaCallEvents = async (): Promise<boolean> => { const { name, data } = event; if (name === 'RNCallKeepPerformAnswerCallAction') { const { callUUID } = data; - if (initialEvents.callUUID.toLowerCase() === callUUID.toLowerCase()) { + if (initialEvents.callId === callUUID) { wasAnswered = true; console.log(`${TAG} Call was already answered via CallKit`); break; @@ -123,12 +124,11 @@ export const getInitialMediaCallEvents = async (): Promise<boolean> => { } if (wasAnswered) { - useCallStore.getState().setCallUUID(initialEvents.callUUID); + useCallStore.getState().setCallId(initialEvents.callId); store.dispatch( voipCallOpen({ callId: initialEvents.callId, - callUUID: initialEvents.callUUID, host: initialEvents.host }) ); diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 7b01092196b..02e32e961a1 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -8,6 +8,7 @@ import { } from '@rocket.chat/media-signaling'; import RNCallKeep from 'react-native-callkeep'; import { registerGlobals } from 'react-native-webrtc'; +import { getUniqueId } from 'react-native-device-info'; import { mediaSessionStore } from './MediaSessionStore'; import { useCallStore } from './useCallStore'; @@ -15,7 +16,7 @@ import { store } from '../../store/auxStore'; import sdk from '../sdk'; import Navigation from '../../navigation/appNavigation'; import { parseStringToIceServers } from './parseStringToIceServers'; -import CallIdUUIDModule from '../../native/NativeCallIdUUID'; +import NativeVoipModule from '../../native/NativeVoip'; import type { IceServer } from '../../../definitions/Voip'; import type { IDDPMessage } from '../../../definitions/IDDPMessage'; import type { ISubscription, TSubscriptionModel } from '../../../definitions'; @@ -34,6 +35,8 @@ class MediaSessionInstance { this.stop(); registerGlobals(); this.configureIceServers(); + // prevent JS and native DDP clients from interfering with each other + NativeVoipModule.stopNativeDDPClient(); mediaSessionStore.setWebRTCProcessorFactory( (config: WebRTCProcessorConfig) => @@ -59,6 +62,11 @@ class MediaSessionInstance { } const signal = ddpMessage.fields.args[0]; this.instance.processSignal(signal); + + // If the call was accepted from another device, end the call + if (signal.type === 'notification' && signal.notification === 'accepted' && signal.signedContractId !== getUniqueId()) { + // TODO: pop from call view, end callkeep and remove incoming call notification + } }); this.instance?.on('newCall', ({ call }: { call: IClientMediaCall }) => { @@ -67,43 +75,40 @@ class MediaSessionInstance { console.log(`📊 ${oldState} → ${call.state}`); }); - const existingCallUUID = useCallStore.getState().callUUID; - console.log('[VoIP] Existing call UUID:', existingCallUUID); + const existingCallId = useCallStore.getState().callId; + console.log('[VoIP] Existing call Id:', existingCallId); // // TODO: need to answer the call here? - if (existingCallUUID) { - this.answerCall(existingCallUUID); + if (existingCallId) { + this.answerCall(existingCallId); return; } - const callUUID = CallIdUUIDModule.toUUID(call.callId); - console.log('[VoIP] New call UUID:', callUUID); - if (call.role === 'caller') { - useCallStore.getState().setCall(call, callUUID); - Navigation.navigate('CallView', { callUUID }); + useCallStore.getState().setCall(call); + Navigation.navigate('CallView'); } call.emitter.on('ended', () => { - RNCallKeep.endCall(callUUID); + RNCallKeep.endCall(call.callId); }); } }); } - public answerCall = async (callUUID: string) => { - console.log('[VoIP] Answering call:', callUUID); + public answerCall = async (callId: string) => { + console.log('[VoIP] Answering call:', callId); const mainCall = this.instance?.getMainCall(); console.log('[VoIP] Main call:', mainCall); - // Compare using deterministic UUID conversion - if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { - console.log('[VoIP] Accepting call:', callUUID); + + if (mainCall && mainCall.callId === callId) { + console.log('[VoIP] Accepting call:', callId); await mainCall.accept(); - console.log('[VoIP] Setting current call active:', callUUID); - RNCallKeep.setCurrentCallActive(callUUID); - useCallStore.getState().setCall(mainCall, callUUID); - Navigation.navigate('CallView', { callUUID }); + console.log('[VoIP] Setting current call active:', callId); + RNCallKeep.setCurrentCallActive(callId); + useCallStore.getState().setCall(mainCall); + Navigation.navigate('CallView'); } else { - RNCallKeep.endCall(callUUID); + RNCallKeep.endCall(callId); alert('Call not found'); // TODO: Show error message? } }; @@ -120,17 +125,17 @@ class MediaSessionInstance { this.instance?.startCall(actor, userId); }; - public endCall = (callUUID: string) => { + public endCall = (callId: string) => { const mainCall = this.instance?.getMainCall(); - // Compare using deterministic UUID conversion - if (mainCall && CallIdUUIDModule.toUUID(mainCall.callId) === callUUID) { + + if (mainCall && mainCall.callId === callId) { if (mainCall.state === 'ringing') { mainCall.reject(); } else { mainCall.hangup(); } } - RNCallKeep.endCall(callUUID); + RNCallKeep.endCall(callId); RNCallKeep.setCurrentCallActive(''); RNCallKeep.setAvailable(true); // Reset Zustand store diff --git a/app/lib/services/voip/pushTokenAux.ts b/app/lib/services/voip/pushTokenAux.ts deleted file mode 100644 index b369f770aa1..00000000000 --- a/app/lib/services/voip/pushTokenAux.ts +++ /dev/null @@ -1,8 +0,0 @@ -// TODO: find a better place for this -let voipPushToken: string | null = null; - -export const getVoipPushToken = (): string | null => voipPushToken; - -export const setVoipPushToken = (token: string): void => { - voipPushToken = token; -}; diff --git a/app/lib/services/voip/simulateCall.ts b/app/lib/services/voip/simulateCall.ts deleted file mode 100644 index 5ce82715db6..00000000000 --- a/app/lib/services/voip/simulateCall.ts +++ /dev/null @@ -1,106 +0,0 @@ -import type { CallState, IClientMediaCall } from '@rocket.chat/media-signaling'; -import { randomUuid } from '@rocket.chat/mobile-crypto'; - -// import Navigation from '../../navigation/appNavigation'; -import { useCallStore } from './useCallStore'; - -interface SimulateCallOptions { - callState?: CallState; - contact?: { - displayName?: string; - username?: string; - sipExtension?: string; - }; - isMuted?: boolean; - isOnHold?: boolean; -} - -const defaultContact = { - displayName: 'Bob Burnquist', - username: 'bob.burnquist', - sipExtension: '2244' -}; - -/** - * Simulates a call for UI development purposes. - * Creates a mock IClientMediaCall object, sets it in the call store, and navigates to CallView. - */ -export const simulateCall = async (options: SimulateCallOptions = {}): Promise<void> => { - const { callState = 'active', contact = defaultContact, isMuted = false, isOnHold = false } = options; - - // Create a simple event emitter for the mock call - const listeners: Record<string, Set<(...args: unknown[]) => void>> = {}; - - const emitter = { - on: (event: string, callback: (...args: unknown[]) => void) => { - if (!listeners[event]) { - listeners[event] = new Set(); - } - listeners[event].add(callback); - }, - off: (event: string, callback: (...args: unknown[]) => void) => { - listeners[event]?.delete(callback); - }, - emit: (event: string, ...args: unknown[]) => { - listeners[event]?.forEach(cb => cb(...args)); - } - }; - - // Track mutable state for the mock - let currentMuted = isMuted; - let currentHeld = isOnHold; - let currentState: CallState = callState; - - const mockCall = { - callId: `mock-call-${Date.now()}`, - state: currentState, - get muted() { - return currentMuted; - }, - get held() { - return currentHeld; - }, - contact: { - displayName: contact.displayName, - username: contact.username, - sipExtension: contact.sipExtension - }, - setMuted: (muted: boolean) => { - currentMuted = muted; - emitter.emit('trackStateChange'); - }, - setHeld: (held: boolean) => { - currentHeld = held; - emitter.emit('trackStateChange'); - }, - hangup: () => { - currentState = 'ended' as CallState; - emitter.emit('ended'); - }, - reject: () => { - currentState = 'ended' as CallState; - emitter.emit('ended'); - }, - sendDTMF: (_digits: string) => { - // No-op for simulation - }, - emitter - } as unknown as IClientMediaCall; - - // Generate a unique callUUID - const callUUID = (await randomUuid()).toLowerCase(); - - // Set up the call store - useCallStore.getState().setCall(mockCall, callUUID); - - // If simulating a specific initial state, update the store - if (isMuted || isOnHold) { - useCallStore.setState({ - isMuted, - isOnHold - }); - } - - // Navigate to CallView - // Navigation.navigate('CallView', { callUUID }); -}; diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index 56bb1c19717..bcd78534605 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -9,7 +9,7 @@ import { hideActionSheetRef } from '../../../containers/ActionSheet'; interface CallStoreState { // Call reference call: IClientMediaCall | null; - callUUID: string | null; + callId: string | null; // Call state callState: CallState; @@ -27,8 +27,8 @@ interface CallStoreState { } interface CallStoreActions { - setCallUUID: (callUUID: string | null) => void; - setCall: (call: IClientMediaCall, callUUID: string) => void; + setCallId: (callId: string | null) => void; + setCall: (call: IClientMediaCall) => void; toggleMute: () => void; toggleHold: () => void; toggleSpeaker: () => void; @@ -42,7 +42,7 @@ export type CallStore = CallStoreState & CallStoreActions; const initialState: CallStoreState = { call: null, - callUUID: null, + callId: null, callState: 'none', isMuted: false, isOnHold: false, @@ -58,15 +58,15 @@ const initialState: CallStoreState = { export const useCallStore = create<CallStore>((set, get) => ({ ...initialState, - setCallUUID: (callUUID: string | null) => { - set({ callUUID }); + setCallId: (callId: string | null) => { + set({ callId }); }, - setCall: (call: IClientMediaCall, callUUID: string) => { + setCall: (call: IClientMediaCall) => { // Update state with call info set({ call, - callUUID, + callId: call.callId, callState: call.state, isMuted: call.muted, isOnHold: call.held, @@ -140,8 +140,8 @@ export const useCallStore = create<CallStore>((set, get) => ({ }, toggleSpeaker: async () => { - const { callUUID, isSpeakerOn } = get(); - if (!callUUID) return; + const { callId, isSpeakerOn } = get(); + if (!callId) return; const newSpeakerOn = !isSpeakerOn; @@ -159,7 +159,7 @@ export const useCallStore = create<CallStore>((set, get) => ({ if (isFocused) { Navigation.back(); } else { - Navigation.navigate('CallView', { callUUID: get().callUUID }); + Navigation.navigate('CallView'); } }, @@ -172,15 +172,16 @@ export const useCallStore = create<CallStore>((set, get) => ({ set({ dialpadValue: newValue }); }, + // TODO: do it here or in MediaSessionInstance? endCall: () => { - const { call, callUUID } = get(); + const { call, callId } = get(); if (call) { call.hangup(); } - if (callUUID) { - RNCallKeep.endCall(callUUID); + if (callId) { + RNCallKeep.endCall(callId); } // Navigation.back(); // TODO: It could be collapsed, so going back woudln't make sense diff --git a/app/stacks/types.ts b/app/stacks/types.ts index 02d606a5833..6996ae91c4f 100644 --- a/app/stacks/types.ts +++ b/app/stacks/types.ts @@ -296,9 +296,7 @@ export type InsideStackParamList = { ModalBlockView: { data: any; // TODO: Change; }; - CallView: { - callUUID: string; - }; + CallView: undefined; }; export type OutsideParamList = { diff --git a/app/views/CallView/CallView.stories.tsx b/app/views/CallView/CallView.stories.tsx index 1fe80b664df..e4a4a18a5ac 100644 --- a/app/views/CallView/CallView.stories.tsx +++ b/app/views/CallView/CallView.stories.tsx @@ -41,7 +41,7 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat useCallStore.setState({ call: mockCall, - callUUID: 'test-uuid', + callId: 'test-id', callState: 'active', isMuted: false, isOnHold: false, diff --git a/app/views/CallView/components/CallerInfo.stories.tsx b/app/views/CallView/components/CallerInfo.stories.tsx index c24c3ac1184..c554a4fa253 100644 --- a/app/views/CallView/components/CallerInfo.stories.tsx +++ b/app/views/CallView/components/CallerInfo.stories.tsx @@ -19,7 +19,7 @@ const setStoreState = (contact: { displayName?: string; username?: string; sipEx useCallStore.setState({ contact, call: {} as any, - callUUID: 'test-uuid', + callId: 'test-id', callState: 'active', isMuted: false, isOnHold: false, diff --git a/app/views/CallView/components/CallerInfo.test.tsx b/app/views/CallView/components/CallerInfo.test.tsx index c411cfa5a3d..7fbc6b88e9f 100644 --- a/app/views/CallView/components/CallerInfo.test.tsx +++ b/app/views/CallView/components/CallerInfo.test.tsx @@ -15,7 +15,7 @@ const setStoreState = (contact: { displayName?: string; username?: string; sipEx useCallStore.setState({ contact, call: {} as any, - callUUID: 'test-uuid', + callId: 'test-id', callState: 'active', isMuted: false, isOnHold: false, diff --git a/app/views/CallView/components/Dialpad/Dialpad.stories.tsx b/app/views/CallView/components/Dialpad/Dialpad.stories.tsx index 5060a0a804e..e17db7cd370 100644 --- a/app/views/CallView/components/Dialpad/Dialpad.stories.tsx +++ b/app/views/CallView/components/Dialpad/Dialpad.stories.tsx @@ -27,7 +27,7 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat useCallStore.setState({ call: mockCall, - callUUID: 'test-uuid', + callId: 'test-id', callState: 'active', dialpadValue: '', ...overrides diff --git a/app/views/CallView/components/Dialpad/Dialpad.test.tsx b/app/views/CallView/components/Dialpad/Dialpad.test.tsx index 557c0b0a464..a0f94e8eec0 100644 --- a/app/views/CallView/components/Dialpad/Dialpad.test.tsx +++ b/app/views/CallView/components/Dialpad/Dialpad.test.tsx @@ -29,7 +29,7 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat useCallStore.setState({ call: mockCall, - callUUID: 'test-uuid', + callId: 'test-id', callState: 'active', dialpadValue: '', ...overrides diff --git a/app/views/CallView/index.test.tsx b/app/views/CallView/index.test.tsx index e303ef3741c..edbd908843f 100644 --- a/app/views/CallView/index.test.tsx +++ b/app/views/CallView/index.test.tsx @@ -61,7 +61,7 @@ const setStoreState = (overrides: Partial<ReturnType<typeof useCallStore.getStat const mockCall = createMockCall(); useCallStore.setState({ call: mockCall as any, - callUUID: 'test-uuid', + callId: 'test-id', callState: 'active', isMuted: false, isOnHold: false, diff --git a/ios/AppDelegate.swift b/ios/AppDelegate.swift index 6bdaefb7b45..43cd51d2c7c 100644 --- a/ios/AppDelegate.swift +++ b/ios/AppDelegate.swift @@ -94,53 +94,3 @@ class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate { #endif } } - -// MARK: - PKPushRegistryDelegate - -extension AppDelegate: PKPushRegistryDelegate { - // Handle updated push credentials - public func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { - // Register VoIP push token (a property of PKPushCredentials) with server - VoipService.didUpdatePushCredentials(credentials, forType: type.rawValue) - } - - public func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { - // The system calls this method when a previously provided push token is no longer valid for use. - // No action is necessary on your part to reregister the push type. - // Instead, use this method to notify your server not to send push notifications using the matching push token. - // TODO: call restapi to unregister the push token - } - - public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { - let callId = payload.dictionaryPayload["callId"] as? String - let caller = payload.dictionaryPayload["caller"] as? String - - guard let callId = callId else { - completion() - return - } - - // Convert callId to deterministic UUID v5 for CallKit - let callIdUUID = CallIdUUID.generateUUIDv5(from: callId) - - // Store pending call data in our native module - VoipService.didReceiveIncomingPush(with: payload, forType: type.rawValue) - - RNCallKeep.reportNewIncomingCall( - callIdUUID, - handle: caller, - handleType: "generic", - hasVideo: true, - localizedCallerName: caller, - supportsHolding: true, - supportsDTMF: true, - supportsGrouping: true, - supportsUngrouping: true, - fromPushKit: true, - payload: payload.dictionaryPayload, - withCompletionHandler: nil - ) - - completion() - } -} diff --git a/ios/Libraries/AppDelegate+Voip.swift b/ios/Libraries/AppDelegate+Voip.swift new file mode 100644 index 00000000000..6ceb69013a0 --- /dev/null +++ b/ios/Libraries/AppDelegate+Voip.swift @@ -0,0 +1,59 @@ +import PushKit + +// MARK: - PKPushRegistryDelegate + +extension AppDelegate: PKPushRegistryDelegate { + + // Handle updated push credentials + public func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { + // Register VoIP push token (a property of PKPushCredentials) with server + VoipService.didUpdatePushCredentials(credentials, forType: type.rawValue) + } + + public func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { + // The system calls this method when a previously provided push token is no longer valid for use. + // No action is necessary on your part to reregister the push type. + // Instead, use this method to notify your server not to send push notifications using the matching push token. + VoipService.invalidatePushToken() + } + + public func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { + let payloadDict = payload.dictionaryPayload + + guard let voipPayload = VoipPayload.fromDictionary(payloadDict) else { + #if DEBUG + print("[\(TAG)] Failed to parse incoming VoIP payload") + #endif + completion() + return + } + + let callId = voipPayload.callId + let caller = voipPayload.caller + guard !voipPayload.isExpired() else { + #if DEBUG + print("[\(TAG)] Skipping expired or invalid VoIP payload for callId: \(callId)") + #endif + completion() + return + } + + VoipService.prepareIncomingCall(voipPayload) + + RNCallKeep.reportNewIncomingCall( + callId, + handle: caller, + handleType: "generic", + hasVideo: false, + localizedCallerName: caller, + supportsHolding: true, + supportsDTMF: true, + supportsGrouping: false, + supportsUngrouping: false, + fromPushKit: true, + payload: payloadDict, + withCompletionHandler: {} + ) + completion() + } +} diff --git a/ios/Libraries/CallIdUUID.m b/ios/Libraries/CallIdUUID.m deleted file mode 100644 index 019b69f4938..00000000000 --- a/ios/Libraries/CallIdUUID.m +++ /dev/null @@ -1,7 +0,0 @@ -#import <React/RCTBridgeModule.h> - -@interface RCT_EXTERN_MODULE(CallIdUUID, NSObject) - -RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(toUUID:(NSString *)callId) - -@end diff --git a/ios/Libraries/CallIdUUID.swift b/ios/Libraries/CallIdUUID.swift deleted file mode 100644 index 8318e45d36b..00000000000 --- a/ios/Libraries/CallIdUUID.swift +++ /dev/null @@ -1,67 +0,0 @@ -import Foundation -import CommonCrypto - -/** - * CallIdUUID - Converts a callId string to a deterministic UUID v5. - * This is used by CallKit which requires UUIDs, while the server sends random callId strings. - */ -@objc(CallIdUUID) -final class CallIdUUID: NSObject { - - // Fixed namespace UUID for VoIP calls (RFC 4122 URL namespace) - // Using the standard URL namespace UUID: 6ba7b811-9dad-11d1-80b4-00c04fd430c8 - private static let namespaceUUID: [UInt8] = [ - 0x6b, 0xa7, 0xb8, 0x11, - 0x9d, 0xad, - 0x11, 0xd1, - 0x80, 0xb4, - 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 - ] - - @objc - static func requiresMainQueueSetup() -> Bool { - return false - } - - /** - * Converts a callId string to a deterministic UUID v5 string. - * Uses SHA-1 hash of namespace + callId, then formats as UUID v5. - * This is a synchronous method for use from JavaScript. - */ - @objc - func toUUID(_ callId: String) -> String { - return CallIdUUID.generateUUIDv5(from: callId) - } - - /** - * Static method for use in AppDelegate and other native code. - * Generates a UUID v5 from a callId string. - */ - static func generateUUIDv5(from callId: String) -> String { - // Concatenate namespace UUID bytes with callId UTF-8 bytes - var data = Data(namespaceUUID) - data.append(callId.data(using: .utf8) ?? Data()) - - // SHA-1 hash - var hash = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH)) - data.withUnsafeBytes { dataBytes in - _ = CC_SHA1(dataBytes.baseAddress, CC_LONG(data.count), &hash) - } - - // Set version (4 bits) to 5 (0101) - hash[6] = (hash[6] & 0x0F) | 0x50 - - // Set variant (2 bits) to 10 - hash[8] = (hash[8] & 0x3F) | 0x80 - - // Format as UUID string (only use first 16 bytes) - let uuid = String(format: "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - hash[0], hash[1], hash[2], hash[3], - hash[4], hash[5], - hash[6], hash[7], - hash[8], hash[9], - hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]) - - return uuid - } -} diff --git a/ios/Libraries/DDPClient.swift b/ios/Libraries/DDPClient.swift new file mode 100644 index 00000000000..ffebef6df48 --- /dev/null +++ b/ios/Libraries/DDPClient.swift @@ -0,0 +1,391 @@ +import Foundation + +/// Minimal DDP WebSocket client for listening to Rocket.Chat media-signal events from native iOS. +/// Only implements the subset needed to detect call hangup: connect, login, subscribe, and ping/pong. +final class DDPClient { + private struct QueuedMethodCall { + let method: String + let params: [Any] + let completion: (Bool) -> Void + } + + private static let TAG = "RocketChat.DDPClient" + private let stateQueueKey = DispatchSpecificKey<Void>() + private let stateQueue = DispatchQueue(label: "chat.rocket.reactnative.ddp-client") + + private var webSocketTask: URLSessionWebSocketTask? + private var urlSession: URLSession? + private var sendCounter = 0 + private var isConnected = false + + /// Called for every incoming DDP collection message (e.g. stream-notify-user). + var onCollectionMessage: (([String: Any]) -> Void)? + + init() { + stateQueue.setSpecific(key: stateQueueKey, value: ()) + } + + // MARK: - Connect + + func connect(host: String, completion: @escaping (Bool) -> Void) { + stateQueue.async { + let wsUrl = Self.buildWebSocketURL(host: host) + + guard let url = URL(string: wsUrl) else { + #if DEBUG + print("[\(Self.TAG)] Invalid WebSocket URL: \(wsUrl)") + #endif + completion(false) + return + } + + #if DEBUG + print("[\(Self.TAG)] Connecting to \(wsUrl)") + #endif + + let session = URLSession(configuration: .default) + let task = session.webSocketTask(with: url) + + self.urlSession = session + self.webSocketTask = task + self.isConnected = false + task.resume() + + self.listenForMessages(task: task) + + let connectMsg: [String: Any] = [ + "msg": "connect", + "version": "1", + "support": ["1", "pre2", "pre1"] + ] + + self.send(connectMsg) { [weak self] success in + guard let self else { return } + if success { + self.waitForConnected(timeout: 10.0, completion: completion) + } else { + completion(false) + } + } + } + } + + // MARK: - Login + + func login(token: String, completion: @escaping (Bool) -> Void) { + stateQueue.async { + let msg = self.nextMessage(msg: "method", extra: [ + "method": "login", + "params": [["resume": token]] + ]) + + let msgId = msg["id"] as? String + + self.pendingCallbacks[msgId ?? ""] = { [weak self] data in + self?.pendingCallbacks.removeValue(forKey: msgId ?? "") + let hasError = data["error"] != nil + #if DEBUG + if hasError { + print("[\(Self.TAG)] Login failed: \(data["error"] ?? "unknown")") + } else { + print("[\(Self.TAG)] Login succeeded") + } + #endif + completion(!hasError) + } + + self.send(msg) { [weak self] success in + guard let self else { return } + if !success { + self.stateQueue.async { + self.pendingCallbacks.removeValue(forKey: msgId ?? "") + completion(false) + } + } + } + } + } + + // MARK: - Subscribe + + func subscribe(name: String, params: [Any], completion: @escaping (Bool) -> Void) { + stateQueue.async { + let msg = self.nextMessage(msg: "sub", extra: [ + "name": name, + "params": params + ]) + + let msgId = msg["id"] as? String + + self.pendingCallbacks[msgId ?? ""] = { [weak self] data in + self?.pendingCallbacks.removeValue(forKey: msgId ?? "") + let didSubscribe = (data["msg"] as? String) == "ready" && data["error"] == nil + #if DEBUG + if didSubscribe { + print("[\(Self.TAG)] Subscribed to \(name)") + } else { + print("[\(Self.TAG)] Failed to subscribe to \(name): \(data["error"] ?? "nosub")") + } + #endif + completion(didSubscribe) + } + + self.send(msg) { [weak self] success in + guard let self else { return } + if !success { + self.stateQueue.async { + self.pendingCallbacks.removeValue(forKey: msgId ?? "") + completion(false) + } + } + } + } + } + + // MARK: - Disconnect + + func disconnect() { + stateQueue.async { + #if DEBUG + print("[\(Self.TAG)] Disconnecting") + #endif + self.isConnected = false + self.pendingCallbacks.removeAll() + self.clearQueuedMethodCalls() + self.connectedCallback = nil + self.onCollectionMessage = nil + self.webSocketTask?.cancel(with: .normalClosure, reason: nil) + self.webSocketTask = nil + self.urlSession?.invalidateAndCancel() + self.urlSession = nil + } + } + + // MARK: - Private + + private var pendingCallbacks: [String: ([String: Any]) -> Void] = [:] + private var queuedMethodCalls: [QueuedMethodCall] = [] + private var connectedCallback: ((Bool) -> Void)? + + private func nextMessage(msg: String, extra: [String: Any] = [:]) -> [String: Any] { + sendCounter += 1 + var dict: [String: Any] = ["msg": msg, "id": "ddp-\(sendCounter)"] + for (key, value) in extra { + dict[key] = value + } + return dict + } + + private func send(_ dict: [String: Any], completion: @escaping (Bool) -> Void) { + guard let data = try? JSONSerialization.data(withJSONObject: dict), + let string = String(data: data, encoding: .utf8) else { + completion(false) + return + } + + guard let webSocketTask else { + completion(false) + return + } + + webSocketTask.send(.string(string)) { error in + if let error = error { + #if DEBUG + print("[\(Self.TAG)] Send error: \(error.localizedDescription)") + #endif + completion(false) + } else { + completion(true) + } + } + } + + func callMethod(_ method: String, params: [Any], completion: @escaping (Bool) -> Void) { + stateQueue.async { + let msg = self.nextMessage(msg: "method", extra: [ + "method": method, + "params": params + ]) + + let msgId = msg["id"] as? String + + self.pendingCallbacks[msgId ?? ""] = { [weak self] data in + self?.pendingCallbacks.removeValue(forKey: msgId ?? "") + let hasError = data["error"] != nil + #if DEBUG + if hasError { + print("[\(Self.TAG)] Method \(method) failed: \(data["error"] ?? "unknown")") + } + #endif + completion(!hasError) + } + + self.send(msg) { [weak self] success in + guard let self else { return } + if !success { + self.stateQueue.async { + self.pendingCallbacks.removeValue(forKey: msgId ?? "") + completion(false) + } + } + } + } + } + + func queueMethodCall(_ method: String, params: [Any], completion: @escaping (Bool) -> Void = { _ in }) { + stateQueue.async { + self.queuedMethodCalls.append( + QueuedMethodCall( + method: method, + params: params, + completion: completion + ) + ) + } + } + + func hasQueuedMethodCalls() -> Bool { + if DispatchQueue.getSpecific(key: stateQueueKey) != nil { + return !queuedMethodCalls.isEmpty + } + + return stateQueue.sync { + !queuedMethodCalls.isEmpty + } + } + + func flushQueuedMethodCalls() { + stateQueue.async { + let queuedCalls = self.queuedMethodCalls + self.queuedMethodCalls.removeAll() + + queuedCalls.forEach { queuedCall in + self.callMethod(queuedCall.method, params: queuedCall.params, completion: queuedCall.completion) + } + } + } + + func clearQueuedMethodCalls() { + if DispatchQueue.getSpecific(key: stateQueueKey) != nil { + queuedMethodCalls.removeAll() + return + } + + stateQueue.async { + self.queuedMethodCalls.removeAll() + } + } + + private func waitForConnected(timeout: TimeInterval, completion: @escaping (Bool) -> Void) { + connectedCallback = completion + DispatchQueue.main.asyncAfter(deadline: .now() + timeout) { [weak self] in + self?.stateQueue.async { + guard let self = self, let cb = self.connectedCallback else { return } + self.connectedCallback = nil + #if DEBUG + print("[\(Self.TAG)] Connect timeout") + #endif + cb(false) + } + } + } + + private func listenForMessages(task: URLSessionWebSocketTask) { + task.receive { [weak self] result in + self?.stateQueue.async { + guard let self = self, let currentTask = self.webSocketTask, task === currentTask else { return } + + switch result { + case .success(let message): + switch message { + case .string(let text): + self.handleMessage(text) + default: + break + } + self.listenForMessages(task: task) + + case .failure(let error): + #if DEBUG + print("[\(Self.TAG)] Receive error: \(error.localizedDescription)") + #endif + } + } + } + } + + private func handleMessage(_ text: String) { + guard let data = text.data(using: .utf8), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + return + } + + let msg = json["msg"] as? String + + switch msg { + case "connected": + isConnected = true + if let cb = connectedCallback { + connectedCallback = nil + cb(true) + } + + case "ping": + send(["msg": "pong"]) { _ in } + + case "result": + if let id = json["id"] as? String, let cb = pendingCallbacks[id] { + cb(json) + } + + case "ready": + if let subs = json["subs"] as? [String] { + subs.forEach { subId in + pendingCallbacks[subId]?(json) + } + } + + case "changed", "added", "removed": + if let collection = json["collection"] as? String { + var message = json + message["collection"] = collection + onCollectionMessage?(message) + } + + case "nosub": + if let id = json["id"] as? String, let cb = pendingCallbacks[id] { + cb(json) + } + + default: + if let collection = json["collection"] as? String { + onCollectionMessage?(json) + _ = collection + } + } + } + + // MARK: - URL Helpers + + private static func buildWebSocketURL(host: String) -> String { + var cleaned = host + + if cleaned.hasSuffix("/") { + cleaned = String(cleaned.dropLast()) + } + + let useSsl: Bool + if cleaned.hasPrefix("https://") { + useSsl = true + cleaned = String(cleaned.dropFirst("https://".count)) + } else if cleaned.hasPrefix("http://") { + useSsl = false + cleaned = String(cleaned.dropFirst("http://".count)) + } else { + useSsl = true + } + + let scheme = useSsl ? "wss" : "ws" + return "\(scheme)://\(cleaned)/websocket" + } +} diff --git a/ios/Libraries/VoipModule.mm b/ios/Libraries/VoipModule.mm index 2c3ff8cda89..bb2f6953305 100644 --- a/ios/Libraries/VoipModule.mm +++ b/ios/Libraries/VoipModule.mm @@ -11,6 +11,8 @@ @interface VoipService : NSObject + (void)voipRegistration; + (NSDictionary * _Nullable)getInitialEvents; + (void)clearInitialEvents; ++ (NSString * _Nonnull)getLastVoipToken; ++ (void)stopDDPClient; @end @implementation VoipModule { @@ -89,6 +91,14 @@ - (void)clearInitialEvents { [VoipService clearInitialEvents]; } +- (NSString * _Nonnull)getLastVoipToken { + return [VoipService getLastVoipToken]; +} + +- (void)stopNativeDDPClient { + [VoipService stopDDPClient]; +} + - (void)addListener:(NSString *)eventName { // Required for NativeEventEmitter - starts observing } diff --git a/ios/Libraries/VoipPayload.swift b/ios/Libraries/VoipPayload.swift new file mode 100644 index 00000000000..f7769e97222 --- /dev/null +++ b/ios/Libraries/VoipPayload.swift @@ -0,0 +1,210 @@ +import Foundation + +private struct RemoteCaller { + let name: String? + let username: String? + let avatarUrl: String? + + static func fromDictionary(_ payload: [AnyHashable: Any]) -> RemoteCaller { + RemoteCaller( + name: payload["name"] as? String, + username: payload["username"] as? String, + avatarUrl: payload["avatarUrl"] as? String + ) + } +} + +private struct RemoteVoipPayload { + let callId: String? + let caller: RemoteCaller? + let username: String? + let host: String? + let type: String? + let hostName: String? + let notificationType: String? + let createdAt: String? + + static func fromDictionary(_ payload: [AnyHashable: Any]) -> RemoteVoipPayload { + let caller = (payload["caller"] as? [AnyHashable: Any]).map(RemoteCaller.fromDictionary) + + return RemoteVoipPayload( + callId: payload["callId"] as? String, + caller: caller, + username: payload["username"] as? String, + host: payload["host"] as? String, + type: payload["type"] as? String, + hostName: payload["hostName"] as? String, + notificationType: payload["notificationType"] as? String, + createdAt: payload["createdAt"] as? String + ) + } + + func toVoipPayload() -> VoipPayload? { + guard notificationType == "voip" else { + return nil + } + + guard + let payloadCallId = callId, + let payloadCallUUID = UUID(uuidString: payloadCallId), + let payloadCaller = caller?.name, + let payloadUsername = caller?.username ?? username, + let payloadHost = host, + let payloadType = type, + let payloadHostName = hostName, + let payloadCreatedAt = createdAt, + !payloadCreatedAt.isEmpty + else { + return nil + } + + return VoipPayload( + callId: payloadCallId, + callUUID: payloadCallUUID, + caller: payloadCaller, + username: payloadUsername, + host: payloadHost, + type: payloadType, + hostName: payloadHostName, + avatarUrl: caller?.avatarUrl, + createdAt: payloadCreatedAt + ) + } +} + +/// Data structure for initial events payload +@objc(VoipPayload) +public class VoipPayload: NSObject { + // the amount of time in seconds that an incoming call will be kept alive + @objc public static let INCOMING_CALL_LIFETIME_SEC: TimeInterval = 60 + + @objc public let callId: String + let callUUID: UUID + @objc public let caller: String + @objc public let username: String + @objc public let host: String + @objc public let type: String + @objc public let hostName: String + @objc public let avatarUrl: String? + @objc public let createdAt: String? + + private var createdAtDate: Date? { + return Self.parseCreatedAt(createdAt) + } + + private var expiresAt: Date? { + return createdAtDate?.addingTimeInterval(Self.INCOMING_CALL_LIFETIME_SEC) + } + + private static let iso8601FormatterWithFractionalSeconds: ISO8601DateFormatter = { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] + formatter.timeZone = TimeZone(secondsFromGMT: 0) + return formatter + }() + + private static let iso8601Formatter: ISO8601DateFormatter = { + let formatter = ISO8601DateFormatter() + formatter.formatOptions = [.withInternetDateTime] + formatter.timeZone = TimeZone(secondsFromGMT: 0) + return formatter + }() + + @objc public var notificationId: Int { + return Self.stableNotificationId(for: callId) + } + + /// Deterministic hash for consistent notification IDs across app launches. + /// Matches Java/Kotlin String.hashCode() semantics over UTF-16 code units. + private static func stableNotificationId(for value: String) -> Int { + var hash: Int32 = 0 + for codeUnit in value.utf16 { + hash = (31 &* hash) &+ Int32(codeUnit) + } + return Int(hash) + } + + init(callId: String, callUUID: UUID, caller: String, username: String, host: String, type: String, hostName: String, avatarUrl: String?, createdAt: String?) { + self.callId = callId + self.callUUID = callUUID + self.caller = caller + self.username = username + self.host = host + self.type = type + self.hostName = hostName + self.avatarUrl = avatarUrl + self.createdAt = createdAt + super.init() + } + + @objc + public func isVoipIncomingCall() -> Bool { + return type == "incoming_call" && !callId.isEmpty && !caller.isEmpty && !host.isEmpty + } + + @objc + public func toDictionary() -> [String: Any] { + return [ + "callId": callId, + "caller": caller, + "username": username, + "host": host, + "type": type, + "hostName": hostName, + "avatarUrl": avatarUrl ?? NSNull(), + "createdAt": createdAt ?? NSNull(), + "notificationId": notificationId + ] + } + + public func remainingLifetime(now: Date = Date()) -> TimeInterval? { + guard let expiresAt else { + return nil + } + + return max(0, expiresAt.timeIntervalSince(now)) + } + + public func isExpired(now: Date = Date()) -> Bool { + guard let remainingLifetime = remainingLifetime(now: now) else { + return true + } + + return remainingLifetime <= 0 + } + + @objc + public static func fromDictionary(_ dict: [AnyHashable: Any]) -> VoipPayload? { + if let parsedPayload = parseRemotePayload(from: dict).toVoipPayload() { + return parsedPayload + } + + guard + let ejsonString = dict["ejson"] as? String, + !ejsonString.isEmpty, + ejsonString != "{}", + let data = ejsonString.data(using: .utf8), + let ejsonPayload = (try? JSONSerialization.jsonObject(with: data)) as? [AnyHashable: Any] + else { + return nil + } + + return parseRemotePayload(from: ejsonPayload).toVoipPayload() + } + + private static func parseRemotePayload(from payload: [AnyHashable: Any]) -> RemoteVoipPayload { + return RemoteVoipPayload.fromDictionary(payload) + } + + private static func parseCreatedAt(_ value: String?) -> Date? { + guard let value, !value.isEmpty else { + return nil + } + + if let parsed = iso8601FormatterWithFractionalSeconds.date(from: value) { + return parsed + } + + return iso8601Formatter.date(from: value) + } +} diff --git a/ios/Libraries/VoipService.swift b/ios/Libraries/VoipService.swift index 05510d27a83..8db99f60731 100644 --- a/ios/Libraries/VoipService.swift +++ b/ios/Libraries/VoipService.swift @@ -1,3 +1,4 @@ +import CallKit import Foundation import PushKit @@ -12,18 +13,35 @@ import PushKit */ @objc(VoipService) public final class VoipService: NSObject { + private struct ObservedIncomingCall { + let payload: VoipPayload + } + + private final class IncomingCallObserver: NSObject, CXCallObserverDelegate { + func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) { + VoipService.handleObservedCallChanged(call) + } + } // MARK: - Constants - private static let TAG = "RocketChat.VoipModule" + private static let TAG = "RocketChat.VoipService" + private static let voipTokenStorageKey = "RCVoipPushToken" + private static let storage = MMKVBridge.build() // MARK: - Static Properties private static var initialEventsData: VoipPayload? - private static var initialEventsTimestamp: TimeInterval = 0 private static var isVoipRegistered = false - private static var lastVoipToken: String = "" + private static var lastVoipToken: String = loadPersistedVoipToken() private static var voipRegistry: PKPushRegistry? + private static var incomingCallTimeouts: [String: DispatchWorkItem] = [:] + private static var ddpClient: DDPClient? + private static let callObserver = CXCallObserver() + private static let incomingCallObserver = IncomingCallObserver() + private static var isCallObserverConfigured = false + private static var observedIncomingCall: ObservedIncomingCall? + private static var isDdpLoggedIn = false // MARK: - Static Methods (Called from VoipModule.mm and AppDelegate) @@ -64,7 +82,16 @@ public final class VoipService: NSObject { // Convert token data to hex string let token = credentials.token.map { String(format: "%02x", $0) }.joined() + + if lastVoipToken == token { + #if DEBUG + print("[\(TAG)] VoIP token unchanged") + #endif + return + } + lastVoipToken = token + persistVoipToken(token) #if DEBUG print("[\(TAG)] VoIP token: \(token)") @@ -77,35 +104,37 @@ public final class VoipService: NSObject { userInfo: ["token": token] ) } - - /// Called from AppDelegate when a VoIP push initial events are received + + /// Called from AppDelegate when a previously registered token is invalidated + // TODO: remove voip token from all logged in workspaces, since they share the same token @objc - public static func didReceiveIncomingPush(with payload: PKPushPayload, forType type: String) { + public static func invalidatePushToken() { + lastVoipToken = "" + storage.removeValue(forKey: voipTokenStorageKey) + #if DEBUG - print("[\(TAG)] didReceiveIncomingPush payload: \(payload.dictionaryPayload)") + print("[\(TAG)] Invalidated VoIP token") #endif - - guard let voipPayload = VoipPayload.fromDictionary(payload.dictionaryPayload) else { - #if DEBUG - print("[\(TAG)] Failed to parse VoIP payload") - #endif - return - } - - storeInitialEvents(voipPayload) } + + public static func prepareIncomingCall(_ payload: VoipPayload) { + storeInitialEvents(payload) + scheduleIncomingCallTimeout(for: payload) + startListeningForCallEnd(payload: payload) + } + + // MARK: - Initial Events /// Stores initial events for JS to retrieve. @objc public static func storeInitialEvents(_ payload: VoipPayload) { initialEventsData = payload - initialEventsTimestamp = Date().timeIntervalSince1970 #if DEBUG print("[\(TAG)] Stored initial events: \(payload.callId)") #endif } - + /// Gets any initial events. Returns nil if no initial events. @objc public static func getInitialEvents() -> [String: Any]? { @@ -113,9 +142,7 @@ public final class VoipService: NSObject { return nil } - // Check if data is older than 5 minutes - let now = Date().timeIntervalSince1970 - if now - initialEventsTimestamp > 5 * 60 { + if data.isExpired() { clearInitialEventsInternal() return nil } @@ -135,75 +162,348 @@ public final class VoipService: NSObject { /// Clears initial events (internal) private static func clearInitialEventsInternal() { initialEventsData = nil - initialEventsTimestamp = 0 #if DEBUG print("[\(TAG)] Cleared initial events") #endif } - + + // MARK: - VoIP Token + /// Returns the last registered VoIP token @objc public static func getLastVoipToken() -> String { + if lastVoipToken.isEmpty { + lastVoipToken = loadPersistedVoipToken() + } return lastVoipToken } -} -// MARK: - VoipPayload + private static func loadPersistedVoipToken() -> String { + return storage.string(forKey: voipTokenStorageKey) ?? "" + } -/// Data structure for initial events payload -@objc(VoipPayload) -public class VoipPayload: NSObject { - @objc public let callId: String - @objc public let caller: String - @objc public let host: String - @objc public let type: String - - @objc public var notificationId: Int { - return callId.hashValue + private static func persistVoipToken(_ token: String) { + storage.setString(token, forKey: voipTokenStorageKey) } - - @objc public var callUUID: String { - return CallIdUUID.generateUUIDv5(from: callId) + + // MARK: - Incoming Call Timeout + + public static func scheduleIncomingCallTimeout(for payload: VoipPayload) { + guard let delay = payload.remainingLifetime(), delay > 0 else { + #if DEBUG + print("[\(TAG)] Skipping incoming call timeout for expired or invalid payload: \(payload.callId)") + #endif + return + } + + cancelIncomingCallTimeout(for: payload.callId) + + let workItem = DispatchWorkItem { + handleIncomingCallTimeout(for: payload) + } + + incomingCallTimeouts[payload.callId] = workItem + DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: workItem) + + #if DEBUG + print("[\(TAG)] Scheduled incoming call timeout for \(payload.callId) in \(delay)s") + #endif } - - @objc - public init(callId: String, caller: String, host: String, type: String) { - self.callId = callId - self.caller = caller - self.host = host - self.type = type - super.init() + + private static func cancelIncomingCallTimeout(for callId: String) { + incomingCallTimeouts.removeValue(forKey: callId)?.cancel() } - - @objc - public func isVoipIncomingCall() -> Bool { - return type == "incoming_call" && !callId.isEmpty && !caller.isEmpty && !host.isEmpty + + private static func handleIncomingCallTimeout(for payload: VoipPayload) { + incomingCallTimeouts.removeValue(forKey: payload.callId) + clearTrackedIncomingCall(for: payload.callUUID) + stopDDPClientInternal() + + let callId = payload.callId + let callUUID = payload.callUUID + + configureCallObserverIfNeeded() + guard let call = callObserver.calls.first(where: { $0.uuid == callUUID }) else { + return + } + + guard !call.hasConnected, !call.hasEnded else { + return + } + + RNCallKeep.endCall(withUUID: callId, reason: 3) } - - @objc - public func toDictionary() -> [String: Any] { - return [ - "callId": callId, - "caller": caller, - "host": host, - "type": type, - "callUUID": callUUID, - "notificationId": notificationId - ] + + // MARK: - Native DDP Listener (Call End Detection) + + /// Opens a lightweight DDP WebSocket to detect call hangup before JS boots. + private static func startListeningForCallEnd(payload: VoipPayload) { + stopDDPClientInternal() + + let credentialStorage = Storage() + guard let credentials = credentialStorage.getCredentials(server: payload.host.removeTrailingSlash()) else { + #if DEBUG + print("[\(TAG)] No credentials for \(payload.host), skipping DDP listener") + #endif + return + } + + let callId = payload.callId + let userId = credentials.userId + let deviceId = DeviceUID.uid() + let client = DDPClient() + ddpClient = client + isDdpLoggedIn = false + trackIncomingCall(payload) + + #if DEBUG + print("[\(TAG)] Starting DDP listener for call \(callId)") + #endif + + client.onCollectionMessage = { message in + guard ddpClient === client else { + return + } + guard let fields = message["fields"] as? [String: Any], + let eventName = fields["eventName"] as? String, + eventName.hasSuffix("/media-signal"), + let args = fields["args"] as? [Any], + let firstArg = args.first as? [String: Any], + let signalType = firstArg["type"] as? String, + signalType == "notification", + let signalCallId = firstArg["callId"] as? String, + signalCallId == callId + else { + return + } + + let signalNotification = firstArg["notification"] as? String + let signedContractId = firstArg["signedContractId"] as? String + + let isHangup = signalNotification == "hangup" + let isAcceptedOnAnotherDevice = signedContractId != nil && signedContractId != deviceId + + guard isHangup || isAcceptedOnAnotherDevice else { + return + } + + #if DEBUG + print("[\(TAG)] DDP received hangup for call or accepted from another device \(callId)") + #endif + + DispatchQueue.main.async { + guard ddpClient === client else { + return + } + clearTrackedIncomingCall(for: payload.callUUID) + RNCallKeep.endCall(withUUID: callId, reason: 3) + cancelIncomingCallTimeout(for: callId) + stopDDPClientInternal() + } + } + + client.connect(host: payload.host) { connected in + guard ddpClient === client else { + return + } + guard connected else { + #if DEBUG + print("[\(TAG)] DDP connection failed") + #endif + stopDDPClientInternal() + return + } + + client.login(token: credentials.userToken) { loggedIn in + guard ddpClient === client else { + return + } + guard loggedIn else { + #if DEBUG + print("[\(TAG)] DDP login failed") + #endif + stopDDPClientInternal() + return + } + + isDdpLoggedIn = true + if flushPendingRejectSignalIfNeeded() { + return + } + + let params: [Any] = [ + "\(userId)/media-signal", + ["useCollection": false, "args": [false]] + ] + + client.subscribe(name: "stream-notify-user", params: params) { subscribed in + guard ddpClient === client else { + return + } + #if DEBUG + print("[\(TAG)] DDP subscribe result: \(subscribed)") + #endif + if !subscribed { + stopDDPClientInternal() + } + } + } + } } - + + /// Stops the native DDP listener. Called from JS when it takes over signaling. @objc - public static func fromDictionary(_ dict: [AnyHashable: Any]) -> VoipPayload? { - guard let type = dict["type"] as? String, - let callId = dict["callId"] as? String, - type == "incoming_call", - !callId.isEmpty else { + public static func stopDDPClient() { + #if DEBUG + print("[\(TAG)] stopDDPClient called from JS") + #endif + stopDDPClientInternal() + } + + private static func stopDDPClientInternal() { + isDdpLoggedIn = false + observedIncomingCall = nil + ddpClient?.clearQueuedMethodCalls() + ddpClient?.disconnect() + ddpClient = nil + } + + private static func buildRejectMethodParams(payload: VoipPayload) -> [Any]? { + let credentialStorage = Storage() + guard let credentials = credentialStorage.getCredentials(server: payload.host.removeTrailingSlash()) else { + #if DEBUG + print("[\(TAG)] Missing credentials, cannot send reject for \(payload.callId)") + #endif + stopDDPClientInternal() return nil } - - let caller = dict["caller"] as? String ?? "" - let host = dict["host"] as? String ?? "" - - return VoipPayload(callId: callId, caller: caller, host: host, type: type) + + let signal: [String: Any] = [ + "callId": payload.callId, + "contractId": DeviceUID.uid(), + "type": "answer", + "answer": "reject" + ] + + guard + let signalData = try? JSONSerialization.data(withJSONObject: signal), + let signalString = String(data: signalData, encoding: .utf8) + else { + stopDDPClientInternal() + return nil + } + + return ["\(credentials.userId)/media-calls", signalString] + } + + private static func sendRejectSignal(payload: VoipPayload) { + guard let client = ddpClient else { + #if DEBUG + print("[\(TAG)] Native DDP client unavailable, cannot send reject for \(payload.callId)") + #endif + return + } + + guard let params = buildRejectMethodParams(payload: payload) else { + return + } + + client.callMethod("stream-notify-user", params: params) { success in + #if DEBUG + print("[\(TAG)] Native reject signal result for \(payload.callId): \(success)") + #endif + stopDDPClientInternal() + } + } + + private static func queueRejectSignal(payload: VoipPayload) { + guard let client = ddpClient else { + #if DEBUG + print("[\(TAG)] Native DDP client unavailable, cannot queue reject for \(payload.callId)") + #endif + return + } + + guard let params = buildRejectMethodParams(payload: payload) else { + return + } + + client.queueMethodCall("stream-notify-user", params: params) { success in + #if DEBUG + print("[\(TAG)] Queued native reject signal result for \(payload.callId): \(success)") + #endif + stopDDPClientInternal() + } + } + + private static func flushPendingRejectSignalIfNeeded() -> Bool { + guard let client = ddpClient, client.hasQueuedMethodCalls() else { + return false + } + + client.flushQueuedMethodCalls() + return true + } + + private static func configureCallObserverIfNeeded() { + guard !isCallObserverConfigured else { + return + } + + callObserver.setDelegate(incomingCallObserver, queue: .main) + isCallObserverConfigured = true + } + + private static func trackIncomingCall(_ payload: VoipPayload) { + let trackCall = { + configureCallObserverIfNeeded() + observedIncomingCall = ObservedIncomingCall(payload: payload) + } + + if Thread.isMainThread { + trackCall() + } else { + DispatchQueue.main.async(execute: trackCall) + } + } + + private static func clearTrackedIncomingCall(for callUUID: UUID) { + let clearCall = { + guard observedIncomingCall?.payload.callUUID == callUUID else { + return + } + + observedIncomingCall = nil + } + + if Thread.isMainThread { + clearCall() + } else { + DispatchQueue.main.async(execute: clearCall) + } + } + + private static func handleObservedCallChanged(_ call: CXCall) { + guard let observedCall = observedIncomingCall, observedCall.payload.callUUID == call.uuid else { + return + } + + if call.hasConnected { + observedIncomingCall = nil + return + } + + guard call.hasEnded else { + return + } + + observedIncomingCall = nil + cancelIncomingCallTimeout(for: observedCall.payload.callId) + + if isDdpLoggedIn { + sendRejectSignal(payload: observedCall.payload) + } else { + queueRejectSignal(payload: observedCall.payload) + } } } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 3c31f0c4908..b5ba945299a 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -3177,7 +3177,7 @@ SPEC CHECKSUMS: React-timing: 2d07431f1c1203c5b0aaa6dc7b5f503704519218 React-utils: 67cf7dcfc18aa4c56bec19e11886033bb057d9fa ReactAppDependencyProvider: bf62814e0fde923f73fc64b7e82d76c63c284da9 - ReactCodegen: 5c6b68a6cfdfce6b69a8b12d2eb93e1117d96113 + ReactCodegen: 5e787c775647706c2d66bf5a77bcdd49624aaf34 ReactCommon: 177fca841e97b2c0e288e86097b8be04c6e7ae36 ReactNativeIncallManager: dccd3e7499caa3bb73d3acfedf4fb0360f1a87d5 RNBootSplash: 1280eeb18d887de0a45bb4923d4fc56f25c8b99c diff --git a/ios/RocketChatRN-Bridging-Header.h b/ios/RocketChatRN-Bridging-Header.h index a4434b7fd77..0c10d8e72ff 100644 --- a/ios/RocketChatRN-Bridging-Header.h +++ b/ios/RocketChatRN-Bridging-Header.h @@ -7,6 +7,7 @@ #import "MMKVKeyManager.h" #import "Shared/RocketChat/MMKVBridge.h" #import <RNBootSplash.h> +#import <RNDeviceInfo/DeviceUID.h> #import <MobileCrypto/RSACrypto.h> #import <MobileCrypto/AESCrypto.h> #import <MobileCrypto/RandomUtils.h> diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj index 8e0336f1f18..139b1bb5d7f 100644 --- a/ios/RocketChatRN.xcodeproj/project.pbxproj +++ b/ios/RocketChatRN.xcodeproj/project.pbxproj @@ -301,10 +301,10 @@ 7A0D62D2242AB187006D5C06 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */; }; 7A14FCED257FEB3A005BDCD4 /* Experimental.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A14FCEC257FEB3A005BDCD4 /* Experimental.xcassets */; }; 7A14FCF4257FEB59005BDCD4 /* Official.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A14FCF3257FEB59005BDCD4 /* Official.xcassets */; }; - 7A3F4C6B2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F4C6A2F1AAFA700B6B4BD /* CallIdUUID.swift */; }; - 7A3F4C6C2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F4C692F1AAFA700B6B4BD /* CallIdUUID.m */; }; - 7A3F4C6D2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F4C6A2F1AAFA700B6B4BD /* CallIdUUID.swift */; }; - 7A3F4C6E2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F4C692F1AAFA700B6B4BD /* CallIdUUID.m */; }; + 7A1B58412F5F58FF002A6BDE /* VoipPayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1B58402F5F58FF002A6BDE /* VoipPayload.swift */; }; + 7A1B58422F5F58FF002A6BDE /* VoipPayload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1B58402F5F58FF002A6BDE /* VoipPayload.swift */; }; + 7A1B58442F5F63DB002A6BDE /* AppDelegate+Voip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1B58432F5F63DB002A6BDE /* AppDelegate+Voip.swift */; }; + 7A1B58452F5F63DB002A6BDE /* AppDelegate+Voip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1B58432F5F63DB002A6BDE /* AppDelegate+Voip.swift */; }; 7A610CD227ECE38100B8ABDD /* custom.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7A610CD127ECE38100B8ABDD /* custom.ttf */; }; 7A610CD427ECE38100B8ABDD /* custom.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7A610CD127ECE38100B8ABDD /* custom.ttf */; }; 7A610CD527ECE38100B8ABDD /* custom.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7A610CD127ECE38100B8ABDD /* custom.ttf */; }; @@ -371,7 +371,9 @@ A48B46D92D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; A48B46DA2D3FFBD200945489 /* A11yFlowModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A48B46D82D3FFBD200945489 /* A11yFlowModule.m */; }; AC6086DB073443D98330ED08 /* Pods_defaults_NotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 112EC394C611BEEA2867A6D3 /* Pods_defaults_NotificationService.framework */; }; + AE692FD072A44EA955D0C0D8 /* DDPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BE2F3DC02A264F204E3EDE3 /* DDPClient.swift */; }; BC404914E86821389EEB543D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 391C4F7AA7023CD41EEBD106 /* ExpoModulesProvider.swift */; }; + CE4453310C9A08AB0DAC2307 /* DDPClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BE2F3DC02A264F204E3EDE3 /* DDPClient.swift */; }; DD2BA30A89E64F189C2C24AC /* libWatermelonDB.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA7E862283664608B3894E34 /* libWatermelonDB.a */; }; /* End PBXBuildFile section */ @@ -636,8 +638,8 @@ 7A0D62D1242AB187006D5C06 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; }; 7A14FCEC257FEB3A005BDCD4 /* Experimental.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Experimental.xcassets; sourceTree = "<group>"; }; 7A14FCF3257FEB59005BDCD4 /* Official.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Official.xcassets; sourceTree = "<group>"; }; - 7A3F4C692F1AAFA700B6B4BD /* CallIdUUID.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CallIdUUID.m; sourceTree = "<group>"; }; - 7A3F4C6A2F1AAFA700B6B4BD /* CallIdUUID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallIdUUID.swift; sourceTree = "<group>"; }; + 7A1B58402F5F58FF002A6BDE /* VoipPayload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoipPayload.swift; sourceTree = "<group>"; }; + 7A1B58432F5F63DB002A6BDE /* AppDelegate+Voip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Voip.swift"; sourceTree = "<group>"; }; 7A610CD127ECE38100B8ABDD /* custom.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = custom.ttf; sourceTree = "<group>"; }; 7A8B30742BCD9D3F00146A40 /* SSLPinning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSLPinning.h; sourceTree = "<group>"; }; 7A8B30752BCD9D3F00146A40 /* SSLPinning.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SSLPinning.mm; sourceTree = "<group>"; }; @@ -652,6 +654,7 @@ 9B215A42CFB843397273C7EA /* SecureStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = SecureStorage.m; sourceTree = "<group>"; }; 9B215A44CFB843397273C7EC /* MMKVBridge.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MMKVBridge.mm; path = Shared/RocketChat/MMKVBridge.mm; sourceTree = "<group>"; }; 9BD1145A1612F5D6A655D75A /* Pods-defaults-RocketChatRN.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-RocketChatRN.release.xcconfig"; path = "Target Support Files/Pods-defaults-RocketChatRN/Pods-defaults-RocketChatRN.release.xcconfig"; sourceTree = "<group>"; }; + 9BE2F3DC02A264F204E3EDE3 /* DDPClient.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DDPClient.swift; sourceTree = "<group>"; }; A3FFA83FC7CA4F1C7C42F2A8 /* Pods-defaults-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-defaults-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-defaults-NotificationService/Pods-defaults-NotificationService.release.xcconfig"; sourceTree = "<group>"; }; A48B46D72D3FFBD200945489 /* A11yFlowModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = A11yFlowModule.h; sourceTree = "<group>"; }; A48B46D82D3FFBD200945489 /* A11yFlowModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = A11yFlowModule.m; sourceTree = "<group>"; }; @@ -1143,8 +1146,8 @@ 7A76DEE42F1AA6EF00750653 /* Libraries */ = { isa = PBXGroup; children = ( - 7A3F4C692F1AAFA700B6B4BD /* CallIdUUID.m */, - 7A3F4C6A2F1AAFA700B6B4BD /* CallIdUUID.swift */, + 7A1B58432F5F63DB002A6BDE /* AppDelegate+Voip.swift */, + 7A1B58402F5F58FF002A6BDE /* VoipPayload.swift */, 7A0000042F1BAFA700B6B4BD /* VoipModule.mm */, 7A0000032F1BAFA700B6B4BD /* VoipService.swift */, B179038FDD7AAF285047814B /* SecureStorage.h */, @@ -1155,6 +1158,7 @@ 66C2701A2EBBCB570062725F /* MMKVKeyManager.mm */, 7A8B30742BCD9D3F00146A40 /* SSLPinning.h */, 7A8B30752BCD9D3F00146A40 /* SSLPinning.mm */, + 9BE2F3DC02A264F204E3EDE3 /* DDPClient.swift */, ); path = Libraries; sourceTree = "<group>"; @@ -2059,8 +2063,7 @@ 1E76CBD825152C870067298C /* Request.swift in Sources */, 1E51411C2B85683C007BE94A /* SSLPinning.m in Sources */, 66C2701B2EBBCB570062725F /* MMKVKeyManager.mm in Sources */, - 7A3F4C6B2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */, - 7A3F4C6C2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */, + 7A1B58422F5F58FF002A6BDE /* VoipPayload.swift in Sources */, 7A0000012F1BAFA700B6B4BD /* VoipService.swift in Sources */, 7A0000022F1BAFA700B6B4BD /* VoipModule.mm in Sources */, 1ED00BB12513E04400A1331F /* ReplyNotification.swift in Sources */, @@ -2094,6 +2097,7 @@ 1E068D0124FD2E0500A0FFC1 /* AppGroup.m in Sources */, 1ED038C42B50A1F500C007D4 /* WatchMessage.swift in Sources */, 1E76CBD025152C6E0067298C /* URL+Extensions.swift in Sources */, + 7A1B58442F5F63DB002A6BDE /* AppDelegate+Voip.swift in Sources */, 1E068CFE24FD2DC700A0FFC1 /* AppGroup.swift in Sources */, 1E76CBCE25152C2F0067298C /* RoomKey.swift in Sources */, 1E76CBCC25152C290067298C /* Message.swift in Sources */, @@ -2102,6 +2106,7 @@ 1E76CBDA25152C8E0067298C /* SendMessage.swift in Sources */, 4C4C8603EF082F0A33A95522 /* ExpoModulesProvider.swift in Sources */, A2C6E2DD38F8BEE19BFB2E1D /* SecureStorage.m in Sources */, + AE692FD072A44EA955D0C0D8 /* DDPClient.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2337,8 +2342,7 @@ 7AAB3E16257E6A6E00707CF6 /* Request.swift in Sources */, 1E51411D2B85683C007BE94A /* SSLPinning.m in Sources */, 66C2701C2EBBCB570062725F /* MMKVKeyManager.mm in Sources */, - 7A3F4C6D2F1AAFA700B6B4BD /* CallIdUUID.swift in Sources */, - 7A3F4C6E2F1AAFA700B6B4BD /* CallIdUUID.m in Sources */, + 7A1B58412F5F58FF002A6BDE /* VoipPayload.swift in Sources */, 7A0000052F1BAFA700B6B4BD /* VoipService.swift in Sources */, 7A0000062F1BAFA700B6B4BD /* VoipModule.mm in Sources */, 7AAB3E17257E6A6E00707CF6 /* ReplyNotification.swift in Sources */, @@ -2372,6 +2376,7 @@ 7AAB3E2A257E6A6E00707CF6 /* AppGroup.m in Sources */, 1ED038C52B50A1F500C007D4 /* WatchMessage.swift in Sources */, 7AAB3E2C257E6A6E00707CF6 /* URL+Extensions.swift in Sources */, + 7A1B58452F5F63DB002A6BDE /* AppDelegate+Voip.swift in Sources */, 7AAB3E2D257E6A6E00707CF6 /* AppGroup.swift in Sources */, 7AAB3E2E257E6A6E00707CF6 /* RoomKey.swift in Sources */, 7AAB3E2F257E6A6E00707CF6 /* Message.swift in Sources */, @@ -2380,6 +2385,7 @@ 7AAB3E31257E6A6E00707CF6 /* SendMessage.swift in Sources */, BC404914E86821389EEB543D /* ExpoModulesProvider.swift in Sources */, 79D8C97F8CE2EC1B6882826B /* SecureStorage.m in Sources */, + CE4453310C9A08AB0DAC2307 /* DDPClient.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 306f8ccae745fb25b693bb6540226e1f3f8c99d4 Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 24 Mar 2026 13:29:32 -0300 Subject: [PATCH 59/61] feat: Refactor media session handling and improve disconnect logic (#7065) --- app/lib/methods/logout.ts | 3 +- app/lib/services/connect.ios.test.ts | 4 + app/lib/services/connect.test.ts | 4 + app/lib/services/connect.ts | 5 +- .../voip/MediaSessionInstance.test.ts | 159 ++++++++++++++++++ app/lib/services/voip/MediaSessionInstance.ts | 26 +-- app/lib/services/voip/MediaSessionStore.ts | 10 ++ app/sagas/login.js | 8 +- app/sagas/selectServer.ts | 2 + .../NewServerView/hooks/useConnectServer.tsx | 4 +- 10 files changed, 208 insertions(+), 17 deletions(-) create mode 100644 app/lib/services/voip/MediaSessionInstance.test.ts diff --git a/app/lib/methods/logout.ts b/app/lib/methods/logout.ts index 69a9643ec2d..d27819472d4 100644 --- a/app/lib/methods/logout.ts +++ b/app/lib/methods/logout.ts @@ -6,6 +6,7 @@ import { isSsl } from './helpers'; import { BASIC_AUTH_KEY } from './helpers/fetch'; import database, { getDatabase } from '../database'; import log from './helpers/log'; +import { disconnect } from '../services/connect'; import sdk from '../services/sdk'; import { CURRENT_SERVER, E2E_PRIVATE_KEY, E2E_PUBLIC_KEY, E2E_RANDOM_PASSWORD_KEY, TOKEN_KEY } from '../constants/keys'; import UserPreferences from './userPreferences'; @@ -111,7 +112,7 @@ export async function logout({ server }: { server: string }): Promise<void> { } if (sdk.current) { - sdk.disconnect(); + disconnect(); } await removeServerData({ server }); diff --git a/app/lib/services/connect.ios.test.ts b/app/lib/services/connect.ios.test.ts index 84e3a5f1e87..1db1ec22ed9 100644 --- a/app/lib/services/connect.ios.test.ts +++ b/app/lib/services/connect.ios.test.ts @@ -1,5 +1,9 @@ import { determineAuthType } from './connect'; +jest.mock('./voip/MediaSessionInstance', () => ({ + mediaSessionInstance: { reset: jest.fn(), init: jest.fn() } +})); + // Mock the isIOS helper to return true for iOS-specific tests jest.mock('../methods/helpers', () => ({ ...jest.requireActual('../methods/helpers'), diff --git a/app/lib/services/connect.test.ts b/app/lib/services/connect.test.ts index 8b1ed79e2bd..34e1ceea898 100644 --- a/app/lib/services/connect.test.ts +++ b/app/lib/services/connect.test.ts @@ -1,5 +1,9 @@ import { determineAuthType } from './connect'; +jest.mock('./voip/MediaSessionInstance', () => ({ + mediaSessionInstance: { reset: jest.fn(), init: jest.fn() } +})); + // Mock the isIOS helper jest.mock('../methods/helpers/deviceInfo', () => ({ ...jest.requireActual('../methods/helpers/deviceInfo'), diff --git a/app/lib/services/connect.ts b/app/lib/services/connect.ts index 2c292873522..095fb24338c 100644 --- a/app/lib/services/connect.ts +++ b/app/lib/services/connect.ts @@ -11,6 +11,7 @@ import { twoFactor } from './twoFactor'; import { store } from '../store/auxStore'; import { loginRequest, logout, setLoginServices, setUser } from '../../actions/login'; import sdk from './sdk'; +import { mediaSessionInstance } from './voip/MediaSessionInstance'; import I18n from '../../i18n'; import { type ICredentials, type ILoggedUser, STATUSES } from '../../definitions'; import { connectRequest, connectSuccess, disconnect as disconnectAction } from '../../actions/connect'; @@ -407,7 +408,9 @@ function checkAndReopen() { } function disconnect() { - return sdk.disconnect(); + const result = sdk.disconnect(); + mediaSessionInstance.reset(); + return result; } async function getWebsocketInfo({ diff --git a/app/lib/services/voip/MediaSessionInstance.test.ts b/app/lib/services/voip/MediaSessionInstance.test.ts new file mode 100644 index 00000000000..640d499b427 --- /dev/null +++ b/app/lib/services/voip/MediaSessionInstance.test.ts @@ -0,0 +1,159 @@ +import { mediaSessionStore } from './MediaSessionStore'; +import { mediaSessionInstance } from './MediaSessionInstance'; + +const mockCallStoreReset = jest.fn(); + +jest.mock('./useCallStore', () => ({ + useCallStore: { + getState: jest.fn(() => ({ + reset: mockCallStoreReset, + setCall: jest.fn(), + callId: null as string | null + })) + } +})); + +const mockOnStreamDataStop = jest.fn(); +const mockOnStreamData = jest.fn(() => ({ stop: mockOnStreamDataStop })); +const mockMethodCall = jest.fn(); + +jest.mock('../sdk', () => ({ + __esModule: true, + default: { + onStreamData: (...args: Parameters<typeof mockOnStreamData>) => mockOnStreamData(...args), + methodCall: (...args: unknown[]) => mockMethodCall(...args) + } +})); + +jest.mock('../../store/auxStore', () => ({ + store: { + getState: jest.fn(() => ({ + settings: { + VoIP_TeamCollab_Ice_Servers: '', + VoIP_TeamCollab_Ice_Gathering_Timeout: 5000 + } + })), + subscribe: jest.fn(() => jest.fn()) + } +})); + +jest.mock('react-native-webrtc', () => ({ + registerGlobals: jest.fn(), + mediaDevices: { getUserMedia: jest.fn() } +})); + +jest.mock('react-native-callkeep', () => ({})); + +jest.mock('react-native-device-info', () => ({ + getUniqueId: jest.fn(() => 'test-device-id') +})); + +jest.mock('../../native/NativeVoip', () => ({ + __esModule: true, + default: { stopNativeDDPClient: jest.fn() } +})); + +jest.mock('../../navigation/appNavigation', () => ({ + __esModule: true, + default: { navigate: jest.fn() } +})); + +type SessionRecord = { userId: string; endSession: jest.Mock }; +const createdSessions: SessionRecord[] = []; + +jest.mock('@rocket.chat/media-signaling', () => ({ + MediaCallWebRTCProcessor: jest.fn().mockImplementation(function MediaCallWebRTCProcessor(this: unknown) { + return this; + }), + MediaSignalingSession: jest.fn().mockImplementation(function MockMediaSignalingSession(this: any, config: { userId: string }) { + const endSession = jest.fn(); + createdSessions.push({ userId: config.userId, endSession }); + this.userId = config.userId; + this.endSession = endSession; + this.on = jest.fn(); + this.processSignal = jest.fn().mockResolvedValue(undefined); + this.setIceGatheringTimeout = jest.fn(); + this.startCall = jest.fn().mockResolvedValue(undefined); + this.getMainCall = jest.fn(); + }) +})); + +describe('MediaSessionInstance', () => { + beforeEach(() => { + jest.clearAllMocks(); + createdSessions.length = 0; + mediaSessionInstance.reset(); + }); + + afterEach(() => { + mediaSessionInstance.reset(); + }); + + describe('init', () => { + it('should register stream-notify-user listener', () => { + mediaSessionInstance.init('user-1'); + expect(mockOnStreamData).toHaveBeenCalledWith('stream-notify-user', expect.any(Function)); + }); + + it('should create session with userId', () => { + mediaSessionInstance.init('user-abc'); + expect(createdSessions).toHaveLength(1); + expect(createdSessions[0].userId).toBe('user-abc'); + }); + + it('should route sendSignal through sdk.methodCall with user media-calls channel', () => { + const spy = jest.spyOn(mediaSessionStore, 'setSendSignalFn'); + mediaSessionInstance.init('user-xyz'); + expect(spy).toHaveBeenCalled(); + const sendFn = spy.mock.calls[spy.mock.calls.length - 1][0] as (signal: { type: string }) => void; + sendFn({ type: 'register' }); + expect(mockMethodCall).toHaveBeenCalledWith( + 'stream-notify-user', + 'user-xyz/media-calls', + expect.stringContaining('register') + ); + spy.mockRestore(); + }); + }); + + describe('teardown and user switch', () => { + it('should call endSession on previous session when init with different userId', () => { + mediaSessionInstance.init('user-1'); + const first = createdSessions[0]; + mediaSessionInstance.init('user-2'); + expect(first.endSession).toHaveBeenCalled(); + expect(createdSessions[createdSessions.length - 1].userId).toBe('user-2'); + }); + + it('should only have one active onChange handler after re-init (getInstance once per change emit)', () => { + mediaSessionInstance.init('user-1'); + mediaSessionInstance.init('user-2'); + const spy = jest.spyOn(mediaSessionStore, 'getInstance'); + mediaSessionStore.emit('change'); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith('user-2'); + spy.mockRestore(); + }); + + it('should throw existing makeInstance error when getInstance after reset without init', () => { + mediaSessionInstance.init('user-1'); + mediaSessionInstance.reset(); + expect(() => mediaSessionStore.getInstance('any')).toThrow('WebRTC processor factory and send signal function must be set'); + }); + + it('should allow init after reset', () => { + mediaSessionInstance.init('user-1'); + mediaSessionInstance.reset(); + mediaSessionInstance.init('user-2'); + expect(createdSessions[createdSessions.length - 1].userId).toBe('user-2'); + }); + + it('should not throw when reset is called twice', () => { + mediaSessionInstance.init('user-1'); + expect(() => { + mediaSessionInstance.reset(); + mediaSessionInstance.reset(); + }).not.toThrow(); + }); + }); +}); diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 02e32e961a1..772086438d0 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -26,13 +26,13 @@ class MediaSessionInstance { private iceServers: IceServer[] = []; private iceGatheringTimeout: number = 5000; private mediaSignalListener: { stop: () => void } | null = null; - private mediaSignalsListener: { stop: () => void } | null = null; private instance: MediaSignalingSession | null = null; + private mediaSessionStoreChangeUnsubscribe: (() => void) | null = null; private storeTimeoutUnsubscribe: (() => void) | null = null; private storeIceServersUnsubscribe: (() => void) | null = null; public init(userId: string): void { - this.stop(); + this.reset(); registerGlobals(); this.configureIceServers(); // prevent JS and native DDP clients from interfering with each other @@ -50,7 +50,9 @@ class MediaSessionInstance { sdk.methodCall('stream-notify-user', `${userId}/media-calls`, JSON.stringify(signal)); }); this.instance = mediaSessionStore.getInstance(userId); - mediaSessionStore.onChange(() => (this.instance = mediaSessionStore.getInstance(userId))); + this.mediaSessionStoreChangeUnsubscribe = mediaSessionStore.onChange(() => { + this.instance = mediaSessionStore.getInstance(userId); + }); this.mediaSignalListener = sdk.onStreamData('stream-notify-user', (ddpMessage: IDDPMessage) => { if (!this.instance) { @@ -168,22 +170,26 @@ class MediaSessionInstance { }); } - private stop() { + public reset() { + if (this.mediaSessionStoreChangeUnsubscribe) { + this.mediaSessionStoreChangeUnsubscribe(); + this.mediaSessionStoreChangeUnsubscribe = null; + } if (this.mediaSignalListener?.stop) { this.mediaSignalListener.stop(); } - if (this.mediaSignalsListener?.stop) { - this.mediaSignalsListener.stop(); - } + this.mediaSignalListener = null; if (this.storeTimeoutUnsubscribe) { this.storeTimeoutUnsubscribe(); + this.storeTimeoutUnsubscribe = null; } if (this.storeIceServersUnsubscribe) { this.storeIceServersUnsubscribe(); + this.storeIceServersUnsubscribe = null; } - if (this.instance) { - this.instance.endSession(); - } + mediaSessionStore.dispose(); + this.instance = null; + useCallStore.getState().reset(); } } diff --git a/app/lib/services/voip/MediaSessionStore.ts b/app/lib/services/voip/MediaSessionStore.ts index dfb4719176a..8ccc513999c 100644 --- a/app/lib/services/voip/MediaSessionStore.ts +++ b/app/lib/services/voip/MediaSessionStore.ts @@ -93,6 +93,16 @@ class MediaSessionStore extends Emitter<{ change: void }> { public getCurrentInstance(): MediaSignalingSession | null { return this.sessionInstance; } + + public dispose(): void { + if (this.sessionInstance !== null) { + this.sessionInstance.endSession(); + this.sessionInstance = null; + } + this.sendSignalFn = null; + this._webrtcProcessorFactory = null; + this.change(); + } } // TODO: change name diff --git a/app/sagas/login.js b/app/sagas/login.js index d3c52a6b9a8..a011021fe2c 100644 --- a/app/sagas/login.js +++ b/app/sagas/login.js @@ -32,7 +32,7 @@ import { getSlashCommands } from '../lib/methods/getSlashCommands'; import { getUserPresence, subscribeUsersPresence } from '../lib/methods/getUsersPresence'; import { logout, removeServerData, removeServerDatabase } from '../lib/methods/logout'; import { subscribeSettings } from '../lib/methods/getSettings'; -import { loginWithPassword, login } from '../lib/services/connect'; +import { disconnect, loginWithPassword, login } from '../lib/services/connect'; import { saveUserProfile, registerPushToken, getUsersRoles } from '../lib/services/restApi'; import { setUsersRoles } from '../actions/usersRoles'; import { getServerById } from '../lib/database/services/Server'; @@ -234,6 +234,8 @@ const startVoipFork = function* startVoipFork() { if (isVoipModuleAvailable() && (hasPermissions[0] || hasPermissions[1])) { const userId = yield select(state => state.login.user.id); mediaSessionInstance.init(userId); + } else { + mediaSessionInstance.reset(); } } catch (e) { log(e); @@ -411,10 +413,10 @@ const handleDeleteAccount = function* handleDeleteAccount() { } } // if there's no servers, go outside - sdk.disconnect(); + disconnect(); yield put(appStart({ root: RootEnum.ROOT_OUTSIDE })); } catch (e) { - sdk.disconnect(); + disconnect(); yield put(appStart({ root: RootEnum.ROOT_OUTSIDE })); log(e); } diff --git a/app/sagas/selectServer.ts b/app/sagas/selectServer.ts index 5373f6b0fcf..ca9e76e0b33 100644 --- a/app/sagas/selectServer.ts +++ b/app/sagas/selectServer.ts @@ -39,6 +39,7 @@ import { setPermissions } from '../lib/methods/getPermissions'; import { setRoles } from '../lib/methods/getRoles'; import { connect, disconnect, getWebsocketInfo, getLoginServices } from '../lib/services/connect'; import sdk from '../lib/services/sdk'; +import { mediaSessionInstance } from '../lib/services/voip/MediaSessionInstance'; import { appSelector } from '../lib/hooks/useAppSelector'; import { getServerById } from '../lib/database/services/Server'; import { getLoggedUserById } from '../lib/database/services/LoggedUser'; @@ -150,6 +151,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch yield put(inquiryReset()); yield put(encryptionStop()); yield put(clearActiveUsers()); + mediaSessionInstance.reset(); const userId = UserPreferences.getString(`${TOKEN_KEY}-${server}`); let user = null; if (userId) { diff --git a/app/views/NewServerView/hooks/useConnectServer.tsx b/app/views/NewServerView/hooks/useConnectServer.tsx index fa48fa73697..04bab105efa 100644 --- a/app/views/NewServerView/hooks/useConnectServer.tsx +++ b/app/views/NewServerView/hooks/useConnectServer.tsx @@ -1,7 +1,7 @@ import { Keyboard } from 'react-native'; import { useDispatch } from 'react-redux'; -import sdk from '../../../lib/services/sdk'; +import { disconnect } from '../../../lib/services/connect'; import { events, logEvent } from '../../../lib/methods/helpers/log'; import { selectServerClear, serverRequest } from '../../../actions/server'; import completeUrl from '../utils/completeUrl'; @@ -24,7 +24,7 @@ const useConnectServer = ({ workspaceUrl, certificate, previousServer }: TUseNew // Clear the previous workspace to prevent being stuck on the previous server if (!previousServer) { - sdk.disconnect(); + disconnect(); dispatch(selectServerClear()); } if (workspaceUrl || serverUrl) { From 106cbd7e2c0a7490f941b4e16b6f21b5e115cb5a Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Wed, 25 Mar 2026 16:04:11 -0300 Subject: [PATCH 60/61] feat: Control incoming call from native (#7066) --- .cursor/skills/agent-skills | 1 + android/app/src/main/AndroidManifest.xml | 5 - .../chat/rocket/reactnative/MainActivity.kt | 6 +- .../notification/NotificationIntentHandler.kt | 43 +-- .../RCFirebaseMessagingService.kt | 18 -- .../reactnative/voip/IncomingCallActivity.kt | 12 +- .../rocket/reactnative/voip/VoipModule.kt | 25 ++ .../reactnative/voip/VoipNotification.kt | 272 +++++++++++++++++- .../rocket/reactnative/voip/VoipPayload.kt | 9 +- app/actions/actionsTypes.ts | 2 +- app/actions/deepLinking.ts | 23 +- app/definitions/Voip.ts | 1 + app/i18n/locales/ar.json | 1 + app/i18n/locales/bn-IN.json | 1 + app/i18n/locales/cs.json | 1 + app/i18n/locales/de.json | 1 + app/i18n/locales/en.json | 1 + app/i18n/locales/es.json | 1 + app/i18n/locales/fi.json | 1 + app/i18n/locales/fr.json | 1 + app/i18n/locales/hi-IN.json | 1 + app/i18n/locales/hu.json | 1 + app/i18n/locales/it.json | 1 + app/i18n/locales/ja.json | 1 + app/i18n/locales/nl.json | 1 + app/i18n/locales/nn.json | 1 + app/i18n/locales/no.json | 1 + app/i18n/locales/pt-BR.json | 1 + app/i18n/locales/pt-PT.json | 1 + app/i18n/locales/ru.json | 1 + app/i18n/locales/sl-SI.json | 1 + app/i18n/locales/sv.json | 1 + app/i18n/locales/ta-IN.json | 1 + app/i18n/locales/te-IN.json | 1 + app/i18n/locales/tr.json | 1 + app/i18n/locales/zh-CN.json | 1 + app/i18n/locales/zh-TW.json | 1 + app/index.tsx | 6 +- app/lib/services/voip/MediaCallEvents.ts | 79 +++-- .../voip/MediaSessionInstance.test.ts | 3 +- app/lib/services/voip/MediaSessionInstance.ts | 30 +- app/lib/services/voip/MediaSessionStore.ts | 8 +- app/lib/services/voip/useCallStore.ts | 16 ++ app/sagas/deepLinking.js | 70 ++++- ios/Libraries/AppDelegate+Voip.swift | 6 +- ios/Libraries/VoipModule.mm | 17 +- ios/Libraries/VoipPayload.swift | 24 +- ios/Libraries/VoipService.swift | 138 ++++++++- package.json | 2 +- .../rocket.chat-media-signaling-0.1.1.tgz | Bin 62589 -> 0 bytes .../rocket.chat-media-signaling-0.1.3.tgz | Bin 0 -> 70712 bytes yarn.lock | 6 +- 52 files changed, 661 insertions(+), 186 deletions(-) create mode 160000 .cursor/skills/agent-skills delete mode 100644 packages/rocket.chat-media-signaling-0.1.1.tgz create mode 100644 packages/rocket.chat-media-signaling-0.1.3.tgz diff --git a/.cursor/skills/agent-skills b/.cursor/skills/agent-skills new file mode 160000 index 00000000000..a4f602ffb4a --- /dev/null +++ b/.cursor/skills/agent-skills @@ -0,0 +1 @@ +Subproject commit a4f602ffb4aeaf4199fa97b7162f9c9d1f655904 diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ca983f7a6e1..ab1f838aa9f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -133,11 +133,6 @@ android:enabled="true" android:exported="false" /> - <service - android:name="chat.rocket.reactnative.voip.VoipForegroundService" - android:exported="false" - android:foregroundServiceType="phoneCall" /> - <service android:name="io.wazo.callkeep.VoiceConnectionService" android:label="Wazo" android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" diff --git a/android/app/src/main/java/chat/rocket/reactnative/MainActivity.kt b/android/app/src/main/java/chat/rocket/reactnative/MainActivity.kt index e4ab65ceba1..dc2417f85c6 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/MainActivity.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/MainActivity.kt @@ -29,7 +29,7 @@ class MainActivity : ReactActivity() { override fun onCreate(savedInstanceState: Bundle?) { RNBootSplash.init(this, R.style.BootTheme) super.onCreate(null) - + // Handle notification intents intent?.let { NotificationIntentHandler.handleIntent(this, it) } } @@ -37,7 +37,7 @@ class MainActivity : ReactActivity() { public override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) setIntent(intent) - + // Handle notification intents when activity is already running NotificationIntentHandler.handleIntent(this, intent) } @@ -45,4 +45,4 @@ class MainActivity : ReactActivity() { override fun invokeDefaultOnBackPressed() { moveTaskToBack(true) } -} \ No newline at end of file +} diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt index 060d4792077..41d5921cc16 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/NotificationIntentHandler.kt @@ -6,11 +6,6 @@ import android.os.Bundle import android.util.Log import com.google.gson.GsonBuilder import chat.rocket.reactnative.voip.VoipNotification -import chat.rocket.reactnative.voip.VoipModule -import chat.rocket.reactnative.voip.VoipPayload -import android.os.Build -import android.app.KeyguardManager -import android.app.Activity /** * Handles notification Intent processing from MainActivity. @@ -27,8 +22,7 @@ class NotificationIntentHandler { */ @JvmStatic fun handleIntent(context: Context, intent: Intent) { - // Handle VoIP action first - if (handleVoipIntent(context, intent)) { + if (VoipNotification.handleMainActivityVoipIntent(context, intent)) { return } @@ -41,41 +35,6 @@ class NotificationIntentHandler { handleNotificationIntent(context, intent) } - /** - * Handles VoIP call notification Intent. - * @return true if this was a VoIP intent, false otherwise - */ - @JvmStatic - private fun handleVoipIntent(context: Context, intent: Intent): Boolean { - if (!intent.getBooleanExtra("voipAction", false)) { - return false - } - val voipPayload = VoipPayload.fromBundle(intent.extras) - if (voipPayload == null || !voipPayload.isVoipIncomingCall()) { - return false - } - - Log.d(TAG, "Handling VoIP intent - voipPayload: $voipPayload") - - VoipNotification.cancelById(context, voipPayload.notificationId) - VoipNotification.cancelTimeout(voipPayload.callId) - VoipModule.storeInitialEvents(voipPayload) - - if (context is Activity) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { - context.setShowWhenLocked(true) - context.setTurnScreenOn(true) - val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager - keyguardManager.requestDismissKeyguard(context, null) - } - } - - // Clear the voip flag to prevent re-processing - intent.removeExtra("voipAction") - - return true - } - /** * Handles video conference notification Intent. * @return true if this was a video conf intent, false otherwise diff --git a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt index 46253da2788..1fdfacc21c4 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/notification/RCFirebaseMessagingService.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.util.Log import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage -import com.google.gson.Gson import chat.rocket.reactnative.voip.VoipNotification import chat.rocket.reactnative.voip.VoipPayload @@ -19,7 +18,6 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { companion object { private const val TAG = "RocketChat.FCM" - private val gson = Gson() } override fun onMessageReceived(remoteMessage: RemoteMessage) { @@ -53,22 +51,6 @@ class RCFirebaseMessagingService : FirebaseMessagingService() { } } - /** - * Safely parses ejson string to Ejson object. - */ - private fun parseEjson(ejsonStr: String?): Ejson? { - if (ejsonStr.isNullOrEmpty() || ejsonStr == "{}") { - return null - } - - return try { - gson.fromJson(ejsonStr, Ejson::class.java) - } catch (e: Exception) { - Log.e(TAG, "Failed to parse ejson", e) - null - } - } - override fun onNewToken(token: String) { Log.d(TAG, "FCM token refreshed") // Token handling is done by expo-notifications JS layer diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt index f74d24a06b7..1c5ee3633c8 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/IncomingCallActivity.kt @@ -24,7 +24,6 @@ import android.widget.FrameLayout import android.util.Log import android.view.ViewOutlineProvider import com.bumptech.glide.Glide -import chat.rocket.reactnative.MainActivity import chat.rocket.reactnative.R import android.graphics.Typeface import chat.rocket.reactnative.notification.Ejson @@ -283,15 +282,8 @@ class IncomingCallActivity : Activity() { clearTimeout() VoipNotification.cancelTimeout(payload.callId) stopRingtone() - - // Launch MainActivity with call data - val launchIntent = Intent(this, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP - putExtras(payload.toBundle()) - } - startActivity(launchIntent) - - finish() + VoipNotification.handleAcceptAction(this, payload) + // Activity finishes when ACTION_DISMISS is broadcast from handleAcceptAction (async DDP). } private fun handleDecline(payload: VoipPayload) { diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt index 0862c42a9df..8e67e69fa9a 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipModule.kt @@ -17,6 +17,7 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo companion object { private const val TAG = "RocketChat.VoipModule" private const val EVENT_INITIAL_EVENTS = "VoipPushInitialEvents" + private const val EVENT_VOIP_ACCEPT_FAILED = "VoipAcceptFailed" private var reactContextRef: WeakReference<ReactApplicationContext>? = null private var initialEventsData: VoipPayload? = null @@ -57,6 +58,30 @@ class VoipModule(reactContext: ReactApplicationContext) : NativeVoipSpec(reactCo emitInitialEventsEvent(voipPayload) } + /** + * Stash native accept failure for cold start [getInitialEvents] and emit [EVENT_VOIP_ACCEPT_FAILED] when JS is running. + */ + @JvmStatic + fun storeAcceptFailureForJs(payload: VoipPayload) { + val failed = payload.copy(voipAcceptFailed = true) + initialEventsData = failed + emitVoipAcceptFailedEvent(failed) + } + + private fun emitVoipAcceptFailedEvent(voipPayload: VoipPayload) { + try { + reactContextRef?.get()?.let { context -> + if (context.hasActiveReactInstance()) { + context + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) + .emit(EVENT_VOIP_ACCEPT_FAILED, voipPayload.toWritableMap()) + } + } + } catch (e: Exception) { + Log.e(TAG, "Failed to emit VoipAcceptFailed", e) + } + } + @JvmStatic fun clearInitialEventsInternal() { try { diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt index 96a0d5e1bcd..f2fa81ffede 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipNotification.kt @@ -25,10 +25,13 @@ import android.telecom.PhoneAccountHandle import android.telecom.TelecomManager import io.wazo.callkeep.VoiceConnection import io.wazo.callkeep.VoiceConnectionService +import android.app.Activity +import android.app.KeyguardManager import chat.rocket.reactnative.MainActivity import chat.rocket.reactnative.notification.Ejson import org.json.JSONArray import org.json.JSONObject +import java.util.concurrent.atomic.AtomicBoolean /** * Handles VoIP call notifications using Android's Telecom framework via CallKeep. @@ -48,12 +51,25 @@ class VoipNotification(private val context: Context) { const val ACTION_ACCEPT = "chat.rocket.reactnative.ACTION_VOIP_ACCEPT" const val ACTION_DECLINE = "chat.rocket.reactnative.ACTION_VOIP_DECLINE" + + /** + * Set on the heads-up Accept action [PendingIntent] ([PendingIntent.getActivity] → MainActivity). + * Android 12+ blocks starting an activity from a notification [BroadcastReceiver] trampoline; + * MainActivity opens first, then [handleMainActivityVoipIntent] runs accept with + * [handleAcceptAction] and `skipLaunchMainActivity = true`. + */ + const val ACTION_VOIP_ACCEPT_HEADS_UP = "chat.rocket.reactnative.ACTION_VOIP_ACCEPT_HEADS_UP" const val ACTION_TIMEOUT = "chat.rocket.reactnative.ACTION_VOIP_TIMEOUT" const val ACTION_DISMISS = "chat.rocket.reactnative.ACTION_VOIP_DISMISS" // react-native-callkeep's ConnectionService class name private const val CALLKEEP_CONNECTION_SERVICE_CLASS = "io.wazo.callkeep.VoiceConnectionService" private const val DISCONNECT_REASON_MISSED = 6 + + private data class VoipMediaCallIdentity(val userId: String, val deviceId: String) + + /** Keep in sync with MediaSessionStore features (audio-only today). */ + private val SUPPORTED_VOIP_FEATURES = JSONArray().apply { put("audio") } private val timeoutHandler = Handler(Looper.getMainLooper()) private val timeoutCallbacks = mutableMapOf<String, Runnable>() private var ddpClient: DDPClient? = null @@ -141,6 +157,151 @@ class VoipNotification(private val context: Context) { ) } + /** + * Routes VoIP-related intents delivered to [MainActivity] (cold start or [Activity.onNewIntent]). + * + * @return `true` if the intent was handled as VoIP and downstream handlers should not process it. + */ + @JvmStatic + fun handleMainActivityVoipIntent(context: Context, intent: Intent): Boolean { + val payload = VoipPayload.fromBundle(intent.extras) + if (payload == null || !payload.isVoipIncomingCall()) { + return false + } + + val headsUpAccept = intent.action == ACTION_VOIP_ACCEPT_HEADS_UP + if (headsUpAccept) { + intent.action = Intent.ACTION_MAIN + prepareMainActivityForIncomingVoip(context, payload, storePayloadForJs = false) + handleAcceptAction(context, payload, skipLaunchMainActivity = true) + intent.removeExtra("voipAction") + return true + } + + if (intent.getBooleanExtra("voipAction", false)) { + prepareMainActivityForIncomingVoip(context, payload) + intent.removeExtra("voipAction") + return true + } + + return false + } + + /** + * Prepares MainActivity after launch with incoming-call context: cancel notification and timeout, + * stash payload for JS, and unlock/show above keyguard when [context] is an [Activity]. + */ + private fun prepareMainActivityForIncomingVoip( + context: Context, + payload: VoipPayload, + storePayloadForJs: Boolean = true + ) { + Log.d(TAG, "prepareMainActivityForIncomingVoip — callId: ${payload.callId}") + cancelById(context, payload.notificationId) + cancelTimeout(payload.callId) + if (storePayloadForJs) { + VoipModule.storeInitialEvents(payload) + } + + if (context is Activity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + context.setShowWhenLocked(true) + context.setTurnScreenOn(true) + val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager + keyguardManager.requestDismissKeyguard(context, null) + } + } + + /** + * Accept from notification or IncomingCallActivity: send accept over native DDP, sync Telecom, + * dismiss UI, then open MainActivity (unless [skipLaunchMainActivity] — already in MainActivity + * from heads-up Accept [PendingIntent.getActivity]). JS still runs answerCall afterward. + * + * The DDP call is asynchronous; [VoipModule.storeInitialEvents], notification cancel, Telecom + * answer, and [ACTION_DISMISS] run from an internal completion callback. [IncomingCallActivity] + * stays open until that broadcast is received. + */ + @JvmStatic + @JvmOverloads + fun handleAcceptAction(context: Context, payload: VoipPayload, skipLaunchMainActivity: Boolean = false) { + Log.d(TAG, "Accept action triggered for callId: ${payload.callId}") + cancelTimeout(payload.callId) + + val appCtx = context.applicationContext + // Guard so finish() is called at most once, whether by the DDP callback or the timeout. + val finished = AtomicBoolean(false) + val timeoutHandler = Handler(Looper.getMainLooper()) + val timeoutRunnable = Runnable { + if (finished.compareAndSet(false, true)) { + Log.w(TAG, "Native accept timed out for ${payload.callId}; falling back to JS recovery") + finish(false) + } + } + timeoutHandler.postDelayed(timeoutRunnable, 10_000L) + + fun finish(ddpSuccess: Boolean) { + if (!finished.compareAndSet(false, true)) return + timeoutHandler.removeCallbacks(timeoutRunnable) + stopDDPClientInternal() + if (ddpSuccess) { + answerIncomingCall(payload.callId) + VoipModule.storeInitialEvents(payload) + } else { + Log.d(TAG, "Native accept did not succeed over DDP for ${payload.callId}; opening app for JS recovery") + disconnectIncomingCall(payload.callId, false) + VoipModule.storeAcceptFailureForJs(payload) + } + cancelById(appCtx, payload.notificationId) + LocalBroadcastManager.getInstance(appCtx).sendBroadcast( + Intent(ACTION_DISMISS).apply { + putExtras(payload.toBundle()) + } + ) + if (!skipLaunchMainActivity) { + launchMainActivityForVoip(context, payload) + } + } + + val client = ddpClient + if (client == null) { + Log.d(TAG, "Native DDP client unavailable for accept ${payload.callId}") + finish(false) + return + } + + if (isDdpLoggedIn) { + sendAcceptSignal(context, payload) { success -> + finish(success) + } + } else { + queueAcceptSignal(context, payload) { success -> + finish(success) + } + } + } + + private fun launchMainActivityForVoip(context: Context, payload: VoipPayload) { + val intent = Intent(context, MainActivity::class.java).apply { + putExtras(payload.toBundle()) + if (context is Activity) { + flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP + } else { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or + Intent.FLAG_ACTIVITY_CLEAR_TOP or + Intent.FLAG_ACTIVITY_SINGLE_TOP + } + } + context.startActivity(intent) + } + + private fun answerIncomingCall(callId: String) { + val connection = VoiceConnectionService.getConnection(callId) + when (connection) { + is VoiceConnection -> connection.onAnswer() + null -> Log.d(TAG, "No active VoiceConnection found for accepted call: $callId") + else -> Log.d(TAG, "Non-VoiceConnection for accept, callId: $callId") + } + } + // TODO: unify these three functions and check VoiceConnectionService private fun disconnectTimedOutCall(callId: String) { val connection = VoiceConnectionService.getConnection(callId) @@ -206,7 +367,7 @@ class VoipNotification(private val context: Context) { Log.d(TAG, "Queued native reject signal for ${payload.callId}") } - private fun flushPendingRejectSignalIfNeeded(): Boolean { + private fun flushPendingQueuedSignalsIfNeeded(): Boolean { val client = ddpClient ?: return false if (!client.hasQueuedMethodCalls()) { return false @@ -216,33 +377,101 @@ class VoipNotification(private val context: Context) { return true } - private fun buildRejectSignalParams(context: Context, payload: VoipPayload): JSONArray? { + private fun sendAcceptSignal( + context: Context, + payload: VoipPayload, + onComplete: (Boolean) -> Unit + ) { + val client = ddpClient + if (client == null) { + Log.d(TAG, "Native DDP client unavailable, cannot send accept for ${payload.callId}") + onComplete(false) + return + } + + val params = buildAcceptSignalParams(context, payload) ?: run { + onComplete(false) + return + } + + client.callMethod("stream-notify-user", params) { success -> + Log.d(TAG, "Native accept signal result for ${payload.callId}: $success") + onComplete(success) + } + } + + private fun queueAcceptSignal( + context: Context, + payload: VoipPayload, + onComplete: (Boolean) -> Unit + ) { + val client = ddpClient + if (client == null) { + Log.d(TAG, "Native DDP client unavailable, cannot queue accept for ${payload.callId}") + onComplete(false) + return + } + + val params = buildAcceptSignalParams(context, payload) ?: run { + onComplete(false) + return + } + + client.queueMethodCall("stream-notify-user", params) { success -> + Log.d(TAG, "Queued native accept signal result for ${payload.callId}: $success") + onComplete(success) + } + Log.d(TAG, "Queued native accept signal for ${payload.callId}") + } + + /** + * Resolves user id for this host and Android [Settings.Secure.ANDROID_ID] as media-signaling contractId. + * Must match JS `getUniqueIdSync()` from react-native-device-info (iOS native code uses `DeviceUID`). + */ + private fun resolveVoipMediaCallIdentity(context: Context, payload: VoipPayload): VoipMediaCallIdentity? { val ejson = Ejson().apply { host = payload.host } val userId = ejson.userId() if (userId.isNullOrEmpty()) { - Log.d(TAG, "Missing userId, cannot send reject for ${payload.callId}") + Log.d(TAG, "Missing userId, cannot build stream-notify-user params for ${payload.callId}") stopDDPClientInternal() return null } - val deviceId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) if (deviceId.isNullOrEmpty()) { - Log.d(TAG, "Missing deviceId, cannot send reject for ${payload.callId}") + Log.d(TAG, "Missing deviceId, cannot build stream-notify-user params for ${payload.callId}") stopDDPClientInternal() return null } + return VoipMediaCallIdentity(userId, deviceId) + } + private fun buildAcceptSignalParams(context: Context, payload: VoipPayload): JSONArray? { + val ids = resolveVoipMediaCallIdentity(context, payload) ?: return null val signal = JSONObject().apply { put("callId", payload.callId) - put("contractId", deviceId) + put("contractId", ids.deviceId) put("type", "answer") - put("answer", "reject") + put("answer", "accept") + put("supportedFeatures", SUPPORTED_VOIP_FEATURES) } + return JSONArray().apply { + put("${ids.userId}/media-calls") + put(signal.toString()) + } + } + private fun buildRejectSignalParams(context: Context, payload: VoipPayload): JSONArray? { + val ids = resolveVoipMediaCallIdentity(context, payload) ?: return null + val signal = JSONObject().apply { + put("callId", payload.callId) + put("contractId", ids.deviceId) + put("type", "answer") + put("answer", "reject") + } return JSONArray().apply { - put("$userId/media-calls") + put("${ids.userId}/media-calls") put(signal.toString()) } } @@ -327,7 +556,7 @@ class VoipNotification(private val context: Context) { } isDdpLoggedIn = true - if (flushPendingRejectSignalIfNeeded()) { + if (flushPendingQueuedSignalsIfNeeded()) { return@login } @@ -535,12 +764,31 @@ class VoipNotification(private val context: Context) { } val fullScreenPendingIntent = createPendingIntent(notificationId, fullScreenIntent) - // Create Accept action + // Accept: must use getActivity — Android 12+ blocks starting MainActivity from a + // notification BroadcastReceiver ("trampoline"). MainActivity runs native accept with + // skipLaunchMainActivity after opening. val acceptIntent = Intent(context, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP + action = ACTION_VOIP_ACCEPT_HEADS_UP + flags = Intent.FLAG_ACTIVITY_NEW_TASK or + Intent.FLAG_ACTIVITY_CLEAR_TOP or + Intent.FLAG_ACTIVITY_SINGLE_TOP putExtras(voipPayload.toBundle()) } - val acceptPendingIntent = createPendingIntent(notificationId + 1, acceptIntent) + val acceptPendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + PendingIntent.getActivity( + context, + notificationId + 1, + acceptIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + } else { + PendingIntent.getActivity( + context, + notificationId + 1, + acceptIntent, + PendingIntent.FLAG_UPDATE_CURRENT + ) + } // Create Decline action val declineIntent = Intent(context, DeclineReceiver::class.java).apply { diff --git a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt index d361f711f30..beaa441871c 100644 --- a/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt +++ b/android/app/src/main/java/chat/rocket/reactnative/voip/VoipPayload.kt @@ -41,6 +41,8 @@ data class VoipPayload( @SerializedName("createdAt") val createdAt: String?, + + val voipAcceptFailed: Boolean = false, ) { val notificationId: Int = callId.hashCode() val pushType: VoipPushType? @@ -86,6 +88,9 @@ data class VoipPayload( putString("avatarUrl", avatarUrl) putString("createdAt", createdAt) putInt("notificationId", notificationId) + if (voipAcceptFailed) { + putBoolean("voipAcceptFailed", true) + } } } @@ -164,6 +169,7 @@ data class VoipPayload( hostName = hostName.orEmpty(), avatarUrl = caller?.avatarUrl, createdAt = payloadCreatedAt, + voipAcceptFailed = false, ) } } @@ -188,7 +194,8 @@ data class VoipPayload( return null } - return VoipPayload(callId, caller, username, host, type, hostName, avatarUrl, createdAt) + val voipAcceptFailed = bundle.getBoolean("voipAcceptFailed", false) + return VoipPayload(callId, caller, username, host, type, hostName, avatarUrl, createdAt, voipAcceptFailed) } private fun parseRemotePayload(data: Map<String, String>): RemoteVoipPayload? { diff --git a/app/actions/actionsTypes.ts b/app/actions/actionsTypes.ts index 996edcd8a2f..938ff7b9d5d 100644 --- a/app/actions/actionsTypes.ts +++ b/app/actions/actionsTypes.ts @@ -59,7 +59,7 @@ export const METEOR = createRequestTypes('METEOR_CONNECT', [...defaultTypes, 'DI export const LOGOUT = 'LOGOUT'; // logout is always success export const DELETE_ACCOUNT = 'DELETE_ACCOUNT'; export const SNIPPETED_MESSAGES = createRequestTypes('SNIPPETED_MESSAGES', ['OPEN', 'READY', 'CLOSE', 'MESSAGES_RECEIVED']); -export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN', 'OPEN_VIDEO_CONF', 'VOIP_CALL']); +export const DEEP_LINKING = createRequestTypes('DEEP_LINKING', ['OPEN', 'OPEN_VIDEO_CONF']); export const SORT_PREFERENCES = createRequestTypes('SORT_PREFERENCES', ['SET_ALL', 'SET']); export const SET_CUSTOM_EMOJIS = 'SET_CUSTOM_EMOJIS'; export const ACTIVE_USERS = createRequestTypes('ACTIVE_USERS', ['SET', 'CLEAR']); diff --git a/app/actions/deepLinking.ts b/app/actions/deepLinking.ts index d55de045aa3..3ff1e22fed9 100644 --- a/app/actions/deepLinking.ts +++ b/app/actions/deepLinking.ts @@ -10,21 +10,15 @@ interface IParams { fullURL: string; type: string; token: string; + callId?: string; + username?: string; + voipAcceptFailed?: boolean; } interface IDeepLinkingOpen extends Action { params: Partial<IParams>; } -interface IVoipCallParams { - callId: string; - host: string; -} - -interface IVoipCallOpen extends Action { - params: IVoipCallParams; -} - export function deepLinkingOpen(params: Partial<IParams>): IDeepLinkingOpen { return { type: DEEP_LINKING.OPEN, @@ -38,14 +32,3 @@ export function deepLinkingClickCallPush(params: any): IDeepLinkingOpen { params }; } - -/** - * Action to handle VoIP call from push notification. - * Triggers server switching if needed and processes the incoming call. - */ -export function voipCallOpen(params: IVoipCallParams): IVoipCallOpen { - return { - type: DEEP_LINKING.VOIP_CALL, - params - }; -} diff --git a/app/definitions/Voip.ts b/app/definitions/Voip.ts index 72df8d1a870..e815bc8d3ed 100644 --- a/app/definitions/Voip.ts +++ b/app/definitions/Voip.ts @@ -14,4 +14,5 @@ export interface VoipPayload { readonly avatarUrl?: string | null; readonly createdAt?: string | null; readonly notificationId: number; + readonly voipAcceptFailed?: boolean; } diff --git a/app/i18n/locales/ar.json b/app/i18n/locales/ar.json index 21e8858388d..05ea6661682 100644 --- a/app/i18n/locales/ar.json +++ b/app/i18n/locales/ar.json @@ -621,6 +621,7 @@ "Version_no": "إصدار التطبيق: {{version}}", "View_Original": "عرض المحتوى الأصلي", "View_Thread": "عرض الموضوع", + "VoIP_Call_Issue": "حدثت مشكلة في المكالمة، حاول مرة أخرى لاحقًا.", "Wait_activation_warning": "يحب تفعيل حسابك من المشرف قبل تسجيل الدخول", "Waiting_for_network": "بانتظار توفر شبكة...", "Websocket_disabled": "تم تعطيل Websocket لهذا الخادم.\n{{contact}}", diff --git a/app/i18n/locales/bn-IN.json b/app/i18n/locales/bn-IN.json index 410bf5ee2a7..fe56fb6199d 100644 --- a/app/i18n/locales/bn-IN.json +++ b/app/i18n/locales/bn-IN.json @@ -874,6 +874,7 @@ "video-conf-provider-not-configured-header": "কনফারেন্স কল সক্ষম হয়নি", "View_Original": "মৌলিক দেখুন", "View_Thread": "থ্রেড দেখুন", + "VoIP_Call_Issue": "কলে একটি সমস্যা হয়েছে, পরে আবার চেষ্টা করুন।", "Wait_activation_warning": "আপনি লগ ইন করতে প্রারম্ভ করতে, আপনার অ্যাকাউন্টটি প্রশাসক দ্বারা ম্যানুয়ালি অ্যাক্টিভেট হতে হবে।", "Waiting_for_answer": "উত্তরের জন্য অপেক্ষা করছি", "Waiting_for_network": "নেটওয়ার্কের জন্য অপেক্ষা করছে...", diff --git a/app/i18n/locales/cs.json b/app/i18n/locales/cs.json index 6718cc41ef5..e6a450ac36e 100644 --- a/app/i18n/locales/cs.json +++ b/app/i18n/locales/cs.json @@ -945,6 +945,7 @@ "video-conf-provider-not-configured-header": "Konferenční hovor není povolen", "View_Original": "Zobrazit originál", "View_Thread": "Zobrazit vlákno", + "VoIP_Call_Issue": "Došlo k problému s hovorem, zkuste to znovu později.", "Wait_activation_warning": "Než se budete moci přihlásit, váš účet musí být ručně aktivován administrátorem.", "Waiting_for_answer": "Čekání na odpověď", "Waiting_for_network": "Čekání na síť...", diff --git a/app/i18n/locales/de.json b/app/i18n/locales/de.json index 4c2ba85c2ef..6f5fcb3cf2a 100644 --- a/app/i18n/locales/de.json +++ b/app/i18n/locales/de.json @@ -867,6 +867,7 @@ "video-conf-provider-not-configured-header": "Telefonkonferenz nicht aktiviert", "View_Original": "Original anzeigen", "View_Thread": "Thread anzeigen", + "VoIP_Call_Issue": "Bei dem Anruf ist ein Problem aufgetreten. Bitte versuchen Sie es später erneut.", "Wait_activation_warning": "Bevor Sie sich anmelden können, muss Ihr Konto durch einen Administrator freigeschaltet werden.", "Waiting_for_answer": "Warten auf Antwort", "Waiting_for_network": "Warte auf das Netzwerk …", diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index 9aa2c054952..b6fc371d6de 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -984,6 +984,7 @@ "View_Original": "View original", "View_Thread": "View thread", "Voice_call": "Voice call", + "VoIP_Call_Issue": "There was an issue with the call, try again later.", "Wait_activation_warning": "Before you can login, your account must be manually activated by an administrator.", "Waiting_for_answer": "Waiting for answer", "Waiting_for_network": "Waiting for network...", diff --git a/app/i18n/locales/es.json b/app/i18n/locales/es.json index 72e0d6b62ff..bc9252ed24b 100644 --- a/app/i18n/locales/es.json +++ b/app/i18n/locales/es.json @@ -460,6 +460,7 @@ "Version_no": "Versión de la aplicación: {{version}}", "View_Original": "Ver original", "View_Thread": "Ver hilo", + "VoIP_Call_Issue": "Hubo un problema con la llamada, inténtelo de nuevo más tarde.", "Websocket_disabled": "Websocket está deshabilitado para este servidor.\n{{contact}}", "Whats_the_password_for_your_certificate": "¿Cuál es la contraseña de tu certificado?", "Without_Servers": "Sin servidores", diff --git a/app/i18n/locales/fi.json b/app/i18n/locales/fi.json index 377f38d5c34..74766801202 100644 --- a/app/i18n/locales/fi.json +++ b/app/i18n/locales/fi.json @@ -839,6 +839,7 @@ "Version_no": "Sovelluksen versio: {{version}}", "View_Original": "Näytä alkuperäinen", "View_Thread": "Katsele säiettä", + "VoIP_Call_Issue": "Puhelussa ilmeni ongelma, yritä myöhemmin uudelleen.", "Wait_activation_warning": "Ennen kuin voit kirjautua, järjestelmänvalvojan on aktivoitava tilisi manuaalisesti.", "Waiting_for_answer": "Odotetaan vastausta", "Waiting_for_network": "Odotetaan verkkoa...", diff --git a/app/i18n/locales/fr.json b/app/i18n/locales/fr.json index eb65e6e5ab8..b0be369a630 100644 --- a/app/i18n/locales/fr.json +++ b/app/i18n/locales/fr.json @@ -761,6 +761,7 @@ "Version_no": "Version de l'application : {{version}}", "View_Original": "Voir l'original", "View_Thread": "Afficher le fil", + "VoIP_Call_Issue": "Un problème est survenu avec l'appel, veuillez réessayer plus tard.", "Wait_activation_warning": "Avant de pouvoir vous connecter, votre compte doit être activé manuellement par un administrateur.", "Waiting_for_network": "En attente du réseau...", "Websocket_disabled": "Le Websocket est désactivé pour ce serveur.\n{{contact}}", diff --git a/app/i18n/locales/hi-IN.json b/app/i18n/locales/hi-IN.json index 78bb09a910e..110f1725d9a 100644 --- a/app/i18n/locales/hi-IN.json +++ b/app/i18n/locales/hi-IN.json @@ -874,6 +874,7 @@ "video-conf-provider-not-configured-header": "कॉन्फ़्रेंस कॉल सक्षम नहीं है", "View_Original": "मूल देखें", "View_Thread": "थ्रेड देखें", + "VoIP_Call_Issue": "कॉल में समस्या आई, कृपया बाद में पुनः प्रयास करें।", "Wait_activation_warning": "आप लॉगिन करने से पहले, आपका खाता प्रशासक द्वारा मैन्युअल रूप से सक्रिय किया जाना चाहिए।", "Waiting_for_answer": "उत्तर का इंतजार", "Waiting_for_network": "नेटवर्क के लिए प्रतीक्षा कर रहा है...", diff --git a/app/i18n/locales/hu.json b/app/i18n/locales/hu.json index 6839e2c30ba..e43c6178dad 100644 --- a/app/i18n/locales/hu.json +++ b/app/i18n/locales/hu.json @@ -876,6 +876,7 @@ "video-conf-provider-not-configured-header": "Konferenciahívás nem engedélyezett", "View_Original": "Eredeti megtekintése", "View_Thread": "Szál megtekintése", + "VoIP_Call_Issue": "Probléma történt a hívással, próbálja újra később.", "Wait_activation_warning": "Mielőtt bejelentkezhetne, a fiókját kézileg kell aktiválnia egy adminisztrátornak.", "Waiting_for_answer": "Várakozás válaszra", "Waiting_for_network": "Hálózatra várva...", diff --git a/app/i18n/locales/it.json b/app/i18n/locales/it.json index 4344347fc2f..0255e51c013 100644 --- a/app/i18n/locales/it.json +++ b/app/i18n/locales/it.json @@ -668,6 +668,7 @@ "Version_no": "Versione dell'app: {{version}}", "View_Original": "Mostra originale", "View_Thread": "Visualizza thread", + "VoIP_Call_Issue": "Si è verificato un problema con la chiamata, riprova più tardi.", "Wait_activation_warning": "Prima di poter accedere, il tuo account deve essere attivato manualmente da un amministratore.", "Waiting_for_network": "In attesa di connessione ...", "Websocket_disabled": "Websocket disabilitata per questo server.\n{{contact}}", diff --git a/app/i18n/locales/ja.json b/app/i18n/locales/ja.json index dda45aad4d9..50bf3af873e 100644 --- a/app/i18n/locales/ja.json +++ b/app/i18n/locales/ja.json @@ -551,6 +551,7 @@ "Version_no": "アプリバージョン: {{version}}", "View_Original": "オリジナルを見る", "View_Thread": "スレッドを表示します", + "VoIP_Call_Issue": "通話に問題が発生しました。しばらくしてからもう一度お試しください。", "Websocket_disabled": "Websocketはこのサーバーでは無効化されています。\n{{contact}}", "Whats_the_password_for_your_certificate": "証明書のパスワードはなんですか?", "Without_Servers": "サーバーを除く", diff --git a/app/i18n/locales/nl.json b/app/i18n/locales/nl.json index 522d23cc72d..69500f02958 100644 --- a/app/i18n/locales/nl.json +++ b/app/i18n/locales/nl.json @@ -761,6 +761,7 @@ "Version_no": "App-versie: {{version}}", "View_Original": "Bekijk origineel", "View_Thread": "Bekijk thread", + "VoIP_Call_Issue": "Er was een probleem met het gesprek, probeer het later opnieuw.", "Wait_activation_warning": "Voordat u kunt inloggen, moet uw account handmatig worden geactiveerd door een beheerder.", "Waiting_for_network": "Wachten op netwerk...", "Websocket_disabled": "Websocket is uitgeschakeld voor deze server.\n{{contact}}", diff --git a/app/i18n/locales/nn.json b/app/i18n/locales/nn.json index d171c7c1707..830c4bfc86c 100644 --- a/app/i18n/locales/nn.json +++ b/app/i18n/locales/nn.json @@ -414,6 +414,7 @@ "Verify": "Bekreft", "Verify_email_desc": "Vi har sendt deg en e-post for å bekrefte din registrering. Hvis du ikke mottar en epost, vennligst kom tilbake og prøv igjen.", "View_Thread": "Se tråden", + "VoIP_Call_Issue": "Det oppstod eit problem med samtalen, prøv igjen seinare.", "Wait_activation_warning": "Før du kan logge inn, må kontoen din aktiveres manuelt av en administrator.", "What_are_you_doing_right_now": "Hva gjør du akkurat nå?", "Why_do_you_want_to_report": "Hvorfor vil du rapportere?", diff --git a/app/i18n/locales/no.json b/app/i18n/locales/no.json index 2d5c014ce43..a520e093f8e 100644 --- a/app/i18n/locales/no.json +++ b/app/i18n/locales/no.json @@ -919,6 +919,7 @@ "video-conf-provider-not-configured-header": "Konferansesamtale ikke aktivert", "View_Original": "Se originalen", "View_Thread": "Se tråden", + "VoIP_Call_Issue": "Det oppstod et problem med samtalen, prøv igjen senere.", "Wait_activation_warning": "Før du kan logge på, må kontoen din aktiveres manuelt av en administrator.", "Waiting_for_answer": "Venter på svar", "Waiting_for_network": "Venter på nettverket ...", diff --git a/app/i18n/locales/pt-BR.json b/app/i18n/locales/pt-BR.json index cbd4dfb4eae..fd7286bad25 100644 --- a/app/i18n/locales/pt-BR.json +++ b/app/i18n/locales/pt-BR.json @@ -955,6 +955,7 @@ "video-conf-provider-not-configured-header": "Video conferência não ativada", "View_Original": "Visualizar original", "View_Thread": "Exibir thread", + "VoIP_Call_Issue": "Houve um problema com a chamada, tente novamente mais tarde.", "Wait_activation_warning": "Antes que você possa fazer o login, sua conta deve ser manualmente ativada por um administrador.", "Waiting_for_answer": "Esperando por resposta", "Waiting_for_network": "Aguardando rede...", diff --git a/app/i18n/locales/pt-PT.json b/app/i18n/locales/pt-PT.json index 4f71d5315db..f854037fcb0 100644 --- a/app/i18n/locales/pt-PT.json +++ b/app/i18n/locales/pt-PT.json @@ -523,6 +523,7 @@ "Username_or_email": "Nome de utilizador ou e-mail", "Username_required": "Nome de utilizador necessário", "View_Thread": "Exibir thread", + "VoIP_Call_Issue": "Ocorreu um problema com a chamada, tente novamente mais tarde.", "Whats_the_password_for_your_certificate": "Qual é a palavra-passe para o seu certificado?", "Workspace_URL": "URL do espaço de trabalho", "Workspace_URL_Example": "open.rocket.chat", diff --git a/app/i18n/locales/ru.json b/app/i18n/locales/ru.json index faded076a86..9a065cbcd3d 100644 --- a/app/i18n/locales/ru.json +++ b/app/i18n/locales/ru.json @@ -807,6 +807,7 @@ "Version_no": "Версия приложения: {{version}}", "View_Original": "Посмотреть оригинал", "View_Thread": "Посмотреть тему", + "VoIP_Call_Issue": "Возникла проблема со звонком, повторите попытку позже.", "Wait_activation_warning": "До того как вы сможете войти, ваш аккаунт должен быть вручную активирован администратором сервера.", "Waiting_for_answer": "Ожидание ответа", "Waiting_for_network": "Ожидание сети...", diff --git a/app/i18n/locales/sl-SI.json b/app/i18n/locales/sl-SI.json index 68e8aa5caf7..a1c6d1e7112 100644 --- a/app/i18n/locales/sl-SI.json +++ b/app/i18n/locales/sl-SI.json @@ -776,6 +776,7 @@ "Version_no": "Različica aplikacije: {{version}}", "View_Original": "Pogled original", "View_Thread": "Pogled nit", + "VoIP_Call_Issue": "Pri klicu je prišlo do težave, poskusite znova pozneje.", "Wait_activation_warning": "Preden se lahko prijavite, mora skrbnik ročno aktivirati vaš račun.", "Waiting_for_network": "Čakanje na omrežje ...", "Websocket_disabled": "WebSocket je onemogočen za ta strežnik.\n{{contact}}", diff --git a/app/i18n/locales/sv.json b/app/i18n/locales/sv.json index f22df03c7be..94945091575 100644 --- a/app/i18n/locales/sv.json +++ b/app/i18n/locales/sv.json @@ -837,6 +837,7 @@ "Version_no": "Appversion: {{version}}", "View_Original": "Visa original", "View_Thread": "Visa tråd", + "VoIP_Call_Issue": "Ett problem uppstod med samtalet, försök igen senare.", "Wait_activation_warning": "Innan du kan logga in måste ditt konto aktiveras manuellt av en administratör.", "Waiting_for_answer": "Väntar på svar", "Waiting_for_network": "Väntar på nätverket...", diff --git a/app/i18n/locales/ta-IN.json b/app/i18n/locales/ta-IN.json index a7c1dc4da6a..bcfeacc4834 100644 --- a/app/i18n/locales/ta-IN.json +++ b/app/i18n/locales/ta-IN.json @@ -874,6 +874,7 @@ "video-conf-provider-not-configured-header": "காந்ஃபரன்ஸ் கால் கொள்ளை இயக்கப்படவில்லை", "View_Original": "மூலத்தைக் காண்", "View_Thread": "நூலைக் காண்க", + "VoIP_Call_Issue": "அழைப்பில் சிக்கல் ஏற்பட்டது, பின்னர் மீண்டும் முயற்சிக்கவும்.", "Wait_activation_warning": "உள்நுழைவு செய்ய முன்வந்து, உங்கள் கணக்கு ஒரு நிர்வாகியால் கையாளப்பட வேண்டும்.", "Waiting_for_answer": "பதிலை காத்திருக்கின்றன", "Waiting_for_network": "பிணையத்தைக் காத்திருக்கின்றது...", diff --git a/app/i18n/locales/te-IN.json b/app/i18n/locales/te-IN.json index f209d932ed9..b3413bb9253 100644 --- a/app/i18n/locales/te-IN.json +++ b/app/i18n/locales/te-IN.json @@ -873,6 +873,7 @@ "video-conf-provider-not-configured-header": "కాన్ఫరెన్స్ కాల్ అనేకంగా లేదు", "View_Original": "అసలు చూడండి", "View_Thread": "థ్రెడ్‌ను వీక్షించండి", + "VoIP_Call_Issue": "కాల్‌లో సమస్య ఉంది, తర్వాత మళ్లీ ప్రయత్నించండి.", "Wait_activation_warning": "మీరు లాగిన్ చేయడానికి మొదటి స్థాయింలో మీ ఖాతాను ఒక అడ్మినిస్ట్రేటర్ మానవారం ప్రత్యామ్నాయం చేయాలి.", "Waiting_for_answer": "జవాబు కోసం ఎదురు ఉంది", "Waiting_for_network": "నెట్వర్క్ కోసం వేచి ఉండి...", diff --git a/app/i18n/locales/tr.json b/app/i18n/locales/tr.json index 051fc752a8c..20cd7c83df6 100644 --- a/app/i18n/locales/tr.json +++ b/app/i18n/locales/tr.json @@ -651,6 +651,7 @@ "Version_no": "Uygulama sürümü: {{version}}", "View_Original": "Orijinali Görüntüle", "View_Thread": "İpliği görüntüleyin", + "VoIP_Call_Issue": "Görüşmede bir sorun oluştu, daha sonra tekrar deneyin.", "Wait_activation_warning": "Giriş yapmadan önce, hesabınız bir yönetici tarafından manuel olarak etkinleştirilmelidir.", "Waiting_for_network": "Ağ bağlantısı bekleniyor ...", "Websocket_disabled": "Bu sunucu için Websocket devre dışı bırakıldı.\n{{contact}}", diff --git a/app/i18n/locales/zh-CN.json b/app/i18n/locales/zh-CN.json index 95d7ee7684c..1141065daa5 100644 --- a/app/i18n/locales/zh-CN.json +++ b/app/i18n/locales/zh-CN.json @@ -612,6 +612,7 @@ "Version_no": "应用版本: {{version}}", "View_Original": "检视原文", "View_Thread": "查看线程", + "VoIP_Call_Issue": "通话出现问题,请稍后再试。", "Wait_activation_warning": "您的帐号必须由管理员手动启用后才能登入。", "Waiting_for_network": "等待网路连接", "Websocket_disabled": "Websocket 已于此伺服器上禁用。 \\n{{contact}}", diff --git a/app/i18n/locales/zh-TW.json b/app/i18n/locales/zh-TW.json index b66d5dee1c8..6bd89bdc169 100644 --- a/app/i18n/locales/zh-TW.json +++ b/app/i18n/locales/zh-TW.json @@ -641,6 +641,7 @@ "Version_no": "應用程式版本: {{version}}", "View_Original": "檢視原文", "View_Thread": "查看線程", + "VoIP_Call_Issue": "通話發生問題,請稍後再試。", "Wait_activation_warning": "您的帳號必須由管理員手動啟用後才能登入。", "Waiting_for_network": "等待網路連線", "Websocket_disabled": "Websocket 已於此伺服器上禁用。\\n{{contact}}", diff --git a/app/index.tsx b/app/index.tsx index 87ee0fb5c82..8ff8e9d1d1b 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -153,9 +153,9 @@ export default class Root extends React.Component<{}, IState> { return; } - // TODO: change name - const handledVoipCall = await getInitialMediaCallEvents(); - if (handledVoipCall) { + const voipInitialHandled = await getInitialMediaCallEvents(); + if (voipInitialHandled) { + // VoIP path already dispatched navigation (or will via deep linking); do not call appInit() in parallel return; } diff --git a/app/lib/services/voip/MediaCallEvents.ts b/app/lib/services/voip/MediaCallEvents.ts index 141dcbfdd24..127cbef46e6 100644 --- a/app/lib/services/voip/MediaCallEvents.ts +++ b/app/lib/services/voip/MediaCallEvents.ts @@ -3,7 +3,7 @@ import { DeviceEventEmitter, NativeEventEmitter } from 'react-native'; import { isIOS } from '../../methods/helpers'; import store from '../../store'; -import { voipCallOpen } from '../../../actions/deepLinking'; +import { deepLinkingOpen } from '../../../actions/deepLinking'; import { useCallStore } from './useCallStore'; import { mediaSessionInstance } from './MediaSessionInstance'; import type { VoipPayload } from '../../../definitions/Voip'; @@ -14,6 +14,30 @@ const Emitter = isIOS ? new NativeEventEmitter(NativeVoipModule) : DeviceEventEm const platform = isIOS ? 'iOS' : 'Android'; const TAG = `[MediaCallEvents][${platform}]`; +const EVENT_VOIP_ACCEPT_FAILED = 'VoipAcceptFailed'; + +/** Dedupe native emit + stash replay for the same failed accept. */ +let lastHandledVoipAcceptFailureCallId: string | null = null; + +function dispatchVoipAcceptFailureFromNative(raw: VoipPayload & { voipAcceptFailed?: boolean }) { + if (!raw.voipAcceptFailed) { + return; + } + const { callId } = raw; + if (callId && lastHandledVoipAcceptFailureCallId === callId) { + return; + } + lastHandledVoipAcceptFailureCallId = callId; + store.dispatch( + deepLinkingOpen({ + host: raw.host, + callId: raw.callId, + username: raw.username, + voipAcceptFailed: true + }) + ); +} + /** * Sets up listeners for media call events. * @returns Cleanup function to remove listeners @@ -32,25 +56,28 @@ export const setupMediaCallEvents = (): (() => void) => { }) ); - subscriptions.push( - RNCallKeep.addEventListener('answerCall', ({ callUUID }) => { - console.log(`${TAG} Answer call event listener:`, callUUID); - mediaSessionInstance.answerCall(callUUID); - NativeVoipModule.clearInitialEvents(); - RNCallKeep.clearInitialEvents(); - }) - ); subscriptions.push( RNCallKeep.addEventListener('endCall', ({ callUUID }) => { console.log(`${TAG} End call event listener:`, callUUID); mediaSessionInstance.endCall(callUUID); }) ); + + // Note: there is intentionally no 'answerCall' listener here. + // VoipService.swift handles accept natively: handleObservedCallChanged detects + // hasConnected = true and calls handleNativeAccept(), which sends the DDP accept + // signal before JS runs. JS only reads the stored initialEventsData payload after the fact. } else { // Android listens for media call events from VoipModule subscriptions.push( - Emitter.addListener('VoipPushInitialEvents', async (data: VoipPayload) => { + Emitter.addListener('VoipPushInitialEvents', async (data: VoipPayload & { voipAcceptFailed?: boolean }) => { try { + if (data.voipAcceptFailed) { + console.log(`${TAG} Accept failed initial event`); + dispatchVoipAcceptFailureFromNative(data); + NativeVoipModule.clearInitialEvents(); + return; + } if (data.type !== 'incoming_call') { console.log(`${TAG} Not an incoming call`); return; @@ -59,7 +86,7 @@ export const setupMediaCallEvents = (): (() => void) => { NativeVoipModule.clearInitialEvents(); useCallStore.getState().setCallId(data.callId); store.dispatch( - voipCallOpen({ + deepLinkingOpen({ callId: data.callId, host: data.host }) @@ -72,20 +99,26 @@ export const setupMediaCallEvents = (): (() => void) => { ); } - // Return cleanup function + subscriptions.push( + Emitter.addListener(EVENT_VOIP_ACCEPT_FAILED, (data: VoipPayload & { voipAcceptFailed?: boolean }) => { + console.log(`${TAG} VoipAcceptFailed event:`, data); + dispatchVoipAcceptFailureFromNative({ ...data, voipAcceptFailed: true }); + NativeVoipModule.clearInitialEvents(); + }) + ); + return () => { subscriptions.forEach(sub => sub.remove()); }; }; /** - * Handles initial media call events. - * @returns true if the call was answered, false otherwise + * Handles initial media call events (cold start). + * @returns true if startup should skip the default `appInit()` path (answered call, or accept failure handed to deep linking) */ export const getInitialMediaCallEvents = async (): Promise<boolean> => { try { - // Get initial events from native module - const initialEvents = NativeVoipModule.getInitialEvents() as VoipPayload | null; + const initialEvents = NativeVoipModule.getInitialEvents() as (VoipPayload & { voipAcceptFailed?: boolean }) | null; if (!initialEvents) { console.log(`${TAG} No initial events from native module`); RNCallKeep.clearInitialEvents(); @@ -93,6 +126,14 @@ export const getInitialMediaCallEvents = async (): Promise<boolean> => { } console.log(`${TAG} Found initial events:`, initialEvents); + if (initialEvents.voipAcceptFailed && initialEvents.callId && initialEvents.host) { + dispatchVoipAcceptFailureFromNative(initialEvents); + RNCallKeep.clearInitialEvents(); + NativeVoipModule.clearInitialEvents(); + // Avoid racing `appInit()` with the deep-linking saga that handles the failure + return true; + } + if (!initialEvents.callId || !initialEvents.host || initialEvents.type !== 'incoming_call') { console.log(`${TAG} Missing required call data`); RNCallKeep.clearInitialEvents(); @@ -101,12 +142,12 @@ export const getInitialMediaCallEvents = async (): Promise<boolean> => { let wasAnswered = false; + // iOS loops through the events and checks if the call was already answered if (isIOS) { const callKeepInitialEvents = await RNCallKeep.getInitialEvents(); RNCallKeep.clearInitialEvents(); console.log(`${TAG} CallKeep initial events:`, JSON.stringify(callKeepInitialEvents, null, 2)); - // iOS loops through the events and checks if the call was already answered for (const event of callKeepInitialEvents) { const { name, data } = event; if (name === 'RNCallKeepPerformAnswerCallAction') { @@ -127,12 +168,12 @@ export const getInitialMediaCallEvents = async (): Promise<boolean> => { useCallStore.getState().setCallId(initialEvents.callId); store.dispatch( - voipCallOpen({ + deepLinkingOpen({ callId: initialEvents.callId, host: initialEvents.host }) ); - console.log(`${TAG} Dispatched voipCallOpen action`); + console.log(`${TAG} Dispatched deepLinkingOpen for VoIP`); } return Promise.resolve(wasAnswered); diff --git a/app/lib/services/voip/MediaSessionInstance.test.ts b/app/lib/services/voip/MediaSessionInstance.test.ts index 640d499b427..ca475453b75 100644 --- a/app/lib/services/voip/MediaSessionInstance.test.ts +++ b/app/lib/services/voip/MediaSessionInstance.test.ts @@ -45,7 +45,8 @@ jest.mock('react-native-webrtc', () => ({ jest.mock('react-native-callkeep', () => ({})); jest.mock('react-native-device-info', () => ({ - getUniqueId: jest.fn(() => 'test-device-id') + getUniqueId: jest.fn(() => 'test-device-id'), + getUniqueIdSync: jest.fn(() => 'test-device-id') })); jest.mock('../../native/NativeVoip', () => ({ diff --git a/app/lib/services/voip/MediaSessionInstance.ts b/app/lib/services/voip/MediaSessionInstance.ts index 772086438d0..0c066d037ad 100644 --- a/app/lib/services/voip/MediaSessionInstance.ts +++ b/app/lib/services/voip/MediaSessionInstance.ts @@ -8,7 +8,7 @@ import { } from '@rocket.chat/media-signaling'; import RNCallKeep from 'react-native-callkeep'; import { registerGlobals } from 'react-native-webrtc'; -import { getUniqueId } from 'react-native-device-info'; +import { getUniqueIdSync } from 'react-native-device-info'; import { mediaSessionStore } from './MediaSessionStore'; import { useCallStore } from './useCallStore'; @@ -16,7 +16,6 @@ import { store } from '../../store/auxStore'; import sdk from '../sdk'; import Navigation from '../../navigation/appNavigation'; import { parseStringToIceServers } from './parseStringToIceServers'; -import NativeVoipModule from '../../native/NativeVoip'; import type { IceServer } from '../../../definitions/Voip'; import type { IDDPMessage } from '../../../definitions/IDDPMessage'; import type { ISubscription, TSubscriptionModel } from '../../../definitions'; @@ -35,8 +34,6 @@ class MediaSessionInstance { this.reset(); registerGlobals(); this.configureIceServers(); - // prevent JS and native DDP clients from interfering with each other - NativeVoipModule.stopNativeDDPClient(); mediaSessionStore.setWebRTCProcessorFactory( (config: WebRTCProcessorConfig) => @@ -65,26 +62,27 @@ class MediaSessionInstance { const signal = ddpMessage.fields.args[0]; this.instance.processSignal(signal); - // If the call was accepted from another device, end the call - if (signal.type === 'notification' && signal.notification === 'accepted' && signal.signedContractId !== getUniqueId()) { - // TODO: pop from call view, end callkeep and remove incoming call notification + console.log('🤙 [VoIP] Processed signal:', signal); + + // If the call was accepted from this device, answer it + if (signal.type === 'notification' && signal.notification === 'accepted' && signal.signedContractId === getUniqueIdSync()) { + this.answerCall(signal.callId).catch(error => { + console.error('[VoIP] Error answering call :', error); + }); } }); + this.instance?.on('registered', ({ activeCalls }) => { + console.log('[VoIP] Media session registered, activeCalls:', activeCalls); + }); + this.instance?.on('newCall', ({ call }: { call: IClientMediaCall }) => { if (call && !call.hidden) { call.emitter.on('stateChange', oldState => { console.log(`📊 ${oldState} → ${call.state}`); + console.log('🤙 [VoIP] New call data:', call); }); - const existingCallId = useCallStore.getState().callId; - console.log('[VoIP] Existing call Id:', existingCallId); - // // TODO: need to answer the call here? - if (existingCallId) { - this.answerCall(existingCallId); - return; - } - if (call.role === 'caller') { useCallStore.getState().setCall(call); Navigation.navigate('CallView'); @@ -111,7 +109,7 @@ class MediaSessionInstance { Navigation.navigate('CallView'); } else { RNCallKeep.endCall(callId); - alert('Call not found'); // TODO: Show error message? + console.warn('[VoIP] Call not found:', callId); // TODO: Show error message? } }; diff --git a/app/lib/services/voip/MediaSessionStore.ts b/app/lib/services/voip/MediaSessionStore.ts index 8ccc513999c..ede6e89063a 100644 --- a/app/lib/services/voip/MediaSessionStore.ts +++ b/app/lib/services/voip/MediaSessionStore.ts @@ -7,6 +7,7 @@ import type { MediaCallWebRTCProcessor } from '@rocket.chat/media-signaling'; import { mediaDevices } from 'react-native-webrtc'; +import { getUniqueIdSync } from 'react-native-device-info'; import { MediaCallLogger } from './MediaCallLogger'; @@ -52,6 +53,9 @@ class MediaSessionStore extends Emitter<{ change: void }> { throw new Error('WebRTC processor factory and send signal function must be set'); } + // Must match native VoIP DDP contractId: iOS `DeviceUID`, Android `Settings.Secure.ANDROID_ID` (see native VoipService / VoipNotification). + const mobileDeviceId = getUniqueIdSync(); + console.log('[VoIP] Mobile device ID:', mobileDeviceId); this.sessionInstance = new MediaSignalingSession({ userId, transport: (signal: ClientMediaSignal) => this.sendSignal(signal), @@ -59,9 +63,11 @@ class MediaSessionStore extends Emitter<{ change: void }> { webrtc: (config: WebRTCProcessorConfig) => this.webrtcProcessorFactory(config) }, mediaStreamFactory: (constraints: any) => mediaDevices.getUserMedia(constraints) as unknown as Promise<MediaStream>, + displayMediaFactory: (constraints: any) => mediaDevices.getUserMedia(constraints) as unknown as Promise<MediaStream>, randomStringFactory, logger: new MediaCallLogger(), - features: ['audio'] + features: ['audio'], + mobileDeviceId }); this.change(); diff --git a/app/lib/services/voip/useCallStore.ts b/app/lib/services/voip/useCallStore.ts index bcd78534605..028cfb1ce49 100644 --- a/app/lib/services/voip/useCallStore.ts +++ b/app/lib/services/voip/useCallStore.ts @@ -29,6 +29,7 @@ interface CallStoreState { interface CallStoreActions { setCallId: (callId: string | null) => void; setCall: (call: IClientMediaCall) => void; + _cleanupCallListeners: () => void; toggleMute: () => void; toggleHold: () => void; toggleSpeaker: () => void; @@ -40,6 +41,8 @@ interface CallStoreActions { export type CallStore = CallStoreState & CallStoreActions; +let callListenersCleanup: (() => void) | null = null; + const initialState: CallStoreState = { call: null, callId: null, @@ -62,7 +65,13 @@ export const useCallStore = create<CallStore>((set, get) => ({ set({ callId }); }, + _cleanupCallListeners: () => { + callListenersCleanup?.(); + callListenersCleanup = null; + }, + setCall: (call: IClientMediaCall) => { + get()._cleanupCallListeners(); // Update state with call info set({ call, @@ -121,6 +130,12 @@ export const useCallStore = create<CallStore>((set, get) => ({ call.emitter.on('stateChange', handleStateChange); call.emitter.on('trackStateChange', handleTrackStateChange); call.emitter.on('ended', handleEnded); + + callListenersCleanup = () => { + call.emitter.off('stateChange', handleStateChange); + call.emitter.off('trackStateChange', handleTrackStateChange); + call.emitter.off('ended', handleEnded); + }; }, toggleMute: () => { @@ -189,6 +204,7 @@ export const useCallStore = create<CallStore>((set, get) => ({ }, reset: () => { + get()._cleanupCallListeners(); try { InCallManager.stop(); } catch (error) { diff --git a/app/sagas/deepLinking.js b/app/sagas/deepLinking.js index 6b0aca2235a..54452e83711 100644 --- a/app/sagas/deepLinking.js +++ b/app/sagas/deepLinking.js @@ -1,3 +1,6 @@ +import { InteractionManager } from 'react-native'; +import RNCallKeep from 'react-native-callkeep'; +import I18n from 'i18n-js'; import { all, call, delay, put, select, take, takeLatest } from 'redux-saga/effects'; import { shareSetParams } from '../actions/share'; @@ -17,12 +20,14 @@ import EventEmitter from '../lib/methods/helpers/events'; import { goRoom, navigateToRoom } from '../lib/methods/helpers/goRoom'; import { localAuthenticate } from '../lib/methods/helpers/localAuthentication'; import log from '../lib/methods/helpers/log'; +import { showToast } from '../lib/methods/helpers/showToast'; import UserPreferences from '../lib/methods/userPreferences'; import { videoConfJoin } from '../lib/methods/videoConf'; import { loginOAuthOrSso } from '../lib/services/connect'; import { notifyUser } from '../lib/services/restApi'; import sdk from '../lib/services/sdk'; import Navigation from '../lib/navigation/appNavigation'; +import { useCallStore } from '../lib/services/voip/useCallStore'; const roomTypes = { channel: 'c', @@ -87,6 +92,47 @@ const navigate = function* navigate({ params }) { yield put(appStart({ root: RootEnum.ROOT_INSIDE })); }; +/** + * After native VoIP accept fails: reset call state, end CallKit session, land inside root, + * optionally open DM via same pipeline as deep links (`direct/username`), then toast/dialog per a11y. + */ +const handleVoipAcceptFailed = function* handleVoipAcceptFailed(params) { + try { + const { callId, username } = params; + useCallStore.getState().reset(); + if (callId) { + RNCallKeep.endCall(callId); + } + + yield call(waitForNavigation); + + const navigateParams = { + ...params, + path: username ? `direct/${username}` : params.path + }; + yield navigate({ params: navigateParams }); + + yield call( + () => + new Promise((resolve) => { + InteractionManager.runAfterInteractions(() => resolve()); + }) + ); + + showToast(I18n.t('VoIP_Call_Issue')); + } catch (e) { + log(e); + } +}; + +const completeDeepLinkNavigation = function* completeDeepLinkNavigation(params) { + if (params.voipAcceptFailed) { + yield call(handleVoipAcceptFailed, params); + } else { + yield navigate({ params }); + } +}; + const fallbackNavigation = function* fallbackNavigation() { const currentRoot = yield select(state => state.app.root); if (currentRoot) { @@ -140,6 +186,10 @@ const handleOpen = function* handleOpen({ params }) { // If there's no host on the deep link params and the app is opened, just call appInit() let { host } = params; if (!host) { + if (params.voipAcceptFailed) { + yield call(handleVoipAcceptFailed, params); + return; + } yield fallbackNavigation(); return; } @@ -176,7 +226,7 @@ const handleOpen = function* handleOpen({ params }) { yield put(selectServerRequest(host, serverRecord.version, true)); yield take(types.LOGIN.SUCCESS); } - yield navigate({ params }); + yield completeDeepLinkNavigation(params); } else { // search if deep link's server already exists try { @@ -184,7 +234,7 @@ const handleOpen = function* handleOpen({ params }) { yield localAuthenticate(host); yield put(selectServerRequest(host, serverRecord.version, true, true)); yield take(types.LOGIN.SUCCESS); - yield navigate({ params }); + yield completeDeepLinkNavigation(params); return; } } catch (e) { @@ -193,6 +243,10 @@ const handleOpen = function* handleOpen({ params }) { // if deep link is from a different server const result = yield getServerInfo(host); if (!result.success) { + if (params.voipAcceptFailed) { + yield call(handleVoipAcceptFailed, params); + return; + } // Fallback to prevent the app from being stuck on splash screen yield fallbackNavigation(); return; @@ -207,7 +261,7 @@ const handleOpen = function* handleOpen({ params }) { yield put(loginRequest({ resume: params.token }, true)); yield take(types.LOGIN.SUCCESS); yield put(appReady({})); - yield navigate({ params }); + yield completeDeepLinkNavigation(params); } else { yield handleInviteLink({ params, requireLogin: true }); } @@ -297,18 +351,8 @@ const handleClickCallPush = function* handleClickCallPush({ params }) { } }; -/** - * Handle VoIP call from push notification. - * Ensures the app is connected to the correct server before the call can be processed. - * The actual call handling is done by MediaSessionInstance via the pending call store. - */ -const handleVoipCall = function* handleVoipCall({ params }) { - yield handleOpen({ params }); -}; - const root = function* root() { yield takeLatest(types.DEEP_LINKING.OPEN, handleOpen); yield takeLatest(types.DEEP_LINKING.OPEN_VIDEO_CONF, handleClickCallPush); - yield takeLatest(types.DEEP_LINKING.VOIP_CALL, handleVoipCall); }; export default root; diff --git a/ios/Libraries/AppDelegate+Voip.swift b/ios/Libraries/AppDelegate+Voip.swift index 6ceb69013a0..81b7f7ccc3c 100644 --- a/ios/Libraries/AppDelegate+Voip.swift +++ b/ios/Libraries/AppDelegate+Voip.swift @@ -1,5 +1,7 @@ import PushKit +fileprivate let voipAppDelegateLogTag = "RocketChat.AppDelegate+Voip" + // MARK: - PKPushRegistryDelegate extension AppDelegate: PKPushRegistryDelegate { @@ -22,7 +24,7 @@ extension AppDelegate: PKPushRegistryDelegate { guard let voipPayload = VoipPayload.fromDictionary(payloadDict) else { #if DEBUG - print("[\(TAG)] Failed to parse incoming VoIP payload") + print("[\(voipAppDelegateLogTag)] Failed to parse incoming VoIP payload: \(payloadDict)") #endif completion() return @@ -32,7 +34,7 @@ extension AppDelegate: PKPushRegistryDelegate { let caller = voipPayload.caller guard !voipPayload.isExpired() else { #if DEBUG - print("[\(TAG)] Skipping expired or invalid VoIP payload for callId: \(callId)") + print("[\(voipAppDelegateLogTag)] Skipping expired or invalid VoIP payload for callId: \(callId): \(voipPayload)") #endif completion() return diff --git a/ios/Libraries/VoipModule.mm b/ios/Libraries/VoipModule.mm index bb2f6953305..4fb3a329e19 100644 --- a/ios/Libraries/VoipModule.mm +++ b/ios/Libraries/VoipModule.mm @@ -35,7 +35,7 @@ - (instancetype)init { } - (NSArray<NSString *> *)supportedEvents { - return @[@"VoipPushTokenRegistered"]; + return @[@"VoipPushTokenRegistered", @"VoipAcceptFailed"]; } - (void)startObserving { @@ -46,6 +46,11 @@ - (void)startObserving { name:@"VoipPushTokenRegistered" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleVoipAcceptFailed:) + name:@"VoipAcceptFailed" + object:nil]; + // Send any delayed events for (NSDictionary *event in _delayedEvents) { NSString *name = event[@"name"]; @@ -67,6 +72,10 @@ - (void)handleVoipTokenRegistered:(NSNotification *)notification { [self sendEventWrapper:@"VoipPushTokenRegistered" body:notification.userInfo]; } +- (void)handleVoipAcceptFailed:(NSNotification *)notification { + [self sendEventWrapper:@"VoipAcceptFailed" body:notification.userInfo]; +} + - (void)sendEventWrapper:(NSString *)name body:(id)body { if (_hasListeners) { [self sendEventWithName:name body:body]; @@ -99,12 +108,14 @@ - (void)stopNativeDDPClient { [VoipService stopDDPClient]; } +// TurboModule codegen calls these on VoipModule directly. Empty implementations replaced +// RCTEventEmitter's logic, so startObserving/stopObserving never ran and no events reached JS. - (void)addListener:(NSString *)eventName { - // Required for NativeEventEmitter - starts observing + [super addListener:eventName]; } - (void)removeListeners:(double)count { - // Required for NativeEventEmitter - stops observing + [super removeListeners:count]; } #pragma mark - TurboModule diff --git a/ios/Libraries/VoipPayload.swift b/ios/Libraries/VoipPayload.swift index f7769e97222..c70a0bdf571 100644 --- a/ios/Libraries/VoipPayload.swift +++ b/ios/Libraries/VoipPayload.swift @@ -67,7 +67,8 @@ private struct RemoteVoipPayload { type: payloadType, hostName: payloadHostName, avatarUrl: caller?.avatarUrl, - createdAt: payloadCreatedAt + createdAt: payloadCreatedAt, + voipAcceptFailed: false ) } } @@ -87,6 +88,7 @@ public class VoipPayload: NSObject { @objc public let hostName: String @objc public let avatarUrl: String? @objc public let createdAt: String? + @objc public let voipAcceptFailed: Bool private var createdAtDate: Date? { return Self.parseCreatedAt(createdAt) @@ -124,7 +126,18 @@ public class VoipPayload: NSObject { return Int(hash) } - init(callId: String, callUUID: UUID, caller: String, username: String, host: String, type: String, hostName: String, avatarUrl: String?, createdAt: String?) { + init( + callId: String, + callUUID: UUID, + caller: String, + username: String, + host: String, + type: String, + hostName: String, + avatarUrl: String?, + createdAt: String?, + voipAcceptFailed: Bool = false + ) { self.callId = callId self.callUUID = callUUID self.caller = caller @@ -134,6 +147,7 @@ public class VoipPayload: NSObject { self.hostName = hostName self.avatarUrl = avatarUrl self.createdAt = createdAt + self.voipAcceptFailed = voipAcceptFailed super.init() } @@ -144,7 +158,7 @@ public class VoipPayload: NSObject { @objc public func toDictionary() -> [String: Any] { - return [ + var dict: [String: Any] = [ "callId": callId, "caller": caller, "username": username, @@ -155,6 +169,10 @@ public class VoipPayload: NSObject { "createdAt": createdAt ?? NSNull(), "notificationId": notificationId ] + if voipAcceptFailed { + dict["voipAcceptFailed"] = true + } + return dict } public func remainingLifetime(now: Date = Date()) -> TimeInterval? { diff --git a/ios/Libraries/VoipService.swift b/ios/Libraries/VoipService.swift index 8db99f60731..e0903696c36 100644 --- a/ios/Libraries/VoipService.swift +++ b/ios/Libraries/VoipService.swift @@ -42,7 +42,25 @@ public final class VoipService: NSObject { private static var isCallObserverConfigured = false private static var observedIncomingCall: ObservedIncomingCall? private static var isDdpLoggedIn = false - + /// Deduplication guard: `CXCallObserver` can call `callChanged` with `hasConnected = true` + /// multiple times for the same call (e.g. observer re-registration, system race). This set + /// ensures `handleNativeAccept` sends the DDP accept signal exactly once per callId. + /// + /// Lifecycle: + /// Added: At the start of `handleNativeAccept()`, before any DDP call. + /// Removed: After native accept DDP succeeds or fails, + /// on call timeout (`handleIncomingCallTimeout`), + /// on DDP call-end signal from another device (ddp stream listener), + /// on CallKit call-ended observer event (only before connect — `observedIncomingCall` is cleared on answer). + /// + /// Memory: One entry only while a native accept is in flight; cleared when the DDP accept finishes or other exit paths run. + private static var nativeAcceptHandledCallIds = Set<String>() + + private enum VoipMediaCallAnswerKind { + case accept + case reject + } + // MARK: - Static Methods (Called from VoipModule.mm and AppDelegate) /// Registers for VoIP push notifications via PushKit @@ -214,10 +232,15 @@ public final class VoipService: NSObject { incomingCallTimeouts.removeValue(forKey: callId)?.cancel() } + private static func clearNativeAcceptDedupe(for callId: String) { + nativeAcceptHandledCallIds.remove(callId) + } + private static func handleIncomingCallTimeout(for payload: VoipPayload) { incomingCallTimeouts.removeValue(forKey: payload.callId) clearTrackedIncomingCall(for: payload.callUUID) stopDDPClientInternal() + clearNativeAcceptDedupe(for: payload.callId) let callId = payload.callId let callUUID = payload.callUUID @@ -296,6 +319,7 @@ public final class VoipService: NSObject { return } clearTrackedIncomingCall(for: payload.callUUID) + clearNativeAcceptDedupe(for: callId) RNCallKeep.endCall(withUUID: callId, reason: 3) cancelIncomingCallTimeout(for: callId) stopDDPClientInternal() @@ -327,7 +351,7 @@ public final class VoipService: NSObject { } isDdpLoggedIn = true - if flushPendingRejectSignalIfNeeded() { + if flushPendingQueuedSignalsIfNeeded() { return } @@ -368,22 +392,28 @@ public final class VoipService: NSObject { ddpClient = nil } - private static func buildRejectMethodParams(payload: VoipPayload) -> [Any]? { + // MARK: - Native DDP signaling (accept / reject) + + /// `contractId` must match JS `getUniqueIdSync()` from react-native-device-info (`DeviceUID` on iOS; Android uses `Settings.Secure.ANDROID_ID` in VoipNotification). + private static func buildMediaCallAnswerParams(payload: VoipPayload, kind: VoipMediaCallAnswerKind) -> [Any]? { let credentialStorage = Storage() guard let credentials = credentialStorage.getCredentials(server: payload.host.removeTrailingSlash()) else { #if DEBUG - print("[\(TAG)] Missing credentials, cannot send reject for \(payload.callId)") + print("[\(TAG)] Missing credentials, cannot build media-call answer params for \(payload.callId)") #endif stopDDPClientInternal() return nil } - let signal: [String: Any] = [ + var signal: [String: Any] = [ "callId": payload.callId, "contractId": DeviceUID.uid(), "type": "answer", - "answer": "reject" + "answer": kind == .accept ? "accept" : "reject" ] + if kind == .accept { + signal["supportedFeatures"] = ["audio"] + } guard let signalData = try? JSONSerialization.data(withJSONObject: signal), @@ -396,6 +426,93 @@ public final class VoipService: NSObject { return ["\(credentials.userId)/media-calls", signalString] } + /// Native DDP accept when the user answers via CallKit (parity with Android `VoipNotification.handleAcceptAction`). + private static func handleNativeAccept(payload: VoipPayload) { + if nativeAcceptHandledCallIds.contains(payload.callId) { + return + } + nativeAcceptHandledCallIds.insert(payload.callId) + + cancelIncomingCallTimeout(for: payload.callId) + + let finishAccept: (Bool) -> Void = { success in + stopDDPClientInternal() + if success { + storeInitialEvents(payload) + clearNativeAcceptDedupe(for: payload.callId) + } else { + clearNativeAcceptDedupe(for: payload.callId) + RNCallKeep.endCall(withUUID: payload.callId, reason: 6) + let failedPayload = VoipPayload( + callId: payload.callId, + callUUID: payload.callUUID, + caller: payload.caller, + username: payload.username, + host: payload.host, + type: payload.type, + hostName: payload.hostName, + avatarUrl: payload.avatarUrl, + createdAt: payload.createdAt, + voipAcceptFailed: true + ) + storeInitialEvents(failedPayload) + var acceptFailedUserInfo: [String: Any] = [ + "callId": failedPayload.callId, + "caller": failedPayload.caller, + "username": failedPayload.username, + "host": failedPayload.host, + "type": failedPayload.type, + "hostName": failedPayload.hostName, + "notificationId": failedPayload.notificationId, + "voipAcceptFailed": true + ] + if let avatarUrl = failedPayload.avatarUrl { + acceptFailedUserInfo["avatarUrl"] = avatarUrl + } + if let createdAt = failedPayload.createdAt { + acceptFailedUserInfo["createdAt"] = createdAt + } + NotificationCenter.default.post( + name: NSNotification.Name("VoipAcceptFailed"), + object: nil, + userInfo: acceptFailedUserInfo + ) + } + } + + guard let client = ddpClient else { + #if DEBUG + print("[\(TAG)] Native DDP client unavailable for accept \(payload.callId); relying on JS") + #endif + finishAccept(false) + return + } + + guard let params = buildMediaCallAnswerParams(payload: payload, kind: .accept) else { + finishAccept(false) + return + } + + if isDdpLoggedIn { + client.callMethod("stream-notify-user", params: params) { success in + #if DEBUG + print("[\(TAG)] Native accept signal result for \(payload.callId): \(success)") + #endif + finishAccept(success) + } + } else { + client.queueMethodCall("stream-notify-user", params: params) { success in + #if DEBUG + print("[\(TAG)] Queued native accept signal result for \(payload.callId): \(success)") + #endif + finishAccept(success) + } + #if DEBUG + print("[\(TAG)] Queued native accept signal for \(payload.callId)") + #endif + } + } + private static func sendRejectSignal(payload: VoipPayload) { guard let client = ddpClient else { #if DEBUG @@ -404,7 +521,7 @@ public final class VoipService: NSObject { return } - guard let params = buildRejectMethodParams(payload: payload) else { + guard let params = buildMediaCallAnswerParams(payload: payload, kind: .reject) else { return } @@ -424,7 +541,7 @@ public final class VoipService: NSObject { return } - guard let params = buildRejectMethodParams(payload: payload) else { + guard let params = buildMediaCallAnswerParams(payload: payload, kind: .reject) else { return } @@ -436,7 +553,7 @@ public final class VoipService: NSObject { } } - private static func flushPendingRejectSignalIfNeeded() -> Bool { + private static func flushPendingQueuedSignalsIfNeeded() -> Bool { guard let client = ddpClient, client.hasQueuedMethodCalls() else { return false } @@ -489,7 +606,9 @@ public final class VoipService: NSObject { } if call.hasConnected { + let payload = observedCall.payload observedIncomingCall = nil + handleNativeAccept(payload: payload) return } @@ -499,6 +618,7 @@ public final class VoipService: NSObject { observedIncomingCall = nil cancelIncomingCallTimeout(for: observedCall.payload.callId) + clearNativeAcceptDedupe(for: observedCall.payload.callId) if isDdpLoggedIn { sendRejectSignal(payload: observedCall.payload) diff --git a/package.json b/package.json index f263e21bcc3..3e1adde3de5 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@react-navigation/elements": "^2.6.1", "@react-navigation/native": "^7.1.16", "@react-navigation/native-stack": "^7.3.23", - "@rocket.chat/media-signaling": "file:./packages/rocket.chat-media-signaling-0.1.1.tgz", + "@rocket.chat/media-signaling": "file:./packages/rocket.chat-media-signaling-0.1.3.tgz", "@rocket.chat/message-parser": "^0.31.31", "@rocket.chat/mobile-crypto": "RocketChat/rocket.chat-mobile-crypto", "@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#mobile", diff --git a/packages/rocket.chat-media-signaling-0.1.1.tgz b/packages/rocket.chat-media-signaling-0.1.1.tgz deleted file mode 100644 index 52ffe0f9308c843b85ce5f4f652b1ebbf36b929a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62589 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%0AF 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 OKK~DB$<4$7C<g$o<y@%% diff --git a/packages/rocket.chat-media-signaling-0.1.3.tgz b/packages/rocket.chat-media-signaling-0.1.3.tgz new file mode 100644 index 0000000000000000000000000000000000000000..77146990c5e151e5892f1efdf0777b5bd8b96ca9 GIT binary patch literal 70712 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 hB|}{ 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%0A#HshD%Aw@p7;Qoy^ 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 W|GIzOzwY1t{`>#Mpyet6W(WYFsFS|{ literal 0 HcmV?d00001 diff --git a/yarn.lock b/yarn.lock index 47c478e3563..132ba5a32c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5016,9 +5016,9 @@ dependencies: eslint-plugin-import "^2.17.2" -"@rocket.chat/media-signaling@file:./packages/rocket.chat-media-signaling-0.1.1.tgz": - version "0.1.1" - resolved "file:./packages/rocket.chat-media-signaling-0.1.1.tgz#b9859941d78af41e1fd82d2e0cf53d119aeaac9b" +"@rocket.chat/media-signaling@file:./packages/rocket.chat-media-signaling-0.1.3.tgz": + version "0.1.3" + resolved "file:./packages/rocket.chat-media-signaling-0.1.3.tgz#d120c37812a26c2223a53761c7936938ad05ccfb" dependencies: "@rocket.chat/emitter" "^0.32.0" ajv "^8.17.1" From e3a7a78297403418ac953cb1d3d45b7ca83c15db Mon Sep 17 00:00:00 2001 From: Diego Mello <diegolmello@gmail.com> Date: Tue, 24 Mar 2026 09:26:45 -0300 Subject: [PATCH 61/61] feat: Voice message blocks (#7057) --- android/app/src/main/assets/fonts/custom.ttf | Bin 60696 -> 61728 bytes app/containers/CustomIcon/mappedIcons.js | 7 +- app/containers/CustomIcon/selection.json | 2 +- .../MediaCallHeader/components/EndCall.tsx | 2 +- .../__snapshots__/ServerItem.test.tsx.snap | 4 +- app/containers/UIKit/Actions.tsx | 36 +- app/containers/UIKit/Context.tsx | 8 +- app/containers/UIKit/Icon.test.tsx | 87 + app/containers/UIKit/Icon.tsx | 59 + app/containers/UIKit/IconButton.tsx | 72 + app/containers/UIKit/Image.tsx | 6 +- app/containers/UIKit/InfoCard.test.tsx | 92 + app/containers/UIKit/InfoCard.tsx | 98 + app/containers/UIKit/Input.tsx | 2 +- app/containers/UIKit/Section.tsx | 11 +- app/containers/UIKit/UiKitMessage.stories.tsx | 254 +- .../VideoConferenceBaseContainer.tsx | 2 +- .../__snapshots__/UiKitMessage.test.tsx.snap | 5147 +++++++++++++++-- .../__snapshots__/UiKitModal.test.tsx.snap | 99 + app/containers/UIKit/index.tsx | 89 +- .../UIKit/interactionAdapters.test.ts | 93 + app/containers/UIKit/interactionAdapters.ts | 105 + app/containers/UIKit/interfaces.ts | 267 +- app/containers/markdown/Markdown.stories.tsx | 18 + .../markdown/Markdown.textStyle.test.tsx | 44 + .../__snapshots__/Markdown.test.tsx.snap | 1039 ++++ app/containers/markdown/components/Plain.tsx | 6 +- .../markdown/components/inline/Link.tsx | 7 +- .../components/mentions/AtMention.tsx | 21 +- .../markdown/components/mentions/Hashtag.tsx | 17 +- .../markdown/contexts/MarkdownContext.ts | 5 +- app/containers/markdown/index.tsx | 9 +- app/i18n/locales/ar.json | 4 + app/i18n/locales/bn-IN.json | 4 + app/i18n/locales/cs.json | 4 + app/i18n/locales/de.json | 4 + app/i18n/locales/en.json | 4 + app/i18n/locales/es.json | 4 + app/i18n/locales/fi.json | 4 + app/i18n/locales/fr.json | 4 + app/i18n/locales/hi-IN.json | 4 + app/i18n/locales/hu.json | 4 + app/i18n/locales/it.json | 4 + app/i18n/locales/ja.json | 4 + app/i18n/locales/nl.json | 4 + app/i18n/locales/nn.json | 4 + app/i18n/locales/no.json | 5 + app/i18n/locales/pt-BR.json | 4 + app/i18n/locales/pt-PT.json | 4 + app/i18n/locales/ru.json | 4 + app/i18n/locales/sl-SI.json | 4 + app/i18n/locales/sv.json | 4 + app/i18n/locales/ta-IN.json | 4 + app/i18n/locales/te-IN.json | 4 + app/i18n/locales/tr.json | 4 + app/i18n/locales/zh-CN.json | 4 + app/i18n/locales/zh-TW.json | 4 + app/lib/methods/actions.test.ts | 253 + app/lib/methods/actions.ts | 167 +- app/lib/methods/triggerActions.test.ts | 112 + .../__snapshots__/index.test.tsx.snap | 12 +- .../components/CallActionButton.stories.tsx | 4 +- .../components/CallActionButton.test.tsx | 2 +- app/views/CallView/components/CallButtons.tsx | 2 +- app/views/ModalBlockView.tsx | 6 +- ios/custom.ttf | Bin 60696 -> 61728 bytes jest.config.js | 2 +- jest.setup.js | 36 +- package.json | 5 +- yarn.lock | 197 +- 70 files changed, 7685 insertions(+), 922 deletions(-) create mode 100644 app/containers/UIKit/Icon.test.tsx create mode 100644 app/containers/UIKit/Icon.tsx create mode 100644 app/containers/UIKit/IconButton.tsx create mode 100644 app/containers/UIKit/InfoCard.test.tsx create mode 100644 app/containers/UIKit/InfoCard.tsx create mode 100644 app/containers/UIKit/interactionAdapters.test.ts create mode 100644 app/containers/UIKit/interactionAdapters.ts create mode 100644 app/containers/markdown/Markdown.textStyle.test.tsx create mode 100644 app/lib/methods/actions.test.ts create mode 100644 app/lib/methods/triggerActions.test.ts diff --git a/android/app/src/main/assets/fonts/custom.ttf b/android/app/src/main/assets/fonts/custom.ttf index 3151388990e26173f1f0b9471ecf479503da664c..d60bb85fc58b015925b642a282790f4a40a200b7 100644 GIT binary patch delta 2425 zcmcIkYiv|S6rR_eJNLEsxx3xcF0gIy@({Y)UAE;}Ob~guKzYft&_a2%T`3|ZCW{7* z;g`|`kr+dae@ryN6b(O2B#;<m2r&`;LC_xt2-Of@@eyOhGj|~xe`xSAch1Z`GiT13 zne%;f@+v+3Ijta!5HipaL{Y9|b#sgDsWmY24#>70{oUo{+K&bi!gZi`?dl#XL+^kt zd$DWZ@Xm{`wLb^?A%t$BzTWPh>ED?b5gG#>mHJ>ny}&Mmeg^c$zWxJ;-aHL|XzU6? z^z6RD9W%S17#!V%(Cufz$+iCOLuK?cZbIm*9<Z7)(B0qr@vm)ffPNI_50?jr4!}mC ze1o1p_b|S7952PUMwj8%k;)Nz9zBLW0JCIEVmwacNJtvT)fk4_Os3;3)V!2zSZu~& zF`vzZ4KUb{;Wh@VJkQA9#(AlL<aj)jQ`>O94bQ|4a)yUs4{J;9cpkndg?Oe?^$>+h z%HXZ}T(K~t^>-uqEl6oez<gwKx638KeLg8IOI7bO0_=*QWPIj?M7A@dJ1LDQ3d6L{ zF&aH(SkV~cl&d%@3gs1MyAw?<X}KcCF|Cecl~aWfP^iX+{j6z^W0)v9(bIw6v~F^| zagO6Gm>h3fRA<_ZQA`|z4}&?ugy@2Chck`&UXx`tdAcX0E_6bq`(Y!1jxuIyylzob zB|dq9L$+asQSQf>NZN`PtFyGs+`zUJ9AbqMSnLXwzz;-#5^YkpgmR|B9AnX584kJW z_-*4gH}n)YC7A6gM4|H;C)_m^OBKEmWNi^*ESRQn)#KBsqDV*JfM949xD!w1CKn{M zC&jtp3vMdJbioBfqw`NZSYKfX-8oM;0C0xT`{)Wz0eDJ@@qn3RB8Wr&t6&It{*UQ` z*?c-mWjoH#!>xr<qA&~6nk(c2nMg>mgdRYyx}1kHnSYjcGOrThr!`qMRC#a@wfCYW zS^zIl+X1mTo^QD8Qo4#jSOs*ooe`EI%Th64%;mF6OClcdhD<o4Sn{igO9WLSKwFRH zTqT@~i*l7bMX4ys5m7;!@gSMtDu6vKR`*cAy?#ccv!mP#KqA~Se2nONQgBbRR6~hw z9uTLxI%aA$y%+#g_IyeMUoq2x;%5WBap?r7ewtBnVoiZnGd0FIW|(nTS5xh^!kgkM z!X%UtGn+7Lrx|8pqLXf~H+>--)p96#6k~uAQ&itz!d95dV)i&qOPSnYGOolRV|X?m zvV7l?5`>PE;;PD14i(h4<ml8&4I#pyPz)gg!w5vAF~c%zSY+#j0l7mQhm{pg0m|vF zD!B#lm2kAolu#XEC|X1}N?}J5(u~a38iSfyDK(blgi*oVe2tZyWVrSNweEz48Qsme zz>Z2%<MAY$Pi%{VAGkGMKQHZ0EEwjrl$FQ=T&bbiSx=u0@i?Ir0%JiTv|*++tuCh8 zDvt?f_$r)SPL|)Tp4am6e8Vu(o*(*N8qP?73|QU-&P><g`eJaGbpoCWg+rB^uxglM zn$-n{G5W$=+nX!!)&fHwzsr!Zf60$F9KRoa;P%b%#{LCA(vlnz>hGH$O{JFP$djMe zSN?lg-xsQ9{1aGT8|gTkIG*8^{}G&ji%m@Fiu*<9Ax+b3^~FoHT3yqYEU9XX^;%7b zK{WE?^{4B;J$7>SR(sC($bi=w%8jw>4fpzylQ&xN?a>c!oS`G<Z?e%NV-MlVsijAj z{;;fP`7_HuS+SzS>p0ul*m-&7>np!rwSCpK)h~DPt`l89t*KqJWo_-+zO`ShJG}1F z`p)&|*5BMP>yh_19^3fYCUeumO_w$oHy_-5X-j(Rg>8$v!|q?UU*7Rb&z_#Ey*0f@ zcaoi_cA2}b^bPFhyASX2_Po8faqsngQ}#X8-#MxOr2%i?z`(16sH~S)l@IS1`wtFX aH~>_EZQsTX$dubhWCY*#M=M{xh<^iFTtcn@ delta 1369 zcmbu9O>7%Q6vt<Fc6WBx-u2pEuk+!L#)<79xlZgjb|R$)BuZ(%znc$Ni4!L=Nt_Qg zq5-vWfC~tO+C)@U=^-ahtrW=xDuk-2^a!XD<x;@~5<)~;P6&`_VAipV$Prd=cjnD| z`p?_>z1@xP(bb123m^c%09FA4wH-Y*VUq>h>B?vH9v#ml7wr9C&jA1()bE{2o?D=! zLVbM{re<HA{Cw@5N$M{H@WY?!iDW7m`)vk*oh2HNrs)E{%YI4y8`Q5#XO@<4ZqOOn zxeox^oSh$UOiq0lcn^TRRVwl@lU!Z^e?Tt)KPPC`vAJYs;+unpo7BHR<F75upIf4Z z(rf?s%ePO#-8I+(cXO>Uww`?-ZGkrM0Zr4Qu{exHef}Ukv`Sl8v%BD-VHsk70}S~h z^~Lznth!J!*$pfBypAugNoC`(&gS8Dk-X`eF{&2LM(XoXed{A>m7!v`38D(KPf}bA z!x7@vo=F9R?W(ysaD1pzGO;XzjLo<TA&Zbm1XUoas8-8Tm4zrg%R<O7kfvzX*Pq-u zDwF+BIxxr)bID1s#c#2?M5`TRF3w?IQ+SyWn^ab34L}HqRV1n)U<T3MnRvbm$Uu(e zC2V%%<GRLk|5qe;<I3|+JB9n#7CKK^y1_K~h|-LP-4t(pw=By=H8<1>XK$<h2Wf$A zxWLE_T?IOr_dIO^ed3E0@YoND@aogH&?j2B5cb!4LbaYl!j;7?S-*6RWb2EKP*0)z znYYC<@$_l>Af&mOkbijxdzwc$L3kr8F#5S6kvEizq}+t1JWP6g22S={R}>rKoTbKN zsv58d27Ue}*%Wa)8We(YiOKPj6KnOVD6xo>!;R&RkR&yDy<J|}MnsEXwzC%~3ak*K zNd^@QW<ha_qC?`197`bPSR)7F2^3p@R8gL_u{QHXt6%15kYhMR`I#Jqlp1-0C{<dc zz#1@#3m%*6lv6I{F;QYpXGAtN`TT>lI#qQ`B~I>HPBRmWz9lWh+h~+R4o67l5RyeT zVsC=<#aIjp%NcpeA&PE=mW5S=!DttV8Pkrs2y*C?v6}TKKfUSj_6^pIn3{eC23G&F z!Opvb=ZoX|^}QI}&pp`NM7g&forKv`OLNOsYp|`eZKJ)U{o9U}j>nx>yI$$~v^&uK zVNbf}e(z}S-QMlK>b~v%aR03{FPynDP&V+!z~&%3qzpY6t{(0mzLd}sD~YYM+S&Ao zab#_DA^GB1$=Lq*tyEQNEcMky>%{hC|CDR$cDgft@8!fan4X&n&MeJ*F?-E5`(q}N hxs!Q3*F4`le|`SmV)x?K;sGsJ|BdeFrhoYu{tZ^0_bvbc diff --git a/app/containers/CustomIcon/mappedIcons.js b/app/containers/CustomIcon/mappedIcons.js index 8d2ba432a98..b0a14e91e81 100644 --- a/app/containers/CustomIcon/mappedIcons.js +++ b/app/containers/CustomIcon/mappedIcons.js @@ -157,13 +157,14 @@ export const mappedIcons = { 'pause': 59803, 'pause-filled': 59802, 'pause-shape-filled': 59843, - 'pause-shape-unfilled': 59879, + 'pause-shape-unfilled': 59880, 'percentage': 59777, 'phone': 59806, 'phone-disabled': 59804, - 'phone-end': 59805, 'phone-in': 59809, - 'phone-issue': 59835, + 'phone-issue': 59879, + 'phone-off': 59805, + 'phone-question-mark': 59835, 'pin': 59808, 'pin-map': 59807, 'play': 59811, diff --git a/app/containers/CustomIcon/selection.json b/app/containers/CustomIcon/selection.json index 4638607a1bb..4e60e220047 100644 --- a/app/containers/CustomIcon/selection.json +++ b/app/containers/CustomIcon/selection.json @@ -1 +1 @@ -{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M224 192c-17.673 0-32 14.327-32 32v576c0 17.674 14.327 32 32 32h192c17.674 0 32-14.326 32-32v-576c0-17.673-14.326-32-32-32h-192zM256 768v-512h128v512h-128z","M608 192c-17.674 0-32 14.327-32 32v576c0 17.674 14.326 32 32 32h192c17.674 0 32-14.326 32-32v-576c0-17.673-14.326-32-32-32h-192zM640 768v-512h128v512h-128z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause-shape-unfilled"],"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]}},"attrs":[{},{}],"properties":{"order":1152,"id":227,"name":"pause-shape-unfilled","prevSize":32,"code":59879},"setIdx":0,"setId":6,"iconIdx":0},{"icon":{"paths":["M727.050 406.195c12.259-12.73 11.878-32.986-0.854-45.245-12.73-12.259-32.986-11.878-45.245 0.854l-254.285 264.061-115.615-120.061c-12.259-12.733-32.516-13.114-45.247-0.854s-13.113 32.515-0.854 45.245l138.666 144c6.032 6.266 14.355 9.805 23.050 9.805 8.698 0 17.021-3.539 23.053-9.805l277.331-288z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["check-single"],"grid":0},"attrs":[{}],"properties":{"order":1151,"id":0,"name":"check-single","prevSize":32,"code":59876},"setIdx":0,"setId":6,"iconIdx":1},{"icon":{"paths":["M599.050 406.195c12.259-12.73 11.878-32.986-0.854-45.245-12.73-12.259-32.986-11.878-45.245 0.854l-254.284 264.061-115.616-120.061c-12.259-12.733-32.516-13.114-45.247-0.854s-13.113 32.515-0.854 45.245l138.667 144c6.032 6.266 14.354 9.805 23.050 9.805s17.018-3.539 23.052-9.805l277.331-288z","M887.021 406.227c12.275-12.714 11.92-32.973-0.794-45.248s-32.973-11.92-45.248 0.794l-255.040 264.157-50.918-52.739c-12.275-12.714-32.534-13.069-45.248-0.794s-13.069 32.534-0.794 45.248l73.939 76.582c6.029 6.246 14.339 9.773 23.021 9.773s16.992-3.526 23.021-9.773l278.061-288z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["check-double"],"grid":0},"attrs":[{},{}],"properties":{"order":1150,"id":1,"name":"check-double","prevSize":32,"code":59875},"setIdx":0,"setId":6,"iconIdx":2},{"icon":{"paths":["M511.997 256c35.347 0 64-28.654 64-64s-28.653-64-64-64c-35.344 0-64 28.654-64 64s28.656 64 64 64zM639.997 192c0 70.692-57.306 128-128 128-70.691 0-128-57.308-128-128s57.309-128 128-128c70.694 0 128 57.308 128 128z","M192.859 431.645c0.669 1.446 2.097 3.488 5.957 5.232 18.33 8.272 67.426 22.054 115.377 34.39 23.244 5.981 45.187 11.366 61.327 15.261 8.067 1.946 14.672 3.517 19.258 4.598l7.078 1.664c0 0 0.026 0.003-0.218 1.046l0.218-1.046c8.33 1.933 15.562 7.123 20.042 14.406 4.48 7.28 5.859 16.054 3.834 24.358l-83.856 343.437c-0.483 1.984-1.155 3.914-2.006 5.77-1.155 2.509-1.242 5.302-0.272 7.853 0.982 2.573 3.053 4.893 6.006 6.237 2.976 1.357 6.438 1.523 9.568 0.435 3.114-1.082 5.44-3.238 6.688-5.754 0.362-0.73 0.749-1.443 1.165-2.144l121.434-204.461c5.766-9.706 16.224-15.658 27.514-15.658 11.293 0 21.747 5.952 27.514 15.658l121.437 204.461c0.413 0.701 0.803 1.414 1.165 2.144 1.245 2.515 3.571 4.672 6.685 5.754 3.13 1.088 6.592 0.922 9.568-0.435 2.957-1.344 5.027-3.664 6.006-6.237 0.97-2.55 0.883-5.344-0.269-7.853-0.854-1.856-1.526-3.786-2.010-5.77l-83.853-343.437c-2.029-8.304-0.65-17.075 3.83-24.358 4.48-7.28 11.686-12.467 20.013-14.4l0.266 1.139c-0.262-1.139-0.266-1.139-0.266-1.139l1.821-0.426 5.283-1.245c4.582-1.082 11.184-2.653 19.248-4.598 16.138-3.894 38.074-9.28 61.312-15.261 47.936-12.333 97.046-26.118 115.424-34.4 3.888-1.75 5.322-3.802 5.994-5.248 0.813-1.763 1.155-4.179 0.557-6.861-0.602-2.678-1.974-4.858-3.629-6.259-1.402-1.187-3.76-2.499-8.109-2.499h-615.975c-4.316 0-6.656 1.302-8.052 2.486-1.647 1.402-3.026 3.581-3.628 6.272s-0.26 5.12 0.556 6.886zM172.486 495.21c-75.805-34.218-48.392-143.21 31.498-143.21h615.975c79.907 0 107.44 108.989 31.478 143.216-24.554 11.066-79.939 26.24-125.766 38.032-21.494 5.533-41.85 10.554-57.651 14.384l75.597 309.616c6.986 17.306 7.216 36.614 0.538 54.147-7.085 18.598-21.283 33.501-39.283 41.699-17.978 8.189-38.474 9.126-57.123 2.64-18.234-6.342-33.469-19.36-42.39-36.566l-93.386-157.232-93.386 157.232c-8.918 17.206-24.157 30.224-42.387 36.566-18.653 6.486-39.146 5.549-57.126-2.64-18-8.198-32.198-23.101-39.282-41.699-6.678-17.533-6.449-36.842 0.539-54.147l75.595-309.613c-15.808-3.83-36.172-8.854-57.676-14.387-45.829-11.789-101.229-26.966-125.761-38.038z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["accessibility"],"grid":0},"attrs":[{},{}],"properties":{"order":1147,"id":2,"name":"accessibility","prevSize":32,"code":59874},"setIdx":0,"setId":6,"iconIdx":3},{"icon":{"paths":["M512 928c-229.75 0-416-186.246-416-416 0-229.75 186.25-416 416-416 229.754 0 416 186.25 416 416 0 229.754-186.246 416-416 416zM678.176 433.884c12.742-12.247 13.139-32.504 0.896-45.246-12.25-12.742-32.506-13.143-45.247-0.896l-207.030 198.991-68.644-65.834c-12.755-12.232-33.012-11.809-45.245 0.946s-11.809 33.012 0.946 45.245l90.819 87.1c12.39 11.885 31.948 11.872 44.324-0.026l229.183-220.28z"],"attrs":[{"fill":"rgb(20, 134, 96)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":0}]},"tags":["success-circle"],"grid":0},"attrs":[{"fill":"rgb(20, 134, 96)"}],"properties":{"order":1143,"id":3,"name":"success-circle","prevSize":32,"code":59869},"setIdx":0,"setId":6,"iconIdx":4},{"icon":{"paths":["M928 512c0-229.75-186.246-416-416-416-229.75 0-416 186.25-416 416 0 229.754 186.25 416 416 416 229.754 0 416-186.246 416-416zM662.63 361.373c12.493 12.497 12.493 32.758 0 45.254l-105.375 105.373 105.375 105.373c12.493 12.497 12.493 32.758 0 45.258-12.499 12.493-32.761 12.493-45.258 0l-105.373-105.375-105.373 105.375c-12.497 12.493-32.758 12.493-45.254 0-12.497-12.499-12.497-32.761 0-45.258l105.372-105.373-105.372-105.373c-12.497-12.497-12.497-32.758 0-45.254s32.758-12.497 45.254 0l105.373 105.372 105.373-105.372c12.497-12.497 32.758-12.497 45.258 0z"],"attrs":[{"fill":"rgb(212, 12, 38)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":1}]},"tags":["error-circle"],"grid":0},"attrs":[{"fill":"rgb(212, 12, 38)"}],"properties":{"order":1144,"id":4,"name":"error-circle","prevSize":32,"code":59873},"setIdx":0,"setId":6,"iconIdx":5},{"icon":{"paths":["M512 819.2c169.661 0 307.2-137.539 307.2-307.2s-137.539-307.2-307.2-307.2c-169.662 0-307.2 137.538-307.2 307.2s137.538 307.2 307.2 307.2z","M1024 512c0-282.77-229.228-512-512-512-282.77 0-512 229.23-512 512 0 282.772 229.23 512 512 512 282.772 0 512-229.228 512-512zM921.6 512c0 226.217-183.383 409.6-409.6 409.6-226.216 0-409.6-183.383-409.6-409.6 0-226.215 183.384-409.6 409.6-409.6 226.217 0 409.6 183.385 409.6 409.6z"],"attrs":[{"fill":"rgb(21, 111, 245)"},{"fill":"rgb(21, 111, 245)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912111124512431405712431908124569921291162451452241651":[{"f":2},{"f":2}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":4},{"f":4}]},"tags":["radio-checked"],"grid":0},"attrs":[{"fill":"rgb(21, 111, 245)"},{"fill":"rgb(21, 111, 245)"}],"properties":{"order":5,"id":5,"name":"radio-checked","prevSize":32,"code":59855},"setIdx":0,"setId":6,"iconIdx":6},{"icon":{"paths":["M512 0c282.767 0 512 229.23 512 512 0 282.767-229.233 512-512 512-282.77 0-512-229.233-512-512 0-282.77 229.23-512 512-512zM512 921.6c226.217 0 409.6-183.383 409.6-409.6 0-226.216-183.383-409.6-409.6-409.6-226.216 0-409.6 183.384-409.6 409.6 0 226.217 183.384 409.6 409.6 409.6z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912111124512431405712431908124569921291162451452241651":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["radio-unchecked"],"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":4,"id":6,"name":"radio-unchecked","prevSize":32,"code":59867},"setIdx":0,"setId":6,"iconIdx":7},{"icon":{"paths":["M678.736 135.922c7.414-5.157 16.23-7.922 25.264-7.922s17.85 2.764 25.264 7.922c7.414 5.157 13.075 12.46 16.218 20.928l0.074 0.2 32.371 89.024 89.226 32.445c8.467 3.143 15.77 8.803 20.928 16.219 5.155 7.415 7.92 16.231 7.92 25.264 0 9.034-2.765 17.85-7.92 25.264-5.158 7.414-12.461 13.075-20.931 16.218l-0.198 0.074-89.024 32.371-32.445 89.226c-3.142 8.467-8.803 15.77-16.218 20.928-7.414 5.155-16.23 7.92-25.264 7.92s-17.85-2.765-25.264-7.92c-7.414-5.158-13.075-12.461-16.218-20.931l-0.074-0.198-32.371-89.024-89.226-32.445c-8.467-3.142-15.77-8.803-20.928-16.218-5.155-7.414-7.92-16.23-7.92-25.264 0-9.032 2.765-17.848 7.92-25.264 5.158-7.415 12.461-13.075 20.931-16.218l0.198-0.074 89.024-32.372 32.445-89.224c3.142-8.468 8.803-15.771 16.218-20.928zM713.437 384l7.533-20.717c2.224-6.029 5.725-11.504 10.269-16.045 4.541-4.544 10.016-8.045 16.045-10.269l0.128-0.045 46.541-16.925-46.669-16.971c-6.029-2.221-11.504-5.724-16.045-10.267-4.544-4.542-8.045-10.017-10.269-16.044l-0.045-0.128-16.925-46.541-16.97 46.669c-2.221 6.028-5.725 11.502-10.269 16.044-4.541 4.543-10.016 8.045-16.045 10.267l-0.128 0.047-46.541 16.924 46.669 16.97c6.029 2.221 11.504 5.725 16.045 10.269 4.544 4.541 8.045 10.016 10.269 16.045l0.045 0.128 16.925 46.541 9.437-25.952z","M323.091 265.629c8.256-6.153 18.346-9.629 28.909-9.629s20.653 3.477 28.909 9.629c8.224 6.127 14.17 14.542 17.402 23.873l0.067 0.191 47.674 140.467 130.595 50.883c9.696 3.856 17.67 10.64 23.126 19.046 5.44 8.381 8.227 18.118 8.227 27.91s-2.787 19.53-8.227 27.91c-5.456 8.406-13.434 15.19-23.126 19.046l-0.208 0.083-130.387 50.8-47.741 140.659c-3.232 9.328-9.178 17.744-17.402 23.872-8.256 6.15-18.346 9.629-28.909 9.629s-20.653-3.478-28.909-9.629c-8.223-6.128-14.17-14.544-17.402-23.875l-0.066-0.189-47.673-140.467-130.596-50.883c-9.694-3.856-17.669-10.64-23.125-19.046-5.442-8.381-8.228-18.118-8.228-27.91s2.787-19.53 8.228-27.91c5.456-8.406 13.431-15.19 23.125-19.046l0.208-0.083 130.388-50.8 47.739-140.658c3.233-9.331 9.18-17.746 17.403-23.873zM381.222 617.712l6.314-18.602c2.291-6.659 5.958-12.874 10.88-18.147 4.928-5.28 11.014-9.507 17.917-12.23l0.134-0.054 104.41-40.678-104.544-40.733c-6.902-2.723-12.989-6.95-17.917-12.23-4.922-5.274-8.589-11.488-10.88-18.147l-0.042-0.125-35.494-104.579-35.536 104.704c-2.291 6.659-5.959 12.874-10.881 18.147-4.929 5.28-11.015 9.507-17.916 12.23l-0.133 0.054-104.411 40.678 104.544 40.733c6.901 2.723 12.988 6.95 17.916 12.23 4.923 5.274 8.59 11.488 10.881 18.147l0.042 0.125 35.494 104.579 29.222-86.102z","M704 544c-9.034 0-17.85 2.765-25.264 7.92-7.414 5.158-13.075 12.461-16.218 20.928l-32.445 89.226-89.222 32.445c-8.47 3.142-15.773 8.803-20.931 16.218-5.155 7.414-7.92 16.23-7.92 25.264s2.765 17.85 7.92 25.264c5.158 7.414 12.461 13.075 20.928 16.218l89.226 32.445 32.445 89.222c3.142 8.47 8.803 15.773 16.218 20.931 7.414 5.155 16.23 7.92 25.264 7.92s17.85-2.765 25.264-7.92c7.414-5.158 13.075-12.461 16.218-20.928l32.445-89.226 89.222-32.445c8.47-3.142 15.773-8.803 20.931-16.218 5.155-7.414 7.92-16.23 7.92-25.264s-2.765-17.85-7.92-25.264c-5.158-7.414-12.461-13.075-20.928-16.218l-89.226-32.445-32.445-89.222c-3.142-8.47-8.803-15.773-16.218-20.931-7.414-5.155-16.23-7.92-25.264-7.92zM720.97 779.283l-6.829 18.784-10.141 27.885-16.97-46.669c-2.224-6.029-5.725-11.504-10.269-16.045-4.541-4.544-10.016-8.048-16.045-10.269l-46.669-16.97 46.669-16.97c6.029-2.221 11.504-5.725 16.045-10.269 4.544-4.541 8.048-10.016 10.269-16.045l16.97-46.669 16.97 46.669c2.224 6.029 5.725 11.504 10.269 16.045 4.541 4.544 10.016 8.048 16.045 10.269l46.669 16.97-46.669 16.97c-6.029 2.224-11.504 5.725-16.045 10.269-4.544 4.541-8.045 10.016-10.269 16.045z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{},{}]},"tags":["stars"],"grid":0},"attrs":[{},{},{}],"properties":{"order":1139,"id":7,"name":"stars","prevSize":32,"code":59845},"setIdx":0,"setId":6,"iconIdx":8},{"icon":{"paths":["M810.666 512c0.022 8.358-2.173 16.579-6.371 23.862-4.195 7.283-10.253 13.382-17.581 17.706l-454.067 271.187c-7.658 4.576-16.425 7.075-25.4 7.235-8.975 0.163-17.832-2.016-25.656-6.314-7.749-4.23-14.205-10.397-18.702-17.872-4.498-7.472-6.875-15.981-6.888-24.65v-542.311c0.013-8.668 2.39-17.176 6.888-24.649s10.953-13.642 18.702-17.872c7.824-4.297 16.681-6.477 25.656-6.315s17.743 2.661 25.4 7.237l454.067 271.186c7.328 4.323 13.386 10.422 17.581 17.706 4.198 7.283 6.394 15.504 6.371 23.862z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["play-shape-filled"],"grid":0},"attrs":[{}],"properties":{"order":4,"id":8,"name":"play-shape-filled","prevSize":32,"code":59842},"setIdx":0,"setId":6,"iconIdx":9},{"icon":{"paths":["M832 245.333v533.332c0 14.147-5.693 27.712-15.824 37.712-10.131 10.003-23.872 15.622-38.202 15.622h-135.066c-14.33 0-28.070-5.619-38.202-15.622-10.131-10-15.824-23.565-15.824-37.712v-533.332c0-14.145 5.693-27.71 15.824-37.712s23.872-15.621 38.202-15.621h135.066c14.33 0 28.070 5.619 38.202 15.621s15.824 23.567 15.824 37.712zM381.091 192h-135.065c-14.329 0-28.070 5.619-38.202 15.621s-15.824 23.567-15.824 37.712v533.332c0 14.147 5.692 27.712 15.824 37.712 10.132 10.003 23.874 15.622 38.202 15.622h135.065c14.33 0 28.070-5.619 38.202-15.622 10.131-10 15.824-23.565 15.824-37.712v-533.332c0-14.145-5.693-27.71-15.824-37.712s-23.872-15.621-38.202-15.621z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["pause-shape-filled"],"grid":0},"attrs":[{}],"properties":{"order":3,"id":9,"name":"pause-shape-filled","prevSize":32,"code":59843},"setIdx":0,"setId":6,"iconIdx":10},{"icon":{"paths":["M593.158 920.006c-80.698 16.051-164.342 7.814-240.355-23.674-76.014-31.485-140.984-84.806-186.695-153.216s-70.108-148.842-70.108-231.117h64c0 69.619 20.644 137.674 59.323 195.562 38.678 57.885 93.653 103.002 157.973 129.645 64.32 26.64 135.094 33.613 203.376 20.029 68.282-13.581 131.002-47.107 180.23-96.333 49.226-49.229 82.752-111.949 96.333-180.23 13.584-68.282 6.611-139.056-20.029-203.376-26.643-64.32-71.76-119.295-129.645-157.973-57.888-38.678-125.942-59.323-195.562-59.323v-64c82.278 0 162.707 24.398 231.117 70.109s121.731 110.681 153.216 186.695v0c31.488 76.013 39.725 159.658 23.674 240.355-16.051 80.694-55.67 154.819-113.85 212.998s-132.304 97.798-212.998 113.85z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["loading"],"grid":0},"attrs":[{}],"properties":{"order":2,"id":10,"name":"loading","prevSize":32,"code":59844},"setIdx":0,"setId":6,"iconIdx":11},{"icon":{"paths":["M544 208c0-17.673-14.326-32-32-32s-32 14.327-32 32v271.997h-271.998c-17.673 0-32 14.326-32 32s14.327 32 32 32h271.998v272.003c0 17.674 14.326 32 32 32s32-14.326 32-32v-272.003l272-0.003c17.674 0 32-14.326 32-32s-14.326-32-32-32l-272 0.003v-271.997z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["add"],"defaultCode":59872,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":923,"name":"add","prevSize":32,"id":11,"code":59872},"setIdx":0,"setId":6,"iconIdx":12},{"icon":{"paths":["M512 928c-14.218 0-28.275-0.714-42.144-2.112-16.694-1.68-30.557-12.528-36.688-27.395l-40.538-98.304-98.162 40.838c-14.837 6.173-32.3 4.048-45.292-6.554-21.838-17.818-41.831-37.811-59.65-59.648-10.601-12.992-12.726-30.454-6.553-45.293l40.839-98.16-98.307-40.541c-14.864-6.131-25.714-19.994-27.395-36.688-1.396-13.869-2.111-27.926-2.111-42.144 0-14.214 0.714-28.275 2.11-42.141 1.681-16.694 12.531-30.557 27.395-36.688l98.308-40.541-40.84-98.163c-6.173-14.837-4.047-32.3 6.553-45.292 17.818-21.838 37.81-41.83 59.648-59.648 12.992-10.6 30.455-12.726 45.292-6.553l98.165 40.84 40.541-98.309c6.128-14.865 19.994-25.714 36.688-27.395 13.866-1.396 27.926-2.11 42.141-2.11s28.275 0.714 42.141 2.11c16.694 1.681 30.56 12.531 36.688 27.395l40.541 98.309 98.163-40.84c14.838-6.173 32.301-4.047 45.293 6.553 21.837 17.818 41.83 37.81 59.648 59.648 10.602 12.992 12.726 30.455 6.554 45.292l-40.842 98.163 98.31 40.541c14.864 6.131 25.712 19.994 27.392 36.688 1.398 13.866 2.112 27.926 2.112 42.141 0 14.218-0.714 28.275-2.112 42.144-1.68 16.694-12.528 30.557-27.395 36.688l-98.307 40.541 40.842 98.16c6.173 14.838 4.045 32.301-6.554 45.293-17.821 21.837-37.811 41.83-59.651 59.648-12.992 10.602-30.454 12.726-45.29 6.554l-98.163-40.838-40.538 98.304c-6.131 14.867-19.994 25.715-36.688 27.395-13.869 1.398-27.93 2.112-42.144 2.112zM444.451 757.984l43.386 105.2c7.981 0.541 16.038 0.816 24.163 0.816s16.182-0.275 24.163-0.816l43.382-105.2c9.456-22.925 35.731-33.808 58.627-24.285l105.056 43.709c12.157-10.602 23.578-22.022 34.179-34.179l-43.709-105.056c-9.526-22.893 1.36-49.171 24.282-58.624l105.203-43.386c0.541-7.978 0.816-16.038 0.816-24.163s-0.275-16.182-0.816-24.16l-105.203-43.386c-22.922-9.453-33.808-35.731-24.282-58.624l43.709-105.060c-10.602-12.156-22.022-23.577-34.176-34.177l-105.059 43.708c-22.896 9.525-49.171-1.359-58.627-24.283l-43.382-105.204c-7.981-0.54-16.038-0.815-24.163-0.815s-16.182 0.275-24.163 0.815l-43.386 105.204c-9.453 22.924-35.728 33.808-58.624 24.283l-105.058-43.708c-12.156 10.6-23.577 22.021-34.177 34.177l43.708 105.059c9.525 22.893-1.359 49.171-24.284 58.624l-105.203 43.386c-0.54 7.978-0.815 16.035-0.815 24.16 0 8.128 0.275 16.186 0.815 24.163l105.203 43.386c22.924 9.453 33.809 35.731 24.284 58.624l-43.708 105.056c10.601 12.157 22.022 23.578 34.178 34.179l105.056-43.709c22.896-9.523 49.171 1.36 58.624 24.285zM416 512c0-53.021 42.979-96 96-96s96 42.979 96 96c0 53.021-42.979 96-96 96s-96-42.979-96-96zM512 352c-88.365 0-160 71.635-160 160s71.635 160 160 160c88.365 0 160-71.635 160-160s-71.635-160-160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["administration"],"defaultCode":59662,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":924,"name":"administration","prevSize":32,"id":12,"code":59662},"setIdx":0,"setId":6,"iconIdx":13},{"icon":{"paths":["M878.739 567.622c-41.853-41.136-161.235-29.824-220.925-22.282-59.005-35.997-98.458-85.706-126.243-158.73 13.379-55.194 34.646-139.185 18.525-191.98-14.41-89.82-129.674-80.907-146.141-20.227-15.094 55.195-1.373 131.988 24.013 230.034-34.304 81.936-85.421 191.984-121.441 255.062-68.611 35.312-161.235 89.821-174.957 158.384-11.321 54.166 89.194 189.238 261.063-106.96 76.845-25.37 160.547-56.566 234.65-68.909 64.835 34.97 140.65 58.282 191.421 58.282 87.478 0 96.054-96.678 60.035-132.675zM199.152 834.342c17.496-46.97 84.048-101.133 104.288-119.99-65.18 103.875-104.288 122.39-104.288 119.99zM479.082 180.918c25.386 0 22.986 110.047 6.176 139.873-15.094-47.653-14.752-139.873-6.176-139.873zM395.379 649.216c33.274-57.936 61.747-126.845 84.733-187.526 28.474 51.766 64.838 93.251 103.258 121.706-71.354 14.739-133.446 44.909-187.99 65.821zM846.835 632.074c0 0-17.152 20.57-127.958-26.739 120.413-8.912 140.307 18.512 127.958 26.739z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["adobe-reader-monochromatic"],"defaultCode":59663,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":925,"name":"adobe-reader-monochromatic","prevSize":32,"id":13,"code":59663},"setIdx":0,"setId":6,"iconIdx":14},{"icon":{"paths":["M512 192c-13.056 0-25.578 5.187-34.813 14.419-9.232 9.233-14.419 21.755-14.419 34.812v162.462c0 12.122-6.848 23.2-17.686 28.621l-253.082 126.541v49.498l232.493-46.499c9.402-1.882 19.149 0.554 26.563 6.63 7.414 6.080 11.712 15.162 11.712 24.749v108.307c0 8.486-3.37 16.624-9.373 22.627l-44.781 44.781v47.789l91.501-36.602c7.629-3.050 16.141-3.050 23.77 0l91.501 36.602v-47.789l-44.781-44.781c-6.003-6.003-9.373-14.141-9.373-22.627v-108.307c0-9.587 4.298-18.669 11.712-24.749 7.414-6.077 17.162-8.512 26.563-6.63l232.493 46.499v-49.498l-253.082-126.541c-10.838-5.421-17.686-16.499-17.686-28.621v-162.462c0-13.057-5.187-25.579-14.419-34.812-9.235-9.232-21.757-14.419-34.813-14.419zM431.933 161.164c21.235-21.235 50.035-33.164 80.067-33.164s58.832 11.93 80.067 33.164c21.235 21.235 33.165 50.036 33.165 80.066v142.686l253.078 126.538c10.842 5.421 17.69 16.502 17.69 28.624v108.307c0 9.587-4.298 18.669-11.712 24.746s-17.162 8.512-26.563 6.63l-232.493-46.496v56.019l44.781 44.781c6 6 9.373 14.141 9.373 22.627v108.307c0 10.618-5.267 20.544-14.061 26.499-8.794 5.952-19.965 7.155-29.824 3.213l-123.501-49.402-123.501 49.402c-9.859 3.942-21.030 2.739-29.824-3.213-8.794-5.955-14.061-15.882-14.061-26.499v-108.307c0-8.486 3.373-16.627 9.373-22.627l44.781-44.781v-56.019l-232.492 46.496c-9.401 1.882-19.149-0.554-26.564-6.63s-11.712-15.158-11.712-24.746v-108.307c0-12.122 6.848-23.203 17.689-28.624l253.079-126.538v-142.686c0-30.031 11.93-58.831 33.165-80.066z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["airplane"],"defaultCode":59815,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":926,"id":14,"name":"airplane","prevSize":32,"code":59815},"setIdx":0,"setId":6,"iconIdx":15},{"icon":{"paths":["M448 188.865c0 33.615 27.251 60.865 60.864 60.865 33.616 0 60.867-27.25 60.867-60.865s-27.251-60.865-60.867-60.865c-33.613 0-60.864 27.25-60.864 60.865zM384 188.865c0 59.026 40.957 108.485 96 121.512v77.745c-44.314 11.69-78.986 47.13-89.578 91.878h-80.045c-13.027-55.043-62.486-96-121.512-96-68.961 0-124.865 55.904-124.865 124.864 0 68.963 55.904 124.867 124.865 124.867 56.762 0 104.678-37.875 119.854-89.731h83.361c12.227 41.773 45.696 74.47 87.92 85.61v77.744c-55.043 13.027-96 62.486-96 121.51 0 68.963 55.904 124.867 124.864 124.867 68.963 0 124.867-55.904 124.867-124.867 0-56.762-37.875-104.675-89.731-119.853v-79.437c42.163-11.171 75.578-43.846 87.789-85.574h77.222c15.178 51.856 63.091 89.731 119.853 89.731 68.963 0 124.867-55.904 124.867-124.867 0-68.96-55.904-124.864-124.867-124.864-59.024 0-108.483 40.957-121.51 96h-73.907c-10.579-44.707-45.194-80.122-89.446-91.843v-79.438c51.856-15.176 89.731-63.092 89.731-119.854 0-68.961-55.904-124.865-124.867-124.865-68.96 0-124.864 55.904-124.864 124.865zM828.864 569.731c-33.613 0-60.864-27.251-60.864-60.867 0-33.613 27.251-60.864 60.864-60.864 33.616 0 60.867 27.251 60.867 60.864 0 33.616-27.251 60.867-60.867 60.867zM188.865 569.731c-33.615 0-60.865-27.251-60.865-60.867 0-33.613 27.25-60.864 60.865-60.864s60.865 27.251 60.865 60.864c0 33.616-27.25 60.867-60.865 60.867zM451.069 508.864c0 33.616 27.251 60.867 60.867 60.867 33.613 0 60.864-27.251 60.864-60.867 0-33.613-27.251-60.864-60.864-60.864-33.616 0-60.867 27.251-60.867 60.864zM508.864 889.731c-33.613 0-60.864-27.251-60.864-60.867 0-33.613 27.251-60.864 60.864-60.864 33.616 0 60.867 27.251 60.867 60.864 0 33.616-27.251 60.867-60.867 60.867z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["all-contacts-in-channels"],"defaultCode":59664,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":927,"name":"all-contacts-in-channels","prevSize":32,"id":15,"code":59664},"setIdx":0,"setId":6,"iconIdx":16},{"icon":{"paths":["M861.437 160c17.67 0 32 14.327 32 32s-14.33 32-32 32h-384c-17.674 0-32-14.327-32-32s14.326-32 32-32h384zM334.717 442.397c-24.962 0-45.197-20.237-45.197-45.2 0-24.96 20.236-45.197 45.197-45.197 24.963 0 45.2 20.237 45.2 45.197 0 24.963-20.237 45.2-45.2 45.2zM334.717 506.397c-60.308 0-109.197-48.89-109.197-109.2 0-60.307 48.89-109.197 109.197-109.197 60.31 0 109.2 48.89 109.2 109.197 0 60.31-48.89 109.2-109.2 109.2zM456.278 535.504c-18.288-4.899-37.504-5.2-55.939-0.88l-45.005 10.547c-13.194 3.091-26.947 2.877-40.036-0.63l-31.676-8.483c-19.669-5.27-40.384-5.562-60.154-0.928-55.68 13.050-95.468 62.781-95.468 120.179v34.752c0 42.906 34.783 77.686 77.689 77.686h258.057c42.906 0 77.69-34.781 77.69-77.686v-43.587c0-52-34.928-97.514-85.158-110.97zM414.944 596.934c8.166-1.914 16.675-1.779 24.774 0.39 22.246 5.958 37.718 26.118 37.718 49.149v43.587c0 7.558-6.131 13.686-13.69 13.686h-258.057c-7.56 0-13.689-6.128-13.689-13.686v-34.752c0-27.469 19.123-51.552 46.072-57.869 9.556-2.24 19.564-2.086 28.99 0.438l31.676 8.483c23.277 6.237 47.738 6.621 71.2 1.12l45.005-10.547zM893.437 512c0-17.674-14.33-32-32-32h-224c-17.674 0-32 14.326-32 32s14.326 32 32 32h224c17.67 0 32-14.326 32-32zM861.437 640c17.67 0 32 14.326 32 32s-14.33 32-32 32h-192c-17.674 0-32-14.326-32-32s14.326-32 32-32h192zM893.437 352c0-17.674-14.33-32-32-32h-288c-17.674 0-32 14.326-32 32s14.326 32 32 32h288c17.67 0 32-14.326 32-32zM861.437 800c17.67 0 32 14.326 32 32s-14.33 32-32 32h-256c-17.674 0-32-14.326-32-32s14.326-32 32-32h256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["all-contacts-in-queue"],"defaultCode":59665,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":928,"name":"all-contacts-in-queue","prevSize":32,"id":16,"code":59665},"setIdx":0,"setId":6,"iconIdx":17},{"icon":{"paths":["M523.571 295.385c33.133 0 74.669-22.133 99.402-51.645 22.4-26.745 38.733-64.095 38.733-101.445 0-5.072-0.467-10.144-1.402-14.294-36.864 1.383-81.2 24.439-107.798 55.334-21.002 23.517-40.134 60.406-40.134 98.218 0 5.533 0.934 11.067 1.402 12.911 2.333 0.461 6.067 0.922 9.798 0.922zM406.906 853.334c45.267 0 65.334-29.974 121.798-29.974 57.402 0 70 29.050 120.4 29.050 49.469 0 82.602-45.187 113.869-89.456 34.998-50.72 49.466-100.522 50.4-102.829-3.267-0.922-98-39.194-98-146.634 0-93.146 74.666-135.107 78.867-138.333-49.469-70.090-124.602-71.935-145.136-71.935-55.533 0-100.8 33.199-129.264 33.199-30.8 0-71.402-31.354-119.469-31.354-91.466 0-184.333 74.701-184.333 215.802 0 87.61 34.533 180.294 77 240.24 36.402 50.723 68.133 92.224 113.867 92.224z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["apple-monochromatic"],"defaultCode":59666,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":929,"name":"apple-monochromatic","prevSize":32,"id":17,"code":59666},"setIdx":0,"setId":6,"iconIdx":18},{"icon":{"paths":["M498.694 141.561l-298.666 136.533c-11.39 5.207-18.696 16.58-18.696 29.103v386.844c0 11.818 6.513 22.675 16.941 28.237l298.667 159.286c9.411 5.021 20.707 5.021 30.118 0l298.666-159.286c10.429-5.562 16.941-16.419 16.941-28.237v-386.844c0-12.524-7.306-23.896-18.694-29.103l-298.666-136.533c-8.451-3.862-18.16-3.862-26.611 0zM245.333 357.011l234.667 107.277v335.709l-234.667-125.155v-317.83zM544 799.997l234.666-125.155v-317.83l-234.666 107.277v335.709zM512 408.544l-221.7-101.347 221.7-101.348 221.699 101.348-221.699 101.347z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["apps"],"defaultCode":59667,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":930,"name":"apps","prevSize":32,"id":18,"code":59667},"setIdx":0,"setId":6,"iconIdx":19},{"icon":{"paths":["M374.627 297.372c-12.496-12.497-32.758-12.497-45.254 0l-192 192c-12.497 12.496-12.497 32.758 0 45.254l192 192c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-137.372-137.373h578.745v128c0 17.674 14.326 32 32 32s32-14.326 32-32v-160c0-17.674-14.326-32-32-32h-610.745l137.372-137.373c12.496-12.496 12.496-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-back"],"defaultCode":59668,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":931,"name":"arrow-back","prevSize":32,"id":19,"code":59668},"setIdx":0,"setId":6,"iconIdx":20},{"icon":{"paths":["M551.392 242.502c0.189-17.672 14.669-31.845 32.339-31.656 17.674 0.189 31.846 14.668 31.658 32.34l-1.318 123.489 193.44-193.439c12.496-12.497 32.755-12.497 45.254 0 12.496 12.497 12.496 32.758 0 45.255l-193.44 193.439 123.488-1.318c17.674-0.189 32.154 13.984 32.339 31.654 0.189 17.674-13.984 32.154-31.654 32.342l-201.92 2.154c-8.605 0.093-16.886-3.283-22.97-9.37-6.086-6.083-9.462-14.365-9.373-22.97l2.157-201.92zM475.981 782.147c-0.189 17.674-14.669 31.846-32.339 31.658-17.674-0.189-31.846-14.669-31.658-32.342l1.318-123.488-193.438 193.44c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l193.438-193.44-123.488 1.318c-17.672 0.189-32.151-13.984-32.34-31.654-0.189-17.674 13.984-32.154 31.656-32.342l201.922-2.154c8.605-0.093 16.883 3.283 22.966 9.37 6.086 6.083 9.462 14.365 9.373 22.97l-2.157 201.92z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-collapse"],"defaultCode":59669,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":932,"name":"arrow-collapse","prevSize":32,"id":20,"code":59669},"setIdx":0,"setId":6,"iconIdx":21},{"icon":{"paths":["M576 672c-17.674 0-32 14.326-32 32s14.326 32 32 32h224c17.674 0 32-14.326 32-32v-208c0-17.674-14.326-32-32-32s-32 14.326-32 32v130.746l-233.373-233.373c-12.496-12.496-32.758-12.496-45.254 0l-73.373 73.373-169.372-169.373c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.759 0 45.255l192 192c12.496 12.496 32.758 12.496 45.254 0l73.373-73.373 210.746 210.746h-146.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-decrease"],"defaultCode":59670,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":933,"name":"arrow-decrease","prevSize":32,"id":21,"code":59670},"setIdx":0,"setId":6,"iconIdx":22},{"icon":{"paths":["M726.88 526.064c12.355 12.637 12.128 32.896-0.509 45.254l-191.968 187.715c-12.438 12.163-32.31 12.163-44.746 0l-191.97-187.715c-12.636-12.358-12.863-32.618-0.507-45.254 12.356-12.634 32.615-12.861 45.252-0.506l137.597 134.55v-372.109c0-17.673 14.33-32 32-32 17.674 0 32 14.327 32 32v372.109l137.6-134.55c12.634-12.355 32.896-12.128 45.251 0.506z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-down"],"defaultCode":59673,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":934,"name":"arrow-down","prevSize":32,"id":22,"code":59673},"setIdx":0,"setId":6,"iconIdx":23},{"icon":{"paths":["M329.373 550.627c-12.497-12.496-12.497-32.758 0-45.254s32.758-12.496 45.254 0l105.373 105.373v-418.746c0-17.673 14.326-32 32-32s32 14.327 32 32v418.746l105.373-105.373c12.496-12.496 32.758-12.496 45.254 0s12.496 32.758 0 45.254l-160 160c-12.496 12.496-32.758 12.496-45.254 0l-160-160zM112 864c0 17.674 14.327 32 32 32h768c17.674 0 32-14.326 32-32v-512c0-17.674-14.326-32-32-32h-96c-17.674 0-32 14.326-32 32s14.326 32 32 32h64v448h-704v-448h64c17.673 0 32-14.326 32-32s-14.327-32-32-32h-96c-17.673 0-32 14.326-32 32v512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-down-box"],"defaultCode":59671,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":935,"name":"arrow-down-box","prevSize":32,"id":23,"code":59671},"setIdx":0,"setId":6,"iconIdx":24},{"icon":{"paths":["M866.49 512c0-194.404-157.802-352-352.464-352-194.661 0-352.465 157.596-352.465 352s157.804 352 352.465 352c194.662 0 352.464-157.597 352.464-352zM930.576 512c0 229.75-186.496 416-416.55 416s-416.549-186.25-416.549-416c0-229.75 186.495-416 416.549-416s416.55 186.25 416.55 416zM696.525 571.37c12.682-12.33 12.957-32.589 0.611-45.251-12.342-12.666-32.63-12.938-45.309-0.611l-105.789 102.842v-276.349c0-17.674-14.346-32-32.045-32-17.696 0-32.042 14.326-32.042 32v276.349l-105.789-102.842c-12.678-12.326-32.966-12.054-45.309 0.611-12.344 12.662-12.071 32.922 0.608 45.251l160.182 155.715c12.438 12.093 32.259 12.093 44.701 0l160.179-155.715z"],"width":1056,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-down-circle"],"defaultCode":59672,"grid":0},"attrs":[{}],"properties":{"order":936,"name":"arrow-down-circle","prevSize":32,"id":24,"code":59672},"setIdx":0,"setId":6,"iconIdx":25},{"icon":{"paths":["M859.978 398.15c-0.189 17.67-14.666 31.843-32.339 31.654-17.67-0.189-31.846-14.666-31.658-32.339l1.318-123.488-193.437 193.437c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.755 0-45.254l193.437-193.437-123.488 1.318c-17.67 0.189-32.15-13.984-32.339-31.656s13.984-32.151 31.658-32.34l201.92-2.156c8.605-0.092 16.883 3.286 22.97 9.371 6.083 6.085 9.462 14.364 9.37 22.969l-2.157 201.922zM167.394 626.522c0.189-17.674 14.668-31.846 32.34-31.658s31.845 14.669 31.657 32.339l-1.319 123.488 193.438-193.437c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-193.438 193.437 123.489-1.318c17.67-0.189 32.15 13.984 32.339 31.658 0.189 17.67-13.984 32.15-31.658 32.339l-201.92 2.157c-8.605 0.093-16.884-3.286-22.969-9.37-6.085-6.086-9.463-14.365-9.371-22.97l2.156-201.92z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-expand"],"defaultCode":59674,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":937,"name":"arrow-expand","prevSize":32,"id":25,"code":59674},"setIdx":0,"setId":6,"iconIdx":26},{"icon":{"paths":["M623.488 420.944h-129.030c-146.778 0-279.962 128.675-298.822 309.533 98.511-81.834 219.072-127.946 345.446-127.946h82.406v123.408l188.595-214.202-188.595-214.2v123.406zM888.045 501.165c5.322 6.045 5.325 15.104 0 21.149l-300.547 341.354c-9.747 11.069-28.010 4.176-28.010-10.573v-186.563h-18.406c-15.286 0-30.496 0.774-45.594 2.298-112.397 11.35-218.514 64.397-302.132 150.954-2.078 2.15-4.142 4.32-6.191 6.512-7.238 7.741-14.299 15.738-21.173 23.984-2.611 3.133-5.195 6.301-7.751 9.504l-0.376 0.474c-9.438 11.834-28.508 5.158-28.508-9.978v-75.606c0-230.707 163.46-417.728 365.102-417.728h65.030v-186.56c0-14.749 18.262-21.643 28.010-10.573l300.547 341.354z"],"width":1056,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-forward"],"defaultCode":59841,"grid":0},"attrs":[{}],"properties":{"order":938,"id":26,"name":"arrow-forward","prevSize":32,"code":59841},"setIdx":0,"setId":6,"iconIdx":27},{"icon":{"paths":["M576 352c-17.674 0-32-14.326-32-32s14.326-32 32-32h224c17.674 0 32 14.327 32 32v208c0 17.674-14.326 32-32 32s-32-14.326-32-32v-130.746l-233.373 233.373c-12.496 12.496-32.758 12.496-45.254 0l-73.373-73.373-169.372 169.373c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l192-192c12.496-12.496 32.758-12.496 45.254 0l73.373 73.373 210.746-210.746h-146.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-increase"],"defaultCode":59675,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":939,"name":"arrow-increase","prevSize":32,"id":27,"code":59675},"setIdx":0,"setId":6,"iconIdx":28},{"icon":{"paths":["M297.766 105.372c12.513-12.497 32.801-12.497 45.316 0 12.512 12.497 12.512 32.758 0 45.255l-105.513 105.372h611.551c17.699 0 32.045 14.327 32.045 32v112c0 17.674-14.346 32-32.045 32-17.696 0-32.042-14.326-32.042-32v-80h-579.51l105.513 105.373c12.512 12.496 12.512 32.758 0 45.254-12.515 12.496-32.803 12.496-45.316 0l-160.212-160c-12.513-12.497-12.513-32.758 0-45.255l160.212-160zM711.568 918.627c-12.515 12.496-32.803 12.496-45.315 0-12.515-12.496-12.515-32.758 0-45.254l105.51-105.373h-611.552c-17.696 0-32.042-14.326-32.042-32v-112c0-17.674 14.346-32 32.042-32s32.042 14.326 32.042 32v80h579.509l-105.51-105.373c-12.515-12.496-12.515-32.758 0-45.254 12.512-12.496 32.8-12.496 45.315 0l160.211 160c12.512 12.496 12.512 32.758 0 45.254l-160.211 160z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-looping"],"defaultCode":59677,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":940,"name":"arrow-looping","prevSize":32,"id":28,"code":59677},"setIdx":0,"setId":6,"iconIdx":29},{"icon":{"paths":["M374.627 769.296c-12.496 12.496-32.758 12.496-45.254 0l-192-192c-12.497-12.496-12.497-32.758 0-45.254l192-192c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-137.372 137.373h578.745v-192h-192c-17.674 0-32-14.328-32-32.001s14.326-32 32-32h224c17.674 0 32 14.327 32 32v256.001c0 17.674-14.326 32-32 32h-610.745l137.372 137.373c12.496 12.496 12.496 32.758 0 45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-return"],"defaultCode":59678,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":941,"name":"arrow-return","prevSize":32,"id":29,"code":59678},"setIdx":0,"setId":6,"iconIdx":30},{"icon":{"paths":["M526.064 297.121c12.637-12.356 32.896-12.129 45.254 0.507l187.715 191.969c12.163 12.438 12.163 32.31 0 44.746l-187.715 191.971c-12.358 12.634-32.618 12.861-45.254 0.506-12.634-12.355-12.861-32.614-0.506-45.251l134.55-137.597h-372.109c-17.673 0-32-14.33-32-32 0-17.674 14.327-32 32-32h372.109l-134.55-137.6c-12.355-12.634-12.128-32.894 0.506-45.251z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-right"],"defaultCode":59838,"grid":0},"attrs":[{}],"properties":{"order":942,"id":30,"name":"arrow-right","prevSize":32,"code":59838},"setIdx":0,"setId":6,"iconIdx":31},{"icon":{"paths":["M297.181 498.090c-12.356-12.634-12.129-32.896 0.507-45.251l191.97-187.717c12.435-12.161 32.307-12.161 44.746 0l191.968 187.717c12.637 12.355 12.864 32.618 0.509 45.251-12.355 12.637-32.618 12.864-45.251 0.509l-137.6-134.55v372.109c0 17.674-14.326 32-32 32-17.67 0-32-14.326-32-32v-372.109l-137.597 134.55c-12.637 12.355-32.895 12.128-45.251-0.509z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-up"],"defaultCode":59680,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":943,"name":"arrow-up","prevSize":32,"id":31,"code":59680},"setIdx":0,"setId":6,"iconIdx":32},{"icon":{"paths":["M694.627 473.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-105.373-105.373v418.746c0 17.674-14.326 32-32 32s-32-14.326-32-32v-418.746l-105.373 105.373c-12.496 12.496-32.758 12.496-45.254 0s-12.497-32.758 0-45.254l160-160c12.496-12.497 32.758-12.497 45.254 0l160 160zM912 160c0-17.673-14.326-32-32-32h-768c-17.673 0-32 14.327-32 32v512c0 17.674 14.327 32 32 32h96c17.673 0 32-14.326 32-32s-14.327-32-32-32h-64v-448h704v448h-64c-17.674 0-32 14.326-32 32s14.326 32 32 32h96c17.674 0 32-14.326 32-32v-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-up-box"],"defaultCode":59679,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":944,"name":"arrow-up-box","prevSize":32,"id":32,"code":59679},"setIdx":0,"setId":6,"iconIdx":33},{"icon":{"paths":["M649.427 192c-26.454 0-52.016 10.804-71.005 30.343l-305.1 313.906c-31.48 32.387-49.322 76.506-49.322 122.694 0 46.186 17.842 90.304 49.322 122.694 31.451 32.355 73.91 50.362 117.984 50.362s86.531-18.006 117.981-50.362l305.101-313.907c12.317-12.672 32.576-12.96 45.248-0.643 12.675 12.317 12.963 32.576 0.646 45.251l-305.101 313.904c-43.302 44.554-102.23 69.757-163.875 69.757s-120.574-25.203-163.877-69.757c-43.273-44.522-67.428-104.717-67.428-167.299s24.155-122.781 67.428-167.302l305.1-313.905c30.845-31.735 72.874-49.737 116.899-49.737s86.054 18.002 116.899 49.737c30.816 31.704 47.971 74.514 47.971 118.968s-17.155 87.263-47.971 118.969l-305.43 313.904c-0.003 0.006 0.003-0.003 0 0-18.384 18.909-43.523 29.718-69.923 29.718-26.406 0-51.539-10.8-69.923-29.718-18.356-18.883-28.512-44.31-28.512-70.634 0-26.326 10.156-51.754 28.512-70.637l281.872-289.668c12.326-12.666 32.586-12.942 45.251-0.617s12.941 32.585 0.618 45.251l-281.846 289.638c-6.557 6.752-10.406 16.106-10.406 26.032 0 9.93 3.843 19.277 10.406 26.029 6.531 6.72 15.194 10.323 24.029 10.323s17.498-3.603 24.029-10.323l305.43-313.907c19.024-19.568 29.866-46.301 29.866-74.361 0-28.059-10.842-54.791-29.866-74.362-18.989-19.54-44.55-30.343-71.005-30.343z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["attach"],"defaultCode":59676,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":945,"name":"attach","prevSize":32,"id":33,"code":59676},"setIdx":0,"setId":6,"iconIdx":34},{"icon":{"paths":["M300.1 631.12h-113.433v-280.89h113.433l12.366-48.048c11.054-42.953 50.123-74.619 96.423-74.619h58.666v526.223h-58.666c-46.301 0-85.37-31.667-96.423-74.621l-12.366-48.045zM163.556 695.12h86.931c18.156 70.541 82.192 122.666 158.403 122.666h81.776c22.582 0 40.89-18.307 40.89-40.89v-572.444c0-22.582-18.307-40.889-40.89-40.889h-81.776c-76.211 0-140.247 52.124-158.403 122.667h-86.931c-22.582 0-40.889 18.306-40.889 40.89v327.11c0 22.582 18.307 40.89 40.889 40.89zM646.461 316.515c17.146-4.286 34.518 6.138 38.806 23.284l11.136 44.55c20.81 83.229 20.81 170.301 0 253.533l-11.136 44.55c-4.288 17.146-21.661 27.568-38.806 23.283-17.146-4.288-27.571-21.661-23.283-38.806l11.136-44.55c18.262-73.040 18.262-149.45 0.003-222.486l-11.139-44.55c-4.288-17.146 6.138-34.522 23.283-38.807zM807.472 235.936c-5.197-16.892-23.104-26.372-39.994-21.174-16.893 5.197-26.371 23.104-21.174 39.996l35.536 115.489c28.112 91.37 26.976 189.242-3.254 279.933l-32.054 96.16c-5.59 16.765 3.472 34.886 20.237 40.477 16.768 5.587 34.89-3.472 40.48-20.24l32.051-96.16c34.448-103.344 35.747-214.87 3.709-318.989l-35.536-115.491z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio"],"defaultCode":59683,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":946,"name":"audio","prevSize":32,"id":34,"code":59683},"setIdx":0,"setId":6,"iconIdx":35},{"icon":{"paths":["M866.128 153.127c-12.496-12.497-32.758-12.497-45.254 0l-668.246 668.245c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l668.246-668.245c12.496-12.497 12.496-32.758 0-45.255zM674.643 480.358l55.92-55.923c16.259 79.565 14.515 161.866-5.229 240.842l-11.622 46.49c-4.288 17.146-21.661 27.571-38.806 23.283-17.146-4.285-27.568-21.661-23.283-38.806l11.622-46.486c13.875-55.507 17.677-112.874 11.398-169.398zM817.162 385.923l-11.312-36.771 51.203-51.206 21.28 69.155c33.344 108.368 31.994 224.445-3.859 332.010l-33.45 100.342c-5.587 16.765-23.709 25.827-40.477 20.24-16.765-5.59-25.827-23.712-20.237-40.48l33.446-100.339c31.635-94.912 32.826-197.334 3.405-292.95zM490.666 664.333l64-64v210.346c0 23.562-19.101 42.666-42.666 42.666h-85.334c-35.459 0-68.394-10.816-95.683-29.325l46.611-46.611c14.701 7.629 31.395 11.936 49.072 11.936h64v-125.011zM128 682.678c0 19.738 13.403 36.346 31.604 41.216l62.552-62.55h-30.156v-298.666h118.99l12.367-48.049c11.843-46.020 53.696-79.953 103.309-79.953h64v158.155l64-64v-115.488c0-23.564-19.101-42.667-42.666-42.667h-85.334c-79.523 0-146.343 54.39-165.289 128h-90.71c-23.564 0-42.667 19.102-42.667 42.667v341.334z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio-disabled"],"defaultCode":59681,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":947,"name":"audio-disabled","prevSize":32,"id":35,"code":59681},"setIdx":0,"setId":6,"iconIdx":36},{"icon":{"paths":["M310.99 661.344h-118.99v-298.666h118.99l12.367-48.049c11.843-46.020 53.696-79.953 103.309-79.953h64v554.667h-64c-49.613 0-91.466-33.933-103.309-79.952l-12.367-48.048zM170.667 725.344h90.71c18.946 73.61 85.766 128 165.289 128h85.334c23.565 0 42.666-19.104 42.666-42.666v-597.335c0-23.564-19.101-42.667-42.666-42.667h-85.334c-79.523 0-146.343 54.39-165.289 128h-90.71c-23.564 0-42.667 19.102-42.667 42.667v341.334c0 23.562 19.103 42.666 42.667 42.666zM886.627 393.373c12.496 12.496 12.496 32.758 0 45.254l-73.373 73.373 73.373 73.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-73.373-73.373-73.373 73.373c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l73.373-73.373-73.373-73.373c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l73.373 73.373 73.373-73.373c12.496-12.496 32.758-12.496 45.254 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio-unavailable"],"defaultCode":59682,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":948,"name":"audio-unavailable","prevSize":32,"id":36,"code":59682},"setIdx":0,"setId":6,"iconIdx":37},{"icon":{"paths":["M418.704 128c-35.344 0-64 28.654-64 64v226.637c20.774-2.822 42.134-3.456 64-1.526v-225.11h176v180.707c0 35.344 28.656 64 64 64h176v331.293h-120.554c-17.155 22.179-36.323 43.869-57.312 64h177.866c35.347 0 64-28.653 64-64v-363.293c0-6.413-1.923-12.675-5.526-17.978l-156.63-230.681c-11.914-17.544-31.741-28.049-52.947-28.049h-264.896zM658.704 372.707v-180.707h24.896l122.698 180.707h-147.594zM167.939 668.547c120.524 156.138 218.24 174.586 285.133 158.739 73.293-17.36 139.232-81.648 183.466-151.763-115.155-155.869-211.581-174.589-279.149-158.915-74.362 17.251-142.707 81.683-189.45 151.939zM104.428 649.037c100.621-162.8 337.62-357.19 593.252 1.789 9.072 12.739 10.32 29.818 2.422 43.315-95.27 162.854-326.394 358.346-593.234-0.224-9.745-13.094-11.022-30.995-2.44-44.88zM401.664 735.994c31.514 0 60.269-26.858 60.269-64 0-37.146-28.755-64-60.269-64-31.51 0-60.266 26.854-60.266 64 0 37.142 28.755 64 60.266 64zM401.664 799.994c68.634 0 124.269-57.309 124.269-128 0-70.694-55.635-128-124.269-128-68.63 0-124.267 57.306-124.267 128 0 70.691 55.636 128 124.267 128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["auditing"],"defaultCode":59684,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":949,"name":"auditing","prevSize":32,"id":37,"code":59684},"setIdx":0,"setId":6,"iconIdx":38},{"icon":{"paths":["M224 224c-17.673 0-32 14.327-32 32v544c0 17.674 14.327 32 32 32h544c17.674 0 32-14.326 32-32v-544c0-17.673-14.326-32-32-32h-544zM128 256c0-53.019 42.981-96 96-96h544c53.021 0 96 42.981 96 96v544c0 53.021-42.979 96-96 96h-544c-53.019 0-96-42.979-96-96v-544zM608 460.813c0 41.798-26.714 77.357-64 90.538v133.462h-64v-133.462c-37.286-13.181-64-48.739-64-90.538 0-53.021 42.979-96 96-96s96 42.979 96 96zM608 588.826c38.861-29.19 64-75.667 64-128.013 0-88.365-71.635-160-160-160s-160 71.636-160 160c0 52.346 25.139 98.822 64 128.013v127.987c0 17.674 14.326 32 32 32h128c17.674 0 32-14.326 32-32v-127.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["auth"],"defaultCode":59685,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":950,"name":"auth","prevSize":32,"id":38,"code":59685},"setIdx":0,"setId":6,"iconIdx":39},{"icon":{"paths":["M513.35 554.019c66.467 0 120.349-52.493 120.349-117.242 0-64.752-53.882-117.243-120.349-117.243-66.464 0-120.346 52.491-120.346 117.243 0 64.749 53.882 117.242 120.346 117.242zM513.35 490.019c-32.704 0-56.346-25.405-56.346-53.242 0-27.84 23.642-53.242 56.346-53.242 32.707 0 56.349 25.402 56.349 53.242 0 27.837-23.642 53.242-56.349 53.242z","M365.478 894.144h-172.126c-17.673 0-32-14.33-32-32v-702.144c0-17.673 14.327-32 32-32h640.001c17.674 0 32 14.327 32 32v702.144c0 17.67-14.326 32-32 32h-172.128c-6.24 1.274-12.701 1.942-19.318 1.942h-257.11c-6.618 0-13.078-0.669-19.318-1.942zM225.353 830.144h68.244c-3.114-9.456-4.799-19.558-4.799-30.058v-93.446c0-56.109 37.881-105.142 92.172-119.309 19.171-5.002 39.264-5.312 58.579-0.902l42.778 9.766c20.051 4.579 40.909 4.259 60.81-0.934l28.070-7.325c20.694-5.398 42.384-5.734 63.232-0.973 60.534 13.821 103.469 67.664 103.469 129.754v83.37c0 10.499-1.686 20.602-4.8 30.058h68.246v-638.144h-576.001v638.144zM652.918 830.144c12.246-4.49 20.989-16.253 20.989-30.058v-83.37c0-32.234-22.288-60.186-53.715-67.36-10.822-2.47-22.083-2.298-32.826 0.506l-28.070 7.325c-29.853 7.789-61.139 8.272-91.216 1.405l-42.774-9.766c-9.293-2.122-18.957-1.974-28.176 0.432-26.112 6.813-44.333 30.397-44.333 57.382v93.446c0 13.805 8.742 25.568 20.989 30.058h279.133z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["avatar"],"defaultCode":59686,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":951,"name":"avatar","prevSize":32,"id":39,"code":59686},"setIdx":0,"setId":6,"iconIdx":40},{"icon":{"paths":["M737.779 361.376c12.499 12.496 12.499 32.758 0 45.254l-110.947 110.95 110.947 110.947c12.499 12.496 12.499 32.758 0 45.254-12.496 12.499-32.758 12.499-45.254 0l-110.947-110.947-110.95 110.947c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.758 0-45.254l110.95-110.947-110.95-110.95c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l110.95 110.95 110.947-110.95c12.496-12.496 32.758-12.496 45.254 0z","M312.246 218.073c12.061-16.393 31.2-26.073 51.552-26.073h468.202c35.347 0 64 28.654 64 64v512c0 35.347-28.653 64-64 64h-468.202c-20.352 0-39.491-9.68-51.552-26.074l-188.343-256c-16.598-22.56-16.598-53.293 0-75.853l188.343-256.001zM363.798 256l-188.343 256 188.343 256h468.202v-512h-468.202z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["backspace"],"defaultCode":59687,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":952,"name":"backspace","prevSize":32,"id":40,"code":59687},"setIdx":0,"setId":6,"iconIdx":41},{"icon":{"paths":["M896 512c0-212.077-171.923-384-384-384s-384 171.923-384 384c0 212.077 171.923 384 384 384s384-171.923 384-384zM480 544v286.419c-56.483-5.606-108.646-25.904-152.618-57.011 46.403-78.992 67.251-156.97 71.734-229.408h80.883zM334.8 544c-4.282 58.995-21.005 122.198-56.631 186.458-46.616-49.875-77.462-114.678-84.589-186.458h141.22zM398.954 480c-6.192-93.13-37.366-173.574-70.627-230.072 43.773-30.733 95.594-50.78 151.674-56.348v286.42h-81.046zM279.095 292.556c26.251 47.457 50.118 112.532 55.644 187.444h-141.159c7.174-72.253 38.381-137.437 85.515-187.444zM544 544h80.883c4.483 72.438 25.331 150.416 71.734 229.408-43.971 31.107-96.134 51.405-152.618 57.011v-286.419zM830.419 544c-7.126 71.779-37.971 136.582-84.589 186.458-35.626-64.259-52.349-127.462-56.63-186.458h141.219zM830.419 480h-141.158c5.526-74.912 29.395-139.987 55.645-187.444 47.133 50.008 78.339 115.192 85.514 187.444zM544 193.58c56.080 5.568 107.901 25.614 151.674 56.348-33.261 56.499-64.435 136.943-70.627 230.072h-81.046v-286.42z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["basketball"],"defaultCode":59776,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":953,"id":41,"name":"basketball","prevSize":32,"code":59776},"setIdx":0,"setId":6,"iconIdx":42},{"icon":{"paths":["M233.358 169.364c6.002-6.001 14.141-9.372 22.629-9.372l304.020 0.020c0 0 0.003 0 0 0 46.678 0 91.446 18.543 124.451 51.549 33.008 33.006 51.549 77.772 51.549 124.452s-18.541 91.443-51.549 124.451c-0.803 0.803-1.616 1.6-2.435 2.387 22.867 9.552 43.888 23.533 61.75 41.395 36.006 36.006 56.234 84.845 56.234 135.766s-20.227 99.757-56.234 135.763c-36.006 36.006-84.845 56.237-135.766 56.237l-352.024-0.019c-17.673-0.003-31.998-14.33-31.998-32v-608.001c0-8.487 3.372-16.627 9.373-22.628zM560.006 448.013c29.706 0 58.192-11.802 79.197-32.806 21.005-21.002 32.803-49.491 32.803-79.194 0-29.705-11.798-58.193-32.803-79.197s-49.491-32.804-79.197-32.804l-272.022-0.018v224.019h272.022zM287.984 512.013v255.981l320.022 0.019c0 0 0.003 0 0 0 33.949 0 66.506-13.488 90.512-37.491 24.003-24.006 37.488-56.563 37.488-90.509 0-33.949-13.485-66.506-37.488-90.512-24.006-24.003-56.563-37.488-90.512-37.488h-320.022z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["bold"],"defaultCode":59688,"grid":0},"attrs":[{}],"properties":{"order":954,"name":"bold","prevSize":32,"id":42,"code":59688},"setIdx":0,"setId":6,"iconIdx":43},{"icon":{"paths":["M352 445.437c0-17.67 14.326-32 32-32h256c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M352 322.557c0-17.672 14.326-31.999 32-31.999h256c17.674 0 32 14.327 32 31.999 0 17.674-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M864 679.68c0 17.674-14.326 32-32 32h-18.509c-8.218 40.547-8.218 82.333 0 122.88h19.789c16.966 0 30.72 13.754 30.72 30.72s-13.754 30.72-30.72 30.72h-545.28c-70.692 0-128-55.014-128-122.88v-453.12c0-106.038 85.961-192 192-192h480c17.674 0 32 14.327 32 32v519.68zM748.419 834.56c-6.787-40.678-6.787-82.202 0-122.88h-460.419c-35.346 0-64 27.507-64 61.44s28.654 61.44 64 61.44h460.419zM224 647.68h576v-455.68h-448c-70.692 0-128 57.308-128 128v327.68z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["book"],"defaultCode":59689,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":955,"name":"book","prevSize":32,"id":43,"code":59689},"setIdx":0,"setId":6,"iconIdx":44},{"icon":{"paths":["M193.603 416h-33.603c-17.673 0-32 14.326-32 32s14.327 32 32 32h704c17.674 0 32-14.326 32-32s-14.326-32-32-32h-33.603c-7.347-73.117-39.702-141.853-92.122-194.274-60.013-60.012-141.405-93.726-226.275-93.726s-166.262 33.714-226.274 93.726c-52.421 52.421-84.777 121.157-92.123 194.274zM330.979 266.981c48.010-48.010 113.126-74.981 181.021-74.981s133.011 26.971 181.021 74.981c40.403 40.404 65.907 92.923 72.973 149.019h-507.987c7.066-56.096 32.57-108.615 72.972-149.019z","M877.242 605.133c16.090-7.315 23.203-26.285 15.891-42.374-7.315-16.090-26.285-23.203-42.374-15.891l-127.558 57.981-127.558-57.981c-8.413-3.824-18.070-3.824-26.483 0l-127.558 57.981-127.558-57.981c-8.413-3.824-18.070-3.824-26.483 0l-140.8 64c-16.089 7.315-23.203 26.285-15.89 42.374s26.284 23.203 42.373 15.891l18.758-8.528v29.68c0 38.102 15.908 74.31 43.672 100.752 27.712 26.394 64.978 40.963 103.528 40.963h345.6c38.55 0 75.814-14.57 103.526-40.963 27.766-26.442 43.674-62.65 43.674-100.752v-64.589l45.242-20.563zM736.442 669.133l31.558-14.346v35.498c0 20.093-8.368 39.699-23.811 54.41-15.494 14.758-36.832 23.306-59.389 23.306h-345.6c-22.556 0-43.893-8.547-59.39-23.306-15.444-14.71-23.81-34.317-23.81-54.41v-58.771l44.8-20.362 127.558 57.981c8.413 3.824 18.070 3.824 26.483 0l127.558-57.981 127.558 57.981c8.413 3.824 18.070 3.824 26.483 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["burger"],"defaultCode":59813,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":956,"id":44,"name":"burger","prevSize":32,"code":59813},"setIdx":0,"setId":6,"iconIdx":45},{"icon":{"paths":["M224 224h320v576h-96v-112c0-8.835-7.165-16-16-16h-96c-8.835 0-16 7.165-16 16v112h-96v-576zM608 448h192v352h-192v-352zM832 384h-224v-192c0-17.673-14.326-32-32-32h-384c-17.673 0-32 14.327-32 32v640c0 17.674 14.327 32 32 32h640c17.674 0 32-14.326 32-32v-416c0-17.674-14.326-32-32-32zM304 288c-8.836 0-16 7.164-16 16v32c0 8.835 7.164 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.836-7.165-16-16-16h-32zM288 432c0-8.835 7.164-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.836 0-16-7.165-16-16v-32zM304 544c-8.836 0-16 7.165-16 16v32c0 8.835 7.164 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM416 304c0-8.836 7.165-16 16-16h32c8.835 0 16 7.164 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32zM432 416c-8.835 0-16 7.165-16 16v32c0 8.835 7.165 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM416 560c0-8.835 7.165-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32zM688 512c-8.835 0-16 7.165-16 16v32c0 8.835 7.165 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM672 656c0-8.835 7.165-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["business"],"defaultCode":59690,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":957,"name":"business","prevSize":32,"id":45,"code":59690},"setIdx":0,"setId":6,"iconIdx":46},{"icon":{"paths":["M277.831 157.44c0-16.259 13.181-29.44 29.44-29.44s29.439 13.181 29.439 29.44v58.876h353.28v-58.876c0-16.259 13.181-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.876h85.76c17.674 0 32 14.327 32 32v583.68c0 17.674-14.326 32-32 32h-642.559c-17.673 0-32-14.326-32-32v-583.68c0-1.105 0.056-2.196 0.165-3.272 1.639-16.136 15.266-28.728 31.835-28.728h85.76v-58.876zM802.63 392.957h-578.559v407.040h578.559v-407.040zM425.034 644.474c0-8.835 7.162-16 16-16h26.88c8.835 0 16 7.165 16 16v26.88c0 8.838-7.165 16-16 16h-26.88c-8.838 0-16-7.162-16-16v-26.88zM323.27 510.72c-8.836 0-15.999 7.162-15.999 16v26.88c0 8.835 7.163 16 15.999 16h26.88c8.838 0 16-7.165 16-16v-26.88c0-8.838-7.162-16-16-16h-26.88zM542.79 526.72c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.835-7.162 16-16 16h-26.88c-8.835 0-16-7.165-16-16v-26.88zM323.27 628.474c-8.835 0-15.999 7.165-15.999 16v26.88c0 8.838 7.164 16 15.999 16h26.88c8.838 0 16-7.162 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88zM542.79 644.474c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.838-7.162 16-16 16h-26.88c-8.835 0-16-7.162-16-16v-26.88zM441.030 510.72c-8.835 0-16 7.165-16 16v26.88c0 8.835 7.165 16 16 16h26.88c8.838 0 16-7.165 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88zM660.55 526.72c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.835-7.162 16-16 16h-26.88c-8.835 0-16-7.165-16-16v-26.88zM676.55 628.474c-8.835 0-16 7.165-16 16v26.88c0 8.838 7.165 16 16 16h26.88c8.838 0 16-7.162 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["calendar"],"defaultCode":59691,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":958,"name":"calendar","prevSize":32,"id":46,"code":59691},"setIdx":0,"setId":6,"iconIdx":47},{"icon":{"paths":["M256 202.672c0-17.673 19.102-32 42.667-32h255.999c23.565 0 42.669 14.327 42.669 32s-19.104 32-42.669 32h-255.999c-23.564 0-42.667-14.327-42.667-32zM160 383.994c0-5.891 4.776-10.666 10.667-10.666h511.999c5.891 0 10.669 4.774 10.669 10.666v85.334c0 11.376 6.038 21.894 15.859 27.632s21.949 5.83 31.856 0.243l97.83-55.165c2.531-1.427 4.858-3.19 6.912-5.248 6.72-6.717 18.208-1.958 18.208 7.546v263.318c0 9.504-11.488 14.262-18.208 7.542-2.054-2.054-4.381-3.818-6.912-5.245l-97.83-55.165c-9.907-5.587-22.035-5.494-31.856 0.243s-15.859 16.256-15.859 27.632v85.331c0 5.891-4.778 10.669-10.669 10.669h-511.999c-5.891 0-10.667-4.778-10.667-10.669v-384zM170.667 309.328c-41.237 0-74.667 33.43-74.667 74.666v384c0 41.238 33.429 74.669 74.667 74.669h511.999c41.238 0 74.669-33.43 74.669-74.669v-30.55l46.778 26.374c47.418 41.99 123.888 8.701 123.888-56.163v-263.318c0-64.864-76.47-98.157-123.888-56.166l-46.778 26.378v-30.554c0-41.235-33.43-74.666-74.669-74.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["camera"],"defaultCode":59696,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":959,"name":"camera","prevSize":32,"id":47,"code":59696},"setIdx":0,"setId":6,"iconIdx":48},{"icon":{"paths":["M866.128 153.126c-12.496-12.497-32.758-12.497-45.254 0l-668.246 668.246c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l668.246-668.246c12.496-12.497 12.496-32.758 0-45.255zM298.667 170.671c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h255.999c23.565 0 42.669-14.327 42.669-32s-19.104-32-42.669-32h-255.999zM574.173 309.327h-403.506c-41.237 0-74.667 33.428-74.667 74.667v384c0 6.010 0.71 11.856 2.051 17.453l61.949-61.949v-339.504c0-5.891 4.776-10.666 10.667-10.666h339.506l64-64.001zM376.339 778.659h306.326c5.891 0 10.669-4.774 10.669-10.666v-85.334c0-11.373 6.038-21.891 15.859-27.629s21.949-5.83 31.856-0.243l97.83 55.162c2.531 1.427 4.858 3.194 6.912 5.248 6.72 6.72 18.208 1.962 18.208-7.542v-263.322c0-9.501-11.488-14.262-18.208-7.542-2.054 2.054-4.381 3.821-6.912 5.248l-97.83 55.162c-9.907 5.587-22.035 5.494-31.856-0.243-9.821-5.734-15.859-16.256-15.859-27.629v-7.661l110.778-73.498c47.418-41.99 123.888-8.701 123.888 56.163v263.322c0 64.864-76.47 98.154-123.888 56.163l-46.778-26.378v30.554c0 41.238-33.43 74.666-74.669 74.666h-370.327l64.001-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["camera-disabled"],"defaultCode":59692,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":960,"name":"camera-disabled","prevSize":32,"id":48,"code":59692},"setIdx":0,"setId":6,"iconIdx":49},{"icon":{"paths":["M288 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h256c17.674 0 32-14.327 32-32s-14.326-32-32-32h-256z","M170.667 341.328c-23.564 0-42.667 19.104-42.667 42.666v384c0 23.565 19.102 42.669 42.667 42.669h511.999c23.565 0 42.669-19.104 42.669-42.669v-128l97.83 97.83c26.877 26.88 72.835 7.843 72.835-30.17v-263.318c0-38.013-45.958-57.050-72.835-30.173l-97.83 97.83v-128c0-23.562-19.104-42.666-42.669-42.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["camera-filled"],"defaultCode":59693,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":961,"name":"camera-filled","prevSize":32,"id":49,"code":59693},"setIdx":0,"setId":6,"iconIdx":50},{"icon":{"paths":["M196.731 191.997c0-15.807 12.814-28.622 28.622-28.622h128.001c15.805 0 28.621 12.814 28.621 28.622s-12.816 28.621-28.621 28.621h-128.001c-15.807 0-28.622-12.814-28.622-28.621z","M737.354 559.997c0 97.203-78.8 176-176 176-97.203 0-176-78.797-176-176s78.797-176 176-176c97.2 0 176 78.797 176 176zM673.354 559.997c0-61.856-50.144-112-112-112s-112 50.144-112 112c0 61.856 50.144 112 112 112s112-50.144 112-112z","M193.353 255.997c-35.346 0-64 28.654-64 64v448c0 35.347 28.654 64 64 64h640.001c35.344 0 64-28.653 64-64v-448c0-35.346-28.656-64-64-64h-640.001zM833.354 319.997v448h-640.001v-448h640.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["camera-photo"],"defaultCode":59694,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":962,"name":"camera-photo","prevSize":32,"id":50,"code":59694},"setIdx":0,"setId":6,"iconIdx":51},{"icon":{"paths":["M298.667 170.672c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h255.999c23.565 0 42.669-14.327 42.669-32s-19.104-32-42.669-32h-255.999z","M545.712 503.453c11.267-11.267 11.19-29.61-0.17-40.97s-29.706-11.437-40.973-0.17l-71.402 71.402-71.994-71.997c-11.363-11.36-29.706-11.437-40.973-0.17s-11.19 29.61 0.17 40.97l71.997 71.997-71.402 71.402c-11.266 11.267-11.19 29.61 0.17 40.97 11.363 11.36 29.706 11.437 40.973 0.17l71.402-71.402 71.997 71.997c11.36 11.36 29.702 11.437 40.97 0.17s11.19-29.61-0.17-40.97l-71.997-71.997 71.402-71.402z","M96 383.994c0-41.235 33.429-74.666 74.667-74.666h511.999c41.238 0 74.669 33.43 74.669 74.666v30.554l46.778-26.378c47.418-41.99 123.888-8.698 123.888 56.166v263.318c0 64.864-76.47 98.154-123.888 56.163l-46.778-26.374v30.55c0 41.238-33.43 74.669-74.669 74.669h-511.999c-41.237 0-74.667-33.43-74.667-74.669v-384zM170.667 373.328c-5.891 0-10.667 4.774-10.667 10.666v384c0 5.891 4.776 10.669 10.667 10.669h511.999c5.891 0 10.669-4.778 10.669-10.669v-85.331c0-11.376 6.038-21.894 15.859-27.632s21.949-5.83 31.856-0.243l97.83 55.165c2.531 1.427 4.858 3.19 6.912 5.245 6.72 6.72 18.208 1.962 18.208-7.542v-263.318c0-9.504-11.488-14.262-18.208-7.546-2.054 2.058-4.381 3.821-6.912 5.248l-97.83 55.165c-9.907 5.587-22.035 5.494-31.856-0.243s-15.859-16.256-15.859-27.632v-85.334c0-5.891-4.778-10.666-10.669-10.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["camera-unavailable"],"defaultCode":59695,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":963,"name":"camera-unavailable","prevSize":32,"id":51,"code":59695},"setIdx":0,"setId":6,"iconIdx":52},{"icon":{"paths":["M224.248 304.026c-49.642 68.947-66.502 152.646-66.502 207.968v1.453l-0.132 1.446c-9.702 106.717 28.59 181.93 90.135 234.006 62.938 53.254 152.152 83.731 244.197 93.958 91.965 10.218 193.27 1.446 273.306-15.482 40.022-8.461 73.616-18.733 97.443-29.075 9.245-4.013 16.438-7.786 21.734-11.126-2.464-1.565-5.446-3.306-9.002-5.197-9.222-4.912-19.779-9.578-30.733-14.368l-1.914-0.835c-9.667-4.221-20.47-8.941-28.656-13.517-14.835-8.298-29.389-17.734-40.006-27.776-5.222-4.941-11.165-11.571-15.146-19.827-4.208-8.742-7.226-21.792-1.306-35.597 31.978-74.621 47.178-115.494 54.538-142.483 6.874-25.2 6.874-37.888 6.874-58.064v-0.182c0-16.035-9.318-89.517-55.811-158.032-45.018-66.338-125.99-129.968-274.854-129.968-134.637 0-215.698 55.382-264.165 122.698zM172.309 266.63c60.333-83.796 160.606-149.302 316.103-149.302 171.136 0 271.494 75.037 327.811 158.032 54.842 80.819 66.854 167.338 66.854 193.968 0 22.384-0.022 41.696-9.126 75.088-8.131 29.805-23.485 70.928-51.946 137.923 5.261 4.166 13.072 9.306 23.36 15.062 5.315 2.97 13.485 6.55 24.963 11.568 10.653 4.659 23.437 10.266 35.174 16.515 11.258 5.994 24.416 14.029 34.202 24.538 10.234 10.992 20.973 29.846 13.299 52.864-5.056 15.168-16.794 25.939-26.576 33.094-10.63 7.776-23.818 14.762-38.253 21.030-29.008 12.589-67.030 23.962-109.683 32.982-85.309 18.038-193.581 27.587-293.616 16.474-99.955-11.107-202.74-44.634-278.468-108.71-76.833-65.011-123.811-159.994-112.66-287.222 0.286-65.549 19.841-162.349 78.561-243.904zM493.744 320c17.674 0 32 14.326 32 32v224c0 17.674-14.326 32-32 32s-32-14.326-32-32v-224c0-17.674 14.326-32 32-32zM525.744 672c0-17.674-14.326-32-32-32s-32 14.326-32 32c0 17.674 14.326 32 32 32s32-14.326 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["canned-response"],"defaultCode":59697,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":964,"name":"canned-response","prevSize":32,"id":52,"code":59697},"setIdx":0,"setId":6,"iconIdx":53},{"icon":{"paths":["M193.352 181.331c-53.020 0-96 42.981-96 96v469.335c0 53.018 42.98 96 96 96h639.999c53.021 0 96-42.982 96-96v-469.335c0-53.019-42.979-96-96-96h-639.999zM161.352 277.331c0-17.673 14.327-32 32-32h639.999c17.674 0 32 14.327 32 32v202.673h-703.999v-202.673zM161.352 544.003h703.999v202.662c0 17.67-14.326 32-32 32h-639.999c-17.673 0-32-14.33-32-32v-202.662zM812.016 661.331c0-35.347-28.653-64-64-64-35.344 0-64 28.653-64 64s28.656 64 64 64c35.347 0 64-28.653 64-64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["card"],"defaultCode":59698,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":965,"name":"card","prevSize":32,"id":53,"code":59698},"setIdx":0,"setId":6,"iconIdx":54},{"icon":{"paths":["M368 182.4c0-17.673-14.326-32-32-32s-32 14.327-32 32v144h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v288h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v144c0 17.674 14.327 32 32 32s32-14.326 32-32v-144h288v144c0 17.674 14.326 32 32 32s32-14.326 32-32v-144h144c17.674 0 32-14.326 32-32s-14.326-32-32-32h-144v-80h-64v80h-288v-288h80v-64h-80v-144z","M640.515 327.283c-15.328-3.59-31.306-3.338-46.512 0.733-41.763 11.187-70.803 49.030-70.803 92.269v35.539c0 36.003 29.187 65.194 65.194 65.194h210.413c36.006 0 65.194-29.19 65.194-65.194v-28.336c0-47.667-33.040-88.957-79.27-99.792-16.413-3.846-33.613-3.603-49.946 0.771l-25.827 6.918c-10.381 2.781-21.286 2.95-31.747 0.499l-36.694-8.602z","M782.637 217.037c0 49.174-39.862 89.037-89.037 89.037s-89.037-39.863-89.037-89.037c0-49.174 39.862-89.037 89.037-89.037s89.037 39.863 89.037 89.037z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["channel-auto-join"],"defaultCode":59746,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":966,"name":"channel-auto-join","prevSize":32,"id":54,"code":59746},"setIdx":0,"setId":6,"iconIdx":55},{"icon":{"paths":["M236.709 162.578c11.779-5.037 25.426-2.564 34.688 6.286l150.709 144c6.32 6.037 9.894 14.396 9.894 23.136s-3.574 17.101-9.894 23.136l-150.709 144c-9.262 8.851-22.909 11.325-34.688 6.288s-19.419-16.614-19.419-29.424v-112h-73.29c-17.673 0-32-14.326-32-32 0-17.672 14.327-31.999 32-31.999h73.29v-112c0-12.81 7.64-24.386 19.419-29.423zM320 368.179v-0.179h0.189l-0.189 0.179zM320.189 304.001h-0.189v-0.179l0.189 0.179z","M492.899 303.258c8.762-9.388 21.245-15.258 35.101-15.258 26.509 0 48 21.49 48 48s-21.491 48-48 48c-16.582 0-31.203-8.41-39.824-21.197l-43.098 48.483c20.49 22.554 50.051 36.714 82.922 36.714 61.856 0 112-50.144 112-112s-50.144-112-112-112c-25.549 0-49.098 8.554-67.942 22.955l32.842 56.303z","M145.615 483.229l32.174 64.349c-0.861 3.040-1.318 6.23-1.318 9.501v44.688c0 17.674 14.327 32 32 32h79.53v64h-79.53c-53.019 0-96-42.979-96-96v-44.688c0-28.848 12.515-55.488 33.144-73.85z","M625.267 640h-0.797c0.259 0.598 0.525 1.194 0.797 1.786v-1.786z","M424.714 640h-0.797v1.786c0.272-0.592 0.538-1.187 0.797-1.786z","M477.901 494.515c-28.56-10.957-60.291-10.211-88.307 2.067-42.282 18.534-69.594 60.326-69.594 106.49v132.928c0 53.021 42.979 96 96 96h224c53.021 0 96-42.979 96-96v-125.062c0-51.162-31.536-97.034-79.306-115.354-30.352-11.642-64.067-10.851-93.84 2.198l-2.070 0.909c-21.523 9.434-45.901 10.006-67.843 1.59l-15.040-5.766zM415.286 555.2c12.595-5.52 26.858-5.856 39.699-0.931l15.040 5.77c37.664 14.445 79.504 13.462 116.451-2.73l2.070-0.909c14.349-6.288 30.602-6.669 45.229-1.059 23.024 8.829 38.224 30.938 38.224 55.597v125.062c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32v-132.928c0-20.752 12.278-39.539 31.286-47.872z","M864 320c0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96s96-42.979 96-96zM800 320c0 17.674-14.326 32-32 32s-32-14.326-32-32c0-17.673 14.326-32 32-32s32 14.327 32 32z","M840.714 697.766h-72.714v-64h72.714c17.674 0 32-14.326 32-32v-44.688c0-15.050-9.664-28.394-23.958-33.091-7.536-2.474-15.69-2.304-23.114 0.483l-4.554 1.709c-19.77 7.421-40.89 9.978-61.619 7.632-12.438-31.683-37.722-57.549-70.774-70.227-1.754-0.672-3.52-1.302-5.296-1.894 18.058-5.312 37.36-5.040 55.344 0.867l14.182 4.659c14.886 4.893 30.998 4.554 45.667-0.954l4.554-1.709c21.069-7.91 44.205-8.394 65.581-1.37 40.566 13.325 67.987 51.197 67.987 93.894v44.688c0 53.021-42.982 96-96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["channel-move-to-team"],"defaultCode":59747,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":967,"name":"channel-move-to-team","prevSize":32,"id":55,"code":59747},"setIdx":0,"setId":6,"iconIdx":56},{"icon":{"paths":["M368 160c0-17.673-14.326-32-32-32s-32 14.327-32 32v144h-144c-17.673 0-32 14.327-32 32s14.327 32 32 32h144v288h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v144c0 17.674 14.327 32 32 32s32-14.326 32-32v-144h288v144c0 17.674 14.326 32 32 32s32-14.326 32-32v-144h144c17.674 0 32-14.326 32-32s-14.326-32-32-32h-144v-80h-58.666c-1.786 0-3.565-0.042-5.334-0.118v80.118h-288v-288h168.79c-0.522-5.264-0.79-10.602-0.79-16v-48h-168v-144z","M760 96c-57.437 0-104 46.562-104 104v56h-24c-17.674 0-32 14.327-32 32v192c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-192c0-17.673-14.326-32-32-32h-24v-56c0-57.438-46.563-104-104-104zM800 255.238h-80v-55.238c0-22.092 17.907-40 40-40s40 17.908 40 40v55.238z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["channel-private"],"defaultCode":59699,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":968,"name":"channel-private","prevSize":32,"id":56,"code":59699},"setIdx":0,"setId":6,"iconIdx":57},{"icon":{"paths":["M336 128c17.674 0 32 14.327 32 32v144h288v-144c0-17.673 14.326-32 32-32s32 14.327 32 32v144h144c17.674 0 32 14.327 32 32s-14.326 32-32 32h-144v288h144c17.674 0 32 14.326 32 32s-14.326 32-32 32h-144v144c0 17.674-14.326 32-32 32s-32-14.326-32-32v-144h-288v144c0 17.674-14.326 32-32 32s-32-14.326-32-32v-144h-144c-17.673 0-32-14.326-32-32s14.327-32 32-32h144v-288h-144c-17.673 0-32-14.326-32-32s14.327-32 32-32h144v-144c0-17.673 14.327-32 32-32zM368 368v288h288v-288h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["channel-public"],"defaultCode":59700,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":969,"name":"channel-public","prevSize":32,"id":57,"code":59700},"setIdx":0,"setId":6,"iconIdx":58},{"icon":{"paths":["M886.627 105.372c12.496 12.497 12.496 32.758 0 45.255l-89.373 89.372 89.373 89.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-89.373-89.372-89.373 89.372c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l89.373-89.373-89.373-89.372c-12.496-12.497-12.496-32.758 0-45.255s32.758-12.497 45.254 0l89.373 89.373 89.373-89.373c12.496-12.497 32.758-12.497 45.254 0zM226.501 304.042c-49.642 68.947-66.502 152.646-66.502 207.968v1.453l-0.132 1.446c-9.701 106.717 28.59 181.93 90.135 234.006 62.938 53.254 152.151 83.731 244.196 93.958 91.968 10.218 193.27 1.446 273.309-15.482 40.019-8.461 73.613-18.733 97.44-29.075 9.245-4.013 16.438-7.786 21.738-11.126-2.467-1.565-5.446-3.306-9.005-5.2-9.222-4.909-19.776-9.574-30.733-14.365l-1.917-0.838c-9.667-4.221-20.47-8.938-28.653-13.517-14.835-8.294-29.389-17.731-40.003-27.773-5.226-4.941-11.168-11.571-15.146-19.827-4.211-8.742-7.226-21.792-1.309-35.6 42.086-98.205 54.957-137.722 59.219-163.318 2.906-17.434 19.392-29.21 36.822-26.307 17.434 2.906 29.213 19.389 26.307 36.822-5.453 32.749-20.333 76.41-58.006 165.088 5.261 4.166 13.069 9.306 23.357 15.059 5.315 2.973 13.485 6.554 24.963 11.571 10.656 4.656 23.437 10.266 35.174 16.515 11.261 5.994 24.419 14.029 34.202 24.538 10.234 10.992 20.973 29.846 13.299 52.864-5.053 15.168-16.794 25.939-26.576 33.094-10.627 7.776-23.814 14.762-38.253 21.027-29.005 12.592-67.027 23.965-109.68 32.986-85.312 18.038-193.584 27.587-293.616 16.47-99.955-11.104-202.742-44.63-278.471-108.707-76.833-65.014-123.811-159.997-112.66-287.222 0.286-65.549 19.841-162.349 78.561-243.904 60.333-83.796 160.605-149.302 316.103-149.302 17.674 0 32 14.327 32 32s-14.326 32-32 32c-134.637 0-215.697 55.382-264.164 122.698z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chat-close"],"defaultCode":59701,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":970,"name":"chat-close","prevSize":32,"id":58,"code":59701},"setIdx":0,"setId":6,"iconIdx":59},{"icon":{"paths":["M778 93.833c-11.795-13.162-32.026-14.271-45.187-2.477s-14.272 32.025-2.477 45.187l81.222 90.645h-216.358c-17.674 0-32 14.327-32 32s14.326 32 32 32h216.358l-81.222 90.646c-11.795 13.162-10.685 33.392 2.477 45.187 13.162 11.792 33.392 10.685 45.187-2.477l129.030-144.001c10.893-12.154 10.893-30.556 0-42.71l-129.030-144zM159.999 512.010c0-55.322 16.86-139.021 66.502-207.968 48.467-67.316 129.527-122.698 264.164-122.698 17.674 0 32-14.327 32-32s-14.326-32-32-32c-155.498 0-255.77 65.507-316.102 149.302-58.72 81.555-78.275 178.355-78.561 243.904-11.151 127.229 35.827 222.211 112.66 287.222 75.729 64.077 178.516 97.603 278.471 108.707 100.032 11.117 208.304 1.568 293.616-16.47 42.653-9.021 80.675-20.394 109.68-32.982 14.438-6.269 27.626-13.254 38.253-21.030 9.782-7.155 21.523-17.926 26.579-33.094 7.67-23.018-3.069-41.872-13.302-52.864-9.782-10.509-22.941-18.544-34.202-24.538-11.738-6.25-24.518-11.859-35.171-16.515-11.482-5.018-19.651-8.598-24.966-11.571-10.288-5.754-18.096-10.89-23.357-15.059 37.674-88.678 52.554-132.339 58.010-165.088 2.902-17.43-8.877-33.917-26.31-36.822-17.43-2.902-33.917 8.877-36.822 26.307-4.262 25.597-17.133 65.114-59.219 163.318-5.917 13.808-2.902 26.858 1.309 35.6 3.978 8.256 9.92 14.886 15.146 19.827 10.614 10.042 25.171 19.478 40.003 27.776 8.186 4.576 18.989 9.296 28.656 13.517v0l1.914 0.835c10.957 4.79 21.51 9.456 30.733 14.368 3.558 1.891 6.541 3.632 9.005 5.197-5.299 3.341-12.493 7.114-21.738 11.126-23.827 10.342-57.421 20.614-97.44 29.075-80.038 16.928-181.341 25.699-273.309 15.482-92.045-10.227-181.258-40.704-244.196-93.958-61.545-52.077-99.836-127.29-90.135-234.006l0.132-1.446v-1.453z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chat-forward"],"defaultCode":59702,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":971,"name":"chat-forward","prevSize":32,"id":59,"code":59702},"setIdx":0,"setId":6,"iconIdx":60},{"icon":{"paths":["M854.506 233.252c12.563 12.429 12.672 32.691 0.243 45.254l-474.877 480c-6.013 6.077-14.208 9.498-22.755 9.494-8.55-0.003-16.742-3.427-22.752-9.507l-165.126-167.088c-12.423-12.57-12.303-32.832 0.268-45.254s32.831-12.304 45.254 0.269l142.375 144.067 452.115-456.992c12.429-12.564 32.691-12.672 45.254-0.243z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["check"],"defaultCode":59703,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":972,"name":"check","prevSize":32,"id":60,"code":59703},"setIdx":0,"setId":6,"iconIdx":61},{"icon":{"paths":["M204.8 128h614.4c42.416 0 76.8 34.385 76.8 76.8v614.4c0 42.416-34.384 76.8-76.8 76.8h-614.4c-42.415 0-76.8-34.384-76.8-76.8v-614.4c0-42.415 34.385-76.8 76.8-76.8zM769.062 336.88c9.322-9.424 9.238-24.619-0.182-33.941-9.424-9.322-24.621-9.241-33.942 0.182l-339.085 342.745-106.782-108.051c-9.317-9.43-24.513-9.52-33.94-0.202s-9.518 24.512-0.201 33.939l123.842 125.318c4.509 4.56 10.653 7.126 17.066 7.13s12.557-2.563 17.069-7.12l356.157-360z"],"attrs":[{"fill":"rgb(29, 116, 245)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":5}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":4}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":6}]},"tags":["checkbox-checked"],"defaultCode":59654,"grid":0},"attrs":[{"fill":"rgb(29, 116, 245)"}],"properties":{"order":973,"name":"checkbox-checked","prevSize":32,"id":61,"code":59654},"setIdx":0,"setId":6,"iconIdx":62},{"icon":{"paths":["M819.2 204.8v614.4h-614.4v-614.4h614.4zM204.8 128c-42.415 0-76.8 34.385-76.8 76.8v614.4c0 42.416 34.385 76.8 76.8 76.8h614.4c42.416 0 76.8-34.384 76.8-76.8v-614.4c0-42.415-34.384-76.8-76.8-76.8h-614.4z"],"attrs":[{"fill":"rgb(203, 206, 209)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":8}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":8}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":10}]},"tags":["checkbox-unchecked"],"defaultCode":59653,"grid":0},"attrs":[{"fill":"rgb(203, 206, 209)"}],"properties":{"order":974,"name":"checkbox-unchecked","prevSize":32,"id":62,"code":59653},"setIdx":0,"setId":6,"iconIdx":63},{"icon":{"paths":["M281.372 436.042c12.497-12.499 32.758-12.499 45.255 0l185.373 185.373 185.373-185.373c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-208 208c-12.496 12.496-32.758 12.496-45.254 0l-208-208c-12.497-12.496-12.497-32.758 0-45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-down"],"defaultCode":59704,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":975,"name":"chevron-down","prevSize":32,"id":63,"code":59704},"setIdx":0,"setId":6,"iconIdx":64},{"icon":{"paths":["M587.962 281.372c12.496 12.497 12.496 32.758 0 45.255l-185.373 185.373 185.373 185.373c12.496 12.496 12.496 32.758 0 45.254-12.499 12.496-32.758 12.496-45.258 0l-208-208c-12.496-12.496-12.496-32.758 0-45.254l208-208c12.499-12.497 32.758-12.497 45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-left"],"defaultCode":59706,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":976,"name":"chevron-left","prevSize":32,"id":64,"code":59706},"setIdx":0,"setId":6,"iconIdx":65},{"icon":{"paths":["M670.17 183.165c16.662 16.662 16.662 43.677 0 60.34l-268.496 268.495 268.496 268.499c16.662 16.662 16.662 43.677 0 60.339s-43.677 16.662-60.339 0l-298.668-298.669c-8.002-8-12.497-18.851-12.497-30.17 0-11.315 4.495-22.166 12.497-30.17l298.668-298.666c16.662-16.662 43.677-16.662 60.339 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-left-big"],"defaultCode":59705,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":977,"name":"chevron-left-big","prevSize":32,"id":65,"code":59705},"setIdx":0,"setId":6,"iconIdx":66},{"icon":{"paths":["M436.038 742.627c-12.496-12.496-12.496-32.758 0-45.254l185.373-185.373-185.373-185.373c-12.496-12.497-12.496-32.758 0-45.254 12.499-12.497 32.758-12.497 45.254 0l208 208c12.499 12.496 12.499 32.758 0 45.254l-207.997 208c-12.499 12.496-32.758 12.496-45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-right"],"defaultCode":59707,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":978,"name":"chevron-right","prevSize":32,"id":66,"code":59707},"setIdx":0,"setId":6,"iconIdx":67},{"icon":{"paths":["M742.627 587.958c-12.496 12.499-32.758 12.499-45.254 0l-185.373-185.373-185.373 185.373c-12.496 12.499-32.758 12.499-45.254 0-12.497-12.496-12.497-32.758 0-45.254l208-208c12.496-12.496 32.758-12.496 45.254 0l208 208c12.496 12.496 12.496 32.758 0 45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-up"],"defaultCode":59708,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":979,"name":"chevron-up","prevSize":32,"id":67,"code":59708},"setIdx":0,"setId":6,"iconIdx":68},{"icon":{"paths":["M512 864c194.403 0 352-157.597 352-352 0-46.522-9.024-90.931-25.418-131.581l48.518-48.518c26.211 54.496 40.899 115.581 40.899 180.099 0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416 95.376 0 183.254 32.096 253.424 86.076l-45.712 45.712c-58.221-42.623-130.029-67.788-207.712-67.788-194.404 0-352 157.596-352 352s157.596 352 352 352zM902.63 230.623c12.496-12.499 12.493-32.76-0.006-45.255s-32.762-12.491-45.254 0.008l-345.386 345.503-105.341-105.491c-12.486-12.506-32.749-12.522-45.254-0.032-12.506 12.486-12.522 32.749-0.032 45.254l127.971 128.157c6 6.006 14.144 9.386 22.634 9.389 8.493 0 16.637-3.373 22.64-9.376l368.029-368.157z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["circle-check"],"defaultCode":59709,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":980,"name":"circle-check","prevSize":32,"id":68,"code":59709},"setIdx":0,"setId":6,"iconIdx":69},{"icon":{"paths":["M608 192c0-53.019-42.979-96-96-96s-96 42.981-96 96h-192c-17.673 0-32 14.327-32 32v672c0 17.674 14.327 32 32 32h576c17.674 0 32-14.326 32-32v-672c0-17.673-14.326-32-32-32h-192zM256 864v-608h96v64c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-64h96v608h-512zM512 224c17.674 0 32-14.327 32-32s-14.326-32-32-32c-17.674 0-32 14.327-32 32s14.326 32 32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["clipboard"],"defaultCode":59710,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":981,"name":"clipboard","prevSize":32,"id":69,"code":59710},"setIdx":0,"setId":6,"iconIdx":70},{"icon":{"paths":["M864 512c0 194.403-157.597 352-352 352s-352-157.597-352-352c0-194.404 157.596-352 352-352s352 157.596 352 352zM928 512c0-229.75-186.25-416-416-416s-416 186.25-416 416c0 229.75 186.25 416 416 416s416-186.25 416-416zM544 288c0-17.673-14.326-32-32-32s-32 14.327-32 32v224c0 8.486 3.373 16.627 9.373 22.627l96 96c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-86.627-86.627v-210.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["clock"],"defaultCode":59711,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":982,"name":"clock","prevSize":32,"id":70,"code":59711},"setIdx":0,"setId":6,"iconIdx":71},{"icon":{"paths":["M806.627 262.628c12.496-12.497 12.496-32.758 0-45.255s-32.758-12.497-45.254 0l-249.373 249.373-249.372-249.373c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l249.373 249.372-249.373 249.373c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l249.372-249.373 249.373 249.373c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-249.373-249.373 249.373-249.372z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["close"],"defaultCode":59712,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":983,"name":"close","prevSize":32,"id":71,"code":59712},"setIdx":0,"setId":6,"iconIdx":72},{"icon":{"paths":["M273.129 356.678c6.747-28.298 25.696-52.004 51.21-67.152 25.6-15.2 56.323-20.858 84.698-14.53 27.642 6.163 55.117 24.12 74.874 60.339l22.541 41.325 30.134-36.16c27.238-32.689 85.126-39.713 134.714-14.064 23.562 12.186 42.208 30.618 52.064 53.488 9.654 22.406 12.112 51.898-1.434 89.149l-15.616 42.938h45.686c53.606 0 82.419 15.882 97.642 33.75 15.651 18.374 21.898 44.646 18.557 74.714-3.344 30.083-16.054 60.518-33.456 82.89-17.939 23.066-36.646 32.646-50.742 32.646h-543.998c-18.791 0-37.068-10.362-52.195-31.578-15.217-21.344-24.978-51.050-25.818-81.312-0.84-30.227 7.237-57.914 23.733-77.491 15.796-18.746 42.268-33.619 86.279-33.619h59.791l-33.165-49.75c-27.882-41.824-32.118-77.814-25.498-105.581zM518.218 272.084c-26.339-32.073-59.667-51.619-95.251-59.554-45.626-10.174-92.902-0.833-131.301 21.965-38.487 22.85-69.538 60.142-80.791 107.342-8.278 34.72-5.369 72.758 10.731 111.77-35.67 8.464-64.099 26.186-84.825 50.784-29.004 34.422-39.927 78.733-38.766 120.506 1.159 41.738 14.399 84.032 37.682 116.688 23.373 32.784 59.097 58.426 104.306 58.426h543.999c41.907 0 77.2-26.419 101.261-57.354 24.598-31.629 41.888-73.197 46.544-115.114 4.659-41.933-3.094-87.658-33.443-123.283-24.106-28.301-59.504-46.774-105.616-53.456 5.83-35.194 1.686-67.674-10.605-96.205-16.646-38.628-46.998-67.197-81.437-85.010-54.902-28.397-128.733-32.652-182.486 2.495zM512 437.331c17.674 0 32 14.33 32 32v53.328h53.334c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-53.334v53.341c0 17.674-14.326 32-32 32s-32-14.326-32-32v-53.341h-53.331c-17.674 0-32-14.326-32-32 0-17.67 14.326-32 32-32h53.331v-53.328c0-17.67 14.326-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["cloud-connectivity"],"defaultCode":59713,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":984,"name":"cloud-connectivity","prevSize":32,"id":72,"code":59713},"setIdx":0,"setId":6,"iconIdx":73},{"icon":{"paths":["M630.157 204.798c16.493 6.344 24.723 24.859 18.378 41.355l-213.331 554.667c-6.346 16.496-24.861 24.723-41.357 18.381-16.493-6.346-24.723-24.861-18.378-41.357l213.331-554.666c6.346-16.495 24.861-24.724 41.357-18.38zM321.296 361.37c12.496 12.499 12.496 32.758 0 45.258l-105.373 105.37 105.373 105.373c12.496 12.499 12.496 32.758 0 45.258-12.497 12.496-32.759 12.496-45.255 0l-128-128c-12.497-12.499-12.497-32.758 0-45.258l128-128c12.497-12.496 32.758-12.496 45.255 0zM702.707 361.37c12.496-12.496 32.758-12.496 45.254 0l128 128c12.496 12.499 12.496 32.758 0 45.258l-128 128c-12.496 12.496-32.758 12.496-45.254 0-12.496-12.499-12.496-32.758 0-45.258l105.373-105.373-105.373-105.37c-12.496-12.499-12.496-32.758 0-45.258z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["code"],"defaultCode":59714,"grid":0},"attrs":[{}],"properties":{"order":985,"name":"code","prevSize":32,"id":73,"code":59714},"setIdx":0,"setId":6,"iconIdx":74},{"icon":{"paths":["M507.488 130.134c16.496 6.344 24.723 24.859 18.378 41.354l-160 416c-6.342 16.496-24.858 24.723-41.354 18.381-16.494-6.346-24.723-24.861-18.379-41.357l160.002-415.998c6.342-16.495 24.858-24.724 41.354-18.38z","M278.628 249.373c12.497 12.497 12.497 32.758 0 45.255l-73.373 73.372 73.373 73.373c12.497 12.496 12.497 32.758 0 45.254-12.497 12.499-32.758 12.499-45.255 0l-96-96c-6.001-6-9.372-14.141-9.372-22.627s3.372-16.624 9.372-22.627l96-95.999c12.497-12.497 32.758-12.497 45.255 0z","M553.373 249.373c12.496-12.497 32.758-12.497 45.254 0l96 95.999c6 6.003 9.373 14.141 9.373 22.627s-3.373 16.627-9.373 22.627l-96 96c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.758 0-45.254l73.373-73.373-73.373-73.372c-12.496-12.497-12.496-32.758 0-45.255z","M672 160c0-17.673 14.326-32 32-32h96c53.021 0 96 42.981 96 96v576c0 53.021-42.979 96-96 96h-576c-53.020 0-96-42.979-96-96v-160c0-17.674 14.327-32 32-32s32 14.326 32 32v192h640v-640h-128c-17.674 0-32-14.327-32-32z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{},{},{},{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{},{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{},{},{}]},"tags":["code-block"],"defaultCode":59840,"grid":0},"attrs":[{},{},{},{}],"properties":{"order":986,"id":74,"name":"code-block","prevSize":32,"code":59840},"setIdx":0,"setId":6,"iconIdx":75},{"icon":{"paths":["M770.704 224c17.674 0 32 14.327 32 32v544c0 17.674-14.326 32-32 32h-543.999c-17.673 0-32-14.326-32-32v-128c17.673 0 32-14.326 32-32s-14.327-32-32-32v-192c17.673 0 32-14.326 32-32s-14.327-32-32-32v-96c0-17.673 14.327-32 32-32h543.999zM130.705 608c-17.673 0-32 14.326-32 32s14.327 32 32 32v128c0 53.021 42.981 96 96 96h543.999c53.021 0 96-42.979 96-96v-544c0-53.019-42.979-96-96-96h-543.999c-53.019 0-96 42.981-96 96v96c-17.673 0-32 14.326-32 32s14.327 32 32 32v192zM427.91 514.266c13.315-3.568 27.309-3.789 40.73-0.643l31.52 7.389c8.73 2.045 17.83 1.904 26.49-0.416l22.186-5.942c14.285-3.827 29.328-4.042 43.683-0.675 40.429 9.475 69.325 45.584 69.325 87.277v24.336c0 31.811-25.789 57.6-57.6 57.6h-180.739c-31.811 0-57.6-25.789-57.6-57.6v-30.525c0-37.862 25.434-71.005 62.006-80.8zM456.957 563.472c-5.206-1.219-10.634-1.133-15.798 0.25-14.189 3.798-24.054 16.656-24.054 31.344v30.525c0 3.536 2.867 6.4 6.4 6.4h180.739c3.533 0 6.4-2.864 6.4-6.4v-24.336c0-17.75-12.365-33.341-29.808-37.427-6.186-1.45-12.662-1.35-18.752 0.282l-22.186 5.942c-16.813 4.502-34.474 4.781-51.421 0.81l-31.52-7.389zM539.155 420.48c0-13.962-11.318-25.28-25.28-25.28s-25.283 11.318-25.283 25.28c0 13.962 11.322 25.28 25.283 25.28s25.28-11.318 25.28-25.28zM590.355 420.48c0 42.24-34.243 76.48-76.48 76.48-42.24 0-76.483-34.24-76.483-76.48s34.243-76.48 76.483-76.48c42.237 0 76.48 34.24 76.48 76.48z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["contacts"],"defaultCode":59715,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":987,"name":"contacts","prevSize":32,"id":75,"code":59715},"setIdx":0,"setId":6,"iconIdx":76},{"icon":{"paths":["M464 272c-35.347 0-64 28.654-64 64v480c0 35.347 28.653 64 64 64h352c35.347 0 64-28.653 64-64v-304c0-6.509-1.984-12.864-5.69-18.214l-134.458-194.215c-11.952-17.267-31.619-27.571-52.621-27.571h-223.232zM464 336h144v144c0 35.347 28.653 64 64 64h144v272h-352v-480zM672 480v-144h15.232l99.693 144h-114.925zM144 208c0-35.346 28.654-64 64-64h241.844c18.032 0 35.229 7.607 47.357 20.949l39.136 43.051h-328.336v480h128v64h-128c-35.346 0-64-28.653-64-64v-480z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["copy"],"defaultCode":59716,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":988,"name":"copy","prevSize":32,"id":76,"code":59716},"setIdx":0,"setId":6,"iconIdx":77},{"icon":{"paths":["M824.682 183.521c-37.19-37.986-98.202-38.583-136.131-1.333l-348.48 342.237c-12.739 12.512-21.733 28.32-25.976 45.654l-23.681 96.749c-6.94 28.355 16.754 54.845 45.747 51.142l90.691-11.578c20.224-2.582 39.104-11.52 53.907-25.52l360.486-340.922c38.986-36.868 40.173-98.482 2.637-136.82l-19.2-19.61zM733.485 227.821c12.643-12.417 32.979-12.218 45.376 0.444l19.2 19.61c12.512 12.78 12.115 33.317-0.88 45.607l-69.965 66.169-63.446-63.364 69.715-68.466zM618.074 341.162l62.592 62.512-243.971 230.73c-4.934 4.666-11.229 7.645-17.968 8.506l-58.307 7.443 15.926-65.075c1.414-5.779 4.413-11.046 8.659-15.219l233.069-228.896zM193.608 265.602c0-17.673 14.346-32 32.042-32h281.332c17.696 0 32.042-14.327 32.042-32s-14.346-32-32.042-32h-281.332c-53.089 0-96.127 42.981-96.127 96v534.402c0 53.018 43.037 95.997 96.127 95.997h529.764c53.091 0 96.128-42.979 96.128-96v-279.414c0-17.67-14.346-32-32.042-32s-32.042 14.33-32.042 32v279.414c0 17.674-14.346 32-32.045 32h-529.764c-17.696 0-32.042-14.326-32.042-31.997v-534.402z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["create"],"defaultCode":59717,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":989,"name":"create","prevSize":32,"id":77,"code":59717},"setIdx":0,"setId":6,"iconIdx":78},{"icon":{"paths":["M717.373 298.663c0-17.673-14.326-32-32-32s-32 14.327-32 32v426.665c0 17.674 14.326 32 32 32s32-14.326 32-32v-426.665z","M514.704 394.672c17.674 0 32 14.326 32 32v298.666c0 17.674-14.326 32-32 32s-32-14.326-32-32v-298.666c0-17.674 14.326-32 32-32z","M376.038 554.672c0-17.674-14.326-32-32-32s-32 14.326-32 32v170.669c0 17.67 14.327 32 32 32s32-14.33 32-32v-170.669z","M130.705 199.556v624.889c0 39.52 32.036 71.555 71.556 71.555h624.888c39.52 0 71.555-32.035 71.555-71.555v-624.889c0-39.519-32.035-71.556-71.555-71.556h-624.888c-39.519 0-71.556 32.036-71.556 71.556zM202.26 192h624.888c4.173 0 7.555 3.383 7.555 7.556v624.889c0 4.173-3.382 7.555-7.555 7.555h-624.888c-4.173 0-7.556-3.382-7.556-7.555v-624.889c0-4.173 3.383-7.556 7.556-7.556z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["dashboard"],"defaultCode":59718,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":990,"name":"dashboard","prevSize":32,"id":78,"code":59718},"setIdx":0,"setId":6,"iconIdx":79},{"icon":{"paths":["M739.68 864v-448h-448.593v448h448.593zM227.003 864v-448c-35.393 0-64.084-28.653-64.084-64v-128c0-35.346 28.692-64 64.084-64h224.297c0-35.346 28.691-64 64.083-64 35.395 0 64.086 28.654 64.086 64h224.294c35.395 0 64.086 28.654 64.086 64v128c0 35.347-28.691 64-64.086 64v448c0 35.347-28.691 64-64.083 64h-448.593c-35.393 0-64.085-28.653-64.085-64zM803.763 224h-576.761v128h576.761v-128zM419.258 544v192c0 17.674 14.346 32 32.042 32s32.042-14.326 32.042-32v-192c0-17.674-14.346-32-32.042-32s-32.042 14.326-32.042 32zM579.469 512c17.696 0 32.042 14.326 32.042 32v192c0 17.674-14.346 32-32.042 32s-32.042-14.326-32.042-32v-192c0-17.674 14.346-32 32.042-32z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["delete"],"defaultCode":59719,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":991,"name":"delete","prevSize":32,"id":79,"code":59719},"setIdx":0,"setId":6,"iconIdx":80},{"icon":{"paths":["M341.334 778.672c-17.674 0-32 14.326-32 32s14.327 32 32 32h341.334c17.67 0 32-14.326 32-32s-14.33-32-32-32h-341.334z","M85.334 298.672c0-70.692 57.308-128 128-128h597.335c70.691 0 128 57.308 128 128v298.666c0 70.694-57.309 128-128 128h-597.335c-70.692 0-128-57.306-128-128v-298.666zM213.334 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.347 28.654 64 64 64h597.335c35.344 0 64-28.653 64-64v-298.666c0-35.347-28.656-64-64-64h-597.335z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["desktop"],"defaultCode":59720,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":992,"name":"desktop","prevSize":32,"id":80,"code":59720},"setIdx":0,"setId":6,"iconIdx":81},{"icon":{"paths":["M325.837 160c0-17.673-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.327-32.042 32v64c0 17.673 14.346 32 32.042 32h64.085c17.696 0 32.043-14.327 32.043-32v-64zM325.837 586.666c0-17.674-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.085c17.696 0 32.043-14.326 32.043-32v-64zM454.006 160c0-17.673 14.346-32 32.042-32h64.083c17.696 0 32.042 14.327 32.042 32v64c0 17.673-14.346 32-32.042 32h-64.083c-17.696 0-32.042-14.327-32.042-32v-64zM582.173 373.334c0-17.674-14.346-32-32.042-32h-64.083c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM454.006 586.666c0-17.674 14.346-32 32.042-32h64.083c17.696 0 32.042 14.326 32.042 32v64c0 17.674-14.346 32-32.042 32h-64.083c-17.696 0-32.042-14.326-32.042-32v-64zM582.173 800c0-17.674-14.346-32-32.042-32h-64.083c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM710.342 160c0-17.673 14.346-32 32.045-32h64.083c17.696 0 32.042 14.327 32.042 32v64c0 17.673-14.346 32-32.042 32h-64.083c-17.699 0-32.045-14.327-32.045-32v-64zM838.512 373.334c0-17.674-14.346-32-32.042-32h-64.083c-17.699 0-32.045 14.326-32.045 32v64c0 17.674 14.346 32 32.045 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM710.342 586.666c0-17.674 14.346-32 32.045-32h64.083c17.696 0 32.042 14.326 32.042 32v64c0 17.674-14.346 32-32.042 32h-64.083c-17.699 0-32.045-14.326-32.045-32v-64zM325.837 373.334c0-17.674-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.085c17.696 0 32.043-14.326 32.043-32v-64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["dialpad"],"defaultCode":59721,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":993,"name":"dialpad","prevSize":32,"id":81,"code":59721},"setIdx":0,"setId":6,"iconIdx":82},{"icon":{"paths":["M478.65 672c-17.674 0-32-14.326-32-32v-32h-32c-17.674 0-32-14.326-32-32s14.326-32 32-32h32v-58.88h-32c-17.674 0-32-14.326-32-32s14.326-32 32-32h32v-37.12c0-17.674 14.326-32 32-32 17.67 0 32 14.326 32 32v37.12h58.88v-37.12c0-17.674 14.326-32 32-32s32 14.326 32 32v37.12h37.12c17.67 0 32 14.326 32 32s-14.33 32-32 32h-37.12v58.88h37.12c17.67 0 32 14.326 32 32s-14.33 32-32 32h-37.12v32c0 17.674-14.326 32-32 32s-32-14.326-32-32v-32h-58.88v32c0 17.674-14.33 32-32 32zM510.65 544h58.88v-58.88h-58.88v58.88z","M158.648 672h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-192h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-160c0-35.346 28.654-64 64-64h608.001c35.344 0 64 28.654 64 64v640c0 35.347-28.656 64-64 64h-608.001c-35.346 0-64-28.653-64-64v-160zM830.65 192h-608.001v160h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v192h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v160h608.001v-640z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["directory"],"defaultCode":59648,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":994,"id":82,"name":"directory","prevSize":32,"code":59648},"setIdx":0,"setId":6,"iconIdx":83},{"icon":{"paths":["M833.35 128c10.285 0 20 2.425 28.611 6.735-11.834 4.684-22.922 11.812-32.493 21.383l-35.882 35.882h-568.236v160h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v192h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v88.237l-64 64v-152.237h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-192h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-160c0-35.346 28.654-64 64-64h607.999z","M361.117 896l64-64h408.234v-408.237l64-64v472.237c0 35.347-28.653 64-64 64h-472.234z","M604.23 352c8.166 0 15.616 3.056 21.267 8.090l-53.267 53.267v-29.357c0-17.674 14.33-32 32-32z","M513.35 421.12h51.117l-115.117 115.117v-51.117h-32c-17.67 0-32-14.326-32-32s14.33-32 32-32h32v-37.12c0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32v37.12z","M391.174 594.413l50.413-50.413h-24.237c-17.67 0-32 14.326-32 32 0 6.854 2.157 13.203 5.824 18.413z","M919.978 201.372c-12.496-12.497-32.755-12.497-45.254 0l-671.999 672c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l671.999-672c12.499-12.497 12.499-32.758 0-45.255z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["directory-disabled"],"defaultCode":59649,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":995,"id":83,"name":"directory-disabled","prevSize":32,"code":59649},"setIdx":0,"setId":6,"iconIdx":84},{"icon":{"paths":["M919.978 105.372c12.499 12.497 12.499 32.758 0 45.255l-89.373 89.372 89.373 89.373c12.499 12.496 12.499 32.758 0 45.254-12.496 12.496-32.755 12.496-45.254 0l-89.373-89.372-89.373 89.372c-12.496 12.496-32.755 12.496-45.254 0-12.496-12.496-12.496-32.758 0-45.254l89.373-89.373-89.373-89.372c-12.496-12.497-12.496-32.758 0-45.255 12.499-12.497 32.758-12.497 45.254 0l89.373 89.373 89.373-89.373c12.499-12.497 32.758-12.497 45.254 0z","M512.419 126.678c1.491 17.61-11.578 33.094-29.187 34.585-180.289 15.259-321.88 166.478-321.88 350.731 0 194.406 157.596 352 351.999 352 194.406 0 352-157.594 352-352 0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32 0 229.75-186.25 416-416 416s-415.999-186.25-415.999-416c0-217.79 167.341-396.462 380.482-414.503 17.61-1.491 33.094 11.577 34.586 29.187z","M119.219 432.47c0-17.674 14.327-32 32-32h329.037c17.67 0 32 14.326 32 32 0 17.67-14.33 32-32 32h-329.037c-17.673 0-32-14.33-32-32z","M119.233 640c0-17.674 14.327-32 32-32h724.255c17.674 0 32 14.326 32 32s-14.326 32-32 32h-724.255c-17.673 0-32-14.326-32-32z","M504.81 121.090c11.117 13.739 8.992 33.888-4.749 45.005-8.666 7.012-18.886 20.139-29.238 40.961-10.179 20.471-19.61 46.603-27.635 77.587-16.042 61.955-25.837 140.879-25.837 227.356 0 103.555 14.038 195.981 35.85 261.411 10.96 32.88 23.306 57.181 35.462 72.605 12.438 15.786 21.024 17.978 24.688 17.978 3.667 0 12.253-2.192 24.691-17.978 12.157-15.424 24.502-39.725 35.462-72.605 21.808-65.43 35.846-157.856 35.846-261.411 0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32 0 108.522-14.614 208.096-39.133 281.648-12.202 36.608-27.437 68.544-45.91 91.984-18.186 23.078-43.274 42.362-74.957 42.362-31.68 0-56.768-19.283-74.957-42.362-18.47-23.44-33.706-55.376-45.91-91.984-24.515-73.552-39.133-173.126-39.133-281.648 0-90.915 10.256-175.338 27.882-243.4 8.81-34.025 19.619-64.572 32.282-90.038 12.49-25.115 27.712-47.185 46.288-62.217 13.741-11.117 33.888-8.992 45.008 4.746z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["directory-error"],"defaultCode":59650,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":996,"id":84,"name":"directory-error","prevSize":32,"code":59650},"setIdx":0,"setId":6,"iconIdx":85},{"icon":{"paths":["M561.667 127.992c-121.696 0-200.973 50.509-248.813 115.801-46.216 63.073-61.638 137.752-61.933 188.616-8.705 98.746 28.601 172.896 89.422 223.469 59.686 49.626 140.202 75.258 217.85 83.738 77.75 8.486 161.715 1.197 227.856-12.547 33.066-6.87 62.774-15.581 85.642-25.331 11.366-4.848 22.029-10.368 30.797-16.669 7.875-5.661 18.541-14.976 23.242-28.835 7.286-21.475-3.133-38.784-11.965-48.102-8.41-8.877-19.427-15.405-28.24-20.016-9.306-4.867-19.379-9.206-27.533-12.707-8.973-3.856-14.858-6.4-18.56-8.432-4.845-2.662-8.842-5.088-12.026-7.203 20.256-47.142 31.549-77.043 37.696-99.19 7.293-26.272 7.315-41.725 7.315-58.909 0-21.523-9.603-88.542-52.81-151.108-44.701-64.73-124.074-122.573-257.939-122.573zM314.916 433.898c0-40.416 12.607-101.84 49.564-152.277 35.782-48.836 95.882-89.628 197.187-89.628 112.086 0 172.090 46.886 205.277 94.94 34.678 50.219 41.472 104.040 41.472 114.741v0.198c0 14.918 0 23.638-4.982 41.594-5.491 19.779-16.963 50.189-41.539 106.538-5.802 13.296-2.762 25.77 1.155 33.754 3.664 7.478 9.005 13.242 13.331 17.261 8.835 8.211 20.653 15.686 32.224 22.045 6.618 3.638 15.238 7.334 22.563 10.477l1.562 0.672c5.904 2.534 11.52 4.97 16.688 7.418-0.909 0.406-1.856 0.819-2.835 1.238-17.741 7.568-43.078 15.206-73.555 21.539-60.947 12.666-138.064 19.21-207.888 11.587-69.926-7.635-136.982-30.336-183.878-69.328-45.459-37.798-73.674-92.064-66.481-169.821l0.136-1.469v-1.478zM819.162 553.354l-0.074-0.086c0 0.003 0.010 0.013 0.029 0.035 0.010 0.013 0.026 0.029 0.045 0.051z","M178.552 502.474c7.496-11.258 16.26-22.259 26.436-32.592 0.876 31.747 6.169 61.226 15.216 88.358-15.094 30.877-18.374 59.315-18.374 65.357v0.186c0 11.382 0 17.536 3.524 30.701 3.993 14.918 12.441 38.211 30.867 82.022 5.256 12.496 2.48 24.099-0.985 31.43-3.249 6.874-7.925 12.058-11.512 15.514-7.319 7.053-16.852 13.254-25.75 18.326-5.008 2.854-11.333 5.706-16.546 8.029 11.182 3.939 24.98 7.814 40.802 11.226 44.977 9.693 101.833 14.669 153.062 8.87 51.28-5.808 99.776-23.014 133.35-51.965l0.608-0.528c14.794 2.784 29.53 4.938 44.051 6.525 10.886 1.187 21.862 2.086 32.877 2.72-10.122 14.797-22.163 28.045-35.741 39.754-46.362 39.974-108.547 60.362-167.946 67.088-59.45 6.73-123.405 0.947-173.744-9.901-25.17-5.424-48.056-12.352-65.901-20.243-8.86-3.92-17.458-8.502-24.686-13.891-6.431-4.794-15.831-13.171-20.001-25.92-6.422-19.632 2.792-35.443 10.458-43.834 7.193-7.872 16.405-13.462 23.248-17.174 7.309-3.965 15.158-7.466 21.235-10.173 6.907-3.078 10.854-4.858 13.183-6.186 1.349-0.768 2.591-1.501 3.727-2.195-13.937-33.885-21.976-56.118-26.48-72.947-5.68-21.222-5.7-33.875-5.7-47.434 0-17.712 7.436-71.139 40.721-121.123zM155.337 797.248c-0.012 0 0.084 0.102 0.317 0.301-0.19-0.202-0.306-0.301-0.317-0.301zM179.587 737.085c-0.004 0-0.052 0.051-0.137 0.15l0.112-0.118c0.019-0.022 0.027-0.032 0.025-0.032z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["discussions"],"defaultCode":59722,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":997,"name":"discussions","prevSize":32,"id":85,"code":59722},"setIdx":0,"setId":6,"iconIdx":86},{"icon":{"paths":["M160 256c0-17.673 14.327-32 32-32h640c17.674 0 32 14.327 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.327-32-32zM160 421.162c0-17.674 14.327-32 32-32h640c17.674 0 32 14.326 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.326-32-32zM160 602.838c0-17.674 14.327-32 32-32h640c17.674 0 32 14.326 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.326-32-32zM160 768c0-17.674 14.327-32 32-32h344.614c17.674 0 32 14.326 32 32s-14.326 32-32 32h-344.614c-17.673 0-32-14.326-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["document"],"defaultCode":59723,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":998,"name":"document","prevSize":32,"id":86,"code":59723},"setIdx":0,"setId":6,"iconIdx":87},{"icon":{"paths":["M128.169 352c0-17.674 14.346-32 32.042-32h704.928c17.696 0 32.045 14.326 32.045 32s-14.349 32-32.045 32h-704.928c-17.696 0-32.042-14.326-32.042-32zM213.615 522.669c0-17.674 14.346-32 32.042-32h534.036c17.699 0 32.045 14.326 32.045 32s-14.346 32-32.045 32h-534.036c-17.697 0-32.042-14.326-32.042-32zM331.104 661.331c-17.698 0-32.043 14.326-32.043 32s14.346 32 32.043 32h363.146c17.696 0 32.042-14.326 32.042-32s-14.346-32-32.042-32h-363.146z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["donner"],"defaultCode":59724,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":999,"name":"donner","prevSize":32,"id":87,"code":59724},"setIdx":0,"setId":6,"iconIdx":88},{"icon":{"paths":["M273.128 356.678c-6.62 27.766-2.384 63.757 25.498 105.581l21.374 32.061v17.69h-48c-44.011 0-70.483 14.874-86.278 33.619-16.496 19.578-24.573 47.264-23.734 77.491 0.841 30.262 10.601 59.968 25.818 81.312 15.127 21.216 33.404 31.578 52.195 31.578h79.999v64h-80c-45.209 0-80.932-25.642-104.306-58.426-23.283-32.656-36.522-74.95-37.682-116.688-1.16-41.773 9.763-86.083 38.766-120.506 20.726-24.598 49.155-42.32 84.825-50.784-16.1-39.011-19.009-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.4-22.798 85.677-32.139 131.303-21.965 35.584 7.935 68.909 27.48 95.251 59.554 53.75-35.147 127.584-30.892 182.483-2.495 34.438 17.812 64.794 46.382 81.437 85.010 12.294 28.531 16.438 61.011 10.608 96.205 46.112 6.682 81.507 25.155 105.613 53.456 30.349 35.626 38.106 81.35 33.446 123.283-4.659 41.917-21.946 83.485-46.544 115.114-24.061 30.934-59.354 57.354-101.261 57.354h-80v-64h80c14.093 0 32.8-9.581 50.742-32.646 17.398-22.371 30.112-52.806 33.453-82.89 3.341-30.067-2.902-56.339-18.554-74.714-15.222-17.869-44.035-33.75-97.642-33.75h-45.686l15.613-42.938c13.546-37.251 11.091-66.742 1.437-89.149-9.856-22.87-28.502-41.302-52.064-53.488-49.587-25.649-107.475-18.625-134.717 14.064l-30.134 36.16-22.541-41.325c-19.757-36.219-47.232-54.175-74.87-60.339-28.378-6.327-59.098-0.669-84.701 14.53-25.512 15.148-44.461 38.855-51.208 67.152zM630.979 787.222c12.298-12.691 11.981-32.95-0.707-45.251-12.691-12.298-32.95-11.981-45.251 0.707l-41.021 42.326v-273.005c0-17.674-14.326-32-32-32s-32 14.326-32 32v273.005l-41.021-42.326c-12.301-12.688-32.56-13.005-45.251-0.707-12.688 12.301-13.005 32.56-0.707 45.251l96 99.050c6.029 6.218 14.32 9.728 22.979 9.728s16.95-3.51 22.979-9.728l96-99.050z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["download"],"defaultCode":59725,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1000,"name":"download","prevSize":32,"id":88,"code":59725},"setIdx":0,"setId":6,"iconIdx":89},{"icon":{"paths":["M795.648 132.004c-25.027-25.027-65.603-25.027-90.63-0l-530.467 530.469c-9.577 9.574-15.873 21.939-17.985 35.318l-19.611 124.186c-1.386 8.771-0.942 17.299 1.006 25.261 7.597 31.037 38.083 53.44 72.291 48.038l124.184-19.613c13.379-2.112 25.744-8.41 35.322-17.984l530.467-530.47c12.512-12.513 18.768-28.914 18.768-45.316 0-10.379-2.506-20.757-7.517-30.15-2.906-5.451-6.656-10.57-11.251-15.164l-104.576-104.575zM630.675 296.979l119.658-119.658 104.576 104.574-119.658 119.657-104.576-104.573zM200.255 831.974l19.611-124.186 365.494-365.494 104.576 104.573-365.494 365.494-124.187 19.613z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["edit"],"defaultCode":59726,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1001,"name":"edit","prevSize":32,"id":89,"code":59726},"setIdx":0,"setId":6,"iconIdx":90},{"icon":{"paths":["M330.074 644.886c-21.572-19.619-6.010-52.886 23.152-52.886 8.963 0 17.526 3.53 24.272 9.437 21.603 18.918 42.64 31.958 62.701 40.509 36.563 15.59 71.805 17.107 104.794 9.939 37.632-8.176 72.659-27.808 102.109-51.341 6.726-5.376 14.995-8.544 23.606-8.544 30.218 0 45.616 34.256 22.397 53.594-36.912 30.742-82.79 57.59-134.522 68.832-44.794 9.734-93.67 7.632-143.485-13.606-28.79-12.275-57.232-30.653-85.024-55.933z","M400.17 480c35.344 0 64-28.653 64-64s-28.656-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64z","M624.17 480c35.344 0 64-28.653 64-64s-28.656-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64z","M928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["emoji"],"defaultCode":59729,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1002,"name":"emoji","prevSize":32,"id":90,"code":59729},"setIdx":0,"setId":6,"iconIdx":91},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM400.166 480c-35.347 0-64-28.653-64-64s28.653-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64zM688.166 416c0-35.347-28.653-64-64-64s-64 28.653-64 64c0 35.347 28.653 64 64 64s64-28.653 64-64zM353.226 720c8.963 0 17.526-3.53 24.272-9.437 21.603-18.918 42.64-31.958 62.701-40.509 36.563-15.59 71.805-17.107 104.794-9.939 37.632 8.176 72.659 27.808 102.109 51.341 6.726 5.376 14.995 8.544 23.606 8.544 30.218 0 45.616-34.256 22.397-53.594-36.912-30.742-82.79-57.59-134.522-68.832-44.794-9.734-93.67-7.632-143.485 13.606-28.79 12.275-57.232 30.653-85.024 55.933-21.572 19.619-6.010 52.886 23.152 52.886z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["emoji-bad-mood"],"defaultCode":59727,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1003,"name":"emoji-bad-mood","prevSize":32,"id":91,"code":59727},"setIdx":0,"setId":6,"iconIdx":92},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM400.166 480c-35.347 0-64-28.653-64-64s28.653-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64zM688.166 416c0-35.347-28.653-64-64-64s-64 28.653-64 64c0 35.347 28.653 64 64 64s64-28.653 64-64zM384 640h256c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32s14.326-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["emoji-neutral-mood"],"defaultCode":59728,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1004,"name":"emoji-neutral-mood","prevSize":32,"id":92,"code":59728},"setIdx":0,"setId":6,"iconIdx":93},{"icon":{"paths":["M655.744 512c88.365 0 160-71.635 160-160s-71.635-160-160-160c-88.368 0-160 71.635-160 160 0 26.934 6.653 52.314 18.41 74.582l-11.914 11.914 0.128 0.131-299.135 299.136c-3.533 9.926-6.41 20.976-7.738 31.606-1.652 13.219-0.563 22.966 1.874 28.938 1.768 4.333 4.22 7.232 10.772 9.014 8.316 2.262 24.518 2.794 52.822-5.501 8.524-3.808 27.721-16.285 45.132-35.382 18.18-19.939 29.648-41.856 29.648-62.438 0-15.642 11.309-28.992 26.736-31.565l91.75-15.293c3.766-2.656 18.768-15.693 10.134-58.867-2.099-10.49 1.184-21.338 8.749-28.902l88.198-88.195c26.467 19.379 59.114 30.822 94.432 30.822zM439.571 410.915c-5.104-18.771-7.827-38.525-7.827-58.915 0-123.712 100.288-224 224-224 123.709 0 224 100.288 224 224s-100.291 224-224 224c-29.29 0-57.264-5.619-82.906-15.843l-43.008 43.008c7.158 65.494-23.99 104.534-55.968 115.194l-2.384 0.794-74.854 12.477c-7.085 31.405-25.174 58.122-43.235 77.933-23.123 25.357-50.958 44.627-69.762 52.15l-1.324 0.528-1.365 0.41c-34.714 10.416-64.73 13.19-89.594 6.429-26.782-7.286-44.33-24.784-53.228-46.586-8.23-20.163-8.473-42.282-6.126-61.062 2.402-19.216 7.899-37.958 14.042-53.315 1.61-4.022 4.020-7.677 7.084-10.742l286.456-286.458zM623.744 336c0 26.509 21.488 48 48 48 26.509 0 48-21.491 48-48s-21.491-48-48-48c-26.512 0-48 21.49-48 48z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["encrypted"],"defaultCode":59730,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1005,"name":"encrypted","prevSize":32,"id":93,"code":59730},"setIdx":0,"setId":6,"iconIdx":94},{"icon":{"paths":["M536.89 64c233.677 0 423.11 189.433 423.11 423.11h-423.11v-423.11z","M64 536.89c0-233.678 189.433-423.112 423.11-423.112v423.112h423.11c0 233.677-189.43 423.11-423.11 423.11-233.677 0-423.11-189.434-423.11-423.11z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["engagement-dashboard"],"defaultCode":59731,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1006,"name":"engagement-dashboard","prevSize":32,"id":94,"code":59731},"setIdx":0,"setId":6,"iconIdx":95},{"icon":{"paths":["M416 586.445v177.232l75.514-62.928c11.869-9.888 29.104-9.888 40.973 0l75.514 62.928v-177.232c-29.098 13.821-61.645 21.555-96 21.555s-66.902-7.734-96-21.555zM352 540.768v291.232c0 12.416 7.184 23.712 18.426 28.979 11.245 5.267 24.522 3.552 34.061-4.397l107.514-89.594 107.514 89.594c9.539 7.949 22.816 9.664 34.061 4.397 11.242-5.267 18.426-16.563 18.426-28.979v-291.232c39.59-40.403 64-95.734 64-156.768 0-123.712-100.288-224.001-224-224.001s-224 100.288-224 224.001c0 61.034 24.41 116.365 64 156.768zM416 512.013l-0.016-0.013c-38.854-29.19-63.984-75.661-63.984-128 0-88.366 71.635-160.001 160-160.001s160 71.635 160 160.001c0 52.339-25.13 98.81-63.984 128l-0.016 0.013c-26.742 20.083-59.981 31.987-96 31.987s-69.258-11.904-96-31.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["enterprise-feature"],"defaultCode":59732,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1007,"name":"enterprise-feature","prevSize":32,"id":95,"code":59732},"setIdx":0,"setId":6,"iconIdx":96},{"icon":{"paths":["M500.64 128c213.35 0 386.336 172.985 386.336 386.336 0 192.87-141.254 352.707-325.974 381.664v-269.958h90.022l17.114-111.706h-107.136v-72.47c0-11.462 2.102-22.822 7.274-32.544 2.474-4.656 5.651-8.934 9.635-12.666 9.866-9.245 24.688-15.152 46.058-15.152h48.733v-95.080c0 0-44.224-7.552-86.493-7.552-84.698 0-141.258 49.313-145.651 138.907-0.182 3.738-0.275 7.546-0.275 11.424v85.133h-98.122v111.706h98.122v269.958c-184.721-29.011-325.978-188.848-325.978-381.664 0-213.351 172.985-386.336 386.336-386.336z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["facebook-monochromatic"],"defaultCode":59733,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1008,"name":"facebook-monochromatic","prevSize":32,"id":96,"code":59733},"setIdx":0,"setId":6,"iconIdx":97},{"icon":{"paths":["M865.139 512c0 33.28-4.624 65.485-13.267 96h-183.274c2.803-30.816 4.288-62.957 4.288-96 0-16.234-0.358-32.25-1.056-48h190.061c2.141 15.696 3.248 31.718 3.248 48zM607.68 464c0.739 15.67 1.123 31.686 1.123 48 0 33.398-1.61 65.555-4.57 96h-183.117c-2.963-30.445-4.57-62.602-4.57-96 0-16.314 0.384-32.33 1.123-48h190.010zM667.014 400c-10.016-93.226-32.221-173.252-61.875-227.763 113.702 30.788 204.579 116.981 241.782 227.763h-179.907zM420.211 172.237c-29.654 54.51-51.862 134.537-61.875 227.763h-179.91c37.204-110.782 128.083-196.975 241.785-227.763zM422.816 400c7.171-62.314 20.064-116.804 36.384-159.18 12.842-33.339 26.56-55.927 38.528-69.070 8.406-9.235 13.446-11.291 14.947-11.698 1.501 0.407 6.541 2.463 14.947 11.698 11.968 13.143 25.686 35.731 38.525 69.070 16.32 42.377 29.216 96.867 36.387 159.18h-179.718zM353.52 464c-0.698 15.75-1.056 31.766-1.056 48 0 33.043 1.482 65.184 4.288 96h-183.275c-8.643-30.515-13.268-62.72-13.268-96 0-16.282 1.107-32.304 3.249-48h190.061zM364.742 672c11.667 72.646 31.040 134.861 55.466 179.763-96.678-26.179-176.854-92.413-221.565-179.763h166.1zM513.152 928c229.834-0.259 416.070-186.41 416.070-416 0-229.75-186.493-416-416.547-416s-416.55 186.25-416.55 416c0 229.59 186.237 415.741 416.070 416 0.16 0 0.32 0 0.48 0s0.32 0 0.477 0zM605.142 851.763c24.426-44.902 43.798-107.117 55.466-179.763h166.099c-44.71 87.35-124.89 153.584-221.565 179.763zM595.638 672c-7.379 42.458-17.514 80.083-29.491 111.184-12.838 33.338-26.557 55.926-38.525 69.069-8.406 9.235-13.446 11.29-14.947 11.699-1.501-0.41-6.541-2.464-14.947-11.699-11.968-13.142-25.686-35.731-38.528-69.069-11.978-31.101-22.109-68.726-29.488-111.184h165.926z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["federation"],"defaultCode":59652,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1009,"id":97,"name":"federation","prevSize":32,"code":59652},"setIdx":0,"setId":6,"iconIdx":98},{"icon":{"paths":["M542.65 96c80.093 0 154.902 22.636 218.374 61.859l-46.746 46.746c-24.739-13.843-51.322-24.785-79.286-32.368 12.166 22.395 23.078 49.095 32.406 79.249l-52 51.999c-5.654-22.994-12.17-44.005-19.347-62.666-12.822-33.339-26.522-55.927-38.474-69.070-8.397-9.235-13.43-11.291-14.928-11.698-1.498 0.407-6.531 2.463-14.928 11.698-11.952 13.143-25.654 35.731-38.477 69.070-16.298 42.377-29.174 96.867-36.336 159.18h65.974l-64 64h-7.114c-0.118 2.47-0.224 4.95-0.323 7.437l-64.538 64.538c-0.173-7.933-0.259-15.926-0.259-23.974 0-16.234 0.358-32.25 1.053-48h-189.809c-2.14 15.696-3.245 31.718-3.245 48 0 33.28 4.619 65.485 13.251 96h106.984l-64 64h-17.852c2.004 3.92 4.078 7.798 6.223 11.629l-46.746 46.749c-39.223-63.475-61.859-138.282-61.859-218.378 0-229.75 186.25-416 416.001-416zM896.79 293.623l-46.746 46.748c10.56 18.87 19.43 38.816 26.413 59.629h-86.045l-64 64h164.992c2.138 15.696 3.245 31.718 3.245 48 0 33.28-4.621 65.485-13.251 96h-183.030c2.8-30.816 4.282-62.957 4.282-96 0-8.045-0.090-16.042-0.262-23.974l-64.534 64.534c-0.752 19.008-2.026 37.523-3.766 55.44h-51.674l-64 64h107.088c-7.37 42.458-17.488 80.083-29.45 111.184-12.822 33.338-26.522 55.926-38.474 69.069-8.397 9.235-13.43 11.29-14.928 11.699-1.498-0.41-6.531-2.464-14.928-11.699-11.952-13.142-25.654-35.731-38.477-69.069-7.178-18.662-13.69-39.677-19.344-62.669l-52 51.997c9.325 30.154 20.237 56.854 32.403 79.251-27.965-7.584-54.547-18.525-79.286-32.368l-46.746 46.746c63.347 39.146 137.984 61.77 217.901 61.859h0.954c229.53-0.259 415.523-186.41 415.523-416 0-80.096-22.637-154.902-61.859-218.377zM450.307 172.237c-113.552 30.788-204.312 116.98-241.467 227.763h179.675c10-93.226 32.176-173.252 61.792-227.763zM634.995 851.763c24.394-44.902 43.741-107.117 55.392-179.763h165.878c-44.653 87.35-124.723 153.584-221.27 179.763zM856.022 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672.001 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672.001-672z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["federation-disabled"],"defaultCode":59651,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1010,"id":98,"name":"federation-disabled","prevSize":32,"code":59651},"setIdx":0,"setId":6,"iconIdx":99},{"icon":{"paths":["M373.334 448c0-17.674 14.326-32 32-32h213.331c17.674 0 32 14.326 32 32s-14.326 32-32 32h-213.331c-17.674 0-32-14.326-32-32z","M405.334 544c-17.674 0-32 14.326-32 32s14.326 32 32 32h213.331c17.674 0 32-14.326 32-32s-14.326-32-32-32h-213.331z","M256 128c-17.673 0-32 14.327-32 32v704c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-501.744c0-6.672-2.083-13.174-5.962-18.602l-144.467-202.254c-6.006-8.409-15.706-13.4-26.038-13.4h-367.533zM736 372.509v459.491h-448v-640h319.066l128.934 180.509z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["file-document"],"defaultCode":59734,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1011,"name":"file-document","prevSize":32,"id":99,"code":59734},"setIdx":0,"setId":6,"iconIdx":100},{"icon":{"paths":["M128 192c-17.673 0-32 14.327-32 32v576.019c0 17.674 14.327 32 32 32h768c17.674 0 32-14.326 32-32v-576.019c0-17.673-14.326-32-32-32h-768zM160 378.301v-122.301h149.333v122.301h-149.333zM160 442.301h149.333v141.722h-149.333v-141.722zM160 648.022h149.333v119.997h-149.333v-119.997zM373.334 768.019v-119.997h490.666v119.997h-490.666zM864 584.022h-490.666v-141.722h490.666v141.722zM864 378.301h-490.666v-122.301h490.666v122.301z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["file-sheet"],"defaultCode":59735,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1012,"name":"file-sheet","prevSize":32,"id":100,"code":59735},"setIdx":0,"setId":6,"iconIdx":101},{"icon":{"paths":["M206.667 293.692c-30.421-42.402-0.116-101.442 52.070-101.442h518.572c51.174 0 81.706 57.026 53.334 99.615l-180.678 271.207v220.762c0 46.352-47.693 77.373-90.067 58.582l-121.424-53.85c-23.168-10.275-38.102-33.238-38.102-58.582v-166.304l-193.704-269.988zM777.309 256.334h-518.572l193.705 269.989c7.811 10.89 12.013 23.955 12.013 37.357v166.304l121.424 53.85v-220.762c0-12.646 3.741-25.008 10.752-35.533l180.678-271.205z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["filter"],"defaultCode":59736,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1013,"name":"filter","prevSize":32,"id":101,"code":59736},"setIdx":0,"setId":6,"iconIdx":102},{"icon":{"paths":["M623.091 896c-2.806 0-5.296-0.624-7.168-0.938-62-16.858-102.816-39.648-145.811-80.858-55.149-54.010-85.37-125.814-85.37-202.301 0-65.875 56.704-119.571 126.496-119.571s126.496 53.696 126.496 119.571c0 34.963 31.469 63.373 69.792 63.373s69.789-28.41 69.789-63.373c0-135.808-119.642-246.637-266.701-246.637-104.998 0-200.338 57.133-243.334 145.795-14.332 29.347-21.498 63.066-21.498 100.842 0 28.72 2.492 73.363 24.925 131.744 2.804 7.181 2.492 14.675-0.623 21.856-3.116 6.867-9.035 11.862-16.201 14.358-2.804 1.251-6.231 1.562-9.659 1.562-11.84 0-22.433-7.181-26.484-18.106-19.005-50.266-28.353-99.904-28.353-151.728 0-46.205 9.036-88.352 26.795-125.504 52.343-108.019 167.936-177.638 294.432-177.638 178.528 0 323.718 135.804 323.718 302.828 0 65.875-56.704 119.571-126.806 119.571s-126.81-53.696-126.81-119.571c0-34.963-31.469-63.373-69.792-63.373-38.634 0-69.789 28.41-69.789 63.373 0 61.504 24.301 119.261 68.544 162.342 35.206 34.029 68.858 53.072 120.576 67.123 7.168 1.872 13.398 6.557 17.136 13.11 3.741 6.557 4.675 14.362 2.806 21.229-2.806 11.866-14.022 20.918-27.107 20.918zM426.803 888.195c-7.789 0-15.267-3.123-20.253-8.742-33.338-32.781-51.718-54.010-77.891-100.525-26.795-47.142-41.127-105.21-41.127-167.338 0-116.448 100.948-211.357 224.951-211.357s224.954 94.909 224.954 211.357c0 15.61-12.464 28.096-28.352 28.096-15.891 0-28.666-12.173-28.666-28.096 0-85.542-75.398-155.162-168.246-155.162s-168.246 69.619-168.246 155.162c0 52.448 11.84 100.528 34.272 139.552 23.366 41.52 38.947 59.005 68.858 88.662 10.902 11.238 10.902 28.723 0 39.648-5.92 5.933-13.088 8.742-20.253 8.742zM699.738 818.886c-47.36 0-88.797-11.862-123.382-34.963-59.197-39.651-94.717-103.962-94.717-172.333 0-15.61 12.464-28.099 28.352-28.099 15.891 0 28.355 12.49 28.355 28.099 0 49.638 26.17 96.781 69.789 125.501 25.238 16.861 55.149 24.976 91.603 24.976 7.789 0 22.432-0.934 38.010-3.744 1.558-0.314 3.427-0.314 4.986-0.314 13.709 0 25.238 9.99 27.728 23.414 1.248 7.181-0.31 14.672-4.362 20.605-4.362 6.243-10.902 10.614-18.694 11.862-23.366 4.685-43.93 4.995-47.667 4.995zM188.765 435.824c-5.608 0-11.217-1.562-16.202-4.995-6.543-4.058-10.593-10.614-12.151-18.106-1.246-7.494 0.311-14.986 4.985-21.232 38.635-53.696 87.862-95.843 146.125-125.501 60.132-30.595 129.613-46.829 200.961-46.829 71.037 0 140.205 15.922 200.029 46.205 58.573 29.659 107.802 71.492 146.125 124.567 4.362 5.93 6.23 13.424 4.986 20.915-1.248 7.494-5.61 14.048-11.84 18.419-4.986 3.437-10.595 4.995-16.515 4.995-9.034 0-17.757-4.371-23.056-11.862-33.338-45.891-75.709-82.109-125.562-107.083-52.342-26.224-112.787-40.273-174.477-40.273-62.314 0-122.758 14.049-175.101 40.585-49.852 25.913-92.537 62.128-126.186 108.643-3.739 6.87-12.463 11.552-22.121 11.552zM733.696 239.141c-4.672 0-9.347-1.249-13.395-3.434-71.35-35.902-133.354-51.512-207.504-51.512-74.467 0-144.256 17.483-207.817 51.824-4.050 2.185-8.724 3.122-13.397 3.122-10.282 0-19.629-5.62-24.925-14.361-3.739-6.556-4.673-14.361-2.492-21.541s7.166-13.424 13.709-16.859c72.594-38.712 151.733-58.38 234.924-58.38 82.563 0 154.848 17.795 233.987 58.068 6.854 3.434 11.84 9.366 14.33 16.859 2.182 7.18 1.248 14.673-2.179 21.229-4.986 9.054-14.643 14.985-25.238 14.985z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["fingerprint"],"defaultCode":59737,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1014,"name":"fingerprint","prevSize":32,"id":102,"code":59737},"setIdx":0,"setId":6,"iconIdx":103},{"icon":{"paths":["M266.667 170.664c0-17.673 14.327-32 32-32h500.623c12.122 0 23.2 6.848 28.621 17.689s4.253 23.814-3.021 33.511l-122.134 162.843 122.134 162.845c7.274 9.696 8.442 22.672 3.021 33.51-5.421 10.842-16.499 17.69-28.621 17.69h-468.624v286.579c0 17.674-14.325 32-31.999 32s-32-14.326-32-32v-682.667zM330.666 502.752h404.624l-98.134-130.845c-8.531-11.376-8.531-27.021 0-38.4l98.134-130.843h-404.624v300.088z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["flag"],"defaultCode":59738,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1015,"name":"flag","prevSize":32,"id":103,"code":59738},"setIdx":0,"setId":6,"iconIdx":104},{"icon":{"paths":["M140.020 213.336c0-17.673 14.327-32 32-32h234.057c7.181 0 14.157 2.416 19.798 6.86l88.813 69.94h339.997c17.674 0 32 14.327 32 32v520.533c0 17.674-14.326 32-32 32h-682.665c-17.673 0-32-14.326-32-32v-597.333zM204.020 245.336v533.333h618.665v-456.534h-319.085c-7.181 0-14.154-2.415-19.798-6.858l-88.813-69.94h-190.969z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["folder"],"defaultCode":59739,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1016,"name":"folder","prevSize":32,"id":104,"code":59739},"setIdx":0,"setId":6,"iconIdx":105},{"icon":{"paths":["M370.704 544c0-17.674-14.326-32-32-32s-31.999 14.326-31.999 32v32h-32c-17.673 0-32 14.326-32 32s14.327 32 32 32h32v32c0 17.674 14.325 32 31.999 32s32-14.326 32-32v-32h32c17.674 0 32-14.326 32-32s-14.326-32-32-32h-32v-32z","M746.704 624c30.928 0 56-25.072 56-56s-25.072-56-56-56c-30.928 0-56 25.072-56 56s25.072 56 56 56z","M674.704 664c0 30.928-25.072 56-56 56s-56-25.072-56-56c0-30.928 25.072-56 56-56s56 25.072 56 56z","M706.704 128c0-17.673-14.326-32-32-32s-32 14.327-32 32v96h-128c-17.674 0-32 14.327-32 32v96h-191.999c-106.038 0-192 85.962-192 192v128c0 106.038 85.961 192 192 192h447.999c106.038 0 192-85.962 192-192v-128c0-106.038-85.962-192-192-192h-192v-64h128c17.674 0 32-14.327 32-32v-128zM866.704 544v128c0 70.691-57.306 128-128 128h-447.999c-70.692 0-128-57.309-128-128v-128c0-70.691 57.308-128 128-128h447.999c70.694 0 128 57.309 128 128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["game"],"defaultCode":59753,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1017,"name":"game","prevSize":32,"id":105,"code":59753},"setIdx":0,"setId":6,"iconIdx":106},{"icon":{"paths":["M494.31 170.648l23.037 24.005 23.629-24.005 74.669 0.041v75.854h74.669v75.856h74.666v26.518h0.003v504.419h-522.678v-682.689h252.006zM540.976 246.503h-224.004v530.979h373.341v-379.229h-149.338v-151.75z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["giphy-monochromatic"],"defaultCode":59754,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1018,"name":"giphy-monochromatic","prevSize":32,"id":106,"code":59754},"setIdx":0,"setId":6,"iconIdx":107},{"icon":{"paths":["M862.454 324.045c-35.2-60.31-82.944-108.057-143.248-143.253-60.314-35.198-126.16-52.792-197.581-52.792-71.414 0-137.28 17.6-197.581 52.792-60.31 35.194-108.053 82.943-143.253 143.253-35.194 60.307-52.792 126.166-52.792 197.571 0 85.77 25.024 162.899 75.086 231.405 50.056 68.509 114.721 115.917 193.989 142.224 9.229 1.712 16.058 0.509 20.499-3.584 4.442-4.096 6.662-9.226 6.662-15.37 0-1.024-0.090-10.246-0.259-27.674-0.176-17.43-0.259-32.637-0.259-45.61l-11.789 2.038c-7.517 1.379-16.998 1.962-28.445 1.795-11.443-0.16-23.322-1.357-35.619-3.587-12.304-2.211-23.747-7.334-34.342-15.366-10.588-8.029-18.104-18.538-22.547-31.514l-5.125-11.795c-3.416-7.853-8.795-16.573-16.142-26.134-7.348-9.571-14.778-16.058-22.294-19.475l-3.588-2.57c-2.391-1.706-4.61-3.766-6.662-6.154-2.050-2.39-3.585-4.781-4.61-7.174-1.027-2.397-0.176-4.365 2.562-5.907 2.738-1.539 7.685-2.288 14.864-2.288l10.247 1.53c6.834 1.37 15.287 5.462 25.371 12.298 10.078 6.835 18.363 15.715 24.856 26.646 7.863 14.013 17.335 24.688 28.445 32.038 11.101 7.347 22.294 11.014 33.568 11.014s21.011-0.854 29.216-2.557c8.192-1.709 15.882-4.275 23.062-7.69 3.075-22.902 11.446-40.499 25.11-52.797-19.475-2.045-36.982-5.13-52.534-9.226-15.542-4.106-31.603-10.765-48.173-20-16.579-9.222-30.331-20.672-41.262-34.333-10.932-13.67-19.905-31.613-26.904-53.818-7.003-22.214-10.505-47.837-10.505-76.88 0-41.35 13.5-76.541 40.493-105.584-12.645-31.088-11.451-65.939 3.585-104.55 9.908-3.079 24.606-0.768 44.078 6.916 19.478 7.689 33.738 14.275 42.797 19.736 9.059 5.46 16.317 10.087 21.786 13.837 31.782-8.88 64.582-13.322 98.406-13.322s66.63 4.442 98.416 13.322l19.475-12.295c13.318-8.204 29.046-15.722 47.142-22.556 18.112-6.83 31.958-8.712 41.53-5.633 15.37 38.612 16.739 73.46 4.093 104.548 26.992 29.046 40.496 64.243 40.496 105.587 0 29.043-3.514 54.746-10.506 77.13-7.002 22.387-16.051 40.314-27.152 53.818-11.114 13.501-24.957 24.864-41.526 34.083-16.573 9.226-32.637 15.888-48.179 19.99-15.552 4.102-33.059 7.187-52.534 9.238 17.763 15.37 26.646 39.632 26.646 72.774v108.134c0 6.141 2.134 11.27 6.41 15.37 4.272 4.090 11.018 5.296 20.243 3.581 79.28-26.304 143.946-73.712 194-142.224 50.048-68.502 75.082-145.632 75.082-231.405-0.019-71.395-17.626-137.248-52.803-197.555z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["github-monochromatic"],"defaultCode":59655,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1019,"name":"github-monochromatic","prevSize":32,"id":107,"code":59655},"setIdx":0,"setId":6,"iconIdx":108},{"icon":{"paths":["M133.618 423.61h215.092l-92.537-284.607c-4.74-14.67-25.504-14.67-30.244 0l-92.311 284.607zM86.899 567.171l46.72-143.546h737.133l46.72 143.546c4.288 13.088-0.451 27.533-11.51 35.434l-403.776 293.408-403.776-293.408c-11.060-7.901-15.799-22.346-11.511-35.434zM655.661 423.61h215.091l-92.31-284.607c-4.739-14.67-25.504-14.67-30.243 0l-92.538 284.607z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["gitlab-monochromatic"],"defaultCode":59656,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1020,"name":"gitlab-monochromatic","prevSize":32,"id":108,"code":59656},"setIdx":0,"setId":6,"iconIdx":109},{"icon":{"paths":["M226.9 260.289c6.691-2.875 13.811-4.319 20.961-4.288 17.673 0.077 32.062-14.187 32.14-31.86s-14.187-32.062-31.86-32.14c-15.989-0.070-31.8 3.167-46.506 9.485-14.702 6.317-27.969 15.571-39.071 27.156-11.1 11.582-19.822 25.269-25.729 40.238-5.898 14.946-8.889 30.916-8.834 47.005l-0.001 15.941 0.001-11.899v255.848c-0 0.074-0.001 0.15-0.001 0.224v89.6c0 43.642 16.497 85.792 46.318 117.104 29.872 31.366 70.73 49.296 113.682 49.296 42.954 0 83.811-17.93 113.683-49.296 29.821-31.312 46.317-73.462 46.317-117.104v-57.6h128v57.6c0 43.642 16.496 85.792 46.317 117.104 29.872 31.366 70.73 49.296 113.683 49.296s83.811-17.93 113.683-49.296c29.821-31.312 46.317-73.462 46.317-117.104v-89.6c0-0.077 0-0.15 0-0.227v-259.883c0.054-16.090-2.938-32.062-8.835-47.010-5.907-14.969-14.627-28.656-25.728-40.238-11.104-11.585-24.368-20.839-39.072-27.156-14.704-6.318-30.515-9.555-46.506-9.485-17.674 0.077-31.936 14.467-31.859 32.14s14.467 31.937 32.141 31.86c7.149-0.031 14.269 1.413 20.96 4.288 6.694 2.876 12.867 7.147 18.128 12.636 5.264 5.492 9.501 12.090 12.403 19.448 2.906 7.36 4.4 15.292 4.368 23.326v228.302h-639.999l0-228.173-0-0.128c-0.032-8.034 1.462-15.965 4.366-23.326 2.904-7.358 7.141-13.957 12.404-19.448 5.26-5.489 11.434-9.759 18.129-12.636zM269.255 608l104.214 104.214c6.826-14.237 10.531-30.173 10.531-46.614v-57.6h-114.745zM717.254 608l104.214 104.214c6.826-14.237 10.531-30.173 10.531-46.614v-57.6h-114.746zM896 315.89v0zM128.001 319.928l0-3.973-0-0.069v4.043zM328.954 758.208l-136.954-136.954v44.346c0 27.648 10.475 53.869 28.663 72.966 18.137 19.043 42.394 29.434 67.337 29.434 14.208 0 28.194-3.37 40.954-9.792zM640 665.6v-44.346l136.954 136.954c-12.758 6.422-26.746 9.792-40.954 9.792-24.944 0-49.2-10.39-67.338-29.434-18.189-19.098-28.662-45.318-28.662-72.966z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["glasses"],"defaultCode":59812,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1021,"id":109,"name":"glasses","prevSize":32,"code":59812},"setIdx":0,"setId":6,"iconIdx":110},{"icon":{"paths":["M634.803 170.664h-256.112l-264.387 460.802 124.984 221.866h534.916l124.982-221.866-264.384-460.802zM367.814 631.466l138.931-239.789 138.934 239.789h-277.866z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["google-drive-monochromatic"],"defaultCode":59756,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1022,"name":"google-drive-monochromatic","prevSize":32,"id":110,"code":59756},"setIdx":0,"setId":6,"iconIdx":111},{"icon":{"paths":["M658.794 338.154c-39.798-38.052-90.416-57.426-146.794-57.426-100.016 0-184.669 67.548-214.865 158.313l-0.002-0.003c-7.679 23.040-12.042 47.648-12.042 72.957s4.364 49.92 12.044 72.96l0 0.003c30.196 90.765 114.849 158.314 214.865 158.314 51.664 0 95.651-13.613 130.035-36.653v-0.016c40.669-27.229 67.725-67.898 76.627-115.898h-206.662v-148.538h361.658c4.538 25.136 6.982 51.315 6.982 78.547 0 116.944-41.891 215.389-114.502 282.24v0.013c-63.533 58.646-150.458 93.030-254.138 93.030-150.109 0-279.971-86.048-343.156-211.549l-0-0.003c-26.007-51.84-40.844-110.49-40.844-172.451 0-61.965 14.836-120.611 40.844-172.451h0.004c63.187-125.495 193.047-211.542 343.153-211.542 103.504 0 190.429 38.051 256.931 100.014l-110.138 110.139z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["google-monochromatic"],"defaultCode":59657,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1023,"name":"google-monochromatic","prevSize":32,"id":111,"code":59657},"setIdx":0,"setId":6,"iconIdx":112},{"icon":{"paths":["M129.354 272c0-17.673 14.327-32 32-32h704c17.674 0 32 14.327 32 32s-14.326 32-32 32h-704c-17.673 0-32-14.327-32-32zM289.354 432c0 17.674-14.327 32-32 32s-32-14.326-32-32c0-17.674 14.327-32 32-32s32 14.326 32 32zM289.354 752c0 17.674-14.327 32-32 32s-32-14.326-32-32c0-17.674 14.327-32 32-32s32 14.326 32 32zM449.354 624c17.674 0 32-14.326 32-32s-14.326-32-32-32c-17.674 0-32 14.326-32 32s14.326 32 32 32zM385.354 400c-17.674 0-32 14.326-32 32s14.326 32 32 32h480c17.674 0 32-14.326 32-32s-14.326-32-32-32h-480zM353.354 752c0-17.674 14.326-32 32-32h480c17.674 0 32 14.326 32 32s-14.326 32-32 32h-480c-17.674 0-32-14.326-32-32zM577.354 560c-17.674 0-32 14.326-32 32s14.326 32 32 32h288c17.674 0 32-14.326 32-32s-14.326-32-32-32h-288z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["group-by-type"],"defaultCode":59757,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1024,"name":"group-by-type","prevSize":32,"id":112,"code":59757},"setIdx":0,"setId":6,"iconIdx":113},{"icon":{"paths":["M170.668 245.336c0-17.673 14.327-32 32-32h640.846c17.674 0 32 14.327 32 32s-14.326 32-32 32h-640.846c-17.673 0-32-14.327-32-32zM170.668 501.334c0-17.67 14.327-32 32-32h640.846c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-640.846c-17.673 0-32-14.326-32-32zM170.668 757.334c0-17.67 14.327-32 32-32h640.846c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-640.846c-17.673 0-32-14.326-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["hamburguer"],"defaultCode":59758,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1025,"name":"hamburguer","prevSize":32,"id":113,"code":59758},"setIdx":0,"setId":6,"iconIdx":114},{"icon":{"paths":["M832 512c0 176.73-143.27 320-320 320s-320-143.27-320-320h-64c0 212.077 171.923 384 384 384s384-171.923 384-384c0-212.077-171.923-384-384-384-123.718 0-233.772 58.508-304 149.364v-101.364c0-17.673-14.327-32-32-32s-32 14.327-32 32v192c0 17.674 14.327 32 32 32h176c17.674 0 32-14.326 32-32s-14.326-32-32-32h-107.295c57.24-86.756 155.583-144 267.295-144 176.73 0 320 143.27 320 320z","M544 320c0-17.673-14.326-32-32-32s-32 14.327-32 32v224c0 8.486 3.373 16.627 9.373 22.627l96 96c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-86.627-86.627v-210.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["history"],"defaultCode":59759,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1026,"name":"history","prevSize":32,"id":114,"code":59759},"setIdx":0,"setId":6,"iconIdx":115},{"icon":{"paths":["M522.042 195.354l224.464 260.044v366.234c0 5.856-4.752 10.605-10.614 10.605h-136.416v-149.821c0-23.424-19.014-42.413-42.47-42.413h-85.955c-23.453 0-42.467 18.989-42.467 42.413v149.821h-136.41c-5.864 0-10.617-4.749-10.617-10.605v-366.307l224.403-259.971c4.237-4.907 11.85-4.907 16.083 0zM560.57 895.856h175.322c41.043 0 74.32-33.232 74.32-74.224v-244.205h56.227c12.454 0 23.766-7.251 28.954-18.557 5.19-11.309 3.302-24.602-4.829-34.022l-320.272-371.033c-29.648-34.347-82.934-34.347-112.582 0l-320.27 371.033c-8.132 9.421-10.020 22.714-4.831 34.022 5.188 11.306 16.501 18.557 28.956 18.557h56.288v244.205c0 40.992 33.274 74.224 74.32 74.224h175.316c1.174 0.096 2.362 0.147 3.562 0.147h85.955c1.2 0 2.39-0.051 3.565-0.147z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["home"],"defaultCode":59760,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1027,"name":"home","prevSize":32,"id":115,"code":59760},"setIdx":0,"setId":6,"iconIdx":116},{"icon":{"paths":["M864 512c0-86.89-31.482-166.429-83.664-227.826l-496.162 496.162c61.397 52.182 140.937 83.664 227.826 83.664 194.403 0 352-157.597 352-352zM239.349 734.65l495.3-495.3c-60.662-49.597-138.182-79.349-222.65-79.349-194.404 0-352 157.596-352 352 0 84.467 29.753 161.987 79.349 222.65zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["ignore"],"defaultCode":59740,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1028,"name":"ignore","prevSize":32,"id":116,"code":59740},"setIdx":0,"setId":6,"iconIdx":117},{"icon":{"paths":["M406.685 405.334c0 47.126-38.205 85.331-85.334 85.331-47.127 0-85.332-38.205-85.332-85.331 0-47.13 38.205-85.334 85.332-85.334 47.13 0 85.334 38.205 85.334 85.334z","M97.352 192c0-17.673 14.327-32 32-32h767.999c17.674 0 32 14.327 32 32v640c0 17.674-14.326 32-32 32h-767.999c-17.673 0-32-14.326-32-32v-640zM161.352 764.163l151.704-176.989c9.271-10.813 24.57-14.202 37.536-8.307l153.123 69.603 160.474-204.24c6.010-7.651 15.174-12.15 24.902-12.23s18.963 4.272 25.098 11.821l151.162 186.048v-405.869h-703.999v540.163zM214.927 800h650.423v-68.64l-175.581-216.099-166.781 212.269-176.989-80.448-131.073 152.918z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["image"],"defaultCode":59761,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1029,"name":"image","prevSize":32,"id":117,"code":59761},"setIdx":0,"setId":6,"iconIdx":118},{"icon":{"paths":["M512 873.027c-199.389 0-361.026-161.635-361.026-361.024s161.636-361.026 361.026-361.026c199.389 0 361.024 161.637 361.024 361.026s-161.635 361.024-361.024 361.024zM512 938.669c235.642 0 426.666-191.024 426.666-426.666s-191.024-426.667-426.666-426.667c-235.642 0-426.667 191.025-426.667 426.667s191.025 426.666 426.667 426.666zM544.819 347.901c0 18.125-14.694 32.819-32.819 32.819-18.128 0-32.822-14.694-32.822-32.819 0-18.128 14.694-32.821 32.822-32.821 18.125 0 32.819 14.693 32.819 32.821zM512 413.542c-18.128 0-32.822 14.694-32.822 32.819v229.744c0 18.125 14.694 32.819 32.822 32.819 18.125 0 32.819-14.694 32.819-32.819v-229.744c0-18.125-14.694-32.819-32.819-32.819z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["info"],"defaultCode":59762,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1030,"name":"info","prevSize":32,"id":118,"code":59762},"setIdx":0,"setId":6,"iconIdx":119},{"icon":{"paths":["M512 864c-194.404 0-352-157.597-352-352s157.596-352 352-352c194.403 0 352 157.596 352 352s-157.597 352-352 352zM512 928c229.75 0 416-186.25 416-416s-186.25-416-416-416c-229.75 0-416 186.25-416 416s186.25 416 416 416zM662.627 361.373c12.496 12.496 12.496 32.758 0 45.254l-105.373 105.373 105.373 105.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-105.373-105.373-105.373 105.373c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l105.373-105.373-105.373-105.373c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l105.373 105.373 105.373-105.373c12.496-12.496 32.758-12.496 45.254 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["input-clear"],"defaultCode":59763,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1031,"name":"input-clear","prevSize":32,"id":119,"code":59763},"setIdx":0,"setId":6,"iconIdx":120},{"icon":{"paths":["M384 288c-17.674 0-32 14.327-32 32s14.326 32 32 32h256c17.674 0 32-14.326 32-32s-14.326-32-32-32h-256z","M352 448c0-17.674 14.326-32 32-32h256c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M512 640c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M224 224v576c0 35.347 28.654 64 64 64h448c35.347 0 64-28.653 64-64v-576c0-35.346-28.653-64-64-64h-448c-35.346 0-64 28.654-64 64zM288 800v-576h448v576h-448z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["instance"],"defaultCode":59764,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1032,"name":"instance","prevSize":32,"id":120,"code":59764},"setIdx":0,"setId":6,"iconIdx":121},{"icon":{"paths":["M563.59 255.992l-170.669 512.001h-136.941c-17.673 0-32 14.326-32 32 0 17.67 14.327 32 32 32h320c17.674 0 32-14.33 32-32 0-17.674-14.326-32-32-32h-115.597l170.669-512.001h136.928c17.674 0 32-14.327 32-32s-14.326-32-32-32h-159.002c-0.666-0.021-1.328-0.021-1.99 0h-159.008c-17.674 0-32 14.327-32 32s14.326 32 32 32h115.61z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["italic"],"defaultCode":59765,"grid":0},"attrs":[{}],"properties":{"order":1033,"name":"italic","prevSize":32,"id":121,"code":59765},"setIdx":0,"setId":6,"iconIdx":122},{"icon":{"paths":["M497.136 169.372c12.499 12.497 12.499 32.758 0 45.255l-35.958 35.96c1.078-0.016 2.163-0.025 3.245-0.025h191.152c115.11 0 208.426 93.316 208.426 208.426 0 115.107-93.315 208.422-208.426 208.422h-15.574v-64h15.574c79.763 0 144.426-64.659 144.426-144.422 0-79.766-64.662-144.426-144.426-144.426h-191.152c-1.030 0-2.058 0.011-3.082 0.032l35.795 35.796c12.499 12.499 12.499 32.758 0 45.258-12.496 12.496-32.758 12.496-45.254 0l-90.509-90.511c-12.496-12.497-12.496-32.758 0-45.255l90.509-90.51c12.496-12.497 32.758-12.497 45.254 0zM201.318 500.746h56.159v325.818h-59.023v-268.387h-1.909l-76.204 48.682v-54.090l80.977-52.022zM570.41 719.494c0 64.749-48.045 111.523-116.931 111.523-63.638 0-110.886-38.979-112.48-93.069h57.274c2.070 26.726 25.773 45.341 55.206 45.341 34.838 0 59.978-25.933 59.818-62.365 0.16-36.909-25.613-63.318-61.411-63.475-19.568-0.16-40.25 7.955-51.226 20.045l-53.296-8.749 17.024-168h188.998v49.318h-140.16l-9.386 86.384h1.91c12.090-14.317 35.475-24.816 61.885-24.816 59.184 0 102.774 45.181 102.774 107.862z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-backward"],"defaultCode":59766,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1034,"name":"jump-backward","prevSize":32,"id":122,"code":59766},"setIdx":0,"setId":6,"iconIdx":123},{"icon":{"paths":["M494.861 169.372c-12.496 12.497-12.496 32.758 0 45.255l35.962 35.96c-1.082-0.016-2.163-0.025-3.248-0.025h-191.149c-115.111 0-208.426 93.316-208.426 208.426 0 115.107 93.315 208.422 208.426 208.422h15.574v-64h-15.574c-79.764 0-144.426-64.659-144.426-144.422 0-79.766 64.661-144.426 144.426-144.426h191.149c1.030 0 2.061 0.011 3.085 0.032l-35.798 35.796c-12.496 12.499-12.496 32.758 0 45.258 12.499 12.496 32.758 12.496 45.258 0l90.509-90.511c12.496-12.497 12.496-32.758 0-45.255l-90.509-90.51c-12.499-12.497-32.758-12.497-45.258 0zM521.318 500.746h56.157v325.818h-59.021v-268.387h-1.91l-76.205 48.682v-54.090l80.979-52.022zM890.41 719.494c0 64.749-48.048 111.523-116.934 111.523-63.635 0-110.886-38.979-112.477-93.069h57.274c2.067 26.726 25.773 45.341 55.203 45.341 34.842 0 59.978-25.933 59.821-62.365 0.157-36.909-25.616-63.318-61.411-63.475-19.568-0.16-40.25 7.955-51.226 20.045l-53.296-8.749 17.021-168h189.002v49.318h-140.16l-9.386 86.384h1.91c12.090-14.317 35.475-24.816 61.885-24.816 59.181 0 102.774 45.181 102.774 107.862z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-forward"],"defaultCode":59767,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1035,"name":"jump-forward","prevSize":32,"id":123,"code":59767},"setIdx":0,"setId":6,"iconIdx":124},{"icon":{"paths":["M769.296 649.373c12.496 12.496 12.496 32.758 0 45.254l-192 192c-12.499 12.496-32.758 12.496-45.258 0l-192-192c-12.496-12.496-12.496-32.758 0-45.254 12.499-12.496 32.758-12.496 45.258 0l137.37 137.373v-578.746h-192v192c0 17.674-14.325 32-31.999 32s-32-14.326-32-32v-224c0-17.673 14.327-32 32-32h255.999c17.674 0 32 14.327 32 32v610.746l137.373-137.373c12.499-12.496 32.758-12.496 45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-to-message"],"defaultCode":59768,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1036,"name":"jump-to-message","prevSize":32,"id":124,"code":59768},"setIdx":0,"setId":6,"iconIdx":125},{"icon":{"paths":["M576 256c0 35.346-28.653 64-64 64s-64-28.654-64-64c0-35.346 28.653-64 64-64s64 28.654 64 64z","M576 512c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64z","M576 768c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["kebab"],"defaultCode":59769,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1037,"name":"kebab","prevSize":32,"id":125,"code":59769},"setIdx":0,"setId":6,"iconIdx":126},{"icon":{"paths":["M160 224c-35.346 0-64 28.654-64 64v448c0 35.347 28.654 64 64 64h704c35.347 0 64-28.653 64-64v-448c0-35.346-28.653-64-64-64h-704zM160 288h704v448h-704v-448zM256 352c-17.673 0-32 14.326-32 32s14.327 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM256 512c0-17.674 14.327-32 32-32h64c17.674 0 32 14.326 32 32s-14.326 32-32 32h-64c-17.673 0-32-14.326-32-32zM480 480c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM640 512c0-17.674 14.326-32 32-32h64c17.674 0 32 14.326 32 32s-14.326 32-32 32h-64c-17.674 0-32-14.326-32-32zM480 352c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM320 640c0-17.674 14.326-32 32-32h320c17.674 0 32 14.326 32 32s-14.326 32-32 32h-320c-17.674 0-32-14.326-32-32zM704 352c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["keyboard"],"defaultCode":59770,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1038,"name":"keyboard","prevSize":32,"id":126,"code":59770},"setIdx":0,"setId":6,"iconIdx":127},{"icon":{"paths":["M505.133 128.078c60.819-1.376 120.422 15.569 170.346 48.251 49.904 32.67 87.501 79.327 107.75 133.159 20.24 53.808 22.205 112.266 5.648 167.165-16.554 54.89-50.864 103.683-98.368 139.309-15.501 11.462-28.189 26.246-36.989 43.309-8.822 17.107-13.469 36-13.507 55.216v21.514h-96.013v-148.774l120.989-151.235c11.040-13.802 8.803-33.939-4.998-44.979s-33.939-8.803-44.979 4.998l-103.011 128.765-103.011-128.765c-11.040-13.802-31.178-16.038-44.979-4.998s-16.038 31.178-4.998 44.979l120.989 151.235v148.774h-95.994v-21.677c-0.138-19.030-4.762-37.728-13.462-54.691-8.694-16.954-21.21-31.69-36.509-43.194l-19.229 25.578 19.069-25.696c-34.247-25.418-61.857-57.84-80.845-94.736-18.985-36.89-28.886-77.331-29.027-118.285v-0.045c-0.71-146.981 123.709-271.715 281.13-275.177zM640.013 800c16.506 0 32.618-6.243 44.72-17.795 12.157-11.603 19.28-27.664 19.28-44.746v-22.842c0.022-8.947 2.182-17.856 6.39-26.016 4.214-8.176 10.406-15.459 18.208-21.216l0.192-0.144c58.173-43.59 100.733-103.75 121.35-172.109 20.621-68.378 18.154-141.245-7.021-208.177-25.168-66.908-71.664-124.28-132.602-164.174-60.915-39.878-133.274-60.348-206.826-58.689-189.76 4.184-344.567 155.060-343.702 339.427l0 0.045 32-0.154-32 0.109c0.176 51.165 12.553 101.558 36.121 147.35 23.547 45.754 57.616 85.658 99.521 116.774 7.682 5.792 13.781 13.062 17.952 21.194 4.164 8.122 6.33 16.944 6.409 25.84v22.781c0 17.082 7.123 33.142 19.28 44.746 12.106 11.552 28.218 17.795 44.72 17.795h256.006zM352 864c-17.674 0-32 14.326-32 32s14.326 32 32 32h320c17.674 0 32-14.326 32-32s-14.326-32-32-32h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["lamp-bulb"],"defaultCode":59836,"grid":0},"attrs":[{}],"properties":{"order":1039,"id":127,"name":"lamp-bulb","prevSize":32,"code":59836},"setIdx":0,"setId":6,"iconIdx":128},{"icon":{"paths":["M681.904 256c0-17.673-14.326-32-32-32s-32 14.327-32 32v56.875l-80.346 13.998c-17.411 3.034-29.069 19.61-26.035 37.021 3.034 17.408 19.61 29.066 37.021 26.032l69.36-12.086v69.373c-30.384 6.851-60.461 20.074-84.154 43.139-27.923 27.184-44.070 65.238-44.070 113.808 0 25.741 6.262 48.262 18.451 66.621 12.186 18.349 29.062 30.682 47.251 38 35.357 14.221 76.72 10.173 108.128-4.579l1.206-0.566c31.126-14.621 62.493-29.354 90.723-57.818 21.325-21.507 39.709-49.539 56.848-88.678 5.654 9.498 9.594 20.966 10.285 34.339 1.632 31.526-14.275 82.813-87.955 153.418-12.758 12.227-13.19 32.483-0.963 45.245 12.227 12.758 32.486 13.19 45.245 0.963 80.192-76.851 110.586-145.034 107.59-202.934-2.986-57.658-38.586-96.022-70.675-113.955-20.774-13.014-50.214-22.826-81.216-28.288-16.624-2.931-34.47-4.749-52.694-4.995v-74.243l101.718-17.722c17.411-3.034 29.066-19.61 26.032-37.019-3.034-17.411-19.606-29.066-37.018-26.032l-90.733 15.809v-45.724zM578.394 536.208c10.163-9.891 23.565-17.475 39.51-22.704v138.653c-13.443 2.547-27.485 1.731-38.634-2.752-7.712-3.104-13.658-7.757-17.824-14.029-4.157-6.262-7.766-15.997-7.766-31.216 0-33.35 10.563-54.176 24.714-67.952zM709.994 600.752c-8.682 8.755-17.782 15.706-28.090 22.074v-117.888c14.125 0.24 28.224 1.661 41.587 4.016 13.587 2.397 25.683 5.622 35.763 9.165-16.88 42.038-33.069 66.304-49.261 82.634zM247.704 565.334h98.386l-49.193-184.883-49.193 184.883zM390.851 733.562l-27.734-104.227h-132.442l-27.732 104.227c-4.544 17.078-22.073 27.242-39.152 22.694-17.079-4.544-27.24-22.070-22.696-39.152l106.323-399.598c13.494-50.714 85.462-50.713 98.956 0l106.323 399.598c4.544 17.082-5.616 34.608-22.694 39.152-17.078 4.547-34.608-5.616-39.152-22.694z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["language"],"defaultCode":59771,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1040,"name":"language","prevSize":32,"id":128,"code":59771},"setIdx":0,"setId":6,"iconIdx":129},{"icon":{"paths":["M234.831 743.917c-75.198-141.606-58.197-285.718 40.507-391.734 101.776-109.314 284.915-172.318 524.636-158.217 16.192 0.953 29.114 13.872 30.064 30.066 14.102 239.723-48.902 422.859-158.218 524.635-106.016 98.707-250.128 115.706-391.737 40.506l-65.457 65.456c-12.497 12.499-32.758 12.499-45.255 0-12.497-12.496-12.497-32.758 0-45.254l65.458-65.456zM282.51 696.237l300.107-300.109c12.496-12.496 32.758-12.496 45.254 0 12.496 12.499 12.496 32.758 0 45.258l-300.109 300.106c113.565 53.238 220.73 34.554 300.448-39.664 86.579-80.611 146.157-231.866 139.251-445.286-213.418-6.905-364.675 52.673-445.283 139.254-74.219 79.715-92.904 186.877-39.669 300.442z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["leaf"],"defaultCode":59814,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1041,"id":129,"name":"leaf","prevSize":32,"code":59814},"setIdx":0,"setId":6,"iconIdx":130},{"icon":{"paths":["M254.841 275.612l-13.972 14.271c-37.092 37.883-36.449 98.664 1.435 135.758l145.619 142.573c37.885 37.091 98.666 36.448 135.76-1.437l13.971-14.269c0.723-0.739 1.43-1.488 2.128-2.243l0.099 0.099c5.805-5.904 13.888-9.568 22.822-9.568 17.674 0 32 14.326 32 32 0 9.6-4.227 18.211-10.922 24.077l-0.397 0.41-13.974 14.269c-61.818 63.142-163.12 64.214-226.259 2.394l-145.622-142.576c-63.141-61.818-64.212-163.119-2.392-226.26l13.972-14.27c61.82-63.141 163.12-64.212 226.263-2.392l74.691 73.131c0.976 0.847 1.901 1.752 2.768 2.71l0.374 0.366-0.026 0.026c4.934 5.63 7.923 13.005 7.923 21.078 0 17.674-14.326 32-32 32-7.83 0-15.005-2.813-20.566-7.482l-0.106 0.109-77.834-76.206c-37.885-37.092-98.666-36.45-135.757 1.435zM790.566 768.003l13.971-14.269c37.091-37.885 36.448-98.666-1.437-135.757l-145.619-142.576c-37.885-37.091-98.666-36.448-135.757 1.437l-13.971 14.269c-0.723 0.739-1.434 1.488-2.128 2.243l-0.102-0.099c-5.805 5.907-13.885 9.568-22.822 9.568-17.67 0-32-14.326-32-32 0-9.6 4.227-18.211 10.922-24.077l0.4-0.406 13.971-14.272c61.821-63.142 163.12-64.211 226.262-2.39l145.619 142.573c63.142 61.821 64.211 163.12 2.394 226.262l-13.971 14.269c-61.821 63.142-163.123 64.211-226.262 2.394l-74.694-73.133c-0.976-0.845-1.901-1.75-2.768-2.71l-0.374-0.365 0.026-0.026c-4.931-5.629-7.923-13.005-7.923-21.078 0-17.674 14.326-32 32-32 7.83 0 15.005 2.813 20.566 7.482l0.106-0.109 77.837 76.208c37.885 37.091 98.662 36.448 135.757-1.437z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["link"],"defaultCode":59752,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1042,"name":"link","prevSize":32,"id":130,"code":59752},"setIdx":0,"setId":6,"iconIdx":131},{"icon":{"paths":["M840.541 128c31.318 0 56.813 24.79 56.813 55.383v657.212c0 30.592-25.494 55.427-56.813 55.427h-654.546c-31.254 0-56.642-24.835-56.642-55.427v-657.212c0-30.593 25.387-55.383 56.642-55.383h654.546zM300.196 233.75c-36.588 0-66.093 29.59-66.093 66.050 0 36.482 29.505 66.072 66.093 66.072 36.437 0 66.005-29.59 66.005-66.072 0-36.46-29.568-66.050-66.005-66.050zM243.148 782.461h114.029v-366.515h-114.029v366.515zM537.814 415.923h-109.187v366.515h113.773v-181.274c0-47.83 9.046-94.147 68.333-94.147 58.454 0 59.181 54.678 59.181 97.174v178.246h113.901v-201.008c0-98.714-21.312-174.598-136.666-174.598-55.402 0-92.566 30.381-107.757 59.203h-1.578v-50.112z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["linkedin-monochromatic"],"defaultCode":59658,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1043,"name":"linkedin-monochromatic","prevSize":32,"id":131,"code":59658},"setIdx":0,"setId":6,"iconIdx":132},{"icon":{"paths":["M700.144 361.891c4.685-24.973 34.704-34.093 49.13-13.171 31.994 46.403 50.726 102.653 50.726 163.28s-18.733 116.88-50.726 163.283c-14.426 20.922-44.445 11.802-49.13-13.174l-1.706-9.101c-1.581-8.429 0.384-17.082 4.858-24.403 20.749-33.965 32.704-73.888 32.704-116.605 0-42.714-11.955-82.637-32.704-116.605-4.474-7.318-6.438-15.971-4.858-24.4l1.706-9.104z","M320.704 395.395c-20.748 33.968-32.704 73.891-32.704 116.605 0 42.717 11.956 82.64 32.704 116.605 4.474 7.322 6.438 15.974 4.858 24.403l-1.706 9.101c-4.684 24.976-34.705 34.096-49.128 13.174-31.994-46.403-50.728-102.656-50.728-163.283s18.733-116.877 50.728-163.28c14.424-20.922 44.444-11.802 49.128 13.171l1.706 9.104c1.581 8.429-0.384 17.082-4.858 24.4z","M728.765 209.256l-0.515 2.747c-2.234 11.911 2.534 23.967 11.763 31.821 75.866 64.565 123.987 160.751 123.987 268.175 0 107.427-48.122 203.613-123.987 268.176-9.229 7.856-13.997 19.914-11.763 31.824l0.515 2.746c4.192 22.362 29.69 33.194 47.261 18.746 92.794-76.294 151.974-191.981 151.974-321.491 0-129.507-59.181-245.193-151.974-321.489-17.571-14.448-43.069-3.615-47.261 18.745z","M283.986 243.825c9.228-7.854 13.998-19.911 11.764-31.821l-0.515-2.747c-4.192-22.359-29.69-33.193-47.262-18.745-92.793 76.296-151.973 191.981-151.973 321.489 0 129.51 59.18 245.197 151.973 321.491 17.572 14.448 43.070 3.616 47.262-18.746l0.515-2.746c2.233-11.91-2.536-23.968-11.764-31.824-75.864-64.563-123.986-160.749-123.986-268.176 0-107.424 48.122-203.61 123.986-268.175z","M608 512c0 53.021-42.979 96-96 96s-96-42.979-96-96c0-53.018 42.979-96 96-96s96 42.982 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["live"],"defaultCode":59774,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1044,"name":"live","prevSize":32,"id":132,"code":59774},"setIdx":0,"setId":6,"iconIdx":133},{"icon":{"paths":["M439.274 704.374c0-33.645 26.278-47.677 72.726-47.677s72.73 14.032 72.73 47.677c0 32.96-13.19 111.069-23.914 149.76-4.963 17.808-22.080 25.171-48.816 25.171s-43.85-7.363-48.813-25.174c-10.717-38.666-23.914-116.688-23.914-149.757zM616.778 870.374l0.026-0.090c6.176-22.291 12.566-53.869 17.386-83.453 4.688-28.787 8.72-60.707 8.72-82.458 0-35.891-15.811-67.802-46.797-87.114-26.035-16.227-57.152-19.926-84.112-19.926-26.957 0-58.077 3.699-84.112 19.926-30.982 19.312-46.797 51.222-46.797 87.114 0 21.805 4.035 53.728 8.726 82.515 4.819 29.578 11.21 61.123 17.379 83.392l0.026 0.086c7.402 26.557 24.982 45.664 46.87 56.467 19.472 9.61 40.426 11.834 57.907 11.834 17.485 0 38.435-2.224 57.907-11.83 21.888-10.8 39.469-29.907 46.87-56.464zM459.635 460.8c0-28.275 23.446-51.2 52.365-51.2s52.365 22.925 52.365 51.2c0 28.278-23.446 51.2-52.365 51.2s-52.365-22.922-52.365-51.2zM512 341.334c-67.478 0-122.182 53.488-122.182 119.466 0 65.981 54.704 119.469 122.182 119.469s122.182-53.488 122.182-119.469c0-65.978-54.704-119.466-122.182-119.466zM677.802 537.254c-6.662 13.792-3.882 31.11 6.278 42.573 14.086 15.894 39.85 17.939 50.205-0.602 19.642-35.174 30.806-75.526 30.806-118.426 0-136.672-113.315-247.465-253.091-247.465-139.779 0-253.092 110.793-253.092 247.465 0 42.899 11.164 83.251 30.806 118.426 10.354 18.541 36.119 16.496 50.205 0.602 10.16-11.462 12.938-28.781 6.275-42.573-11.203-23.187-17.469-49.104-17.469-76.454 0-98.97 82.054-179.199 183.274-179.199s183.27 80.229 183.27 179.199c0 27.35-6.262 53.267-17.469 76.454zM730.16 699.795c-0.304-10.659 3.542-21.072 10.928-28.762 52.771-54.957 85.094-128.902 85.094-210.234 0-169.661-140.666-307.199-314.182-307.199s-314.182 137.538-314.182 307.199c0 81.331 32.323 155.28 85.093 210.234 7.386 7.69 11.234 18.102 10.928 28.762-0.833 29.018-31.273 47.917-52.121 27.715-70.223-68.042-113.718-162.41-113.718-266.71 0-207.363 171.923-375.465 384-375.465s384 168.102 384 375.465c0 104.304-43.498 198.672-113.722 266.714-20.848 20.202-51.286 1.302-52.118-27.718z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["live-streaming"],"defaultCode":59773,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1045,"name":"live-streaming","prevSize":32,"id":133,"code":59773},"setIdx":0,"setId":6,"iconIdx":134},{"icon":{"paths":["M397.011 527.334c26.576 0 48.122-21.587 48.122-48.214s-21.546-48.214-48.122-48.214c-26.576 0-48.118 21.587-48.118 48.214s21.542 48.214 48.118 48.214z","M589.491 479.12c0 26.627-21.542 48.214-48.118 48.214s-48.122-21.587-48.122-48.214c0-26.627 21.546-48.214 48.122-48.214s48.118 21.587 48.118 48.214z","M733.853 479.12c0 26.627-21.542 48.214-48.118 48.214s-48.122-21.587-48.122-48.214c0-26.627 21.546-48.214 48.122-48.214s48.118 21.587 48.118 48.214z","M88.039 813.683l119.625 31.283c85.312 22.307 173.45-16.256 238.691-79.709 29.501 4.794 59.875 7.242 90.678 7.242 218.294 0 404.339-122.864 404.339-294.518 0-171.664-186.042-294.52-404.339-294.52-218.314 0-404.351 122.852-404.34 294.523 0 65.072 27.642 125.014 75.655 173.587-2.847 24.835-14.596 44.73-36.049 68.55l-84.261 93.562zM537.034 258.997c183.13 0 331.6 98.043 331.6 218.984 0 120.931-148.47 218.982-331.6 218.982-40.781 0-79.834-4.877-115.91-13.763-36.669 45.6-117.335 109.008-195.697 88.518 25.489-28.304 63.251-76.131 55.168-154.909-46.968-37.779-75.162-86.134-75.162-138.829-0.008-120.95 148.461-218.984 331.6-218.984z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["livechat-monochromatic"],"defaultCode":59775,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1046,"name":"livechat-monochromatic","prevSize":32,"id":134,"code":59775},"setIdx":0,"setId":6,"iconIdx":135},{"icon":{"paths":["M512 128c-97.203 0-176 78.798-176 176v142.477h-16c-53.020 0-96 42.979-96 96v257.523c0 53.021 42.981 96 96 96h384c53.021 0 96-42.979 96-96v-257.523c0-53.021-42.979-96-96-96h-16v-142.477c0-97.202-78.797-176-176-176zM624 304v142.477h-224v-142.477c0-61.856 50.144-112 112-112s112 50.144 112 112z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["lock-filled"],"defaultCode":59748,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1047,"name":"lock-filled","prevSize":32,"id":135,"code":59748},"setIdx":0,"setId":6,"iconIdx":136},{"icon":{"paths":["M336 304c0-97.202 78.797-176 176-176s176 78.798 176 176v142.477h16c53.021 0 96 42.979 96 96v257.523c0 53.021-42.979 96-96 96h-384c-53.019 0-96-42.979-96-96v-257.523c0-53.021 42.981-96 96-96h16v-142.477zM400 446.477h224v-142.477c0-61.856-50.144-112-112-112s-112 50.144-112 112v142.477zM320 510.477c-17.673 0-32 14.326-32 32v257.523c0 17.674 14.327 32 32 32h384c17.674 0 32-14.326 32-32v-257.523c0-17.674-14.326-32-32-32h-384z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["locker"],"defaultCode":59749,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1048,"name":"locker","prevSize":32,"id":136,"code":59749},"setIdx":0,"setId":6,"iconIdx":137},{"icon":{"paths":["M341.334 778.672c-17.674 0-32 14.326-32 32s14.326 32 32 32h341.334c17.674 0 32-14.326 32-32s-14.326-32-32-32h-341.334zM85.335 298.672c0-70.692 57.308-128 128-128h597.334c70.691 0 128 57.308 128 128v298.666c0 70.694-57.309 128-128 128h-597.334c-70.692 0-128-57.306-128-128v-298.666zM213.335 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.347 28.654 64 64 64h597.334c35.344 0 64-28.653 64-64v-298.666c0-35.347-28.656-64-64-64h-597.334zM256 320c0-11.782 9.551-21.333 21.333-21.333h170.667c11.782 0 21.334 9.551 21.334 21.333s-9.552 21.334-21.334 21.334h-170.667c-11.782 0-21.333-9.552-21.333-21.334zM277.333 554.666c-11.782 0-21.333 9.552-21.333 21.334s9.551 21.334 21.333 21.334h85.332c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-85.332zM554.666 320c0-11.782 9.552-21.333 21.334-21.333h170.666c11.782 0 21.334 9.551 21.334 21.333s-9.552 21.334-21.334 21.334h-170.666c-11.782 0-21.334-9.552-21.334-21.334zM448 554.666c-11.782 0-21.334 9.552-21.334 21.334s9.552 21.334 21.334 21.334h298.666c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-298.666zM256 448c0-11.782 9.551-21.334 21.333-21.334h213.332c11.782 0 21.334 9.552 21.334 21.334s-9.552 21.334-21.334 21.334h-213.332c-11.782 0-21.333-9.552-21.333-21.334zM618.666 426.666c-11.782 0-21.331 9.552-21.331 21.334s9.549 21.334 21.331 21.334h128c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["log-view"],"defaultCode":59778,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1049,"name":"log-view","prevSize":32,"id":137,"code":59778},"setIdx":0,"setId":6,"iconIdx":138},{"icon":{"paths":["M176 96c-17.673 0-32 14.327-32 32v768c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-96c0-17.674-14.326-32-32-32s-32 14.326-32 32v64h-448v-704h448v64c0 17.673 14.326 32 32 32s32-14.327 32-32v-96c0-17.673-14.326-32-32-32h-512zM521.373 329.373c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.254l-105.373 105.373h418.746c17.674 0 32 14.326 32 32s-14.326 32-32 32h-418.746l105.373 105.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-160-160c-12.496-12.496-12.496-32.758 0-45.254l160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["login"],"defaultCode":59779,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1050,"name":"login","prevSize":32,"id":138,"code":59779},"setIdx":0,"setId":6,"iconIdx":139},{"icon":{"paths":["M268.099 96c-17.673 0-32 14.327-32 32v768c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-96c0-17.674-14.326-32-32-32s-32 14.326-32 32v64h-448v-704h448v64c0 17.673 14.326 32 32 32s32-14.327 32-32v-96c0-17.673-14.326-32-32-32h-512zM994.726 489.373l-160-160c-12.496-12.497-32.758-12.497-45.254 0s-12.496 32.758 0 45.254l105.373 105.373h-418.746c-17.674 0-32 14.326-32 32s14.326 32 32 32h418.746l-105.373 105.373c-12.496 12.496-12.496 32.758 0 45.254s32.758 12.496 45.254 0l160-160c12.496-12.496 12.496-32.758 0-45.254z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["logout"],"defaultCode":59780,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1051,"name":"logout","prevSize":32,"id":139,"code":59780},"setIdx":0,"setId":6,"iconIdx":140},{"icon":{"paths":["M192 736h640v-448h-640v448zM128 256c0-17.673 14.327-32 32-32h704c17.674 0 32 14.327 32 32v512c0 17.674-14.326 32-32 32h-704c-17.673 0-32-14.326-32-32v-512zM305.304 389.082c-14.866-9.555-34.665-5.251-44.222 9.613-9.557 14.867-5.253 34.666 9.613 44.224l241.304 155.123 241.306-155.123c14.864-9.558 19.168-29.357 9.613-44.224-9.558-14.864-29.357-19.168-44.224-9.613l-206.694 132.877-206.696-132.877z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["mail"],"defaultCode":59781,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1052,"name":"mail","prevSize":32,"id":140,"code":59781},"setIdx":0,"setId":6,"iconIdx":141},{"icon":{"paths":["M302.769 192h418.463l23.187 72.727h-0.211l23.792 63.999c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818c0-18.476-14.326-33.454-32-33.454s-32 14.978-32 33.454c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818c0-18.476-14.326-33.454-32-33.454s-32 14.978-32 33.454c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818l23.794-63.999h-0.213l23.188-72.727zM212.406 264.727l36.491-114.448c4.231-13.27 16.56-22.279 30.488-22.279h465.23c13.93 0 26.259 9.009 30.49 22.279l56.896 178.447c0 33.939-12.083 64.925-32 88.515v350.778c0 53.018-42.979 96-96 96h-384c-53.019 0-96-42.982-96-96v-350.778c-19.916-23.59-32-54.576-32-88.515l20.406-63.999zM288 458.33v309.69c0 17.67 14.327 32 32 32h128v-192.019h128v192.019h128c17.674 0 32-14.33 32-32v-309.69c-10.227 2.752-20.95 4.214-32 4.214-38.23 0-72.547-17.52-96-45.302-23.453 27.782-57.77 45.302-96 45.302s-72.547-17.52-96-45.302c-23.453 27.782-57.77 45.302-96 45.302-11.050 0-21.772-1.462-32-4.214z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["marketplace"],"defaultCode":59782,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1053,"name":"marketplace","prevSize":32,"id":141,"code":59782},"setIdx":0,"setId":6,"iconIdx":142},{"icon":{"paths":["M773.072 576c-35.344 0-64-28.653-64-64s28.656-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64z","M517.072 576c-35.344 0-64-28.653-64-64s28.656-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64z","M261.073 576c-35.346 0-64-28.653-64-64s28.654-64 64-64c35.346 0 63.999 28.653 63.999 64s-28.652 64-63.999 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["meatballs"],"defaultCode":59783,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1054,"name":"meatballs","prevSize":32,"id":142,"code":59783},"setIdx":0,"setId":6,"iconIdx":143},{"icon":{"paths":["M651.36 116.071c-57.242-19.989-105.792-20.069-138.358-20.071v64l-1.002-64c-92.006 0.342-297.345 47.824-381.242 242.995-17.897 38.97-34.758 103.344-34.758 173.005 0 69.958 17.020 146.285 52.216 207.875 23.229 40.653 92.799 131.376 191.179 173.536 94.861 40.656 206.368 52.349 296.49 16.301 16.41-6.563 24.39-25.187 17.827-41.597s-25.187-24.39-41.597-17.827c-69.878 27.952-163.171 20.445-247.51-15.699-80.819-34.64-141.384-112.451-160.821-146.464-28.804-50.41-43.784-115.418-43.784-176.125 0-60.765 15.020-116.182 29.055-146.589l0.184-0.4 0.173-0.406c69.507-162.181 243.823-204.604 323.589-204.605 31.594 0.002 70.877 0.296 117.258 16.493 46.147 16.114 101.389 48.779 161.824 116.767 43.658 49.115 63.533 114.977 69.389 177.713 5.891 63.12-2.854 118.189-11.546 142.093-6.4 17.6-20.429 45.44-59.392 45.699-18.259-0.806-72.822-14.672-83.12-69.568v-235.062c0-17.674-3.414-34.134-29.014-34.134-19.338 0-26.454 16.461-26.454 34.134v34.131c-35.181-39.859-95.402-68.266-152.746-68.266-106.038 0-192 85.962-192 192s85.962 192 192 192c62.179 0 117.658-29.555 152.746-75.386 25.715 71.078 102.57 93.027 137.014 94.134l0.515 0.016h0.512c82.643 0 111.715-64.806 120.086-87.83 12.64-34.762 21.674-99.696 15.12-169.907-6.589-70.595-29.379-151.401-85.277-214.287-66.902-75.265-131.075-114.597-188.557-134.67zM627.2 512c0 70.691-57.309 128-128 128s-128-57.309-128-128c0-70.691 57.309-128 128-128s128 57.309 128 128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["mention"],"defaultCode":59784,"grid":0},"attrs":[{}],"properties":{"order":1055,"name":"mention","prevSize":32,"id":143,"code":59784},"setIdx":0,"setId":6,"iconIdx":144},{"icon":{"paths":["M223.311 308.609c-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-9.348 103.235 27.547 175.997 86.848 226.374 60.643 51.52 146.602 80.998 235.29 90.893 88.614 9.885 186.224 1.398 263.341-14.973 38.56-8.189 70.928-18.125 93.888-28.128 8.906-3.882 15.837-7.536 20.944-10.765-2.378-1.514-5.248-3.197-8.675-5.030-8.886-4.749-19.059-9.261-29.613-13.894l-1.843-0.81c-9.315-4.083-19.725-8.65-27.613-13.078-14.291-8.026-28.317-17.155-38.544-26.867-5.034-4.781-10.762-11.194-14.595-19.184-4.054-8.454-6.96-21.078-1.261-34.435 30.816-72.186 45.459-111.725 52.554-137.834 6.621-24.378 6.621-36.653 6.621-56.17v-0.179c0-15.51-8.979-86.595-53.776-152.876-43.376-64.174-121.395-125.729-264.832-125.729-129.725 0-207.83 53.576-254.529 118.696zM173.267 272.433c58.132-81.063 154.749-144.433 304.573-144.433 164.896 0 261.594 72.589 315.859 152.878 52.838 78.181 64.416 161.881 64.416 187.641 0 21.654-0.022 40.336-8.797 72.64-7.83 28.835-22.627 68.614-50.048 133.424 5.069 4.032 12.592 9.005 22.506 14.57 5.123 2.877 12.995 6.339 24.054 11.194 10.266 4.506 22.582 9.93 33.891 15.978 10.848 5.798 23.526 13.571 32.954 23.738 9.859 10.63 20.208 28.87 12.816 51.139-4.87 14.672-16.182 25.091-25.61 32.016-10.24 7.52-22.947 14.278-36.858 20.342-27.946 12.176-64.582 23.181-105.68 31.907-82.198 17.453-186.522 26.688-282.909 15.936-96.31-10.746-195.346-43.178-268.313-105.165-74.031-62.893-119.295-154.778-108.551-277.856 0.276-63.411 19.117-157.053 75.696-235.948z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["message"],"defaultCode":59786,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1056,"name":"message","prevSize":32,"id":144,"code":59786},"setIdx":0,"setId":6,"iconIdx":145},{"icon":{"paths":["M477.84 128c104.256 0 181.251 29.018 237.494 70.652l-44.317 44.317c-45.52-31.22-107.747-53.057-193.178-53.057-129.725 0-207.83 53.576-254.529 118.696-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-7.328 80.928 13.761 143.126 51.784 190.499l-43.879 43.878c-50.179-59.901-78.131-139.043-69.441-238.595 0.276-63.411 19.117-157.053 75.696-235.948 58.132-81.063 154.749-144.433 304.573-144.433zM822.848 332.499l-47.008 47.008c16.502 42.634 20.608 78.525 20.608 89.011v0.179c0 19.517 0 31.792-6.621 56.17-7.094 26.109-21.738 65.648-52.554 137.834-5.699 13.357-2.794 25.981 1.261 34.435 3.834 7.99 9.562 14.403 14.595 19.184 10.227 9.712 24.253 18.842 38.544 26.867 7.888 4.429 18.298 8.995 27.613 13.078l1.843 0.81c10.554 4.634 20.726 9.146 29.613 13.894 3.427 1.834 6.298 3.517 8.672 5.030-5.104 3.229-12.035 6.883-20.941 10.765-22.96 10.003-55.328 19.939-93.888 28.128-77.12 16.371-174.73 24.858-263.341 14.973-43.744-4.88-86.826-14.525-126.534-29.229l-47.542 47.542c52.771 23.018 110.492 36.886 167.267 43.222 96.387 10.752 200.71 1.517 282.909-15.936 41.098-8.726 77.731-19.731 105.68-31.907 13.91-6.064 26.618-12.822 36.858-20.342 9.427-6.925 20.739-17.344 25.61-32.016 7.392-22.269-2.957-40.509-12.816-51.139-9.427-10.166-22.106-17.939-32.954-23.738-11.309-6.048-23.626-11.472-33.891-15.978-11.059-4.854-18.934-8.317-24.054-11.194-9.914-5.565-17.437-10.538-22.506-14.57 27.421-64.81 42.214-104.589 50.048-133.424 8.774-32.304 8.797-50.986 8.797-72.64 0-20.106-7.053-75.501-35.267-136.019zM836.038 153.372c12.499-12.497 32.758-12.497 45.254 0 12.499 12.497 12.499 32.758 0 45.255l-682.665 682.665c-12.497 12.499-32.758 12.499-45.255 0-12.497-12.496-12.497-32.755 0-45.254l682.666-682.666z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["message-disabled"],"defaultCode":59785,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1057,"name":"message-disabled","prevSize":32,"id":145,"code":59785},"setIdx":0,"setId":6,"iconIdx":146},{"icon":{"paths":["M86.686 85.336l730.792 774.088c0 0 24.899 17.558 43.936-2.928 19.040-20.486 4.394-40.973 4.394-40.973l-779.122-730.187zM318.080 158.503l556.516 599.955c0 0 24.896 17.558 43.936-2.928 19.037-20.486 4.394-40.973 4.394-40.973l-604.845-556.054zM712.035 915.030l-556.517-599.955 604.843 556.054c0 0 14.646 20.486-4.39 40.973-19.040 20.486-43.936 2.928-43.936 2.928zM513.693 221.419l388.803 419.15c0 0 17.395 12.269 30.694-2.042 13.302-14.314 3.069-28.627 3.069-28.627l-422.566-388.482zM597.878 915.677l-388.805-419.152 422.568 388.48c0 0 10.234 14.314-3.069 28.627-13.302 14.31-30.694 2.045-30.694 2.045zM713.498 312.143l176.221 190.551c0 0 8.605 5.747 15.184-0.96 6.579-6.704 1.517-13.411 1.517-13.411l-192.922-176.18zM482.582 880.23l-176.219-190.55 192.923 176.179c0 0 5.059 6.707-1.52 13.414-6.579 6.704-15.184 0.957-15.184 0.957z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["meteor-monochromatic"],"defaultCode":59659,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1058,"name":"meteor-monochromatic","prevSize":32,"id":146,"code":59659},"setIdx":0,"setId":6,"iconIdx":147},{"icon":{"paths":["M608 288c0-53.019-42.979-96-96-96s-96 42.981-96 96v128c0 53.021 42.979 96 96 96s96-42.979 96-96v-128zM352 288c0-88.365 71.635-160 160-160s160 71.635 160 160v128c0 88.365-71.635 160-160 160s-160-71.635-160-160v-128zM256 384c17.673 0 32 14.326 32 32 0 92.086 37.757 149.632 83.722 185.6 46.464 36.358 102.736 51.581 140.278 54.326 37.542-2.746 93.814-17.968 140.278-54.326 45.962-35.968 83.722-93.514 83.722-185.6 0-17.674 14.326-32 32-32s32 14.326 32 32c0 112.714-47.574 188.499-108.278 236-47.904 37.485-103.082 56.762-147.722 64.381v115.619h160c17.674 0 32 14.326 32 32s-14.326 32-32 32h-384c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-115.619c-44.64-7.619-99.818-26.896-147.722-64.381-60.703-47.501-108.278-123.286-108.278-236 0-17.674 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["microphone"],"defaultCode":59788,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1059,"name":"microphone","prevSize":32,"id":147,"code":59788},"setIdx":0,"setId":6,"iconIdx":148},{"icon":{"paths":["M512 128c75.546 0 138.861 52.356 155.645 122.762l-59.645 59.644v-22.405c0-53.019-42.979-96-96-96s-96 42.981-96 96v128c0 24.067 8.858 46.067 23.488 62.915l-45.322 45.325c-26.182-28.49-42.166-66.499-42.166-108.24v-128c0-88.365 71.635-160 160-160zM561.35 568.243l102.893-102.893c-15.763 48.672-54.221 87.13-102.893 102.893zM288 416c0 72.154 23.181 123.101 55.328 159.078l-45.304 45.302c-43.428-47.35-74.024-113.99-74.024-204.381 0-17.674 14.327-32 32-32s32 14.326 32 32zM478.659 650.938l-51.808 51.808c18.56 6.374 36.579 10.806 53.149 13.635v115.619h-160c-17.673 0-32 14.326-32 32s14.327 32 32 32h384c17.674 0 32-14.326 32-32s-14.326-32-32-32h-160v-115.619c44.64-7.619 99.818-26.896 147.722-64.381 60.704-47.501 108.278-123.286 108.278-236 0-17.674-14.326-32-32-32s-32 14.326-32 32c0 92.086-37.757 149.632-83.722 185.6-46.464 36.358-102.736 51.581-140.278 54.326-9.971-0.73-21.264-2.339-33.341-4.989zM825.373 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672-672z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["microphone-disabled"],"defaultCode":59787,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1060,"name":"microphone-disabled","prevSize":32,"id":148,"code":59787},"setIdx":0,"setId":6,"iconIdx":149},{"icon":{"paths":["M234.666 170.661c0-47.128 38.205-85.333 85.333-85.333h384.001c47.126 0 85.331 38.205 85.331 85.333v682.667c0 47.13-38.205 85.334-85.331 85.334h-384.001c-47.128 0-85.333-38.205-85.333-85.334v-682.667zM298.666 170.661v682.667c0 11.782 9.551 21.334 21.333 21.334h384.001c11.782 0 21.331-9.552 21.331-21.334v-682.667c0-11.782-9.549-21.333-21.331-21.333h-96.291c-2.653 24.002-23.002 42.672-47.709 42.672h-96c-24.707 0-45.056-18.67-47.709-42.672h-96.292c-11.782 0-21.333 9.551-21.333 21.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["mobile"],"defaultCode":59789,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1061,"name":"mobile","prevSize":32,"id":149,"code":59789},"setIdx":0,"setId":6,"iconIdx":150},{"icon":{"paths":["M319.247 231.566c-62.882 49.504-135.086 136.549-141.94 266.127-5.762 108.922 37.404 187.184 89.915 241.51 53.258 55.098 115.702 84.925 144.25 94.438 41.859 13.955 114.269 29.536 234.643-15.603 34.858-13.072 73.165-42.096 108.304-78.426 14.272-14.755 27.616-30.294 39.6-45.773-28.778 9.293-61.699 17.754-96.589 23.594-56.192 9.405-119.29 12.32-179.411-0.237-2.49-0.518-4.96-1.030-7.408-1.536-22.195-4.576-42.733-8.816-62.589-17.648-23.091-10.275-43.805-25.891-69.299-51.386-42.096-42.096-89.142-107.222-89.371-213.843-1.569-34.080 4.622-81.878 13.764-129.216 4.624-23.946 10.142-48.465 16.132-72.003zM345.562 138.217c32.8-17.15 63.709 15.843 53.875 45.907-12.234 37.414-24.586 85.511-33.482 131.58-9.024 46.732-13.949 88.633-12.643 114.7l0.038 0.797v0.8c0 84.915 36.173 134.918 70.627 169.373 22.509 22.509 36.835 32.278 50.064 38.166 13.229 5.885 26.832 8.717 51.085 13.763 1.923 0.4 3.917 0.816 5.978 1.248 49.914 10.426 104.534 8.336 155.76-0.237 65.434-10.954 122.384-31.981 152.374-47.386 17.562-9.021 34.992-2.47 44.477 5.965 9.661 8.589 19.376 27.152 8.886 46.954-20.637 38.95-53.645 84.419-92.182 124.259-38.211 39.51-84.317 76.038-131.834 93.859-135.626 50.858-223.216 34.438-277.354 16.394-36.515-12.173-108.392-46.912-170.026-110.675-62.381-64.534-114.684-159.427-107.81-289.373 10.79-203.979 157.583-317.098 232.165-356.093z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["moon"],"defaultCode":59790,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1062,"name":"moon","prevSize":32,"id":150,"code":59790},"setIdx":0,"setId":6,"iconIdx":151},{"icon":{"paths":["M144 160c-17.673 0-32 14.327-32 32s14.327 32 32 32h192c17.674 0 32-14.327 32-32s-14.326-32-32-32h-192zM700.4 346.646c11.795-13.165 32.026-14.272 45.187-2.48 13.162 11.795 14.272 32.026 2.477 45.187l-81.222 90.646h216.358c17.674 0 32 14.326 32 32s-14.326 32-32 32h-216.358l81.222 90.646c11.795 13.162 10.685 33.392-2.477 45.187-13.162 11.792-33.392 10.685-45.187-2.48l-129.030-144c-10.893-12.154-10.893-30.554 0-42.707l129.030-144zM112 512c0-17.674 14.327-32 32-32h192c17.674 0 32 14.326 32 32s-14.326 32-32 32h-192c-17.673 0-32-14.326-32-32zM144 640c-17.673 0-32 14.326-32 32s14.327 32 32 32h192c17.674 0 32-14.326 32-32s-14.326-32-32-32h-192zM112 352c0-17.674 14.327-32 32-32h192c17.674 0 32 14.326 32 32s-14.326 32-32 32h-192c-17.673 0-32-14.326-32-32zM144 800c-17.673 0-32 14.326-32 32s14.327 32 32 32h192c17.674 0 32-14.326 32-32s-14.326-32-32-32h-192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["move-to-the-queue"],"defaultCode":59791,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1063,"name":"move-to-the-queue","prevSize":32,"id":151,"code":59791},"setIdx":0,"setId":6,"iconIdx":152},{"icon":{"paths":["M809.002 166.758c7.782 6.063 12.333 15.377 12.333 25.242v448h-0.112c0.074 1.734 0.112 3.478 0.112 5.229 0 69.053-57.309 125.030-128 125.030-70.694 0-128-55.978-128-125.030s57.306-125.030 128-125.030c23.312 0 45.171 6.090 64 16.73v-303.86l-384 96.798v409.136c0 69.053-57.309 125.037-128.001 125.037s-128-55.978-128-125.030c0-69.050 57.308-125.027 128-125.027 23.314 0 45.173 6.086 64 16.726v-325.777c0-14.66 9.962-27.446 24.177-31.029l448-112.93c9.568-2.411 19.709-0.276 27.491 5.788z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["musical-note"],"defaultCode":59792,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1064,"name":"musical-note","prevSize":32,"id":152,"code":59792},"setIdx":0,"setId":6,"iconIdx":153},{"icon":{"paths":["M208 176c-35.346 0-64 28.654-64 64v576c0 35.347 28.654 64 64 64h576c35.347 0 64-28.653 64-64v-576c0-35.346-28.653-64-64-64h-576zM208 240h576v576h-576v-576zM698.627 558.15c-0.189 17.674-14.669 31.846-32.339 31.658-17.674-0.189-31.846-14.669-31.658-32.339l1.318-123.594-309.341 308.774c-12.51 12.483-32.771 12.464-45.256-0.042-12.485-12.509-12.467-32.771 0.042-45.258l309.195-308.624-123.382 1.315c-17.674 0.189-32.154-13.984-32.339-31.654-0.189-17.674 13.984-32.15 31.654-32.339l201.92-2.157c8.605-0.093 16.886 3.286 22.97 9.37 6.086 6.086 9.462 14.365 9.373 22.97l-2.157 201.92z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["new-window"],"defaultCode":59793,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1065,"name":"new-window","prevSize":32,"id":153,"code":59793},"setIdx":0,"setId":6,"iconIdx":154},{"icon":{"paths":["M601.331 808.928h-174.154c0.003 48.090 38.989 87.072 87.078 87.072s87.075-38.982 87.075-87.072zM815.597 731.677c7.274 9.696 8.442 22.669 3.021 33.51s-16.499 17.69-28.621 17.69h-565.996c-12.943 0-24.611-7.798-29.564-19.757-4.953-11.955-2.215-25.718 6.937-34.87l51.653-51.654v-274.032c0-144.272 116.957-261.228 261.229-261.228s261.229 116.956 261.229 261.228v275.629l40.112 53.485zM711.485 715.894v-313.331c0-108.926-88.304-197.228-197.229-197.228-108.928 0-197.229 88.302-197.229 197.228v313.331h394.458z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["notification"],"defaultCode":59795,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1066,"name":"notification","prevSize":32,"id":154,"code":59795},"setIdx":0,"setId":6,"iconIdx":155},{"icon":{"paths":["M781.837 402.634c0-5.245-0.154-10.454-0.461-15.622l-63.539 63.539v265.363h-265.363l-66.979 66.979h425.363c12.944 0 24.611-7.795 29.565-19.754 4.954-11.955 2.214-25.722-6.938-34.874l-51.648-51.648v-273.984zM704.765 217.373l-45.254 45.255c-35.638-35.351-84.704-57.189-138.867-57.189-108.909 0-197.194 88.287-197.194 197.195v196.054l-64.001 64v-260.054c0-144.254 116.941-261.195 261.194-261.195 71.837 0 136.899 29.001 184.122 75.934zM433.578 808.934c0 48.086 38.982 87.066 87.066 87.066s87.066-38.979 87.066-87.066h-174.131zM854.275 190.982c-11.334-11.334-29.709-11.334-41.043 0l-612.732 612.733c-11.333 11.331-11.333 29.709 0 41.040 11.334 11.334 29.709 11.334 41.043 0l612.732-612.731c11.334-11.333 11.334-29.709 0-41.043z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["notification-disabled"],"defaultCode":59794,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1067,"name":"notification-disabled","prevSize":32,"id":155,"code":59794},"setIdx":0,"setId":6,"iconIdx":156},{"icon":{"paths":["M712.051 512.675v54.89c-0.195 76.736-43.741 143.283-107.44 176.445-5.53-25.67-28.362-44.906-55.683-44.906h-72.502c-31.459 0-56.963 25.501-56.963 56.963v41.427c0 31.462 25.504 56.963 56.963 56.963h72.502c28.509 0 52.128-20.944 56.307-48.288 69.261-26.829 123.962-82.883 148.966-153.030 4.723 1.27 9.69 1.946 14.813 1.946h28.483c31.459 0 56.963-25.504 56.963-56.963v-85.446c0-31.459-25.504-56.963-56.963-56.963h-28.483v-28.483c0-141.572-114.765-256.338-256.336-256.338s-256.339 114.766-256.339 256.338v23.302h-28.483c-31.46 0-56.964 25.504-56.964 56.966v103.571c0 31.459 25.504 56.963 56.964 56.963h28.482c31.46 0 56.964-25.504 56.964-56.963v-36.253h0.149c-0.099-2.576-0.148-5.165-0.148-7.766v-139.821c0-110.111 89.263-199.374 199.375-199.374s199.373 89.263 199.373 199.374v85.446z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["omnichannel"],"defaultCode":59796,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1068,"name":"omnichannel","prevSize":32,"id":156,"code":59796},"setIdx":0,"setId":6,"iconIdx":157},{"icon":{"paths":["M705.578 633.158c9.507-9.235 24.701-9.018 33.939 0.486 9.238 9.507 9.021 24.701-0.486 33.939l-208.275 202.387c-9.312 9.050-24.138 9.050-33.45 0l-208.276-202.387c-9.506-9.238-9.724-24.432-0.487-33.939 9.237-9.504 24.432-9.722 33.937-0.486l191.549 186.134 191.549-186.134zM705.578 411.584c9.507 9.238 24.701 9.021 33.939-0.486s9.021-24.701-0.486-33.939l-208.275-202.385c-9.312-9.051-24.138-9.051-33.45 0l-208.276 202.385c-9.506 9.238-9.724 24.432-0.487 33.939 9.237 9.504 24.432 9.725 33.937 0.486l191.549-186.134 191.549 186.134z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["order"],"defaultCode":59797,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1069,"name":"order","prevSize":32,"id":157,"code":59797},"setIdx":0,"setId":6,"iconIdx":158},{"icon":{"paths":["M742.317 652.566c12.666-12.323 12.944-32.582 0.618-45.248-12.323-12.669-32.582-12.944-45.251-0.621l44.634 45.869zM512 832.019l-22.317 22.934c12.422 12.086 32.211 12.086 44.634 0l-22.317-22.934zM326.317 606.698c-12.667-12.323-32.927-12.048-45.252 0.621-12.324 12.666-12.047 32.925 0.619 45.248l44.632-45.869zM697.683 606.698l-208 202.387 44.634 45.869 208-202.387-44.634-45.869zM534.317 809.085l-208-202.387-44.632 45.869 207.999 202.387 44.634-45.869z","M742.317 371.456c12.666 12.323 12.944 32.582 0.618 45.251-12.323 12.666-32.582 12.944-45.251 0.618l44.634-45.869zM512 192.004l-22.317-22.935c12.422-12.087 32.211-12.087 44.634 0l-22.317 22.935zM326.317 417.325c-12.668 12.326-32.927 12.048-45.252-0.618-12.325-12.669-12.048-32.928 0.619-45.251l44.633 45.869zM697.683 417.325l-208-202.386 44.634-45.87 208 202.387-44.634 45.869zM534.317 214.939l-208 202.386-44.633-45.869 207.999-202.387 44.634 45.87z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":9}]},"tags":["ordering-ascending"],"defaultCode":59798,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":1070,"name":"ordering-ascending","prevSize":32,"codes":[59798,59799],"id":158,"code":59798},"setIdx":0,"setId":6,"iconIdx":159},{"icon":{"paths":["M281.684 371.434c-12.667 12.323-12.944 32.582-0.619 45.248 12.324 12.669 32.584 12.944 45.252 0.621l-44.633-45.869zM512 191.981l22.317-22.935c-12.422-12.087-32.211-12.087-44.634 0l22.317 22.935zM697.683 417.302c12.669 12.323 32.928 12.048 45.251-0.621 12.326-12.666 12.048-32.925-0.618-45.248l-44.634 45.869zM326.317 417.302l208-202.387-44.634-45.869-207.999 202.387 44.633 45.869zM489.683 214.916l208 202.387 44.634-45.869-208-202.387-44.634 45.869z","M281.684 652.544c-12.667-12.323-12.944-32.582-0.619-45.251 12.324-12.666 32.584-12.944 45.252-0.618l-44.633 45.869zM512 831.997l22.317 22.934c-12.422 12.086-32.211 12.086-44.634 0l22.317-22.934zM697.683 606.675c12.669-12.326 32.928-12.048 45.251 0.618 12.326 12.669 12.048 32.928-0.618 45.251l-44.634-45.869zM326.317 606.675l208 202.384-44.634 45.872-207.999-202.387 44.633-45.869zM489.683 809.059l208-202.384 44.634 45.869-208 202.387-44.634-45.872z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":9}]},"tags":["ordering-descending"],"defaultCode":59800,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":1071,"name":"ordering-descending","prevSize":32,"codes":[59800,59801],"id":159,"code":59800},"setIdx":0,"setId":6,"iconIdx":160},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352-194.405 0-352.001 157.596-352.001 352s157.596 352 352.001 352c194.403 0 352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416-229.752 0-416.001-186.25-416.001-416s186.25-416 416.001-416c229.75 0 416 186.25 416 416zM399.997 383.994v256c0 17.674 14.326 32 32 32s32-14.326 32-32v-256c0-17.67-14.326-32-32-32s-32 14.33-32 32zM559.997 383.994v256c0 17.674 14.326 32 32 32s32-14.326 32-32v-256c0-17.67-14.326-32-32-32s-32 14.33-32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pause"],"defaultCode":59803,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1072,"name":"pause","prevSize":32,"id":160,"code":59803},"setIdx":0,"setId":6,"iconIdx":161},{"icon":{"paths":["M512 928c229.75 0 416-186.25 416-416s-186.25-416-416-416c-229.752 0-416.001 186.25-416.001 416s186.25 416 416.001 416zM399.997 383.994c0-17.67 14.326-32 32-32s32 14.33 32 32v256c0 17.674-14.326 32-32 32s-32-14.326-32-32v-256zM559.997 383.994c0-17.67 14.326-32 32-32s32 14.33 32 32v256c0 17.674-14.326 32-32 32s-32-14.326-32-32v-256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pause-filled"],"defaultCode":59802,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1073,"name":"pause-filled","prevSize":32,"id":161,"code":59802},"setIdx":0,"setId":6,"iconIdx":162},{"icon":{"paths":["M822.627 201.372c12.496 12.497 12.496 32.758 0 45.255l-576 576c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l576-576c12.496-12.497 32.758-12.497 45.254 0z","M192 320c0-70.692 57.308-128 128-128 70.691 0 128 57.308 128 128 0 70.691-57.309 128-128 128-70.692 0-128-57.309-128-128zM320 256c-35.346 0-64 28.654-64 64s28.654 64 64 64c35.347 0 64-28.653 64-64s-28.653-64-64-64z","M704 576c-70.691 0-128 57.309-128 128s57.309 128 128 128c70.691 0 128-57.309 128-128s-57.309-128-128-128zM640 704c0-35.347 28.653-64 64-64s64 28.653 64 64c0 35.347-28.653 64-64 64s-64-28.653-64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["percentage"],"defaultCode":59777,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1074,"id":162,"name":"percentage","prevSize":32,"code":59777},"setIdx":0,"setId":6,"iconIdx":163},{"icon":{"paths":["M410.502 204.616c-10.419-21.362-34.202-37.856-62.189-33.137-38.104 6.425-88.825 25.194-126.247 57.060-18.972 16.155-35.817 36.795-44.757 62.246-9.15 26.048-9.211 54.919 2.087 85.195 21.202 56.816 60.513 117.456 97.761 167.264 37.482 50.122 74.609 91.552 93.329 110.269l44.173-44.173c-16.406-16.403-51.6-55.536-87.472-103.51-36.11-48.285-71.192-103.264-89.264-151.69-6.437-17.248-5.748-31.056-1.675-42.651 4.283-12.192 13.134-24.16 26.319-35.388 25.849-22.012 63.292-36.814 92.623-42.392l59.075 121.097c0.019 0.074 0.045 0.285-0.013 0.688-0.112 0.749-0.502 1.827-1.344 2.883-7.117 8.95-14.899 20-20.941 31.741-5.674 11.024-11.715 26.246-10.976 42.47 0.643 14.138 7.76 27.773 13.222 36.973 6.275 10.576 14.416 21.741 22.79 32.291 16.806 21.171 36.541 42.326 49.68 55.466l44.173-44.173c-11.952-11.952-29.981-31.309-44.928-50.134-7.504-9.453-13.738-18.157-17.997-25.334-2.87-4.838-3.984-7.578-4.387-8.57l-0.038-0.093c0.266-1.382 1.139-4.736 4.006-10.31 3.552-6.902 8.717-14.438 14.291-21.443 14.611-18.374 20.518-45.424 8.611-69.837l-59.914-122.808zM819.386 613.504c21.36 10.419 37.856 34.202 33.136 62.189-6.426 38.106-25.194 88.826-57.059 126.246-16.157 18.973-36.797 35.818-62.246 44.758-26.048 9.149-54.922 9.21-85.197-2.086-56.813-21.203-117.453-60.515-167.261-97.763-50.122-37.482-91.555-74.608-110.272-93.328l44.173-44.173c16.403 16.406 55.539 51.6 103.51 87.472 48.285 36.109 103.267 71.194 151.69 89.264 17.248 6.435 31.056 5.747 42.653 1.674 12.192-4.282 24.16-13.133 35.386-26.317 22.013-25.85 36.816-63.293 42.394-92.624l-121.094-59.075c-0.077-0.019-0.288-0.048-0.688 0.013-0.752 0.112-1.83 0.502-2.886 1.344-8.95 7.117-20 14.899-31.741 20.941-11.024 5.674-26.246 11.715-42.47 10.976-14.134-0.643-27.773-7.76-36.973-13.222-10.576-6.275-21.741-14.416-32.288-22.79-21.174-16.806-42.33-36.541-55.469-49.68l44.173-44.173c11.952 11.952 31.309 29.981 50.134 44.928 9.453 7.504 18.16 13.738 25.334 17.997 4.838 2.87 7.578 3.984 8.57 4.387l0.093 0.038c1.382-0.266 4.739-1.139 10.314-4.006 6.899-3.552 14.435-8.717 21.44-14.291 18.374-14.611 45.427-20.518 69.837-8.611l122.81 59.914z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone"],"defaultCode":59806,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1075,"name":"phone","prevSize":32,"id":163,"code":59806},"setIdx":0,"setId":6,"iconIdx":164},{"icon":{"paths":["M825.373 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672-672zM575.613 569.069l-44.707 44.707c7.846 5.904 15.846 11.453 23.533 16.016 9.2 5.459 22.838 12.579 36.973 13.222 16.224 0.736 31.446-5.302 42.47-10.976 11.741-6.042 22.79-13.824 31.744-20.944 1.053-0.838 2.134-1.232 2.883-1.341 0.403-0.061 0.611-0.032 0.688-0.013l121.094 59.075c-5.578 29.331-20.381 66.771-42.39 92.621-11.229 13.187-23.197 22.038-35.389 26.32-11.597 4.074-25.402 4.762-42.653-1.677-48.422-18.070-103.405-53.152-151.69-89.261-14.026-10.49-27.299-20.922-39.469-30.842l-44.387 44.39c14.186 11.683 29.84 24.061 46.445 36.48 49.808 37.248 110.448 76.56 167.261 97.76 30.275 11.299 59.149 11.238 85.197 2.086 25.45-8.938 46.090-25.786 62.246-44.755 31.866-37.424 50.634-88.144 57.059-126.246 4.72-27.987-11.776-51.77-33.136-62.192l-122.81-59.91c-24.41-11.907-51.462-6-69.834 8.611-7.008 5.571-14.544 10.739-21.443 14.291-5.574 2.867-8.931 3.741-10.314 4.003l-0.093-0.038c-0.992-0.4-3.731-1.514-8.57-4.387-3.277-1.942-6.87-4.301-10.71-7.002zM313.636 589.683l44.389-44.387c-9.92-12.17-20.349-25.44-30.838-39.466-36.109-48.285-71.192-103.267-89.263-151.69-6.437-17.251-5.748-31.056-1.675-42.652 4.283-12.192 13.134-24.16 26.319-35.388 25.849-22.012 63.291-36.814 92.622-42.392l59.075 121.095c0.019 0.077 0.048 0.285-0.013 0.688-0.109 0.752-0.502 1.83-1.341 2.883-7.12 8.954-14.902 20.003-20.944 31.744-5.674 11.024-11.715 26.246-10.976 42.47 0.643 14.134 7.763 27.773 13.222 36.973 4.563 7.686 10.109 15.683 16.013 23.53l44.707-44.707c-2.701-3.837-5.056-7.434-7.002-10.707-2.87-4.838-3.984-7.578-4.387-8.57l-0.038-0.093c0.266-1.382 1.139-4.739 4.006-10.314 3.552-6.899 8.72-14.435 14.291-21.443 14.611-18.371 20.518-45.424 8.611-69.834l-59.91-122.809c-10.422-21.362-34.205-37.856-62.192-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.757 62.246-9.15 26.048-9.211 54.921 2.087 85.196 21.202 56.813 60.513 117.453 97.761 167.261 12.417 16.605 24.795 32.256 36.478 46.442z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone-disabled"],"defaultCode":59804,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1076,"name":"phone-disabled","prevSize":32,"id":164,"code":59804},"setIdx":0,"setId":6,"iconIdx":165},{"icon":{"paths":["M801.123 657.59c22.474 7.734 50.954 2.582 67.408-20.544 22.4-31.488 44.992-80.624 48.922-129.619 1.99-24.838-0.691-51.344-12.368-75.661-11.949-24.89-32.32-45.35-61.718-58.768-55.165-25.181-125.84-40.262-187.398-49.146-61.946-8.936-117.494-11.98-143.965-11.98v62.469c23.2 0 75.757 2.787 135.043 11.341 59.677 8.611 123.36 22.682 170.381 44.144 16.749 7.645 26.022 17.894 31.344 28.973 5.59 11.651 7.795 26.371 6.413 43.635-2.717 33.843-18.723 70.784-35.52 95.469l-127.398-43.853c-0.067-0.042-0.237-0.17-0.48-0.496-0.451-0.608-0.934-1.651-1.088-2.989-1.296-11.363-3.606-24.678-7.635-37.254-3.786-11.808-10.278-26.842-22.272-37.792-10.451-9.539-25.126-14.15-35.494-16.794-11.914-3.040-25.568-5.181-38.944-6.717-26.858-3.088-55.773-4.093-74.352-4.093v62.47c16.902 0 43.338 0.938 67.219 3.683 11.99 1.379 22.554 3.123 30.64 5.187 5.45 1.389 8.173 2.541 9.162 2.957l0.093 0.038c0.79 1.165 2.544 4.154 4.458 10.125 2.368 7.392 4.045 16.374 5.059 25.267 2.659 23.325 17.61 46.63 43.29 55.469l129.203 44.477zM222.875 657.584c-22.474 7.738-50.954 2.586-67.407-20.544-22.4-31.485-44.993-80.621-48.922-129.616-1.992-24.838 0.691-51.344 12.366-75.664 11.949-24.886 32.321-45.347 61.719-58.765 55.165-25.181 125.841-40.262 187.4-49.146 61.946-8.937 117.494-11.98 143.965-11.98v62.47c-23.2 0-75.757 2.787-135.046 11.341-59.674 8.608-123.358 22.682-170.378 44.144-16.748 7.645-26.024 17.894-31.343 28.973-5.593 11.651-7.797 26.371-6.412 43.635 2.714 33.843 18.721 70.784 35.518 95.469l127.4-43.856c0.067-0.038 0.234-0.166 0.477-0.493 0.454-0.611 0.938-1.651 1.091-2.989 1.296-11.363 3.606-24.682 7.635-37.254 3.786-11.808 10.275-26.842 22.272-37.792 10.448-9.542 25.126-14.15 35.491-16.794 11.917-3.040 25.568-5.181 38.947-6.717 26.858-3.088 55.77-4.093 74.349-4.093v62.47c-16.899 0-43.338 0.938-67.216 3.683-11.99 1.376-22.554 3.123-30.64 5.187-5.453 1.389-8.176 2.541-9.162 2.957l-0.093 0.038c-0.79 1.162-2.547 4.154-4.458 10.125-2.371 7.389-4.045 16.371-5.059 25.267-2.659 23.322-17.61 46.627-43.293 55.469l-129.202 44.474z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone-end"],"defaultCode":59805,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1077,"name":"phone-end","prevSize":32,"id":165,"code":59805},"setIdx":0,"setId":6,"iconIdx":166},{"icon":{"paths":["M717.254 352l137.37-137.372c12.499-12.497 12.499-32.758 0-45.255-12.496-12.497-32.755-12.497-45.254 0l-137.373 137.373v-82.745c0-17.673-14.326-32-32-32-17.67 0-32 14.327-32 32v160c0 4.339 0.864 8.477 2.429 12.25 1.526 3.686 3.773 7.149 6.736 10.166 0.138 0.141 0.278 0.282 0.419 0.419 3.018 2.966 6.48 5.21 10.17 6.736 3.773 1.565 7.91 2.429 12.246 2.429h160c17.674 0 32-14.326 32-32s-14.326-32-32-32h-82.742z","M819.478 613.379l-122.88-59.84c-11.261-5.29-23.786-7.283-36.128-5.757-12.346 1.53-24.003 6.522-33.632 14.397-6.816 5.274-13.978 10.086-21.44 14.4-3.382 1.632-6.922 2.918-10.56 3.84-3.008-1.235-5.901-2.736-8.64-4.48-8.752-5.504-17.19-11.488-25.28-17.92-18.88-15.040-38.080-32-50.24-44.8s-29.76-32-44.8-50.24c-6.435-8.093-12.416-16.531-17.92-25.28-1.747-2.742-3.248-5.635-4.48-8.64 0.918-3.642 2.205-7.181 3.84-10.56 4.314-7.462 9.123-14.627 14.4-21.44 7.875-9.629 12.864-21.29 14.394-33.635 1.53-12.342-0.467-24.867-5.754-36.125l-59.84-122.881c-5.635-11.286-14.73-20.477-25.952-26.234-11.226-5.756-23.997-7.776-36.448-5.766-46.072 7.753-89.44 27.015-126.081 56-20.379 16.952-35.847 39.050-44.8 64-9.479 27.726-8.684 57.931 2.24 85.121 25.032 59.536 57.851 115.491 97.6 166.4 28.686 38.71 59.902 75.485 93.441 110.080 34.406 33.296 70.966 64.298 109.44 92.8 51.203 39.821 107.485 72.643 167.36 97.6 27.158 11.066 57.418 11.862 85.12 2.24 24.368-9.203 45.888-24.653 62.4-44.8 29.328-36.544 48.925-79.92 56.96-126.080 1.984-12.49-0.083-25.286-5.901-36.515-5.814-11.229-15.075-20.301-26.419-25.885zM747.798 761.219c-9.187 11.802-21.331 20.963-35.2 26.56-14.051 4.416-29.197 3.85-42.88-1.6-54.202-23.091-105.187-53.101-151.68-89.28-35.83-27.52-69.923-57.232-102.080-88.96-31.334-32.611-60.618-67.13-87.68-103.36-36.201-46.426-66.113-97.427-88.961-151.68-5.832-13.587-6.514-28.829-1.92-42.881 5.595-13.87 14.757-26.014 26.56-35.2 26.691-20.806 57.953-34.956 91.201-41.28l60.8 121.281c0.154 0.954 0.154 1.926 0 2.88-7.933 9.981-14.899 20.698-20.8 32-7.347 12.966-11.101 27.658-10.88 42.56 1.354 13.142 5.853 25.763 13.12 36.8 6.934 11.104 14.522 21.789 22.72 32 16.96 21.12 36.48 42.56 49.6 55.68s34.56 32 55.68 49.6c10.208 8.198 20.893 15.782 32 22.72 11.034 7.264 23.658 11.763 36.8 13.12 14.899 0.218 29.59-3.536 42.56-10.88 11.302-5.904 22.016-12.867 32-20.8 0.851-0.707 1.827-1.251 2.88-1.6l118.72 59.84c-6.509 33.811-21.11 65.542-42.56 92.48z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["phone-in"],"grid":0},"attrs":[{},{}],"properties":{"order":1078,"id":166,"name":"phone-in","prevSize":32,"code":59809},"setIdx":0,"setId":6,"iconIdx":167},{"icon":{"paths":["M649.373 137.372c12.496-12.497 32.758-12.497 45.254 0l73.373 73.373 73.373-73.373c12.499-12.497 32.758-12.497 45.254 0 12.499 12.497 12.499 32.758 0 45.255l-73.373 73.372 73.373 73.373c12.499 12.496 12.499 32.758 0 45.254-12.496 12.496-32.755 12.496-45.254 0l-73.373-73.372-73.373 73.372c-12.496 12.496-32.755 12.496-45.254 0-12.496-12.496-12.496-32.758 0-45.254l73.373-73.373-73.373-73.372c-12.496-12.497-12.496-32.758 0-45.255zM361.062 167.708c28.672-4.835 53.037 12.064 63.712 33.949l61.379 125.818c12.202 25.008 6.147 52.72-8.822 71.546-5.706 7.178-11.002 14.899-14.64 21.968-2.938 5.712-3.834 9.149-4.102 10.563 0.378 0.928 1.494 3.754 4.534 8.877 4.362 7.35 10.749 16.269 18.438 25.952 15.312 19.29 33.782 39.12 46.026 51.363s32.077 30.717 51.363 46.029c9.683 7.69 18.602 14.077 25.955 18.442 5.12 3.040 7.946 4.154 8.874 4.534 1.414-0.272 4.854-1.165 10.563-4.106 7.069-3.638 14.79-8.931 21.968-14.64 18.822-14.97 46.538-21.021 71.546-8.822l125.818 61.379c21.885 10.678 38.784 35.040 33.949 63.715-6.582 39.037-25.811 90.998-58.458 129.338-16.55 19.437-37.696 36.694-63.773 45.856-26.685 9.373-56.266 9.437-87.283-2.141-58.205-21.722-120.33-61.997-171.36-100.16-51.347-38.4-93.795-76.438-112.973-95.616s-57.213-61.622-95.613-112.973c-38.16-51.027-78.435-113.152-100.156-171.357-11.575-31.018-11.513-60.598-2.138-87.284 9.159-26.075 26.417-47.22 45.854-63.771 38.339-32.647 90.303-51.876 129.34-58.458zM368.106 231.463c-30.048 5.715-68.407 20.88-94.89 43.431-13.508 11.503-22.577 23.764-26.964 36.255-4.173 11.878-4.878 26.025 1.716 43.696 18.514 49.61 54.456 105.939 91.45 155.408 36.752 49.146 72.806 89.238 89.613 106.045 16.81 16.81 56.902 52.864 106.048 89.619 49.469 36.995 105.798 72.938 155.408 91.453 17.67 6.592 31.818 5.888 43.696 1.715 12.49-4.387 24.752-13.456 36.256-26.963 22.55-26.483 37.715-64.842 43.43-94.893l-124.064-60.522c-0.077-0.019-0.291-0.048-0.704 0.013-0.768 0.112-1.875 0.515-2.954 1.376-9.171 7.293-20.493 15.264-32.518 21.456-11.296 5.811-26.89 12-43.514 11.245-14.483-0.659-28.454-7.955-37.878-13.549-10.835-6.432-22.275-14.771-33.082-23.35-21.69-17.222-43.363-37.44-56.822-50.899s-33.677-35.133-50.896-56.826c-8.579-10.803-16.918-22.246-23.35-33.078-5.594-9.427-12.886-23.398-13.546-37.878-0.755-16.624 5.434-32.218 11.245-43.514 6.189-12.026 14.163-23.347 21.456-32.518 0.858-1.078 1.261-2.186 1.376-2.954 0.061-0.413 0.032-0.627 0.013-0.704l-60.525-124.063z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["phone-issue"],"grid":0},"attrs":[{}],"properties":{"order":1079,"id":167,"name":"phone-issue","prevSize":32,"code":59835},"setIdx":0,"setId":6,"iconIdx":168},{"icon":{"paths":["M428.346 199.399c17.542-17.543 45.984-17.543 63.53 0 17.542 17.543 17.542 45.986 0 63.53l-43.661 43.659 177.83 177.828 60.339-60.339c24.992-24.995 65.517-24.995 90.509 0l45.254 45.254-331.869 331.869-45.254-45.254c-24.992-24.995-24.992-65.517 0-90.509l60.339-60.339-177.827-177.83-43.661 43.661c-17.543 17.542-45.987 17.542-63.53 0s-17.543-45.987 0-63.53l208.001-207.999zM175.090 362.144c-42.537 42.538-42.537 111.501 0 154.038 42.001 42.003 109.771 42.531 152.42 1.587l87.334 87.334-15.075 15.075c-49.987 49.987-49.987 131.034 0 181.021l67.882 67.882c12.496 12.496 32.758 12.496 45.254 0l167.936-167.933 88.013 92.003c12.218 12.771 32.474 13.219 45.245 1.002 12.771-12.214 13.219-32.47 1.002-45.242l-88.995-93.030 163.923-163.923c12.499-12.496 12.499-32.758 0-45.254l-67.882-67.882c-49.987-49.987-131.030-49.987-181.018 0l-15.907 15.907-87.325-87.323c41.766-42.596 41.51-110.983-0.768-153.262-42.538-42.537-111.504-42.537-154.042 0l-207.998 208z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pin"],"defaultCode":59808,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1080,"name":"pin","prevSize":32,"id":168,"code":59808},"setIdx":0,"setId":6,"iconIdx":169},{"icon":{"paths":["M512.608 128.019c-72.378-1.376-144.906 25.78-199.307 80.524-54.654 54.999-89.301 136.056-89.301 239.464 0 80.234 44.5 174.87 97.546 252.806 53.066 77.965 120.829 148.157 176.141 175.821l15.194 7.6 14.81-8.326c217.158-122.154 272.31-333.882 272.31-427.898 0-101.731-27.923-181.776-80.179-236.932-52.346-55.248-125.296-81.503-207.213-83.060zM288 448.006c0-88.589 29.353-152.745 70.698-194.351 41.6-41.862 97.072-62.705 152.694-61.648 68.992 1.311 124.038 23.054 161.968 63.088 38.019 40.126 62.64 102.649 62.64 192.914 0 74.55-44.691 253.677-224.176 363.030-39.683-25.61-92.186-79.853-137.37-146.237-50.954-74.864-86.454-156.221-86.454-216.797zM544 416c0-17.674-14.326-32-32-32s-32 14.326-32 32c0 17.674 14.326 32 32 32s32-14.326 32-32zM608 416c0 53.021-42.979 96-96 96s-96-42.979-96-96c0-53.021 42.979-96 96-96s96 42.979 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pin-map"],"defaultCode":59807,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1081,"name":"pin-map","prevSize":32,"id":169,"code":59807},"setIdx":0,"setId":6,"iconIdx":170},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM451.85 357.187l195.254 136.768c14.208 9.949 18.496 30.87 9.581 46.726-2.432 4.326-5.706 7.981-9.581 10.694l-195.254 136.768c-14.208 9.952-32.954 5.165-41.869-10.694-3.037-5.398-4.646-11.642-4.646-18.016v-273.536c0-18.723 13.597-33.898 30.371-33.898 5.709 0 11.306 1.798 16.144 5.187z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["play"],"defaultCode":59811,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1082,"name":"play","prevSize":32,"id":170,"code":59811},"setIdx":0,"setId":6,"iconIdx":171},{"icon":{"paths":["M512 928.003c229.75 0 416-186.25 416-416s-186.25-415.999-416-415.999c-229.75 0-416 186.25-416 415.999s186.25 416 416 416zM451.846 357.19l195.258 136.768c14.205 9.952 18.496 30.874 9.578 46.73-2.429 4.323-5.706 7.978-9.578 10.691l-195.258 136.768c-14.205 9.952-32.95 5.165-41.866-10.691-3.037-5.398-4.646-11.645-4.646-18.019v-273.536c0-18.72 13.597-33.894 30.368-33.894 5.712 0 11.309 1.795 16.144 5.184z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["play-filled"],"defaultCode":59810,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1083,"name":"play-filled","prevSize":32,"id":171,"code":59810},"setIdx":0,"setId":6,"iconIdx":172},{"icon":{"paths":["M325.686 430.88l224.49 224.49-126.118 126.118-224.491-224.49 126.12-126.118zM370.941 385.626l192.115-192.117 224.49 224.491-192.115 192.115-224.49-224.49zM585.683 125.627c-12.496-12.497-32.758-12.497-45.254 0l-408.745 408.745c-12.497 12.496-12.497 32.758 0 45.254l269.746 269.747c5.229 5.229 11.818 8.269 18.63 9.123v0.067h0.57c2.278 0.243 4.576 0.243 6.851 0h440.579c17.674 0 32-14.33 32-32 0-17.674-14.326-32.003-32-32.003h-366.566l353.936-353.933c12.496-12.496 12.496-32.758 0-45.254l-269.747-269.746z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["prune"],"defaultCode":59817,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1084,"name":"prune","prevSize":32,"id":172,"code":59817},"setIdx":0,"setId":6,"iconIdx":173},{"icon":{"paths":["M230.486 636.688c-14.92-9.472-34.694-5.056-44.167 9.862-9.473 14.922-5.057 34.694 9.862 44.166l298.666 189.632c10.47 6.646 23.837 6.646 34.304 0l298.669-189.632c14.918-9.472 19.334-29.245 9.862-44.166-9.475-14.918-29.248-19.334-44.166-9.862l-281.517 178.739-281.514-178.739zM186.319 494.848c9.473-14.922 29.247-19.334 44.167-9.862l281.514 178.739 281.517-178.739c14.918-9.472 34.691-5.059 44.166 9.862 9.472 14.918 5.056 34.694-9.862 44.166l-298.669 189.632c-10.467 6.646-23.834 6.646-34.304 0l-298.666-189.632c-14.92-9.472-19.335-29.248-9.862-44.166zM529.152 143.657l298.669 189.629c9.245 5.872 14.848 16.064 14.848 27.014 0 10.954-5.603 21.146-14.848 27.014l-298.669 189.632c-10.467 6.646-23.834 6.646-34.304 0l-298.666-189.632c-9.246-5.869-14.848-16.061-14.848-27.014 0-10.95 5.602-21.142 14.848-27.014l298.666-189.629c10.47-6.647 23.837-6.647 34.304 0zM273.035 360.301l238.965 151.725 238.966-151.725-238.966-151.724-238.965 151.724z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["queue"],"defaultCode":59818,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1085,"name":"queue","prevSize":32,"id":173,"code":59818},"setIdx":0,"setId":6,"iconIdx":174},{"icon":{"paths":["M161.352 800c-11.706 0-22.477-6.39-28.087-16.666s-5.161-22.79 1.169-32.64l112.304-174.694h-69.387c-17.673 0-32-14.326-32-32v-288c0-17.673 14.327-32 32-32h255.999c17.674 0 32 14.327 32 32v288c0 6.138-1.763 12.144-5.082 17.306l-143.999 224c-5.888 9.158-16.029 14.694-26.918 14.694h-128zM332.269 561.306l-112.304 174.694h51.916l129.469-201.398v-246.602h-191.999v224h96c11.706 0 22.479 6.39 28.085 16.666 5.61 10.275 5.162 22.79-1.168 32.64zM577.35 800c-11.706 0-22.477-6.39-28.086-16.666s-5.162-22.79 1.171-32.64l112.304-174.694h-69.389c-17.67 0-32-14.326-32-32v-288c0-17.673 14.33-32 32-32h256c17.674 0 32 14.327 32 32v288c0 6.138-1.763 12.144-5.082 17.306l-144 224c-5.888 9.158-16.029 14.694-26.918 14.694h-128zM748.269 561.306l-112.304 174.694h51.917l129.469-201.398v-246.602h-192v224h96c11.706 0 22.48 6.39 28.086 16.666 5.61 10.275 5.162 22.79-1.168 32.64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["quote"],"defaultCode":59819,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1086,"name":"quote","prevSize":32,"id":174,"code":59819},"setIdx":0,"setId":6,"iconIdx":175},{"icon":{"paths":["M800 560c0 176.73-143.27 320-320 320-176.731 0-320-143.27-320-320s143.269-320 320-320v-64c-212.077 0-384 171.923-384 384s171.923 384 384 384c212.077 0 384-171.923 384-384 0-10.778-0.445-21.45-1.315-32h-64.266c1.046 10.525 1.581 21.2 1.581 32zM800 128c0-17.673-14.326-32-32-32s-32 14.327-32 32v112h-112c-17.674 0-32 14.327-32 32s14.326 32 32 32h112v112c0 17.674 14.326 32 32 32s32-14.326 32-32v-112h112c17.674 0 32-14.327 32-32s-14.326-32-32-32h-112v-112zM384 528c35.347 0 64-28.653 64-64s-28.653-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64zM640 464c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64zM329.805 605.075c-10.451-14.25-30.477-17.331-44.728-6.88s-17.333 30.477-6.882 44.73c37.658 51.35 77.754 84.624 119.178 102.662 41.741 18.179 82.797 19.99 120.362 11.651 73.469-16.307 132.211-70.87 164.070-114.314 10.451-14.253 7.37-34.278-6.88-44.73-14.253-10.451-34.278-7.37-44.73 6.88-26.81 36.557-73.664 77.994-126.33 89.686-25.501 5.661-52.643 4.474-80.938-7.85-28.608-12.461-60.381-37.187-93.123-81.837z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["reaction-add"],"defaultCode":59820,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1087,"name":"reaction-add","prevSize":32,"id":175,"code":59820},"setIdx":0,"setId":6,"iconIdx":176},{"icon":{"paths":["M832 512c0-176.73-143.27-320-320-320s-320 143.27-320 320c0 176.73 143.27 320 320 320s320-143.27 320-320zM896 512c0 212.077-171.923 384-384 384s-384-171.923-384-384c0-212.077 171.923-384 384-384s384 171.923 384 384zM512 704c-106.038 0-192-85.962-192-192s85.962-192 192-192c106.038 0 192 85.962 192 192s-85.962 192-192 192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["record"],"defaultCode":59821,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1088,"name":"record","prevSize":32,"id":176,"code":59821},"setIdx":0,"setId":6,"iconIdx":177},{"icon":{"paths":["M896 512h-63.984c0-175.414-145.754-320-328.518-320-115.27 0-215.818 57.513-274.362 144h110.768c17.674 0 32 14.326 32 32s-14.326 32-32 32h-179.904c-17.673 0-32-14.326-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v102.32c71.751-91.401 184.589-150.32 311.498-150.32 216.781 0 392.502 171.923 392.502 384 0 1.114 0.010 2.227 0 3.338v-3.338z","M127.997 512h63.986c0 175.414 145.751 320 328.519 320 115.27 0 215.818-57.514 274.358-144h-110.768c-17.67 0-32-14.326-32-32s14.33-32 32-32h179.907c17.67 0 32 14.326 32 32v192c0 17.674-14.33 32-32 32-17.674 0-32-14.326-32-32v-102.32c-71.754 91.402-184.592 150.32-311.498 150.32-216.782 0-392.505-171.923-392.505-384 0-1.082-0.009-2.166 0-3.245v3.245z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["refresh"],"defaultCode":59822,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1089,"name":"refresh","prevSize":32,"id":177,"code":59822},"setIdx":0,"setId":6,"iconIdx":178},{"icon":{"paths":["M565.802 233.862l-97.261 97.261h-187.521l-0.456 0.003c-14.696 0.208-28.717 6.186-39.042 16.637l-97.095 96.797-0.048 0.048c-7.165 7.174-12.248 16.157-14.707 25.994-2.459 9.834-2.202 20.154 0.745 29.856 2.946 9.699 8.471 18.419 15.984 25.226 7.506 6.8 16.746 11.443 26.678 13.424l125.65 25.19c5.103 1.024 10.166 0.771 14.859-0.538l162.866 162.867c1.987 1.987 4.17 3.654 6.483 5.011l22.88 114.128c1.981 9.936 6.618 19.146 13.418 26.653 6.81 7.514 15.526 13.037 25.229 15.984s20.019 3.203 29.856 0.746c9.837-2.461 18.819-7.542 25.994-14.707l96.842-97.146c10.451-10.323 16.432-24.346 16.64-39.040l0.003-0.454v-193.802c0-2.893-0.384-5.693-1.104-8.358l77.443-77.44c110.522-110.525 110.474-223.191 103.152-273.759-1.862-13.592-8.122-26.204-17.824-35.908s-22.317-15.962-35.907-17.823c-50.57-7.321-163.235-7.371-273.757 103.151zM611.056 279.117c92.138-92.138 182.144-90.373 218.947-85.121 5.254 36.804 7.018 126.811-85.12 218.948l-245.798 245.802-133.83-133.827 245.802-245.802zM404.541 395.123l-104.222 104.221-100.071-20.064 84.42-84.157h119.873zM542.89 705.446l106.909-106.906v135.61l-84.16 84.422-22.266-111.062c-0.138-0.698-0.301-1.386-0.483-2.064z","M286.325 699.699c15.297-8.851 20.524-28.426 11.674-43.725-8.85-15.296-28.426-20.522-43.723-11.674-49.486 28.63-72.438 77.786-83.25 115.523-5.52 19.267-8.252 36.813-9.619 49.539-0.687 6.397-1.037 11.661-1.217 15.424-0.090 1.885-0.137 3.402-0.162 4.499l-0.023 1.334-0.004 0.422-0.001 0.15v0.083c0 8.486 3.372 16.65 9.372 22.65 6.001 6.003 14.14 9.373 22.628 9.373v-32c0 32 0.037 32 0.048 32h0.208l0.424-0.003 1.333-0.022c1.099-0.026 2.614-0.074 4.498-0.163 3.764-0.179 9.029-0.528 15.425-1.216 12.727-1.366 30.272-4.099 49.54-9.619 37.739-10.813 86.892-33.763 115.523-83.251 8.851-15.296 3.622-34.87-11.674-43.722s-34.874-3.626-43.725 11.674c-16.669 28.813-47.164 45.011-77.751 53.776-6.095 1.744-12.005 3.139-17.55 4.25 1.111-5.546 2.505-11.456 4.251-17.549 8.763-30.589 24.961-61.085 53.775-77.754zM192 831.299l-32-0.022c0 0.013 0 0.022 32 0.022z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["rocket"],"defaultCode":59816,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1090,"id":178,"name":"rocket","prevSize":32,"code":59816},"setIdx":0,"setId":6,"iconIdx":179},{"icon":{"paths":["M713.718 450.362c0-142.689-115.824-258.362-258.701-258.362-142.878 0-258.704 115.673-258.704 258.362 0 142.691 115.826 258.365 258.704 258.365 142.877 0 258.701-115.674 258.701-258.365zM659.302 699.965c-55.645 45.475-126.774 72.762-204.285 72.762-178.271 0-322.788-144.326-322.788-322.365 0-178.035 144.517-322.362 322.788-322.362 178.269 0 322.787 144.327 322.787 322.362 0 77.408-27.318 148.442-72.854 204.013l186.838 186.592c12.608 12.589 12.608 33.002 0 45.59-12.605 12.589-33.043 12.589-45.648 0l-186.838-186.592z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["search"],"defaultCode":59823,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1091,"name":"search","prevSize":32,"id":179,"code":59823},"setIdx":0,"setId":6,"iconIdx":180},{"icon":{"paths":["M878.022 192.974c7.85 9.521 9.526 22.708 4.31 33.891l-298.669 640.002c-5.69 12.195-18.403 19.526-31.811 18.342-13.405-1.184-24.637-10.627-28.106-23.632l-81.619-306.070-285.772-142.886c-11.978-5.987-18.959-18.8-17.498-32.112s11.056-24.307 24.048-27.552l682.665-170.668c11.974-2.993 24.598 1.165 32.451 10.686zM505.821 545.968l57.082 214.051 233.027-499.35-533.58 133.395 203.606 101.802 69.51-52.131c14.141-10.605 34.198-7.741 44.8 6.4 10.605 14.138 7.741 34.195-6.4 44.8l-68.045 51.034z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["send"],"defaultCode":59825,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1092,"name":"send","prevSize":32,"id":180,"code":59825},"setIdx":0,"setId":6,"iconIdx":181},{"icon":{"paths":["M891.494 238.96l-297.475 637.446c-16.854 36.115-69.622 31.459-79.891-7.050l-66-247.498 151.248-189.059-219.994 109.997-226.833-113.418c-35.43-17.715-29.696-69.949 8.733-79.555l681.197-170.3c34.842-8.71 64.202 26.892 49.014 59.436z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["send-filled"],"defaultCode":59824,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1093,"name":"send-filled","prevSize":32,"id":181,"code":59824},"setIdx":0,"setId":6,"iconIdx":182},{"icon":{"paths":["M421.334 256c0-44.183-35.818-80-80-80s-80 35.817-80 80c0 44.183 35.817 80 80 80s80-35.817 80-80zM465.302 288c-14.211 55.206-64.326 96-123.968 96-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.327-32-32s14.327-32 32-32h89.367c14.209-55.207 64.324-96 123.968-96 59.642 0 109.757 40.793 123.968 96h430.698c17.674 0 32 14.327 32 32s-14.326 32-32 32h-430.698zM96 768c0-17.674 14.327-32 32-32h89.367c14.209-55.206 64.324-96 123.968-96 60.781 0 111.67 42.365 124.742 99.181 4.208-2.038 8.934-3.181 13.923-3.181h416c17.674 0 32 14.326 32 32s-14.326 32-32 32h-416c-4.989 0-9.715-1.142-13.923-3.181-13.072 56.816-63.962 99.181-124.742 99.181-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.326-32-32zM341.334 848c44.182 0 80-35.818 80-80s-35.818-80-80-80c-44.183 0-80 35.818-80 80s35.817 80 80 80zM796.029 543.757c-14.122 55.331-64.298 96.243-124.029 96.243s-109.904-40.912-124.029-96.243c-1.302 0.16-2.627 0.243-3.971 0.243h-416c-17.673 0-32-14.326-32-32s14.327-32 32-32h416c1.344 0 2.669 0.083 3.971 0.243 14.125-55.331 64.298-96.243 124.029-96.243s109.907 40.912 124.029 96.243c1.302-0.16 2.627-0.243 3.971-0.243h96c17.674 0 32 14.326 32 32s-14.326 32-32 32h-96c-1.344 0-2.669-0.083-3.971-0.243zM752 512c0-44.182-35.818-80-80-80s-80 35.818-80 80c0 44.182 35.818 80 80 80s80-35.818 80-80z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["settings"],"defaultCode":59826,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1094,"name":"settings","prevSize":32,"id":182,"code":59826},"setIdx":0,"setId":6,"iconIdx":183},{"icon":{"paths":["M690.176 301.708c11.645-11.977 11.645-31.396 0-43.374l-149.091-153.351c-11.645-11.977-30.525-11.977-42.17 0l-149.091 153.351c-11.645 11.977-11.645 31.397 0 43.374s30.525 11.978 42.17 0l98.189-100.993v401.343c0 16.938 13.35 30.669 29.818 30.669s29.818-13.731 29.818-30.669v-401.343l98.189 100.993c11.645 11.978 30.525 11.978 42.17 0z","M221.818 379.274h149.091v59.635h-119.272v387.635h536.728v-387.635h-119.274v-59.635h149.091c16.467 0 29.818 13.35 29.818 29.818v447.274c0 16.467-13.35 29.818-29.818 29.818h-596.364c-16.468 0-29.818-13.35-29.818-29.818v-447.274c0-16.467 13.35-29.818 29.818-29.818z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["share"],"defaultCode":59827,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1095,"name":"share","prevSize":32,"id":183,"code":59827},"setIdx":0,"setId":6,"iconIdx":184},{"icon":{"paths":["M502.627 142.69c12.915-3.408 26.509-3.289 39.363 0.345l245.194 69.317c29.165 8.245 51.254 33.818 53.504 65.14 24.506 341.145-184.394 520.422-272.611 580.214-33.053 22.403-75.28 22.474-108.416 0.259-88.758-59.504-300.1-238.589-276.51-579.794 2.205-31.89 24.96-57.772 54.753-65.633l264.724-69.849zM524.579 204.621c-1.837-0.519-3.779-0.536-5.622-0.049l-264.725 69.849c-4.4 1.161-6.999 4.775-7.233 8.165-21.305 308.166 168.214 468.531 248.301 522.218 11.507 7.715 25.434 7.677 36.87-0.077 79.379-53.798 266.835-214.288 244.685-522.649-0.243-3.358-2.787-6.925-7.082-8.139l-245.194-69.317z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["set-as-moderator"],"defaultCode":59661,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1096,"name":"shield","prevSize":32,"id":184,"code":59661},"setIdx":0,"setId":6,"iconIdx":185},{"icon":{"paths":["M513.302 142.705c12.915-3.408 26.509-3.289 39.36 0.345l245.197 69.318c29.165 8.245 51.254 33.818 53.504 65.14 24.506 341.142-184.397 520.422-272.611 580.214-33.053 22.403-75.28 22.47-108.416 0.259-88.762-59.504-300.101-238.589-276.511-579.794 2.205-31.89 24.96-57.772 54.753-65.633l264.725-69.849zM535.251 204.637c-1.834-0.519-3.776-0.536-5.622-0.050l-264.723 69.849c-4.4 1.161-6.999 4.775-7.234 8.164-21.305 308.164 168.216 468.532 248.299 522.218 11.507 7.715 25.434 7.677 36.874-0.077 79.379-53.798 266.832-214.288 244.682-522.65-0.24-3.358-2.784-6.925-7.078-8.139l-245.197-69.317z","M490.672 337.334c-19.76 4.672-47.245 12.31-81.149 24.554 20.81 108.771 53.219 187.014 81.149 238.832v-263.386zM492.867 271.316c33.77-6.898 61.805 19.742 61.805 51.125v360.963c0 17.024-10.333 31.747-25.642 37.52-15.67 5.91-33.779 1.331-44.861-12.675-32.656-41.267-106.323-152.95-141.19-354.563-3.242-18.746 7.066-37.695 25.328-44.726 56.186-21.63 99.094-32.442 124.56-37.644z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["shield"],"defaultCode":59829,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1097,"name":"shield-alt","prevSize":32,"id":185,"code":59829},"setIdx":0,"setId":6,"iconIdx":186},{"icon":{"paths":["M664.083 405.072c11.638-13.299 10.288-33.517-3.011-45.155s-33.517-10.288-45.155 3.011l-125.251 143.142-39.917-45.619c-11.638-13.299-31.853-14.646-45.155-3.011-13.299 11.638-14.646 31.856-3.008 45.155l64 73.142c6.077 6.944 14.854 10.928 24.080 10.928 9.229 0 18.006-3.984 24.083-10.928l149.334-170.666z","M541.99 143.050c-12.854-3.634-26.448-3.753-39.363-0.345l-264.724 69.849c-29.793 7.861-52.548 33.743-54.753 65.633-23.589 341.205 187.752 520.29 276.51 579.794 33.136 22.211 75.363 22.144 108.416-0.259 88.218-59.792 297.117-239.072 272.611-580.214-2.25-31.321-24.339-56.895-53.504-65.14l-245.194-69.318zM518.957 204.587c1.843-0.487 3.786-0.47 5.622 0.049l245.194 69.318c4.294 1.214 6.838 4.781 7.082 8.139 22.15 308.362-165.306 468.851-244.685 522.65-11.437 7.754-25.363 7.792-36.87 0.077-80.086-53.686-269.606-214.054-248.301-522.218 0.234-3.389 2.833-7.004 7.233-8.164l264.725-69.849z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["shield-check"],"defaultCode":59828,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1098,"name":"shield-check","prevSize":32,"id":186,"code":59828},"setIdx":0,"setId":6,"iconIdx":187},{"icon":{"paths":["M778.64 213.336c-17.674 0-32 14.327-32 32v533.333c0 17.674 14.326 32 32 32s32-14.326 32-32v-533.333c0-17.673-14.326-32-32-32z","M600.87 341.334c-17.674 0-32 14.33-32 32v405.334c0 17.674 14.326 32 32 32s32-14.326 32-32v-405.334c0-17.67-14.326-32-32-32z","M423.104 810.669c-17.674 0-32-14.326-32-32v-277.334c0-17.67 14.326-32 32-32 17.67 0 32 14.33 32 32v277.334c0 17.674-14.33 32-32 32z","M245.333 597.334c-17.673 0-32 14.33-32 32v149.334c0 17.674 14.327 32 32 32s32-14.326 32-32v-149.334c0-17.67-14.327-32-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["signal"],"defaultCode":59830,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1099,"name":"signal","prevSize":32,"id":187,"code":59830},"setIdx":0,"setId":6,"iconIdx":188},{"icon":{"paths":["M772.986 470.432h-40.186c-1.104-12.381-10.090-19.757-26.454-19.757-16.278 0-24.416 6.867-24.502 16.365-0.339 10.342 9.667 15.6 25.437 18.992l14.922 3.389c34.253 7.546 52.989 24.502 53.158 52.227-0.17 32.982-25.773 52.566-69.014 52.566-43.661 0-71.894-19.414-72.403-60.026h40.186c0.934 16.701 13.142 25.35 31.709 25.35 16.874 0 26.794-7.376 26.963-17.974-0.17-9.75-8.733-14.922-27.811-19.331l-18.141-4.24c-30.016-6.867-48.496-21.706-48.413-48.070-0.253-32.304 28.317-53.923 67.997-53.923 40.355 0 66.214 21.958 66.554 54.432z","M354.858 470.432h40.186c-0.339-32.474-26.198-54.432-66.554-54.432-39.679 0-68.251 21.619-67.996 53.923-0.085 26.365 18.398 41.203 48.411 48.070l18.145 4.24c19.075 4.41 27.638 9.581 27.808 19.331-0.17 10.598-10.090 17.974-26.96 17.974-18.569 0-30.778-8.65-31.71-25.35h-40.187c0.509 40.611 28.741 60.026 72.403 60.026 43.242 0 68.845-19.584 69.014-52.566-0.17-27.725-18.906-44.682-53.158-52.227l-14.922-3.389c-15.77-3.392-25.774-8.65-25.435-18.992 0.085-9.498 8.224-16.365 24.501-16.365 16.365 0 25.35 7.376 26.454 19.757z","M418.614 418.374v173.635h40.864v-107.251h1.443l41.712 106.15h26.112l41.715-105.555h1.44v106.656h40.867v-173.635h-51.974l-44.086 107.504h-2.035l-44.086-107.504h-51.971z","M864 192c16.973 0 33.251 6.743 45.254 18.745s18.746 28.281 18.746 45.255v635.296c0 12.186-3.478 24.122-10.032 34.397-6.55 10.278-15.898 18.474-26.947 23.619-11.046 5.146-23.334 7.027-35.418 5.43-12.083-1.6-23.456-6.614-32.787-14.458l-128.81-108.285h-534.006c-16.974 0-33.252-6.742-45.255-18.746s-18.745-28.282-18.745-45.254v-512c0-16.974 6.743-33.252 18.745-45.255s28.281-18.745 45.255-18.745h704zM864 256h-704v512h534.006c15.066 0 29.648 5.315 41.181 15.011l128.813 108.285v-635.296z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["sms"],"defaultCode":59772,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1100,"name":"sms","prevSize":32,"id":188,"code":59772},"setIdx":0,"setId":6,"iconIdx":189},{"icon":{"paths":["M919.258 667.229c12.605-12.253 12.877-32.394 0.605-44.982-12.269-12.589-32.435-12.858-45.040-0.605l-106.112 103.155v-500.8c0-17.568-14.259-31.81-31.853-31.81-17.59 0-31.85 14.242-31.85 31.81v500.8l-106.115-103.155c-12.605-12.253-32.768-11.984-45.040 0.605-12.269 12.589-11.997 32.73 0.608 44.982l160.179 155.718c12.368 12.019 32.070 12.019 44.435 0l160.182-155.718zM560.659 333.667c17.59 0 31.85-14.243 31.85-31.811s-14.259-31.809-31.85-31.809h-432.49c-17.591 0-31.852 14.242-31.852 31.809s14.26 31.811 31.852 31.811h432.49zM464.55 536.099c17.59 0 31.85-14.243 31.85-31.811 0-17.565-14.259-31.808-31.85-31.808h-336.381c-17.591 0-31.852 14.24-31.852 31.808s14.26 31.811 31.852 31.811h336.381zM384.458 722.96c17.594 0 31.853-14.24 31.853-31.808s-14.259-31.811-31.853-31.811h-256.289c-17.591 0-31.852 14.243-31.852 31.811s14.26 31.808 31.852 31.808h256.289z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["sort"],"defaultCode":59832,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1101,"name":"sort","prevSize":32,"id":189,"code":59832},"setIdx":0,"setId":6,"iconIdx":190},{"icon":{"paths":["M289.362 192c13.364 0 25.321 8.305 29.987 20.829l96.001 257.699c6.17 16.56-2.256 34.986-18.816 41.155-16.563 6.17-34.989-2.253-41.158-18.816l-20.477-54.963h-91.074l-20.476 54.963c-6.17 16.563-24.597 24.986-41.158 18.816s-24.986-24.595-18.816-41.155l96-257.699c4.666-12.524 16.622-20.829 29.987-20.829zM311.058 373.904l-21.695-58.238-21.695 58.238h43.391z","M522.131 626.435c-12.154 12.829-11.606 33.082 1.222 45.238l160 151.587c12.342 11.693 31.674 11.693 44.016 0l160-151.587c12.832-12.157 13.376-32.41 1.222-45.238s-32.41-13.376-45.238-1.222l-105.99 100.419v-501.632c0-17.673-14.326-32-32-32s-32 14.327-32 32v501.632l-105.994-100.419c-12.829-12.154-33.082-11.606-45.238 1.222z","M193.362 570.947c-17.673 0-32 14.326-32 32 0 17.67 14.327 32 32 32h116.145l-139.065 142.73c-8.979 9.216-11.565 22.915-6.564 34.771 5.001 11.853 16.617 19.562 29.484 19.562h192.001c17.674 0 32-14.326 32-32s-14.326-32-32-32h-116.146l139.064-142.733c8.979-9.216 11.565-22.915 6.563-34.768-4.998-11.856-16.614-19.562-29.482-19.562h-192.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["sort-az"],"defaultCode":59831,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1102,"name":"sort-az","prevSize":32,"id":190,"code":59831},"setIdx":0,"setId":6,"iconIdx":191},{"icon":{"paths":["M472.618 173.508c18.166-58.554 100.454-60.461 121.322-2.812l69.821 192.91h195.44c57.872 0 86.026 70.611 43.994 110.336l-147.888 139.782 53.386 217.363c14.17 57.696-51.251 101.805-99.536 67.11l-177.741-127.709-177.741 127.709c-48.283 34.691-113.703-9.414-99.533-67.11l53.209-216.64-157.591-139.024c-44.179-38.973-16.577-111.818 42.37-111.818h221.513l58.976-190.098zM603.574 385.334l-69.824-192.91-58.976 190.098c-8.304 26.758-33.085 45.002-61.133 45.002h-221.513l157.59 139.021c17.837 15.731 25.456 40.048 19.789 63.13l-53.209 216.643 177.74-127.709c22.33-16.045 52.426-16.045 74.755 0l177.738 127.709-53.386-217.363c-5.478-22.317 1.456-45.856 18.166-61.648l147.888-139.782h-195.44c-26.957 0-51.024-16.87-60.186-42.189z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["star"],"defaultCode":59834,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1103,"name":"star","prevSize":32,"id":191,"code":59834},"setIdx":0,"setId":6,"iconIdx":192},{"icon":{"paths":["M593.939 170.244c-20.867-57.726-103.155-55.816-121.322 2.815l-58.976 190.348h-221.513c-58.947 0-86.549 72.944-42.37 111.968l157.591 139.206-53.209 216.928c-14.17 57.77 51.25 101.936 99.533 67.197l177.741-127.875 177.741 127.875c48.285 34.739 113.706-9.427 99.536-67.197l-53.386-217.651 147.888-139.968c42.032-39.779 13.878-110.483-43.99-110.483h-195.443l-69.821-193.164z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["star-filled"],"defaultCode":59833,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1104,"name":"star-filled","prevSize":32,"id":192,"code":59833},"setIdx":0,"setId":6,"iconIdx":193},{"icon":{"paths":["M512 896c-212.077 0-384-171.923-384-384s171.923-384 384-384c212.077 0 384 171.923 384 384s-171.923 384-384 384zM565.334 288c0-29.455-23.878-53.333-53.334-53.333s-53.334 23.878-53.334 53.333v249.632l180.016 144.013c23.002 18.403 56.563 14.672 74.963-8.326 18.403-23.002 14.672-56.563-8.326-74.963l-139.984-111.987v-198.368z"],"attrs":[{"fill":"rgb(243, 190, 8)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":3}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":2}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":3}]},"tags":["status-away"],"defaultCode":59741,"grid":0},"attrs":[{"fill":"rgb(243, 190, 8)"}],"properties":{"order":1105,"name":"status-away","prevSize":32,"id":193,"code":59741},"setIdx":0,"setId":6,"iconIdx":194},{"icon":{"paths":["M512 896c-212.077 0-384-171.923-384-384s171.923-384 384-384c212.077 0 384 171.923 384 384s-171.923 384-384 384zM384 458.666c-29.456 0-53.334 23.875-53.334 53.331s23.878 53.334 53.334 53.334h256c29.456 0 53.334-23.878 53.334-53.334s-23.878-53.331-53.334-53.331h-256z"],"attrs":[{"fill":"rgb(245, 69, 92)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":6}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":6}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":8}]},"tags":["status-busy"],"defaultCode":59742,"grid":0},"attrs":[{"fill":"rgb(245, 69, 92)"}],"properties":{"order":1106,"name":"status-busy","prevSize":32,"id":194,"code":59742},"setIdx":0,"setId":6,"iconIdx":195},{"icon":{"paths":["M512 896c212.077 0 384-171.923 384-384s-171.923-384-384-384c-212.077 0-384 171.923-384 384s171.923 384 384 384zM554.774 298.667v298.668c0 23.562-19.101 42.666-42.666 42.666s-42.669-19.104-42.669-42.666v-298.668c0-23.564 19.104-42.667 42.669-42.667s42.666 19.102 42.666 42.667zM554.774 725.334c0 23.562-19.101 42.666-42.666 42.666s-42.669-19.104-42.669-42.666c0-23.565 19.104-42.669 42.669-42.669s42.666 19.104 42.666 42.669z"],"attrs":[{"fill":"rgb(243, 140, 57)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":5}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":7}]},"tags":["status-disabled"],"defaultCode":59837,"grid":0},"attrs":[{"fill":"rgb(243, 140, 57)"}],"properties":{"order":1107,"id":195,"name":"status-disabled","prevSize":32,"code":59837},"setIdx":0,"setId":6,"iconIdx":196},{"icon":{"paths":["M888.691 586.941l-125.568-24.838c3.187-16.102 4.877-32.842 4.877-50.102s-1.69-34-4.877-50.102l125.568-24.838c4.794 24.237 7.309 49.296 7.309 74.941s-2.515 50.704-7.309 74.941zM831.322 298.644l-106.365 71.209c-18.726-27.971-42.838-52.083-70.81-70.81l71.21-106.364c41.875 28.035 77.93 64.089 105.965 105.965zM586.941 135.309l-24.838 125.566c-16.102-3.185-32.842-4.876-50.102-4.876s-34 1.69-50.102 4.876l-24.838-125.566c24.237-4.795 49.296-7.309 74.941-7.309s50.704 2.514 74.941 7.309zM298.644 192.679l71.209 106.364c-27.971 18.727-52.083 42.839-70.81 70.81l-106.364-71.209c28.035-41.876 64.089-77.93 105.965-105.964zM135.309 437.059c-4.795 24.237-7.309 49.296-7.309 74.941s2.514 50.704 7.309 74.941l125.566-24.838c-3.185-16.102-4.876-32.842-4.876-50.102s1.69-34 4.876-50.102l-125.566-24.838zM192.679 725.357l106.364-71.21c18.727 27.971 42.839 52.083 70.81 70.81l-71.209 106.365c-41.876-28.035-77.93-64.090-105.964-105.965zM437.059 888.691l24.838-125.568c16.102 3.187 32.842 4.877 50.102 4.877s34-1.69 50.102-4.877l24.838 125.568c-24.237 4.794-49.296 7.309-74.941 7.309s-50.704-2.515-74.941-7.309zM725.357 831.322l-71.21-106.365c27.971-18.726 52.083-42.838 70.81-70.81l106.365 71.21c-28.035 41.875-64.090 77.93-105.965 105.965z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["status-loading"],"defaultCode":59743,"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":1108,"name":"status-loading","prevSize":32,"id":196,"code":59743},"setIdx":0,"setId":6,"iconIdx":197},{"icon":{"paths":["M512 789.334c-153.168 0-277.333-124.166-277.333-277.334s124.165-277.333 277.333-277.333c153.168 0 277.334 124.165 277.334 277.333s-124.166 277.334-277.334 277.334zM512 896c212.077 0 384-171.923 384-384s-171.923-384-384-384c-212.077 0-384 171.923-384 384s171.923 384 384 384z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["status-offline"],"defaultCode":59744,"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":1109,"name":"status-offline","prevSize":32,"id":197,"code":59744},"setIdx":0,"setId":6,"iconIdx":198},{"icon":{"paths":["M896 512c0 212.077-171.923 384-384 384s-384-171.923-384-384c0-212.077 171.923-384 384-384s384 171.923 384 384z"],"attrs":[{"fill":"rgb(45, 224, 165)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":4}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":3}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":5}]},"tags":["status-online"],"defaultCode":59745,"grid":0},"attrs":[{"fill":"rgb(45, 224, 165)"}],"properties":{"order":1110,"name":"status-online","prevSize":32,"id":198,"code":59745},"setIdx":0,"setId":6,"iconIdx":199},{"icon":{"paths":["M511.997 224c-114.163 0-179.555 64.46-179.555 128v0.253c-0.061 7.453 1.072 14.867 3.354 21.962 5.411 16.826-3.84 34.851-20.666 40.259-16.825 5.411-34.85-3.84-40.261-20.666-4.357-13.546-6.527-27.702-6.428-41.933 0.081-113.124 110.343-191.875 243.556-191.875 103.597 0 190.97 46.311 226.886 120.071 7.738 15.889 1.13 35.043-14.762 42.78-15.888 7.738-35.043 1.13-42.781-14.761-22.259-45.713-82.714-84.090-169.344-84.090z","M128 512c0-17.674 14.327-32 32-32h392.893c0.467-0.010 0.938-0.010 1.408 0h309.699c17.674 0 32 14.326 32 32s-14.326 32-32 32h-160.432c38.198 29.328 64.432 70.438 64.432 128.003 0 57.2-32.512 105.965-79.008 139.178-46.557 33.254-109.235 52.822-176.992 52.822s-130.435-19.568-176.992-52.822c-46.495-33.213-79.008-81.978-79.008-139.178 0-17.674 14.327-32 32-32s32 14.326 32 32c0 31.168 17.632 62.4 52.208 87.098 34.515 24.653 83.837 40.902 139.792 40.902s105.277-16.25 139.792-40.902c34.576-24.698 52.208-55.93 52.208-87.098 0-35.558-15.216-59.581-42.134-79.283-27.824-20.368-67.005-35.082-112.88-48.72h-388.986c-17.673 0-32-14.326-32-32z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{},{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["strike"],"defaultCode":59846,"grid":0},"attrs":[{},{}],"properties":{"order":1111,"name":"strike","prevSize":32,"id":199,"code":59846},"setIdx":0,"setId":6,"iconIdx":200},{"icon":{"paths":["M481.35 117.336c0-17.673 14.326-32 32-32s32 14.327 32 32v106.667c0 17.673-14.326 32-32 32s-32-14.327-32-32v-106.667zM771.392 214.631c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-75.411 75.413c-12.499 12.496-32.758 12.496-45.254 0-12.499-12.496-12.499-32.759 0-45.255l75.411-75.412zM336.73 694.63c-12.499-12.496-32.759-12.496-45.256 0l-75.495 75.498c-12.497 12.496-12.497 32.755 0 45.254 12.497 12.496 32.758 12.496 45.255 0l75.496-75.498c12.496-12.496 12.496-32.755 0-45.254zM481.35 800.003c0-17.674 14.326-32 32-32s32 14.326 32 32v106.669c0 17.67-14.326 32-32 32s-32-14.33-32-32v-106.669zM213.352 212.001c-12.497 12.497-12.497 32.758 0 45.255l75.349 75.348c12.497 12.496 32.758 12.496 45.254 0 12.499-12.496 12.496-32.757 0-45.254l-75.348-75.349c-12.497-12.497-32.758-12.497-45.255 0zM695.978 739.885c-12.496-12.496-12.496-32.758 0-45.254 12.499-12.496 32.758-12.496 45.254 0l75.331 75.328c12.496 12.496 12.496 32.758 0 45.254-12.499 12.496-32.758 12.496-45.258 0l-75.328-75.328zM87.751 512.003c0 17.674 14.327 32 32 32h106.667c17.673 0 32-14.326 32-32s-14.327-32-32-32h-106.667c-17.673 0-32 14.326-32 32zM801.35 544.003c-17.674 0-32-14.326-32-32s14.326-32 32-32h106.669c17.67 0 32 14.326 32 32s-14.33 32-32 32h-106.669zM668.17 512c0-85.504-69.315-154.816-154.819-154.816-85.507 0-154.819 69.312-154.819 154.816 0 85.507 69.312 154.819 154.819 154.819 85.504 0 154.819-69.312 154.819-154.819zM726.682 512c0 117.821-95.51 213.334-213.331 213.334s-213.335-95.514-213.335-213.334c0-117.821 95.514-213.332 213.335-213.332s213.331 95.511 213.331 213.332z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["sun"],"defaultCode":59847,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1112,"name":"sun","prevSize":32,"id":200,"code":59847},"setIdx":0,"setId":6,"iconIdx":201},{"icon":{"paths":["M930.704 512c0 229.75-186.25 416-416 416s-415.999-186.25-415.999-416c0-229.75 186.25-416 415.999-416s416 186.25 416 416zM570.49 859.603l-41.827-156.102c-4.611 0.33-9.264 0.499-13.958 0.499-4.57 0-9.101-0.16-13.594-0.474l-41.837 156.134c18.058 2.854 36.573 4.339 55.43 4.339 18.986 0 37.616-1.504 55.786-4.397zM438.893 688.451c-47.549-20.454-85.181-59.571-103.674-108.125l-155.029 41.539c33.968 103.485 114.617 185.805 217.045 222.058l41.658-155.472zM162.705 512c0 16.090 1.080 31.926 3.17 47.443l156.906-42.042c-0.051-1.795-0.077-3.594-0.077-5.402 0-4.909 0.186-9.776 0.547-14.595l-156.051-41.814c-2.958 18.368-4.496 37.21-4.496 56.41zM396.31 180.407c-99.16 35.408-177.786 114.033-213.196 213.19l155.535 41.677c19.357-44.352 54.982-79.978 99.334-99.331l-41.674-155.536zM514.704 160c-19.197 0-38.035 1.537-56.4 4.494l41.814 156.053c4.813-0.362 9.68-0.547 14.586-0.547 5.030 0 10.019 0.192 14.95 0.573l41.808-156.021c-18.477-2.995-37.437-4.552-56.758-4.552zM632.512 843.802c102.659-36.451 183.392-119.194 217.094-223.12l-154.973-41.526c-18.291 48.982-56.010 88.493-103.786 109.155l41.664 155.491zM863.699 558.198c1.984-15.117 3.005-30.538 3.005-46.198 0-18.771-1.469-37.197-4.298-55.171l-156.157 41.84c0.301 4.406 0.454 8.851 0.454 13.331 0 1.376-0.013 2.752-0.042 4.122l157.037 42.077zM846.714 394.774c-35.165-99.6-113.885-178.641-213.277-214.247l-41.68 155.559c44.582 19.555 80.314 55.565 99.504 100.342l155.453-41.654zM642.704 512c0-70.691-57.306-128-128-128-70.691 0-128 57.309-128 128s57.309 128 128 128c70.694 0 128-57.309 128-128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["support"],"defaultCode":59848,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1113,"name":"support","prevSize":32,"id":201,"code":59848},"setIdx":0,"setId":6,"iconIdx":202},{"icon":{"paths":["M368 412.982c-53.592 0-96-42.877-96-94.491 0-51.616 42.408-94.491 96-94.491 53.594 0 96 42.876 96 94.491 0 51.614-42.406 94.491-96 94.491zM368 476.982c88.365 0 160-70.96 160-158.491s-71.635-158.491-160-158.491c-88.365 0-160 70.959-160 158.491s71.635 158.491 160 158.491zM713.6 397.133c-35.92 0-64-28.685-64-62.794s28.080-62.792 64-62.792c35.92 0 64 28.684 64 62.792s-28.080 62.794-64 62.794zM713.6 461.133c70.691 0 128-56.768 128-126.794s-57.309-126.792-128-126.792c-70.691 0-128 56.767-128 126.792s57.309 126.794 128 126.794zM197.459 527.267c27.344-8.707 56.67-9.242 84.319-1.539l48.491 13.51c24.205 6.742 49.882 6.275 73.824-1.347l30.099-9.584c29.475-9.386 61.085-9.962 90.89-1.658 67.962 18.934 114.918 80.333 114.918 150.269v91.987c0 52.518-42.979 95.094-96 95.094h-352c-53.019 0-96-42.576-96-95.094v-103.766c0-62.909 40.999-118.621 101.459-137.872zM264.451 586.758c-15.545-4.333-32.034-4.032-47.407 0.864-33.993 10.822-57.044 42.147-57.044 77.517v103.766c0 17.507 14.327 31.699 32 31.699h352c17.674 0 32-14.192 32-31.699v-91.987c0-41.533-27.885-77.997-68.246-89.242-17.699-4.931-36.474-4.589-53.978 0.986l-30.099 9.584c-35.91 11.434-74.426 12.138-110.737 2.019l-48.489-13.507zM691.2 778.717h140.8c53.021 0 96-42.979 96-96v-30.611c0-56.877-38.614-106.49-93.747-120.454-21.398-5.418-43.853-5.040-65.056 1.098l-16.4 4.746c-21.843 6.323-44.973 6.714-67.018 1.13l-29.805-7.549c-19.907-5.043-40.797-4.691-60.522 1.018-1.066 0.31-2.122 0.634-3.174 0.97 10.71 4.048 20.896 9.539 30.253 16.374l2.429 1.776 15.040 13.206c9.939 8.726 18.141 19.248 24.182 31.014l2.208 4.301 3.677 0.931c33.062 8.374 67.76 7.789 100.525-1.693l16.4-4.749c10.282-2.976 21.171-3.158 31.546-0.531 26.736 6.771 45.462 30.832 45.462 58.413v30.611c0 17.674-14.326 32-32 32h-140.8v64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["team"],"defaultCode":59849,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1114,"name":"team","prevSize":32,"id":202,"code":59849},"setIdx":0,"setId":6,"iconIdx":203},{"icon":{"paths":["M281.184 336c17.673 0 32-14.326 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM281.184 400c-53.020 0-96-42.979-96-96 0-53.019 42.98-96 96-96 53.018 0 96 42.981 96 96 0 53.021-42.982 96-96 96zM576 320c0-26.51-21.491-48-48-48s-48 21.49-48 48c0 26.509 21.491 48 48 48s48-21.491 48-48zM640 320c0 61.856-50.144 112-112 112s-112-50.144-112-112c0-61.856 50.144-112 112-112s112 50.144 112 112zM477.901 478.515c-28.56-10.957-60.291-10.211-88.307 2.067-42.282 18.534-69.594 60.326-69.594 106.49v132.928c0 53.021 42.979 96 96 96h224c53.021 0 96-42.979 96-96v-125.062c0-51.162-31.536-97.034-79.306-115.354-30.352-11.642-64.067-10.851-93.84 2.198l-2.070 0.909c-21.523 9.434-45.901 10.006-67.843 1.59l-15.040-5.766zM415.286 539.2c12.595-5.52 26.858-5.856 39.699-0.931l15.040 5.77c37.664 14.445 79.504 13.462 116.451-2.73l2.070-0.909c14.349-6.288 30.602-6.669 45.229-1.059 23.024 8.829 38.224 30.938 38.224 55.597v125.062c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32v-132.928c0-20.752 12.278-39.539 31.286-47.872zM768 336c-17.674 0-32-14.326-32-32s14.326-32 32-32c17.674 0 32 14.327 32 32s-14.326 32-32 32zM768 400c53.021 0 96-42.979 96-96 0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96zM840.714 681.766h-72.714v-64h72.714c17.674 0 32-14.326 32-32v-44.688c0-15.050-9.664-28.394-23.958-33.091-7.536-2.474-15.69-2.304-23.114 0.483l-4.554 1.709c-19.77 7.421-40.89 9.978-61.619 7.632-12.438-31.683-37.722-57.549-70.774-70.227-1.754-0.672-3.52-1.302-5.296-1.894 18.058-5.312 37.36-5.040 55.344 0.867l14.182 4.659c14.886 4.893 30.998 4.554 45.667-0.954l4.554-1.709c21.069-7.91 44.205-8.394 65.581-1.37 40.566 13.325 67.987 51.197 67.987 93.894v44.688c0 53.021-42.982 96-96 96zM625.267 624h-0.797c0.259 0.598 0.525 1.194 0.797 1.786v-1.786zM357.594 448.582c2.528-1.107 5.088-2.122 7.674-3.043-17.907-5.155-37.014-4.832-54.824 1.018l-14.183 4.659c-14.887 4.893-30.998 4.554-45.668-0.954l-4.554-1.709c-21.067-7.91-44.203-8.394-65.581-1.37-40.565 13.325-67.986 51.197-67.986 93.894v44.688c0 53.021 42.981 96 96 96h79.53v-64h-79.53c-17.673 0-32-14.326-32-32v-44.688c0-15.050 9.664-28.394 23.96-33.091 7.534-2.474 15.688-2.304 23.112 0.483l4.554 1.709c21.238 7.974 44.041 10.333 66.238 7.027 10.398-30.173 32.994-55.357 63.259-68.624zM423.917 624h0.797c-0.259 0.598-0.525 1.194-0.797 1.786v-1.786z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["teams"],"defaultCode":59751,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1115,"name":"teams","prevSize":32,"id":203,"code":59751},"setIdx":0,"setId":6,"iconIdx":204},{"icon":{"paths":["M631.997 256h24v-56c0-57.437 46.563-104 104-104 57.44 0 104 46.562 104 104v56h24c17.674 0 32 14.327 32 32v192c0 17.674-14.326 32-32 32h-256c-17.67 0-32-14.326-32-32v-192c0-17.673 14.33-32 32-32zM759.997 160c-22.090 0-40 17.908-40 40v55.238h80v-55.238c0-22.092-17.907-40-40-40z","M527.997 224c10.096 0 19.882 1.336 29.184 3.84-13.251 16.46-21.184 37.383-21.184 60.16v0.664c-2.602-0.436-5.274-0.664-8-0.664-26.509 0-48 21.49-48 48s21.491 48 48 48c2.726 0 5.398-0.227 8-0.662v64.381c-2.64 0.186-5.309 0.282-8 0.282-61.856 0-112-50.144-112-112s50.144-112 112-112z","M492.941 500.282c14.883 5.709 30.883 7.283 46.355 4.758 6.182 22.938 20.646 42.474 39.987 55.206-35.123 13.318-74.019 13.309-109.261-0.208l-15.040-5.77c-12.838-4.925-27.104-4.589-39.699 0.931-19.008 8.333-31.286 27.12-31.286 47.872v132.928c0 17.674 14.33 32 32 32h224c17.674 0 32-14.326 32-32v-125.062c0-12.842-4.122-24.995-11.325-34.938h70.291c3.29 11.162 5.034 22.902 5.034 34.938v125.062c0 53.021-42.979 96-96 96h-224c-53.018 0-95.999-42.979-95.999-96v-132.928c0-46.163 27.311-87.955 69.592-106.49 28.019-12.278 59.747-13.024 88.31-2.067l15.040 5.766z","M887.997 576h-15.286v25.766c0 17.674-14.326 32-32 32h-72.714v64h72.714c53.021 0 96-42.979 96-96v-39.027c-14.278 8.426-30.931 13.261-48.714 13.261z","M281.182 416c53.020 0 95.999-42.979 95.999-96 0-53.019-42.979-96-95.999-96s-96 42.981-96 96c0 53.021 42.98 96 96 96zM281.182 352c-17.673 0-32-14.326-32-32s14.327-32 32-32c17.673 0 32 14.327 32 32s-14.327 32-32 32z","M625.267 640h-0.8c0.262 0.598 0.528 1.194 0.8 1.786v-1.786z","M357.59 464.582c2.531-1.107 5.091-2.122 7.674-3.043-17.907-5.155-37.011-4.832-54.823 1.018l-14.183 4.659c-14.887 4.893-30.998 4.554-45.668-0.954l-4.554-1.709c-21.067-7.91-44.203-8.394-65.581-1.37-40.565 13.325-67.986 51.197-67.986 93.894v44.688c0 53.021 42.98 96 96 96h79.53v-64h-79.53c-17.673 0-32-14.326-32-32v-44.688c0-15.050 9.664-28.394 23.96-33.091 7.534-2.474 15.688-2.304 23.112 0.483l4.554 1.709c21.238 7.974 44.041 10.333 66.238 7.027 10.398-30.173 32.992-55.357 63.258-68.624z","M423.914 640h0.797c-0.259 0.598-0.525 1.194-0.797 1.786v-1.786z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["teams-private"],"defaultCode":59750,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1116,"name":"teams-private","prevSize":32,"id":204,"code":59750},"setIdx":0,"setId":6,"iconIdx":205},{"icon":{"paths":["M170.664 192c0-17.673 14.327-32 32-32h618.667c17.674 0 32 14.327 32 32v128c0 17.674-14.326 32-32 32s-32-14.326-32-32v-96h-245.334v576h96c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.67 0-32-14.326-32-32s14.33-32 32-32h96v-576h-245.333v96c0 17.674-14.327 32-32 32s-32-14.326-32-32v-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["text-format"],"defaultCode":59839,"grid":0},"attrs":[{}],"properties":{"order":1117,"id":205,"name":"text-format","prevSize":32,"code":59839},"setIdx":0,"setId":6,"iconIdx":206},{"icon":{"paths":["M223.311 308.609c-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-9.348 103.235 27.547 175.997 86.848 226.374 60.642 51.52 146.602 80.998 235.29 90.893 88.611 9.885 186.221 1.398 263.341-14.973 38.56-8.189 70.928-18.125 93.888-28.128 8.906-3.882 15.837-7.536 20.941-10.765-2.374-1.514-5.245-3.197-8.672-5.030-8.886-4.749-19.059-9.261-29.613-13.894l-1.843-0.81c-9.315-4.083-19.725-8.65-27.613-13.078-14.291-8.026-28.317-17.155-38.544-26.867-5.034-4.781-10.762-11.194-14.595-19.184-4.054-8.454-6.96-21.078-1.261-34.435 30.816-72.186 45.459-111.725 52.554-137.834 6.621-24.378 6.621-36.653 6.621-56.17v-0.179c0-15.51-8.979-86.595-53.776-152.876-43.376-64.174-121.398-125.729-264.832-125.729-129.725 0-207.83 53.576-254.529 118.696zM173.267 272.433c58.132-81.063 154.749-144.433 304.573-144.433 164.896 0 261.594 72.589 315.859 152.878 52.838 78.181 64.416 161.881 64.416 187.641 0 21.654-0.022 40.336-8.797 72.64-7.834 28.835-22.627 68.614-50.048 133.424 5.069 4.032 12.592 9.005 22.506 14.57 5.12 2.877 12.995 6.339 24.054 11.194 10.266 4.506 22.582 9.93 33.891 15.978 10.848 5.798 23.526 13.571 32.954 23.738 9.859 10.63 20.208 28.87 12.816 51.139-4.87 14.672-16.182 25.091-25.61 32.016-10.24 7.52-22.947 14.278-36.858 20.342-27.949 12.176-64.582 23.181-105.68 31.907-82.198 17.453-186.522 26.688-282.909 15.936-96.31-10.746-195.346-43.178-268.313-105.165-74.031-62.893-119.295-154.778-108.551-277.856 0.276-63.411 19.117-157.053 75.696-235.948zM333.952 422.051c0-17.648 14.25-31.955 31.83-31.955h183.008c17.578 0 31.827 14.307 31.827 31.955s-14.25 31.955-31.827 31.955h-183.008c-17.581 0-31.83-14.307-31.83-31.955zM365.782 539.709c-17.581 0-31.83 14.307-31.83 31.955s14.25 31.955 31.83 31.955h224.118c17.578 0 31.827-14.307 31.827-31.955s-14.25-31.955-31.827-31.955h-224.118z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["threads"],"defaultCode":59850,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1118,"name":"threads","prevSize":32,"id":206,"code":59850},"setIdx":0,"setId":6,"iconIdx":207},{"icon":{"paths":["M353.354 320c0-17.673 14.326-32 32-32h256c17.674 0 32 14.327 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M385.354 416c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M481.354 448c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M641.354 416c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M353.354 576c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M513.354 544c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M609.354 576c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M385.354 672c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M481.354 704c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M641.354 672c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M289.353 160h448.001c35.344 0 64 28.654 64 64v576c0 35.347-28.656 64-64 64h-448.001c-35.346 0-64-28.653-64-64v-576c0-35.346 28.654-64 64-64zM289.353 224v576h448.001v-576h-448.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["total"],"defaultCode":59851,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1119,"name":"total","prevSize":32,"id":207,"code":59851},"setIdx":0,"setId":6,"iconIdx":208},{"icon":{"paths":["M713.613 91.356c13.162-11.794 33.392-10.685 45.187 2.477l129.034 144c10.89 12.154 10.89 30.556 0 42.71l-129.034 144.001c-11.795 13.162-32.026 14.269-45.187 2.477-13.162-11.795-14.272-32.026-2.477-45.187l81.222-90.646h-216.358c-17.674 0-32-14.327-32-32s14.326-32 32-32h216.358l-81.222-90.645c-11.795-13.162-10.685-33.393 2.477-45.187zM340.026 464.461c8.586-15.45 28.067-21.018 43.514-12.432l128.461 71.366 128.461-71.366c15.446-8.586 34.928-3.018 43.514 12.432 8.582 15.45 3.014 34.931-12.435 43.514l-159.539 88.634-159.539-88.634c-15.45-8.582-21.018-28.064-12.435-43.514zM192 288v448h640v-192c0-17.674 14.326-32 32-32s32 14.326 32 32v224c0 17.674-14.326 32-32 32h-704c-17.673 0-32-14.326-32-32v-512c0-17.673 14.327-32 32-32h272c17.674 0 32 14.327 32 32s-14.326 32-32 32h-240z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["transcript"],"defaultCode":59852,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1120,"name":"transcript","prevSize":32,"id":208,"code":59852},"setIdx":0,"setId":6,"iconIdx":209},{"icon":{"paths":["M378.861 853.331c317.456 0 491.091-262.662 491.091-490.442 0-7.462 0-14.89-0.506-22.282 33.779-24.401 62.938-54.614 86.112-89.224-31.501 13.94-64.918 23.082-99.136 27.12 36.032-21.542 62.998-55.424 75.882-95.34-33.878 20.078-70.944 34.228-109.597 41.839-53.501-56.814-138.515-70.72-207.37-33.919-68.851 36.801-104.426 115.155-86.768 191.127-138.774-6.947-268.074-72.409-355.715-180.093-45.811 78.76-22.412 179.517 53.436 230.1-27.467-0.813-54.335-8.214-78.337-21.574 0 0.704 0 1.443 0 2.182 0.022 82.051 57.937 152.723 138.47 168.97-25.41 6.922-52.071 7.933-77.933 2.957 22.611 70.218 87.409 118.32 161.25 119.706-61.116 47.968-136.616 74.010-214.35 73.933-13.732-0.026-27.452-0.858-41.087-2.486 78.931 50.586 170.772 77.418 264.557 77.293z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["twitter-monochromatic"],"defaultCode":59660,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1121,"name":"twitter-monochromatic","prevSize":32,"id":209,"code":59660},"setIdx":0,"setId":6,"iconIdx":210},{"icon":{"paths":["M384 320c0-17.673-14.326-32-32-32s-32 14.327-32 32v256c0 106.038 85.962 192 192 192s192-85.962 192-192v-256c0-17.673-14.326-32-32-32s-32 14.327-32 32v256c0 70.691-57.309 128-128 128s-128-57.309-128-128v-256zM352 856c-13.254 0-24 10.746-24 24s10.746 24 24 24h320c13.254 0 24-10.746 24-24s-10.746-24-24-24h-320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["underline"],"defaultCode":59853,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1122,"name":"underline","prevSize":32,"id":210,"code":59853},"setIdx":0,"setId":6,"iconIdx":211},{"icon":{"paths":["M512 832c176.73 0 320-143.27 320-320s-143.27-320-320-320c-111.712 0-210.056 57.244-267.295 144h107.295c17.674 0 32 14.326 32 32s-14.326 32-32 32h-176c-17.673 0-32-14.326-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v101.364c70.228-90.856 180.282-149.364 304-149.364 212.077 0 384 171.923 384 384s-171.923 384-384 384c-212.077 0-384-171.923-384-384h64c0 176.73 143.27 320 320 320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["undo"],"defaultCode":59854,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1123,"name":"undo","prevSize":32,"id":211,"code":59854},"setIdx":0,"setId":6,"iconIdx":212},{"icon":{"paths":["M589.36 729.43c-107.366 23.603-252.288-9.875-422.339-221.158 65.137-95.478 165.885-189.15 280.79-213.871 108.314-23.302 251.286 10.604 413.674 221.404-61.546 95.187-158.653 188.682-272.125 213.626zM916.819 482.714c-347.59-456.963-669.742-211.156-808.018-2.662-12.655 19.082-10.846 44.304 3.402 62.227 362.786 456.419 677.038 209.142 808.011 0.563 11.674-18.589 9.894-42.656-3.395-60.128zM619.462 512c0-53.709-45.517-100.57-105.834-100.57s-105.834 46.861-105.834 100.57c0 53.709 45.517 100.573 105.834 100.573s105.834-46.864 105.834-100.573zM683.546 512c0 90.893-76.074 164.573-169.917 164.573s-169.917-73.68-169.917-164.573c0-90.89 76.074-164.57 169.917-164.57s169.917 73.68 169.917 164.57z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["unread-on-top"],"defaultCode":59857,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1124,"name":"unread-on-top","prevSize":32,"id":212,"code":59857},"setIdx":0,"setId":6,"iconIdx":213},{"icon":{"paths":["M829.168 153.372c12.515-12.497 32.803-12.497 45.315 0 12.515 12.497 12.515 32.758 0 45.255l-672.887 672c-12.513 12.496-32.801 12.496-45.315 0s-12.513-32.758 0-45.254l672.887-672zM110.155 480.051c101.936-153.699 303.797-327.676 542.114-225.436l-49.578 49.512c-56.528-19.209-108.077-19.504-153.526-9.726-114.906 24.721-215.653 118.392-280.79 213.871 38.633 48 75.969 86.822 111.862 117.885l-45.363 45.302c-39.684-34.736-80.189-77.437-121.317-129.181-14.248-17.923-16.056-43.146-3.402-62.227zM797.981 350.454l-45.328 45.27c35.546 31.427 72.336 70.947 110.186 120.080-61.546 95.187-158.656 188.682-272.125 213.626-46.752 10.278-100.624 9.734-160.592-11.603l-49.331 49.267c244.662 107.334 443.389-69.158 540.778-224.253 11.674-18.589 9.894-42.656-3.395-60.128-40.493-53.235-80.64-96.931-120.192-132.259zM514.982 347.43c13.709 0 27.037 1.571 39.802 4.541l-203.738 203.469c-3.901-13.837-5.981-28.403-5.981-43.44 0-90.89 76.074-164.57 169.917-164.57zM679.091 469.184l-203.264 202.998c12.57 2.87 25.68 4.39 39.155 4.39 93.843 0 169.917-73.68 169.917-164.573 0-14.81-2.019-29.162-5.808-42.816z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["unread-on-top-disabled"],"defaultCode":59856,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1125,"name":"unread-on-top-disabled","prevSize":32,"id":213,"code":59856},"setIdx":0,"setId":6,"iconIdx":214},{"icon":{"paths":["M273.128 356.678c-6.62 27.766-2.384 63.757 25.498 105.581l33.166 49.75h-59.792c-44.011 0-70.484 14.874-86.279 33.619-16.496 19.578-24.573 47.264-23.734 77.491 0.841 30.262 10.601 59.968 25.818 81.312 15.127 21.216 33.404 31.578 52.195 31.578h143.999v64h-144c-45.209 0-80.932-25.642-104.306-58.426-23.283-32.656-36.522-74.95-37.682-116.688-1.16-41.773 9.763-86.083 38.766-120.506 20.726-24.598 49.155-42.32 84.825-50.784-16.1-39.011-19.009-77.050-10.731-111.77 11.253-47.2 42.305-84.492 80.791-107.342 38.4-22.798 85.677-32.139 131.303-21.965 35.584 7.935 68.909 27.48 95.251 59.554 53.75-35.147 127.584-30.892 182.483-2.495 34.438 17.812 64.794 46.382 81.437 85.010 12.294 28.531 16.438 61.011 10.608 96.205 46.112 6.682 81.507 25.155 105.616 53.456 30.346 35.626 38.102 81.35 33.443 123.283-4.659 41.917-21.946 83.485-46.544 115.114-24.061 30.934-59.354 57.354-101.261 57.354h-144v-64h144c14.093 0 32.8-9.581 50.742-32.646 17.398-22.371 30.112-52.806 33.453-82.89 3.341-30.067-2.902-56.339-18.554-74.714-15.222-17.869-44.035-33.75-97.642-33.75h-45.686l15.613-42.938c13.546-37.251 11.091-66.742 1.437-89.149-9.856-22.87-28.502-41.302-52.064-53.488-49.587-25.649-107.475-18.625-134.717 14.064l-30.134 36.16-22.541-41.325c-19.757-36.219-47.232-54.175-74.87-60.339-28.378-6.327-59.098-0.669-84.701 14.53-25.512 15.148-44.461 38.855-51.208 67.152zM630.979 588.778l-96-99.050c-6.029-6.218-14.32-9.728-22.979-9.728s-16.95 3.51-22.979 9.728l-96 99.050c-12.298 12.691-11.981 32.95 0.707 45.251 12.691 12.298 32.95 11.981 45.251-0.707l41.021-42.326v273.005c0 17.674 14.326 32 32 32s32-14.326 32-32v-273.005l41.021 42.326c12.301 12.688 32.56 13.005 45.251 0.707 12.691-12.301 13.005-32.56 0.707-45.251z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["upload"],"defaultCode":59858,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1126,"name":"upload","prevSize":32,"id":214,"code":59858},"setIdx":0,"setId":6,"iconIdx":215},{"icon":{"paths":["M609.354 336c0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96s96-42.979 96-96zM673.354 336c0 88.365-71.635 160-160 160s-160-71.635-160-160c0-88.365 71.635-160 160-160s160 71.635 160 160zM413.805 551.802c-24.621-5.77-50.285-5.366-74.714 1.178-67.086 17.968-113.738 78.762-113.738 148.211v66.81c0 53.021 42.98 96 96 96h384c53.021 0 96-42.979 96-96v-58.531c0-74.301-51.149-138.826-123.488-155.779l-6.458-1.514c-25.674-6.016-52.435-5.594-77.907 1.229l-49.626 13.293c-20.378 5.456-41.789 5.795-62.326 0.979l-67.744-15.875zM355.651 614.8c14.237-3.814 29.197-4.051 43.549-0.688l67.744 15.878c30.806 7.219 62.925 6.714 93.488-1.472l49.629-13.293c15.283-4.096 31.341-4.349 46.742-0.736l6.458 1.51c43.402 10.173 74.093 48.89 74.093 93.469v58.531c0 17.674-14.326 32-32 32h-384c-17.673 0-32-14.326-32-32v-66.81c0-40.483 27.193-75.917 66.298-86.39z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["user"],"defaultCode":59861,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1127,"name":"user","prevSize":32,"id":215,"code":59861},"setIdx":0,"setId":6,"iconIdx":216},{"icon":{"paths":["M553.411 326.282c0 91.578-75.846 165.818-169.411 165.818-93.564 0-169.412-74.24-169.412-165.818 0-91.581 75.848-165.821 169.412-165.821 93.565 0 169.411 74.24 169.411 165.821zM485.648 326.282c0-54.949-45.51-99.493-101.648-99.493s-101.647 44.544-101.647 99.493c0 54.947 45.509 99.491 101.647 99.491s101.648-44.544 101.648-99.491z","M203.427 511.232c28.952-9.11 60.004-9.67 89.279-1.61l51.342 14.131c25.632 7.056 52.819 6.566 78.166-1.408l31.872-10.026c31.206-9.821 64.678-10.422 96.234-1.738 71.962 19.811 121.68 84.051 121.68 157.219v96.24c0 54.947-45.51 99.491-101.648 99.491h-372.705c-56.138 0-101.647-44.544-101.647-99.491v-108.566c0-65.814 43.411-124.106 107.427-144.243zM274.359 573.472c-16.46-4.531-33.918-4.218-50.196 0.906-35.992 11.322-60.399 44.093-60.399 81.098v108.566c0 18.317 15.17 33.165 33.882 33.165h372.705c18.714 0 33.882-14.848 33.882-33.165v-96.24c0-43.453-29.523-81.603-72.259-93.366-18.739-5.158-38.618-4.8-57.152 1.030l-31.872 10.026c-38.022 11.962-78.803 12.698-117.248 2.115l-51.343-14.134z","M797.091 189.321c0-15.913-13.024-28.812-29.091-28.812s-29.091 12.9-29.091 28.812v100.844h-101.818c-16.067 0-29.091 12.9-29.091 28.812s13.024 28.812 29.091 28.812h101.818v100.845c0 15.914 13.024 28.813 29.091 28.813s29.091-12.899 29.091-28.813v-100.845h101.818c16.067 0 29.091-12.899 29.091-28.812s-13.024-28.812-29.091-28.812h-101.818v-100.844z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["user-add"],"defaultCode":59859,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1128,"name":"user-add","prevSize":32,"id":216,"code":59859},"setIdx":0,"setId":6,"iconIdx":217},{"icon":{"paths":["M464 318.747c0-51.548-42.406-94.366-96-94.366-53.592 0-96 42.819-96 94.366s42.408 94.367 96 94.367c53.594 0 96-42.819 96-94.367zM528 318.747c0 87.416-71.635 158.284-160 158.284s-160-70.867-160-158.284c0-87.417 71.635-158.282 160-158.282s160 70.865 160 158.282zM281.778 525.712c-27.649-7.693-56.976-7.158-84.319 1.536-60.46 19.226-101.459 74.864-101.459 137.69v103.629c0 52.451 42.981 94.97 96 94.97h352c3.606 0 7.165-0.195 10.666-0.579v-64.534c-3.334 1.168-6.925 1.802-10.666 1.802h-352c-17.673 0-32-14.173-32-31.658v-103.629c0-35.325 23.051-66.605 57.044-77.414 15.373-4.89 31.862-5.187 47.407-0.864l48.489 13.491c36.311 10.102 74.827 9.402 110.737-2.016l30.099-9.571c17.504-5.568 36.278-5.91 53.978-0.986 18.899 5.261 35.066 16.042 46.912 30.282v-79.712c-9.309-4.749-19.203-8.627-29.584-11.517-29.805-8.291-61.414-7.715-90.89 1.654l-30.099 9.574c-23.942 7.61-49.619 8.080-73.824 1.344l-48.491-13.491zM763.366 489.709c-12.326-12.646-32.586-12.918-45.248-0.608-12.666 12.31-12.938 32.544-0.611 45.19l102.842 105.51h-324.349c-17.674 0-32 14.307-32 31.958 0 17.648 14.326 31.958 32 31.958h324.349l-102.842 105.507c-12.326 12.65-12.054 32.88 0.611 45.194 12.662 12.31 32.922 12.038 45.248-0.611l155.718-159.757c12.093-12.406 12.093-32.176 0-44.582l-155.718-159.76z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["user-forward"],"defaultCode":59860,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1129,"name":"user-forward","prevSize":32,"id":217,"code":59860},"setIdx":0,"setId":6,"iconIdx":218},{"icon":{"paths":["M201.583 672c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 576c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M201.583 480c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 384c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M201.583 288c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M329.584 192c-17.674 0-32.001 14.327-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.327 32-32s-14.326-32-32-32h-544z","M201.583 864c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 768c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["view-condensed"],"defaultCode":59862,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1130,"name":"view-condensed","prevSize":32,"id":218,"code":59862},"setIdx":0,"setId":6,"iconIdx":219},{"icon":{"paths":["M288 192c0-17.673 14.327-32 32-32h544c17.674 0 32 14.327 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 288c0-17.673 14.327-32 32-32h448c17.674 0 32 14.327 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 304c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M288 464c0-17.674 14.327-32 32-32h544c17.674 0 32 14.326 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.326-32-32zM288 560c0-17.674 14.327-32 32-32h448c17.674 0 32 14.326 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.326-32-32zM192 576c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M288 736c0-17.674 14.327-32 32-32h544c17.674 0 32 14.326 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.326-32-32zM288 832c0-17.674 14.327-32 32-32h448c17.674 0 32 14.326 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.326-32-32zM192 848c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["view-extended"],"defaultCode":59863,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1131,"name":"view-extended","prevSize":32,"id":219,"code":59863},"setIdx":0,"setId":6,"iconIdx":220},{"icon":{"paths":["M192 320c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M320 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.674 0 32-14.327 32-32s-14.326-32-32-32h-544z","M192 576c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M320 480c-17.673 0-32 14.326-32 32s14.327 32 32 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M192 832c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M320 736c-17.673 0-32 14.326-32 32s14.327 32 32 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["view-medium"],"defaultCode":59864,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1132,"name":"view-medium","prevSize":32,"id":220,"code":59864},"setIdx":0,"setId":6,"iconIdx":221},{"icon":{"paths":["M640.854 256c26.512 0 48-21.49 48-48s-21.488-48-48-48c-26.509 0-48 21.49-48 48s21.491 48 48 48zM640.854 320c61.856 0 112-50.144 112-112s-50.144-112-112-112c-61.856 0-112 50.144-112 112s50.144 112 112 112zM592.854 416v256h-160v128h32v-96h224v-288h-96zM528.854 768h160c35.347 0 64-28.653 64-64v-288c0-35.347-28.653-64-64-64h-96c-35.344 0-64 28.653-64 64v192h-96c-35.344 0-64 28.653-64 64v128c0 35.347 28.656 64 64 64h32c35.347 0 64-28.653 64-64v-32zM784.854 448c0-17.674 14.326-32 32-32s32 14.326 32 32v384c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32s14.326-32 32-32h192v-352zM368.403 401.52c9.677-9.059 10.176-24.246 1.117-33.923l-48.272-51.558v-47.925c0-13.255-10.746-24-24-24s-24 10.745-24 24v57.406c0 6.093 2.316 11.955 6.48 16.403l54.752 58.48c9.059 9.677 24.246 10.176 33.923 1.117zM170.974 414.278c53.308 74.218 156.687 91.171 230.908 37.862 10.765-7.731 25.76-5.274 33.494 5.491 7.731 10.768 5.274 25.763-5.494 33.494-95.75 68.771-229.121 46.902-297.894-48.848s-46.902-229.123 48.848-297.895c75.545-54.26 174.453-52.073 246.597-1.796 10.874 7.578 13.546 22.538 5.968 33.412s-22.538 13.547-33.411 5.968c-55.971-39.005-132.65-40.618-191.153 1.402-74.219 53.308-91.171 156.688-37.864 230.909z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["waiting-on-me"],"defaultCode":59865,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1133,"name":"waiting-on-me","prevSize":32,"id":221,"code":59865},"setIdx":0,"setId":6,"iconIdx":222},{"icon":{"paths":["M512 352.003c17.674 0 32 14.33 32 32v224c0 17.674-14.326 32-32 32s-32-14.326-32-32v-224c0-17.67 14.326-32 32-32z","M512 672.003c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32s-32-14.326-32-32c0-17.67 14.326-32 32-32z","M567.101 158.348c-24.774-41.922-85.427-41.922-110.202 0l-359.92 609.099c-25.21 42.662 5.544 96.557 55.099 96.557h719.845c49.555 0 80.307-53.894 55.098-96.557l-359.92-609.099zM512 190.906l359.923 609.097h-719.845l359.922-609.097z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["warning"],"defaultCode":59866,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1134,"name":"warning","prevSize":32,"id":222,"code":59866},"setIdx":0,"setId":6,"iconIdx":223},{"icon":{"paths":["M784.131 240.143c-35.43-35.658-77.581-63.931-124.016-83.181s-96.227-29.094-146.493-28.961c-210.863 0-382.322 171.532-382.414 382.376-0.085 67.104 17.523 133.043 51.047 191.171l-54.256 198.154 202.72-53.174c56.064 30.531 118.883 46.531 182.717 46.538h0.166c210.752 0 382.32-171.552 382.394-382.394 0.16-50.25-9.645-100.029-28.848-146.464-19.2-46.436-47.418-88.604-83.018-124.065zM513.622 828.486h-0.186c-56.922 0.006-112.797-15.293-161.776-44.298l-11.606-6.896-120.302 31.555 32.124-117.347-7.573-12.029c-31.783-50.64-48.608-109.232-48.535-169.021 0-175.235 142.653-317.816 317.981-317.816 84.301 0.049 165.13 33.58 224.707 93.218 59.581 59.638 93.034 140.499 92.998 224.8-0.074 175.254-142.653 317.834-317.834 317.834zM687.958 590.451c-9.552-4.787-56.528-27.907-65.293-31.171s-15.126-4.768-21.491 4.784c-6.362 9.555-24.678 31.171-30.253 37.462-5.574 6.288-11.149 7.187-20.701 2.4-9.555-4.784-40.339-14.87-76.845-47.434-28.403-25.322-47.584-56.621-53.174-66.192-5.594-9.571-0.589-14.669 4.198-19.491 4.291-4.291 9.552-11.168 14.32-16.742s6.381-9.571 9.552-15.933c3.174-6.362 1.597-11.955-0.787-16.739-2.384-4.787-21.491-51.818-29.466-70.96-7.757-18.63-15.622-16.099-21.491-16.394-5.501-0.275-11.955-0.349-18.336-0.349-4.842 0.131-9.606 1.264-13.994 3.325-4.387 2.058-8.298 5.005-11.491 8.65-8.749 9.552-33.428 32.675-33.428 79.706s34.234 92.467 39.002 98.848c4.765 6.381 67.382 102.883 163.187 144.266 17.792 7.68 35.974 14.413 54.477 20.17 22.902 7.334 43.731 6.237 60.179 3.779 18.336-2.733 56.547-23.104 64.506-45.418 7.955-22.317 7.955-41.459 5.501-45.456-2.458-3.997-8.618-6.326-18.173-11.11z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["whatsapp-monochromatic"],"defaultCode":59868,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1135,"name":"whatsapp-monochromatic","prevSize":32,"id":223,"code":59868},"setIdx":0,"setId":6,"iconIdx":224},{"icon":{"paths":["M354.006 399.123l14.029 0.627-0.541-16.726-152.878 1.578c49.916-116.491 165.64-198.133 300.366-198.133 99.645 0 188.893 44.659 248.81 115.065-3.712 0.171-7.491 0.492-11.526 1.068 0 0-63.76 14.898-13.302 118.708 0 0 31.085 84.541-19.306 198.774l-28.403 73.306-99.101-264.723c0 0-5.984-28.154 23.61-28.154l23.76-1.472 0.339-16.035h-228.368v14.458c0 0 39.83-0.288 56.15 27.149l40.762 103.779-73.014 174.403-108.608-272.4c0 0-3.389-31.779 27.222-31.27z","M841.603 513.168c0-33.862-5.235-66.643-14.726-97.357l-145.949 378.755c96.134-56.88 160.675-161.571 160.675-281.398z","M411.478 823.011c32.49 10.912 67.267 16.778 103.488 16.778 37.85 0 74.102-6.406 107.898-18.256l-99.709-258.502-111.677 259.981z","M188.279 513.149c0-32.083 4.712-63.066 13.339-92.336l1 2.051 152.656 375.229c-99.606-55.882-166.994-162.538-166.994-284.944z","M130.705 512.093c0-211.775 172.316-384.093 384.076-384.093 211.725 0 383.923 172.318 383.923 384.093 0 211.776-172.198 384.010-383.923 384.010-211.757 0-384.076-172.234-384.076-384.010zM514.781 879.254c202.384 0 367.11-164.742 367.11-367.178 0-202.486-164.726-367.145-367.11-367.161-202.489 0-367.213 164.673-367.213 367.161 0 202.435 164.724 367.178 367.213 367.178z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["wordpress-monochromatic"],"defaultCode":59755,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1136,"name":"wordpress-monochromatic","prevSize":32,"id":224,"code":59755},"setIdx":0,"setId":6,"iconIdx":225},{"icon":{"paths":["M193.353 405.334h213.332v-213.334h-213.332v213.334zM129.353 170.667c0-23.564 19.102-42.667 42.667-42.667h256c23.565 0 42.666 19.102 42.666 42.667v255.999c0 23.565-19.101 42.669-42.666 42.669h-256c-23.564 0-42.667-19.104-42.667-42.669v-255.999zM620.019 405.334h213.334v-213.334h-213.334v213.334zM556.019 170.667c0-23.564 19.104-42.667 42.666-42.667h256c23.565 0 42.669 19.102 42.669 42.667v255.999c0 23.565-19.104 42.669-42.669 42.669h-256c-23.562 0-42.666-19.104-42.666-42.669v-255.999zM620.019 618.666h213.334v213.334h-213.334v-213.334zM598.685 554.666c-23.562 0-42.666 19.104-42.666 42.669v256c0 23.562 19.104 42.666 42.666 42.666h256c23.565 0 42.669-19.104 42.669-42.666v-256c0-23.565-19.104-42.669-42.669-42.669h-256zM193.353 832h213.332v-213.334h-213.332v213.334zM129.353 597.334c0-23.565 19.102-42.669 42.667-42.669h256c23.565 0 42.666 19.104 42.666 42.669v256c0 23.562-19.101 42.666-42.666 42.666h-256c-23.564 0-42.667-19.104-42.667-42.666v-256z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["workspaces"],"defaultCode":59870,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1137,"name":"workspaces","prevSize":32,"id":225,"code":59870},"setIdx":0,"setId":6,"iconIdx":226},{"icon":{"paths":["M384.509 149.333c0-11.782 9.562-21.333 21.36-21.333h85.446c11.798 0 21.363 9.551 21.363 21.333v106.667h-106.81c-11.798 0-21.36-9.551-21.36-21.333v-85.333z","M512.678 256h106.806c11.798 0 21.36 9.551 21.36 21.333v85.332c0 11.782-9.562 21.334-21.36 21.334h-106.806v-128z","M384.509 405.334c0-11.782 9.562-21.334 21.36-21.334h106.81v128h-106.81c-11.798 0-21.36-9.552-21.36-21.334v-85.331z","M512.678 512h106.806c11.798 0 21.36 9.552 21.36 21.334v106.666h-128.166v-128z","M427.232 640c-23.597 0-42.723 19.104-42.723 42.666v170.669c0 23.562 19.126 42.666 42.723 42.666h170.89c23.597 0 42.723-19.104 42.723-42.666v-213.334h-213.613zM491.315 725.334c-11.798 0-21.36 9.549-21.36 21.331v42.669c0 11.782 9.562 21.331 21.36 21.331h42.723c11.798 0 21.36-9.549 21.36-21.331v-42.669c0-11.782-9.562-21.331-21.36-21.331h-42.723z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["zip"],"defaultCode":59871,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1138,"name":"zip","prevSize":32,"id":226,"code":59871},"setIdx":0,"setId":6,"iconIdx":227},{"icon":{"paths":["M373.437 492.374c25.77-8.39 53.667-8.131 79.376 0.906l19.187 6.752c25.293 8.893 52.963 8.275 77.843-1.718l4.877-1.971c26.989-10.842 56.726-12.432 84.592-4.685 2.832 0.787 5.648 1.674 8.438 2.656 22.342 7.856 41.504 21.35 56.25 38.499 17.84 20.742 29.178 46.848 31.533 75.030 0.304 3.645 0.467 7.328 0.467 11.030v117.126c0 9.936-1.51 19.517-4.314 28.531-4.467 14.371-12.275 27.245-22.435 37.843-2.595 2.704-5.296 5.302-8.189 7.69-2.368 1.952-4.822 3.805-7.376 5.53-5.107 3.453-10.57 6.413-16.31 8.845-11.491 4.861-24.115 7.562-37.376 7.562l-260.938-0.125c-3.277-0.166-6.506-0.515-9.686-1.002-7.949-1.213-15.571-3.398-22.752-6.435-5.741-2.432-11.203-5.392-16.31-8.845-2.55-1.725-5.008-3.578-7.376-5.53-2.893-2.387-5.595-4.986-8.188-7.69-10.162-10.598-17.97-23.472-22.437-37.843-2.803-9.014-4.312-18.595-4.313-28.531v-125.968c0-0.675 0.052-1.357 0.062-2.032 0.487-29.827 11.671-57.741 30.531-79.344 12.578-14.41 28.523-26.032 47.032-33.469 2.576-1.034 5.187-1.958 7.811-2.813zM426.374 552.093c-10.461-2.643-21.446-2.406-31.779 0.688-1.728 0.518-3.443 1.104-5.126 1.782-1.757 0.704-3.466 1.488-5.126 2.342-0.115 0.061-0.227 0.128-0.342 0.189-19.514 10.24-31.997 30.573-32 52.938v125.968c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-117.126c-0.003-23.798-12.39-45.472-32-57.718-0.253-0.157-0.525-0.282-0.781-0.435-1.555-0.944-3.142-1.837-4.781-2.656-0.57-0.288-1.139-0.576-1.718-0.845-2.006-0.934-4.070-1.786-6.189-2.531-3.894-1.37-7.878-2.394-11.907-3.030-10.070-1.597-20.403-0.883-30.218 2.061-1.958 0.589-3.901 1.264-5.811 2.032l-4.877 1.936c-9.818 3.946-19.914 6.973-30.157 9.062-12.81 2.618-25.85 3.763-38.874 3.469l-7.814-0.342c-10.406-0.704-20.774-2.333-30.966-4.906-2.547-0.643-5.072-1.366-7.594-2.125-2.522-0.762-5.037-1.562-7.533-2.438l-19.219-6.749c-1.709-0.602-3.443-1.123-5.187-1.565z","M174.188 458.624c19.051-8.506 40.722-9.024 60.156-1.437l7.906 3.094c8.268 3.229 17.489 2.992 25.594-0.624l0.844-0.378c20.012-8.931 42.773-9.469 63.188-1.498 6.358 2.483 12.262 5.722 17.658 9.562-27.331 11.914-50.085 31.030-66.283 54.688-20.961 6.541-43.62 5.914-64.281-2.157l-7.906-3.062c-3.484-1.36-7.366-1.274-10.781 0.25-5.037 2.25-8.281 7.264-8.281 12.781v49.219c0.001 15.981 12.956 28.938 28.938 28.938h35.125c-0.009 0.675-0.062 1.357-0.062 2.032v61.968h-35.062c-51.328 0-92.937-41.61-92.938-92.938v-49.219c0-30.768 18.093-58.672 46.188-71.219z","M878.406 422.813c11.197 14.163 17.594 31.891 17.594 50.563v102.624c0 53.021-42.979 96-96 96h-32v-53.126l-0.125-6.499c-0.058-1.462-0.246-2.922-0.342-4.374h32.467c17.674 0 32-14.326 32-32v-102.624c0-3.12-0.842-6.109-2.342-8.72 13.494-10.003 27.248-21.219 40.374-33.562 2.797-2.634 5.539-5.45 8.374-8.282z","M512.032 192c-0.106 19.205 0.71 40.743 2.938 64.156-0.986-0.045-1.974-0.156-2.97-0.156-35.347 0-64 28.654-64 64s28.653 64 64 64c14.624 0 28.035-4.995 38.813-13.251 12.131 18.838 26.362 35.45 40.406 49.718-21.798 17.213-49.29 27.533-79.219 27.533-70.691 0-128-57.309-128-128 0-70.692 57.338-128 128.032-128z","M256 224c53.019 0 96 42.981 96 96 0 53.021-42.981 96-96 96s-96-42.979-96-96c0-53.019 42.981-96 96-96zM256 288c-17.673 0-32 14.327-32 32s14.327 32 32 32c17.673 0 32-14.326 32-32s-14.327-32-32-32z","M735.997 96c44.746 0 121.2 10.367 153.827 29.086 4.662 18.723 11.184 75.812 0 154.423-11.187 78.625-107.213 145.092-153.824 168.49-46.614-23.402-142.637-89.869-153.824-168.49-11.184-78.609-4.662-135.699 0-154.423 32.627-18.719 109.072-29.084 153.821-29.086z"],"attrs":[{},{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["team-shield"]},"attrs":[{},{},{},{},{},{}],"properties":{"order":14,"id":1,"name":"team-shield","prevSize":32,"code":59877},"setIdx":4,"setId":2,"iconIdx":0},{"icon":{"paths":["M352 128c17.674 0 32 14.327 32 32v160h142.25c7.789 23.664 19.898 45.082 33.718 64h-175.968v256h256v-177.126c23.274 17.472 46 31.267 64 40.563v136.563h160c17.674 0 32 14.326 32 32s-14.326 32-32 32h-160v160c0 17.674-14.326 32-32 32s-32-14.326-32-32v-160h-256v160c0 17.674-14.326 32-32 32s-32-14.326-32-32v-160h-160c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-256h-160c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-160c0-17.673 14.326-32 32-32z","M735.997 96c44.746 0 121.2 10.367 153.827 29.086 4.662 18.723 11.184 75.812 0 154.423-11.187 78.625-107.213 145.092-153.824 168.49-46.614-23.402-142.637-89.869-153.824-168.49-11.184-78.609-4.662-135.699 0-154.423 32.627-18.719 109.072-29.084 153.821-29.086z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["hash-shield"]},"attrs":[{},{}],"properties":{"order":15,"id":0,"name":"hash-shield","prevSize":32,"code":59878},"setIdx":4,"setId":2,"iconIdx":1}],"height":1024,"metadata":{"name":"custom"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"custom","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon","name":"icomoon"},"historySize":50,"showCodes":true,"gridSize":16}} \ No newline at end of file +{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M224 192c-17.673 0-32 14.327-32 32v576c0 17.674 14.327 32 32 32h192c17.674 0 32-14.326 32-32v-576c0-17.673-14.326-32-32-32h-192zM256 768v-512h128v512h-128z","M608 192c-17.674 0-32 14.327-32 32v576c0 17.674 14.326 32 32 32h192c17.674 0 32-14.326 32-32v-576c0-17.673-14.326-32-32-32h-192zM640 768v-512h128v512h-128z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["pause-shape-unfilled (1)"]},"attrs":[{},{}],"properties":{"order":1252,"id":3,"name":"pause-shape-unfilled","prevSize":32,"code":59880},"setIdx":0,"setId":4,"iconIdx":0},{"icon":{"paths":["M511.981 352l23.158 0.531c27.558 1.075 67.286 3.907 110.31 9.533l21.722 3.062c51.43 7.702 107.453 19.722 152.624 38.406l10.282 4.717c21.552 10.906 38.384 26.317 49.718 45.75l2.531 4.563 4.282 9.187c7.645 18.461 9.974 37.693 9.248 55.75l-0.624 8.906c-4.24 44.458-26.202 87.302-47.219 114.624-15.325 19.914-40.765 28.912-64.966 23.376l-4.813-1.312-121.062-37.782c-6.442-2.010-12.534-5.027-18.032-8.938-5.062-3.6-9.328-7.738-12.813-12l-0.25-0.31c-8.304-10.291-12.813-22.16-14.374-33.533l-0.032 0.032-0.938-6.781c-0.39-2.394-0.851-4.656-1.344-6.752l-1.718-6.061c-0.301-0.877-0.595-1.642-0.877-2.314l-5.062-1.405c-3.606-0.835-7.811-1.603-12.499-2.314l-15.405-1.939c-21.978-2.285-46.368-3.091-61.875-3.091-11.638 0-28.234 0.464-45.062 1.654l-16.752 1.437c-11.101 1.158-20.694 2.554-27.904 4.221l0.029 0.032c-2.042 0.47-3.728 0.979-5.123 1.405l-0.845 2.314c-1.194 3.475-2.288 7.872-3.094 12.813l-0.906 6.781-0.061-0.032c-1.552 11.274-5.997 23.251-14.47 33.686l-0.218 0.25c-3.712 4.525-7.238 7.603-9.094 9.126-1.082 0.89-2.067 1.626-2.874 2.218-0.41 0.301-0.803 0.566-1.158 0.813-0.179 0.128-0.365 0.262-0.531 0.378-0.083 0.054-0.17 0.099-0.25 0.154l-0.125 0.096-0.064 0.061c-5.13 3.453-10.781 6.157-16.685 8l-121.032 37.782c-25.587 7.984-53.434-0.822-69.781-22.064-19.705-25.616-40.268-64.87-46.25-106.31l-0.969-8.314c-2.239-23.485 0.272-49.619 12.906-73.811l2.531-4.595c13.079-22.429 33.47-39.501 59.969-50.467l9.875-3.907c49.97-19.011 111.142-30.586 164.499-37.562l21.19-2.563c48.608-5.517 90.733-7.498 112.278-7.501zM511.952 416c-21.59 0.003-70.278 2.355-125.158 9.533l-20.842 2.934c-48.928 7.35-99.007 18.378-137.313 34.221-16.072 6.65-25.129 15.674-30.281 25.53-5.387 10.317-7.357 23.242-5.938 38.125 2.446 25.635 14.654 53.101 28.313 73.408l5.937 8.25 121.033-37.782 0.374-0.342c0.176-0.218 0.352-0.515 0.499-0.877l0.314-1.28 1.062-7.469c0.915-5.789 2.17-11.942 3.904-18.032l1.907-6.029c3.443-10.022 9.338-22.653 20.25-31.69l3.626-2.688c8.784-5.837 19.83-8.973 28.189-10.906 5.434-1.254 11.283-2.336 17.312-3.248l18.374-2.314c24.688-2.57 51.325-3.437 68.438-3.437 17.11 0 43.786 0.864 68.499 3.437 12.304 1.28 24.822 3.053 35.686 5.562 8.358 1.933 19.405 5.069 28.189 10.906l3.626 2.688c10.915 9.034 16.806 21.664 20.25 31.69 2.742 7.99 4.589 16.346 5.811 24.061l1.062 7.469c0.112 0.944 0.461 1.718 0.813 2.157 0.154 0.189 0.288 0.304 0.346 0.342l121.062 37.782c14.899-19.37 29.488-48.426 33.562-76.125l0.688-5.533c1.418-14.886-0.55-27.808-5.939-38.125-4.509-8.624-11.994-16.621-24.56-22.938l-5.722-2.592c-38.304-15.843-88.384-26.87-137.312-34.221l-20.842-2.934c-54.896-7.178-103.642-9.533-125.219-9.533z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["[redraw] phone-off"]},"attrs":[{}],"properties":{"order":1249,"id":2,"name":"phone-off","prevSize":32,"code":59805},"setIdx":0,"setId":4,"iconIdx":1},{"icon":{"paths":["M357.021 193.344c24.915-3.241 49.27 8.378 62.467 29.406l2.47 4.344 58.874 112.311c3.133 5.974 5.315 12.413 6.438 19.062 1.030 6.122 1.142 12.061 0.592 17.533l-0.061 0.406c-1.405 13.142-6.598 24.73-13.533 33.875l-4.093 5.469c-1.414 1.965-2.682 3.888-3.814 5.718l-3.091 5.501c-0.406 0.826-0.726 1.578-1.002 2.25l2.563 4.592c1.962 3.139 4.41 6.656 7.219 10.47l9.53 12.25c13.923 17.158 30.598 34.973 41.565 45.936 8.227 8.227 20.288 19.632 33.030 30.688l12.845 10.845c8.662 7.030 16.442 12.829 22.717 16.749v-0.061c1.779 1.11 3.338 1.971 4.624 2.656l2.253-1.062c3.296-1.613 7.162-3.955 11.216-6.877l5.44-4.125 0.029 0.064c9.069-6.877 20.691-12.205 34.064-13.594l0.314-0.032c5.821-0.573 10.515-0.266 12.906-0.032 1.389 0.138 2.605 0.317 3.594 0.47 0.493 0.077 0.954 0.176 1.376 0.25 0.214 0.038 0.454 0.086 0.656 0.125 0.096 0.019 0.189 0.045 0.282 0.064h0.25c6.067 1.187 11.99 3.283 17.469 6.154l112.282 58.877c23.734 12.445 37.21 38.358 33.747 64.938-4.179 32.045-17.395 74.342-42.467 107.875l-5.187 6.563c-15.024 18.189-35.302 34.886-61.344 43.062l-5.030 1.469c-25.107 6.608-51.606 4.262-78.096-6.72l-9.75-4.218c-48.774-21.891-100.214-56.989-142.874-89.782l-16.781-13.155c-38.272-30.474-69.482-58.861-84.72-74.096l-15.968-16.749c-18.726-20.246-44.835-50.349-71.281-84.749l-13.188-17.501c-30.919-41.814-62.020-89.946-80.75-135.094l-3.938-10.595c-7.528-22.95-8.54-45.773-2.812-67.53l1.437-5 3.469-9.531c7.649-18.457 19.596-33.715 32.875-45.969l6.75-5.844c34.436-28.435 80.257-43.198 114.439-47.656zM365.27 256.812c-24.234 3.162-55.1 13.389-77.564 30.094l-4.375 3.406c-11.528 9.521-19.294 20.053-22.781 31.156-2.911 9.286-3.262 20.243 1.156 33.594l2.219 5.875c15.884 38.291 43.475 81.52 72.874 121.312l12.688 16.813c33.738 43.885 66.525 80.022 81.782 95.28 15.267 15.267 51.37 48.019 95.248 81.75l16.813 12.656c39.792 29.398 82.995 57.024 121.283 72.909 16.064 6.659 28.854 6.669 39.469 3.341 11.101-3.485 21.635-11.219 31.155-22.749 16.397-19.856 27.203-47.92 31.907-71.936l1.622-10.032-112.31-58.845-0.499-0.032c-0.278 0.032-0.614 0.102-0.97 0.253l-1.126 0.685-6.032 4.531c-4.739 3.446-9.971 6.925-15.498 10l-5.626 2.909c-9.52 4.653-22.614 9.418-36.72 8.093l-4.467-0.656c-10.339-2.083-20.381-7.677-27.658-12.218-4.726-2.954-9.626-6.326-14.531-9.939l-14.624-11.376c-19.277-15.638-38.71-33.869-50.813-45.968-12.099-12.099-30.374-31.549-46.032-50.845-7.795-9.606-15.373-19.731-21.28-29.187-4.541-7.27-10.134-17.29-12.221-27.622l-0.656-4.47c-1.328-14.099 3.411-27.197 8.064-36.72 3.709-7.584 8.317-14.806 12.906-21.123l4.531-6.032c0.592-0.746 0.909-1.565 0.97-2.125 0.022-0.227 0.010-0.397 0-0.467l-58.906-112.314z","M735.987 448c17.674 0 32 14.326 32 32s-14.326 32-32 32c-17.667-0.006-32-14.333-32-32s14.333-31.994 32-32z","M735.987 128c26.314 0 52.234 7.542 74.032 21.906 21.834 14.393 38.666 35.096 47.408 59.5 8.758 24.467 8.758 50.94 0 75.406-8.742 24.404-25.574 45.076-47.408 59.469-4.662 3.072-9.594 5.478-14.032 7.344-19.552 8.224-27.994 21.402-28 31.779v0.595c0 17.674-14.326 32-32 32-17.667-0.006-32-14.333-32-32v-0.595c0.006-46.109 34.675-77.103 67.187-90.78 2.208-0.928 3.322-1.583 3.626-1.781 10.966-7.229 18.586-17.045 22.374-27.625 3.763-10.514 3.766-21.737 0-32.25-3.789-10.58-11.408-20.396-22.374-27.625-10.995-7.245-24.595-11.344-38.813-11.344-14.214 0.003-27.818 4.097-38.813 11.344-10.96 7.229-18.586 17.046-22.374 27.625-3.763 10.511-3.757 21.739 0 32.25 5.958 16.635-2.678 34.976-19.312 40.937-16.634 5.95-34.979-2.709-40.938-19.344-8.758-24.464-8.758-50.942 0-75.406 8.739-24.403 25.578-45.107 47.408-59.5 21.795-14.366 47.718-21.904 74.029-21.906z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["phone-question-mark"]},"attrs":[{},{},{}],"properties":{"order":1250,"id":1,"name":"phone-question-mark","prevSize":32,"code":59835},"setIdx":0,"setId":4,"iconIdx":2},{"icon":{"paths":["M357.018 193.349c24.918-3.241 49.27 8.378 62.47 29.406l2.467 4.312 58.877 112.343c3.133 5.974 5.315 12.413 6.438 19.062 1.030 6.118 1.142 12.058 0.592 17.533l-0.061 0.406c-1.408 13.142-6.598 24.73-13.533 33.875l-4.093 5.469c-1.414 1.962-2.682 3.888-3.814 5.718l-3.091 5.498c-0.406 0.829-0.726 1.581-1.002 2.253l2.563 4.56c1.962 3.142 4.406 6.685 7.219 10.502l9.53 12.25c13.923 17.155 30.598 34.97 41.565 45.936 8.227 8.227 20.288 19.629 33.030 30.688l12.842 10.845c8.669 7.030 16.445 12.829 22.72 16.749v-0.061c1.776 1.107 3.341 1.939 4.624 2.624l2.253-1.030c3.296-1.616 7.162-3.955 11.216-6.877l5.44-4.157 0.029 0.096c9.069-6.877 20.691-12.208 34.064-13.594l0.314-0.032c5.821-0.576 10.515-0.266 12.906-0.032 1.389 0.138 2.605 0.317 3.594 0.47 0.493 0.074 0.954 0.173 1.376 0.25 0.214 0.035 0.454 0.054 0.656 0.093 0.096 0.019 0.186 0.077 0.278 0.093h0.253c6.067 1.19 11.99 3.286 17.469 6.157l112.278 58.877c23.738 12.445 37.213 38.358 33.75 64.934-4.179 32.048-17.395 74.346-42.467 107.875l-5.187 6.563c-15.024 18.192-35.302 34.89-61.344 43.062l-5.030 1.469c-25.107 6.608-51.606 4.262-78.096-6.717l-9.75-4.221c-48.774-21.891-100.214-56.986-142.874-89.779l-16.781-13.158c-38.272-30.47-69.482-58.858-84.72-74.093l-15.968-16.749c-18.726-20.25-44.835-50.352-71.281-84.752l-13.188-17.501c-30.918-41.811-62.020-89.946-80.75-135.091l-3.937-10.595c-7.529-22.95-8.54-45.773-2.812-67.531l1.437-5 3.469-9.531c7.649-18.458 19.595-33.714 32.875-45.969l6.75-5.844c34.436-28.435 80.257-43.198 114.436-47.656zM365.27 256.818c-24.234 3.162-55.1 13.389-77.564 30.094l-4.375 3.406c-11.529 9.522-19.295 20.053-22.781 31.157-2.911 9.286-3.263 20.24 1.156 33.594l2.219 5.875c15.882 38.285 43.479 81.491 72.875 121.28l12.688 16.845c33.738 43.885 66.525 80.022 81.782 95.28 15.267 15.267 51.37 48.019 95.248 81.75l16.813 12.656c39.792 29.398 82.995 57.024 121.283 72.906 16.064 6.662 28.854 6.672 39.469 3.344 11.101-3.485 21.635-11.222 31.155-22.749 16.397-19.856 27.203-47.92 31.907-71.939l1.622-10.029-112.31-58.845-0.502-0.032c-0.275 0.029-0.611 0.099-0.966 0.25l-1.126 0.688-6.032 4.531c-4.739 3.446-9.971 6.925-15.498 10l-5.626 2.906c-9.52 4.653-22.618 9.421-36.72 8.096l-4.467-0.656c-10.339-2.083-20.381-7.677-27.658-12.221-4.726-2.954-9.626-6.323-14.531-9.936l-14.624-11.376c-19.277-15.638-38.71-33.869-50.813-45.968-12.099-12.099-30.378-31.552-46.032-50.845-7.795-9.606-15.373-19.731-21.28-29.187-4.541-7.27-10.134-17.293-12.221-27.626l-0.656-4.467c-1.328-14.099 3.414-27.2 8.064-36.72 3.709-7.584 8.317-14.81 12.906-21.123l4.531-6.064c0.589-0.746 0.909-1.536 0.97-2.093 0.022-0.227 0.010-0.397 0-0.47l-58.906-112.312z","M841.363 137.38c12.496-12.497 32.784-12.497 45.28 0 12.486 12.495 12.486 32.756 0 45.25l-73.498 73.469 73.498 73.501c12.486 12.493 12.483 32.752 0 45.248-12.496 12.496-32.784 12.496-45.28 0l-73.501-73.499-73.248 73.281c-12.499 12.49-32.758 12.493-45.251 0-12.49-12.496-12.486-32.755 0-45.251l73.251-73.28-73.251-73.25c-12.486-12.496-12.49-32.756 0-45.25 12.496-12.497 32.784-12.497 45.28 0l73.251 73.25 73.469-73.469z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["[redraw] phone-issue"]},"attrs":[{},{}],"properties":{"order":1251,"id":0,"name":"phone-issue","prevSize":32,"code":59879},"setIdx":0,"setId":4,"iconIdx":3},{"icon":{"paths":["M727.050 406.195c12.259-12.73 11.878-32.986-0.854-45.245-12.73-12.259-32.986-11.878-45.245 0.854l-254.285 264.061-115.615-120.061c-12.259-12.733-32.516-13.114-45.247-0.854s-13.113 32.515-0.854 45.245l138.666 144c6.032 6.266 14.355 9.805 23.050 9.805 8.698 0 17.021-3.539 23.053-9.805l277.331-288z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["check-single"],"grid":0},"attrs":[{}],"properties":{"order":1151,"id":0,"name":"check-single","prevSize":32,"code":59876},"setIdx":2,"setId":2,"iconIdx":0},{"icon":{"paths":["M599.050 406.195c12.259-12.73 11.878-32.986-0.854-45.245-12.73-12.259-32.986-11.878-45.245 0.854l-254.284 264.061-115.616-120.061c-12.259-12.733-32.516-13.114-45.247-0.854s-13.113 32.515-0.854 45.245l138.667 144c6.032 6.266 14.354 9.805 23.050 9.805s17.018-3.539 23.052-9.805l277.331-288z","M887.021 406.227c12.275-12.714 11.92-32.973-0.794-45.248s-32.973-11.92-45.248 0.794l-255.040 264.157-50.918-52.739c-12.275-12.714-32.534-13.069-45.248-0.794s-13.069 32.534-0.794 45.248l73.939 76.582c6.029 6.246 14.339 9.773 23.021 9.773s16.992-3.526 23.021-9.773l278.061-288z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["check-double"],"grid":0},"attrs":[{},{}],"properties":{"order":1150,"id":1,"name":"check-double","prevSize":32,"code":59875},"setIdx":2,"setId":2,"iconIdx":1},{"icon":{"paths":["M511.997 256c35.347 0 64-28.654 64-64s-28.653-64-64-64c-35.344 0-64 28.654-64 64s28.656 64 64 64zM639.997 192c0 70.692-57.306 128-128 128-70.691 0-128-57.308-128-128s57.309-128 128-128c70.694 0 128 57.308 128 128z","M192.859 431.645c0.669 1.446 2.097 3.488 5.957 5.232 18.33 8.272 67.426 22.054 115.377 34.39 23.244 5.981 45.187 11.366 61.327 15.261 8.067 1.946 14.672 3.517 19.258 4.598l7.078 1.664c0 0 0.026 0.003-0.218 1.046l0.218-1.046c8.33 1.933 15.562 7.123 20.042 14.406 4.48 7.28 5.859 16.054 3.834 24.358l-83.856 343.437c-0.483 1.984-1.155 3.914-2.006 5.77-1.155 2.509-1.242 5.302-0.272 7.853 0.982 2.573 3.053 4.893 6.006 6.237 2.976 1.357 6.438 1.523 9.568 0.435 3.114-1.082 5.44-3.238 6.688-5.754 0.362-0.73 0.749-1.443 1.165-2.144l121.434-204.461c5.766-9.706 16.224-15.658 27.514-15.658 11.293 0 21.747 5.952 27.514 15.658l121.437 204.461c0.413 0.701 0.803 1.414 1.165 2.144 1.245 2.515 3.571 4.672 6.685 5.754 3.13 1.088 6.592 0.922 9.568-0.435 2.957-1.344 5.027-3.664 6.006-6.237 0.97-2.55 0.883-5.344-0.269-7.853-0.854-1.856-1.526-3.786-2.010-5.77l-83.853-343.437c-2.029-8.304-0.65-17.075 3.83-24.358 4.48-7.28 11.686-12.467 20.013-14.4l0.266 1.139c-0.262-1.139-0.266-1.139-0.266-1.139l1.821-0.426 5.283-1.245c4.582-1.082 11.184-2.653 19.248-4.598 16.138-3.894 38.074-9.28 61.312-15.261 47.936-12.333 97.046-26.118 115.424-34.4 3.888-1.75 5.322-3.802 5.994-5.248 0.813-1.763 1.155-4.179 0.557-6.861-0.602-2.678-1.974-4.858-3.629-6.259-1.402-1.187-3.76-2.499-8.109-2.499h-615.975c-4.316 0-6.656 1.302-8.052 2.486-1.647 1.402-3.026 3.581-3.628 6.272s-0.26 5.12 0.556 6.886zM172.486 495.21c-75.805-34.218-48.392-143.21 31.498-143.21h615.975c79.907 0 107.44 108.989 31.478 143.216-24.554 11.066-79.939 26.24-125.766 38.032-21.494 5.533-41.85 10.554-57.651 14.384l75.597 309.616c6.986 17.306 7.216 36.614 0.538 54.147-7.085 18.598-21.283 33.501-39.283 41.699-17.978 8.189-38.474 9.126-57.123 2.64-18.234-6.342-33.469-19.36-42.39-36.566l-93.386-157.232-93.386 157.232c-8.918 17.206-24.157 30.224-42.387 36.566-18.653 6.486-39.146 5.549-57.126-2.64-18-8.198-32.198-23.101-39.282-41.699-6.678-17.533-6.449-36.842 0.539-54.147l75.595-309.613c-15.808-3.83-36.172-8.854-57.676-14.387-45.829-11.789-101.229-26.966-125.761-38.038z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["accessibility"],"grid":0},"attrs":[{},{}],"properties":{"order":1147,"id":2,"name":"accessibility","prevSize":32,"code":59874},"setIdx":2,"setId":2,"iconIdx":2},{"icon":{"paths":["M512 928c-229.75 0-416-186.246-416-416 0-229.75 186.25-416 416-416 229.754 0 416 186.25 416 416 0 229.754-186.246 416-416 416zM678.176 433.884c12.742-12.247 13.139-32.504 0.896-45.246-12.25-12.742-32.506-13.143-45.247-0.896l-207.030 198.991-68.644-65.834c-12.755-12.232-33.012-11.809-45.245 0.946s-11.809 33.012 0.946 45.245l90.819 87.1c12.39 11.885 31.948 11.872 44.324-0.026l229.183-220.28z"],"attrs":[{"fill":"rgb(20, 134, 96)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":0}]},"tags":["success-circle"],"grid":0},"attrs":[{"fill":"rgb(20, 134, 96)"}],"properties":{"order":1143,"id":3,"name":"success-circle","prevSize":32,"code":59869},"setIdx":2,"setId":2,"iconIdx":3},{"icon":{"paths":["M928 512c0-229.75-186.246-416-416-416-229.75 0-416 186.25-416 416 0 229.754 186.25 416 416 416 229.754 0 416-186.246 416-416zM662.63 361.373c12.493 12.497 12.493 32.758 0 45.254l-105.375 105.373 105.375 105.373c12.493 12.497 12.493 32.758 0 45.258-12.499 12.493-32.761 12.493-45.258 0l-105.373-105.375-105.373 105.375c-12.497 12.493-32.758 12.493-45.254 0-12.497-12.499-12.497-32.761 0-45.258l105.372-105.373-105.372-105.373c-12.497-12.497-12.497-32.758 0-45.254s32.758-12.497 45.254 0l105.373 105.372 105.373-105.372c12.497-12.497 32.758-12.497 45.258 0z"],"attrs":[{"fill":"rgb(212, 12, 38)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":1}]},"tags":["error-circle"],"grid":0},"attrs":[{"fill":"rgb(212, 12, 38)"}],"properties":{"order":1144,"id":4,"name":"error-circle","prevSize":32,"code":59873},"setIdx":2,"setId":2,"iconIdx":4},{"icon":{"paths":["M512 819.2c169.661 0 307.2-137.539 307.2-307.2s-137.539-307.2-307.2-307.2c-169.662 0-307.2 137.538-307.2 307.2s137.538 307.2 307.2 307.2z","M1024 512c0-282.77-229.228-512-512-512-282.77 0-512 229.23-512 512 0 282.772 229.23 512 512 512 282.772 0 512-229.228 512-512zM921.6 512c0 226.217-183.383 409.6-409.6 409.6-226.216 0-409.6-183.383-409.6-409.6 0-226.215 183.384-409.6 409.6-409.6 226.217 0 409.6 183.385 409.6 409.6z"],"attrs":[{"fill":"rgb(21, 111, 245)"},{"fill":"rgb(21, 111, 245)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912111124512431405712431908124569921291162451452241651":[{"f":2},{"f":2}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":4},{"f":4}]},"tags":["radio-checked"],"grid":0},"attrs":[{"fill":"rgb(21, 111, 245)"},{"fill":"rgb(21, 111, 245)"}],"properties":{"order":5,"id":5,"name":"radio-checked","prevSize":32,"code":59855},"setIdx":2,"setId":2,"iconIdx":5},{"icon":{"paths":["M512 0c282.767 0 512 229.23 512 512 0 282.767-229.233 512-512 512-282.77 0-512-229.233-512-512 0-282.77 229.23-512 512-512zM512 921.6c226.217 0 409.6-183.383 409.6-409.6 0-226.216-183.383-409.6-409.6-409.6-226.216 0-409.6 183.384-409.6 409.6 0 226.217 183.384 409.6 409.6 409.6z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912111124512431405712431908124569921291162451452241651":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["radio-unchecked"],"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":4,"id":6,"name":"radio-unchecked","prevSize":32,"code":59867},"setIdx":2,"setId":2,"iconIdx":6},{"icon":{"paths":["M678.736 135.922c7.414-5.157 16.23-7.922 25.264-7.922s17.85 2.764 25.264 7.922c7.414 5.157 13.075 12.46 16.218 20.928l0.074 0.2 32.371 89.024 89.226 32.445c8.467 3.143 15.77 8.803 20.928 16.219 5.155 7.415 7.92 16.231 7.92 25.264 0 9.034-2.765 17.85-7.92 25.264-5.158 7.414-12.461 13.075-20.931 16.218l-0.198 0.074-89.024 32.371-32.445 89.226c-3.142 8.467-8.803 15.77-16.218 20.928-7.414 5.155-16.23 7.92-25.264 7.92s-17.85-2.765-25.264-7.92c-7.414-5.158-13.075-12.461-16.218-20.931l-0.074-0.198-32.371-89.024-89.226-32.445c-8.467-3.142-15.77-8.803-20.928-16.218-5.155-7.414-7.92-16.23-7.92-25.264 0-9.032 2.765-17.848 7.92-25.264 5.158-7.415 12.461-13.075 20.931-16.218l0.198-0.074 89.024-32.372 32.445-89.224c3.142-8.468 8.803-15.771 16.218-20.928zM713.437 384l7.533-20.717c2.224-6.029 5.725-11.504 10.269-16.045 4.541-4.544 10.016-8.045 16.045-10.269l0.128-0.045 46.541-16.925-46.669-16.971c-6.029-2.221-11.504-5.724-16.045-10.267-4.544-4.542-8.045-10.017-10.269-16.044l-0.045-0.128-16.925-46.541-16.97 46.669c-2.221 6.028-5.725 11.502-10.269 16.044-4.541 4.543-10.016 8.045-16.045 10.267l-0.128 0.047-46.541 16.924 46.669 16.97c6.029 2.221 11.504 5.725 16.045 10.269 4.544 4.541 8.045 10.016 10.269 16.045l0.045 0.128 16.925 46.541 9.437-25.952z","M323.091 265.629c8.256-6.153 18.346-9.629 28.909-9.629s20.653 3.477 28.909 9.629c8.224 6.127 14.17 14.542 17.402 23.873l0.067 0.191 47.674 140.467 130.595 50.883c9.696 3.856 17.67 10.64 23.126 19.046 5.44 8.381 8.227 18.118 8.227 27.91s-2.787 19.53-8.227 27.91c-5.456 8.406-13.434 15.19-23.126 19.046l-0.208 0.083-130.387 50.8-47.741 140.659c-3.232 9.328-9.178 17.744-17.402 23.872-8.256 6.15-18.346 9.629-28.909 9.629s-20.653-3.478-28.909-9.629c-8.223-6.128-14.17-14.544-17.402-23.875l-0.066-0.189-47.673-140.467-130.596-50.883c-9.694-3.856-17.669-10.64-23.125-19.046-5.442-8.381-8.228-18.118-8.228-27.91s2.787-19.53 8.228-27.91c5.456-8.406 13.431-15.19 23.125-19.046l0.208-0.083 130.388-50.8 47.739-140.658c3.233-9.331 9.18-17.746 17.403-23.873zM381.222 617.712l6.314-18.602c2.291-6.659 5.958-12.874 10.88-18.147 4.928-5.28 11.014-9.507 17.917-12.23l0.134-0.054 104.41-40.678-104.544-40.733c-6.902-2.723-12.989-6.95-17.917-12.23-4.922-5.274-8.589-11.488-10.88-18.147l-0.042-0.125-35.494-104.579-35.536 104.704c-2.291 6.659-5.959 12.874-10.881 18.147-4.929 5.28-11.015 9.507-17.916 12.23l-0.133 0.054-104.411 40.678 104.544 40.733c6.901 2.723 12.988 6.95 17.916 12.23 4.923 5.274 8.59 11.488 10.881 18.147l0.042 0.125 35.494 104.579 29.222-86.102z","M704 544c-9.034 0-17.85 2.765-25.264 7.92-7.414 5.158-13.075 12.461-16.218 20.928l-32.445 89.226-89.222 32.445c-8.47 3.142-15.773 8.803-20.931 16.218-5.155 7.414-7.92 16.23-7.92 25.264s2.765 17.85 7.92 25.264c5.158 7.414 12.461 13.075 20.928 16.218l89.226 32.445 32.445 89.222c3.142 8.47 8.803 15.773 16.218 20.931 7.414 5.155 16.23 7.92 25.264 7.92s17.85-2.765 25.264-7.92c7.414-5.158 13.075-12.461 16.218-20.928l32.445-89.226 89.222-32.445c8.47-3.142 15.773-8.803 20.931-16.218 5.155-7.414 7.92-16.23 7.92-25.264s-2.765-17.85-7.92-25.264c-5.158-7.414-12.461-13.075-20.928-16.218l-89.226-32.445-32.445-89.222c-3.142-8.47-8.803-15.773-16.218-20.931-7.414-5.155-16.23-7.92-25.264-7.92zM720.97 779.283l-6.829 18.784-10.141 27.885-16.97-46.669c-2.224-6.029-5.725-11.504-10.269-16.045-4.541-4.544-10.016-8.048-16.045-10.269l-46.669-16.97 46.669-16.97c6.029-2.221 11.504-5.725 16.045-10.269 4.544-4.541 8.048-10.016 10.269-16.045l16.97-46.669 16.97 46.669c2.224 6.029 5.725 11.504 10.269 16.045 4.541 4.544 10.016 8.048 16.045 10.269l46.669 16.97-46.669 16.97c-6.029 2.224-11.504 5.725-16.045 10.269-4.544 4.541-8.045 10.016-10.269 16.045z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{},{}]},"tags":["stars"],"grid":0},"attrs":[{},{},{}],"properties":{"order":1139,"id":7,"name":"stars","prevSize":32,"code":59845},"setIdx":2,"setId":2,"iconIdx":7},{"icon":{"paths":["M810.666 512c0.022 8.358-2.173 16.579-6.371 23.862-4.195 7.283-10.253 13.382-17.581 17.706l-454.067 271.187c-7.658 4.576-16.425 7.075-25.4 7.235-8.975 0.163-17.832-2.016-25.656-6.314-7.749-4.23-14.205-10.397-18.702-17.872-4.498-7.472-6.875-15.981-6.888-24.65v-542.311c0.013-8.668 2.39-17.176 6.888-24.649s10.953-13.642 18.702-17.872c7.824-4.297 16.681-6.477 25.656-6.315s17.743 2.661 25.4 7.237l454.067 271.186c7.328 4.323 13.386 10.422 17.581 17.706 4.198 7.283 6.394 15.504 6.371 23.862z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["play-shape-filled"],"grid":0},"attrs":[{}],"properties":{"order":4,"id":8,"name":"play-shape-filled","prevSize":32,"code":59842},"setIdx":2,"setId":2,"iconIdx":8},{"icon":{"paths":["M832 245.333v533.332c0 14.147-5.693 27.712-15.824 37.712-10.131 10.003-23.872 15.622-38.202 15.622h-135.066c-14.33 0-28.070-5.619-38.202-15.622-10.131-10-15.824-23.565-15.824-37.712v-533.332c0-14.145 5.693-27.71 15.824-37.712s23.872-15.621 38.202-15.621h135.066c14.33 0 28.070 5.619 38.202 15.621s15.824 23.567 15.824 37.712zM381.091 192h-135.065c-14.329 0-28.070 5.619-38.202 15.621s-15.824 23.567-15.824 37.712v533.332c0 14.147 5.692 27.712 15.824 37.712 10.132 10.003 23.874 15.622 38.202 15.622h135.065c14.33 0 28.070-5.619 38.202-15.622 10.131-10 15.824-23.565 15.824-37.712v-533.332c0-14.145-5.693-27.71-15.824-37.712s-23.872-15.621-38.202-15.621z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["pause-shape-filled"],"grid":0},"attrs":[{}],"properties":{"order":3,"id":9,"name":"pause-shape-filled","prevSize":32,"code":59843},"setIdx":2,"setId":2,"iconIdx":9},{"icon":{"paths":["M593.158 920.006c-80.698 16.051-164.342 7.814-240.355-23.674-76.014-31.485-140.984-84.806-186.695-153.216s-70.108-148.842-70.108-231.117h64c0 69.619 20.644 137.674 59.323 195.562 38.678 57.885 93.653 103.002 157.973 129.645 64.32 26.64 135.094 33.613 203.376 20.029 68.282-13.581 131.002-47.107 180.23-96.333 49.226-49.229 82.752-111.949 96.333-180.23 13.584-68.282 6.611-139.056-20.029-203.376-26.643-64.32-71.76-119.295-129.645-157.973-57.888-38.678-125.942-59.323-195.562-59.323v-64c82.278 0 162.707 24.398 231.117 70.109s121.731 110.681 153.216 186.695v0c31.488 76.013 39.725 159.658 23.674 240.355-16.051 80.694-55.67 154.819-113.85 212.998s-132.304 97.798-212.998 113.85z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["loading"],"grid":0},"attrs":[{}],"properties":{"order":2,"id":10,"name":"loading","prevSize":32,"code":59844},"setIdx":2,"setId":2,"iconIdx":10},{"icon":{"paths":["M544 208c0-17.673-14.326-32-32-32s-32 14.327-32 32v271.997h-271.998c-17.673 0-32 14.326-32 32s14.327 32 32 32h271.998v272.003c0 17.674 14.326 32 32 32s32-14.326 32-32v-272.003l272-0.003c17.674 0 32-14.326 32-32s-14.326-32-32-32l-272 0.003v-271.997z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["add"],"defaultCode":59872,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":923,"name":"add","prevSize":32,"id":11,"code":59872},"setIdx":2,"setId":2,"iconIdx":11},{"icon":{"paths":["M512 928c-14.218 0-28.275-0.714-42.144-2.112-16.694-1.68-30.557-12.528-36.688-27.395l-40.538-98.304-98.162 40.838c-14.837 6.173-32.3 4.048-45.292-6.554-21.838-17.818-41.831-37.811-59.65-59.648-10.601-12.992-12.726-30.454-6.553-45.293l40.839-98.16-98.307-40.541c-14.864-6.131-25.714-19.994-27.395-36.688-1.396-13.869-2.111-27.926-2.111-42.144 0-14.214 0.714-28.275 2.11-42.141 1.681-16.694 12.531-30.557 27.395-36.688l98.308-40.541-40.84-98.163c-6.173-14.837-4.047-32.3 6.553-45.292 17.818-21.838 37.81-41.83 59.648-59.648 12.992-10.6 30.455-12.726 45.292-6.553l98.165 40.84 40.541-98.309c6.128-14.865 19.994-25.714 36.688-27.395 13.866-1.396 27.926-2.11 42.141-2.11s28.275 0.714 42.141 2.11c16.694 1.681 30.56 12.531 36.688 27.395l40.541 98.309 98.163-40.84c14.838-6.173 32.301-4.047 45.293 6.553 21.837 17.818 41.83 37.81 59.648 59.648 10.602 12.992 12.726 30.455 6.554 45.292l-40.842 98.163 98.31 40.541c14.864 6.131 25.712 19.994 27.392 36.688 1.398 13.866 2.112 27.926 2.112 42.141 0 14.218-0.714 28.275-2.112 42.144-1.68 16.694-12.528 30.557-27.395 36.688l-98.307 40.541 40.842 98.16c6.173 14.838 4.045 32.301-6.554 45.293-17.821 21.837-37.811 41.83-59.651 59.648-12.992 10.602-30.454 12.726-45.29 6.554l-98.163-40.838-40.538 98.304c-6.131 14.867-19.994 25.715-36.688 27.395-13.869 1.398-27.93 2.112-42.144 2.112zM444.451 757.984l43.386 105.2c7.981 0.541 16.038 0.816 24.163 0.816s16.182-0.275 24.163-0.816l43.382-105.2c9.456-22.925 35.731-33.808 58.627-24.285l105.056 43.709c12.157-10.602 23.578-22.022 34.179-34.179l-43.709-105.056c-9.526-22.893 1.36-49.171 24.282-58.624l105.203-43.386c0.541-7.978 0.816-16.038 0.816-24.163s-0.275-16.182-0.816-24.16l-105.203-43.386c-22.922-9.453-33.808-35.731-24.282-58.624l43.709-105.060c-10.602-12.156-22.022-23.577-34.176-34.177l-105.059 43.708c-22.896 9.525-49.171-1.359-58.627-24.283l-43.382-105.204c-7.981-0.54-16.038-0.815-24.163-0.815s-16.182 0.275-24.163 0.815l-43.386 105.204c-9.453 22.924-35.728 33.808-58.624 24.283l-105.058-43.708c-12.156 10.6-23.577 22.021-34.177 34.177l43.708 105.059c9.525 22.893-1.359 49.171-24.284 58.624l-105.203 43.386c-0.54 7.978-0.815 16.035-0.815 24.16 0 8.128 0.275 16.186 0.815 24.163l105.203 43.386c22.924 9.453 33.809 35.731 24.284 58.624l-43.708 105.056c10.601 12.157 22.022 23.578 34.178 34.179l105.056-43.709c22.896-9.523 49.171 1.36 58.624 24.285zM416 512c0-53.021 42.979-96 96-96s96 42.979 96 96c0 53.021-42.979 96-96 96s-96-42.979-96-96zM512 352c-88.365 0-160 71.635-160 160s71.635 160 160 160c88.365 0 160-71.635 160-160s-71.635-160-160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["administration"],"defaultCode":59662,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":924,"name":"administration","prevSize":32,"id":12,"code":59662},"setIdx":2,"setId":2,"iconIdx":12},{"icon":{"paths":["M878.739 567.622c-41.853-41.136-161.235-29.824-220.925-22.282-59.005-35.997-98.458-85.706-126.243-158.73 13.379-55.194 34.646-139.185 18.525-191.98-14.41-89.82-129.674-80.907-146.141-20.227-15.094 55.195-1.373 131.988 24.013 230.034-34.304 81.936-85.421 191.984-121.441 255.062-68.611 35.312-161.235 89.821-174.957 158.384-11.321 54.166 89.194 189.238 261.063-106.96 76.845-25.37 160.547-56.566 234.65-68.909 64.835 34.97 140.65 58.282 191.421 58.282 87.478 0 96.054-96.678 60.035-132.675zM199.152 834.342c17.496-46.97 84.048-101.133 104.288-119.99-65.18 103.875-104.288 122.39-104.288 119.99zM479.082 180.918c25.386 0 22.986 110.047 6.176 139.873-15.094-47.653-14.752-139.873-6.176-139.873zM395.379 649.216c33.274-57.936 61.747-126.845 84.733-187.526 28.474 51.766 64.838 93.251 103.258 121.706-71.354 14.739-133.446 44.909-187.99 65.821zM846.835 632.074c0 0-17.152 20.57-127.958-26.739 120.413-8.912 140.307 18.512 127.958 26.739z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["adobe-reader-monochromatic"],"defaultCode":59663,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":925,"name":"adobe-reader-monochromatic","prevSize":32,"id":13,"code":59663},"setIdx":2,"setId":2,"iconIdx":13},{"icon":{"paths":["M512 192c-13.056 0-25.578 5.187-34.813 14.419-9.232 9.233-14.419 21.755-14.419 34.812v162.462c0 12.122-6.848 23.2-17.686 28.621l-253.082 126.541v49.498l232.493-46.499c9.402-1.882 19.149 0.554 26.563 6.63 7.414 6.080 11.712 15.162 11.712 24.749v108.307c0 8.486-3.37 16.624-9.373 22.627l-44.781 44.781v47.789l91.501-36.602c7.629-3.050 16.141-3.050 23.77 0l91.501 36.602v-47.789l-44.781-44.781c-6.003-6.003-9.373-14.141-9.373-22.627v-108.307c0-9.587 4.298-18.669 11.712-24.749 7.414-6.077 17.162-8.512 26.563-6.63l232.493 46.499v-49.498l-253.082-126.541c-10.838-5.421-17.686-16.499-17.686-28.621v-162.462c0-13.057-5.187-25.579-14.419-34.812-9.235-9.232-21.757-14.419-34.813-14.419zM431.933 161.164c21.235-21.235 50.035-33.164 80.067-33.164s58.832 11.93 80.067 33.164c21.235 21.235 33.165 50.036 33.165 80.066v142.686l253.078 126.538c10.842 5.421 17.69 16.502 17.69 28.624v108.307c0 9.587-4.298 18.669-11.712 24.746s-17.162 8.512-26.563 6.63l-232.493-46.496v56.019l44.781 44.781c6 6 9.373 14.141 9.373 22.627v108.307c0 10.618-5.267 20.544-14.061 26.499-8.794 5.952-19.965 7.155-29.824 3.213l-123.501-49.402-123.501 49.402c-9.859 3.942-21.030 2.739-29.824-3.213-8.794-5.955-14.061-15.882-14.061-26.499v-108.307c0-8.486 3.373-16.627 9.373-22.627l44.781-44.781v-56.019l-232.492 46.496c-9.401 1.882-19.149-0.554-26.564-6.63s-11.712-15.158-11.712-24.746v-108.307c0-12.122 6.848-23.203 17.689-28.624l253.079-126.538v-142.686c0-30.031 11.93-58.831 33.165-80.066z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["airplane"],"defaultCode":59815,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":926,"id":14,"name":"airplane","prevSize":32,"code":59815},"setIdx":2,"setId":2,"iconIdx":14},{"icon":{"paths":["M448 188.865c0 33.615 27.251 60.865 60.864 60.865 33.616 0 60.867-27.25 60.867-60.865s-27.251-60.865-60.867-60.865c-33.613 0-60.864 27.25-60.864 60.865zM384 188.865c0 59.026 40.957 108.485 96 121.512v77.745c-44.314 11.69-78.986 47.13-89.578 91.878h-80.045c-13.027-55.043-62.486-96-121.512-96-68.961 0-124.865 55.904-124.865 124.864 0 68.963 55.904 124.867 124.865 124.867 56.762 0 104.678-37.875 119.854-89.731h83.361c12.227 41.773 45.696 74.47 87.92 85.61v77.744c-55.043 13.027-96 62.486-96 121.51 0 68.963 55.904 124.867 124.864 124.867 68.963 0 124.867-55.904 124.867-124.867 0-56.762-37.875-104.675-89.731-119.853v-79.437c42.163-11.171 75.578-43.846 87.789-85.574h77.222c15.178 51.856 63.091 89.731 119.853 89.731 68.963 0 124.867-55.904 124.867-124.867 0-68.96-55.904-124.864-124.867-124.864-59.024 0-108.483 40.957-121.51 96h-73.907c-10.579-44.707-45.194-80.122-89.446-91.843v-79.438c51.856-15.176 89.731-63.092 89.731-119.854 0-68.961-55.904-124.865-124.867-124.865-68.96 0-124.864 55.904-124.864 124.865zM828.864 569.731c-33.613 0-60.864-27.251-60.864-60.867 0-33.613 27.251-60.864 60.864-60.864 33.616 0 60.867 27.251 60.867 60.864 0 33.616-27.251 60.867-60.867 60.867zM188.865 569.731c-33.615 0-60.865-27.251-60.865-60.867 0-33.613 27.25-60.864 60.865-60.864s60.865 27.251 60.865 60.864c0 33.616-27.25 60.867-60.865 60.867zM451.069 508.864c0 33.616 27.251 60.867 60.867 60.867 33.613 0 60.864-27.251 60.864-60.867 0-33.613-27.251-60.864-60.864-60.864-33.616 0-60.867 27.251-60.867 60.864zM508.864 889.731c-33.613 0-60.864-27.251-60.864-60.867 0-33.613 27.251-60.864 60.864-60.864 33.616 0 60.867 27.251 60.867 60.864 0 33.616-27.251 60.867-60.867 60.867z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["all-contacts-in-channels"],"defaultCode":59664,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":927,"name":"all-contacts-in-channels","prevSize":32,"id":15,"code":59664},"setIdx":2,"setId":2,"iconIdx":15},{"icon":{"paths":["M861.437 160c17.67 0 32 14.327 32 32s-14.33 32-32 32h-384c-17.674 0-32-14.327-32-32s14.326-32 32-32h384zM334.717 442.397c-24.962 0-45.197-20.237-45.197-45.2 0-24.96 20.236-45.197 45.197-45.197 24.963 0 45.2 20.237 45.2 45.197 0 24.963-20.237 45.2-45.2 45.2zM334.717 506.397c-60.308 0-109.197-48.89-109.197-109.2 0-60.307 48.89-109.197 109.197-109.197 60.31 0 109.2 48.89 109.2 109.197 0 60.31-48.89 109.2-109.2 109.2zM456.278 535.504c-18.288-4.899-37.504-5.2-55.939-0.88l-45.005 10.547c-13.194 3.091-26.947 2.877-40.036-0.63l-31.676-8.483c-19.669-5.27-40.384-5.562-60.154-0.928-55.68 13.050-95.468 62.781-95.468 120.179v34.752c0 42.906 34.783 77.686 77.689 77.686h258.057c42.906 0 77.69-34.781 77.69-77.686v-43.587c0-52-34.928-97.514-85.158-110.97zM414.944 596.934c8.166-1.914 16.675-1.779 24.774 0.39 22.246 5.958 37.718 26.118 37.718 49.149v43.587c0 7.558-6.131 13.686-13.69 13.686h-258.057c-7.56 0-13.689-6.128-13.689-13.686v-34.752c0-27.469 19.123-51.552 46.072-57.869 9.556-2.24 19.564-2.086 28.99 0.438l31.676 8.483c23.277 6.237 47.738 6.621 71.2 1.12l45.005-10.547zM893.437 512c0-17.674-14.33-32-32-32h-224c-17.674 0-32 14.326-32 32s14.326 32 32 32h224c17.67 0 32-14.326 32-32zM861.437 640c17.67 0 32 14.326 32 32s-14.33 32-32 32h-192c-17.674 0-32-14.326-32-32s14.326-32 32-32h192zM893.437 352c0-17.674-14.33-32-32-32h-288c-17.674 0-32 14.326-32 32s14.326 32 32 32h288c17.67 0 32-14.326 32-32zM861.437 800c17.67 0 32 14.326 32 32s-14.33 32-32 32h-256c-17.674 0-32-14.326-32-32s14.326-32 32-32h256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["all-contacts-in-queue"],"defaultCode":59665,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":928,"name":"all-contacts-in-queue","prevSize":32,"id":16,"code":59665},"setIdx":2,"setId":2,"iconIdx":16},{"icon":{"paths":["M523.571 295.385c33.133 0 74.669-22.133 99.402-51.645 22.4-26.745 38.733-64.095 38.733-101.445 0-5.072-0.467-10.144-1.402-14.294-36.864 1.383-81.2 24.439-107.798 55.334-21.002 23.517-40.134 60.406-40.134 98.218 0 5.533 0.934 11.067 1.402 12.911 2.333 0.461 6.067 0.922 9.798 0.922zM406.906 853.334c45.267 0 65.334-29.974 121.798-29.974 57.402 0 70 29.050 120.4 29.050 49.469 0 82.602-45.187 113.869-89.456 34.998-50.72 49.466-100.522 50.4-102.829-3.267-0.922-98-39.194-98-146.634 0-93.146 74.666-135.107 78.867-138.333-49.469-70.090-124.602-71.935-145.136-71.935-55.533 0-100.8 33.199-129.264 33.199-30.8 0-71.402-31.354-119.469-31.354-91.466 0-184.333 74.701-184.333 215.802 0 87.61 34.533 180.294 77 240.24 36.402 50.723 68.133 92.224 113.867 92.224z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["apple-monochromatic"],"defaultCode":59666,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":929,"name":"apple-monochromatic","prevSize":32,"id":17,"code":59666},"setIdx":2,"setId":2,"iconIdx":17},{"icon":{"paths":["M498.694 141.561l-298.666 136.533c-11.39 5.207-18.696 16.58-18.696 29.103v386.844c0 11.818 6.513 22.675 16.941 28.237l298.667 159.286c9.411 5.021 20.707 5.021 30.118 0l298.666-159.286c10.429-5.562 16.941-16.419 16.941-28.237v-386.844c0-12.524-7.306-23.896-18.694-29.103l-298.666-136.533c-8.451-3.862-18.16-3.862-26.611 0zM245.333 357.011l234.667 107.277v335.709l-234.667-125.155v-317.83zM544 799.997l234.666-125.155v-317.83l-234.666 107.277v335.709zM512 408.544l-221.7-101.347 221.7-101.348 221.699 101.348-221.699 101.347z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["apps"],"defaultCode":59667,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":930,"name":"apps","prevSize":32,"id":18,"code":59667},"setIdx":2,"setId":2,"iconIdx":18},{"icon":{"paths":["M374.627 297.372c-12.496-12.497-32.758-12.497-45.254 0l-192 192c-12.497 12.496-12.497 32.758 0 45.254l192 192c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-137.372-137.373h578.745v128c0 17.674 14.326 32 32 32s32-14.326 32-32v-160c0-17.674-14.326-32-32-32h-610.745l137.372-137.373c12.496-12.496 12.496-32.758 0-45.255z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-back"],"defaultCode":59668,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":931,"name":"arrow-back","prevSize":32,"id":19,"code":59668},"setIdx":2,"setId":2,"iconIdx":19},{"icon":{"paths":["M551.392 242.502c0.189-17.672 14.669-31.845 32.339-31.656 17.674 0.189 31.846 14.668 31.658 32.34l-1.318 123.489 193.44-193.439c12.496-12.497 32.755-12.497 45.254 0 12.496 12.497 12.496 32.758 0 45.255l-193.44 193.439 123.488-1.318c17.674-0.189 32.154 13.984 32.339 31.654 0.189 17.674-13.984 32.154-31.654 32.342l-201.92 2.154c-8.605 0.093-16.886-3.283-22.97-9.37-6.086-6.083-9.462-14.365-9.373-22.97l2.157-201.92zM475.981 782.147c-0.189 17.674-14.669 31.846-32.339 31.658-17.674-0.189-31.846-14.669-31.658-32.342l1.318-123.488-193.438 193.44c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l193.438-193.44-123.488 1.318c-17.672 0.189-32.151-13.984-32.34-31.654-0.189-17.674 13.984-32.154 31.656-32.342l201.922-2.154c8.605-0.093 16.883 3.283 22.966 9.37 6.086 6.083 9.462 14.365 9.373 22.97l-2.157 201.92z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-collapse"],"defaultCode":59669,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":932,"name":"arrow-collapse","prevSize":32,"id":20,"code":59669},"setIdx":2,"setId":2,"iconIdx":20},{"icon":{"paths":["M576 672c-17.674 0-32 14.326-32 32s14.326 32 32 32h224c17.674 0 32-14.326 32-32v-208c0-17.674-14.326-32-32-32s-32 14.326-32 32v130.746l-233.373-233.373c-12.496-12.496-32.758-12.496-45.254 0l-73.373 73.373-169.372-169.373c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.759 0 45.255l192 192c12.496 12.496 32.758 12.496 45.254 0l73.373-73.373 210.746 210.746h-146.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-decrease"],"defaultCode":59670,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":933,"name":"arrow-decrease","prevSize":32,"id":21,"code":59670},"setIdx":2,"setId":2,"iconIdx":21},{"icon":{"paths":["M726.88 526.064c12.355 12.637 12.128 32.896-0.509 45.254l-191.968 187.715c-12.438 12.163-32.31 12.163-44.746 0l-191.97-187.715c-12.636-12.358-12.863-32.618-0.507-45.254 12.356-12.634 32.615-12.861 45.252-0.506l137.597 134.55v-372.109c0-17.673 14.33-32 32-32 17.674 0 32 14.327 32 32v372.109l137.6-134.55c12.634-12.355 32.896-12.128 45.251 0.506z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-down"],"defaultCode":59673,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":934,"name":"arrow-down","prevSize":32,"id":22,"code":59673},"setIdx":2,"setId":2,"iconIdx":22},{"icon":{"paths":["M329.373 550.627c-12.497-12.496-12.497-32.758 0-45.254s32.758-12.496 45.254 0l105.373 105.373v-418.746c0-17.673 14.326-32 32-32s32 14.327 32 32v418.746l105.373-105.373c12.496-12.496 32.758-12.496 45.254 0s12.496 32.758 0 45.254l-160 160c-12.496 12.496-32.758 12.496-45.254 0l-160-160zM112 864c0 17.674 14.327 32 32 32h768c17.674 0 32-14.326 32-32v-512c0-17.674-14.326-32-32-32h-96c-17.674 0-32 14.326-32 32s14.326 32 32 32h64v448h-704v-448h64c17.673 0 32-14.326 32-32s-14.327-32-32-32h-96c-17.673 0-32 14.326-32 32v512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-down-box"],"defaultCode":59671,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":935,"name":"arrow-down-box","prevSize":32,"id":23,"code":59671},"setIdx":2,"setId":2,"iconIdx":23},{"icon":{"paths":["M866.49 512c0-194.404-157.802-352-352.464-352-194.661 0-352.465 157.596-352.465 352s157.804 352 352.465 352c194.662 0 352.464-157.597 352.464-352zM930.576 512c0 229.75-186.496 416-416.55 416s-416.549-186.25-416.549-416c0-229.75 186.495-416 416.549-416s416.55 186.25 416.55 416zM696.525 571.37c12.682-12.33 12.957-32.589 0.611-45.251-12.342-12.666-32.63-12.938-45.309-0.611l-105.789 102.842v-276.349c0-17.674-14.346-32-32.045-32-17.696 0-32.042 14.326-32.042 32v276.349l-105.789-102.842c-12.678-12.326-32.966-12.054-45.309 0.611-12.344 12.662-12.071 32.922 0.608 45.251l160.182 155.715c12.438 12.093 32.259 12.093 44.701 0l160.179-155.715z"],"width":1056,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-down-circle"],"defaultCode":59672,"grid":0},"attrs":[{}],"properties":{"order":936,"name":"arrow-down-circle","prevSize":32,"id":24,"code":59672},"setIdx":2,"setId":2,"iconIdx":24},{"icon":{"paths":["M859.978 398.15c-0.189 17.67-14.666 31.843-32.339 31.654-17.67-0.189-31.846-14.666-31.658-32.339l1.318-123.488-193.437 193.437c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.755 0-45.254l193.437-193.437-123.488 1.318c-17.67 0.189-32.15-13.984-32.339-31.656s13.984-32.151 31.658-32.34l201.92-2.156c8.605-0.092 16.883 3.286 22.97 9.371 6.083 6.085 9.462 14.364 9.37 22.969l-2.157 201.922zM167.394 626.522c0.189-17.674 14.668-31.846 32.34-31.658s31.845 14.669 31.657 32.339l-1.319 123.488 193.438-193.437c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-193.438 193.437 123.489-1.318c17.67-0.189 32.15 13.984 32.339 31.658 0.189 17.67-13.984 32.15-31.658 32.339l-201.92 2.157c-8.605 0.093-16.884-3.286-22.969-9.37-6.085-6.086-9.463-14.365-9.371-22.97l2.156-201.92z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-expand"],"defaultCode":59674,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":937,"name":"arrow-expand","prevSize":32,"id":25,"code":59674},"setIdx":2,"setId":2,"iconIdx":25},{"icon":{"paths":["M623.488 420.944h-129.030c-146.778 0-279.962 128.675-298.822 309.533 98.511-81.834 219.072-127.946 345.446-127.946h82.406v123.408l188.595-214.202-188.595-214.2v123.406zM888.045 501.165c5.322 6.045 5.325 15.104 0 21.149l-300.547 341.354c-9.747 11.069-28.010 4.176-28.010-10.573v-186.563h-18.406c-15.286 0-30.496 0.774-45.594 2.298-112.397 11.35-218.514 64.397-302.132 150.954-2.078 2.15-4.142 4.32-6.191 6.512-7.238 7.741-14.299 15.738-21.173 23.984-2.611 3.133-5.195 6.301-7.751 9.504l-0.376 0.474c-9.438 11.834-28.508 5.158-28.508-9.978v-75.606c0-230.707 163.46-417.728 365.102-417.728h65.030v-186.56c0-14.749 18.262-21.643 28.010-10.573l300.547 341.354z"],"width":1056,"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-forward"],"defaultCode":59841,"grid":0},"attrs":[{}],"properties":{"order":938,"id":26,"name":"arrow-forward","prevSize":32,"code":59841},"setIdx":2,"setId":2,"iconIdx":26},{"icon":{"paths":["M576 352c-17.674 0-32-14.326-32-32s14.326-32 32-32h224c17.674 0 32 14.327 32 32v208c0 17.674-14.326 32-32 32s-32-14.326-32-32v-130.746l-233.373 233.373c-12.496 12.496-32.758 12.496-45.254 0l-73.373-73.373-169.372 169.373c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l192-192c12.496-12.496 32.758-12.496 45.254 0l73.373 73.373 210.746-210.746h-146.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-increase"],"defaultCode":59675,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":939,"name":"arrow-increase","prevSize":32,"id":27,"code":59675},"setIdx":2,"setId":2,"iconIdx":27},{"icon":{"paths":["M297.766 105.372c12.513-12.497 32.801-12.497 45.316 0 12.512 12.497 12.512 32.758 0 45.255l-105.513 105.372h611.551c17.699 0 32.045 14.327 32.045 32v112c0 17.674-14.346 32-32.045 32-17.696 0-32.042-14.326-32.042-32v-80h-579.51l105.513 105.373c12.512 12.496 12.512 32.758 0 45.254-12.515 12.496-32.803 12.496-45.316 0l-160.212-160c-12.513-12.497-12.513-32.758 0-45.255l160.212-160zM711.568 918.627c-12.515 12.496-32.803 12.496-45.315 0-12.515-12.496-12.515-32.758 0-45.254l105.51-105.373h-611.552c-17.696 0-32.042-14.326-32.042-32v-112c0-17.674 14.346-32 32.042-32s32.042 14.326 32.042 32v80h579.509l-105.51-105.373c-12.515-12.496-12.515-32.758 0-45.254 12.512-12.496 32.8-12.496 45.315 0l160.211 160c12.512 12.496 12.512 32.758 0 45.254l-160.211 160z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-looping"],"defaultCode":59677,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":940,"name":"arrow-looping","prevSize":32,"id":28,"code":59677},"setIdx":2,"setId":2,"iconIdx":28},{"icon":{"paths":["M374.627 769.296c-12.496 12.496-32.758 12.496-45.254 0l-192-192c-12.497-12.496-12.497-32.758 0-45.254l192-192c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-137.372 137.373h578.745v-192h-192c-17.674 0-32-14.328-32-32.001s14.326-32 32-32h224c17.674 0 32 14.327 32 32v256.001c0 17.674-14.326 32-32 32h-610.745l137.372 137.373c12.496 12.496 12.496 32.758 0 45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-return"],"defaultCode":59678,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":941,"name":"arrow-return","prevSize":32,"id":29,"code":59678},"setIdx":2,"setId":2,"iconIdx":29},{"icon":{"paths":["M526.064 297.121c12.637-12.356 32.896-12.129 45.254 0.507l187.715 191.969c12.163 12.438 12.163 32.31 0 44.746l-187.715 191.971c-12.358 12.634-32.618 12.861-45.254 0.506-12.634-12.355-12.861-32.614-0.506-45.251l134.55-137.597h-372.109c-17.673 0-32-14.33-32-32 0-17.674 14.327-32 32-32h372.109l-134.55-137.6c-12.355-12.634-12.128-32.894 0.506-45.251z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["arrow-right"],"defaultCode":59838,"grid":0},"attrs":[{}],"properties":{"order":942,"id":30,"name":"arrow-right","prevSize":32,"code":59838},"setIdx":2,"setId":2,"iconIdx":30},{"icon":{"paths":["M297.181 498.090c-12.356-12.634-12.129-32.896 0.507-45.251l191.97-187.717c12.435-12.161 32.307-12.161 44.746 0l191.968 187.717c12.637 12.355 12.864 32.618 0.509 45.251-12.355 12.637-32.618 12.864-45.251 0.509l-137.6-134.55v372.109c0 17.674-14.326 32-32 32-17.67 0-32-14.326-32-32v-372.109l-137.597 134.55c-12.637 12.355-32.895 12.128-45.251-0.509z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-up"],"defaultCode":59680,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":943,"name":"arrow-up","prevSize":32,"id":31,"code":59680},"setIdx":2,"setId":2,"iconIdx":31},{"icon":{"paths":["M694.627 473.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-105.373-105.373v418.746c0 17.674-14.326 32-32 32s-32-14.326-32-32v-418.746l-105.373 105.373c-12.496 12.496-32.758 12.496-45.254 0s-12.497-32.758 0-45.254l160-160c12.496-12.497 32.758-12.497 45.254 0l160 160zM912 160c0-17.673-14.326-32-32-32h-768c-17.673 0-32 14.327-32 32v512c0 17.674 14.327 32 32 32h96c17.673 0 32-14.326 32-32s-14.327-32-32-32h-64v-448h704v448h-64c-17.674 0-32 14.326-32 32s14.326 32 32 32h96c17.674 0 32-14.326 32-32v-512z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["arrow-up-box"],"defaultCode":59679,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":944,"name":"arrow-up-box","prevSize":32,"id":32,"code":59679},"setIdx":2,"setId":2,"iconIdx":32},{"icon":{"paths":["M649.427 192c-26.454 0-52.016 10.804-71.005 30.343l-305.1 313.906c-31.48 32.387-49.322 76.506-49.322 122.694 0 46.186 17.842 90.304 49.322 122.694 31.451 32.355 73.91 50.362 117.984 50.362s86.531-18.006 117.981-50.362l305.101-313.907c12.317-12.672 32.576-12.96 45.248-0.643 12.675 12.317 12.963 32.576 0.646 45.251l-305.101 313.904c-43.302 44.554-102.23 69.757-163.875 69.757s-120.574-25.203-163.877-69.757c-43.273-44.522-67.428-104.717-67.428-167.299s24.155-122.781 67.428-167.302l305.1-313.905c30.845-31.735 72.874-49.737 116.899-49.737s86.054 18.002 116.899 49.737c30.816 31.704 47.971 74.514 47.971 118.968s-17.155 87.263-47.971 118.969l-305.43 313.904c-0.003 0.006 0.003-0.003 0 0-18.384 18.909-43.523 29.718-69.923 29.718-26.406 0-51.539-10.8-69.923-29.718-18.356-18.883-28.512-44.31-28.512-70.634 0-26.326 10.156-51.754 28.512-70.637l281.872-289.668c12.326-12.666 32.586-12.942 45.251-0.617s12.941 32.585 0.618 45.251l-281.846 289.638c-6.557 6.752-10.406 16.106-10.406 26.032 0 9.93 3.843 19.277 10.406 26.029 6.531 6.72 15.194 10.323 24.029 10.323s17.498-3.603 24.029-10.323l305.43-313.907c19.024-19.568 29.866-46.301 29.866-74.361 0-28.059-10.842-54.791-29.866-74.362-18.989-19.54-44.55-30.343-71.005-30.343z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["attach"],"defaultCode":59676,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":945,"name":"attach","prevSize":32,"id":33,"code":59676},"setIdx":2,"setId":2,"iconIdx":33},{"icon":{"paths":["M300.1 631.12h-113.433v-280.89h113.433l12.366-48.048c11.054-42.953 50.123-74.619 96.423-74.619h58.666v526.223h-58.666c-46.301 0-85.37-31.667-96.423-74.621l-12.366-48.045zM163.556 695.12h86.931c18.156 70.541 82.192 122.666 158.403 122.666h81.776c22.582 0 40.89-18.307 40.89-40.89v-572.444c0-22.582-18.307-40.889-40.89-40.889h-81.776c-76.211 0-140.247 52.124-158.403 122.667h-86.931c-22.582 0-40.889 18.306-40.889 40.89v327.11c0 22.582 18.307 40.89 40.889 40.89zM646.461 316.515c17.146-4.286 34.518 6.138 38.806 23.284l11.136 44.55c20.81 83.229 20.81 170.301 0 253.533l-11.136 44.55c-4.288 17.146-21.661 27.568-38.806 23.283-17.146-4.288-27.571-21.661-23.283-38.806l11.136-44.55c18.262-73.040 18.262-149.45 0.003-222.486l-11.139-44.55c-4.288-17.146 6.138-34.522 23.283-38.807zM807.472 235.936c-5.197-16.892-23.104-26.372-39.994-21.174-16.893 5.197-26.371 23.104-21.174 39.996l35.536 115.489c28.112 91.37 26.976 189.242-3.254 279.933l-32.054 96.16c-5.59 16.765 3.472 34.886 20.237 40.477 16.768 5.587 34.89-3.472 40.48-20.24l32.051-96.16c34.448-103.344 35.747-214.87 3.709-318.989l-35.536-115.491z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio"],"defaultCode":59683,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":946,"name":"audio","prevSize":32,"id":34,"code":59683},"setIdx":2,"setId":2,"iconIdx":34},{"icon":{"paths":["M866.128 153.127c-12.496-12.497-32.758-12.497-45.254 0l-668.246 668.245c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l668.246-668.245c12.496-12.497 12.496-32.758 0-45.255zM674.643 480.358l55.92-55.923c16.259 79.565 14.515 161.866-5.229 240.842l-11.622 46.49c-4.288 17.146-21.661 27.571-38.806 23.283-17.146-4.285-27.568-21.661-23.283-38.806l11.622-46.486c13.875-55.507 17.677-112.874 11.398-169.398zM817.162 385.923l-11.312-36.771 51.203-51.206 21.28 69.155c33.344 108.368 31.994 224.445-3.859 332.010l-33.45 100.342c-5.587 16.765-23.709 25.827-40.477 20.24-16.765-5.59-25.827-23.712-20.237-40.48l33.446-100.339c31.635-94.912 32.826-197.334 3.405-292.95zM490.666 664.333l64-64v210.346c0 23.562-19.101 42.666-42.666 42.666h-85.334c-35.459 0-68.394-10.816-95.683-29.325l46.611-46.611c14.701 7.629 31.395 11.936 49.072 11.936h64v-125.011zM128 682.678c0 19.738 13.403 36.346 31.604 41.216l62.552-62.55h-30.156v-298.666h118.99l12.367-48.049c11.843-46.020 53.696-79.953 103.309-79.953h64v158.155l64-64v-115.488c0-23.564-19.101-42.667-42.666-42.667h-85.334c-79.523 0-146.343 54.39-165.289 128h-90.71c-23.564 0-42.667 19.102-42.667 42.667v341.334z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio-disabled"],"defaultCode":59681,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":947,"name":"audio-disabled","prevSize":32,"id":35,"code":59681},"setIdx":2,"setId":2,"iconIdx":35},{"icon":{"paths":["M310.99 661.344h-118.99v-298.666h118.99l12.367-48.049c11.843-46.020 53.696-79.953 103.309-79.953h64v554.667h-64c-49.613 0-91.466-33.933-103.309-79.952l-12.367-48.048zM170.667 725.344h90.71c18.946 73.61 85.766 128 165.289 128h85.334c23.565 0 42.666-19.104 42.666-42.666v-597.335c0-23.564-19.101-42.667-42.666-42.667h-85.334c-79.523 0-146.343 54.39-165.289 128h-90.71c-23.564 0-42.667 19.102-42.667 42.667v341.334c0 23.562 19.103 42.666 42.667 42.666zM886.627 393.373c12.496 12.496 12.496 32.758 0 45.254l-73.373 73.373 73.373 73.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-73.373-73.373-73.373 73.373c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l73.373-73.373-73.373-73.373c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l73.373 73.373 73.373-73.373c12.496-12.496 32.758-12.496 45.254 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["audio-unavailable"],"defaultCode":59682,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":948,"name":"audio-unavailable","prevSize":32,"id":36,"code":59682},"setIdx":2,"setId":2,"iconIdx":36},{"icon":{"paths":["M418.704 128c-35.344 0-64 28.654-64 64v226.637c20.774-2.822 42.134-3.456 64-1.526v-225.11h176v180.707c0 35.344 28.656 64 64 64h176v331.293h-120.554c-17.155 22.179-36.323 43.869-57.312 64h177.866c35.347 0 64-28.653 64-64v-363.293c0-6.413-1.923-12.675-5.526-17.978l-156.63-230.681c-11.914-17.544-31.741-28.049-52.947-28.049h-264.896zM658.704 372.707v-180.707h24.896l122.698 180.707h-147.594zM167.939 668.547c120.524 156.138 218.24 174.586 285.133 158.739 73.293-17.36 139.232-81.648 183.466-151.763-115.155-155.869-211.581-174.589-279.149-158.915-74.362 17.251-142.707 81.683-189.45 151.939zM104.428 649.037c100.621-162.8 337.62-357.19 593.252 1.789 9.072 12.739 10.32 29.818 2.422 43.315-95.27 162.854-326.394 358.346-593.234-0.224-9.745-13.094-11.022-30.995-2.44-44.88zM401.664 735.994c31.514 0 60.269-26.858 60.269-64 0-37.146-28.755-64-60.269-64-31.51 0-60.266 26.854-60.266 64 0 37.142 28.755 64 60.266 64zM401.664 799.994c68.634 0 124.269-57.309 124.269-128 0-70.694-55.635-128-124.269-128-68.63 0-124.267 57.306-124.267 128 0 70.691 55.636 128 124.267 128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["auditing"],"defaultCode":59684,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":949,"name":"auditing","prevSize":32,"id":37,"code":59684},"setIdx":2,"setId":2,"iconIdx":37},{"icon":{"paths":["M224 224c-17.673 0-32 14.327-32 32v544c0 17.674 14.327 32 32 32h544c17.674 0 32-14.326 32-32v-544c0-17.673-14.326-32-32-32h-544zM128 256c0-53.019 42.981-96 96-96h544c53.021 0 96 42.981 96 96v544c0 53.021-42.979 96-96 96h-544c-53.019 0-96-42.979-96-96v-544zM608 460.813c0 41.798-26.714 77.357-64 90.538v133.462h-64v-133.462c-37.286-13.181-64-48.739-64-90.538 0-53.021 42.979-96 96-96s96 42.979 96 96zM608 588.826c38.861-29.19 64-75.667 64-128.013 0-88.365-71.635-160-160-160s-160 71.636-160 160c0 52.346 25.139 98.822 64 128.013v127.987c0 17.674 14.326 32 32 32h128c17.674 0 32-14.326 32-32v-127.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["auth"],"defaultCode":59685,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":950,"name":"auth","prevSize":32,"id":38,"code":59685},"setIdx":2,"setId":2,"iconIdx":38},{"icon":{"paths":["M513.35 554.019c66.467 0 120.349-52.493 120.349-117.242 0-64.752-53.882-117.243-120.349-117.243-66.464 0-120.346 52.491-120.346 117.243 0 64.749 53.882 117.242 120.346 117.242zM513.35 490.019c-32.704 0-56.346-25.405-56.346-53.242 0-27.84 23.642-53.242 56.346-53.242 32.707 0 56.349 25.402 56.349 53.242 0 27.837-23.642 53.242-56.349 53.242z","M365.478 894.144h-172.126c-17.673 0-32-14.33-32-32v-702.144c0-17.673 14.327-32 32-32h640.001c17.674 0 32 14.327 32 32v702.144c0 17.67-14.326 32-32 32h-172.128c-6.24 1.274-12.701 1.942-19.318 1.942h-257.11c-6.618 0-13.078-0.669-19.318-1.942zM225.353 830.144h68.244c-3.114-9.456-4.799-19.558-4.799-30.058v-93.446c0-56.109 37.881-105.142 92.172-119.309 19.171-5.002 39.264-5.312 58.579-0.902l42.778 9.766c20.051 4.579 40.909 4.259 60.81-0.934l28.070-7.325c20.694-5.398 42.384-5.734 63.232-0.973 60.534 13.821 103.469 67.664 103.469 129.754v83.37c0 10.499-1.686 20.602-4.8 30.058h68.246v-638.144h-576.001v638.144zM652.918 830.144c12.246-4.49 20.989-16.253 20.989-30.058v-83.37c0-32.234-22.288-60.186-53.715-67.36-10.822-2.47-22.083-2.298-32.826 0.506l-28.070 7.325c-29.853 7.789-61.139 8.272-91.216 1.405l-42.774-9.766c-9.293-2.122-18.957-1.974-28.176 0.432-26.112 6.813-44.333 30.397-44.333 57.382v93.446c0 13.805 8.742 25.568 20.989 30.058h279.133z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["avatar"],"defaultCode":59686,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":951,"name":"avatar","prevSize":32,"id":39,"code":59686},"setIdx":2,"setId":2,"iconIdx":39},{"icon":{"paths":["M737.779 361.376c12.499 12.496 12.499 32.758 0 45.254l-110.947 110.95 110.947 110.947c12.499 12.496 12.499 32.758 0 45.254-12.496 12.499-32.758 12.499-45.254 0l-110.947-110.947-110.95 110.947c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.758 0-45.254l110.95-110.947-110.95-110.95c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l110.95 110.95 110.947-110.95c12.496-12.496 32.758-12.496 45.254 0z","M312.246 218.073c12.061-16.393 31.2-26.073 51.552-26.073h468.202c35.347 0 64 28.654 64 64v512c0 35.347-28.653 64-64 64h-468.202c-20.352 0-39.491-9.68-51.552-26.074l-188.343-256c-16.598-22.56-16.598-53.293 0-75.853l188.343-256.001zM363.798 256l-188.343 256 188.343 256h468.202v-512h-468.202z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["backspace"],"defaultCode":59687,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":952,"name":"backspace","prevSize":32,"id":40,"code":59687},"setIdx":2,"setId":2,"iconIdx":40},{"icon":{"paths":["M896 512c0-212.077-171.923-384-384-384s-384 171.923-384 384c0 212.077 171.923 384 384 384s384-171.923 384-384zM480 544v286.419c-56.483-5.606-108.646-25.904-152.618-57.011 46.403-78.992 67.251-156.97 71.734-229.408h80.883zM334.8 544c-4.282 58.995-21.005 122.198-56.631 186.458-46.616-49.875-77.462-114.678-84.589-186.458h141.22zM398.954 480c-6.192-93.13-37.366-173.574-70.627-230.072 43.773-30.733 95.594-50.78 151.674-56.348v286.42h-81.046zM279.095 292.556c26.251 47.457 50.118 112.532 55.644 187.444h-141.159c7.174-72.253 38.381-137.437 85.515-187.444zM544 544h80.883c4.483 72.438 25.331 150.416 71.734 229.408-43.971 31.107-96.134 51.405-152.618 57.011v-286.419zM830.419 544c-7.126 71.779-37.971 136.582-84.589 186.458-35.626-64.259-52.349-127.462-56.63-186.458h141.219zM830.419 480h-141.158c5.526-74.912 29.395-139.987 55.645-187.444 47.133 50.008 78.339 115.192 85.514 187.444zM544 193.58c56.080 5.568 107.901 25.614 151.674 56.348-33.261 56.499-64.435 136.943-70.627 230.072h-81.046v-286.42z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["basketball"],"defaultCode":59776,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":953,"id":41,"name":"basketball","prevSize":32,"code":59776},"setIdx":2,"setId":2,"iconIdx":41},{"icon":{"paths":["M233.358 169.364c6.002-6.001 14.141-9.372 22.629-9.372l304.020 0.020c0 0 0.003 0 0 0 46.678 0 91.446 18.543 124.451 51.549 33.008 33.006 51.549 77.772 51.549 124.452s-18.541 91.443-51.549 124.451c-0.803 0.803-1.616 1.6-2.435 2.387 22.867 9.552 43.888 23.533 61.75 41.395 36.006 36.006 56.234 84.845 56.234 135.766s-20.227 99.757-56.234 135.763c-36.006 36.006-84.845 56.237-135.766 56.237l-352.024-0.019c-17.673-0.003-31.998-14.33-31.998-32v-608.001c0-8.487 3.372-16.627 9.373-22.628zM560.006 448.013c29.706 0 58.192-11.802 79.197-32.806 21.005-21.002 32.803-49.491 32.803-79.194 0-29.705-11.798-58.193-32.803-79.197s-49.491-32.804-79.197-32.804l-272.022-0.018v224.019h272.022zM287.984 512.013v255.981l320.022 0.019c0 0 0.003 0 0 0 33.949 0 66.506-13.488 90.512-37.491 24.003-24.006 37.488-56.563 37.488-90.509 0-33.949-13.485-66.506-37.488-90.512-24.006-24.003-56.563-37.488-90.512-37.488h-320.022z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["bold"],"defaultCode":59688,"grid":0},"attrs":[{}],"properties":{"order":954,"name":"bold","prevSize":32,"id":42,"code":59688},"setIdx":2,"setId":2,"iconIdx":42},{"icon":{"paths":["M352 445.437c0-17.67 14.326-32 32-32h256c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M352 322.557c0-17.672 14.326-31.999 32-31.999h256c17.674 0 32 14.327 32 31.999 0 17.674-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M864 679.68c0 17.674-14.326 32-32 32h-18.509c-8.218 40.547-8.218 82.333 0 122.88h19.789c16.966 0 30.72 13.754 30.72 30.72s-13.754 30.72-30.72 30.72h-545.28c-70.692 0-128-55.014-128-122.88v-453.12c0-106.038 85.961-192 192-192h480c17.674 0 32 14.327 32 32v519.68zM748.419 834.56c-6.787-40.678-6.787-82.202 0-122.88h-460.419c-35.346 0-64 27.507-64 61.44s28.654 61.44 64 61.44h460.419zM224 647.68h576v-455.68h-448c-70.692 0-128 57.308-128 128v327.68z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["book"],"defaultCode":59689,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":955,"name":"book","prevSize":32,"id":43,"code":59689},"setIdx":2,"setId":2,"iconIdx":43},{"icon":{"paths":["M193.603 416h-33.603c-17.673 0-32 14.326-32 32s14.327 32 32 32h704c17.674 0 32-14.326 32-32s-14.326-32-32-32h-33.603c-7.347-73.117-39.702-141.853-92.122-194.274-60.013-60.012-141.405-93.726-226.275-93.726s-166.262 33.714-226.274 93.726c-52.421 52.421-84.777 121.157-92.123 194.274zM330.979 266.981c48.010-48.010 113.126-74.981 181.021-74.981s133.011 26.971 181.021 74.981c40.403 40.404 65.907 92.923 72.973 149.019h-507.987c7.066-56.096 32.57-108.615 72.972-149.019z","M877.242 605.133c16.090-7.315 23.203-26.285 15.891-42.374-7.315-16.090-26.285-23.203-42.374-15.891l-127.558 57.981-127.558-57.981c-8.413-3.824-18.070-3.824-26.483 0l-127.558 57.981-127.558-57.981c-8.413-3.824-18.070-3.824-26.483 0l-140.8 64c-16.089 7.315-23.203 26.285-15.89 42.374s26.284 23.203 42.373 15.891l18.758-8.528v29.68c0 38.102 15.908 74.31 43.672 100.752 27.712 26.394 64.978 40.963 103.528 40.963h345.6c38.55 0 75.814-14.57 103.526-40.963 27.766-26.442 43.674-62.65 43.674-100.752v-64.589l45.242-20.563zM736.442 669.133l31.558-14.346v35.498c0 20.093-8.368 39.699-23.811 54.41-15.494 14.758-36.832 23.306-59.389 23.306h-345.6c-22.556 0-43.893-8.547-59.39-23.306-15.444-14.71-23.81-34.317-23.81-54.41v-58.771l44.8-20.362 127.558 57.981c8.413 3.824 18.070 3.824 26.483 0l127.558-57.981 127.558 57.981c8.413 3.824 18.070 3.824 26.483 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["burger"],"defaultCode":59813,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":956,"id":44,"name":"burger","prevSize":32,"code":59813},"setIdx":2,"setId":2,"iconIdx":44},{"icon":{"paths":["M224 224h320v576h-96v-112c0-8.835-7.165-16-16-16h-96c-8.835 0-16 7.165-16 16v112h-96v-576zM608 448h192v352h-192v-352zM832 384h-224v-192c0-17.673-14.326-32-32-32h-384c-17.673 0-32 14.327-32 32v640c0 17.674 14.327 32 32 32h640c17.674 0 32-14.326 32-32v-416c0-17.674-14.326-32-32-32zM304 288c-8.836 0-16 7.164-16 16v32c0 8.835 7.164 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.836-7.165-16-16-16h-32zM288 432c0-8.835 7.164-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.836 0-16-7.165-16-16v-32zM304 544c-8.836 0-16 7.165-16 16v32c0 8.835 7.164 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM416 304c0-8.836 7.165-16 16-16h32c8.835 0 16 7.164 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32zM432 416c-8.835 0-16 7.165-16 16v32c0 8.835 7.165 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM416 560c0-8.835 7.165-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32zM688 512c-8.835 0-16 7.165-16 16v32c0 8.835 7.165 16 16 16h32c8.835 0 16-7.165 16-16v-32c0-8.835-7.165-16-16-16h-32zM672 656c0-8.835 7.165-16 16-16h32c8.835 0 16 7.165 16 16v32c0 8.835-7.165 16-16 16h-32c-8.835 0-16-7.165-16-16v-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["business"],"defaultCode":59690,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":957,"name":"business","prevSize":32,"id":45,"code":59690},"setIdx":2,"setId":2,"iconIdx":45},{"icon":{"paths":["M277.831 157.44c0-16.259 13.181-29.44 29.44-29.44s29.439 13.181 29.439 29.44v58.876h353.28v-58.876c0-16.259 13.181-29.44 29.44-29.44s29.44 13.181 29.44 29.44v58.876h85.76c17.674 0 32 14.327 32 32v583.68c0 17.674-14.326 32-32 32h-642.559c-17.673 0-32-14.326-32-32v-583.68c0-1.105 0.056-2.196 0.165-3.272 1.639-16.136 15.266-28.728 31.835-28.728h85.76v-58.876zM802.63 392.957h-578.559v407.040h578.559v-407.040zM425.034 644.474c0-8.835 7.162-16 16-16h26.88c8.835 0 16 7.165 16 16v26.88c0 8.838-7.165 16-16 16h-26.88c-8.838 0-16-7.162-16-16v-26.88zM323.27 510.72c-8.836 0-15.999 7.162-15.999 16v26.88c0 8.835 7.163 16 15.999 16h26.88c8.838 0 16-7.165 16-16v-26.88c0-8.838-7.162-16-16-16h-26.88zM542.79 526.72c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.835-7.162 16-16 16h-26.88c-8.835 0-16-7.165-16-16v-26.88zM323.27 628.474c-8.835 0-15.999 7.165-15.999 16v26.88c0 8.838 7.164 16 15.999 16h26.88c8.838 0 16-7.162 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88zM542.79 644.474c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.838-7.162 16-16 16h-26.88c-8.835 0-16-7.162-16-16v-26.88zM441.030 510.72c-8.835 0-16 7.165-16 16v26.88c0 8.835 7.165 16 16 16h26.88c8.838 0 16-7.165 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88zM660.55 526.72c0-8.835 7.165-16 16-16h26.88c8.838 0 16 7.165 16 16v26.88c0 8.835-7.162 16-16 16h-26.88c-8.835 0-16-7.165-16-16v-26.88zM676.55 628.474c-8.835 0-16 7.165-16 16v26.88c0 8.838 7.165 16 16 16h26.88c8.838 0 16-7.162 16-16v-26.88c0-8.835-7.162-16-16-16h-26.88z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["calendar"],"defaultCode":59691,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":958,"name":"calendar","prevSize":32,"id":46,"code":59691},"setIdx":2,"setId":2,"iconIdx":46},{"icon":{"paths":["M256 202.672c0-17.673 19.102-32 42.667-32h255.999c23.565 0 42.669 14.327 42.669 32s-19.104 32-42.669 32h-255.999c-23.564 0-42.667-14.327-42.667-32zM160 383.994c0-5.891 4.776-10.666 10.667-10.666h511.999c5.891 0 10.669 4.774 10.669 10.666v85.334c0 11.376 6.038 21.894 15.859 27.632s21.949 5.83 31.856 0.243l97.83-55.165c2.531-1.427 4.858-3.19 6.912-5.248 6.72-6.717 18.208-1.958 18.208 7.546v263.318c0 9.504-11.488 14.262-18.208 7.542-2.054-2.054-4.381-3.818-6.912-5.245l-97.83-55.165c-9.907-5.587-22.035-5.494-31.856 0.243s-15.859 16.256-15.859 27.632v85.331c0 5.891-4.778 10.669-10.669 10.669h-511.999c-5.891 0-10.667-4.778-10.667-10.669v-384zM170.667 309.328c-41.237 0-74.667 33.43-74.667 74.666v384c0 41.238 33.429 74.669 74.667 74.669h511.999c41.238 0 74.669-33.43 74.669-74.669v-30.55l46.778 26.374c47.418 41.99 123.888 8.701 123.888-56.163v-263.318c0-64.864-76.47-98.157-123.888-56.166l-46.778 26.378v-30.554c0-41.235-33.43-74.666-74.669-74.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["camera"],"defaultCode":59696,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":959,"name":"camera","prevSize":32,"id":47,"code":59696},"setIdx":2,"setId":2,"iconIdx":47},{"icon":{"paths":["M866.128 153.126c-12.496-12.497-32.758-12.497-45.254 0l-668.246 668.246c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l668.246-668.246c12.496-12.497 12.496-32.758 0-45.255zM298.667 170.671c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h255.999c23.565 0 42.669-14.327 42.669-32s-19.104-32-42.669-32h-255.999zM574.173 309.327h-403.506c-41.237 0-74.667 33.428-74.667 74.667v384c0 6.010 0.71 11.856 2.051 17.453l61.949-61.949v-339.504c0-5.891 4.776-10.666 10.667-10.666h339.506l64-64.001zM376.339 778.659h306.326c5.891 0 10.669-4.774 10.669-10.666v-85.334c0-11.373 6.038-21.891 15.859-27.629s21.949-5.83 31.856-0.243l97.83 55.162c2.531 1.427 4.858 3.194 6.912 5.248 6.72 6.72 18.208 1.962 18.208-7.542v-263.322c0-9.501-11.488-14.262-18.208-7.542-2.054 2.054-4.381 3.821-6.912 5.248l-97.83 55.162c-9.907 5.587-22.035 5.494-31.856-0.243-9.821-5.734-15.859-16.256-15.859-27.629v-7.661l110.778-73.498c47.418-41.99 123.888-8.701 123.888 56.163v263.322c0 64.864-76.47 98.154-123.888 56.163l-46.778-26.378v30.554c0 41.238-33.43 74.666-74.669 74.666h-370.327l64.001-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["camera-disabled"],"defaultCode":59692,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":960,"name":"camera-disabled","prevSize":32,"id":48,"code":59692},"setIdx":2,"setId":2,"iconIdx":48},{"icon":{"paths":["M288 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h256c17.674 0 32-14.327 32-32s-14.326-32-32-32h-256z","M170.667 341.328c-23.564 0-42.667 19.104-42.667 42.666v384c0 23.565 19.102 42.669 42.667 42.669h511.999c23.565 0 42.669-19.104 42.669-42.669v-128l97.83 97.83c26.877 26.88 72.835 7.843 72.835-30.17v-263.318c0-38.013-45.958-57.050-72.835-30.173l-97.83 97.83v-128c0-23.562-19.104-42.666-42.669-42.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["camera-filled"],"defaultCode":59693,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":961,"name":"camera-filled","prevSize":32,"id":49,"code":59693},"setIdx":2,"setId":2,"iconIdx":49},{"icon":{"paths":["M196.731 191.997c0-15.807 12.814-28.622 28.622-28.622h128.001c15.805 0 28.621 12.814 28.621 28.622s-12.816 28.621-28.621 28.621h-128.001c-15.807 0-28.622-12.814-28.622-28.621z","M737.354 559.997c0 97.203-78.8 176-176 176-97.203 0-176-78.797-176-176s78.797-176 176-176c97.2 0 176 78.797 176 176zM673.354 559.997c0-61.856-50.144-112-112-112s-112 50.144-112 112c0 61.856 50.144 112 112 112s112-50.144 112-112z","M193.353 255.997c-35.346 0-64 28.654-64 64v448c0 35.347 28.654 64 64 64h640.001c35.344 0 64-28.653 64-64v-448c0-35.346-28.656-64-64-64h-640.001zM833.354 319.997v448h-640.001v-448h640.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["camera-photo"],"defaultCode":59694,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":962,"name":"camera-photo","prevSize":32,"id":50,"code":59694},"setIdx":2,"setId":2,"iconIdx":50},{"icon":{"paths":["M298.667 170.672c-23.564 0-42.667 14.327-42.667 32s19.102 32 42.667 32h255.999c23.565 0 42.669-14.327 42.669-32s-19.104-32-42.669-32h-255.999z","M545.712 503.453c11.267-11.267 11.19-29.61-0.17-40.97s-29.706-11.437-40.973-0.17l-71.402 71.402-71.994-71.997c-11.363-11.36-29.706-11.437-40.973-0.17s-11.19 29.61 0.17 40.97l71.997 71.997-71.402 71.402c-11.266 11.267-11.19 29.61 0.17 40.97 11.363 11.36 29.706 11.437 40.973 0.17l71.402-71.402 71.997 71.997c11.36 11.36 29.702 11.437 40.97 0.17s11.19-29.61-0.17-40.97l-71.997-71.997 71.402-71.402z","M96 383.994c0-41.235 33.429-74.666 74.667-74.666h511.999c41.238 0 74.669 33.43 74.669 74.666v30.554l46.778-26.378c47.418-41.99 123.888-8.698 123.888 56.166v263.318c0 64.864-76.47 98.154-123.888 56.163l-46.778-26.374v30.55c0 41.238-33.43 74.669-74.669 74.669h-511.999c-41.237 0-74.667-33.43-74.667-74.669v-384zM170.667 373.328c-5.891 0-10.667 4.774-10.667 10.666v384c0 5.891 4.776 10.669 10.667 10.669h511.999c5.891 0 10.669-4.778 10.669-10.669v-85.331c0-11.376 6.038-21.894 15.859-27.632s21.949-5.83 31.856-0.243l97.83 55.165c2.531 1.427 4.858 3.19 6.912 5.245 6.72 6.72 18.208 1.962 18.208-7.542v-263.318c0-9.504-11.488-14.262-18.208-7.546-2.054 2.058-4.381 3.821-6.912 5.248l-97.83 55.165c-9.907 5.587-22.035 5.494-31.856-0.243s-15.859-16.256-15.859-27.632v-85.334c0-5.891-4.778-10.666-10.669-10.666h-511.999z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["camera-unavailable"],"defaultCode":59695,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":963,"name":"camera-unavailable","prevSize":32,"id":51,"code":59695},"setIdx":2,"setId":2,"iconIdx":51},{"icon":{"paths":["M224.248 304.026c-49.642 68.947-66.502 152.646-66.502 207.968v1.453l-0.132 1.446c-9.702 106.717 28.59 181.93 90.135 234.006 62.938 53.254 152.152 83.731 244.197 93.958 91.965 10.218 193.27 1.446 273.306-15.482 40.022-8.461 73.616-18.733 97.443-29.075 9.245-4.013 16.438-7.786 21.734-11.126-2.464-1.565-5.446-3.306-9.002-5.197-9.222-4.912-19.779-9.578-30.733-14.368l-1.914-0.835c-9.667-4.221-20.47-8.941-28.656-13.517-14.835-8.298-29.389-17.734-40.006-27.776-5.222-4.941-11.165-11.571-15.146-19.827-4.208-8.742-7.226-21.792-1.306-35.597 31.978-74.621 47.178-115.494 54.538-142.483 6.874-25.2 6.874-37.888 6.874-58.064v-0.182c0-16.035-9.318-89.517-55.811-158.032-45.018-66.338-125.99-129.968-274.854-129.968-134.637 0-215.698 55.382-264.165 122.698zM172.309 266.63c60.333-83.796 160.606-149.302 316.103-149.302 171.136 0 271.494 75.037 327.811 158.032 54.842 80.819 66.854 167.338 66.854 193.968 0 22.384-0.022 41.696-9.126 75.088-8.131 29.805-23.485 70.928-51.946 137.923 5.261 4.166 13.072 9.306 23.36 15.062 5.315 2.97 13.485 6.55 24.963 11.568 10.653 4.659 23.437 10.266 35.174 16.515 11.258 5.994 24.416 14.029 34.202 24.538 10.234 10.992 20.973 29.846 13.299 52.864-5.056 15.168-16.794 25.939-26.576 33.094-10.63 7.776-23.818 14.762-38.253 21.030-29.008 12.589-67.030 23.962-109.683 32.982-85.309 18.038-193.581 27.587-293.616 16.474-99.955-11.107-202.74-44.634-278.468-108.71-76.833-65.011-123.811-159.994-112.66-287.222 0.286-65.549 19.841-162.349 78.561-243.904zM493.744 320c17.674 0 32 14.326 32 32v224c0 17.674-14.326 32-32 32s-32-14.326-32-32v-224c0-17.674 14.326-32 32-32zM525.744 672c0-17.674-14.326-32-32-32s-32 14.326-32 32c0 17.674 14.326 32 32 32s32-14.326 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["canned-response"],"defaultCode":59697,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":964,"name":"canned-response","prevSize":32,"id":52,"code":59697},"setIdx":2,"setId":2,"iconIdx":52},{"icon":{"paths":["M193.352 181.331c-53.020 0-96 42.981-96 96v469.335c0 53.018 42.98 96 96 96h639.999c53.021 0 96-42.982 96-96v-469.335c0-53.019-42.979-96-96-96h-639.999zM161.352 277.331c0-17.673 14.327-32 32-32h639.999c17.674 0 32 14.327 32 32v202.673h-703.999v-202.673zM161.352 544.003h703.999v202.662c0 17.67-14.326 32-32 32h-639.999c-17.673 0-32-14.33-32-32v-202.662zM812.016 661.331c0-35.347-28.653-64-64-64-35.344 0-64 28.653-64 64s28.656 64 64 64c35.347 0 64-28.653 64-64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["card"],"defaultCode":59698,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":965,"name":"card","prevSize":32,"id":53,"code":59698},"setIdx":2,"setId":2,"iconIdx":53},{"icon":{"paths":["M368 182.4c0-17.673-14.326-32-32-32s-32 14.327-32 32v144h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v288h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v144c0 17.674 14.327 32 32 32s32-14.326 32-32v-144h288v144c0 17.674 14.326 32 32 32s32-14.326 32-32v-144h144c17.674 0 32-14.326 32-32s-14.326-32-32-32h-144v-80h-64v80h-288v-288h80v-64h-80v-144z","M640.515 327.283c-15.328-3.59-31.306-3.338-46.512 0.733-41.763 11.187-70.803 49.030-70.803 92.269v35.539c0 36.003 29.187 65.194 65.194 65.194h210.413c36.006 0 65.194-29.19 65.194-65.194v-28.336c0-47.667-33.040-88.957-79.27-99.792-16.413-3.846-33.613-3.603-49.946 0.771l-25.827 6.918c-10.381 2.781-21.286 2.95-31.747 0.499l-36.694-8.602z","M782.637 217.037c0 49.174-39.862 89.037-89.037 89.037s-89.037-39.863-89.037-89.037c0-49.174 39.862-89.037 89.037-89.037s89.037 39.863 89.037 89.037z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["channel-auto-join"],"defaultCode":59746,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":966,"name":"channel-auto-join","prevSize":32,"id":54,"code":59746},"setIdx":2,"setId":2,"iconIdx":54},{"icon":{"paths":["M236.709 162.578c11.779-5.037 25.426-2.564 34.688 6.286l150.709 144c6.32 6.037 9.894 14.396 9.894 23.136s-3.574 17.101-9.894 23.136l-150.709 144c-9.262 8.851-22.909 11.325-34.688 6.288s-19.419-16.614-19.419-29.424v-112h-73.29c-17.673 0-32-14.326-32-32 0-17.672 14.327-31.999 32-31.999h73.29v-112c0-12.81 7.64-24.386 19.419-29.423zM320 368.179v-0.179h0.189l-0.189 0.179zM320.189 304.001h-0.189v-0.179l0.189 0.179z","M492.899 303.258c8.762-9.388 21.245-15.258 35.101-15.258 26.509 0 48 21.49 48 48s-21.491 48-48 48c-16.582 0-31.203-8.41-39.824-21.197l-43.098 48.483c20.49 22.554 50.051 36.714 82.922 36.714 61.856 0 112-50.144 112-112s-50.144-112-112-112c-25.549 0-49.098 8.554-67.942 22.955l32.842 56.303z","M145.615 483.229l32.174 64.349c-0.861 3.040-1.318 6.23-1.318 9.501v44.688c0 17.674 14.327 32 32 32h79.53v64h-79.53c-53.019 0-96-42.979-96-96v-44.688c0-28.848 12.515-55.488 33.144-73.85z","M625.267 640h-0.797c0.259 0.598 0.525 1.194 0.797 1.786v-1.786z","M424.714 640h-0.797v1.786c0.272-0.592 0.538-1.187 0.797-1.786z","M477.901 494.515c-28.56-10.957-60.291-10.211-88.307 2.067-42.282 18.534-69.594 60.326-69.594 106.49v132.928c0 53.021 42.979 96 96 96h224c53.021 0 96-42.979 96-96v-125.062c0-51.162-31.536-97.034-79.306-115.354-30.352-11.642-64.067-10.851-93.84 2.198l-2.070 0.909c-21.523 9.434-45.901 10.006-67.843 1.59l-15.040-5.766zM415.286 555.2c12.595-5.52 26.858-5.856 39.699-0.931l15.040 5.77c37.664 14.445 79.504 13.462 116.451-2.73l2.070-0.909c14.349-6.288 30.602-6.669 45.229-1.059 23.024 8.829 38.224 30.938 38.224 55.597v125.062c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32v-132.928c0-20.752 12.278-39.539 31.286-47.872z","M864 320c0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96s96-42.979 96-96zM800 320c0 17.674-14.326 32-32 32s-32-14.326-32-32c0-17.673 14.326-32 32-32s32 14.327 32 32z","M840.714 697.766h-72.714v-64h72.714c17.674 0 32-14.326 32-32v-44.688c0-15.050-9.664-28.394-23.958-33.091-7.536-2.474-15.69-2.304-23.114 0.483l-4.554 1.709c-19.77 7.421-40.89 9.978-61.619 7.632-12.438-31.683-37.722-57.549-70.774-70.227-1.754-0.672-3.52-1.302-5.296-1.894 18.058-5.312 37.36-5.040 55.344 0.867l14.182 4.659c14.886 4.893 30.998 4.554 45.667-0.954l4.554-1.709c21.069-7.91 44.205-8.394 65.581-1.37 40.566 13.325 67.987 51.197 67.987 93.894v44.688c0 53.021-42.982 96-96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["channel-move-to-team"],"defaultCode":59747,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":967,"name":"channel-move-to-team","prevSize":32,"id":55,"code":59747},"setIdx":2,"setId":2,"iconIdx":55},{"icon":{"paths":["M368 160c0-17.673-14.326-32-32-32s-32 14.327-32 32v144h-144c-17.673 0-32 14.327-32 32s14.327 32 32 32h144v288h-144c-17.673 0-32 14.326-32 32s14.327 32 32 32h144v144c0 17.674 14.327 32 32 32s32-14.326 32-32v-144h288v144c0 17.674 14.326 32 32 32s32-14.326 32-32v-144h144c17.674 0 32-14.326 32-32s-14.326-32-32-32h-144v-80h-58.666c-1.786 0-3.565-0.042-5.334-0.118v80.118h-288v-288h168.79c-0.522-5.264-0.79-10.602-0.79-16v-48h-168v-144z","M760 96c-57.437 0-104 46.562-104 104v56h-24c-17.674 0-32 14.327-32 32v192c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-192c0-17.673-14.326-32-32-32h-24v-56c0-57.438-46.563-104-104-104zM800 255.238h-80v-55.238c0-22.092 17.907-40 40-40s40 17.908 40 40v55.238z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["channel-private"],"defaultCode":59699,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":968,"name":"channel-private","prevSize":32,"id":56,"code":59699},"setIdx":2,"setId":2,"iconIdx":56},{"icon":{"paths":["M336 128c17.674 0 32 14.327 32 32v144h288v-144c0-17.673 14.326-32 32-32s32 14.327 32 32v144h144c17.674 0 32 14.327 32 32s-14.326 32-32 32h-144v288h144c17.674 0 32 14.326 32 32s-14.326 32-32 32h-144v144c0 17.674-14.326 32-32 32s-32-14.326-32-32v-144h-288v144c0 17.674-14.326 32-32 32s-32-14.326-32-32v-144h-144c-17.673 0-32-14.326-32-32s14.327-32 32-32h144v-288h-144c-17.673 0-32-14.326-32-32s14.327-32 32-32h144v-144c0-17.673 14.327-32 32-32zM368 368v288h288v-288h-288z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["channel-public"],"defaultCode":59700,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":969,"name":"channel-public","prevSize":32,"id":57,"code":59700},"setIdx":2,"setId":2,"iconIdx":57},{"icon":{"paths":["M886.627 105.372c12.496 12.497 12.496 32.758 0 45.255l-89.373 89.372 89.373 89.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-89.373-89.372-89.373 89.372c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l89.373-89.373-89.373-89.372c-12.496-12.497-12.496-32.758 0-45.255s32.758-12.497 45.254 0l89.373 89.373 89.373-89.373c12.496-12.497 32.758-12.497 45.254 0zM226.501 304.042c-49.642 68.947-66.502 152.646-66.502 207.968v1.453l-0.132 1.446c-9.701 106.717 28.59 181.93 90.135 234.006 62.938 53.254 152.151 83.731 244.196 93.958 91.968 10.218 193.27 1.446 273.309-15.482 40.019-8.461 73.613-18.733 97.44-29.075 9.245-4.013 16.438-7.786 21.738-11.126-2.467-1.565-5.446-3.306-9.005-5.2-9.222-4.909-19.776-9.574-30.733-14.365l-1.917-0.838c-9.667-4.221-20.47-8.938-28.653-13.517-14.835-8.294-29.389-17.731-40.003-27.773-5.226-4.941-11.168-11.571-15.146-19.827-4.211-8.742-7.226-21.792-1.309-35.6 42.086-98.205 54.957-137.722 59.219-163.318 2.906-17.434 19.392-29.21 36.822-26.307 17.434 2.906 29.213 19.389 26.307 36.822-5.453 32.749-20.333 76.41-58.006 165.088 5.261 4.166 13.069 9.306 23.357 15.059 5.315 2.973 13.485 6.554 24.963 11.571 10.656 4.656 23.437 10.266 35.174 16.515 11.261 5.994 24.419 14.029 34.202 24.538 10.234 10.992 20.973 29.846 13.299 52.864-5.053 15.168-16.794 25.939-26.576 33.094-10.627 7.776-23.814 14.762-38.253 21.027-29.005 12.592-67.027 23.965-109.68 32.986-85.312 18.038-193.584 27.587-293.616 16.47-99.955-11.104-202.742-44.63-278.471-108.707-76.833-65.014-123.811-159.997-112.66-287.222 0.286-65.549 19.841-162.349 78.561-243.904 60.333-83.796 160.605-149.302 316.103-149.302 17.674 0 32 14.327 32 32s-14.326 32-32 32c-134.637 0-215.697 55.382-264.164 122.698z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chat-close"],"defaultCode":59701,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":970,"name":"chat-close","prevSize":32,"id":58,"code":59701},"setIdx":2,"setId":2,"iconIdx":58},{"icon":{"paths":["M778 93.833c-11.795-13.162-32.026-14.271-45.187-2.477s-14.272 32.025-2.477 45.187l81.222 90.645h-216.358c-17.674 0-32 14.327-32 32s14.326 32 32 32h216.358l-81.222 90.646c-11.795 13.162-10.685 33.392 2.477 45.187 13.162 11.792 33.392 10.685 45.187-2.477l129.030-144.001c10.893-12.154 10.893-30.556 0-42.71l-129.030-144zM159.999 512.010c0-55.322 16.86-139.021 66.502-207.968 48.467-67.316 129.527-122.698 264.164-122.698 17.674 0 32-14.327 32-32s-14.326-32-32-32c-155.498 0-255.77 65.507-316.102 149.302-58.72 81.555-78.275 178.355-78.561 243.904-11.151 127.229 35.827 222.211 112.66 287.222 75.729 64.077 178.516 97.603 278.471 108.707 100.032 11.117 208.304 1.568 293.616-16.47 42.653-9.021 80.675-20.394 109.68-32.982 14.438-6.269 27.626-13.254 38.253-21.030 9.782-7.155 21.523-17.926 26.579-33.094 7.67-23.018-3.069-41.872-13.302-52.864-9.782-10.509-22.941-18.544-34.202-24.538-11.738-6.25-24.518-11.859-35.171-16.515-11.482-5.018-19.651-8.598-24.966-11.571-10.288-5.754-18.096-10.89-23.357-15.059 37.674-88.678 52.554-132.339 58.010-165.088 2.902-17.43-8.877-33.917-26.31-36.822-17.43-2.902-33.917 8.877-36.822 26.307-4.262 25.597-17.133 65.114-59.219 163.318-5.917 13.808-2.902 26.858 1.309 35.6 3.978 8.256 9.92 14.886 15.146 19.827 10.614 10.042 25.171 19.478 40.003 27.776 8.186 4.576 18.989 9.296 28.656 13.517v0l1.914 0.835c10.957 4.79 21.51 9.456 30.733 14.368 3.558 1.891 6.541 3.632 9.005 5.197-5.299 3.341-12.493 7.114-21.738 11.126-23.827 10.342-57.421 20.614-97.44 29.075-80.038 16.928-181.341 25.699-273.309 15.482-92.045-10.227-181.258-40.704-244.196-93.958-61.545-52.077-99.836-127.29-90.135-234.006l0.132-1.446v-1.453z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chat-forward"],"defaultCode":59702,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":971,"name":"chat-forward","prevSize":32,"id":59,"code":59702},"setIdx":2,"setId":2,"iconIdx":59},{"icon":{"paths":["M854.506 233.252c12.563 12.429 12.672 32.691 0.243 45.254l-474.877 480c-6.013 6.077-14.208 9.498-22.755 9.494-8.55-0.003-16.742-3.427-22.752-9.507l-165.126-167.088c-12.423-12.57-12.303-32.832 0.268-45.254s32.831-12.304 45.254 0.269l142.375 144.067 452.115-456.992c12.429-12.564 32.691-12.672 45.254-0.243z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["check"],"defaultCode":59703,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":972,"name":"check","prevSize":32,"id":60,"code":59703},"setIdx":2,"setId":2,"iconIdx":60},{"icon":{"paths":["M204.8 128h614.4c42.416 0 76.8 34.385 76.8 76.8v614.4c0 42.416-34.384 76.8-76.8 76.8h-614.4c-42.415 0-76.8-34.384-76.8-76.8v-614.4c0-42.415 34.385-76.8 76.8-76.8zM769.062 336.88c9.322-9.424 9.238-24.619-0.182-33.941-9.424-9.322-24.621-9.241-33.942 0.182l-339.085 342.745-106.782-108.051c-9.317-9.43-24.513-9.52-33.94-0.202s-9.518 24.512-0.201 33.939l123.842 125.318c4.509 4.56 10.653 7.126 17.066 7.13s12.557-2.563 17.069-7.12l356.157-360z"],"attrs":[{"fill":"rgb(29, 116, 245)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":5}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":4}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":6}]},"tags":["checkbox-checked"],"defaultCode":59654,"grid":0},"attrs":[{"fill":"rgb(29, 116, 245)"}],"properties":{"order":973,"name":"checkbox-checked","prevSize":32,"id":61,"code":59654},"setIdx":2,"setId":2,"iconIdx":61},{"icon":{"paths":["M819.2 204.8v614.4h-614.4v-614.4h614.4zM204.8 128c-42.415 0-76.8 34.385-76.8 76.8v614.4c0 42.416 34.385 76.8 76.8 76.8h614.4c42.416 0 76.8-34.384 76.8-76.8v-614.4c0-42.415-34.384-76.8-76.8-76.8h-614.4z"],"attrs":[{"fill":"rgb(203, 206, 209)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":8}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":8}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":10}]},"tags":["checkbox-unchecked"],"defaultCode":59653,"grid":0},"attrs":[{"fill":"rgb(203, 206, 209)"}],"properties":{"order":974,"name":"checkbox-unchecked","prevSize":32,"id":62,"code":59653},"setIdx":2,"setId":2,"iconIdx":62},{"icon":{"paths":["M281.372 436.042c12.497-12.499 32.758-12.499 45.255 0l185.373 185.373 185.373-185.373c12.496-12.499 32.758-12.499 45.254 0 12.496 12.496 12.496 32.758 0 45.254l-208 208c-12.496 12.496-32.758 12.496-45.254 0l-208-208c-12.497-12.496-12.497-32.758 0-45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-down"],"defaultCode":59704,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":975,"name":"chevron-down","prevSize":32,"id":63,"code":59704},"setIdx":2,"setId":2,"iconIdx":63},{"icon":{"paths":["M587.962 281.372c12.496 12.497 12.496 32.758 0 45.255l-185.373 185.373 185.373 185.373c12.496 12.496 12.496 32.758 0 45.254-12.499 12.496-32.758 12.496-45.258 0l-208-208c-12.496-12.496-12.496-32.758 0-45.254l208-208c12.499-12.497 32.758-12.497 45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-left"],"defaultCode":59706,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":976,"name":"chevron-left","prevSize":32,"id":64,"code":59706},"setIdx":2,"setId":2,"iconIdx":64},{"icon":{"paths":["M670.17 183.165c16.662 16.662 16.662 43.677 0 60.34l-268.496 268.495 268.496 268.499c16.662 16.662 16.662 43.677 0 60.339s-43.677 16.662-60.339 0l-298.668-298.669c-8.002-8-12.497-18.851-12.497-30.17 0-11.315 4.495-22.166 12.497-30.17l298.668-298.666c16.662-16.662 43.677-16.662 60.339 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-left-big"],"defaultCode":59705,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":977,"name":"chevron-left-big","prevSize":32,"id":65,"code":59705},"setIdx":2,"setId":2,"iconIdx":65},{"icon":{"paths":["M436.038 742.627c-12.496-12.496-12.496-32.758 0-45.254l185.373-185.373-185.373-185.373c-12.496-12.497-12.496-32.758 0-45.254 12.499-12.497 32.758-12.497 45.254 0l208 208c12.499 12.496 12.499 32.758 0 45.254l-207.997 208c-12.499 12.496-32.758 12.496-45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-right"],"defaultCode":59707,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":978,"name":"chevron-right","prevSize":32,"id":66,"code":59707},"setIdx":2,"setId":2,"iconIdx":66},{"icon":{"paths":["M742.627 587.958c-12.496 12.499-32.758 12.499-45.254 0l-185.373-185.373-185.373 185.373c-12.496 12.499-32.758 12.499-45.254 0-12.497-12.496-12.497-32.758 0-45.254l208-208c12.496-12.496 32.758-12.496 45.254 0l208 208c12.496 12.496 12.496 32.758 0 45.254z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["chevron-up"],"defaultCode":59708,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":979,"name":"chevron-up","prevSize":32,"id":67,"code":59708},"setIdx":2,"setId":2,"iconIdx":67},{"icon":{"paths":["M512 864c194.403 0 352-157.597 352-352 0-46.522-9.024-90.931-25.418-131.581l48.518-48.518c26.211 54.496 40.899 115.581 40.899 180.099 0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416 95.376 0 183.254 32.096 253.424 86.076l-45.712 45.712c-58.221-42.623-130.029-67.788-207.712-67.788-194.404 0-352 157.596-352 352s157.596 352 352 352zM902.63 230.623c12.496-12.499 12.493-32.76-0.006-45.255s-32.762-12.491-45.254 0.008l-345.386 345.503-105.341-105.491c-12.486-12.506-32.749-12.522-45.254-0.032-12.506 12.486-12.522 32.749-0.032 45.254l127.971 128.157c6 6.006 14.144 9.386 22.634 9.389 8.493 0 16.637-3.373 22.64-9.376l368.029-368.157z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["circle-check"],"defaultCode":59709,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":980,"name":"circle-check","prevSize":32,"id":68,"code":59709},"setIdx":2,"setId":2,"iconIdx":68},{"icon":{"paths":["M608 192c0-53.019-42.979-96-96-96s-96 42.981-96 96h-192c-17.673 0-32 14.327-32 32v672c0 17.674 14.327 32 32 32h576c17.674 0 32-14.326 32-32v-672c0-17.673-14.326-32-32-32h-192zM256 864v-608h96v64c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-64h96v608h-512zM512 224c17.674 0 32-14.327 32-32s-14.326-32-32-32c-17.674 0-32 14.327-32 32s14.326 32 32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["clipboard"],"defaultCode":59710,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":981,"name":"clipboard","prevSize":32,"id":69,"code":59710},"setIdx":2,"setId":2,"iconIdx":69},{"icon":{"paths":["M864 512c0 194.403-157.597 352-352 352s-352-157.597-352-352c0-194.404 157.596-352 352-352s352 157.596 352 352zM928 512c0-229.75-186.25-416-416-416s-416 186.25-416 416c0 229.75 186.25 416 416 416s416-186.25 416-416zM544 288c0-17.673-14.326-32-32-32s-32 14.327-32 32v224c0 8.486 3.373 16.627 9.373 22.627l96 96c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-86.627-86.627v-210.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["clock"],"defaultCode":59711,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":982,"name":"clock","prevSize":32,"id":70,"code":59711},"setIdx":2,"setId":2,"iconIdx":70},{"icon":{"paths":["M806.627 262.628c12.496-12.497 12.496-32.758 0-45.255s-32.758-12.497-45.254 0l-249.373 249.373-249.372-249.373c-12.497-12.497-32.758-12.497-45.255 0s-12.497 32.758 0 45.255l249.373 249.372-249.373 249.373c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l249.372-249.373 249.373 249.373c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-249.373-249.373 249.373-249.372z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["close"],"defaultCode":59712,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":983,"name":"close","prevSize":32,"id":71,"code":59712},"setIdx":2,"setId":2,"iconIdx":71},{"icon":{"paths":["M273.129 356.678c6.747-28.298 25.696-52.004 51.21-67.152 25.6-15.2 56.323-20.858 84.698-14.53 27.642 6.163 55.117 24.12 74.874 60.339l22.541 41.325 30.134-36.16c27.238-32.689 85.126-39.713 134.714-14.064 23.562 12.186 42.208 30.618 52.064 53.488 9.654 22.406 12.112 51.898-1.434 89.149l-15.616 42.938h45.686c53.606 0 82.419 15.882 97.642 33.75 15.651 18.374 21.898 44.646 18.557 74.714-3.344 30.083-16.054 60.518-33.456 82.89-17.939 23.066-36.646 32.646-50.742 32.646h-543.998c-18.791 0-37.068-10.362-52.195-31.578-15.217-21.344-24.978-51.050-25.818-81.312-0.84-30.227 7.237-57.914 23.733-77.491 15.796-18.746 42.268-33.619 86.279-33.619h59.791l-33.165-49.75c-27.882-41.824-32.118-77.814-25.498-105.581zM518.218 272.084c-26.339-32.073-59.667-51.619-95.251-59.554-45.626-10.174-92.902-0.833-131.301 21.965-38.487 22.85-69.538 60.142-80.791 107.342-8.278 34.72-5.369 72.758 10.731 111.77-35.67 8.464-64.099 26.186-84.825 50.784-29.004 34.422-39.927 78.733-38.766 120.506 1.159 41.738 14.399 84.032 37.682 116.688 23.373 32.784 59.097 58.426 104.306 58.426h543.999c41.907 0 77.2-26.419 101.261-57.354 24.598-31.629 41.888-73.197 46.544-115.114 4.659-41.933-3.094-87.658-33.443-123.283-24.106-28.301-59.504-46.774-105.616-53.456 5.83-35.194 1.686-67.674-10.605-96.205-16.646-38.628-46.998-67.197-81.437-85.010-54.902-28.397-128.733-32.652-182.486 2.495zM512 437.331c17.674 0 32 14.33 32 32v53.328h53.334c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-53.334v53.341c0 17.674-14.326 32-32 32s-32-14.326-32-32v-53.341h-53.331c-17.674 0-32-14.326-32-32 0-17.67 14.326-32 32-32h53.331v-53.328c0-17.67 14.326-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["cloud-connectivity"],"defaultCode":59713,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":984,"name":"cloud-connectivity","prevSize":32,"id":72,"code":59713},"setIdx":2,"setId":2,"iconIdx":72},{"icon":{"paths":["M630.157 204.798c16.493 6.344 24.723 24.859 18.378 41.355l-213.331 554.667c-6.346 16.496-24.861 24.723-41.357 18.381-16.493-6.346-24.723-24.861-18.378-41.357l213.331-554.666c6.346-16.495 24.861-24.724 41.357-18.38zM321.296 361.37c12.496 12.499 12.496 32.758 0 45.258l-105.373 105.37 105.373 105.373c12.496 12.499 12.496 32.758 0 45.258-12.497 12.496-32.759 12.496-45.255 0l-128-128c-12.497-12.499-12.497-32.758 0-45.258l128-128c12.497-12.496 32.758-12.496 45.255 0zM702.707 361.37c12.496-12.496 32.758-12.496 45.254 0l128 128c12.496 12.499 12.496 32.758 0 45.258l-128 128c-12.496 12.496-32.758 12.496-45.254 0-12.496-12.499-12.496-32.758 0-45.258l105.373-105.373-105.373-105.37c-12.496-12.499-12.496-32.758 0-45.258z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["code"],"defaultCode":59714,"grid":0},"attrs":[{}],"properties":{"order":985,"name":"code","prevSize":32,"id":73,"code":59714},"setIdx":2,"setId":2,"iconIdx":73},{"icon":{"paths":["M507.488 130.134c16.496 6.344 24.723 24.859 18.378 41.354l-160 416c-6.342 16.496-24.858 24.723-41.354 18.381-16.494-6.346-24.723-24.861-18.379-41.357l160.002-415.998c6.342-16.495 24.858-24.724 41.354-18.38z","M278.628 249.373c12.497 12.497 12.497 32.758 0 45.255l-73.373 73.372 73.373 73.373c12.497 12.496 12.497 32.758 0 45.254-12.497 12.499-32.758 12.499-45.255 0l-96-96c-6.001-6-9.372-14.141-9.372-22.627s3.372-16.624 9.372-22.627l96-95.999c12.497-12.497 32.758-12.497 45.255 0z","M553.373 249.373c12.496-12.497 32.758-12.497 45.254 0l96 95.999c6 6.003 9.373 14.141 9.373 22.627s-3.373 16.627-9.373 22.627l-96 96c-12.496 12.499-32.758 12.499-45.254 0-12.496-12.496-12.496-32.758 0-45.254l73.373-73.373-73.373-73.372c-12.496-12.497-12.496-32.758 0-45.255z","M672 160c0-17.673 14.326-32 32-32h96c53.021 0 96 42.981 96 96v576c0 53.021-42.979 96-96 96h-576c-53.020 0-96-42.979-96-96v-160c0-17.674 14.327-32 32-32s32 14.326 32 32v192h640v-640h-128c-17.674 0-32-14.327-32-32z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{},{},{},{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{},{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{},{},{}]},"tags":["code-block"],"defaultCode":59840,"grid":0},"attrs":[{},{},{},{}],"properties":{"order":986,"id":74,"name":"code-block","prevSize":32,"code":59840},"setIdx":2,"setId":2,"iconIdx":74},{"icon":{"paths":["M770.704 224c17.674 0 32 14.327 32 32v544c0 17.674-14.326 32-32 32h-543.999c-17.673 0-32-14.326-32-32v-128c17.673 0 32-14.326 32-32s-14.327-32-32-32v-192c17.673 0 32-14.326 32-32s-14.327-32-32-32v-96c0-17.673 14.327-32 32-32h543.999zM130.705 608c-17.673 0-32 14.326-32 32s14.327 32 32 32v128c0 53.021 42.981 96 96 96h543.999c53.021 0 96-42.979 96-96v-544c0-53.019-42.979-96-96-96h-543.999c-53.019 0-96 42.981-96 96v96c-17.673 0-32 14.326-32 32s14.327 32 32 32v192zM427.91 514.266c13.315-3.568 27.309-3.789 40.73-0.643l31.52 7.389c8.73 2.045 17.83 1.904 26.49-0.416l22.186-5.942c14.285-3.827 29.328-4.042 43.683-0.675 40.429 9.475 69.325 45.584 69.325 87.277v24.336c0 31.811-25.789 57.6-57.6 57.6h-180.739c-31.811 0-57.6-25.789-57.6-57.6v-30.525c0-37.862 25.434-71.005 62.006-80.8zM456.957 563.472c-5.206-1.219-10.634-1.133-15.798 0.25-14.189 3.798-24.054 16.656-24.054 31.344v30.525c0 3.536 2.867 6.4 6.4 6.4h180.739c3.533 0 6.4-2.864 6.4-6.4v-24.336c0-17.75-12.365-33.341-29.808-37.427-6.186-1.45-12.662-1.35-18.752 0.282l-22.186 5.942c-16.813 4.502-34.474 4.781-51.421 0.81l-31.52-7.389zM539.155 420.48c0-13.962-11.318-25.28-25.28-25.28s-25.283 11.318-25.283 25.28c0 13.962 11.322 25.28 25.283 25.28s25.28-11.318 25.28-25.28zM590.355 420.48c0 42.24-34.243 76.48-76.48 76.48-42.24 0-76.483-34.24-76.483-76.48s34.243-76.48 76.483-76.48c42.237 0 76.48 34.24 76.48 76.48z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["contacts"],"defaultCode":59715,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":987,"name":"contacts","prevSize":32,"id":75,"code":59715},"setIdx":2,"setId":2,"iconIdx":75},{"icon":{"paths":["M464 272c-35.347 0-64 28.654-64 64v480c0 35.347 28.653 64 64 64h352c35.347 0 64-28.653 64-64v-304c0-6.509-1.984-12.864-5.69-18.214l-134.458-194.215c-11.952-17.267-31.619-27.571-52.621-27.571h-223.232zM464 336h144v144c0 35.347 28.653 64 64 64h144v272h-352v-480zM672 480v-144h15.232l99.693 144h-114.925zM144 208c0-35.346 28.654-64 64-64h241.844c18.032 0 35.229 7.607 47.357 20.949l39.136 43.051h-328.336v480h128v64h-128c-35.346 0-64-28.653-64-64v-480z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["copy"],"defaultCode":59716,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":988,"name":"copy","prevSize":32,"id":76,"code":59716},"setIdx":2,"setId":2,"iconIdx":76},{"icon":{"paths":["M824.682 183.521c-37.19-37.986-98.202-38.583-136.131-1.333l-348.48 342.237c-12.739 12.512-21.733 28.32-25.976 45.654l-23.681 96.749c-6.94 28.355 16.754 54.845 45.747 51.142l90.691-11.578c20.224-2.582 39.104-11.52 53.907-25.52l360.486-340.922c38.986-36.868 40.173-98.482 2.637-136.82l-19.2-19.61zM733.485 227.821c12.643-12.417 32.979-12.218 45.376 0.444l19.2 19.61c12.512 12.78 12.115 33.317-0.88 45.607l-69.965 66.169-63.446-63.364 69.715-68.466zM618.074 341.162l62.592 62.512-243.971 230.73c-4.934 4.666-11.229 7.645-17.968 8.506l-58.307 7.443 15.926-65.075c1.414-5.779 4.413-11.046 8.659-15.219l233.069-228.896zM193.608 265.602c0-17.673 14.346-32 32.042-32h281.332c17.696 0 32.042-14.327 32.042-32s-14.346-32-32.042-32h-281.332c-53.089 0-96.127 42.981-96.127 96v534.402c0 53.018 43.037 95.997 96.127 95.997h529.764c53.091 0 96.128-42.979 96.128-96v-279.414c0-17.67-14.346-32-32.042-32s-32.042 14.33-32.042 32v279.414c0 17.674-14.346 32-32.045 32h-529.764c-17.696 0-32.042-14.326-32.042-31.997v-534.402z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["create"],"defaultCode":59717,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":989,"name":"create","prevSize":32,"id":77,"code":59717},"setIdx":2,"setId":2,"iconIdx":77},{"icon":{"paths":["M717.373 298.663c0-17.673-14.326-32-32-32s-32 14.327-32 32v426.665c0 17.674 14.326 32 32 32s32-14.326 32-32v-426.665z","M514.704 394.672c17.674 0 32 14.326 32 32v298.666c0 17.674-14.326 32-32 32s-32-14.326-32-32v-298.666c0-17.674 14.326-32 32-32z","M376.038 554.672c0-17.674-14.326-32-32-32s-32 14.326-32 32v170.669c0 17.67 14.327 32 32 32s32-14.33 32-32v-170.669z","M130.705 199.556v624.889c0 39.52 32.036 71.555 71.556 71.555h624.888c39.52 0 71.555-32.035 71.555-71.555v-624.889c0-39.519-32.035-71.556-71.555-71.556h-624.888c-39.519 0-71.556 32.036-71.556 71.556zM202.26 192h624.888c4.173 0 7.555 3.383 7.555 7.556v624.889c0 4.173-3.382 7.555-7.555 7.555h-624.888c-4.173 0-7.556-3.382-7.556-7.555v-624.889c0-4.173 3.383-7.556 7.556-7.556z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["dashboard"],"defaultCode":59718,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":990,"name":"dashboard","prevSize":32,"id":78,"code":59718},"setIdx":2,"setId":2,"iconIdx":78},{"icon":{"paths":["M739.68 864v-448h-448.593v448h448.593zM227.003 864v-448c-35.393 0-64.084-28.653-64.084-64v-128c0-35.346 28.692-64 64.084-64h224.297c0-35.346 28.691-64 64.083-64 35.395 0 64.086 28.654 64.086 64h224.294c35.395 0 64.086 28.654 64.086 64v128c0 35.347-28.691 64-64.086 64v448c0 35.347-28.691 64-64.083 64h-448.593c-35.393 0-64.085-28.653-64.085-64zM803.763 224h-576.761v128h576.761v-128zM419.258 544v192c0 17.674 14.346 32 32.042 32s32.042-14.326 32.042-32v-192c0-17.674-14.346-32-32.042-32s-32.042 14.326-32.042 32zM579.469 512c17.696 0 32.042 14.326 32.042 32v192c0 17.674-14.346 32-32.042 32s-32.042-14.326-32.042-32v-192c0-17.674 14.346-32 32.042-32z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["delete"],"defaultCode":59719,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":991,"name":"delete","prevSize":32,"id":79,"code":59719},"setIdx":2,"setId":2,"iconIdx":79},{"icon":{"paths":["M341.334 778.672c-17.674 0-32 14.326-32 32s14.327 32 32 32h341.334c17.67 0 32-14.326 32-32s-14.33-32-32-32h-341.334z","M85.334 298.672c0-70.692 57.308-128 128-128h597.335c70.691 0 128 57.308 128 128v298.666c0 70.694-57.309 128-128 128h-597.335c-70.692 0-128-57.306-128-128v-298.666zM213.334 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.347 28.654 64 64 64h597.335c35.344 0 64-28.653 64-64v-298.666c0-35.347-28.656-64-64-64h-597.335z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["desktop"],"defaultCode":59720,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":992,"name":"desktop","prevSize":32,"id":80,"code":59720},"setIdx":2,"setId":2,"iconIdx":80},{"icon":{"paths":["M325.837 160c0-17.673-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.327-32.042 32v64c0 17.673 14.346 32 32.042 32h64.085c17.696 0 32.043-14.327 32.043-32v-64zM325.837 586.666c0-17.674-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.085c17.696 0 32.043-14.326 32.043-32v-64zM454.006 160c0-17.673 14.346-32 32.042-32h64.083c17.696 0 32.042 14.327 32.042 32v64c0 17.673-14.346 32-32.042 32h-64.083c-17.696 0-32.042-14.327-32.042-32v-64zM582.173 373.334c0-17.674-14.346-32-32.042-32h-64.083c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM454.006 586.666c0-17.674 14.346-32 32.042-32h64.083c17.696 0 32.042 14.326 32.042 32v64c0 17.674-14.346 32-32.042 32h-64.083c-17.696 0-32.042-14.326-32.042-32v-64zM582.173 800c0-17.674-14.346-32-32.042-32h-64.083c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM710.342 160c0-17.673 14.346-32 32.045-32h64.083c17.696 0 32.042 14.327 32.042 32v64c0 17.673-14.346 32-32.042 32h-64.083c-17.699 0-32.045-14.327-32.045-32v-64zM838.512 373.334c0-17.674-14.346-32-32.042-32h-64.083c-17.699 0-32.045 14.326-32.045 32v64c0 17.674 14.346 32 32.045 32h64.083c17.696 0 32.042-14.326 32.042-32v-64zM710.342 586.666c0-17.674 14.346-32 32.045-32h64.083c17.696 0 32.042 14.326 32.042 32v64c0 17.674-14.346 32-32.042 32h-64.083c-17.699 0-32.045-14.326-32.045-32v-64zM325.837 373.334c0-17.674-14.347-32-32.043-32h-64.085c-17.696 0-32.042 14.326-32.042 32v64c0 17.674 14.346 32 32.042 32h64.085c17.696 0 32.043-14.326 32.043-32v-64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["dialpad"],"defaultCode":59721,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":993,"name":"dialpad","prevSize":32,"id":81,"code":59721},"setIdx":2,"setId":2,"iconIdx":81},{"icon":{"paths":["M478.65 672c-17.674 0-32-14.326-32-32v-32h-32c-17.674 0-32-14.326-32-32s14.326-32 32-32h32v-58.88h-32c-17.674 0-32-14.326-32-32s14.326-32 32-32h32v-37.12c0-17.674 14.326-32 32-32 17.67 0 32 14.326 32 32v37.12h58.88v-37.12c0-17.674 14.326-32 32-32s32 14.326 32 32v37.12h37.12c17.67 0 32 14.326 32 32s-14.33 32-32 32h-37.12v58.88h37.12c17.67 0 32 14.326 32 32s-14.33 32-32 32h-37.12v32c0 17.674-14.326 32-32 32s-32-14.326-32-32v-32h-58.88v32c0 17.674-14.33 32-32 32zM510.65 544h58.88v-58.88h-58.88v58.88z","M158.648 672h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-192h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-160c0-35.346 28.654-64 64-64h608.001c35.344 0 64 28.654 64 64v640c0 35.347-28.656 64-64 64h-608.001c-35.346 0-64-28.653-64-64v-160zM830.65 192h-608.001v160h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v192h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v160h608.001v-640z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["directory"],"defaultCode":59648,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":994,"id":82,"name":"directory","prevSize":32,"code":59648},"setIdx":2,"setId":2,"iconIdx":82},{"icon":{"paths":["M833.35 128c10.285 0 20 2.425 28.611 6.735-11.834 4.684-22.922 11.812-32.493 21.383l-35.882 35.882h-568.236v160h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v192h32c17.673 0 32 14.326 32 32s-14.327 32-32 32h-32v88.237l-64 64v-152.237h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-192h-32c-17.673 0-32-14.326-32-32s14.327-32 32-32h32v-160c0-35.346 28.654-64 64-64h607.999z","M361.117 896l64-64h408.234v-408.237l64-64v472.237c0 35.347-28.653 64-64 64h-472.234z","M604.23 352c8.166 0 15.616 3.056 21.267 8.090l-53.267 53.267v-29.357c0-17.674 14.33-32 32-32z","M513.35 421.12h51.117l-115.117 115.117v-51.117h-32c-17.67 0-32-14.326-32-32s14.33-32 32-32h32v-37.12c0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32v37.12z","M391.174 594.413l50.413-50.413h-24.237c-17.67 0-32 14.326-32 32 0 6.854 2.157 13.203 5.824 18.413z","M919.978 201.372c-12.496-12.497-32.755-12.497-45.254 0l-671.999 672c-12.497 12.496-12.497 32.758 0 45.254s32.758 12.496 45.255 0l671.999-672c12.499-12.497 12.499-32.758 0-45.255z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["directory-disabled"],"defaultCode":59649,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":995,"id":83,"name":"directory-disabled","prevSize":32,"code":59649},"setIdx":2,"setId":2,"iconIdx":83},{"icon":{"paths":["M919.978 105.372c12.499 12.497 12.499 32.758 0 45.255l-89.373 89.372 89.373 89.373c12.499 12.496 12.499 32.758 0 45.254-12.496 12.496-32.755 12.496-45.254 0l-89.373-89.372-89.373 89.372c-12.496 12.496-32.755 12.496-45.254 0-12.496-12.496-12.496-32.758 0-45.254l89.373-89.373-89.373-89.372c-12.496-12.497-12.496-32.758 0-45.255 12.499-12.497 32.758-12.497 45.254 0l89.373 89.373 89.373-89.373c12.499-12.497 32.758-12.497 45.254 0z","M512.419 126.678c1.491 17.61-11.578 33.094-29.187 34.585-180.289 15.259-321.88 166.478-321.88 350.731 0 194.406 157.596 352 351.999 352 194.406 0 352-157.594 352-352 0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32 0 229.75-186.25 416-416 416s-415.999-186.25-415.999-416c0-217.79 167.341-396.462 380.482-414.503 17.61-1.491 33.094 11.577 34.586 29.187z","M119.219 432.47c0-17.674 14.327-32 32-32h329.037c17.67 0 32 14.326 32 32 0 17.67-14.33 32-32 32h-329.037c-17.673 0-32-14.33-32-32z","M119.233 640c0-17.674 14.327-32 32-32h724.255c17.674 0 32 14.326 32 32s-14.326 32-32 32h-724.255c-17.673 0-32-14.326-32-32z","M504.81 121.090c11.117 13.739 8.992 33.888-4.749 45.005-8.666 7.012-18.886 20.139-29.238 40.961-10.179 20.471-19.61 46.603-27.635 77.587-16.042 61.955-25.837 140.879-25.837 227.356 0 103.555 14.038 195.981 35.85 261.411 10.96 32.88 23.306 57.181 35.462 72.605 12.438 15.786 21.024 17.978 24.688 17.978 3.667 0 12.253-2.192 24.691-17.978 12.157-15.424 24.502-39.725 35.462-72.605 21.808-65.43 35.846-157.856 35.846-261.411 0-17.674 14.33-32 32-32 17.674 0 32 14.326 32 32 0 108.522-14.614 208.096-39.133 281.648-12.202 36.608-27.437 68.544-45.91 91.984-18.186 23.078-43.274 42.362-74.957 42.362-31.68 0-56.768-19.283-74.957-42.362-18.47-23.44-33.706-55.376-45.91-91.984-24.515-73.552-39.133-173.126-39.133-281.648 0-90.915 10.256-175.338 27.882-243.4 8.81-34.025 19.619-64.572 32.282-90.038 12.49-25.115 27.712-47.185 46.288-62.217 13.741-11.117 33.888-8.992 45.008 4.746z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["directory-error"],"defaultCode":59650,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":996,"id":84,"name":"directory-error","prevSize":32,"code":59650},"setIdx":2,"setId":2,"iconIdx":84},{"icon":{"paths":["M561.667 127.992c-121.696 0-200.973 50.509-248.813 115.801-46.216 63.073-61.638 137.752-61.933 188.616-8.705 98.746 28.601 172.896 89.422 223.469 59.686 49.626 140.202 75.258 217.85 83.738 77.75 8.486 161.715 1.197 227.856-12.547 33.066-6.87 62.774-15.581 85.642-25.331 11.366-4.848 22.029-10.368 30.797-16.669 7.875-5.661 18.541-14.976 23.242-28.835 7.286-21.475-3.133-38.784-11.965-48.102-8.41-8.877-19.427-15.405-28.24-20.016-9.306-4.867-19.379-9.206-27.533-12.707-8.973-3.856-14.858-6.4-18.56-8.432-4.845-2.662-8.842-5.088-12.026-7.203 20.256-47.142 31.549-77.043 37.696-99.19 7.293-26.272 7.315-41.725 7.315-58.909 0-21.523-9.603-88.542-52.81-151.108-44.701-64.73-124.074-122.573-257.939-122.573zM314.916 433.898c0-40.416 12.607-101.84 49.564-152.277 35.782-48.836 95.882-89.628 197.187-89.628 112.086 0 172.090 46.886 205.277 94.94 34.678 50.219 41.472 104.040 41.472 114.741v0.198c0 14.918 0 23.638-4.982 41.594-5.491 19.779-16.963 50.189-41.539 106.538-5.802 13.296-2.762 25.77 1.155 33.754 3.664 7.478 9.005 13.242 13.331 17.261 8.835 8.211 20.653 15.686 32.224 22.045 6.618 3.638 15.238 7.334 22.563 10.477l1.562 0.672c5.904 2.534 11.52 4.97 16.688 7.418-0.909 0.406-1.856 0.819-2.835 1.238-17.741 7.568-43.078 15.206-73.555 21.539-60.947 12.666-138.064 19.21-207.888 11.587-69.926-7.635-136.982-30.336-183.878-69.328-45.459-37.798-73.674-92.064-66.481-169.821l0.136-1.469v-1.478zM819.162 553.354l-0.074-0.086c0 0.003 0.010 0.013 0.029 0.035 0.010 0.013 0.026 0.029 0.045 0.051z","M178.552 502.474c7.496-11.258 16.26-22.259 26.436-32.592 0.876 31.747 6.169 61.226 15.216 88.358-15.094 30.877-18.374 59.315-18.374 65.357v0.186c0 11.382 0 17.536 3.524 30.701 3.993 14.918 12.441 38.211 30.867 82.022 5.256 12.496 2.48 24.099-0.985 31.43-3.249 6.874-7.925 12.058-11.512 15.514-7.319 7.053-16.852 13.254-25.75 18.326-5.008 2.854-11.333 5.706-16.546 8.029 11.182 3.939 24.98 7.814 40.802 11.226 44.977 9.693 101.833 14.669 153.062 8.87 51.28-5.808 99.776-23.014 133.35-51.965l0.608-0.528c14.794 2.784 29.53 4.938 44.051 6.525 10.886 1.187 21.862 2.086 32.877 2.72-10.122 14.797-22.163 28.045-35.741 39.754-46.362 39.974-108.547 60.362-167.946 67.088-59.45 6.73-123.405 0.947-173.744-9.901-25.17-5.424-48.056-12.352-65.901-20.243-8.86-3.92-17.458-8.502-24.686-13.891-6.431-4.794-15.831-13.171-20.001-25.92-6.422-19.632 2.792-35.443 10.458-43.834 7.193-7.872 16.405-13.462 23.248-17.174 7.309-3.965 15.158-7.466 21.235-10.173 6.907-3.078 10.854-4.858 13.183-6.186 1.349-0.768 2.591-1.501 3.727-2.195-13.937-33.885-21.976-56.118-26.48-72.947-5.68-21.222-5.7-33.875-5.7-47.434 0-17.712 7.436-71.139 40.721-121.123zM155.337 797.248c-0.012 0 0.084 0.102 0.317 0.301-0.19-0.202-0.306-0.301-0.317-0.301zM179.587 737.085c-0.004 0-0.052 0.051-0.137 0.15l0.112-0.118c0.019-0.022 0.027-0.032 0.025-0.032z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["discussions"],"defaultCode":59722,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":997,"name":"discussions","prevSize":32,"id":85,"code":59722},"setIdx":2,"setId":2,"iconIdx":85},{"icon":{"paths":["M160 256c0-17.673 14.327-32 32-32h640c17.674 0 32 14.327 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.327-32-32zM160 421.162c0-17.674 14.327-32 32-32h640c17.674 0 32 14.326 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.326-32-32zM160 602.838c0-17.674 14.327-32 32-32h640c17.674 0 32 14.326 32 32s-14.326 32-32 32h-640c-17.673 0-32-14.326-32-32zM160 768c0-17.674 14.327-32 32-32h344.614c17.674 0 32 14.326 32 32s-14.326 32-32 32h-344.614c-17.673 0-32-14.326-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["document"],"defaultCode":59723,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":998,"name":"document","prevSize":32,"id":86,"code":59723},"setIdx":2,"setId":2,"iconIdx":86},{"icon":{"paths":["M128.169 352c0-17.674 14.346-32 32.042-32h704.928c17.696 0 32.045 14.326 32.045 32s-14.349 32-32.045 32h-704.928c-17.696 0-32.042-14.326-32.042-32zM213.615 522.669c0-17.674 14.346-32 32.042-32h534.036c17.699 0 32.045 14.326 32.045 32s-14.346 32-32.045 32h-534.036c-17.697 0-32.042-14.326-32.042-32zM331.104 661.331c-17.698 0-32.043 14.326-32.043 32s14.346 32 32.043 32h363.146c17.696 0 32.042-14.326 32.042-32s-14.346-32-32.042-32h-363.146z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["donner"],"defaultCode":59724,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":999,"name":"donner","prevSize":32,"id":87,"code":59724},"setIdx":2,"setId":2,"iconIdx":87},{"icon":{"paths":["M273.128 356.678c-6.62 27.766-2.384 63.757 25.498 105.581l21.374 32.061v17.69h-48c-44.011 0-70.483 14.874-86.278 33.619-16.496 19.578-24.573 47.264-23.734 77.491 0.841 30.262 10.601 59.968 25.818 81.312 15.127 21.216 33.404 31.578 52.195 31.578h79.999v64h-80c-45.209 0-80.932-25.642-104.306-58.426-23.283-32.656-36.522-74.95-37.682-116.688-1.16-41.773 9.763-86.083 38.766-120.506 20.726-24.598 49.155-42.32 84.825-50.784-16.1-39.011-19.009-77.050-10.731-111.77 11.253-47.2 42.304-84.492 80.791-107.342 38.4-22.798 85.677-32.139 131.303-21.965 35.584 7.935 68.909 27.48 95.251 59.554 53.75-35.147 127.584-30.892 182.483-2.495 34.438 17.812 64.794 46.382 81.437 85.010 12.294 28.531 16.438 61.011 10.608 96.205 46.112 6.682 81.507 25.155 105.613 53.456 30.349 35.626 38.106 81.35 33.446 123.283-4.659 41.917-21.946 83.485-46.544 115.114-24.061 30.934-59.354 57.354-101.261 57.354h-80v-64h80c14.093 0 32.8-9.581 50.742-32.646 17.398-22.371 30.112-52.806 33.453-82.89 3.341-30.067-2.902-56.339-18.554-74.714-15.222-17.869-44.035-33.75-97.642-33.75h-45.686l15.613-42.938c13.546-37.251 11.091-66.742 1.437-89.149-9.856-22.87-28.502-41.302-52.064-53.488-49.587-25.649-107.475-18.625-134.717 14.064l-30.134 36.16-22.541-41.325c-19.757-36.219-47.232-54.175-74.87-60.339-28.378-6.327-59.098-0.669-84.701 14.53-25.512 15.148-44.461 38.855-51.208 67.152zM630.979 787.222c12.298-12.691 11.981-32.95-0.707-45.251-12.691-12.298-32.95-11.981-45.251 0.707l-41.021 42.326v-273.005c0-17.674-14.326-32-32-32s-32 14.326-32 32v273.005l-41.021-42.326c-12.301-12.688-32.56-13.005-45.251-0.707-12.688 12.301-13.005 32.56-0.707 45.251l96 99.050c6.029 6.218 14.32 9.728 22.979 9.728s16.95-3.51 22.979-9.728l96-99.050z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["download"],"defaultCode":59725,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1000,"name":"download","prevSize":32,"id":88,"code":59725},"setIdx":2,"setId":2,"iconIdx":88},{"icon":{"paths":["M795.648 132.004c-25.027-25.027-65.603-25.027-90.63-0l-530.467 530.469c-9.577 9.574-15.873 21.939-17.985 35.318l-19.611 124.186c-1.386 8.771-0.942 17.299 1.006 25.261 7.597 31.037 38.083 53.44 72.291 48.038l124.184-19.613c13.379-2.112 25.744-8.41 35.322-17.984l530.467-530.47c12.512-12.513 18.768-28.914 18.768-45.316 0-10.379-2.506-20.757-7.517-30.15-2.906-5.451-6.656-10.57-11.251-15.164l-104.576-104.575zM630.675 296.979l119.658-119.658 104.576 104.574-119.658 119.657-104.576-104.573zM200.255 831.974l19.611-124.186 365.494-365.494 104.576 104.573-365.494 365.494-124.187 19.613z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["edit"],"defaultCode":59726,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1001,"name":"edit","prevSize":32,"id":89,"code":59726},"setIdx":2,"setId":2,"iconIdx":89},{"icon":{"paths":["M330.074 644.886c-21.572-19.619-6.010-52.886 23.152-52.886 8.963 0 17.526 3.53 24.272 9.437 21.603 18.918 42.64 31.958 62.701 40.509 36.563 15.59 71.805 17.107 104.794 9.939 37.632-8.176 72.659-27.808 102.109-51.341 6.726-5.376 14.995-8.544 23.606-8.544 30.218 0 45.616 34.256 22.397 53.594-36.912 30.742-82.79 57.59-134.522 68.832-44.794 9.734-93.67 7.632-143.485-13.606-28.79-12.275-57.232-30.653-85.024-55.933z","M400.17 480c35.344 0 64-28.653 64-64s-28.656-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64z","M624.17 480c35.344 0 64-28.653 64-64s-28.656-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64z","M928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["emoji"],"defaultCode":59729,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1002,"name":"emoji","prevSize":32,"id":90,"code":59729},"setIdx":2,"setId":2,"iconIdx":90},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM400.166 480c-35.347 0-64-28.653-64-64s28.653-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64zM688.166 416c0-35.347-28.653-64-64-64s-64 28.653-64 64c0 35.347 28.653 64 64 64s64-28.653 64-64zM353.226 720c8.963 0 17.526-3.53 24.272-9.437 21.603-18.918 42.64-31.958 62.701-40.509 36.563-15.59 71.805-17.107 104.794-9.939 37.632 8.176 72.659 27.808 102.109 51.341 6.726 5.376 14.995 8.544 23.606 8.544 30.218 0 45.616-34.256 22.397-53.594-36.912-30.742-82.79-57.59-134.522-68.832-44.794-9.734-93.67-7.632-143.485 13.606-28.79 12.275-57.232 30.653-85.024 55.933-21.572 19.619-6.010 52.886 23.152 52.886z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["emoji-bad-mood"],"defaultCode":59727,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1003,"name":"emoji-bad-mood","prevSize":32,"id":91,"code":59727},"setIdx":2,"setId":2,"iconIdx":91},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM400.166 480c-35.347 0-64-28.653-64-64s28.653-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64zM688.166 416c0-35.347-28.653-64-64-64s-64 28.653-64 64c0 35.347 28.653 64 64 64s64-28.653 64-64zM384 640h256c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32s14.326-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["emoji-neutral-mood"],"defaultCode":59728,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1004,"name":"emoji-neutral-mood","prevSize":32,"id":92,"code":59728},"setIdx":2,"setId":2,"iconIdx":92},{"icon":{"paths":["M655.744 512c88.365 0 160-71.635 160-160s-71.635-160-160-160c-88.368 0-160 71.635-160 160 0 26.934 6.653 52.314 18.41 74.582l-11.914 11.914 0.128 0.131-299.135 299.136c-3.533 9.926-6.41 20.976-7.738 31.606-1.652 13.219-0.563 22.966 1.874 28.938 1.768 4.333 4.22 7.232 10.772 9.014 8.316 2.262 24.518 2.794 52.822-5.501 8.524-3.808 27.721-16.285 45.132-35.382 18.18-19.939 29.648-41.856 29.648-62.438 0-15.642 11.309-28.992 26.736-31.565l91.75-15.293c3.766-2.656 18.768-15.693 10.134-58.867-2.099-10.49 1.184-21.338 8.749-28.902l88.198-88.195c26.467 19.379 59.114 30.822 94.432 30.822zM439.571 410.915c-5.104-18.771-7.827-38.525-7.827-58.915 0-123.712 100.288-224 224-224 123.709 0 224 100.288 224 224s-100.291 224-224 224c-29.29 0-57.264-5.619-82.906-15.843l-43.008 43.008c7.158 65.494-23.99 104.534-55.968 115.194l-2.384 0.794-74.854 12.477c-7.085 31.405-25.174 58.122-43.235 77.933-23.123 25.357-50.958 44.627-69.762 52.15l-1.324 0.528-1.365 0.41c-34.714 10.416-64.73 13.19-89.594 6.429-26.782-7.286-44.33-24.784-53.228-46.586-8.23-20.163-8.473-42.282-6.126-61.062 2.402-19.216 7.899-37.958 14.042-53.315 1.61-4.022 4.020-7.677 7.084-10.742l286.456-286.458zM623.744 336c0 26.509 21.488 48 48 48 26.509 0 48-21.491 48-48s-21.491-48-48-48c-26.512 0-48 21.49-48 48z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["encrypted"],"defaultCode":59730,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1005,"name":"encrypted","prevSize":32,"id":93,"code":59730},"setIdx":2,"setId":2,"iconIdx":93},{"icon":{"paths":["M536.89 64c233.677 0 423.11 189.433 423.11 423.11h-423.11v-423.11z","M64 536.89c0-233.678 189.433-423.112 423.11-423.112v423.112h423.11c0 233.677-189.43 423.11-423.11 423.11-233.677 0-423.11-189.434-423.11-423.11z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["engagement-dashboard"],"defaultCode":59731,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1006,"name":"engagement-dashboard","prevSize":32,"id":94,"code":59731},"setIdx":2,"setId":2,"iconIdx":94},{"icon":{"paths":["M416 586.445v177.232l75.514-62.928c11.869-9.888 29.104-9.888 40.973 0l75.514 62.928v-177.232c-29.098 13.821-61.645 21.555-96 21.555s-66.902-7.734-96-21.555zM352 540.768v291.232c0 12.416 7.184 23.712 18.426 28.979 11.245 5.267 24.522 3.552 34.061-4.397l107.514-89.594 107.514 89.594c9.539 7.949 22.816 9.664 34.061 4.397 11.242-5.267 18.426-16.563 18.426-28.979v-291.232c39.59-40.403 64-95.734 64-156.768 0-123.712-100.288-224.001-224-224.001s-224 100.288-224 224.001c0 61.034 24.41 116.365 64 156.768zM416 512.013l-0.016-0.013c-38.854-29.19-63.984-75.661-63.984-128 0-88.366 71.635-160.001 160-160.001s160 71.635 160 160.001c0 52.339-25.13 98.81-63.984 128l-0.016 0.013c-26.742 20.083-59.981 31.987-96 31.987s-69.258-11.904-96-31.987z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["enterprise-feature"],"defaultCode":59732,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1007,"name":"enterprise-feature","prevSize":32,"id":95,"code":59732},"setIdx":2,"setId":2,"iconIdx":95},{"icon":{"paths":["M500.64 128c213.35 0 386.336 172.985 386.336 386.336 0 192.87-141.254 352.707-325.974 381.664v-269.958h90.022l17.114-111.706h-107.136v-72.47c0-11.462 2.102-22.822 7.274-32.544 2.474-4.656 5.651-8.934 9.635-12.666 9.866-9.245 24.688-15.152 46.058-15.152h48.733v-95.080c0 0-44.224-7.552-86.493-7.552-84.698 0-141.258 49.313-145.651 138.907-0.182 3.738-0.275 7.546-0.275 11.424v85.133h-98.122v111.706h98.122v269.958c-184.721-29.011-325.978-188.848-325.978-381.664 0-213.351 172.985-386.336 386.336-386.336z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["facebook-monochromatic"],"defaultCode":59733,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1008,"name":"facebook-monochromatic","prevSize":32,"id":96,"code":59733},"setIdx":2,"setId":2,"iconIdx":96},{"icon":{"paths":["M865.139 512c0 33.28-4.624 65.485-13.267 96h-183.274c2.803-30.816 4.288-62.957 4.288-96 0-16.234-0.358-32.25-1.056-48h190.061c2.141 15.696 3.248 31.718 3.248 48zM607.68 464c0.739 15.67 1.123 31.686 1.123 48 0 33.398-1.61 65.555-4.57 96h-183.117c-2.963-30.445-4.57-62.602-4.57-96 0-16.314 0.384-32.33 1.123-48h190.010zM667.014 400c-10.016-93.226-32.221-173.252-61.875-227.763 113.702 30.788 204.579 116.981 241.782 227.763h-179.907zM420.211 172.237c-29.654 54.51-51.862 134.537-61.875 227.763h-179.91c37.204-110.782 128.083-196.975 241.785-227.763zM422.816 400c7.171-62.314 20.064-116.804 36.384-159.18 12.842-33.339 26.56-55.927 38.528-69.070 8.406-9.235 13.446-11.291 14.947-11.698 1.501 0.407 6.541 2.463 14.947 11.698 11.968 13.143 25.686 35.731 38.525 69.070 16.32 42.377 29.216 96.867 36.387 159.18h-179.718zM353.52 464c-0.698 15.75-1.056 31.766-1.056 48 0 33.043 1.482 65.184 4.288 96h-183.275c-8.643-30.515-13.268-62.72-13.268-96 0-16.282 1.107-32.304 3.249-48h190.061zM364.742 672c11.667 72.646 31.040 134.861 55.466 179.763-96.678-26.179-176.854-92.413-221.565-179.763h166.1zM513.152 928c229.834-0.259 416.070-186.41 416.070-416 0-229.75-186.493-416-416.547-416s-416.55 186.25-416.55 416c0 229.59 186.237 415.741 416.070 416 0.16 0 0.32 0 0.48 0s0.32 0 0.477 0zM605.142 851.763c24.426-44.902 43.798-107.117 55.466-179.763h166.099c-44.71 87.35-124.89 153.584-221.565 179.763zM595.638 672c-7.379 42.458-17.514 80.083-29.491 111.184-12.838 33.338-26.557 55.926-38.525 69.069-8.406 9.235-13.446 11.29-14.947 11.699-1.501-0.41-6.541-2.464-14.947-11.699-11.968-13.142-25.686-35.731-38.528-69.069-11.978-31.101-22.109-68.726-29.488-111.184h165.926z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["federation"],"defaultCode":59652,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1009,"id":97,"name":"federation","prevSize":32,"code":59652},"setIdx":2,"setId":2,"iconIdx":97},{"icon":{"paths":["M542.65 96c80.093 0 154.902 22.636 218.374 61.859l-46.746 46.746c-24.739-13.843-51.322-24.785-79.286-32.368 12.166 22.395 23.078 49.095 32.406 79.249l-52 51.999c-5.654-22.994-12.17-44.005-19.347-62.666-12.822-33.339-26.522-55.927-38.474-69.070-8.397-9.235-13.43-11.291-14.928-11.698-1.498 0.407-6.531 2.463-14.928 11.698-11.952 13.143-25.654 35.731-38.477 69.070-16.298 42.377-29.174 96.867-36.336 159.18h65.974l-64 64h-7.114c-0.118 2.47-0.224 4.95-0.323 7.437l-64.538 64.538c-0.173-7.933-0.259-15.926-0.259-23.974 0-16.234 0.358-32.25 1.053-48h-189.809c-2.14 15.696-3.245 31.718-3.245 48 0 33.28 4.619 65.485 13.251 96h106.984l-64 64h-17.852c2.004 3.92 4.078 7.798 6.223 11.629l-46.746 46.749c-39.223-63.475-61.859-138.282-61.859-218.378 0-229.75 186.25-416 416.001-416zM896.79 293.623l-46.746 46.748c10.56 18.87 19.43 38.816 26.413 59.629h-86.045l-64 64h164.992c2.138 15.696 3.245 31.718 3.245 48 0 33.28-4.621 65.485-13.251 96h-183.030c2.8-30.816 4.282-62.957 4.282-96 0-8.045-0.090-16.042-0.262-23.974l-64.534 64.534c-0.752 19.008-2.026 37.523-3.766 55.44h-51.674l-64 64h107.088c-7.37 42.458-17.488 80.083-29.45 111.184-12.822 33.338-26.522 55.926-38.474 69.069-8.397 9.235-13.43 11.29-14.928 11.699-1.498-0.41-6.531-2.464-14.928-11.699-11.952-13.142-25.654-35.731-38.477-69.069-7.178-18.662-13.69-39.677-19.344-62.669l-52 51.997c9.325 30.154 20.237 56.854 32.403 79.251-27.965-7.584-54.547-18.525-79.286-32.368l-46.746 46.746c63.347 39.146 137.984 61.77 217.901 61.859h0.954c229.53-0.259 415.523-186.41 415.523-416 0-80.096-22.637-154.902-61.859-218.377zM450.307 172.237c-113.552 30.788-204.312 116.98-241.467 227.763h179.675c10-93.226 32.176-173.252 61.792-227.763zM634.995 851.763c24.394-44.902 43.741-107.117 55.392-179.763h165.878c-44.653 87.35-124.723 153.584-221.27 179.763zM856.022 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672.001 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672.001-672z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["federation-disabled"],"defaultCode":59651,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1010,"id":98,"name":"federation-disabled","prevSize":32,"code":59651},"setIdx":2,"setId":2,"iconIdx":98},{"icon":{"paths":["M373.334 448c0-17.674 14.326-32 32-32h213.331c17.674 0 32 14.326 32 32s-14.326 32-32 32h-213.331c-17.674 0-32-14.326-32-32z","M405.334 544c-17.674 0-32 14.326-32 32s14.326 32 32 32h213.331c17.674 0 32-14.326 32-32s-14.326-32-32-32h-213.331z","M256 128c-17.673 0-32 14.327-32 32v704c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-501.744c0-6.672-2.083-13.174-5.962-18.602l-144.467-202.254c-6.006-8.409-15.706-13.4-26.038-13.4h-367.533zM736 372.509v459.491h-448v-640h319.066l128.934 180.509z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["file-document"],"defaultCode":59734,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1011,"name":"file-document","prevSize":32,"id":99,"code":59734},"setIdx":2,"setId":2,"iconIdx":99},{"icon":{"paths":["M128 192c-17.673 0-32 14.327-32 32v576.019c0 17.674 14.327 32 32 32h768c17.674 0 32-14.326 32-32v-576.019c0-17.673-14.326-32-32-32h-768zM160 378.301v-122.301h149.333v122.301h-149.333zM160 442.301h149.333v141.722h-149.333v-141.722zM160 648.022h149.333v119.997h-149.333v-119.997zM373.334 768.019v-119.997h490.666v119.997h-490.666zM864 584.022h-490.666v-141.722h490.666v141.722zM864 378.301h-490.666v-122.301h490.666v122.301z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["file-sheet"],"defaultCode":59735,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1012,"name":"file-sheet","prevSize":32,"id":100,"code":59735},"setIdx":2,"setId":2,"iconIdx":100},{"icon":{"paths":["M206.667 293.692c-30.421-42.402-0.116-101.442 52.070-101.442h518.572c51.174 0 81.706 57.026 53.334 99.615l-180.678 271.207v220.762c0 46.352-47.693 77.373-90.067 58.582l-121.424-53.85c-23.168-10.275-38.102-33.238-38.102-58.582v-166.304l-193.704-269.988zM777.309 256.334h-518.572l193.705 269.989c7.811 10.89 12.013 23.955 12.013 37.357v166.304l121.424 53.85v-220.762c0-12.646 3.741-25.008 10.752-35.533l180.678-271.205z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["filter"],"defaultCode":59736,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1013,"name":"filter","prevSize":32,"id":101,"code":59736},"setIdx":2,"setId":2,"iconIdx":101},{"icon":{"paths":["M623.091 896c-2.806 0-5.296-0.624-7.168-0.938-62-16.858-102.816-39.648-145.811-80.858-55.149-54.010-85.37-125.814-85.37-202.301 0-65.875 56.704-119.571 126.496-119.571s126.496 53.696 126.496 119.571c0 34.963 31.469 63.373 69.792 63.373s69.789-28.41 69.789-63.373c0-135.808-119.642-246.637-266.701-246.637-104.998 0-200.338 57.133-243.334 145.795-14.332 29.347-21.498 63.066-21.498 100.842 0 28.72 2.492 73.363 24.925 131.744 2.804 7.181 2.492 14.675-0.623 21.856-3.116 6.867-9.035 11.862-16.201 14.358-2.804 1.251-6.231 1.562-9.659 1.562-11.84 0-22.433-7.181-26.484-18.106-19.005-50.266-28.353-99.904-28.353-151.728 0-46.205 9.036-88.352 26.795-125.504 52.343-108.019 167.936-177.638 294.432-177.638 178.528 0 323.718 135.804 323.718 302.828 0 65.875-56.704 119.571-126.806 119.571s-126.81-53.696-126.81-119.571c0-34.963-31.469-63.373-69.792-63.373-38.634 0-69.789 28.41-69.789 63.373 0 61.504 24.301 119.261 68.544 162.342 35.206 34.029 68.858 53.072 120.576 67.123 7.168 1.872 13.398 6.557 17.136 13.11 3.741 6.557 4.675 14.362 2.806 21.229-2.806 11.866-14.022 20.918-27.107 20.918zM426.803 888.195c-7.789 0-15.267-3.123-20.253-8.742-33.338-32.781-51.718-54.010-77.891-100.525-26.795-47.142-41.127-105.21-41.127-167.338 0-116.448 100.948-211.357 224.951-211.357s224.954 94.909 224.954 211.357c0 15.61-12.464 28.096-28.352 28.096-15.891 0-28.666-12.173-28.666-28.096 0-85.542-75.398-155.162-168.246-155.162s-168.246 69.619-168.246 155.162c0 52.448 11.84 100.528 34.272 139.552 23.366 41.52 38.947 59.005 68.858 88.662 10.902 11.238 10.902 28.723 0 39.648-5.92 5.933-13.088 8.742-20.253 8.742zM699.738 818.886c-47.36 0-88.797-11.862-123.382-34.963-59.197-39.651-94.717-103.962-94.717-172.333 0-15.61 12.464-28.099 28.352-28.099 15.891 0 28.355 12.49 28.355 28.099 0 49.638 26.17 96.781 69.789 125.501 25.238 16.861 55.149 24.976 91.603 24.976 7.789 0 22.432-0.934 38.010-3.744 1.558-0.314 3.427-0.314 4.986-0.314 13.709 0 25.238 9.99 27.728 23.414 1.248 7.181-0.31 14.672-4.362 20.605-4.362 6.243-10.902 10.614-18.694 11.862-23.366 4.685-43.93 4.995-47.667 4.995zM188.765 435.824c-5.608 0-11.217-1.562-16.202-4.995-6.543-4.058-10.593-10.614-12.151-18.106-1.246-7.494 0.311-14.986 4.985-21.232 38.635-53.696 87.862-95.843 146.125-125.501 60.132-30.595 129.613-46.829 200.961-46.829 71.037 0 140.205 15.922 200.029 46.205 58.573 29.659 107.802 71.492 146.125 124.567 4.362 5.93 6.23 13.424 4.986 20.915-1.248 7.494-5.61 14.048-11.84 18.419-4.986 3.437-10.595 4.995-16.515 4.995-9.034 0-17.757-4.371-23.056-11.862-33.338-45.891-75.709-82.109-125.562-107.083-52.342-26.224-112.787-40.273-174.477-40.273-62.314 0-122.758 14.049-175.101 40.585-49.852 25.913-92.537 62.128-126.186 108.643-3.739 6.87-12.463 11.552-22.121 11.552zM733.696 239.141c-4.672 0-9.347-1.249-13.395-3.434-71.35-35.902-133.354-51.512-207.504-51.512-74.467 0-144.256 17.483-207.817 51.824-4.050 2.185-8.724 3.122-13.397 3.122-10.282 0-19.629-5.62-24.925-14.361-3.739-6.556-4.673-14.361-2.492-21.541s7.166-13.424 13.709-16.859c72.594-38.712 151.733-58.38 234.924-58.38 82.563 0 154.848 17.795 233.987 58.068 6.854 3.434 11.84 9.366 14.33 16.859 2.182 7.18 1.248 14.673-2.179 21.229-4.986 9.054-14.643 14.985-25.238 14.985z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["fingerprint"],"defaultCode":59737,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1014,"name":"fingerprint","prevSize":32,"id":102,"code":59737},"setIdx":2,"setId":2,"iconIdx":102},{"icon":{"paths":["M266.667 170.664c0-17.673 14.327-32 32-32h500.623c12.122 0 23.2 6.848 28.621 17.689s4.253 23.814-3.021 33.511l-122.134 162.843 122.134 162.845c7.274 9.696 8.442 22.672 3.021 33.51-5.421 10.842-16.499 17.69-28.621 17.69h-468.624v286.579c0 17.674-14.325 32-31.999 32s-32-14.326-32-32v-682.667zM330.666 502.752h404.624l-98.134-130.845c-8.531-11.376-8.531-27.021 0-38.4l98.134-130.843h-404.624v300.088z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["flag"],"defaultCode":59738,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1015,"name":"flag","prevSize":32,"id":103,"code":59738},"setIdx":2,"setId":2,"iconIdx":103},{"icon":{"paths":["M140.020 213.336c0-17.673 14.327-32 32-32h234.057c7.181 0 14.157 2.416 19.798 6.86l88.813 69.94h339.997c17.674 0 32 14.327 32 32v520.533c0 17.674-14.326 32-32 32h-682.665c-17.673 0-32-14.326-32-32v-597.333zM204.020 245.336v533.333h618.665v-456.534h-319.085c-7.181 0-14.154-2.415-19.798-6.858l-88.813-69.94h-190.969z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["folder"],"defaultCode":59739,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1016,"name":"folder","prevSize":32,"id":104,"code":59739},"setIdx":2,"setId":2,"iconIdx":104},{"icon":{"paths":["M370.704 544c0-17.674-14.326-32-32-32s-31.999 14.326-31.999 32v32h-32c-17.673 0-32 14.326-32 32s14.327 32 32 32h32v32c0 17.674 14.325 32 31.999 32s32-14.326 32-32v-32h32c17.674 0 32-14.326 32-32s-14.326-32-32-32h-32v-32z","M746.704 624c30.928 0 56-25.072 56-56s-25.072-56-56-56c-30.928 0-56 25.072-56 56s25.072 56 56 56z","M674.704 664c0 30.928-25.072 56-56 56s-56-25.072-56-56c0-30.928 25.072-56 56-56s56 25.072 56 56z","M706.704 128c0-17.673-14.326-32-32-32s-32 14.327-32 32v96h-128c-17.674 0-32 14.327-32 32v96h-191.999c-106.038 0-192 85.962-192 192v128c0 106.038 85.961 192 192 192h447.999c106.038 0 192-85.962 192-192v-128c0-106.038-85.962-192-192-192h-192v-64h128c17.674 0 32-14.327 32-32v-128zM866.704 544v128c0 70.691-57.306 128-128 128h-447.999c-70.692 0-128-57.309-128-128v-128c0-70.691 57.308-128 128-128h447.999c70.694 0 128 57.309 128 128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["game"],"defaultCode":59753,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1017,"name":"game","prevSize":32,"id":105,"code":59753},"setIdx":2,"setId":2,"iconIdx":105},{"icon":{"paths":["M494.31 170.648l23.037 24.005 23.629-24.005 74.669 0.041v75.854h74.669v75.856h74.666v26.518h0.003v504.419h-522.678v-682.689h252.006zM540.976 246.503h-224.004v530.979h373.341v-379.229h-149.338v-151.75z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["giphy-monochromatic"],"defaultCode":59754,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1018,"name":"giphy-monochromatic","prevSize":32,"id":106,"code":59754},"setIdx":2,"setId":2,"iconIdx":106},{"icon":{"paths":["M862.454 324.045c-35.2-60.31-82.944-108.057-143.248-143.253-60.314-35.198-126.16-52.792-197.581-52.792-71.414 0-137.28 17.6-197.581 52.792-60.31 35.194-108.053 82.943-143.253 143.253-35.194 60.307-52.792 126.166-52.792 197.571 0 85.77 25.024 162.899 75.086 231.405 50.056 68.509 114.721 115.917 193.989 142.224 9.229 1.712 16.058 0.509 20.499-3.584 4.442-4.096 6.662-9.226 6.662-15.37 0-1.024-0.090-10.246-0.259-27.674-0.176-17.43-0.259-32.637-0.259-45.61l-11.789 2.038c-7.517 1.379-16.998 1.962-28.445 1.795-11.443-0.16-23.322-1.357-35.619-3.587-12.304-2.211-23.747-7.334-34.342-15.366-10.588-8.029-18.104-18.538-22.547-31.514l-5.125-11.795c-3.416-7.853-8.795-16.573-16.142-26.134-7.348-9.571-14.778-16.058-22.294-19.475l-3.588-2.57c-2.391-1.706-4.61-3.766-6.662-6.154-2.050-2.39-3.585-4.781-4.61-7.174-1.027-2.397-0.176-4.365 2.562-5.907 2.738-1.539 7.685-2.288 14.864-2.288l10.247 1.53c6.834 1.37 15.287 5.462 25.371 12.298 10.078 6.835 18.363 15.715 24.856 26.646 7.863 14.013 17.335 24.688 28.445 32.038 11.101 7.347 22.294 11.014 33.568 11.014s21.011-0.854 29.216-2.557c8.192-1.709 15.882-4.275 23.062-7.69 3.075-22.902 11.446-40.499 25.11-52.797-19.475-2.045-36.982-5.13-52.534-9.226-15.542-4.106-31.603-10.765-48.173-20-16.579-9.222-30.331-20.672-41.262-34.333-10.932-13.67-19.905-31.613-26.904-53.818-7.003-22.214-10.505-47.837-10.505-76.88 0-41.35 13.5-76.541 40.493-105.584-12.645-31.088-11.451-65.939 3.585-104.55 9.908-3.079 24.606-0.768 44.078 6.916 19.478 7.689 33.738 14.275 42.797 19.736 9.059 5.46 16.317 10.087 21.786 13.837 31.782-8.88 64.582-13.322 98.406-13.322s66.63 4.442 98.416 13.322l19.475-12.295c13.318-8.204 29.046-15.722 47.142-22.556 18.112-6.83 31.958-8.712 41.53-5.633 15.37 38.612 16.739 73.46 4.093 104.548 26.992 29.046 40.496 64.243 40.496 105.587 0 29.043-3.514 54.746-10.506 77.13-7.002 22.387-16.051 40.314-27.152 53.818-11.114 13.501-24.957 24.864-41.526 34.083-16.573 9.226-32.637 15.888-48.179 19.99-15.552 4.102-33.059 7.187-52.534 9.238 17.763 15.37 26.646 39.632 26.646 72.774v108.134c0 6.141 2.134 11.27 6.41 15.37 4.272 4.090 11.018 5.296 20.243 3.581 79.28-26.304 143.946-73.712 194-142.224 50.048-68.502 75.082-145.632 75.082-231.405-0.019-71.395-17.626-137.248-52.803-197.555z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["github-monochromatic"],"defaultCode":59655,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1019,"name":"github-monochromatic","prevSize":32,"id":107,"code":59655},"setIdx":2,"setId":2,"iconIdx":107},{"icon":{"paths":["M133.618 423.61h215.092l-92.537-284.607c-4.74-14.67-25.504-14.67-30.244 0l-92.311 284.607zM86.899 567.171l46.72-143.546h737.133l46.72 143.546c4.288 13.088-0.451 27.533-11.51 35.434l-403.776 293.408-403.776-293.408c-11.060-7.901-15.799-22.346-11.511-35.434zM655.661 423.61h215.091l-92.31-284.607c-4.739-14.67-25.504-14.67-30.243 0l-92.538 284.607z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["gitlab-monochromatic"],"defaultCode":59656,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1020,"name":"gitlab-monochromatic","prevSize":32,"id":108,"code":59656},"setIdx":2,"setId":2,"iconIdx":108},{"icon":{"paths":["M226.9 260.289c6.691-2.875 13.811-4.319 20.961-4.288 17.673 0.077 32.062-14.187 32.14-31.86s-14.187-32.062-31.86-32.14c-15.989-0.070-31.8 3.167-46.506 9.485-14.702 6.317-27.969 15.571-39.071 27.156-11.1 11.582-19.822 25.269-25.729 40.238-5.898 14.946-8.889 30.916-8.834 47.005l-0.001 15.941 0.001-11.899v255.848c-0 0.074-0.001 0.15-0.001 0.224v89.6c0 43.642 16.497 85.792 46.318 117.104 29.872 31.366 70.73 49.296 113.682 49.296 42.954 0 83.811-17.93 113.683-49.296 29.821-31.312 46.317-73.462 46.317-117.104v-57.6h128v57.6c0 43.642 16.496 85.792 46.317 117.104 29.872 31.366 70.73 49.296 113.683 49.296s83.811-17.93 113.683-49.296c29.821-31.312 46.317-73.462 46.317-117.104v-89.6c0-0.077 0-0.15 0-0.227v-259.883c0.054-16.090-2.938-32.062-8.835-47.010-5.907-14.969-14.627-28.656-25.728-40.238-11.104-11.585-24.368-20.839-39.072-27.156-14.704-6.318-30.515-9.555-46.506-9.485-17.674 0.077-31.936 14.467-31.859 32.14s14.467 31.937 32.141 31.86c7.149-0.031 14.269 1.413 20.96 4.288 6.694 2.876 12.867 7.147 18.128 12.636 5.264 5.492 9.501 12.090 12.403 19.448 2.906 7.36 4.4 15.292 4.368 23.326v228.302h-639.999l0-228.173-0-0.128c-0.032-8.034 1.462-15.965 4.366-23.326 2.904-7.358 7.141-13.957 12.404-19.448 5.26-5.489 11.434-9.759 18.129-12.636zM269.255 608l104.214 104.214c6.826-14.237 10.531-30.173 10.531-46.614v-57.6h-114.745zM717.254 608l104.214 104.214c6.826-14.237 10.531-30.173 10.531-46.614v-57.6h-114.746zM896 315.89v0zM128.001 319.928l0-3.973-0-0.069v4.043zM328.954 758.208l-136.954-136.954v44.346c0 27.648 10.475 53.869 28.663 72.966 18.137 19.043 42.394 29.434 67.337 29.434 14.208 0 28.194-3.37 40.954-9.792zM640 665.6v-44.346l136.954 136.954c-12.758 6.422-26.746 9.792-40.954 9.792-24.944 0-49.2-10.39-67.338-29.434-18.189-19.098-28.662-45.318-28.662-72.966z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["glasses"],"defaultCode":59812,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1021,"id":109,"name":"glasses","prevSize":32,"code":59812},"setIdx":2,"setId":2,"iconIdx":109},{"icon":{"paths":["M634.803 170.664h-256.112l-264.387 460.802 124.984 221.866h534.916l124.982-221.866-264.384-460.802zM367.814 631.466l138.931-239.789 138.934 239.789h-277.866z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["google-drive-monochromatic"],"defaultCode":59756,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1022,"name":"google-drive-monochromatic","prevSize":32,"id":110,"code":59756},"setIdx":2,"setId":2,"iconIdx":110},{"icon":{"paths":["M658.794 338.154c-39.798-38.052-90.416-57.426-146.794-57.426-100.016 0-184.669 67.548-214.865 158.313l-0.002-0.003c-7.679 23.040-12.042 47.648-12.042 72.957s4.364 49.92 12.044 72.96l0 0.003c30.196 90.765 114.849 158.314 214.865 158.314 51.664 0 95.651-13.613 130.035-36.653v-0.016c40.669-27.229 67.725-67.898 76.627-115.898h-206.662v-148.538h361.658c4.538 25.136 6.982 51.315 6.982 78.547 0 116.944-41.891 215.389-114.502 282.24v0.013c-63.533 58.646-150.458 93.030-254.138 93.030-150.109 0-279.971-86.048-343.156-211.549l-0-0.003c-26.007-51.84-40.844-110.49-40.844-172.451 0-61.965 14.836-120.611 40.844-172.451h0.004c63.187-125.495 193.047-211.542 343.153-211.542 103.504 0 190.429 38.051 256.931 100.014l-110.138 110.139z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["google-monochromatic"],"defaultCode":59657,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1023,"name":"google-monochromatic","prevSize":32,"id":111,"code":59657},"setIdx":2,"setId":2,"iconIdx":111},{"icon":{"paths":["M129.354 272c0-17.673 14.327-32 32-32h704c17.674 0 32 14.327 32 32s-14.326 32-32 32h-704c-17.673 0-32-14.327-32-32zM289.354 432c0 17.674-14.327 32-32 32s-32-14.326-32-32c0-17.674 14.327-32 32-32s32 14.326 32 32zM289.354 752c0 17.674-14.327 32-32 32s-32-14.326-32-32c0-17.674 14.327-32 32-32s32 14.326 32 32zM449.354 624c17.674 0 32-14.326 32-32s-14.326-32-32-32c-17.674 0-32 14.326-32 32s14.326 32 32 32zM385.354 400c-17.674 0-32 14.326-32 32s14.326 32 32 32h480c17.674 0 32-14.326 32-32s-14.326-32-32-32h-480zM353.354 752c0-17.674 14.326-32 32-32h480c17.674 0 32 14.326 32 32s-14.326 32-32 32h-480c-17.674 0-32-14.326-32-32zM577.354 560c-17.674 0-32 14.326-32 32s14.326 32 32 32h288c17.674 0 32-14.326 32-32s-14.326-32-32-32h-288z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["group-by-type"],"defaultCode":59757,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1024,"name":"group-by-type","prevSize":32,"id":112,"code":59757},"setIdx":2,"setId":2,"iconIdx":112},{"icon":{"paths":["M170.668 245.336c0-17.673 14.327-32 32-32h640.846c17.674 0 32 14.327 32 32s-14.326 32-32 32h-640.846c-17.673 0-32-14.327-32-32zM170.668 501.334c0-17.67 14.327-32 32-32h640.846c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-640.846c-17.673 0-32-14.326-32-32zM170.668 757.334c0-17.67 14.327-32 32-32h640.846c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32h-640.846c-17.673 0-32-14.326-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["hamburguer"],"defaultCode":59758,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1025,"name":"hamburguer","prevSize":32,"id":113,"code":59758},"setIdx":2,"setId":2,"iconIdx":113},{"icon":{"paths":["M832 512c0 176.73-143.27 320-320 320s-320-143.27-320-320h-64c0 212.077 171.923 384 384 384s384-171.923 384-384c0-212.077-171.923-384-384-384-123.718 0-233.772 58.508-304 149.364v-101.364c0-17.673-14.327-32-32-32s-32 14.327-32 32v192c0 17.674 14.327 32 32 32h176c17.674 0 32-14.326 32-32s-14.326-32-32-32h-107.295c57.24-86.756 155.583-144 267.295-144 176.73 0 320 143.27 320 320z","M544 320c0-17.673-14.326-32-32-32s-32 14.327-32 32v224c0 8.486 3.373 16.627 9.373 22.627l96 96c12.496 12.496 32.758 12.496 45.254 0s12.496-32.758 0-45.254l-86.627-86.627v-210.746z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["history"],"defaultCode":59759,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1026,"name":"history","prevSize":32,"id":114,"code":59759},"setIdx":2,"setId":2,"iconIdx":114},{"icon":{"paths":["M522.042 195.354l224.464 260.044v366.234c0 5.856-4.752 10.605-10.614 10.605h-136.416v-149.821c0-23.424-19.014-42.413-42.47-42.413h-85.955c-23.453 0-42.467 18.989-42.467 42.413v149.821h-136.41c-5.864 0-10.617-4.749-10.617-10.605v-366.307l224.403-259.971c4.237-4.907 11.85-4.907 16.083 0zM560.57 895.856h175.322c41.043 0 74.32-33.232 74.32-74.224v-244.205h56.227c12.454 0 23.766-7.251 28.954-18.557 5.19-11.309 3.302-24.602-4.829-34.022l-320.272-371.033c-29.648-34.347-82.934-34.347-112.582 0l-320.27 371.033c-8.132 9.421-10.020 22.714-4.831 34.022 5.188 11.306 16.501 18.557 28.956 18.557h56.288v244.205c0 40.992 33.274 74.224 74.32 74.224h175.316c1.174 0.096 2.362 0.147 3.562 0.147h85.955c1.2 0 2.39-0.051 3.565-0.147z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["home"],"defaultCode":59760,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1027,"name":"home","prevSize":32,"id":115,"code":59760},"setIdx":2,"setId":2,"iconIdx":115},{"icon":{"paths":["M864 512c0-86.89-31.482-166.429-83.664-227.826l-496.162 496.162c61.397 52.182 140.937 83.664 227.826 83.664 194.403 0 352-157.597 352-352zM239.349 734.65l495.3-495.3c-60.662-49.597-138.182-79.349-222.65-79.349-194.404 0-352 157.596-352 352 0 84.467 29.753 161.987 79.349 222.65zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["ignore"],"defaultCode":59740,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1028,"name":"ignore","prevSize":32,"id":116,"code":59740},"setIdx":2,"setId":2,"iconIdx":116},{"icon":{"paths":["M406.685 405.334c0 47.126-38.205 85.331-85.334 85.331-47.127 0-85.332-38.205-85.332-85.331 0-47.13 38.205-85.334 85.332-85.334 47.13 0 85.334 38.205 85.334 85.334z","M97.352 192c0-17.673 14.327-32 32-32h767.999c17.674 0 32 14.327 32 32v640c0 17.674-14.326 32-32 32h-767.999c-17.673 0-32-14.326-32-32v-640zM161.352 764.163l151.704-176.989c9.271-10.813 24.57-14.202 37.536-8.307l153.123 69.603 160.474-204.24c6.010-7.651 15.174-12.15 24.902-12.23s18.963 4.272 25.098 11.821l151.162 186.048v-405.869h-703.999v540.163zM214.927 800h650.423v-68.64l-175.581-216.099-166.781 212.269-176.989-80.448-131.073 152.918z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["image"],"defaultCode":59761,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1029,"name":"image","prevSize":32,"id":117,"code":59761},"setIdx":2,"setId":2,"iconIdx":117},{"icon":{"paths":["M512 873.027c-199.389 0-361.026-161.635-361.026-361.024s161.636-361.026 361.026-361.026c199.389 0 361.024 161.637 361.024 361.026s-161.635 361.024-361.024 361.024zM512 938.669c235.642 0 426.666-191.024 426.666-426.666s-191.024-426.667-426.666-426.667c-235.642 0-426.667 191.025-426.667 426.667s191.025 426.666 426.667 426.666zM544.819 347.901c0 18.125-14.694 32.819-32.819 32.819-18.128 0-32.822-14.694-32.822-32.819 0-18.128 14.694-32.821 32.822-32.821 18.125 0 32.819 14.693 32.819 32.821zM512 413.542c-18.128 0-32.822 14.694-32.822 32.819v229.744c0 18.125 14.694 32.819 32.822 32.819 18.125 0 32.819-14.694 32.819-32.819v-229.744c0-18.125-14.694-32.819-32.819-32.819z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["info"],"defaultCode":59762,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1030,"name":"info","prevSize":32,"id":118,"code":59762},"setIdx":2,"setId":2,"iconIdx":118},{"icon":{"paths":["M512 864c-194.404 0-352-157.597-352-352s157.596-352 352-352c194.403 0 352 157.596 352 352s-157.597 352-352 352zM512 928c229.75 0 416-186.25 416-416s-186.25-416-416-416c-229.75 0-416 186.25-416 416s186.25 416 416 416zM662.627 361.373c12.496 12.496 12.496 32.758 0 45.254l-105.373 105.373 105.373 105.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-105.373-105.373-105.373 105.373c-12.496 12.496-32.758 12.496-45.254 0s-12.496-32.758 0-45.254l105.373-105.373-105.373-105.373c-12.496-12.496-12.496-32.758 0-45.254s32.758-12.496 45.254 0l105.373 105.373 105.373-105.373c12.496-12.496 32.758-12.496 45.254 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["input-clear"],"defaultCode":59763,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1031,"name":"input-clear","prevSize":32,"id":119,"code":59763},"setIdx":2,"setId":2,"iconIdx":119},{"icon":{"paths":["M384 288c-17.674 0-32 14.327-32 32s14.326 32 32 32h256c17.674 0 32-14.326 32-32s-14.326-32-32-32h-256z","M352 448c0-17.674 14.326-32 32-32h256c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M512 640c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M224 224v576c0 35.347 28.654 64 64 64h448c35.347 0 64-28.653 64-64v-576c0-35.346-28.653-64-64-64h-448c-35.346 0-64 28.654-64 64zM288 800v-576h448v576h-448z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["instance"],"defaultCode":59764,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1032,"name":"instance","prevSize":32,"id":120,"code":59764},"setIdx":2,"setId":2,"iconIdx":120},{"icon":{"paths":["M563.59 255.992l-170.669 512.001h-136.941c-17.673 0-32 14.326-32 32 0 17.67 14.327 32 32 32h320c17.674 0 32-14.33 32-32 0-17.674-14.326-32-32-32h-115.597l170.669-512.001h136.928c17.674 0 32-14.327 32-32s-14.326-32-32-32h-159.002c-0.666-0.021-1.328-0.021-1.99 0h-159.008c-17.674 0-32 14.327-32 32s14.326 32 32 32h115.61z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["italic"],"defaultCode":59765,"grid":0},"attrs":[{}],"properties":{"order":1033,"name":"italic","prevSize":32,"id":121,"code":59765},"setIdx":2,"setId":2,"iconIdx":121},{"icon":{"paths":["M497.136 169.372c12.499 12.497 12.499 32.758 0 45.255l-35.958 35.96c1.078-0.016 2.163-0.025 3.245-0.025h191.152c115.11 0 208.426 93.316 208.426 208.426 0 115.107-93.315 208.422-208.426 208.422h-15.574v-64h15.574c79.763 0 144.426-64.659 144.426-144.422 0-79.766-64.662-144.426-144.426-144.426h-191.152c-1.030 0-2.058 0.011-3.082 0.032l35.795 35.796c12.499 12.499 12.499 32.758 0 45.258-12.496 12.496-32.758 12.496-45.254 0l-90.509-90.511c-12.496-12.497-12.496-32.758 0-45.255l90.509-90.51c12.496-12.497 32.758-12.497 45.254 0zM201.318 500.746h56.159v325.818h-59.023v-268.387h-1.909l-76.204 48.682v-54.090l80.977-52.022zM570.41 719.494c0 64.749-48.045 111.523-116.931 111.523-63.638 0-110.886-38.979-112.48-93.069h57.274c2.070 26.726 25.773 45.341 55.206 45.341 34.838 0 59.978-25.933 59.818-62.365 0.16-36.909-25.613-63.318-61.411-63.475-19.568-0.16-40.25 7.955-51.226 20.045l-53.296-8.749 17.024-168h188.998v49.318h-140.16l-9.386 86.384h1.91c12.090-14.317 35.475-24.816 61.885-24.816 59.184 0 102.774 45.181 102.774 107.862z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-backward"],"defaultCode":59766,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1034,"name":"jump-backward","prevSize":32,"id":122,"code":59766},"setIdx":2,"setId":2,"iconIdx":122},{"icon":{"paths":["M494.861 169.372c-12.496 12.497-12.496 32.758 0 45.255l35.962 35.96c-1.082-0.016-2.163-0.025-3.248-0.025h-191.149c-115.111 0-208.426 93.316-208.426 208.426 0 115.107 93.315 208.422 208.426 208.422h15.574v-64h-15.574c-79.764 0-144.426-64.659-144.426-144.422 0-79.766 64.661-144.426 144.426-144.426h191.149c1.030 0 2.061 0.011 3.085 0.032l-35.798 35.796c-12.496 12.499-12.496 32.758 0 45.258 12.499 12.496 32.758 12.496 45.258 0l90.509-90.511c12.496-12.497 12.496-32.758 0-45.255l-90.509-90.51c-12.499-12.497-32.758-12.497-45.258 0zM521.318 500.746h56.157v325.818h-59.021v-268.387h-1.91l-76.205 48.682v-54.090l80.979-52.022zM890.41 719.494c0 64.749-48.048 111.523-116.934 111.523-63.635 0-110.886-38.979-112.477-93.069h57.274c2.067 26.726 25.773 45.341 55.203 45.341 34.842 0 59.978-25.933 59.821-62.365 0.157-36.909-25.616-63.318-61.411-63.475-19.568-0.16-40.25 7.955-51.226 20.045l-53.296-8.749 17.021-168h189.002v49.318h-140.16l-9.386 86.384h1.91c12.090-14.317 35.475-24.816 61.885-24.816 59.181 0 102.774 45.181 102.774 107.862z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-forward"],"defaultCode":59767,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1035,"name":"jump-forward","prevSize":32,"id":123,"code":59767},"setIdx":2,"setId":2,"iconIdx":123},{"icon":{"paths":["M769.296 649.373c12.496 12.496 12.496 32.758 0 45.254l-192 192c-12.499 12.496-32.758 12.496-45.258 0l-192-192c-12.496-12.496-12.496-32.758 0-45.254 12.499-12.496 32.758-12.496 45.258 0l137.37 137.373v-578.746h-192v192c0 17.674-14.325 32-31.999 32s-32-14.326-32-32v-224c0-17.673 14.327-32 32-32h255.999c17.674 0 32 14.327 32 32v610.746l137.373-137.373c12.499-12.496 32.758-12.496 45.258 0z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["jump-to-message"],"defaultCode":59768,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1036,"name":"jump-to-message","prevSize":32,"id":124,"code":59768},"setIdx":2,"setId":2,"iconIdx":124},{"icon":{"paths":["M576 256c0 35.346-28.653 64-64 64s-64-28.654-64-64c0-35.346 28.653-64 64-64s64 28.654 64 64z","M576 512c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64z","M576 768c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["kebab"],"defaultCode":59769,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1037,"name":"kebab","prevSize":32,"id":125,"code":59769},"setIdx":2,"setId":2,"iconIdx":125},{"icon":{"paths":["M160 224c-35.346 0-64 28.654-64 64v448c0 35.347 28.654 64 64 64h704c35.347 0 64-28.653 64-64v-448c0-35.346-28.653-64-64-64h-704zM160 288h704v448h-704v-448zM256 352c-17.673 0-32 14.326-32 32s14.327 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM256 512c0-17.674 14.327-32 32-32h64c17.674 0 32 14.326 32 32s-14.326 32-32 32h-64c-17.673 0-32-14.326-32-32zM480 480c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM640 512c0-17.674 14.326-32 32-32h64c17.674 0 32 14.326 32 32s-14.326 32-32 32h-64c-17.674 0-32-14.326-32-32zM480 352c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64zM320 640c0-17.674 14.326-32 32-32h320c17.674 0 32 14.326 32 32s-14.326 32-32 32h-320c-17.674 0-32-14.326-32-32zM704 352c-17.674 0-32 14.326-32 32s14.326 32 32 32h64c17.674 0 32-14.326 32-32s-14.326-32-32-32h-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["keyboard"],"defaultCode":59770,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1038,"name":"keyboard","prevSize":32,"id":126,"code":59770},"setIdx":2,"setId":2,"iconIdx":126},{"icon":{"paths":["M505.133 128.078c60.819-1.376 120.422 15.569 170.346 48.251 49.904 32.67 87.501 79.327 107.75 133.159 20.24 53.808 22.205 112.266 5.648 167.165-16.554 54.89-50.864 103.683-98.368 139.309-15.501 11.462-28.189 26.246-36.989 43.309-8.822 17.107-13.469 36-13.507 55.216v21.514h-96.013v-148.774l120.989-151.235c11.040-13.802 8.803-33.939-4.998-44.979s-33.939-8.803-44.979 4.998l-103.011 128.765-103.011-128.765c-11.040-13.802-31.178-16.038-44.979-4.998s-16.038 31.178-4.998 44.979l120.989 151.235v148.774h-95.994v-21.677c-0.138-19.030-4.762-37.728-13.462-54.691-8.694-16.954-21.21-31.69-36.509-43.194l-19.229 25.578 19.069-25.696c-34.247-25.418-61.857-57.84-80.845-94.736-18.985-36.89-28.886-77.331-29.027-118.285v-0.045c-0.71-146.981 123.709-271.715 281.13-275.177zM640.013 800c16.506 0 32.618-6.243 44.72-17.795 12.157-11.603 19.28-27.664 19.28-44.746v-22.842c0.022-8.947 2.182-17.856 6.39-26.016 4.214-8.176 10.406-15.459 18.208-21.216l0.192-0.144c58.173-43.59 100.733-103.75 121.35-172.109 20.621-68.378 18.154-141.245-7.021-208.177-25.168-66.908-71.664-124.28-132.602-164.174-60.915-39.878-133.274-60.348-206.826-58.689-189.76 4.184-344.567 155.060-343.702 339.427l0 0.045 32-0.154-32 0.109c0.176 51.165 12.553 101.558 36.121 147.35 23.547 45.754 57.616 85.658 99.521 116.774 7.682 5.792 13.781 13.062 17.952 21.194 4.164 8.122 6.33 16.944 6.409 25.84v22.781c0 17.082 7.123 33.142 19.28 44.746 12.106 11.552 28.218 17.795 44.72 17.795h256.006zM352 864c-17.674 0-32 14.326-32 32s14.326 32 32 32h320c17.674 0 32-14.326 32-32s-14.326-32-32-32h-320z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["lamp-bulb"],"defaultCode":59836,"grid":0},"attrs":[{}],"properties":{"order":1039,"id":127,"name":"lamp-bulb","prevSize":32,"code":59836},"setIdx":2,"setId":2,"iconIdx":127},{"icon":{"paths":["M681.904 256c0-17.673-14.326-32-32-32s-32 14.327-32 32v56.875l-80.346 13.998c-17.411 3.034-29.069 19.61-26.035 37.021 3.034 17.408 19.61 29.066 37.021 26.032l69.36-12.086v69.373c-30.384 6.851-60.461 20.074-84.154 43.139-27.923 27.184-44.070 65.238-44.070 113.808 0 25.741 6.262 48.262 18.451 66.621 12.186 18.349 29.062 30.682 47.251 38 35.357 14.221 76.72 10.173 108.128-4.579l1.206-0.566c31.126-14.621 62.493-29.354 90.723-57.818 21.325-21.507 39.709-49.539 56.848-88.678 5.654 9.498 9.594 20.966 10.285 34.339 1.632 31.526-14.275 82.813-87.955 153.418-12.758 12.227-13.19 32.483-0.963 45.245 12.227 12.758 32.486 13.19 45.245 0.963 80.192-76.851 110.586-145.034 107.59-202.934-2.986-57.658-38.586-96.022-70.675-113.955-20.774-13.014-50.214-22.826-81.216-28.288-16.624-2.931-34.47-4.749-52.694-4.995v-74.243l101.718-17.722c17.411-3.034 29.066-19.61 26.032-37.019-3.034-17.411-19.606-29.066-37.018-26.032l-90.733 15.809v-45.724zM578.394 536.208c10.163-9.891 23.565-17.475 39.51-22.704v138.653c-13.443 2.547-27.485 1.731-38.634-2.752-7.712-3.104-13.658-7.757-17.824-14.029-4.157-6.262-7.766-15.997-7.766-31.216 0-33.35 10.563-54.176 24.714-67.952zM709.994 600.752c-8.682 8.755-17.782 15.706-28.090 22.074v-117.888c14.125 0.24 28.224 1.661 41.587 4.016 13.587 2.397 25.683 5.622 35.763 9.165-16.88 42.038-33.069 66.304-49.261 82.634zM247.704 565.334h98.386l-49.193-184.883-49.193 184.883zM390.851 733.562l-27.734-104.227h-132.442l-27.732 104.227c-4.544 17.078-22.073 27.242-39.152 22.694-17.079-4.544-27.24-22.070-22.696-39.152l106.323-399.598c13.494-50.714 85.462-50.713 98.956 0l106.323 399.598c4.544 17.082-5.616 34.608-22.694 39.152-17.078 4.547-34.608-5.616-39.152-22.694z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["language"],"defaultCode":59771,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1040,"name":"language","prevSize":32,"id":128,"code":59771},"setIdx":2,"setId":2,"iconIdx":128},{"icon":{"paths":["M234.831 743.917c-75.198-141.606-58.197-285.718 40.507-391.734 101.776-109.314 284.915-172.318 524.636-158.217 16.192 0.953 29.114 13.872 30.064 30.066 14.102 239.723-48.902 422.859-158.218 524.635-106.016 98.707-250.128 115.706-391.737 40.506l-65.457 65.456c-12.497 12.499-32.758 12.499-45.255 0-12.497-12.496-12.497-32.758 0-45.254l65.458-65.456zM282.51 696.237l300.107-300.109c12.496-12.496 32.758-12.496 45.254 0 12.496 12.499 12.496 32.758 0 45.258l-300.109 300.106c113.565 53.238 220.73 34.554 300.448-39.664 86.579-80.611 146.157-231.866 139.251-445.286-213.418-6.905-364.675 52.673-445.283 139.254-74.219 79.715-92.904 186.877-39.669 300.442z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["leaf"],"defaultCode":59814,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1041,"id":129,"name":"leaf","prevSize":32,"code":59814},"setIdx":2,"setId":2,"iconIdx":129},{"icon":{"paths":["M254.841 275.612l-13.972 14.271c-37.092 37.883-36.449 98.664 1.435 135.758l145.619 142.573c37.885 37.091 98.666 36.448 135.76-1.437l13.971-14.269c0.723-0.739 1.43-1.488 2.128-2.243l0.099 0.099c5.805-5.904 13.888-9.568 22.822-9.568 17.674 0 32 14.326 32 32 0 9.6-4.227 18.211-10.922 24.077l-0.397 0.41-13.974 14.269c-61.818 63.142-163.12 64.214-226.259 2.394l-145.622-142.576c-63.141-61.818-64.212-163.119-2.392-226.26l13.972-14.27c61.82-63.141 163.12-64.212 226.263-2.392l74.691 73.131c0.976 0.847 1.901 1.752 2.768 2.71l0.374 0.366-0.026 0.026c4.934 5.63 7.923 13.005 7.923 21.078 0 17.674-14.326 32-32 32-7.83 0-15.005-2.813-20.566-7.482l-0.106 0.109-77.834-76.206c-37.885-37.092-98.666-36.45-135.757 1.435zM790.566 768.003l13.971-14.269c37.091-37.885 36.448-98.666-1.437-135.757l-145.619-142.576c-37.885-37.091-98.666-36.448-135.757 1.437l-13.971 14.269c-0.723 0.739-1.434 1.488-2.128 2.243l-0.102-0.099c-5.805 5.907-13.885 9.568-22.822 9.568-17.67 0-32-14.326-32-32 0-9.6 4.227-18.211 10.922-24.077l0.4-0.406 13.971-14.272c61.821-63.142 163.12-64.211 226.262-2.39l145.619 142.573c63.142 61.821 64.211 163.12 2.394 226.262l-13.971 14.269c-61.821 63.142-163.123 64.211-226.262 2.394l-74.694-73.133c-0.976-0.845-1.901-1.75-2.768-2.71l-0.374-0.365 0.026-0.026c-4.931-5.629-7.923-13.005-7.923-21.078 0-17.674 14.326-32 32-32 7.83 0 15.005 2.813 20.566 7.482l0.106-0.109 77.837 76.208c37.885 37.091 98.662 36.448 135.757-1.437z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["link"],"defaultCode":59752,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1042,"name":"link","prevSize":32,"id":130,"code":59752},"setIdx":2,"setId":2,"iconIdx":130},{"icon":{"paths":["M840.541 128c31.318 0 56.813 24.79 56.813 55.383v657.212c0 30.592-25.494 55.427-56.813 55.427h-654.546c-31.254 0-56.642-24.835-56.642-55.427v-657.212c0-30.593 25.387-55.383 56.642-55.383h654.546zM300.196 233.75c-36.588 0-66.093 29.59-66.093 66.050 0 36.482 29.505 66.072 66.093 66.072 36.437 0 66.005-29.59 66.005-66.072 0-36.46-29.568-66.050-66.005-66.050zM243.148 782.461h114.029v-366.515h-114.029v366.515zM537.814 415.923h-109.187v366.515h113.773v-181.274c0-47.83 9.046-94.147 68.333-94.147 58.454 0 59.181 54.678 59.181 97.174v178.246h113.901v-201.008c0-98.714-21.312-174.598-136.666-174.598-55.402 0-92.566 30.381-107.757 59.203h-1.578v-50.112z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["linkedin-monochromatic"],"defaultCode":59658,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1043,"name":"linkedin-monochromatic","prevSize":32,"id":131,"code":59658},"setIdx":2,"setId":2,"iconIdx":131},{"icon":{"paths":["M700.144 361.891c4.685-24.973 34.704-34.093 49.13-13.171 31.994 46.403 50.726 102.653 50.726 163.28s-18.733 116.88-50.726 163.283c-14.426 20.922-44.445 11.802-49.13-13.174l-1.706-9.101c-1.581-8.429 0.384-17.082 4.858-24.403 20.749-33.965 32.704-73.888 32.704-116.605 0-42.714-11.955-82.637-32.704-116.605-4.474-7.318-6.438-15.971-4.858-24.4l1.706-9.104z","M320.704 395.395c-20.748 33.968-32.704 73.891-32.704 116.605 0 42.717 11.956 82.64 32.704 116.605 4.474 7.322 6.438 15.974 4.858 24.403l-1.706 9.101c-4.684 24.976-34.705 34.096-49.128 13.174-31.994-46.403-50.728-102.656-50.728-163.283s18.733-116.877 50.728-163.28c14.424-20.922 44.444-11.802 49.128 13.171l1.706 9.104c1.581 8.429-0.384 17.082-4.858 24.4z","M728.765 209.256l-0.515 2.747c-2.234 11.911 2.534 23.967 11.763 31.821 75.866 64.565 123.987 160.751 123.987 268.175 0 107.427-48.122 203.613-123.987 268.176-9.229 7.856-13.997 19.914-11.763 31.824l0.515 2.746c4.192 22.362 29.69 33.194 47.261 18.746 92.794-76.294 151.974-191.981 151.974-321.491 0-129.507-59.181-245.193-151.974-321.489-17.571-14.448-43.069-3.615-47.261 18.745z","M283.986 243.825c9.228-7.854 13.998-19.911 11.764-31.821l-0.515-2.747c-4.192-22.359-29.69-33.193-47.262-18.745-92.793 76.296-151.973 191.981-151.973 321.489 0 129.51 59.18 245.197 151.973 321.491 17.572 14.448 43.070 3.616 47.262-18.746l0.515-2.746c2.233-11.91-2.536-23.968-11.764-31.824-75.864-64.563-123.986-160.749-123.986-268.176 0-107.424 48.122-203.61 123.986-268.175z","M608 512c0 53.021-42.979 96-96 96s-96-42.979-96-96c0-53.018 42.979-96 96-96s96 42.982 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["live"],"defaultCode":59774,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1044,"name":"live","prevSize":32,"id":132,"code":59774},"setIdx":2,"setId":2,"iconIdx":132},{"icon":{"paths":["M439.274 704.374c0-33.645 26.278-47.677 72.726-47.677s72.73 14.032 72.73 47.677c0 32.96-13.19 111.069-23.914 149.76-4.963 17.808-22.080 25.171-48.816 25.171s-43.85-7.363-48.813-25.174c-10.717-38.666-23.914-116.688-23.914-149.757zM616.778 870.374l0.026-0.090c6.176-22.291 12.566-53.869 17.386-83.453 4.688-28.787 8.72-60.707 8.72-82.458 0-35.891-15.811-67.802-46.797-87.114-26.035-16.227-57.152-19.926-84.112-19.926-26.957 0-58.077 3.699-84.112 19.926-30.982 19.312-46.797 51.222-46.797 87.114 0 21.805 4.035 53.728 8.726 82.515 4.819 29.578 11.21 61.123 17.379 83.392l0.026 0.086c7.402 26.557 24.982 45.664 46.87 56.467 19.472 9.61 40.426 11.834 57.907 11.834 17.485 0 38.435-2.224 57.907-11.83 21.888-10.8 39.469-29.907 46.87-56.464zM459.635 460.8c0-28.275 23.446-51.2 52.365-51.2s52.365 22.925 52.365 51.2c0 28.278-23.446 51.2-52.365 51.2s-52.365-22.922-52.365-51.2zM512 341.334c-67.478 0-122.182 53.488-122.182 119.466 0 65.981 54.704 119.469 122.182 119.469s122.182-53.488 122.182-119.469c0-65.978-54.704-119.466-122.182-119.466zM677.802 537.254c-6.662 13.792-3.882 31.11 6.278 42.573 14.086 15.894 39.85 17.939 50.205-0.602 19.642-35.174 30.806-75.526 30.806-118.426 0-136.672-113.315-247.465-253.091-247.465-139.779 0-253.092 110.793-253.092 247.465 0 42.899 11.164 83.251 30.806 118.426 10.354 18.541 36.119 16.496 50.205 0.602 10.16-11.462 12.938-28.781 6.275-42.573-11.203-23.187-17.469-49.104-17.469-76.454 0-98.97 82.054-179.199 183.274-179.199s183.27 80.229 183.27 179.199c0 27.35-6.262 53.267-17.469 76.454zM730.16 699.795c-0.304-10.659 3.542-21.072 10.928-28.762 52.771-54.957 85.094-128.902 85.094-210.234 0-169.661-140.666-307.199-314.182-307.199s-314.182 137.538-314.182 307.199c0 81.331 32.323 155.28 85.093 210.234 7.386 7.69 11.234 18.102 10.928 28.762-0.833 29.018-31.273 47.917-52.121 27.715-70.223-68.042-113.718-162.41-113.718-266.71 0-207.363 171.923-375.465 384-375.465s384 168.102 384 375.465c0 104.304-43.498 198.672-113.722 266.714-20.848 20.202-51.286 1.302-52.118-27.718z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["live-streaming"],"defaultCode":59773,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1045,"name":"live-streaming","prevSize":32,"id":133,"code":59773},"setIdx":2,"setId":2,"iconIdx":133},{"icon":{"paths":["M397.011 527.334c26.576 0 48.122-21.587 48.122-48.214s-21.546-48.214-48.122-48.214c-26.576 0-48.118 21.587-48.118 48.214s21.542 48.214 48.118 48.214z","M589.491 479.12c0 26.627-21.542 48.214-48.118 48.214s-48.122-21.587-48.122-48.214c0-26.627 21.546-48.214 48.122-48.214s48.118 21.587 48.118 48.214z","M733.853 479.12c0 26.627-21.542 48.214-48.118 48.214s-48.122-21.587-48.122-48.214c0-26.627 21.546-48.214 48.122-48.214s48.118 21.587 48.118 48.214z","M88.039 813.683l119.625 31.283c85.312 22.307 173.45-16.256 238.691-79.709 29.501 4.794 59.875 7.242 90.678 7.242 218.294 0 404.339-122.864 404.339-294.518 0-171.664-186.042-294.52-404.339-294.52-218.314 0-404.351 122.852-404.34 294.523 0 65.072 27.642 125.014 75.655 173.587-2.847 24.835-14.596 44.73-36.049 68.55l-84.261 93.562zM537.034 258.997c183.13 0 331.6 98.043 331.6 218.984 0 120.931-148.47 218.982-331.6 218.982-40.781 0-79.834-4.877-115.91-13.763-36.669 45.6-117.335 109.008-195.697 88.518 25.489-28.304 63.251-76.131 55.168-154.909-46.968-37.779-75.162-86.134-75.162-138.829-0.008-120.95 148.461-218.984 331.6-218.984z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["livechat-monochromatic"],"defaultCode":59775,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1046,"name":"livechat-monochromatic","prevSize":32,"id":134,"code":59775},"setIdx":2,"setId":2,"iconIdx":134},{"icon":{"paths":["M512 128c-97.203 0-176 78.798-176 176v142.477h-16c-53.020 0-96 42.979-96 96v257.523c0 53.021 42.981 96 96 96h384c53.021 0 96-42.979 96-96v-257.523c0-53.021-42.979-96-96-96h-16v-142.477c0-97.202-78.797-176-176-176zM624 304v142.477h-224v-142.477c0-61.856 50.144-112 112-112s112 50.144 112 112z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["lock-filled"],"defaultCode":59748,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1047,"name":"lock-filled","prevSize":32,"id":135,"code":59748},"setIdx":2,"setId":2,"iconIdx":135},{"icon":{"paths":["M336 304c0-97.202 78.797-176 176-176s176 78.798 176 176v142.477h16c53.021 0 96 42.979 96 96v257.523c0 53.021-42.979 96-96 96h-384c-53.019 0-96-42.979-96-96v-257.523c0-53.021 42.981-96 96-96h16v-142.477zM400 446.477h224v-142.477c0-61.856-50.144-112-112-112s-112 50.144-112 112v142.477zM320 510.477c-17.673 0-32 14.326-32 32v257.523c0 17.674 14.327 32 32 32h384c17.674 0 32-14.326 32-32v-257.523c0-17.674-14.326-32-32-32h-384z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["locker"],"defaultCode":59749,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1048,"name":"locker","prevSize":32,"id":136,"code":59749},"setIdx":2,"setId":2,"iconIdx":136},{"icon":{"paths":["M341.334 778.672c-17.674 0-32 14.326-32 32s14.326 32 32 32h341.334c17.674 0 32-14.326 32-32s-14.326-32-32-32h-341.334zM85.335 298.672c0-70.692 57.308-128 128-128h597.334c70.691 0 128 57.308 128 128v298.666c0 70.694-57.309 128-128 128h-597.334c-70.692 0-128-57.306-128-128v-298.666zM213.335 234.672c-35.346 0-64 28.654-64 64v298.666c0 35.347 28.654 64 64 64h597.334c35.344 0 64-28.653 64-64v-298.666c0-35.347-28.656-64-64-64h-597.334zM256 320c0-11.782 9.551-21.333 21.333-21.333h170.667c11.782 0 21.334 9.551 21.334 21.333s-9.552 21.334-21.334 21.334h-170.667c-11.782 0-21.333-9.552-21.333-21.334zM277.333 554.666c-11.782 0-21.333 9.552-21.333 21.334s9.551 21.334 21.333 21.334h85.332c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-85.332zM554.666 320c0-11.782 9.552-21.333 21.334-21.333h170.666c11.782 0 21.334 9.551 21.334 21.333s-9.552 21.334-21.334 21.334h-170.666c-11.782 0-21.334-9.552-21.334-21.334zM448 554.666c-11.782 0-21.334 9.552-21.334 21.334s9.552 21.334 21.334 21.334h298.666c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-298.666zM256 448c0-11.782 9.551-21.334 21.333-21.334h213.332c11.782 0 21.334 9.552 21.334 21.334s-9.552 21.334-21.334 21.334h-213.332c-11.782 0-21.333-9.552-21.333-21.334zM618.666 426.666c-11.782 0-21.331 9.552-21.331 21.334s9.549 21.334 21.331 21.334h128c11.782 0 21.334-9.552 21.334-21.334s-9.552-21.334-21.334-21.334h-128z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["log-view"],"defaultCode":59778,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1049,"name":"log-view","prevSize":32,"id":137,"code":59778},"setIdx":2,"setId":2,"iconIdx":137},{"icon":{"paths":["M176 96c-17.673 0-32 14.327-32 32v768c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-96c0-17.674-14.326-32-32-32s-32 14.326-32 32v64h-448v-704h448v64c0 17.673 14.326 32 32 32s32-14.327 32-32v-96c0-17.673-14.326-32-32-32h-512zM521.373 329.373c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.254l-105.373 105.373h418.746c17.674 0 32 14.326 32 32s-14.326 32-32 32h-418.746l105.373 105.373c12.496 12.496 12.496 32.758 0 45.254s-32.758 12.496-45.254 0l-160-160c-12.496-12.496-12.496-32.758 0-45.254l160-160z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["login"],"defaultCode":59779,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1050,"name":"login","prevSize":32,"id":138,"code":59779},"setIdx":2,"setId":2,"iconIdx":138},{"icon":{"paths":["M268.099 96c-17.673 0-32 14.327-32 32v768c0 17.674 14.327 32 32 32h512c17.674 0 32-14.326 32-32v-96c0-17.674-14.326-32-32-32s-32 14.326-32 32v64h-448v-704h448v64c0 17.673 14.326 32 32 32s32-14.327 32-32v-96c0-17.673-14.326-32-32-32h-512zM994.726 489.373l-160-160c-12.496-12.497-32.758-12.497-45.254 0s-12.496 32.758 0 45.254l105.373 105.373h-418.746c-17.674 0-32 14.326-32 32s14.326 32 32 32h418.746l-105.373 105.373c-12.496 12.496-12.496 32.758 0 45.254s32.758 12.496 45.254 0l160-160c12.496-12.496 12.496-32.758 0-45.254z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["logout"],"defaultCode":59780,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1051,"name":"logout","prevSize":32,"id":139,"code":59780},"setIdx":2,"setId":2,"iconIdx":139},{"icon":{"paths":["M192 736h640v-448h-640v448zM128 256c0-17.673 14.327-32 32-32h704c17.674 0 32 14.327 32 32v512c0 17.674-14.326 32-32 32h-704c-17.673 0-32-14.326-32-32v-512zM305.304 389.082c-14.866-9.555-34.665-5.251-44.222 9.613-9.557 14.867-5.253 34.666 9.613 44.224l241.304 155.123 241.306-155.123c14.864-9.558 19.168-29.357 9.613-44.224-9.558-14.864-29.357-19.168-44.224-9.613l-206.694 132.877-206.696-132.877z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["mail"],"defaultCode":59781,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1052,"name":"mail","prevSize":32,"id":140,"code":59781},"setIdx":2,"setId":2,"iconIdx":140},{"icon":{"paths":["M302.769 192h418.463l23.187 72.727h-0.211l23.792 63.999c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818c0-18.476-14.326-33.454-32-33.454s-32 14.978-32 33.454c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818c0-18.476-14.326-33.454-32-33.454s-32 14.978-32 33.454c0 41.27-31.306 69.818-64 69.818s-64-28.547-64-69.818l23.794-63.999h-0.213l23.188-72.727zM212.406 264.727l36.491-114.448c4.231-13.27 16.56-22.279 30.488-22.279h465.23c13.93 0 26.259 9.009 30.49 22.279l56.896 178.447c0 33.939-12.083 64.925-32 88.515v350.778c0 53.018-42.979 96-96 96h-384c-53.019 0-96-42.982-96-96v-350.778c-19.916-23.59-32-54.576-32-88.515l20.406-63.999zM288 458.33v309.69c0 17.67 14.327 32 32 32h128v-192.019h128v192.019h128c17.674 0 32-14.33 32-32v-309.69c-10.227 2.752-20.95 4.214-32 4.214-38.23 0-72.547-17.52-96-45.302-23.453 27.782-57.77 45.302-96 45.302s-72.547-17.52-96-45.302c-23.453 27.782-57.77 45.302-96 45.302-11.050 0-21.772-1.462-32-4.214z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["marketplace"],"defaultCode":59782,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1053,"name":"marketplace","prevSize":32,"id":141,"code":59782},"setIdx":2,"setId":2,"iconIdx":141},{"icon":{"paths":["M773.072 576c-35.344 0-64-28.653-64-64s28.656-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64z","M517.072 576c-35.344 0-64-28.653-64-64s28.656-64 64-64c35.347 0 64 28.653 64 64s-28.653 64-64 64z","M261.073 576c-35.346 0-64-28.653-64-64s28.654-64 64-64c35.346 0 63.999 28.653 63.999 64s-28.652 64-63.999 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["meatballs"],"defaultCode":59783,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1054,"name":"meatballs","prevSize":32,"id":142,"code":59783},"setIdx":2,"setId":2,"iconIdx":142},{"icon":{"paths":["M651.36 116.071c-57.242-19.989-105.792-20.069-138.358-20.071v64l-1.002-64c-92.006 0.342-297.345 47.824-381.242 242.995-17.897 38.97-34.758 103.344-34.758 173.005 0 69.958 17.020 146.285 52.216 207.875 23.229 40.653 92.799 131.376 191.179 173.536 94.861 40.656 206.368 52.349 296.49 16.301 16.41-6.563 24.39-25.187 17.827-41.597s-25.187-24.39-41.597-17.827c-69.878 27.952-163.171 20.445-247.51-15.699-80.819-34.64-141.384-112.451-160.821-146.464-28.804-50.41-43.784-115.418-43.784-176.125 0-60.765 15.020-116.182 29.055-146.589l0.184-0.4 0.173-0.406c69.507-162.181 243.823-204.604 323.589-204.605 31.594 0.002 70.877 0.296 117.258 16.493 46.147 16.114 101.389 48.779 161.824 116.767 43.658 49.115 63.533 114.977 69.389 177.713 5.891 63.12-2.854 118.189-11.546 142.093-6.4 17.6-20.429 45.44-59.392 45.699-18.259-0.806-72.822-14.672-83.12-69.568v-235.062c0-17.674-3.414-34.134-29.014-34.134-19.338 0-26.454 16.461-26.454 34.134v34.131c-35.181-39.859-95.402-68.266-152.746-68.266-106.038 0-192 85.962-192 192s85.962 192 192 192c62.179 0 117.658-29.555 152.746-75.386 25.715 71.078 102.57 93.027 137.014 94.134l0.515 0.016h0.512c82.643 0 111.715-64.806 120.086-87.83 12.64-34.762 21.674-99.696 15.12-169.907-6.589-70.595-29.379-151.401-85.277-214.287-66.902-75.265-131.075-114.597-188.557-134.67zM627.2 512c0 70.691-57.309 128-128 128s-128-57.309-128-128c0-70.691 57.309-128 128-128s128 57.309 128 128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["mention"],"defaultCode":59784,"grid":0},"attrs":[{}],"properties":{"order":1055,"name":"mention","prevSize":32,"id":143,"code":59784},"setIdx":2,"setId":2,"iconIdx":143},{"icon":{"paths":["M223.311 308.609c-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-9.348 103.235 27.547 175.997 86.848 226.374 60.643 51.52 146.602 80.998 235.29 90.893 88.614 9.885 186.224 1.398 263.341-14.973 38.56-8.189 70.928-18.125 93.888-28.128 8.906-3.882 15.837-7.536 20.944-10.765-2.378-1.514-5.248-3.197-8.675-5.030-8.886-4.749-19.059-9.261-29.613-13.894l-1.843-0.81c-9.315-4.083-19.725-8.65-27.613-13.078-14.291-8.026-28.317-17.155-38.544-26.867-5.034-4.781-10.762-11.194-14.595-19.184-4.054-8.454-6.96-21.078-1.261-34.435 30.816-72.186 45.459-111.725 52.554-137.834 6.621-24.378 6.621-36.653 6.621-56.17v-0.179c0-15.51-8.979-86.595-53.776-152.876-43.376-64.174-121.395-125.729-264.832-125.729-129.725 0-207.83 53.576-254.529 118.696zM173.267 272.433c58.132-81.063 154.749-144.433 304.573-144.433 164.896 0 261.594 72.589 315.859 152.878 52.838 78.181 64.416 161.881 64.416 187.641 0 21.654-0.022 40.336-8.797 72.64-7.83 28.835-22.627 68.614-50.048 133.424 5.069 4.032 12.592 9.005 22.506 14.57 5.123 2.877 12.995 6.339 24.054 11.194 10.266 4.506 22.582 9.93 33.891 15.978 10.848 5.798 23.526 13.571 32.954 23.738 9.859 10.63 20.208 28.87 12.816 51.139-4.87 14.672-16.182 25.091-25.61 32.016-10.24 7.52-22.947 14.278-36.858 20.342-27.946 12.176-64.582 23.181-105.68 31.907-82.198 17.453-186.522 26.688-282.909 15.936-96.31-10.746-195.346-43.178-268.313-105.165-74.031-62.893-119.295-154.778-108.551-277.856 0.276-63.411 19.117-157.053 75.696-235.948z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["message"],"defaultCode":59786,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1056,"name":"message","prevSize":32,"id":144,"code":59786},"setIdx":2,"setId":2,"iconIdx":144},{"icon":{"paths":["M477.84 128c104.256 0 181.251 29.018 237.494 70.652l-44.317 44.317c-45.52-31.22-107.747-53.057-193.178-53.057-129.725 0-207.83 53.576-254.529 118.696-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-7.328 80.928 13.761 143.126 51.784 190.499l-43.879 43.878c-50.179-59.901-78.131-139.043-69.441-238.595 0.276-63.411 19.117-157.053 75.696-235.948 58.132-81.063 154.749-144.433 304.573-144.433zM822.848 332.499l-47.008 47.008c16.502 42.634 20.608 78.525 20.608 89.011v0.179c0 19.517 0 31.792-6.621 56.17-7.094 26.109-21.738 65.648-52.554 137.834-5.699 13.357-2.794 25.981 1.261 34.435 3.834 7.99 9.562 14.403 14.595 19.184 10.227 9.712 24.253 18.842 38.544 26.867 7.888 4.429 18.298 8.995 27.613 13.078l1.843 0.81c10.554 4.634 20.726 9.146 29.613 13.894 3.427 1.834 6.298 3.517 8.672 5.030-5.104 3.229-12.035 6.883-20.941 10.765-22.96 10.003-55.328 19.939-93.888 28.128-77.12 16.371-174.73 24.858-263.341 14.973-43.744-4.88-86.826-14.525-126.534-29.229l-47.542 47.542c52.771 23.018 110.492 36.886 167.267 43.222 96.387 10.752 200.71 1.517 282.909-15.936 41.098-8.726 77.731-19.731 105.68-31.907 13.91-6.064 26.618-12.822 36.858-20.342 9.427-6.925 20.739-17.344 25.61-32.016 7.392-22.269-2.957-40.509-12.816-51.139-9.427-10.166-22.106-17.939-32.954-23.738-11.309-6.048-23.626-11.472-33.891-15.978-11.059-4.854-18.934-8.317-24.054-11.194-9.914-5.565-17.437-10.538-22.506-14.57 27.421-64.81 42.214-104.589 50.048-133.424 8.774-32.304 8.797-50.986 8.797-72.64 0-20.106-7.053-75.501-35.267-136.019zM836.038 153.372c12.499-12.497 32.758-12.497 45.254 0 12.499 12.497 12.499 32.758 0 45.255l-682.665 682.665c-12.497 12.499-32.758 12.499-45.255 0-12.497-12.496-12.497-32.755 0-45.254l682.666-682.666z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["message-disabled"],"defaultCode":59785,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1057,"name":"message-disabled","prevSize":32,"id":145,"code":59785},"setIdx":2,"setId":2,"iconIdx":145},{"icon":{"paths":["M86.686 85.336l730.792 774.088c0 0 24.899 17.558 43.936-2.928 19.040-20.486 4.394-40.973 4.394-40.973l-779.122-730.187zM318.080 158.503l556.516 599.955c0 0 24.896 17.558 43.936-2.928 19.037-20.486 4.394-40.973 4.394-40.973l-604.845-556.054zM712.035 915.030l-556.517-599.955 604.843 556.054c0 0 14.646 20.486-4.39 40.973-19.040 20.486-43.936 2.928-43.936 2.928zM513.693 221.419l388.803 419.15c0 0 17.395 12.269 30.694-2.042 13.302-14.314 3.069-28.627 3.069-28.627l-422.566-388.482zM597.878 915.677l-388.805-419.152 422.568 388.48c0 0 10.234 14.314-3.069 28.627-13.302 14.31-30.694 2.045-30.694 2.045zM713.498 312.143l176.221 190.551c0 0 8.605 5.747 15.184-0.96 6.579-6.704 1.517-13.411 1.517-13.411l-192.922-176.18zM482.582 880.23l-176.219-190.55 192.923 176.179c0 0 5.059 6.707-1.52 13.414-6.579 6.704-15.184 0.957-15.184 0.957z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["meteor-monochromatic"],"defaultCode":59659,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1058,"name":"meteor-monochromatic","prevSize":32,"id":146,"code":59659},"setIdx":2,"setId":2,"iconIdx":146},{"icon":{"paths":["M608 288c0-53.019-42.979-96-96-96s-96 42.981-96 96v128c0 53.021 42.979 96 96 96s96-42.979 96-96v-128zM352 288c0-88.365 71.635-160 160-160s160 71.635 160 160v128c0 88.365-71.635 160-160 160s-160-71.635-160-160v-128zM256 384c17.673 0 32 14.326 32 32 0 92.086 37.757 149.632 83.722 185.6 46.464 36.358 102.736 51.581 140.278 54.326 37.542-2.746 93.814-17.968 140.278-54.326 45.962-35.968 83.722-93.514 83.722-185.6 0-17.674 14.326-32 32-32s32 14.326 32 32c0 112.714-47.574 188.499-108.278 236-47.904 37.485-103.082 56.762-147.722 64.381v115.619h160c17.674 0 32 14.326 32 32s-14.326 32-32 32h-384c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-115.619c-44.64-7.619-99.818-26.896-147.722-64.381-60.703-47.501-108.278-123.286-108.278-236 0-17.674 14.327-32 32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["microphone"],"defaultCode":59788,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1059,"name":"microphone","prevSize":32,"id":147,"code":59788},"setIdx":2,"setId":2,"iconIdx":147},{"icon":{"paths":["M512 128c75.546 0 138.861 52.356 155.645 122.762l-59.645 59.644v-22.405c0-53.019-42.979-96-96-96s-96 42.981-96 96v128c0 24.067 8.858 46.067 23.488 62.915l-45.322 45.325c-26.182-28.49-42.166-66.499-42.166-108.24v-128c0-88.365 71.635-160 160-160zM561.35 568.243l102.893-102.893c-15.763 48.672-54.221 87.13-102.893 102.893zM288 416c0 72.154 23.181 123.101 55.328 159.078l-45.304 45.302c-43.428-47.35-74.024-113.99-74.024-204.381 0-17.674 14.327-32 32-32s32 14.326 32 32zM478.659 650.938l-51.808 51.808c18.56 6.374 36.579 10.806 53.149 13.635v115.619h-160c-17.673 0-32 14.326-32 32s14.327 32 32 32h384c17.674 0 32-14.326 32-32s-14.326-32-32-32h-160v-115.619c44.64-7.619 99.818-26.896 147.722-64.381 60.704-47.501 108.278-123.286 108.278-236 0-17.674-14.326-32-32-32s-32 14.326-32 32c0 92.086-37.757 149.632-83.722 185.6-46.464 36.358-102.736 51.581-140.278 54.326-9.971-0.73-21.264-2.339-33.341-4.989zM825.373 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672-672z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["microphone-disabled"],"defaultCode":59787,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1060,"name":"microphone-disabled","prevSize":32,"id":148,"code":59787},"setIdx":2,"setId":2,"iconIdx":148},{"icon":{"paths":["M234.666 170.661c0-47.128 38.205-85.333 85.333-85.333h384.001c47.126 0 85.331 38.205 85.331 85.333v682.667c0 47.13-38.205 85.334-85.331 85.334h-384.001c-47.128 0-85.333-38.205-85.333-85.334v-682.667zM298.666 170.661v682.667c0 11.782 9.551 21.334 21.333 21.334h384.001c11.782 0 21.331-9.552 21.331-21.334v-682.667c0-11.782-9.549-21.333-21.331-21.333h-96.291c-2.653 24.002-23.002 42.672-47.709 42.672h-96c-24.707 0-45.056-18.67-47.709-42.672h-96.292c-11.782 0-21.333 9.551-21.333 21.333z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["mobile"],"defaultCode":59789,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1061,"name":"mobile","prevSize":32,"id":149,"code":59789},"setIdx":2,"setId":2,"iconIdx":149},{"icon":{"paths":["M319.247 231.566c-62.882 49.504-135.086 136.549-141.94 266.127-5.762 108.922 37.404 187.184 89.915 241.51 53.258 55.098 115.702 84.925 144.25 94.438 41.859 13.955 114.269 29.536 234.643-15.603 34.858-13.072 73.165-42.096 108.304-78.426 14.272-14.755 27.616-30.294 39.6-45.773-28.778 9.293-61.699 17.754-96.589 23.594-56.192 9.405-119.29 12.32-179.411-0.237-2.49-0.518-4.96-1.030-7.408-1.536-22.195-4.576-42.733-8.816-62.589-17.648-23.091-10.275-43.805-25.891-69.299-51.386-42.096-42.096-89.142-107.222-89.371-213.843-1.569-34.080 4.622-81.878 13.764-129.216 4.624-23.946 10.142-48.465 16.132-72.003zM345.562 138.217c32.8-17.15 63.709 15.843 53.875 45.907-12.234 37.414-24.586 85.511-33.482 131.58-9.024 46.732-13.949 88.633-12.643 114.7l0.038 0.797v0.8c0 84.915 36.173 134.918 70.627 169.373 22.509 22.509 36.835 32.278 50.064 38.166 13.229 5.885 26.832 8.717 51.085 13.763 1.923 0.4 3.917 0.816 5.978 1.248 49.914 10.426 104.534 8.336 155.76-0.237 65.434-10.954 122.384-31.981 152.374-47.386 17.562-9.021 34.992-2.47 44.477 5.965 9.661 8.589 19.376 27.152 8.886 46.954-20.637 38.95-53.645 84.419-92.182 124.259-38.211 39.51-84.317 76.038-131.834 93.859-135.626 50.858-223.216 34.438-277.354 16.394-36.515-12.173-108.392-46.912-170.026-110.675-62.381-64.534-114.684-159.427-107.81-289.373 10.79-203.979 157.583-317.098 232.165-356.093z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["moon"],"defaultCode":59790,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1062,"name":"moon","prevSize":32,"id":150,"code":59790},"setIdx":2,"setId":2,"iconIdx":150},{"icon":{"paths":["M144 160c-17.673 0-32 14.327-32 32s14.327 32 32 32h192c17.674 0 32-14.327 32-32s-14.326-32-32-32h-192zM700.4 346.646c11.795-13.165 32.026-14.272 45.187-2.48 13.162 11.795 14.272 32.026 2.477 45.187l-81.222 90.646h216.358c17.674 0 32 14.326 32 32s-14.326 32-32 32h-216.358l81.222 90.646c11.795 13.162 10.685 33.392-2.477 45.187-13.162 11.792-33.392 10.685-45.187-2.48l-129.030-144c-10.893-12.154-10.893-30.554 0-42.707l129.030-144zM112 512c0-17.674 14.327-32 32-32h192c17.674 0 32 14.326 32 32s-14.326 32-32 32h-192c-17.673 0-32-14.326-32-32zM144 640c-17.673 0-32 14.326-32 32s14.327 32 32 32h192c17.674 0 32-14.326 32-32s-14.326-32-32-32h-192zM112 352c0-17.674 14.327-32 32-32h192c17.674 0 32 14.326 32 32s-14.326 32-32 32h-192c-17.673 0-32-14.326-32-32zM144 800c-17.673 0-32 14.326-32 32s14.327 32 32 32h192c17.674 0 32-14.326 32-32s-14.326-32-32-32h-192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["move-to-the-queue"],"defaultCode":59791,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1063,"name":"move-to-the-queue","prevSize":32,"id":151,"code":59791},"setIdx":2,"setId":2,"iconIdx":151},{"icon":{"paths":["M809.002 166.758c7.782 6.063 12.333 15.377 12.333 25.242v448h-0.112c0.074 1.734 0.112 3.478 0.112 5.229 0 69.053-57.309 125.030-128 125.030-70.694 0-128-55.978-128-125.030s57.306-125.030 128-125.030c23.312 0 45.171 6.090 64 16.73v-303.86l-384 96.798v409.136c0 69.053-57.309 125.037-128.001 125.037s-128-55.978-128-125.030c0-69.050 57.308-125.027 128-125.027 23.314 0 45.173 6.086 64 16.726v-325.777c0-14.66 9.962-27.446 24.177-31.029l448-112.93c9.568-2.411 19.709-0.276 27.491 5.788z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["musical-note"],"defaultCode":59792,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1064,"name":"musical-note","prevSize":32,"id":152,"code":59792},"setIdx":2,"setId":2,"iconIdx":152},{"icon":{"paths":["M208 176c-35.346 0-64 28.654-64 64v576c0 35.347 28.654 64 64 64h576c35.347 0 64-28.653 64-64v-576c0-35.346-28.653-64-64-64h-576zM208 240h576v576h-576v-576zM698.627 558.15c-0.189 17.674-14.669 31.846-32.339 31.658-17.674-0.189-31.846-14.669-31.658-32.339l1.318-123.594-309.341 308.774c-12.51 12.483-32.771 12.464-45.256-0.042-12.485-12.509-12.467-32.771 0.042-45.258l309.195-308.624-123.382 1.315c-17.674 0.189-32.154-13.984-32.339-31.654-0.189-17.674 13.984-32.15 31.654-32.339l201.92-2.157c8.605-0.093 16.886 3.286 22.97 9.37 6.086 6.086 9.462 14.365 9.373 22.97l-2.157 201.92z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["new-window"],"defaultCode":59793,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1065,"name":"new-window","prevSize":32,"id":153,"code":59793},"setIdx":2,"setId":2,"iconIdx":153},{"icon":{"paths":["M601.331 808.928h-174.154c0.003 48.090 38.989 87.072 87.078 87.072s87.075-38.982 87.075-87.072zM815.597 731.677c7.274 9.696 8.442 22.669 3.021 33.51s-16.499 17.69-28.621 17.69h-565.996c-12.943 0-24.611-7.798-29.564-19.757-4.953-11.955-2.215-25.718 6.937-34.87l51.653-51.654v-274.032c0-144.272 116.957-261.228 261.229-261.228s261.229 116.956 261.229 261.228v275.629l40.112 53.485zM711.485 715.894v-313.331c0-108.926-88.304-197.228-197.229-197.228-108.928 0-197.229 88.302-197.229 197.228v313.331h394.458z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["notification"],"defaultCode":59795,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1066,"name":"notification","prevSize":32,"id":154,"code":59795},"setIdx":2,"setId":2,"iconIdx":154},{"icon":{"paths":["M781.837 402.634c0-5.245-0.154-10.454-0.461-15.622l-63.539 63.539v265.363h-265.363l-66.979 66.979h425.363c12.944 0 24.611-7.795 29.565-19.754 4.954-11.955 2.214-25.722-6.938-34.874l-51.648-51.648v-273.984zM704.765 217.373l-45.254 45.255c-35.638-35.351-84.704-57.189-138.867-57.189-108.909 0-197.194 88.287-197.194 197.195v196.054l-64.001 64v-260.054c0-144.254 116.941-261.195 261.194-261.195 71.837 0 136.899 29.001 184.122 75.934zM433.578 808.934c0 48.086 38.982 87.066 87.066 87.066s87.066-38.979 87.066-87.066h-174.131zM854.275 190.982c-11.334-11.334-29.709-11.334-41.043 0l-612.732 612.733c-11.333 11.331-11.333 29.709 0 41.040 11.334 11.334 29.709 11.334 41.043 0l612.732-612.731c11.334-11.333 11.334-29.709 0-41.043z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["notification-disabled"],"defaultCode":59794,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1067,"name":"notification-disabled","prevSize":32,"id":155,"code":59794},"setIdx":2,"setId":2,"iconIdx":155},{"icon":{"paths":["M712.051 512.675v54.89c-0.195 76.736-43.741 143.283-107.44 176.445-5.53-25.67-28.362-44.906-55.683-44.906h-72.502c-31.459 0-56.963 25.501-56.963 56.963v41.427c0 31.462 25.504 56.963 56.963 56.963h72.502c28.509 0 52.128-20.944 56.307-48.288 69.261-26.829 123.962-82.883 148.966-153.030 4.723 1.27 9.69 1.946 14.813 1.946h28.483c31.459 0 56.963-25.504 56.963-56.963v-85.446c0-31.459-25.504-56.963-56.963-56.963h-28.483v-28.483c0-141.572-114.765-256.338-256.336-256.338s-256.339 114.766-256.339 256.338v23.302h-28.483c-31.46 0-56.964 25.504-56.964 56.966v103.571c0 31.459 25.504 56.963 56.964 56.963h28.482c31.46 0 56.964-25.504 56.964-56.963v-36.253h0.149c-0.099-2.576-0.148-5.165-0.148-7.766v-139.821c0-110.111 89.263-199.374 199.375-199.374s199.373 89.263 199.373 199.374v85.446z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["omnichannel"],"defaultCode":59796,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1068,"name":"omnichannel","prevSize":32,"id":156,"code":59796},"setIdx":2,"setId":2,"iconIdx":156},{"icon":{"paths":["M705.578 633.158c9.507-9.235 24.701-9.018 33.939 0.486 9.238 9.507 9.021 24.701-0.486 33.939l-208.275 202.387c-9.312 9.050-24.138 9.050-33.45 0l-208.276-202.387c-9.506-9.238-9.724-24.432-0.487-33.939 9.237-9.504 24.432-9.722 33.937-0.486l191.549 186.134 191.549-186.134zM705.578 411.584c9.507 9.238 24.701 9.021 33.939-0.486s9.021-24.701-0.486-33.939l-208.275-202.385c-9.312-9.051-24.138-9.051-33.45 0l-208.276 202.385c-9.506 9.238-9.724 24.432-0.487 33.939 9.237 9.504 24.432 9.725 33.937 0.486l191.549-186.134 191.549 186.134z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["order"],"defaultCode":59797,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1069,"name":"order","prevSize":32,"id":157,"code":59797},"setIdx":2,"setId":2,"iconIdx":157},{"icon":{"paths":["M742.317 652.566c12.666-12.323 12.944-32.582 0.618-45.248-12.323-12.669-32.582-12.944-45.251-0.621l44.634 45.869zM512 832.019l-22.317 22.934c12.422 12.086 32.211 12.086 44.634 0l-22.317-22.934zM326.317 606.698c-12.667-12.323-32.927-12.048-45.252 0.621-12.324 12.666-12.047 32.925 0.619 45.248l44.632-45.869zM697.683 606.698l-208 202.387 44.634 45.869 208-202.387-44.634-45.869zM534.317 809.085l-208-202.387-44.632 45.869 207.999 202.387 44.634-45.869z","M742.317 371.456c12.666 12.323 12.944 32.582 0.618 45.251-12.323 12.666-32.582 12.944-45.251 0.618l44.634-45.869zM512 192.004l-22.317-22.935c12.422-12.087 32.211-12.087 44.634 0l-22.317 22.935zM326.317 417.325c-12.668 12.326-32.927 12.048-45.252-0.618-12.325-12.669-12.048-32.928 0.619-45.251l44.633 45.869zM697.683 417.325l-208-202.386 44.634-45.87 208 202.387-44.634 45.869zM534.317 214.939l-208 202.386-44.633-45.869 207.999-202.387 44.634 45.87z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":9}]},"tags":["ordering-ascending"],"defaultCode":59798,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":1070,"name":"ordering-ascending","prevSize":32,"codes":[59798,59799],"id":158,"code":59798},"setIdx":2,"setId":2,"iconIdx":158},{"icon":{"paths":["M281.684 371.434c-12.667 12.323-12.944 32.582-0.619 45.248 12.324 12.669 32.584 12.944 45.252 0.621l-44.633-45.869zM512 191.981l22.317-22.935c-12.422-12.087-32.211-12.087-44.634 0l22.317 22.935zM697.683 417.302c12.669 12.323 32.928 12.048 45.251-0.621 12.326-12.666 12.048-32.925-0.618-45.248l-44.634 45.869zM326.317 417.302l208-202.387-44.634-45.869-207.999 202.387 44.633 45.869zM489.683 214.916l208 202.387 44.634-45.869-208-202.387-44.634 45.869z","M281.684 652.544c-12.667-12.323-12.944-32.582-0.619-45.251 12.324-12.666 32.584-12.944 45.252-0.618l-44.633 45.869zM512 831.997l22.317 22.934c-12.422 12.086-32.211 12.086-44.634 0l22.317-22.934zM697.683 606.675c12.669-12.326 32.928-12.048 45.251 0.618 12.326 12.669 12.048 32.928-0.618 45.251l-44.634-45.869zM326.317 606.675l208 202.384-44.634 45.872-207.999-202.387 44.633-45.869zM489.683 809.059l208-202.384 44.634 45.869-208 202.387-44.634-45.872z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"isMulticolor":true,"isMulticolor2":true,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":9}]},"tags":["ordering-descending"],"defaultCode":59800,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(158, 162, 168)","opacity":0.7}],"properties":{"order":1071,"name":"ordering-descending","prevSize":32,"codes":[59800,59801],"id":159,"code":59800},"setIdx":2,"setId":2,"iconIdx":159},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352-194.405 0-352.001 157.596-352.001 352s157.596 352 352.001 352c194.403 0 352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416-229.752 0-416.001-186.25-416.001-416s186.25-416 416.001-416c229.75 0 416 186.25 416 416zM399.997 383.994v256c0 17.674 14.326 32 32 32s32-14.326 32-32v-256c0-17.67-14.326-32-32-32s-32 14.33-32 32zM559.997 383.994v256c0 17.674 14.326 32 32 32s32-14.326 32-32v-256c0-17.67-14.326-32-32-32s-32 14.33-32 32z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pause"],"defaultCode":59803,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1072,"name":"pause","prevSize":32,"id":160,"code":59803},"setIdx":2,"setId":2,"iconIdx":160},{"icon":{"paths":["M512 928c229.75 0 416-186.25 416-416s-186.25-416-416-416c-229.752 0-416.001 186.25-416.001 416s186.25 416 416.001 416zM399.997 383.994c0-17.67 14.326-32 32-32s32 14.33 32 32v256c0 17.674-14.326 32-32 32s-32-14.326-32-32v-256zM559.997 383.994c0-17.67 14.326-32 32-32s32 14.33 32 32v256c0 17.674-14.326 32-32 32s-32-14.326-32-32v-256z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pause-filled"],"defaultCode":59802,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1073,"name":"pause-filled","prevSize":32,"id":161,"code":59802},"setIdx":2,"setId":2,"iconIdx":161},{"icon":{"paths":["M822.627 201.372c12.496 12.497 12.496 32.758 0 45.255l-576 576c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l576-576c12.496-12.497 32.758-12.497 45.254 0z","M192 320c0-70.692 57.308-128 128-128 70.691 0 128 57.308 128 128 0 70.691-57.309 128-128 128-70.692 0-128-57.309-128-128zM320 256c-35.346 0-64 28.654-64 64s28.654 64 64 64c35.347 0 64-28.653 64-64s-28.653-64-64-64z","M704 576c-70.691 0-128 57.309-128 128s57.309 128 128 128c70.691 0 128-57.309 128-128s-57.309-128-128-128zM640 704c0-35.347 28.653-64 64-64s64 28.653 64 64c0 35.347-28.653 64-64 64s-64-28.653-64-64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["percentage"],"defaultCode":59777,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1074,"id":162,"name":"percentage","prevSize":32,"code":59777},"setIdx":2,"setId":2,"iconIdx":162},{"icon":{"paths":["M410.502 204.616c-10.419-21.362-34.202-37.856-62.189-33.137-38.104 6.425-88.825 25.194-126.247 57.060-18.972 16.155-35.817 36.795-44.757 62.246-9.15 26.048-9.211 54.919 2.087 85.195 21.202 56.816 60.513 117.456 97.761 167.264 37.482 50.122 74.609 91.552 93.329 110.269l44.173-44.173c-16.406-16.403-51.6-55.536-87.472-103.51-36.11-48.285-71.192-103.264-89.264-151.69-6.437-17.248-5.748-31.056-1.675-42.651 4.283-12.192 13.134-24.16 26.319-35.388 25.849-22.012 63.292-36.814 92.623-42.392l59.075 121.097c0.019 0.074 0.045 0.285-0.013 0.688-0.112 0.749-0.502 1.827-1.344 2.883-7.117 8.95-14.899 20-20.941 31.741-5.674 11.024-11.715 26.246-10.976 42.47 0.643 14.138 7.76 27.773 13.222 36.973 6.275 10.576 14.416 21.741 22.79 32.291 16.806 21.171 36.541 42.326 49.68 55.466l44.173-44.173c-11.952-11.952-29.981-31.309-44.928-50.134-7.504-9.453-13.738-18.157-17.997-25.334-2.87-4.838-3.984-7.578-4.387-8.57l-0.038-0.093c0.266-1.382 1.139-4.736 4.006-10.31 3.552-6.902 8.717-14.438 14.291-21.443 14.611-18.374 20.518-45.424 8.611-69.837l-59.914-122.808zM819.386 613.504c21.36 10.419 37.856 34.202 33.136 62.189-6.426 38.106-25.194 88.826-57.059 126.246-16.157 18.973-36.797 35.818-62.246 44.758-26.048 9.149-54.922 9.21-85.197-2.086-56.813-21.203-117.453-60.515-167.261-97.763-50.122-37.482-91.555-74.608-110.272-93.328l44.173-44.173c16.403 16.406 55.539 51.6 103.51 87.472 48.285 36.109 103.267 71.194 151.69 89.264 17.248 6.435 31.056 5.747 42.653 1.674 12.192-4.282 24.16-13.133 35.386-26.317 22.013-25.85 36.816-63.293 42.394-92.624l-121.094-59.075c-0.077-0.019-0.288-0.048-0.688 0.013-0.752 0.112-1.83 0.502-2.886 1.344-8.95 7.117-20 14.899-31.741 20.941-11.024 5.674-26.246 11.715-42.47 10.976-14.134-0.643-27.773-7.76-36.973-13.222-10.576-6.275-21.741-14.416-32.288-22.79-21.174-16.806-42.33-36.541-55.469-49.68l44.173-44.173c11.952 11.952 31.309 29.981 50.134 44.928 9.453 7.504 18.16 13.738 25.334 17.997 4.838 2.87 7.578 3.984 8.57 4.387l0.093 0.038c1.382-0.266 4.739-1.139 10.314-4.006 6.899-3.552 14.435-8.717 21.44-14.291 18.374-14.611 45.427-20.518 69.837-8.611l122.81 59.914z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone"],"defaultCode":59806,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1075,"name":"phone","prevSize":32,"id":163,"code":59806},"setIdx":2,"setId":2,"iconIdx":163},{"icon":{"paths":["M825.373 153.372c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-672 672c-12.497 12.496-32.758 12.496-45.255 0s-12.497-32.758 0-45.254l672-672zM575.613 569.069l-44.707 44.707c7.846 5.904 15.846 11.453 23.533 16.016 9.2 5.459 22.838 12.579 36.973 13.222 16.224 0.736 31.446-5.302 42.47-10.976 11.741-6.042 22.79-13.824 31.744-20.944 1.053-0.838 2.134-1.232 2.883-1.341 0.403-0.061 0.611-0.032 0.688-0.013l121.094 59.075c-5.578 29.331-20.381 66.771-42.39 92.621-11.229 13.187-23.197 22.038-35.389 26.32-11.597 4.074-25.402 4.762-42.653-1.677-48.422-18.070-103.405-53.152-151.69-89.261-14.026-10.49-27.299-20.922-39.469-30.842l-44.387 44.39c14.186 11.683 29.84 24.061 46.445 36.48 49.808 37.248 110.448 76.56 167.261 97.76 30.275 11.299 59.149 11.238 85.197 2.086 25.45-8.938 46.090-25.786 62.246-44.755 31.866-37.424 50.634-88.144 57.059-126.246 4.72-27.987-11.776-51.77-33.136-62.192l-122.81-59.91c-24.41-11.907-51.462-6-69.834 8.611-7.008 5.571-14.544 10.739-21.443 14.291-5.574 2.867-8.931 3.741-10.314 4.003l-0.093-0.038c-0.992-0.4-3.731-1.514-8.57-4.387-3.277-1.942-6.87-4.301-10.71-7.002zM313.636 589.683l44.389-44.387c-9.92-12.17-20.349-25.44-30.838-39.466-36.109-48.285-71.192-103.267-89.263-151.69-6.437-17.251-5.748-31.056-1.675-42.652 4.283-12.192 13.134-24.16 26.319-35.388 25.849-22.012 63.291-36.814 92.622-42.392l59.075 121.095c0.019 0.077 0.048 0.285-0.013 0.688-0.109 0.752-0.502 1.83-1.341 2.883-7.12 8.954-14.902 20.003-20.944 31.744-5.674 11.024-11.715 26.246-10.976 42.47 0.643 14.134 7.763 27.773 13.222 36.973 4.563 7.686 10.109 15.683 16.013 23.53l44.707-44.707c-2.701-3.837-5.056-7.434-7.002-10.707-2.87-4.838-3.984-7.578-4.387-8.57l-0.038-0.093c0.266-1.382 1.139-4.739 4.006-10.314 3.552-6.899 8.72-14.435 14.291-21.443 14.611-18.371 20.518-45.424 8.611-69.834l-59.91-122.809c-10.422-21.362-34.205-37.856-62.192-33.137-38.103 6.425-88.824 25.194-126.246 57.060-18.972 16.155-35.817 36.795-44.757 62.246-9.15 26.048-9.211 54.921 2.087 85.196 21.202 56.813 60.513 117.453 97.761 167.261 12.417 16.605 24.795 32.256 36.478 46.442z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["phone-disabled"],"defaultCode":59804,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1076,"name":"phone-disabled","prevSize":32,"id":164,"code":59804},"setIdx":2,"setId":2,"iconIdx":164},{"icon":{"paths":["M717.254 352l137.37-137.372c12.499-12.497 12.499-32.758 0-45.255-12.496-12.497-32.755-12.497-45.254 0l-137.373 137.373v-82.745c0-17.673-14.326-32-32-32-17.67 0-32 14.327-32 32v160c0 4.339 0.864 8.477 2.429 12.25 1.526 3.686 3.773 7.149 6.736 10.166 0.138 0.141 0.278 0.282 0.419 0.419 3.018 2.966 6.48 5.21 10.17 6.736 3.773 1.565 7.91 2.429 12.246 2.429h160c17.674 0 32-14.326 32-32s-14.326-32-32-32h-82.742z","M819.478 613.379l-122.88-59.84c-11.261-5.29-23.786-7.283-36.128-5.757-12.346 1.53-24.003 6.522-33.632 14.397-6.816 5.274-13.978 10.086-21.44 14.4-3.382 1.632-6.922 2.918-10.56 3.84-3.008-1.235-5.901-2.736-8.64-4.48-8.752-5.504-17.19-11.488-25.28-17.92-18.88-15.040-38.080-32-50.24-44.8s-29.76-32-44.8-50.24c-6.435-8.093-12.416-16.531-17.92-25.28-1.747-2.742-3.248-5.635-4.48-8.64 0.918-3.642 2.205-7.181 3.84-10.56 4.314-7.462 9.123-14.627 14.4-21.44 7.875-9.629 12.864-21.29 14.394-33.635 1.53-12.342-0.467-24.867-5.754-36.125l-59.84-122.881c-5.635-11.286-14.73-20.477-25.952-26.234-11.226-5.756-23.997-7.776-36.448-5.766-46.072 7.753-89.44 27.015-126.081 56-20.379 16.952-35.847 39.050-44.8 64-9.479 27.726-8.684 57.931 2.24 85.121 25.032 59.536 57.851 115.491 97.6 166.4 28.686 38.71 59.902 75.485 93.441 110.080 34.406 33.296 70.966 64.298 109.44 92.8 51.203 39.821 107.485 72.643 167.36 97.6 27.158 11.066 57.418 11.862 85.12 2.24 24.368-9.203 45.888-24.653 62.4-44.8 29.328-36.544 48.925-79.92 56.96-126.080 1.984-12.49-0.083-25.286-5.901-36.515-5.814-11.229-15.075-20.301-26.419-25.885zM747.798 761.219c-9.187 11.802-21.331 20.963-35.2 26.56-14.051 4.416-29.197 3.85-42.88-1.6-54.202-23.091-105.187-53.101-151.68-89.28-35.83-27.52-69.923-57.232-102.080-88.96-31.334-32.611-60.618-67.13-87.68-103.36-36.201-46.426-66.113-97.427-88.961-151.68-5.832-13.587-6.514-28.829-1.92-42.881 5.595-13.87 14.757-26.014 26.56-35.2 26.691-20.806 57.953-34.956 91.201-41.28l60.8 121.281c0.154 0.954 0.154 1.926 0 2.88-7.933 9.981-14.899 20.698-20.8 32-7.347 12.966-11.101 27.658-10.88 42.56 1.354 13.142 5.853 25.763 13.12 36.8 6.934 11.104 14.522 21.789 22.72 32 16.96 21.12 36.48 42.56 49.6 55.68s34.56 32 55.68 49.6c10.208 8.198 20.893 15.782 32 22.72 11.034 7.264 23.658 11.763 36.8 13.12 14.899 0.218 29.59-3.536 42.56-10.88 11.302-5.904 22.016-12.867 32-20.8 0.851-0.707 1.827-1.251 2.88-1.6l118.72 59.84c-6.509 33.811-21.11 65.542-42.56 92.48z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["phone-in"],"grid":0},"attrs":[{},{}],"properties":{"order":1078,"id":166,"name":"phone-in","prevSize":32,"code":59809},"setIdx":2,"setId":2,"iconIdx":165},{"icon":{"paths":["M428.346 199.399c17.542-17.543 45.984-17.543 63.53 0 17.542 17.543 17.542 45.986 0 63.53l-43.661 43.659 177.83 177.828 60.339-60.339c24.992-24.995 65.517-24.995 90.509 0l45.254 45.254-331.869 331.869-45.254-45.254c-24.992-24.995-24.992-65.517 0-90.509l60.339-60.339-177.827-177.83-43.661 43.661c-17.543 17.542-45.987 17.542-63.53 0s-17.543-45.987 0-63.53l208.001-207.999zM175.090 362.144c-42.537 42.538-42.537 111.501 0 154.038 42.001 42.003 109.771 42.531 152.42 1.587l87.334 87.334-15.075 15.075c-49.987 49.987-49.987 131.034 0 181.021l67.882 67.882c12.496 12.496 32.758 12.496 45.254 0l167.936-167.933 88.013 92.003c12.218 12.771 32.474 13.219 45.245 1.002 12.771-12.214 13.219-32.47 1.002-45.242l-88.995-93.030 163.923-163.923c12.499-12.496 12.499-32.758 0-45.254l-67.882-67.882c-49.987-49.987-131.030-49.987-181.018 0l-15.907 15.907-87.325-87.323c41.766-42.596 41.51-110.983-0.768-153.262-42.538-42.537-111.504-42.537-154.042 0l-207.998 208z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pin"],"defaultCode":59808,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1080,"name":"pin","prevSize":32,"id":168,"code":59808},"setIdx":2,"setId":2,"iconIdx":166},{"icon":{"paths":["M512.608 128.019c-72.378-1.376-144.906 25.78-199.307 80.524-54.654 54.999-89.301 136.056-89.301 239.464 0 80.234 44.5 174.87 97.546 252.806 53.066 77.965 120.829 148.157 176.141 175.821l15.194 7.6 14.81-8.326c217.158-122.154 272.31-333.882 272.31-427.898 0-101.731-27.923-181.776-80.179-236.932-52.346-55.248-125.296-81.503-207.213-83.060zM288 448.006c0-88.589 29.353-152.745 70.698-194.351 41.6-41.862 97.072-62.705 152.694-61.648 68.992 1.311 124.038 23.054 161.968 63.088 38.019 40.126 62.64 102.649 62.64 192.914 0 74.55-44.691 253.677-224.176 363.030-39.683-25.61-92.186-79.853-137.37-146.237-50.954-74.864-86.454-156.221-86.454-216.797zM544 416c0-17.674-14.326-32-32-32s-32 14.326-32 32c0 17.674 14.326 32 32 32s32-14.326 32-32zM608 416c0 53.021-42.979 96-96 96s-96-42.979-96-96c0-53.021 42.979-96 96-96s96 42.979 96 96z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["pin-map"],"defaultCode":59807,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1081,"name":"pin-map","prevSize":32,"id":169,"code":59807},"setIdx":2,"setId":2,"iconIdx":167},{"icon":{"paths":["M864 512c0-194.404-157.597-352-352-352s-352 157.596-352 352c0 194.403 157.596 352 352 352s352-157.597 352-352zM928 512c0 229.75-186.25 416-416 416s-416-186.25-416-416c0-229.75 186.25-416 416-416s416 186.25 416 416zM451.85 357.187l195.254 136.768c14.208 9.949 18.496 30.87 9.581 46.726-2.432 4.326-5.706 7.981-9.581 10.694l-195.254 136.768c-14.208 9.952-32.954 5.165-41.869-10.694-3.037-5.398-4.646-11.642-4.646-18.016v-273.536c0-18.723 13.597-33.898 30.371-33.898 5.709 0 11.306 1.798 16.144 5.187z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["play"],"defaultCode":59811,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1082,"name":"play","prevSize":32,"id":170,"code":59811},"setIdx":2,"setId":2,"iconIdx":168},{"icon":{"paths":["M512 928.003c229.75 0 416-186.25 416-416s-186.25-415.999-416-415.999c-229.75 0-416 186.25-416 415.999s186.25 416 416 416zM451.846 357.19l195.258 136.768c14.205 9.952 18.496 30.874 9.578 46.73-2.429 4.323-5.706 7.978-9.578 10.691l-195.258 136.768c-14.205 9.952-32.95 5.165-41.866-10.691-3.037-5.398-4.646-11.645-4.646-18.019v-273.536c0-18.72 13.597-33.894 30.368-33.894 5.712 0 11.309 1.795 16.144 5.184z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["play-filled"],"defaultCode":59810,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1083,"name":"play-filled","prevSize":32,"id":171,"code":59810},"setIdx":2,"setId":2,"iconIdx":169},{"icon":{"paths":["M325.686 430.88l224.49 224.49-126.118 126.118-224.491-224.49 126.12-126.118zM370.941 385.626l192.115-192.117 224.49 224.491-192.115 192.115-224.49-224.49zM585.683 125.627c-12.496-12.497-32.758-12.497-45.254 0l-408.745 408.745c-12.497 12.496-12.497 32.758 0 45.254l269.746 269.747c5.229 5.229 11.818 8.269 18.63 9.123v0.067h0.57c2.278 0.243 4.576 0.243 6.851 0h440.579c17.674 0 32-14.33 32-32 0-17.674-14.326-32.003-32-32.003h-366.566l353.936-353.933c12.496-12.496 12.496-32.758 0-45.254l-269.747-269.746z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["prune"],"defaultCode":59817,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1084,"name":"prune","prevSize":32,"id":172,"code":59817},"setIdx":2,"setId":2,"iconIdx":170},{"icon":{"paths":["M230.486 636.688c-14.92-9.472-34.694-5.056-44.167 9.862-9.473 14.922-5.057 34.694 9.862 44.166l298.666 189.632c10.47 6.646 23.837 6.646 34.304 0l298.669-189.632c14.918-9.472 19.334-29.245 9.862-44.166-9.475-14.918-29.248-19.334-44.166-9.862l-281.517 178.739-281.514-178.739zM186.319 494.848c9.473-14.922 29.247-19.334 44.167-9.862l281.514 178.739 281.517-178.739c14.918-9.472 34.691-5.059 44.166 9.862 9.472 14.918 5.056 34.694-9.862 44.166l-298.669 189.632c-10.467 6.646-23.834 6.646-34.304 0l-298.666-189.632c-14.92-9.472-19.335-29.248-9.862-44.166zM529.152 143.657l298.669 189.629c9.245 5.872 14.848 16.064 14.848 27.014 0 10.954-5.603 21.146-14.848 27.014l-298.669 189.632c-10.467 6.646-23.834 6.646-34.304 0l-298.666-189.632c-9.246-5.869-14.848-16.061-14.848-27.014 0-10.95 5.602-21.142 14.848-27.014l298.666-189.629c10.47-6.647 23.837-6.647 34.304 0zM273.035 360.301l238.965 151.725 238.966-151.725-238.966-151.724-238.965 151.724z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["queue"],"defaultCode":59818,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1085,"name":"queue","prevSize":32,"id":173,"code":59818},"setIdx":2,"setId":2,"iconIdx":171},{"icon":{"paths":["M161.352 800c-11.706 0-22.477-6.39-28.087-16.666s-5.161-22.79 1.169-32.64l112.304-174.694h-69.387c-17.673 0-32-14.326-32-32v-288c0-17.673 14.327-32 32-32h255.999c17.674 0 32 14.327 32 32v288c0 6.138-1.763 12.144-5.082 17.306l-143.999 224c-5.888 9.158-16.029 14.694-26.918 14.694h-128zM332.269 561.306l-112.304 174.694h51.916l129.469-201.398v-246.602h-191.999v224h96c11.706 0 22.479 6.39 28.085 16.666 5.61 10.275 5.162 22.79-1.168 32.64zM577.35 800c-11.706 0-22.477-6.39-28.086-16.666s-5.162-22.79 1.171-32.64l112.304-174.694h-69.389c-17.67 0-32-14.326-32-32v-288c0-17.673 14.33-32 32-32h256c17.674 0 32 14.327 32 32v288c0 6.138-1.763 12.144-5.082 17.306l-144 224c-5.888 9.158-16.029 14.694-26.918 14.694h-128zM748.269 561.306l-112.304 174.694h51.917l129.469-201.398v-246.602h-192v224h96c11.706 0 22.48 6.39 28.086 16.666 5.61 10.275 5.162 22.79-1.168 32.64z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["quote"],"defaultCode":59819,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1086,"name":"quote","prevSize":32,"id":174,"code":59819},"setIdx":2,"setId":2,"iconIdx":172},{"icon":{"paths":["M800 560c0 176.73-143.27 320-320 320-176.731 0-320-143.27-320-320s143.269-320 320-320v-64c-212.077 0-384 171.923-384 384s171.923 384 384 384c212.077 0 384-171.923 384-384 0-10.778-0.445-21.45-1.315-32h-64.266c1.046 10.525 1.581 21.2 1.581 32zM800 128c0-17.673-14.326-32-32-32s-32 14.327-32 32v112h-112c-17.674 0-32 14.327-32 32s14.326 32 32 32h112v112c0 17.674 14.326 32 32 32s32-14.326 32-32v-112h112c17.674 0 32-14.327 32-32s-14.326-32-32-32h-112v-112zM384 528c35.347 0 64-28.653 64-64s-28.653-64-64-64c-35.347 0-64 28.653-64 64s28.653 64 64 64zM640 464c0 35.347-28.653 64-64 64s-64-28.653-64-64c0-35.347 28.653-64 64-64s64 28.653 64 64zM329.805 605.075c-10.451-14.25-30.477-17.331-44.728-6.88s-17.333 30.477-6.882 44.73c37.658 51.35 77.754 84.624 119.178 102.662 41.741 18.179 82.797 19.99 120.362 11.651 73.469-16.307 132.211-70.87 164.070-114.314 10.451-14.253 7.37-34.278-6.88-44.73-14.253-10.451-34.278-7.37-44.73 6.88-26.81 36.557-73.664 77.994-126.33 89.686-25.501 5.661-52.643 4.474-80.938-7.85-28.608-12.461-60.381-37.187-93.123-81.837z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["reaction-add"],"defaultCode":59820,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1087,"name":"reaction-add","prevSize":32,"id":175,"code":59820},"setIdx":2,"setId":2,"iconIdx":173},{"icon":{"paths":["M832 512c0-176.73-143.27-320-320-320s-320 143.27-320 320c0 176.73 143.27 320 320 320s320-143.27 320-320zM896 512c0 212.077-171.923 384-384 384s-384-171.923-384-384c0-212.077 171.923-384 384-384s384 171.923 384 384zM512 704c-106.038 0-192-85.962-192-192s85.962-192 192-192c106.038 0 192 85.962 192 192s-85.962 192-192 192z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["record"],"defaultCode":59821,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1088,"name":"record","prevSize":32,"id":176,"code":59821},"setIdx":2,"setId":2,"iconIdx":174},{"icon":{"paths":["M896 512h-63.984c0-175.414-145.754-320-328.518-320-115.27 0-215.818 57.513-274.362 144h110.768c17.674 0 32 14.326 32 32s-14.326 32-32 32h-179.904c-17.673 0-32-14.326-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v102.32c71.751-91.401 184.589-150.32 311.498-150.32 216.781 0 392.502 171.923 392.502 384 0 1.114 0.010 2.227 0 3.338v-3.338z","M127.997 512h63.986c0 175.414 145.751 320 328.519 320 115.27 0 215.818-57.514 274.358-144h-110.768c-17.67 0-32-14.326-32-32s14.33-32 32-32h179.907c17.67 0 32 14.326 32 32v192c0 17.674-14.33 32-32 32-17.674 0-32-14.326-32-32v-102.32c-71.754 91.402-184.592 150.32-311.498 150.32-216.782 0-392.505-171.923-392.505-384 0-1.082-0.009-2.166 0-3.245v3.245z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["refresh"],"defaultCode":59822,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1089,"name":"refresh","prevSize":32,"id":177,"code":59822},"setIdx":2,"setId":2,"iconIdx":175},{"icon":{"paths":["M565.802 233.862l-97.261 97.261h-187.521l-0.456 0.003c-14.696 0.208-28.717 6.186-39.042 16.637l-97.095 96.797-0.048 0.048c-7.165 7.174-12.248 16.157-14.707 25.994-2.459 9.834-2.202 20.154 0.745 29.856 2.946 9.699 8.471 18.419 15.984 25.226 7.506 6.8 16.746 11.443 26.678 13.424l125.65 25.19c5.103 1.024 10.166 0.771 14.859-0.538l162.866 162.867c1.987 1.987 4.17 3.654 6.483 5.011l22.88 114.128c1.981 9.936 6.618 19.146 13.418 26.653 6.81 7.514 15.526 13.037 25.229 15.984s20.019 3.203 29.856 0.746c9.837-2.461 18.819-7.542 25.994-14.707l96.842-97.146c10.451-10.323 16.432-24.346 16.64-39.040l0.003-0.454v-193.802c0-2.893-0.384-5.693-1.104-8.358l77.443-77.44c110.522-110.525 110.474-223.191 103.152-273.759-1.862-13.592-8.122-26.204-17.824-35.908s-22.317-15.962-35.907-17.823c-50.57-7.321-163.235-7.371-273.757 103.151zM611.056 279.117c92.138-92.138 182.144-90.373 218.947-85.121 5.254 36.804 7.018 126.811-85.12 218.948l-245.798 245.802-133.83-133.827 245.802-245.802zM404.541 395.123l-104.222 104.221-100.071-20.064 84.42-84.157h119.873zM542.89 705.446l106.909-106.906v135.61l-84.16 84.422-22.266-111.062c-0.138-0.698-0.301-1.386-0.483-2.064z","M286.325 699.699c15.297-8.851 20.524-28.426 11.674-43.725-8.85-15.296-28.426-20.522-43.723-11.674-49.486 28.63-72.438 77.786-83.25 115.523-5.52 19.267-8.252 36.813-9.619 49.539-0.687 6.397-1.037 11.661-1.217 15.424-0.090 1.885-0.137 3.402-0.162 4.499l-0.023 1.334-0.004 0.422-0.001 0.15v0.083c0 8.486 3.372 16.65 9.372 22.65 6.001 6.003 14.14 9.373 22.628 9.373v-32c0 32 0.037 32 0.048 32h0.208l0.424-0.003 1.333-0.022c1.099-0.026 2.614-0.074 4.498-0.163 3.764-0.179 9.029-0.528 15.425-1.216 12.727-1.366 30.272-4.099 49.54-9.619 37.739-10.813 86.892-33.763 115.523-83.251 8.851-15.296 3.622-34.87-11.674-43.722s-34.874-3.626-43.725 11.674c-16.669 28.813-47.164 45.011-77.751 53.776-6.095 1.744-12.005 3.139-17.55 4.25 1.111-5.546 2.505-11.456 4.251-17.549 8.763-30.589 24.961-61.085 53.775-77.754zM192 831.299l-32-0.022c0 0.013 0 0.022 32 0.022z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["rocket"],"defaultCode":59816,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1090,"id":178,"name":"rocket","prevSize":32,"code":59816},"setIdx":2,"setId":2,"iconIdx":176},{"icon":{"paths":["M713.718 450.362c0-142.689-115.824-258.362-258.701-258.362-142.878 0-258.704 115.673-258.704 258.362 0 142.691 115.826 258.365 258.704 258.365 142.877 0 258.701-115.674 258.701-258.365zM659.302 699.965c-55.645 45.475-126.774 72.762-204.285 72.762-178.271 0-322.788-144.326-322.788-322.365 0-178.035 144.517-322.362 322.788-322.362 178.269 0 322.787 144.327 322.787 322.362 0 77.408-27.318 148.442-72.854 204.013l186.838 186.592c12.608 12.589 12.608 33.002 0 45.59-12.605 12.589-33.043 12.589-45.648 0l-186.838-186.592z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["search"],"defaultCode":59823,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1091,"name":"search","prevSize":32,"id":179,"code":59823},"setIdx":2,"setId":2,"iconIdx":177},{"icon":{"paths":["M878.022 192.974c7.85 9.521 9.526 22.708 4.31 33.891l-298.669 640.002c-5.69 12.195-18.403 19.526-31.811 18.342-13.405-1.184-24.637-10.627-28.106-23.632l-81.619-306.070-285.772-142.886c-11.978-5.987-18.959-18.8-17.498-32.112s11.056-24.307 24.048-27.552l682.665-170.668c11.974-2.993 24.598 1.165 32.451 10.686zM505.821 545.968l57.082 214.051 233.027-499.35-533.58 133.395 203.606 101.802 69.51-52.131c14.141-10.605 34.198-7.741 44.8 6.4 10.605 14.138 7.741 34.195-6.4 44.8l-68.045 51.034z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["send"],"defaultCode":59825,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1092,"name":"send","prevSize":32,"id":180,"code":59825},"setIdx":2,"setId":2,"iconIdx":178},{"icon":{"paths":["M891.494 238.96l-297.475 637.446c-16.854 36.115-69.622 31.459-79.891-7.050l-66-247.498 151.248-189.059-219.994 109.997-226.833-113.418c-35.43-17.715-29.696-69.949 8.733-79.555l681.197-170.3c34.842-8.71 64.202 26.892 49.014 59.436z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["send-filled"],"defaultCode":59824,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1093,"name":"send-filled","prevSize":32,"id":181,"code":59824},"setIdx":2,"setId":2,"iconIdx":179},{"icon":{"paths":["M421.334 256c0-44.183-35.818-80-80-80s-80 35.817-80 80c0 44.183 35.817 80 80 80s80-35.817 80-80zM465.302 288c-14.211 55.206-64.326 96-123.968 96-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.327-32-32s14.327-32 32-32h89.367c14.209-55.207 64.324-96 123.968-96 59.642 0 109.757 40.793 123.968 96h430.698c17.674 0 32 14.327 32 32s-14.326 32-32 32h-430.698zM96 768c0-17.674 14.327-32 32-32h89.367c14.209-55.206 64.324-96 123.968-96 60.781 0 111.67 42.365 124.742 99.181 4.208-2.038 8.934-3.181 13.923-3.181h416c17.674 0 32 14.326 32 32s-14.326 32-32 32h-416c-4.989 0-9.715-1.142-13.923-3.181-13.072 56.816-63.962 99.181-124.742 99.181-59.643 0-109.758-40.794-123.968-96h-89.367c-17.673 0-32-14.326-32-32zM341.334 848c44.182 0 80-35.818 80-80s-35.818-80-80-80c-44.183 0-80 35.818-80 80s35.817 80 80 80zM796.029 543.757c-14.122 55.331-64.298 96.243-124.029 96.243s-109.904-40.912-124.029-96.243c-1.302 0.16-2.627 0.243-3.971 0.243h-416c-17.673 0-32-14.326-32-32s14.327-32 32-32h416c1.344 0 2.669 0.083 3.971 0.243 14.125-55.331 64.298-96.243 124.029-96.243s109.907 40.912 124.029 96.243c1.302-0.16 2.627-0.243 3.971-0.243h96c17.674 0 32 14.326 32 32s-14.326 32-32 32h-96c-1.344 0-2.669-0.083-3.971-0.243zM752 512c0-44.182-35.818-80-80-80s-80 35.818-80 80c0 44.182 35.818 80 80 80s80-35.818 80-80z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["settings"],"defaultCode":59826,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1094,"name":"settings","prevSize":32,"id":182,"code":59826},"setIdx":2,"setId":2,"iconIdx":180},{"icon":{"paths":["M690.176 301.708c11.645-11.977 11.645-31.396 0-43.374l-149.091-153.351c-11.645-11.977-30.525-11.977-42.17 0l-149.091 153.351c-11.645 11.977-11.645 31.397 0 43.374s30.525 11.978 42.17 0l98.189-100.993v401.343c0 16.938 13.35 30.669 29.818 30.669s29.818-13.731 29.818-30.669v-401.343l98.189 100.993c11.645 11.978 30.525 11.978 42.17 0z","M221.818 379.274h149.091v59.635h-119.272v387.635h536.728v-387.635h-119.274v-59.635h149.091c16.467 0 29.818 13.35 29.818 29.818v447.274c0 16.467-13.35 29.818-29.818 29.818h-596.364c-16.468 0-29.818-13.35-29.818-29.818v-447.274c0-16.467 13.35-29.818 29.818-29.818z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["share"],"defaultCode":59827,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1095,"name":"share","prevSize":32,"id":183,"code":59827},"setIdx":2,"setId":2,"iconIdx":181},{"icon":{"paths":["M502.627 142.69c12.915-3.408 26.509-3.289 39.363 0.345l245.194 69.317c29.165 8.245 51.254 33.818 53.504 65.14 24.506 341.145-184.394 520.422-272.611 580.214-33.053 22.403-75.28 22.474-108.416 0.259-88.758-59.504-300.1-238.589-276.51-579.794 2.205-31.89 24.96-57.772 54.753-65.633l264.724-69.849zM524.579 204.621c-1.837-0.519-3.779-0.536-5.622-0.049l-264.725 69.849c-4.4 1.161-6.999 4.775-7.233 8.165-21.305 308.166 168.214 468.531 248.301 522.218 11.507 7.715 25.434 7.677 36.87-0.077 79.379-53.798 266.835-214.288 244.685-522.649-0.243-3.358-2.787-6.925-7.082-8.139l-245.194-69.317z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["set-as-moderator"],"defaultCode":59661,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1096,"name":"shield","prevSize":32,"id":184,"code":59661},"setIdx":2,"setId":2,"iconIdx":182},{"icon":{"paths":["M513.302 142.705c12.915-3.408 26.509-3.289 39.36 0.345l245.197 69.318c29.165 8.245 51.254 33.818 53.504 65.14 24.506 341.142-184.397 520.422-272.611 580.214-33.053 22.403-75.28 22.47-108.416 0.259-88.762-59.504-300.101-238.589-276.511-579.794 2.205-31.89 24.96-57.772 54.753-65.633l264.725-69.849zM535.251 204.637c-1.834-0.519-3.776-0.536-5.622-0.050l-264.723 69.849c-4.4 1.161-6.999 4.775-7.234 8.164-21.305 308.164 168.216 468.532 248.299 522.218 11.507 7.715 25.434 7.677 36.874-0.077 79.379-53.798 266.832-214.288 244.682-522.65-0.24-3.358-2.784-6.925-7.078-8.139l-245.197-69.317z","M490.672 337.334c-19.76 4.672-47.245 12.31-81.149 24.554 20.81 108.771 53.219 187.014 81.149 238.832v-263.386zM492.867 271.316c33.77-6.898 61.805 19.742 61.805 51.125v360.963c0 17.024-10.333 31.747-25.642 37.52-15.67 5.91-33.779 1.331-44.861-12.675-32.656-41.267-106.323-152.95-141.19-354.563-3.242-18.746 7.066-37.695 25.328-44.726 56.186-21.63 99.094-32.442 124.56-37.644z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["shield"],"defaultCode":59829,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1097,"name":"shield-alt","prevSize":32,"id":185,"code":59829},"setIdx":2,"setId":2,"iconIdx":183},{"icon":{"paths":["M664.083 405.072c11.638-13.299 10.288-33.517-3.011-45.155s-33.517-10.288-45.155 3.011l-125.251 143.142-39.917-45.619c-11.638-13.299-31.853-14.646-45.155-3.011-13.299 11.638-14.646 31.856-3.008 45.155l64 73.142c6.077 6.944 14.854 10.928 24.080 10.928 9.229 0 18.006-3.984 24.083-10.928l149.334-170.666z","M541.99 143.050c-12.854-3.634-26.448-3.753-39.363-0.345l-264.724 69.849c-29.793 7.861-52.548 33.743-54.753 65.633-23.589 341.205 187.752 520.29 276.51 579.794 33.136 22.211 75.363 22.144 108.416-0.259 88.218-59.792 297.117-239.072 272.611-580.214-2.25-31.321-24.339-56.895-53.504-65.14l-245.194-69.318zM518.957 204.587c1.843-0.487 3.786-0.47 5.622 0.049l245.194 69.318c4.294 1.214 6.838 4.781 7.082 8.139 22.15 308.362-165.306 468.851-244.685 522.65-11.437 7.754-25.363 7.792-36.87 0.077-80.086-53.686-269.606-214.054-248.301-522.218 0.234-3.389 2.833-7.004 7.233-8.164l264.725-69.849z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2}]},"tags":["shield-check"],"defaultCode":59828,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1098,"name":"shield-check","prevSize":32,"id":186,"code":59828},"setIdx":2,"setId":2,"iconIdx":184},{"icon":{"paths":["M778.64 213.336c-17.674 0-32 14.327-32 32v533.333c0 17.674 14.326 32 32 32s32-14.326 32-32v-533.333c0-17.673-14.326-32-32-32z","M600.87 341.334c-17.674 0-32 14.33-32 32v405.334c0 17.674 14.326 32 32 32s32-14.326 32-32v-405.334c0-17.67-14.326-32-32-32z","M423.104 810.669c-17.674 0-32-14.326-32-32v-277.334c0-17.67 14.326-32 32-32 17.67 0 32 14.33 32 32v277.334c0 17.674-14.33 32-32 32z","M245.333 597.334c-17.673 0-32 14.33-32 32v149.334c0 17.674 14.327 32 32 32s32-14.326 32-32v-149.334c0-17.67-14.327-32-32-32z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["signal"],"defaultCode":59830,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1099,"name":"signal","prevSize":32,"id":187,"code":59830},"setIdx":2,"setId":2,"iconIdx":185},{"icon":{"paths":["M772.986 470.432h-40.186c-1.104-12.381-10.090-19.757-26.454-19.757-16.278 0-24.416 6.867-24.502 16.365-0.339 10.342 9.667 15.6 25.437 18.992l14.922 3.389c34.253 7.546 52.989 24.502 53.158 52.227-0.17 32.982-25.773 52.566-69.014 52.566-43.661 0-71.894-19.414-72.403-60.026h40.186c0.934 16.701 13.142 25.35 31.709 25.35 16.874 0 26.794-7.376 26.963-17.974-0.17-9.75-8.733-14.922-27.811-19.331l-18.141-4.24c-30.016-6.867-48.496-21.706-48.413-48.070-0.253-32.304 28.317-53.923 67.997-53.923 40.355 0 66.214 21.958 66.554 54.432z","M354.858 470.432h40.186c-0.339-32.474-26.198-54.432-66.554-54.432-39.679 0-68.251 21.619-67.996 53.923-0.085 26.365 18.398 41.203 48.411 48.070l18.145 4.24c19.075 4.41 27.638 9.581 27.808 19.331-0.17 10.598-10.090 17.974-26.96 17.974-18.569 0-30.778-8.65-31.71-25.35h-40.187c0.509 40.611 28.741 60.026 72.403 60.026 43.242 0 68.845-19.584 69.014-52.566-0.17-27.725-18.906-44.682-53.158-52.227l-14.922-3.389c-15.77-3.392-25.774-8.65-25.435-18.992 0.085-9.498 8.224-16.365 24.501-16.365 16.365 0 25.35 7.376 26.454 19.757z","M418.614 418.374v173.635h40.864v-107.251h1.443l41.712 106.15h26.112l41.715-105.555h1.44v106.656h40.867v-173.635h-51.974l-44.086 107.504h-2.035l-44.086-107.504h-51.971z","M864 192c16.973 0 33.251 6.743 45.254 18.745s18.746 28.281 18.746 45.255v635.296c0 12.186-3.478 24.122-10.032 34.397-6.55 10.278-15.898 18.474-26.947 23.619-11.046 5.146-23.334 7.027-35.418 5.43-12.083-1.6-23.456-6.614-32.787-14.458l-128.81-108.285h-534.006c-16.974 0-33.252-6.742-45.255-18.746s-18.745-28.282-18.745-45.254v-512c0-16.974 6.743-33.252 18.745-45.255s28.281-18.745 45.255-18.745h704zM864 256h-704v512h534.006c15.066 0 29.648 5.315 41.181 15.011l128.813 108.285v-635.296z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["sms"],"defaultCode":59772,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1100,"name":"sms","prevSize":32,"id":188,"code":59772},"setIdx":2,"setId":2,"iconIdx":186},{"icon":{"paths":["M919.258 667.229c12.605-12.253 12.877-32.394 0.605-44.982-12.269-12.589-32.435-12.858-45.040-0.605l-106.112 103.155v-500.8c0-17.568-14.259-31.81-31.853-31.81-17.59 0-31.85 14.242-31.85 31.81v500.8l-106.115-103.155c-12.605-12.253-32.768-11.984-45.040 0.605-12.269 12.589-11.997 32.73 0.608 44.982l160.179 155.718c12.368 12.019 32.070 12.019 44.435 0l160.182-155.718zM560.659 333.667c17.59 0 31.85-14.243 31.85-31.811s-14.259-31.809-31.85-31.809h-432.49c-17.591 0-31.852 14.242-31.852 31.809s14.26 31.811 31.852 31.811h432.49zM464.55 536.099c17.59 0 31.85-14.243 31.85-31.811 0-17.565-14.259-31.808-31.85-31.808h-336.381c-17.591 0-31.852 14.24-31.852 31.808s14.26 31.811 31.852 31.811h336.381zM384.458 722.96c17.594 0 31.853-14.24 31.853-31.808s-14.259-31.811-31.853-31.811h-256.289c-17.591 0-31.852 14.243-31.852 31.811s14.26 31.808 31.852 31.808h256.289z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["sort"],"defaultCode":59832,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1101,"name":"sort","prevSize":32,"id":189,"code":59832},"setIdx":2,"setId":2,"iconIdx":187},{"icon":{"paths":["M289.362 192c13.364 0 25.321 8.305 29.987 20.829l96.001 257.699c6.17 16.56-2.256 34.986-18.816 41.155-16.563 6.17-34.989-2.253-41.158-18.816l-20.477-54.963h-91.074l-20.476 54.963c-6.17 16.563-24.597 24.986-41.158 18.816s-24.986-24.595-18.816-41.155l96-257.699c4.666-12.524 16.622-20.829 29.987-20.829zM311.058 373.904l-21.695-58.238-21.695 58.238h43.391z","M522.131 626.435c-12.154 12.829-11.606 33.082 1.222 45.238l160 151.587c12.342 11.693 31.674 11.693 44.016 0l160-151.587c12.832-12.157 13.376-32.41 1.222-45.238s-32.41-13.376-45.238-1.222l-105.99 100.419v-501.632c0-17.673-14.326-32-32-32s-32 14.327-32 32v501.632l-105.994-100.419c-12.829-12.154-33.082-11.606-45.238 1.222z","M193.362 570.947c-17.673 0-32 14.326-32 32 0 17.67 14.327 32 32 32h116.145l-139.065 142.73c-8.979 9.216-11.565 22.915-6.564 34.771 5.001 11.853 16.617 19.562 29.484 19.562h192.001c17.674 0 32-14.326 32-32s-14.326-32-32-32h-116.146l139.064-142.733c8.979-9.216 11.565-22.915 6.563-34.768-4.998-11.856-16.614-19.562-29.482-19.562h-192.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["sort-az"],"defaultCode":59831,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1102,"name":"sort-az","prevSize":32,"id":190,"code":59831},"setIdx":2,"setId":2,"iconIdx":188},{"icon":{"paths":["M472.618 173.508c18.166-58.554 100.454-60.461 121.322-2.812l69.821 192.91h195.44c57.872 0 86.026 70.611 43.994 110.336l-147.888 139.782 53.386 217.363c14.17 57.696-51.251 101.805-99.536 67.11l-177.741-127.709-177.741 127.709c-48.283 34.691-113.703-9.414-99.533-67.11l53.209-216.64-157.591-139.024c-44.179-38.973-16.577-111.818 42.37-111.818h221.513l58.976-190.098zM603.574 385.334l-69.824-192.91-58.976 190.098c-8.304 26.758-33.085 45.002-61.133 45.002h-221.513l157.59 139.021c17.837 15.731 25.456 40.048 19.789 63.13l-53.209 216.643 177.74-127.709c22.33-16.045 52.426-16.045 74.755 0l177.738 127.709-53.386-217.363c-5.478-22.317 1.456-45.856 18.166-61.648l147.888-139.782h-195.44c-26.957 0-51.024-16.87-60.186-42.189z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["star"],"defaultCode":59834,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1103,"name":"star","prevSize":32,"id":191,"code":59834},"setIdx":2,"setId":2,"iconIdx":189},{"icon":{"paths":["M593.939 170.244c-20.867-57.726-103.155-55.816-121.322 2.815l-58.976 190.348h-221.513c-58.947 0-86.549 72.944-42.37 111.968l157.591 139.206-53.209 216.928c-14.17 57.77 51.25 101.936 99.533 67.197l177.741-127.875 177.741 127.875c48.285 34.739 113.706-9.427 99.536-67.197l-53.386-217.651 147.888-139.968c42.032-39.779 13.878-110.483-43.99-110.483h-195.443l-69.821-193.164z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["star-filled"],"defaultCode":59833,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1104,"name":"star-filled","prevSize":32,"id":192,"code":59833},"setIdx":2,"setId":2,"iconIdx":190},{"icon":{"paths":["M512 896c-212.077 0-384-171.923-384-384s171.923-384 384-384c212.077 0 384 171.923 384 384s-171.923 384-384 384zM565.334 288c0-29.455-23.878-53.333-53.334-53.333s-53.334 23.878-53.334 53.333v249.632l180.016 144.013c23.002 18.403 56.563 14.672 74.963-8.326 18.403-23.002 14.672-56.563-8.326-74.963l-139.984-111.987v-198.368z"],"attrs":[{"fill":"rgb(243, 190, 8)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":3}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":2}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":3}]},"tags":["status-away"],"defaultCode":59741,"grid":0},"attrs":[{"fill":"rgb(243, 190, 8)"}],"properties":{"order":1105,"name":"status-away","prevSize":32,"id":193,"code":59741},"setIdx":2,"setId":2,"iconIdx":191},{"icon":{"paths":["M512 896c-212.077 0-384-171.923-384-384s171.923-384 384-384c212.077 0 384 171.923 384 384s-171.923 384-384 384zM384 458.666c-29.456 0-53.334 23.875-53.334 53.331s23.878 53.334 53.334 53.334h256c29.456 0 53.334-23.878 53.334-53.334s-23.878-53.331-53.334-53.331h-256z"],"attrs":[{"fill":"rgb(245, 69, 92)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":6}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":6}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":8}]},"tags":["status-busy"],"defaultCode":59742,"grid":0},"attrs":[{"fill":"rgb(245, 69, 92)"}],"properties":{"order":1106,"name":"status-busy","prevSize":32,"id":194,"code":59742},"setIdx":2,"setId":2,"iconIdx":192},{"icon":{"paths":["M512 896c212.077 0 384-171.923 384-384s-171.923-384-384-384c-212.077 0-384 171.923-384 384s171.923 384 384 384zM554.774 298.667v298.668c0 23.562-19.101 42.666-42.666 42.666s-42.669-19.104-42.669-42.666v-298.668c0-23.564 19.104-42.667 42.669-42.667s42.666 19.102 42.666 42.667zM554.774 725.334c0 23.562-19.101 42.666-42.666 42.666s-42.669-19.104-42.669-42.666c0-23.565 19.104-42.669 42.669-42.669s42.666 19.104 42.666 42.669z"],"attrs":[{"fill":"rgb(243, 140, 57)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":5}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":7}]},"tags":["status-disabled"],"defaultCode":59837,"grid":0},"attrs":[{"fill":"rgb(243, 140, 57)"}],"properties":{"order":1107,"id":195,"name":"status-disabled","prevSize":32,"code":59837},"setIdx":2,"setId":2,"iconIdx":193},{"icon":{"paths":["M888.691 586.941l-125.568-24.838c3.187-16.102 4.877-32.842 4.877-50.102s-1.69-34-4.877-50.102l125.568-24.838c4.794 24.237 7.309 49.296 7.309 74.941s-2.515 50.704-7.309 74.941zM831.322 298.644l-106.365 71.209c-18.726-27.971-42.838-52.083-70.81-70.81l71.21-106.364c41.875 28.035 77.93 64.089 105.965 105.965zM586.941 135.309l-24.838 125.566c-16.102-3.185-32.842-4.876-50.102-4.876s-34 1.69-50.102 4.876l-24.838-125.566c24.237-4.795 49.296-7.309 74.941-7.309s50.704 2.514 74.941 7.309zM298.644 192.679l71.209 106.364c-27.971 18.727-52.083 42.839-70.81 70.81l-106.364-71.209c28.035-41.876 64.089-77.93 105.965-105.964zM135.309 437.059c-4.795 24.237-7.309 49.296-7.309 74.941s2.514 50.704 7.309 74.941l125.566-24.838c-3.185-16.102-4.876-32.842-4.876-50.102s1.69-34 4.876-50.102l-125.566-24.838zM192.679 725.357l106.364-71.21c18.727 27.971 42.839 52.083 70.81 70.81l-71.209 106.365c-41.876-28.035-77.93-64.090-105.964-105.965zM437.059 888.691l24.838-125.568c16.102 3.187 32.842 4.877 50.102 4.877s34-1.69 50.102-4.877l24.838 125.568c-24.237 4.794-49.296 7.309-74.941 7.309s-50.704-2.515-74.941-7.309zM725.357 831.322l-71.21-106.365c27.971-18.726 52.083-42.838 70.81-70.81l106.365 71.21c-28.035 41.875-64.090 77.93-105.965 105.965z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["status-loading"],"defaultCode":59743,"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":1108,"name":"status-loading","prevSize":32,"id":196,"code":59743},"setIdx":2,"setId":2,"iconIdx":194},{"icon":{"paths":["M512 789.334c-153.168 0-277.333-124.166-277.333-277.334s124.165-277.333 277.333-277.333c153.168 0 277.334 124.165 277.334 277.333s-124.166 277.334-277.334 277.334zM512 896c212.077 0 384-171.923 384-384s-171.923-384-384-384c-212.077 0-384 171.923-384 384s171.923 384 384 384z"],"attrs":[{"fill":"rgb(158, 162, 168)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":7}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":7}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":9}]},"tags":["status-offline"],"defaultCode":59744,"grid":0},"attrs":[{"fill":"rgb(158, 162, 168)"}],"properties":{"order":1109,"name":"status-offline","prevSize":32,"id":197,"code":59744},"setIdx":2,"setId":2,"iconIdx":195},{"icon":{"paths":["M896 512c0 212.077-171.923 384-384 384s-384-171.923-384-384c0-212.077 171.923-384 384-384s384 171.923 384 384z"],"attrs":[{"fill":"rgb(45, 224, 165)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":4}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":3}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":5}]},"tags":["status-online"],"defaultCode":59745,"grid":0},"attrs":[{"fill":"rgb(45, 224, 165)"}],"properties":{"order":1110,"name":"status-online","prevSize":32,"id":198,"code":59745},"setIdx":2,"setId":2,"iconIdx":196},{"icon":{"paths":["M511.997 224c-114.163 0-179.555 64.46-179.555 128v0.253c-0.061 7.453 1.072 14.867 3.354 21.962 5.411 16.826-3.84 34.851-20.666 40.259-16.825 5.411-34.85-3.84-40.261-20.666-4.357-13.546-6.527-27.702-6.428-41.933 0.081-113.124 110.343-191.875 243.556-191.875 103.597 0 190.97 46.311 226.886 120.071 7.738 15.889 1.13 35.043-14.762 42.78-15.888 7.738-35.043 1.13-42.781-14.761-22.259-45.713-82.714-84.090-169.344-84.090z","M128 512c0-17.674 14.327-32 32-32h392.893c0.467-0.010 0.938-0.010 1.408 0h309.699c17.674 0 32 14.326 32 32s-14.326 32-32 32h-160.432c38.198 29.328 64.432 70.438 64.432 128.003 0 57.2-32.512 105.965-79.008 139.178-46.557 33.254-109.235 52.822-176.992 52.822s-130.435-19.568-176.992-52.822c-46.495-33.213-79.008-81.978-79.008-139.178 0-17.674 14.327-32 32-32s32 14.326 32 32c0 31.168 17.632 62.4 52.208 87.098 34.515 24.653 83.837 40.902 139.792 40.902s105.277-16.25 139.792-40.902c34.576-24.698 52.208-55.93 52.208-87.098 0-35.558-15.216-59.581-42.134-79.283-27.824-20.368-67.005-35.082-112.88-48.72h-388.986c-17.673 0-32-14.326-32-32z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124319081245699212911624514522416519902101":[{},{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{},{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{},{}]},"tags":["strike"],"defaultCode":59846,"grid":0},"attrs":[{},{}],"properties":{"order":1111,"name":"strike","prevSize":32,"id":199,"code":59846},"setIdx":2,"setId":2,"iconIdx":197},{"icon":{"paths":["M481.35 117.336c0-17.673 14.326-32 32-32s32 14.327 32 32v106.667c0 17.673-14.326 32-32 32s-32-14.327-32-32v-106.667zM771.392 214.631c12.496-12.497 32.758-12.497 45.254 0s12.496 32.758 0 45.255l-75.411 75.413c-12.499 12.496-32.758 12.496-45.254 0-12.499-12.496-12.499-32.759 0-45.255l75.411-75.412zM336.73 694.63c-12.499-12.496-32.759-12.496-45.256 0l-75.495 75.498c-12.497 12.496-12.497 32.755 0 45.254 12.497 12.496 32.758 12.496 45.255 0l75.496-75.498c12.496-12.496 12.496-32.755 0-45.254zM481.35 800.003c0-17.674 14.326-32 32-32s32 14.326 32 32v106.669c0 17.67-14.326 32-32 32s-32-14.33-32-32v-106.669zM213.352 212.001c-12.497 12.497-12.497 32.758 0 45.255l75.349 75.348c12.497 12.496 32.758 12.496 45.254 0 12.499-12.496 12.496-32.757 0-45.254l-75.348-75.349c-12.497-12.497-32.758-12.497-45.255 0zM695.978 739.885c-12.496-12.496-12.496-32.758 0-45.254 12.499-12.496 32.758-12.496 45.254 0l75.331 75.328c12.496 12.496 12.496 32.758 0 45.254-12.499 12.496-32.758 12.496-45.258 0l-75.328-75.328zM87.751 512.003c0 17.674 14.327 32 32 32h106.667c17.673 0 32-14.326 32-32s-14.327-32-32-32h-106.667c-17.673 0-32 14.326-32 32zM801.35 544.003c-17.674 0-32-14.326-32-32s14.326-32 32-32h106.669c17.67 0 32 14.326 32 32s-14.33 32-32 32h-106.669zM668.17 512c0-85.504-69.315-154.816-154.819-154.816-85.507 0-154.819 69.312-154.819 154.816 0 85.507 69.312 154.819 154.819 154.819 85.504 0 154.819-69.312 154.819-154.819zM726.682 512c0 117.821-95.51 213.334-213.331 213.334s-213.335-95.514-213.335-213.334c0-117.821 95.514-213.332 213.335-213.332s213.331 95.511 213.331 213.332z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["sun"],"defaultCode":59847,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1112,"name":"sun","prevSize":32,"id":200,"code":59847},"setIdx":2,"setId":2,"iconIdx":198},{"icon":{"paths":["M930.704 512c0 229.75-186.25 416-416 416s-415.999-186.25-415.999-416c0-229.75 186.25-416 415.999-416s416 186.25 416 416zM570.49 859.603l-41.827-156.102c-4.611 0.33-9.264 0.499-13.958 0.499-4.57 0-9.101-0.16-13.594-0.474l-41.837 156.134c18.058 2.854 36.573 4.339 55.43 4.339 18.986 0 37.616-1.504 55.786-4.397zM438.893 688.451c-47.549-20.454-85.181-59.571-103.674-108.125l-155.029 41.539c33.968 103.485 114.617 185.805 217.045 222.058l41.658-155.472zM162.705 512c0 16.090 1.080 31.926 3.17 47.443l156.906-42.042c-0.051-1.795-0.077-3.594-0.077-5.402 0-4.909 0.186-9.776 0.547-14.595l-156.051-41.814c-2.958 18.368-4.496 37.21-4.496 56.41zM396.31 180.407c-99.16 35.408-177.786 114.033-213.196 213.19l155.535 41.677c19.357-44.352 54.982-79.978 99.334-99.331l-41.674-155.536zM514.704 160c-19.197 0-38.035 1.537-56.4 4.494l41.814 156.053c4.813-0.362 9.68-0.547 14.586-0.547 5.030 0 10.019 0.192 14.95 0.573l41.808-156.021c-18.477-2.995-37.437-4.552-56.758-4.552zM632.512 843.802c102.659-36.451 183.392-119.194 217.094-223.12l-154.973-41.526c-18.291 48.982-56.010 88.493-103.786 109.155l41.664 155.491zM863.699 558.198c1.984-15.117 3.005-30.538 3.005-46.198 0-18.771-1.469-37.197-4.298-55.171l-156.157 41.84c0.301 4.406 0.454 8.851 0.454 13.331 0 1.376-0.013 2.752-0.042 4.122l157.037 42.077zM846.714 394.774c-35.165-99.6-113.885-178.641-213.277-214.247l-41.68 155.559c44.582 19.555 80.314 55.565 99.504 100.342l155.453-41.654zM642.704 512c0-70.691-57.306-128-128-128-70.691 0-128 57.309-128 128s57.309 128 128 128c70.694 0 128-57.309 128-128z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["support"],"defaultCode":59848,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1113,"name":"support","prevSize":32,"id":201,"code":59848},"setIdx":2,"setId":2,"iconIdx":199},{"icon":{"paths":["M368 412.982c-53.592 0-96-42.877-96-94.491 0-51.616 42.408-94.491 96-94.491 53.594 0 96 42.876 96 94.491 0 51.614-42.406 94.491-96 94.491zM368 476.982c88.365 0 160-70.96 160-158.491s-71.635-158.491-160-158.491c-88.365 0-160 70.959-160 158.491s71.635 158.491 160 158.491zM713.6 397.133c-35.92 0-64-28.685-64-62.794s28.080-62.792 64-62.792c35.92 0 64 28.684 64 62.792s-28.080 62.794-64 62.794zM713.6 461.133c70.691 0 128-56.768 128-126.794s-57.309-126.792-128-126.792c-70.691 0-128 56.767-128 126.792s57.309 126.794 128 126.794zM197.459 527.267c27.344-8.707 56.67-9.242 84.319-1.539l48.491 13.51c24.205 6.742 49.882 6.275 73.824-1.347l30.099-9.584c29.475-9.386 61.085-9.962 90.89-1.658 67.962 18.934 114.918 80.333 114.918 150.269v91.987c0 52.518-42.979 95.094-96 95.094h-352c-53.019 0-96-42.576-96-95.094v-103.766c0-62.909 40.999-118.621 101.459-137.872zM264.451 586.758c-15.545-4.333-32.034-4.032-47.407 0.864-33.993 10.822-57.044 42.147-57.044 77.517v103.766c0 17.507 14.327 31.699 32 31.699h352c17.674 0 32-14.192 32-31.699v-91.987c0-41.533-27.885-77.997-68.246-89.242-17.699-4.931-36.474-4.589-53.978 0.986l-30.099 9.584c-35.91 11.434-74.426 12.138-110.737 2.019l-48.489-13.507zM691.2 778.717h140.8c53.021 0 96-42.979 96-96v-30.611c0-56.877-38.614-106.49-93.747-120.454-21.398-5.418-43.853-5.040-65.056 1.098l-16.4 4.746c-21.843 6.323-44.973 6.714-67.018 1.13l-29.805-7.549c-19.907-5.043-40.797-4.691-60.522 1.018-1.066 0.31-2.122 0.634-3.174 0.97 10.71 4.048 20.896 9.539 30.253 16.374l2.429 1.776 15.040 13.206c9.939 8.726 18.141 19.248 24.182 31.014l2.208 4.301 3.677 0.931c33.062 8.374 67.76 7.789 100.525-1.693l16.4-4.749c10.282-2.976 21.171-3.158 31.546-0.531 26.736 6.771 45.462 30.832 45.462 58.413v30.611c0 17.674-14.326 32-32 32h-140.8v64z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["team"],"defaultCode":59849,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1114,"name":"team","prevSize":32,"id":202,"code":59849},"setIdx":2,"setId":2,"iconIdx":200},{"icon":{"paths":["M281.184 336c17.673 0 32-14.326 32-32s-14.327-32-32-32c-17.673 0-32 14.327-32 32s14.327 32 32 32zM281.184 400c-53.020 0-96-42.979-96-96 0-53.019 42.98-96 96-96 53.018 0 96 42.981 96 96 0 53.021-42.982 96-96 96zM576 320c0-26.51-21.491-48-48-48s-48 21.49-48 48c0 26.509 21.491 48 48 48s48-21.491 48-48zM640 320c0 61.856-50.144 112-112 112s-112-50.144-112-112c0-61.856 50.144-112 112-112s112 50.144 112 112zM477.901 478.515c-28.56-10.957-60.291-10.211-88.307 2.067-42.282 18.534-69.594 60.326-69.594 106.49v132.928c0 53.021 42.979 96 96 96h224c53.021 0 96-42.979 96-96v-125.062c0-51.162-31.536-97.034-79.306-115.354-30.352-11.642-64.067-10.851-93.84 2.198l-2.070 0.909c-21.523 9.434-45.901 10.006-67.843 1.59l-15.040-5.766zM415.286 539.2c12.595-5.52 26.858-5.856 39.699-0.931l15.040 5.77c37.664 14.445 79.504 13.462 116.451-2.73l2.070-0.909c14.349-6.288 30.602-6.669 45.229-1.059 23.024 8.829 38.224 30.938 38.224 55.597v125.062c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32v-132.928c0-20.752 12.278-39.539 31.286-47.872zM768 336c-17.674 0-32-14.326-32-32s14.326-32 32-32c17.674 0 32 14.327 32 32s-14.326 32-32 32zM768 400c53.021 0 96-42.979 96-96 0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96zM840.714 681.766h-72.714v-64h72.714c17.674 0 32-14.326 32-32v-44.688c0-15.050-9.664-28.394-23.958-33.091-7.536-2.474-15.69-2.304-23.114 0.483l-4.554 1.709c-19.77 7.421-40.89 9.978-61.619 7.632-12.438-31.683-37.722-57.549-70.774-70.227-1.754-0.672-3.52-1.302-5.296-1.894 18.058-5.312 37.36-5.040 55.344 0.867l14.182 4.659c14.886 4.893 30.998 4.554 45.667-0.954l4.554-1.709c21.069-7.91 44.205-8.394 65.581-1.37 40.566 13.325 67.987 51.197 67.987 93.894v44.688c0 53.021-42.982 96-96 96zM625.267 624h-0.797c0.259 0.598 0.525 1.194 0.797 1.786v-1.786zM357.594 448.582c2.528-1.107 5.088-2.122 7.674-3.043-17.907-5.155-37.014-4.832-54.824 1.018l-14.183 4.659c-14.887 4.893-30.998 4.554-45.668-0.954l-4.554-1.709c-21.067-7.91-44.203-8.394-65.581-1.37-40.565 13.325-67.986 51.197-67.986 93.894v44.688c0 53.021 42.981 96 96 96h79.53v-64h-79.53c-17.673 0-32-14.326-32-32v-44.688c0-15.050 9.664-28.394 23.96-33.091 7.534-2.474 15.688-2.304 23.112 0.483l4.554 1.709c21.238 7.974 44.041 10.333 66.238 7.027 10.398-30.173 32.994-55.357 63.259-68.624zM423.917 624h0.797c-0.259 0.598-0.525 1.194-0.797 1.786v-1.786z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["teams"],"defaultCode":59751,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1115,"name":"teams","prevSize":32,"id":203,"code":59751},"setIdx":2,"setId":2,"iconIdx":201},{"icon":{"paths":["M631.997 256h24v-56c0-57.437 46.563-104 104-104 57.44 0 104 46.562 104 104v56h24c17.674 0 32 14.327 32 32v192c0 17.674-14.326 32-32 32h-256c-17.67 0-32-14.326-32-32v-192c0-17.673 14.33-32 32-32zM759.997 160c-22.090 0-40 17.908-40 40v55.238h80v-55.238c0-22.092-17.907-40-40-40z","M527.997 224c10.096 0 19.882 1.336 29.184 3.84-13.251 16.46-21.184 37.383-21.184 60.16v0.664c-2.602-0.436-5.274-0.664-8-0.664-26.509 0-48 21.49-48 48s21.491 48 48 48c2.726 0 5.398-0.227 8-0.662v64.381c-2.64 0.186-5.309 0.282-8 0.282-61.856 0-112-50.144-112-112s50.144-112 112-112z","M492.941 500.282c14.883 5.709 30.883 7.283 46.355 4.758 6.182 22.938 20.646 42.474 39.987 55.206-35.123 13.318-74.019 13.309-109.261-0.208l-15.040-5.77c-12.838-4.925-27.104-4.589-39.699 0.931-19.008 8.333-31.286 27.12-31.286 47.872v132.928c0 17.674 14.33 32 32 32h224c17.674 0 32-14.326 32-32v-125.062c0-12.842-4.122-24.995-11.325-34.938h70.291c3.29 11.162 5.034 22.902 5.034 34.938v125.062c0 53.021-42.979 96-96 96h-224c-53.018 0-95.999-42.979-95.999-96v-132.928c0-46.163 27.311-87.955 69.592-106.49 28.019-12.278 59.747-13.024 88.31-2.067l15.040 5.766z","M887.997 576h-15.286v25.766c0 17.674-14.326 32-32 32h-72.714v64h72.714c53.021 0 96-42.979 96-96v-39.027c-14.278 8.426-30.931 13.261-48.714 13.261z","M281.182 416c53.020 0 95.999-42.979 95.999-96 0-53.019-42.979-96-95.999-96s-96 42.981-96 96c0 53.021 42.98 96 96 96zM281.182 352c-17.673 0-32-14.326-32-32s14.327-32 32-32c17.673 0 32 14.327 32 32s-14.327 32-32 32z","M625.267 640h-0.8c0.262 0.598 0.528 1.194 0.8 1.786v-1.786z","M357.59 464.582c2.531-1.107 5.091-2.122 7.674-3.043-17.907-5.155-37.011-4.832-54.823 1.018l-14.183 4.659c-14.887 4.893-30.998 4.554-45.668-0.954l-4.554-1.709c-21.067-7.91-44.203-8.394-65.581-1.37-40.565 13.325-67.986 51.197-67.986 93.894v44.688c0 53.021 42.98 96 96 96h79.53v-64h-79.53c-17.673 0-32-14.326-32-32v-44.688c0-15.050 9.664-28.394 23.96-33.091 7.534-2.474 15.688-2.304 23.112 0.483l4.554 1.709c21.238 7.974 44.041 10.333 66.238 7.027 10.398-30.173 32.992-55.357 63.258-68.624z","M423.914 640h0.797c-0.259 0.598-0.525 1.194-0.797 1.786v-1.786z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["teams-private"],"defaultCode":59750,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1116,"name":"teams-private","prevSize":32,"id":204,"code":59750},"setIdx":2,"setId":2,"iconIdx":202},{"icon":{"paths":["M170.664 192c0-17.673 14.327-32 32-32h618.667c17.674 0 32 14.327 32 32v128c0 17.674-14.326 32-32 32s-32-14.326-32-32v-96h-245.334v576h96c17.674 0 32 14.326 32 32s-14.326 32-32 32h-256c-17.67 0-32-14.326-32-32s14.33-32 32-32h96v-576h-245.333v96c0 17.674-14.327 32-32 32s-32-14.326-32-32v-128z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"10811412211581621681203206209124319081245699212911624514522416519902101":[{}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{}]},"tags":["text-format"],"defaultCode":59839,"grid":0},"attrs":[{}],"properties":{"order":1117,"id":205,"name":"text-format","prevSize":32,"code":59839},"setIdx":2,"setId":2,"iconIdx":203},{"icon":{"paths":["M223.311 308.609c-47.832 66.7-64.077 147.667-64.077 201.187v1.405l-0.127 1.398c-9.348 103.235 27.547 175.997 86.848 226.374 60.642 51.52 146.602 80.998 235.29 90.893 88.611 9.885 186.221 1.398 263.341-14.973 38.56-8.189 70.928-18.125 93.888-28.128 8.906-3.882 15.837-7.536 20.941-10.765-2.374-1.514-5.245-3.197-8.672-5.030-8.886-4.749-19.059-9.261-29.613-13.894l-1.843-0.81c-9.315-4.083-19.725-8.65-27.613-13.078-14.291-8.026-28.317-17.155-38.544-26.867-5.034-4.781-10.762-11.194-14.595-19.184-4.054-8.454-6.96-21.078-1.261-34.435 30.816-72.186 45.459-111.725 52.554-137.834 6.621-24.378 6.621-36.653 6.621-56.17v-0.179c0-15.51-8.979-86.595-53.776-152.876-43.376-64.174-121.398-125.729-264.832-125.729-129.725 0-207.83 53.576-254.529 118.696zM173.267 272.433c58.132-81.063 154.749-144.433 304.573-144.433 164.896 0 261.594 72.589 315.859 152.878 52.838 78.181 64.416 161.881 64.416 187.641 0 21.654-0.022 40.336-8.797 72.64-7.834 28.835-22.627 68.614-50.048 133.424 5.069 4.032 12.592 9.005 22.506 14.57 5.12 2.877 12.995 6.339 24.054 11.194 10.266 4.506 22.582 9.93 33.891 15.978 10.848 5.798 23.526 13.571 32.954 23.738 9.859 10.63 20.208 28.87 12.816 51.139-4.87 14.672-16.182 25.091-25.61 32.016-10.24 7.52-22.947 14.278-36.858 20.342-27.949 12.176-64.582 23.181-105.68 31.907-82.198 17.453-186.522 26.688-282.909 15.936-96.31-10.746-195.346-43.178-268.313-105.165-74.031-62.893-119.295-154.778-108.551-277.856 0.276-63.411 19.117-157.053 75.696-235.948zM333.952 422.051c0-17.648 14.25-31.955 31.83-31.955h183.008c17.578 0 31.827 14.307 31.827 31.955s-14.25 31.955-31.827 31.955h-183.008c-17.581 0-31.83-14.307-31.83-31.955zM365.782 539.709c-17.581 0-31.83 14.307-31.83 31.955s14.25 31.955 31.83 31.955h224.118c17.578 0 31.827-14.307 31.827-31.955s-14.25-31.955-31.827-31.955h-224.118z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["threads"],"defaultCode":59850,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1118,"name":"threads","prevSize":32,"id":206,"code":59850},"setIdx":2,"setId":2,"iconIdx":204},{"icon":{"paths":["M353.354 320c0-17.673 14.326-32 32-32h256c17.674 0 32 14.327 32 32s-14.326 32-32 32h-256c-17.674 0-32-14.326-32-32z","M385.354 416c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M481.354 448c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M641.354 416c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M353.354 576c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M513.354 544c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M609.354 576c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M385.354 672c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M481.354 704c0-17.674 14.326-32 32-32s32 14.326 32 32c0 17.674-14.326 32-32 32s-32-14.326-32-32z","M641.354 672c-17.674 0-32 14.326-32 32s14.326 32 32 32c17.674 0 32-14.326 32-32s-14.326-32-32-32z","M289.353 160h448.001c35.344 0 64 28.654 64 64v576c0 35.347-28.656 64-64 64h-448.001c-35.346 0-64-28.653-64-64v-576c0-35.346 28.654-64 64-64zM289.353 224v576h448.001v-576h-448.001z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["total"],"defaultCode":59851,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1119,"name":"total","prevSize":32,"id":207,"code":59851},"setIdx":2,"setId":2,"iconIdx":205},{"icon":{"paths":["M713.613 91.356c13.162-11.794 33.392-10.685 45.187 2.477l129.034 144c10.89 12.154 10.89 30.556 0 42.71l-129.034 144.001c-11.795 13.162-32.026 14.269-45.187 2.477-13.162-11.795-14.272-32.026-2.477-45.187l81.222-90.646h-216.358c-17.674 0-32-14.327-32-32s14.326-32 32-32h216.358l-81.222-90.645c-11.795-13.162-10.685-33.393 2.477-45.187zM340.026 464.461c8.586-15.45 28.067-21.018 43.514-12.432l128.461 71.366 128.461-71.366c15.446-8.586 34.928-3.018 43.514 12.432 8.582 15.45 3.014 34.931-12.435 43.514l-159.539 88.634-159.539-88.634c-15.45-8.582-21.018-28.064-12.435-43.514zM192 288v448h640v-192c0-17.674 14.326-32 32-32s32 14.326 32 32v224c0 17.674-14.326 32-32 32h-704c-17.673 0-32-14.326-32-32v-512c0-17.673 14.327-32 32-32h272c17.674 0 32 14.327 32 32s-14.326 32-32 32h-240z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["transcript"],"defaultCode":59852,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1120,"name":"transcript","prevSize":32,"id":208,"code":59852},"setIdx":2,"setId":2,"iconIdx":206},{"icon":{"paths":["M378.861 853.331c317.456 0 491.091-262.662 491.091-490.442 0-7.462 0-14.89-0.506-22.282 33.779-24.401 62.938-54.614 86.112-89.224-31.501 13.94-64.918 23.082-99.136 27.12 36.032-21.542 62.998-55.424 75.882-95.34-33.878 20.078-70.944 34.228-109.597 41.839-53.501-56.814-138.515-70.72-207.37-33.919-68.851 36.801-104.426 115.155-86.768 191.127-138.774-6.947-268.074-72.409-355.715-180.093-45.811 78.76-22.412 179.517 53.436 230.1-27.467-0.813-54.335-8.214-78.337-21.574 0 0.704 0 1.443 0 2.182 0.022 82.051 57.937 152.723 138.47 168.97-25.41 6.922-52.071 7.933-77.933 2.957 22.611 70.218 87.409 118.32 161.25 119.706-61.116 47.968-136.616 74.010-214.35 73.933-13.732-0.026-27.452-0.858-41.087-2.486 78.931 50.586 170.772 77.418 264.557 77.293z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["twitter-monochromatic"],"defaultCode":59660,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1121,"name":"twitter-monochromatic","prevSize":32,"id":209,"code":59660},"setIdx":2,"setId":2,"iconIdx":207},{"icon":{"paths":["M384 320c0-17.673-14.326-32-32-32s-32 14.327-32 32v256c0 106.038 85.962 192 192 192s192-85.962 192-192v-256c0-17.673-14.326-32-32-32s-32 14.327-32 32v256c0 70.691-57.309 128-128 128s-128-57.309-128-128v-256zM352 856c-13.254 0-24 10.746-24 24s10.746 24 24 24h320c13.254 0 24-10.746 24-24s-10.746-24-24-24h-320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["underline"],"defaultCode":59853,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1122,"name":"underline","prevSize":32,"id":210,"code":59853},"setIdx":2,"setId":2,"iconIdx":208},{"icon":{"paths":["M512 832c176.73 0 320-143.27 320-320s-143.27-320-320-320c-111.712 0-210.056 57.244-267.295 144h107.295c17.674 0 32 14.326 32 32s-14.326 32-32 32h-176c-17.673 0-32-14.326-32-32v-192c0-17.673 14.327-32 32-32s32 14.327 32 32v101.364c70.228-90.856 180.282-149.364 304-149.364 212.077 0 384 171.923 384 384s-171.923 384-384 384c-212.077 0-384-171.923-384-384h64c0 176.73 143.27 320 320 320z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["undo"],"defaultCode":59854,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1123,"name":"undo","prevSize":32,"id":211,"code":59854},"setIdx":2,"setId":2,"iconIdx":209},{"icon":{"paths":["M589.36 729.43c-107.366 23.603-252.288-9.875-422.339-221.158 65.137-95.478 165.885-189.15 280.79-213.871 108.314-23.302 251.286 10.604 413.674 221.404-61.546 95.187-158.653 188.682-272.125 213.626zM916.819 482.714c-347.59-456.963-669.742-211.156-808.018-2.662-12.655 19.082-10.846 44.304 3.402 62.227 362.786 456.419 677.038 209.142 808.011 0.563 11.674-18.589 9.894-42.656-3.395-60.128zM619.462 512c0-53.709-45.517-100.57-105.834-100.57s-105.834 46.861-105.834 100.57c0 53.709 45.517 100.573 105.834 100.573s105.834-46.864 105.834-100.573zM683.546 512c0 90.893-76.074 164.573-169.917 164.573s-169.917-73.68-169.917-164.573c0-90.89 76.074-164.57 169.917-164.57s169.917 73.68 169.917 164.57z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["unread-on-top"],"defaultCode":59857,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1124,"name":"unread-on-top","prevSize":32,"id":212,"code":59857},"setIdx":2,"setId":2,"iconIdx":210},{"icon":{"paths":["M829.168 153.372c12.515-12.497 32.803-12.497 45.315 0 12.515 12.497 12.515 32.758 0 45.255l-672.887 672c-12.513 12.496-32.801 12.496-45.315 0s-12.513-32.758 0-45.254l672.887-672zM110.155 480.051c101.936-153.699 303.797-327.676 542.114-225.436l-49.578 49.512c-56.528-19.209-108.077-19.504-153.526-9.726-114.906 24.721-215.653 118.392-280.79 213.871 38.633 48 75.969 86.822 111.862 117.885l-45.363 45.302c-39.684-34.736-80.189-77.437-121.317-129.181-14.248-17.923-16.056-43.146-3.402-62.227zM797.981 350.454l-45.328 45.27c35.546 31.427 72.336 70.947 110.186 120.080-61.546 95.187-158.656 188.682-272.125 213.626-46.752 10.278-100.624 9.734-160.592-11.603l-49.331 49.267c244.662 107.334 443.389-69.158 540.778-224.253 11.674-18.589 9.894-42.656-3.395-60.128-40.493-53.235-80.64-96.931-120.192-132.259zM514.982 347.43c13.709 0 27.037 1.571 39.802 4.541l-203.738 203.469c-3.901-13.837-5.981-28.403-5.981-43.44 0-90.89 76.074-164.57 169.917-164.57zM679.091 469.184l-203.264 202.998c12.57 2.87 25.68 4.39 39.155 4.39 93.843 0 169.917-73.68 169.917-164.573 0-14.81-2.019-29.162-5.808-42.816z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["unread-on-top-disabled"],"defaultCode":59856,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1125,"name":"unread-on-top-disabled","prevSize":32,"id":213,"code":59856},"setIdx":2,"setId":2,"iconIdx":211},{"icon":{"paths":["M273.128 356.678c-6.62 27.766-2.384 63.757 25.498 105.581l33.166 49.75h-59.792c-44.011 0-70.484 14.874-86.279 33.619-16.496 19.578-24.573 47.264-23.734 77.491 0.841 30.262 10.601 59.968 25.818 81.312 15.127 21.216 33.404 31.578 52.195 31.578h143.999v64h-144c-45.209 0-80.932-25.642-104.306-58.426-23.283-32.656-36.522-74.95-37.682-116.688-1.16-41.773 9.763-86.083 38.766-120.506 20.726-24.598 49.155-42.32 84.825-50.784-16.1-39.011-19.009-77.050-10.731-111.77 11.253-47.2 42.305-84.492 80.791-107.342 38.4-22.798 85.677-32.139 131.303-21.965 35.584 7.935 68.909 27.48 95.251 59.554 53.75-35.147 127.584-30.892 182.483-2.495 34.438 17.812 64.794 46.382 81.437 85.010 12.294 28.531 16.438 61.011 10.608 96.205 46.112 6.682 81.507 25.155 105.616 53.456 30.346 35.626 38.102 81.35 33.443 123.283-4.659 41.917-21.946 83.485-46.544 115.114-24.061 30.934-59.354 57.354-101.261 57.354h-144v-64h144c14.093 0 32.8-9.581 50.742-32.646 17.398-22.371 30.112-52.806 33.453-82.89 3.341-30.067-2.902-56.339-18.554-74.714-15.222-17.869-44.035-33.75-97.642-33.75h-45.686l15.613-42.938c13.546-37.251 11.091-66.742 1.437-89.149-9.856-22.87-28.502-41.302-52.064-53.488-49.587-25.649-107.475-18.625-134.717 14.064l-30.134 36.16-22.541-41.325c-19.757-36.219-47.232-54.175-74.87-60.339-28.378-6.327-59.098-0.669-84.701 14.53-25.512 15.148-44.461 38.855-51.208 67.152zM630.979 588.778l-96-99.050c-6.029-6.218-14.32-9.728-22.979-9.728s-16.95 3.51-22.979 9.728l-96 99.050c-12.298 12.691-11.981 32.95 0.707 45.251 12.691 12.298 32.95 11.981 45.251-0.707l41.021-42.326v273.005c0 17.674 14.326 32 32 32s32-14.326 32-32v-273.005l41.021 42.326c12.301 12.688 32.56 13.005 45.251 0.707 12.691-12.301 13.005-32.56 0.707-45.251z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["upload"],"defaultCode":59858,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1126,"name":"upload","prevSize":32,"id":214,"code":59858},"setIdx":2,"setId":2,"iconIdx":212},{"icon":{"paths":["M609.354 336c0-53.019-42.979-96-96-96s-96 42.981-96 96c0 53.021 42.979 96 96 96s96-42.979 96-96zM673.354 336c0 88.365-71.635 160-160 160s-160-71.635-160-160c0-88.365 71.635-160 160-160s160 71.635 160 160zM413.805 551.802c-24.621-5.77-50.285-5.366-74.714 1.178-67.086 17.968-113.738 78.762-113.738 148.211v66.81c0 53.021 42.98 96 96 96h384c53.021 0 96-42.979 96-96v-58.531c0-74.301-51.149-138.826-123.488-155.779l-6.458-1.514c-25.674-6.016-52.435-5.594-77.907 1.229l-49.626 13.293c-20.378 5.456-41.789 5.795-62.326 0.979l-67.744-15.875zM355.651 614.8c14.237-3.814 29.197-4.051 43.549-0.688l67.744 15.878c30.806 7.219 62.925 6.714 93.488-1.472l49.629-13.293c15.283-4.096 31.341-4.349 46.742-0.736l6.458 1.51c43.402 10.173 74.093 48.89 74.093 93.469v58.531c0 17.674-14.326 32-32 32h-384c-17.673 0-32-14.326-32-32v-66.81c0-40.483 27.193-75.917 66.298-86.39z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["user"],"defaultCode":59861,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1127,"name":"user","prevSize":32,"id":215,"code":59861},"setIdx":2,"setId":2,"iconIdx":213},{"icon":{"paths":["M553.411 326.282c0 91.578-75.846 165.818-169.411 165.818-93.564 0-169.412-74.24-169.412-165.818 0-91.581 75.848-165.821 169.412-165.821 93.565 0 169.411 74.24 169.411 165.821zM485.648 326.282c0-54.949-45.51-99.493-101.648-99.493s-101.647 44.544-101.647 99.493c0 54.947 45.509 99.491 101.647 99.491s101.648-44.544 101.648-99.491z","M203.427 511.232c28.952-9.11 60.004-9.67 89.279-1.61l51.342 14.131c25.632 7.056 52.819 6.566 78.166-1.408l31.872-10.026c31.206-9.821 64.678-10.422 96.234-1.738 71.962 19.811 121.68 84.051 121.68 157.219v96.24c0 54.947-45.51 99.491-101.648 99.491h-372.705c-56.138 0-101.647-44.544-101.647-99.491v-108.566c0-65.814 43.411-124.106 107.427-144.243zM274.359 573.472c-16.46-4.531-33.918-4.218-50.196 0.906-35.992 11.322-60.399 44.093-60.399 81.098v108.566c0 18.317 15.17 33.165 33.882 33.165h372.705c18.714 0 33.882-14.848 33.882-33.165v-96.24c0-43.453-29.523-81.603-72.259-93.366-18.739-5.158-38.618-4.8-57.152 1.030l-31.872 10.026c-38.022 11.962-78.803 12.698-117.248 2.115l-51.343-14.134z","M797.091 189.321c0-15.913-13.024-28.812-29.091-28.812s-29.091 12.9-29.091 28.812v100.844h-101.818c-16.067 0-29.091 12.9-29.091 28.812s13.024 28.812 29.091 28.812h101.818v100.845c0 15.914 13.024 28.813 29.091 28.813s29.091-12.899 29.091-28.813v-100.845h101.818c16.067 0 29.091-12.899 29.091-28.812s-13.024-28.812-29.091-28.812h-101.818v-100.844z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["user-add"],"defaultCode":59859,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1128,"name":"user-add","prevSize":32,"id":216,"code":59859},"setIdx":2,"setId":2,"iconIdx":214},{"icon":{"paths":["M464 318.747c0-51.548-42.406-94.366-96-94.366-53.592 0-96 42.819-96 94.366s42.408 94.367 96 94.367c53.594 0 96-42.819 96-94.367zM528 318.747c0 87.416-71.635 158.284-160 158.284s-160-70.867-160-158.284c0-87.417 71.635-158.282 160-158.282s160 70.865 160 158.282zM281.778 525.712c-27.649-7.693-56.976-7.158-84.319 1.536-60.46 19.226-101.459 74.864-101.459 137.69v103.629c0 52.451 42.981 94.97 96 94.97h352c3.606 0 7.165-0.195 10.666-0.579v-64.534c-3.334 1.168-6.925 1.802-10.666 1.802h-352c-17.673 0-32-14.173-32-31.658v-103.629c0-35.325 23.051-66.605 57.044-77.414 15.373-4.89 31.862-5.187 47.407-0.864l48.489 13.491c36.311 10.102 74.827 9.402 110.737-2.016l30.099-9.571c17.504-5.568 36.278-5.91 53.978-0.986 18.899 5.261 35.066 16.042 46.912 30.282v-79.712c-9.309-4.749-19.203-8.627-29.584-11.517-29.805-8.291-61.414-7.715-90.89 1.654l-30.099 9.574c-23.942 7.61-49.619 8.080-73.824 1.344l-48.491-13.491zM763.366 489.709c-12.326-12.646-32.586-12.918-45.248-0.608-12.666 12.31-12.938 32.544-0.611 45.19l102.842 105.51h-324.349c-17.674 0-32 14.307-32 31.958 0 17.648 14.326 31.958 32 31.958h324.349l-102.842 105.507c-12.326 12.65-12.054 32.88 0.611 45.194 12.662 12.31 32.922 12.038 45.248-0.611l155.718-159.757c12.093-12.406 12.093-32.176 0-44.582l-155.718-159.76z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["user-forward"],"defaultCode":59860,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1129,"name":"user-forward","prevSize":32,"id":217,"code":59860},"setIdx":2,"setId":2,"iconIdx":215},{"icon":{"paths":["M201.583 672c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 576c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M201.583 480c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 384c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M201.583 288c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M329.584 192c-17.674 0-32.001 14.327-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.327 32-32s-14.326-32-32-32h-544z","M201.583 864c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M329.584 768c-17.674 0-32.001 14.326-32.001 32s14.327 32 32.001 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["view-condensed"],"defaultCode":59862,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1130,"name":"view-condensed","prevSize":32,"id":218,"code":59862},"setIdx":2,"setId":2,"iconIdx":216},{"icon":{"paths":["M288 192c0-17.673 14.327-32 32-32h544c17.674 0 32 14.327 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.327-32-32zM288 288c0-17.673 14.327-32 32-32h448c17.674 0 32 14.327 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.327-32-32zM192 304c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M288 464c0-17.674 14.327-32 32-32h544c17.674 0 32 14.326 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.326-32-32zM288 560c0-17.674 14.327-32 32-32h448c17.674 0 32 14.326 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.326-32-32zM192 576c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M288 736c0-17.674 14.327-32 32-32h544c17.674 0 32 14.326 32 32s-14.326 32-32 32h-544c-17.673 0-32-14.326-32-32zM288 832c0-17.674 14.327-32 32-32h448c17.674 0 32 14.326 32 32s-14.326 32-32 32h-448c-17.673 0-32-14.326-32-32zM192 848c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["view-extended"],"defaultCode":59863,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1131,"name":"view-extended","prevSize":32,"id":219,"code":59863},"setIdx":2,"setId":2,"iconIdx":217},{"icon":{"paths":["M192 320c35.346 0 64-28.654 64-64s-28.654-64-64-64c-35.346 0-64 28.654-64 64s28.654 64 64 64z","M320 224c-17.673 0-32 14.327-32 32s14.327 32 32 32h544c17.674 0 32-14.327 32-32s-14.326-32-32-32h-544z","M192 576c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M320 480c-17.673 0-32 14.326-32 32s14.327 32 32 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z","M192 832c35.346 0 64-28.653 64-64s-28.654-64-64-64c-35.346 0-64 28.653-64 64s28.654 64 64 64z","M320 736c-17.673 0-32 14.326-32 32s14.327 32 32 32h544c17.674 0 32-14.326 32-32s-14.326-32-32-32h-544z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["view-medium"],"defaultCode":59864,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1132,"name":"view-medium","prevSize":32,"id":220,"code":59864},"setIdx":2,"setId":2,"iconIdx":218},{"icon":{"paths":["M640.854 256c26.512 0 48-21.49 48-48s-21.488-48-48-48c-26.509 0-48 21.49-48 48s21.491 48 48 48zM640.854 320c61.856 0 112-50.144 112-112s-50.144-112-112-112c-61.856 0-112 50.144-112 112s50.144 112 112 112zM592.854 416v256h-160v128h32v-96h224v-288h-96zM528.854 768h160c35.347 0 64-28.653 64-64v-288c0-35.347-28.653-64-64-64h-96c-35.344 0-64 28.653-64 64v192h-96c-35.344 0-64 28.653-64 64v128c0 35.347 28.656 64 64 64h32c35.347 0 64-28.653 64-64v-32zM784.854 448c0-17.674 14.326-32 32-32s32 14.326 32 32v384c0 17.674-14.326 32-32 32h-224c-17.674 0-32-14.326-32-32s14.326-32 32-32h192v-352zM368.403 401.52c9.677-9.059 10.176-24.246 1.117-33.923l-48.272-51.558v-47.925c0-13.255-10.746-24-24-24s-24 10.745-24 24v57.406c0 6.093 2.316 11.955 6.48 16.403l54.752 58.48c9.059 9.677 24.246 10.176 33.923 1.117zM170.974 414.278c53.308 74.218 156.687 91.171 230.908 37.862 10.765-7.731 25.76-5.274 33.494 5.491 7.731 10.768 5.274 25.763-5.494 33.494-95.75 68.771-229.121 46.902-297.894-48.848s-46.902-229.123 48.848-297.895c75.545-54.26 174.453-52.073 246.597-1.796 10.874 7.578 13.546 22.538 5.968 33.412s-22.538 13.547-33.411 5.968c-55.971-39.005-132.65-40.618-191.153 1.402-74.219 53.308-91.171 156.688-37.864 230.909z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["waiting-on-me"],"defaultCode":59865,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1133,"name":"waiting-on-me","prevSize":32,"id":221,"code":59865},"setIdx":2,"setId":2,"iconIdx":219},{"icon":{"paths":["M512 352.003c17.674 0 32 14.33 32 32v224c0 17.674-14.326 32-32 32s-32-14.326-32-32v-224c0-17.67 14.326-32 32-32z","M512 672.003c17.674 0 32 14.33 32 32 0 17.674-14.326 32-32 32s-32-14.326-32-32c0-17.67 14.326-32 32-32z","M567.101 158.348c-24.774-41.922-85.427-41.922-110.202 0l-359.92 609.099c-25.21 42.662 5.544 96.557 55.099 96.557h719.845c49.555 0 80.307-53.894 55.098-96.557l-359.92-609.099zM512 190.906l359.923 609.097h-719.845l359.922-609.097z"],"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2}]},"tags":["warning"],"defaultCode":59866,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1134,"name":"warning","prevSize":32,"id":222,"code":59866},"setIdx":2,"setId":2,"iconIdx":220},{"icon":{"paths":["M784.131 240.143c-35.43-35.658-77.581-63.931-124.016-83.181s-96.227-29.094-146.493-28.961c-210.863 0-382.322 171.532-382.414 382.376-0.085 67.104 17.523 133.043 51.047 191.171l-54.256 198.154 202.72-53.174c56.064 30.531 118.883 46.531 182.717 46.538h0.166c210.752 0 382.32-171.552 382.394-382.394 0.16-50.25-9.645-100.029-28.848-146.464-19.2-46.436-47.418-88.604-83.018-124.065zM513.622 828.486h-0.186c-56.922 0.006-112.797-15.293-161.776-44.298l-11.606-6.896-120.302 31.555 32.124-117.347-7.573-12.029c-31.783-50.64-48.608-109.232-48.535-169.021 0-175.235 142.653-317.816 317.981-317.816 84.301 0.049 165.13 33.58 224.707 93.218 59.581 59.638 93.034 140.499 92.998 224.8-0.074 175.254-142.653 317.834-317.834 317.834zM687.958 590.451c-9.552-4.787-56.528-27.907-65.293-31.171s-15.126-4.768-21.491 4.784c-6.362 9.555-24.678 31.171-30.253 37.462-5.574 6.288-11.149 7.187-20.701 2.4-9.555-4.784-40.339-14.87-76.845-47.434-28.403-25.322-47.584-56.621-53.174-66.192-5.594-9.571-0.589-14.669 4.198-19.491 4.291-4.291 9.552-11.168 14.32-16.742s6.381-9.571 9.552-15.933c3.174-6.362 1.597-11.955-0.787-16.739-2.384-4.787-21.491-51.818-29.466-70.96-7.757-18.63-15.622-16.099-21.491-16.394-5.501-0.275-11.955-0.349-18.336-0.349-4.842 0.131-9.606 1.264-13.994 3.325-4.387 2.058-8.298 5.005-11.491 8.65-8.749 9.552-33.428 32.675-33.428 79.706s34.234 92.467 39.002 98.848c4.765 6.381 67.382 102.883 163.187 144.266 17.792 7.68 35.974 14.413 54.477 20.17 22.902 7.334 43.731 6.237 60.179 3.779 18.336-2.733 56.547-23.104 64.506-45.418 7.955-22.317 7.955-41.459 5.501-45.456-2.458-3.997-8.618-6.326-18.173-11.11z"],"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["whatsapp-monochromatic"],"defaultCode":59868,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1135,"name":"whatsapp-monochromatic","prevSize":32,"id":223,"code":59868},"setIdx":2,"setId":2,"iconIdx":221},{"icon":{"paths":["M354.006 399.123l14.029 0.627-0.541-16.726-152.878 1.578c49.916-116.491 165.64-198.133 300.366-198.133 99.645 0 188.893 44.659 248.81 115.065-3.712 0.171-7.491 0.492-11.526 1.068 0 0-63.76 14.898-13.302 118.708 0 0 31.085 84.541-19.306 198.774l-28.403 73.306-99.101-264.723c0 0-5.984-28.154 23.61-28.154l23.76-1.472 0.339-16.035h-228.368v14.458c0 0 39.83-0.288 56.15 27.149l40.762 103.779-73.014 174.403-108.608-272.4c0 0-3.389-31.779 27.222-31.27z","M841.603 513.168c0-33.862-5.235-66.643-14.726-97.357l-145.949 378.755c96.134-56.88 160.675-161.571 160.675-281.398z","M411.478 823.011c32.49 10.912 67.267 16.778 103.488 16.778 37.85 0 74.102-6.406 107.898-18.256l-99.709-258.502-111.677 259.981z","M188.279 513.149c0-32.083 4.712-63.066 13.339-92.336l1 2.051 152.656 375.229c-99.606-55.882-166.994-162.538-166.994-284.944z","M130.705 512.093c0-211.775 172.316-384.093 384.076-384.093 211.725 0 383.923 172.318 383.923 384.093 0 211.776-172.198 384.010-383.923 384.010-211.757 0-384.076-172.234-384.076-384.010zM514.781 879.254c202.384 0 367.11-164.742 367.11-367.178 0-202.486-164.726-367.145-367.11-367.161-202.489 0-367.213 164.673-367.213 367.161 0 202.435 164.724 367.178 367.213 367.178z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["wordpress-monochromatic"],"defaultCode":59755,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1136,"name":"wordpress-monochromatic","prevSize":32,"id":224,"code":59755},"setIdx":2,"setId":2,"iconIdx":222},{"icon":{"paths":["M193.353 405.334h213.332v-213.334h-213.332v213.334zM129.353 170.667c0-23.564 19.102-42.667 42.667-42.667h256c23.565 0 42.666 19.102 42.666 42.667v255.999c0 23.565-19.101 42.669-42.666 42.669h-256c-23.564 0-42.667-19.104-42.667-42.669v-255.999zM620.019 405.334h213.334v-213.334h-213.334v213.334zM556.019 170.667c0-23.564 19.104-42.667 42.666-42.667h256c23.565 0 42.669 19.102 42.669 42.667v255.999c0 23.565-19.104 42.669-42.669 42.669h-256c-23.562 0-42.666-19.104-42.666-42.669v-255.999zM620.019 618.666h213.334v213.334h-213.334v-213.334zM598.685 554.666c-23.562 0-42.666 19.104-42.666 42.669v256c0 23.562 19.104 42.666 42.666 42.666h256c23.565 0 42.669-19.104 42.669-42.666v-256c0-23.565-19.104-42.669-42.669-42.669h-256zM193.353 832h213.332v-213.334h-213.332v213.334zM129.353 597.334c0-23.565 19.102-42.669 42.667-42.669h256c23.565 0 42.666 19.104 42.666 42.669v256c0 23.562-19.101 42.666-42.666 42.666h-256c-23.564 0-42.667-19.104-42.667-42.666v-256z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2}]},"tags":["workspaces"],"defaultCode":59870,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1137,"name":"workspaces","prevSize":32,"id":225,"code":59870},"setIdx":2,"setId":2,"iconIdx":223},{"icon":{"paths":["M384.509 149.333c0-11.782 9.562-21.333 21.36-21.333h85.446c11.798 0 21.363 9.551 21.363 21.333v106.667h-106.81c-11.798 0-21.36-9.551-21.36-21.333v-85.333z","M512.678 256h106.806c11.798 0 21.36 9.551 21.36 21.333v85.332c0 11.782-9.562 21.334-21.36 21.334h-106.806v-128z","M384.509 405.334c0-11.782 9.562-21.334 21.36-21.334h106.81v128h-106.81c-11.798 0-21.36-9.552-21.36-21.334v-85.331z","M512.678 512h106.806c11.798 0 21.36 9.552 21.36 21.334v106.666h-128.166v-128z","M427.232 640c-23.597 0-42.723 19.104-42.723 42.666v170.669c0 23.562 19.126 42.666 42.723 42.666h170.89c23.597 0 42.723-19.104 42.723-42.666v-213.334h-213.613zM491.315 725.334c-11.798 0-21.36 9.549-21.36 21.331v42.669c0 11.782 9.562 21.331 21.36 21.331h42.723c11.798 0 21.36-9.549 21.36-21.331v-42.669c0-11.782-9.562-21.331-21.36-21.331h-42.723z"],"width":1056,"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"isMulticolor":false,"isMulticolor2":false,"colorPermutations":{"1081141221158162168120320620912282312341243190812456992125519219212552552551291162451452241651699010019902101":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}],"10811412211581621681203206209124314057124319081245699212911624514522416519902101":[{"f":1},{"f":1},{"f":1},{"f":1},{"f":1}],"10811412211581621681201349612032062091211112451212123812431405712431908124569921291162451452241651":[{"f":2},{"f":2},{"f":2},{"f":2},{"f":2}]},"tags":["zip"],"defaultCode":59871,"grid":0},"attrs":[{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"},{"fill":"rgb(108, 114, 122)"}],"properties":{"order":1138,"name":"zip","prevSize":32,"id":226,"code":59871},"setIdx":2,"setId":2,"iconIdx":224},{"icon":{"paths":["M373.437 492.374c25.77-8.39 53.667-8.131 79.376 0.906l19.187 6.752c25.293 8.893 52.963 8.275 77.843-1.718l4.877-1.971c26.989-10.842 56.726-12.432 84.592-4.685 2.832 0.787 5.648 1.674 8.438 2.656 22.342 7.856 41.504 21.35 56.25 38.499 17.84 20.742 29.178 46.848 31.533 75.030 0.304 3.645 0.467 7.328 0.467 11.030v117.126c0 9.936-1.51 19.517-4.314 28.531-4.467 14.371-12.275 27.245-22.435 37.843-2.595 2.704-5.296 5.302-8.189 7.69-2.368 1.952-4.822 3.805-7.376 5.53-5.107 3.453-10.57 6.413-16.31 8.845-11.491 4.861-24.115 7.562-37.376 7.562l-260.938-0.125c-3.277-0.166-6.506-0.515-9.686-1.002-7.949-1.213-15.571-3.398-22.752-6.435-5.741-2.432-11.203-5.392-16.31-8.845-2.55-1.725-5.008-3.578-7.376-5.53-2.893-2.387-5.595-4.986-8.188-7.69-10.162-10.598-17.97-23.472-22.437-37.843-2.803-9.014-4.312-18.595-4.313-28.531v-125.968c0-0.675 0.052-1.357 0.062-2.032 0.487-29.827 11.671-57.741 30.531-79.344 12.578-14.41 28.523-26.032 47.032-33.469 2.576-1.034 5.187-1.958 7.811-2.813zM426.374 552.093c-10.461-2.643-21.446-2.406-31.779 0.688-1.728 0.518-3.443 1.104-5.126 1.782-1.757 0.704-3.466 1.488-5.126 2.342-0.115 0.061-0.227 0.128-0.342 0.189-19.514 10.24-31.997 30.573-32 52.938v125.968c0 17.674 14.326 32 32 32h256c17.674 0 32-14.326 32-32v-117.126c-0.003-23.798-12.39-45.472-32-57.718-0.253-0.157-0.525-0.282-0.781-0.435-1.555-0.944-3.142-1.837-4.781-2.656-0.57-0.288-1.139-0.576-1.718-0.845-2.006-0.934-4.070-1.786-6.189-2.531-3.894-1.37-7.878-2.394-11.907-3.030-10.070-1.597-20.403-0.883-30.218 2.061-1.958 0.589-3.901 1.264-5.811 2.032l-4.877 1.936c-9.818 3.946-19.914 6.973-30.157 9.062-12.81 2.618-25.85 3.763-38.874 3.469l-7.814-0.342c-10.406-0.704-20.774-2.333-30.966-4.906-2.547-0.643-5.072-1.366-7.594-2.125-2.522-0.762-5.037-1.562-7.533-2.438l-19.219-6.749c-1.709-0.602-3.443-1.123-5.187-1.565z","M174.188 458.624c19.051-8.506 40.722-9.024 60.156-1.437l7.906 3.094c8.268 3.229 17.489 2.992 25.594-0.624l0.844-0.378c20.012-8.931 42.773-9.469 63.188-1.498 6.358 2.483 12.262 5.722 17.658 9.562-27.331 11.914-50.085 31.030-66.283 54.688-20.961 6.541-43.62 5.914-64.281-2.157l-7.906-3.062c-3.484-1.36-7.366-1.274-10.781 0.25-5.037 2.25-8.281 7.264-8.281 12.781v49.219c0.001 15.981 12.956 28.938 28.938 28.938h35.125c-0.009 0.675-0.062 1.357-0.062 2.032v61.968h-35.062c-51.328 0-92.937-41.61-92.938-92.938v-49.219c0-30.768 18.093-58.672 46.188-71.219z","M878.406 422.813c11.197 14.163 17.594 31.891 17.594 50.563v102.624c0 53.021-42.979 96-96 96h-32v-53.126l-0.125-6.499c-0.058-1.462-0.246-2.922-0.342-4.374h32.467c17.674 0 32-14.326 32-32v-102.624c0-3.12-0.842-6.109-2.342-8.72 13.494-10.003 27.248-21.219 40.374-33.562 2.797-2.634 5.539-5.45 8.374-8.282z","M512.032 192c-0.106 19.205 0.71 40.743 2.938 64.156-0.986-0.045-1.974-0.156-2.97-0.156-35.347 0-64 28.654-64 64s28.653 64 64 64c14.624 0 28.035-4.995 38.813-13.251 12.131 18.838 26.362 35.45 40.406 49.718-21.798 17.213-49.29 27.533-79.219 27.533-70.691 0-128-57.309-128-128 0-70.692 57.338-128 128.032-128z","M256 224c53.019 0 96 42.981 96 96 0 53.021-42.981 96-96 96s-96-42.979-96-96c0-53.019 42.981-96 96-96zM256 288c-17.673 0-32 14.327-32 32s14.327 32 32 32c17.673 0 32-14.326 32-32s-14.327-32-32-32z","M735.997 96c44.746 0 121.2 10.367 153.827 29.086 4.662 18.723 11.184 75.812 0 154.423-11.187 78.625-107.213 145.092-153.824 168.49-46.614-23.402-142.637-89.869-153.824-168.49-11.184-78.609-4.662-135.699 0-154.423 32.627-18.719 109.072-29.084 153.821-29.086z"],"attrs":[{},{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["team-shield"],"grid":0},"attrs":[{},{},{},{},{},{}],"properties":{"order":14,"id":227,"name":"team-shield","prevSize":32,"code":59877},"setIdx":2,"setId":2,"iconIdx":225},{"icon":{"paths":["M352 128c17.674 0 32 14.327 32 32v160h142.25c7.789 23.664 19.898 45.082 33.718 64h-175.968v256h256v-177.126c23.274 17.472 46 31.267 64 40.563v136.563h160c17.674 0 32 14.326 32 32s-14.326 32-32 32h-160v160c0 17.674-14.326 32-32 32s-32-14.326-32-32v-160h-256v160c0 17.674-14.326 32-32 32s-32-14.326-32-32v-160h-160c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-256h-160c-17.673 0-32-14.326-32-32s14.327-32 32-32h160v-160c0-17.673 14.326-32 32-32z","M735.997 96c44.746 0 121.2 10.367 153.827 29.086 4.662 18.723 11.184 75.812 0 154.423-11.187 78.625-107.213 145.092-153.824 168.49-46.614-23.402-142.637-89.869-153.824-168.49-11.184-78.609-4.662-135.699 0-154.423 32.627-18.719 109.072-29.084 153.821-29.086z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["hash-shield"],"grid":0},"attrs":[{},{}],"properties":{"order":15,"id":228,"name":"hash-shield","prevSize":32,"code":59878},"setIdx":2,"setId":2,"iconIdx":226}],"height":1024,"metadata":{"name":"custom"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"custom","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"noie8":true,"ie7":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon","name":"icomoon"},"historySize":50,"showCodes":true,"gridSize":16}} \ No newline at end of file diff --git a/app/containers/MediaCallHeader/components/EndCall.tsx b/app/containers/MediaCallHeader/components/EndCall.tsx index 9ba0968a3d0..aecbdfbb7c5 100644 --- a/app/containers/MediaCallHeader/components/EndCall.tsx +++ b/app/containers/MediaCallHeader/components/EndCall.tsx @@ -14,7 +14,7 @@ const EndCall = () => { testID='media-call-header-end' accessibilityLabel={I18n.t('End')} onPress={endCall} - iconName='phone-end' + iconName='phone-off' color={colors.fontDanger} /> </HeaderButton.Container> diff --git a/app/containers/ServerItem/__snapshots__/ServerItem.test.tsx.snap b/app/containers/ServerItem/__snapshots__/ServerItem.test.tsx.snap index 01509e744dc..93692340de3 100644 --- a/app/containers/ServerItem/__snapshots__/ServerItem.test.tsx.snap +++ b/app/containers/ServerItem/__snapshots__/ServerItem.test.tsx.snap @@ -645,7 +645,7 @@ exports[`Story Snapshots: SwipeActions should match snapshot 1`] = ` "top": 0, }, { - "width": undefined, + "width": 350, }, { "height": 68, @@ -994,7 +994,7 @@ exports[`Story Snapshots: SwipeActions should match snapshot 1`] = ` "top": 0, }, { - "width": undefined, + "width": 350, }, { "height": 68, diff --git a/app/containers/UIKit/Actions.tsx b/app/containers/UIKit/Actions.tsx index 15f01af1c64..154647bf113 100644 --- a/app/containers/UIKit/Actions.tsx +++ b/app/containers/UIKit/Actions.tsx @@ -1,22 +1,44 @@ import React, { useState } from 'react'; +import { View, StyleSheet } from 'react-native'; import { BlockContext } from '@rocket.chat/ui-kit'; import Button from '../Button'; import I18n from '../../i18n'; import { type IActions } from './interfaces'; +const styles = StyleSheet.create({ + hidden: { + overflow: 'hidden', + height: 0 + } +}); + export const Actions = ({ blockId, appId, elements, parser }: IActions) => { const [showMoreVisible, setShowMoreVisible] = useState(() => elements && elements.length > 5); - const renderedElements = showMoreVisible ? elements?.slice(0, 5) : elements; + const shouldShowMore = elements && elements.length > 5; + const maxVisible = 5; + + if (!elements || !parser) { + return null; + } + + // Always render all elements to maintain consistent hook calls + // This ensures hooks are always called in the same order + // Use View wrapper to conditionally hide elements instead of conditionally rendering return ( <> - <> - {renderedElements - ? renderedElements?.map(element => parser?.renderActions({ blockId, appId, ...element }, BlockContext.ACTION, parser)) - : null} - </> - {showMoreVisible && <Button title={I18n.t('Show_more')} onPress={() => setShowMoreVisible(false)} />} + {elements.map((element, index) => { + const isVisible = !showMoreVisible || index < maxVisible; + const component = parser?.renderActions({ blockId, appId, ...element }, BlockContext.ACTION); + // Always render the component, but hide it with styles if needed + return ( + <View key={element.actionId || `action-${index}`} style={!isVisible ? styles.hidden : undefined}> + {component} + </View> + ); + })} + {shouldShowMore && showMoreVisible && <Button title={I18n.t('Show_more')} onPress={() => setShowMoreVisible(false)} />} </> ); }; diff --git a/app/containers/UIKit/Context.tsx b/app/containers/UIKit/Context.tsx index 49344a39d9e..cff859b494b 100644 --- a/app/containers/UIKit/Context.tsx +++ b/app/containers/UIKit/Context.tsx @@ -13,5 +13,11 @@ const styles = StyleSheet.create({ }); export const Context = ({ elements, parser }: IContext) => ( - <View style={styles.container}>{elements?.map(element => parser?.renderContext(element, BlockContext.CONTEXT, parser))}</View> + <View style={styles.container}> + {elements?.map((element, index) => ( + <React.Fragment key={(element as any).type ? `${(element as any).type}-${index}` : `context-${index}`}> + {parser?.renderContext(element, BlockContext.CONTEXT)} + </React.Fragment> + ))} + </View> ); diff --git a/app/containers/UIKit/Icon.test.tsx b/app/containers/UIKit/Icon.test.tsx new file mode 100644 index 00000000000..dcd22068ee1 --- /dev/null +++ b/app/containers/UIKit/Icon.test.tsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { Text } from 'react-native'; +import { render } from '@testing-library/react-native'; + +import { Icon, resolveIconName } from './Icon'; + +const mockHasIcon = jest.fn(); +const mockCustomIcon = jest.fn(() => <Text testID='custom-icon'>icon</Text>); + +jest.mock('../CustomIcon', () => ({ + hasIcon: (...args: unknown[]) => mockHasIcon(...args), + CustomIcon: (...props: Parameters<typeof mockCustomIcon>) => mockCustomIcon(...props) +})); + +jest.mock('../../theme', () => ({ + useTheme: () => ({ + colors: { + fontDefault: '#000000', + fontDanger: '#d00000', + fontSecondaryInfo: '#0060d0', + statusFontWarning: '#d09000', + statusFontDanger: '#ff2020', + surfaceTint: '#f2f2f2' + } + }) +})); + +describe('UIKit Icon', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('resolveIconName', () => { + it('returns original icon when available', () => { + mockHasIcon.mockImplementation((name: string) => name === 'bell'); + + expect(resolveIconName('bell')).toBe('bell'); + }); + + it('resolves known alias when alias icon exists', () => { + mockHasIcon.mockImplementation((name: string) => name === 'phone-off'); + + expect(resolveIconName('phone-end')).toBe('phone-off'); + }); + + it('falls back to info when icon and alias are unavailable', () => { + mockHasIcon.mockReturnValue(false); + + expect(resolveIconName('unknown')).toBe('info'); + }); + }); + + it('renders secondary variant color', () => { + mockHasIcon.mockReturnValue(true); + render(<Icon element={{ icon: 'bell', type: 'icon', variant: 'secondary' } as any} />); + + expect(mockCustomIcon).toHaveBeenCalledTimes(1); + const firstCallArg = (mockCustomIcon.mock.calls[0] as any[])[0]; + expect(firstCallArg).toEqual( + expect.objectContaining({ + name: 'bell', + color: '#0060d0', + size: 20 + }) + ); + }); + + it('uses framed danger color and frame background', () => { + mockHasIcon.mockReturnValue(true); + const { toJSON } = render(<Icon element={{ icon: 'bell', type: 'icon', variant: 'danger', framed: true } as any} />); + + expect(mockCustomIcon).toHaveBeenCalledTimes(1); + const firstCallArg = (mockCustomIcon.mock.calls[0] as any[])[0]; + expect(firstCallArg).toEqual( + expect.objectContaining({ + name: 'bell', + color: '#ff2020', + size: 20 + }) + ); + expect(toJSON()).toMatchObject({ + props: { + style: expect.arrayContaining([expect.objectContaining({ backgroundColor: '#f2f2f2' })]) + } + }); + }); +}); diff --git a/app/containers/UIKit/Icon.tsx b/app/containers/UIKit/Icon.tsx new file mode 100644 index 00000000000..51c20aadcfe --- /dev/null +++ b/app/containers/UIKit/Icon.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; + +import { hasIcon, CustomIcon } from '../CustomIcon'; +import { useTheme } from '../../theme'; +import { type IIcon } from './interfaces'; + +const iconAliases: Record<string, string> = { + 'phone-end': 'phone-off' +}; + +const styles = StyleSheet.create({ + frame: { + width: 28, + height: 28, + borderRadius: 4, + alignItems: 'center', + justifyContent: 'center' + } +}); + +export const resolveIconName = (icon: string) => { + if (hasIcon(icon)) { + return icon as any; + } + + const aliasedIcon = iconAliases[icon]; + if (aliasedIcon && hasIcon(aliasedIcon)) { + return aliasedIcon as any; + } + + return 'info' as any; +}; + +const getIconColor = (variant: IIcon['variant'], colors: ReturnType<typeof useTheme>['colors'], framed?: boolean) => { + switch (variant) { + case 'danger': + return framed ? colors.statusFontDanger : colors.fontDanger; + case 'secondary': + return colors.fontSecondaryInfo; + case 'warning': + return colors.statusFontWarning; + default: + return colors.fontDefault; + } +}; + +export const Icon = ({ element }: { element: IIcon }) => { + const { colors } = useTheme(); + const { icon, variant = 'default', framed } = element; + const color = getIconColor(variant, colors, framed); + const renderedIcon = <CustomIcon name={resolveIconName(icon)} size={20} color={color} />; + + if (!framed) { + return renderedIcon; + } + + return <View style={[styles.frame, { backgroundColor: colors.surfaceTint }]}>{renderedIcon}</View>; +}; diff --git a/app/containers/UIKit/IconButton.tsx b/app/containers/UIKit/IconButton.tsx new file mode 100644 index 00000000000..9d023c1b6ec --- /dev/null +++ b/app/containers/UIKit/IconButton.tsx @@ -0,0 +1,72 @@ +import React from 'react'; +import { Pressable, StyleSheet } from 'react-native'; +import { type BlockContext } from '@rocket.chat/ui-kit'; + +import ActivityIndicator from '../ActivityIndicator'; +import { BUTTON_HIT_SLOP } from '../message/utils'; +import openLink from '../../lib/methods/helpers/openLink'; +import { useTheme } from '../../theme'; +import { useBlockContext } from './utils'; +import { Icon } from './Icon'; +import { type IIconButton, type IText } from './interfaces'; + +const styles = StyleSheet.create({ + button: { + width: 32, + height: 32, + borderWidth: 1, + borderRadius: 8, + alignItems: 'center', + justifyContent: 'center' + }, + loading: { + padding: 0 + } +}); + +const getLabel = (label?: string | IText, fallback?: string) => { + if (typeof label === 'string') { + return label; + } + + if (label?.text) { + return label.text; + } + + return fallback || 'icon button'; +}; + +export const IconButton = ({ element, context }: { element: IIconButton; context: BlockContext }) => { + const { theme, colors } = useTheme(); + const [{ loading }, action] = useBlockContext(element, context); + const label = getLabel(element.label, element.icon?.icon); + + const onPress = async () => { + if (element.url) { + await Promise.allSettled([action({ value: element.value }), openLink(element.url, theme)]); + return; + } + + await action({ value: element.value }); + }; + + return ( + <Pressable + onPress={onPress} + disabled={loading} + hitSlop={BUTTON_HIT_SLOP} + android_ripple={{ color: colors.surfaceNeutral, borderless: false }} + style={({ pressed }) => [ + styles.button, + { + borderColor: colors.strokeLight, + backgroundColor: colors.surfaceLight, + opacity: pressed ? 0.7 : 1 + } + ]} + accessibilityRole={element.url ? 'link' : 'button'} + accessibilityLabel={label}> + {loading ? <ActivityIndicator style={styles.loading} /> : <Icon element={element.icon} />} + </Pressable> + ); +}; diff --git a/app/containers/UIKit/Image.tsx b/app/containers/UIKit/Image.tsx index bac03b64d3d..a240acb9993 100644 --- a/app/containers/UIKit/Image.tsx +++ b/app/containers/UIKit/Image.tsx @@ -5,7 +5,7 @@ import { BlockContext } from '@rocket.chat/ui-kit'; import ImageContainer from '../message/Components/Attachments/Image'; import Navigation from '../../lib/navigation/appNavigation'; -import { type IThumb, type IImage, type IElement } from './interfaces'; +import { type IThumb, type IImage } from './interfaces'; import { type IAttachment } from '../../definitions'; const styles = StyleSheet.create({ @@ -33,7 +33,7 @@ export const Media = ({ element }: IImage) => { return <ImageContainer file={{ image_url: imageUrl }} showAttachment={showAttachment} />; }; -const genericImage = (element: IElement, context?: number) => { +const genericImage = ({ element, context }: IImage) => { switch (context) { case BlockContext.SECTION: return <Thumb element={element} />; @@ -44,4 +44,4 @@ const genericImage = (element: IElement, context?: number) => { } }; -export const Image = ({ element, context }: IImage) => genericImage(element, context); +export const Image = (props: IImage) => genericImage(props); diff --git a/app/containers/UIKit/InfoCard.test.tsx b/app/containers/UIKit/InfoCard.test.tsx new file mode 100644 index 00000000000..19ef39051da --- /dev/null +++ b/app/containers/UIKit/InfoCard.test.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { Text } from 'react-native'; +import { render } from '@testing-library/react-native'; + +import { InfoCard } from './InfoCard'; + +jest.mock('../../theme', () => ({ + useTheme: () => ({ + colors: { + surfaceTint: '#f7f7f7', + strokeExtraLight: '#e1e1e1', + surfaceLight: '#ffffff' + } + }) +})); + +describe('InfoCard', () => { + it('renders row elements in order and applies row background', () => { + const parser = { + icon: jest.fn((element: any) => <Text>{`icon:${element.icon}`}</Text>), + plain_text: jest.fn((element: any) => <Text>{`text:${element.text}`}</Text>), + mrkdwn: jest.fn((element: any) => <Text>{`md:${element.text}`}</Text>), + icon_button: jest.fn(() => <Text>action</Text>) + }; + + const { getByText, toJSON, UNSAFE_getAllByType } = render( + <InfoCard + type='info_card' + parser={parser as any} + blockId='info-card' + rows={[ + { + background: 'default', + elements: [ + { type: 'icon', icon: 'info', variant: 'default' }, + { type: 'plain_text', text: 'Plain text' }, + { type: 'mrkdwn', text: '*Markdown*' } + ] + } + ]} + /> + ); + + expect(getByText('icon:info')).toBeTruthy(); + expect(getByText('text:Plain text')).toBeTruthy(); + expect(getByText('md:*Markdown*')).toBeTruthy(); + + const allTexts = UNSAFE_getAllByType(Text).map(node => node.props.children); + expect(allTexts).toEqual(expect.arrayContaining(['icon:info', 'text:Plain text', 'md:*Markdown*'])); + + expect(toJSON()).toMatchObject({ + children: expect.arrayContaining([ + expect.objectContaining({ + props: { + style: expect.arrayContaining([expect.objectContaining({ backgroundColor: '#ffffff' })]) + } + }) + ]) + }); + }); + + it('ignores row action rendering for now (non-interactive)', () => { + const parser = { + icon: jest.fn((element: any) => <Text>{`icon:${element.icon}`}</Text>), + plain_text: jest.fn((element: any) => <Text>{`text:${element.text}`}</Text>), + mrkdwn: jest.fn((element: any) => <Text>{`md:${element.text}`}</Text>), + icon_button: jest.fn(() => <Text>action</Text>) + }; + + const { queryByText } = render( + <InfoCard + type='info_card' + parser={parser as any} + rows={[ + { + background: 'default', + elements: [{ type: 'plain_text', text: 'Line' }], + action: { + type: 'icon_button', + actionId: 'act-id', + icon: { type: 'icon', icon: 'phone' } + } as any + } + ]} + /> + ); + + expect(queryByText('text:Line')).toBeTruthy(); + expect(queryByText('action')).toBeNull(); + expect(parser.icon_button).not.toHaveBeenCalled(); + }); +}); diff --git a/app/containers/UIKit/InfoCard.tsx b/app/containers/UIKit/InfoCard.tsx new file mode 100644 index 00000000000..29406cfd60d --- /dev/null +++ b/app/containers/UIKit/InfoCard.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; +import { BlockContext } from '@rocket.chat/ui-kit'; + +import { useTheme } from '../../theme'; +import { type IIcon, type IIconButton, type IInfoCard, type IInfoCardRow } from './interfaces'; + +const styles = StyleSheet.create({ + card: { + borderWidth: StyleSheet.hairlineWidth, + borderRadius: 4, + overflow: 'hidden' + }, + row: { + flexDirection: 'row', + alignItems: 'center', + padding: 16 + }, + rowContent: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + flexWrap: 'wrap' + }, + rowElement: { + marginHorizontal: 4 + } +}); + +const renderRowElement = (parser: IInfoCard['parser'], element: IInfoCardRow['elements'][number], key: string) => { + if (element.type === 'icon' && parser.icon) { + return ( + <View key={key} style={styles.rowElement}> + {parser.icon(element as IIcon, BlockContext.NONE)} + </View> + ); + } + + if (element.type === 'mrkdwn' && parser.mrkdwn) { + return ( + <View key={key} style={styles.rowElement}> + {parser.mrkdwn(element as any, BlockContext.NONE)} + </View> + ); + } + + if (element.type === 'plain_text' && parser.plain_text) { + return ( + <View key={key} style={styles.rowElement}> + {parser.plain_text(element as any, BlockContext.NONE)} + </View> + ); + } + + return null; +}; + +const renderRowAction = (parser: IInfoCard['parser'], action: IIconButton | undefined, _appId?: string, _blockId?: string) => { + if (!action || !parser.icon_button) { + return null; + } + + // TODO: Temporarily removed until we have call history implemented + return null; + + // return parser.icon_button( + // { + // ...action, + // appId: action.appId || appId || '', + // blockId: action.blockId || blockId || '' + // }, + // BlockContext.ACTION + // ); +}; + +export const InfoCard = ({ rows, parser, appId, blockId }: IInfoCard) => { + const { colors } = useTheme(); + + return ( + <View style={[styles.card, { backgroundColor: colors.surfaceTint, borderColor: colors.strokeExtraLight }]}> + {rows.map((row, index) => ( + <View + key={`${blockId || 'info-card'}-${index}`} + style={[ + styles.row, + { + backgroundColor: row.background === 'default' ? colors.surfaceLight : undefined + } + ]}> + <View style={styles.rowContent}> + {row.elements.map((element, elementIndex) => renderRowElement(parser, element, `${index}-${elementIndex}`))} + </View> + {row.action ? renderRowAction(parser, row.action, appId, blockId) : null} + </View> + ))} + </View> + ); +}; diff --git a/app/containers/UIKit/Input.tsx b/app/containers/UIKit/Input.tsx index 9c8aa90d56b..051b4cc55f7 100644 --- a/app/containers/UIKit/Input.tsx +++ b/app/containers/UIKit/Input.tsx @@ -38,7 +38,7 @@ export const Input = ({ element, parser, label, description, error, hint, theme <Text style={[styles.label, { color: error ? themes[theme].fontDanger : themes[theme].fontTitlesLabels }]}>{label}</Text> ) : null} {description ? <Text style={[styles.description, { color: themes[theme].fontSecondaryInfo }]}>{description}</Text> : null} - {parser.renderInputs({ ...element }, BlockContext.FORM, parser)} + {parser.renderInputs({ ...element }, BlockContext.FORM)} {error ? <Text style={[styles.error, { color: themes[theme].fontDanger }]}>{error}</Text> : null} {hint ? <Text style={[styles.hint, { color: themes[theme].fontSecondaryInfo }]}>{hint}</Text> : null} </View> diff --git a/app/containers/UIKit/Section.tsx b/app/containers/UIKit/Section.tsx index 17330e88075..4c5f5fd8c33 100644 --- a/app/containers/UIKit/Section.tsx +++ b/app/containers/UIKit/Section.tsx @@ -25,13 +25,16 @@ const styles = StyleSheet.create({ } }); -const Accessory = ({ element, parser }: IAccessoryComponent) => - parser.renderAccessories({ ...element }, BlockContext.SECTION, parser); +const Accessory = ({ element, parser }: IAccessoryComponent) => parser.renderAccessories({ ...element }, BlockContext.SECTION); const Fields = ({ fields, parser, theme }: IFields) => ( <> - {fields.map(field => ( - <Text style={[styles.text, styles.field, { color: themes[theme].fontDefault }]}>{parser.text(field)}</Text> + {fields.map((field, index) => ( + <Text + key={`${(field as any).type || 'field'}-${index}`} + style={[styles.text, styles.field, { color: themes[theme].fontDefault }]}> + {parser.text(field)} + </Text> ))} </> ); diff --git a/app/containers/UIKit/UiKitMessage.stories.tsx b/app/containers/UIKit/UiKitMessage.stories.tsx index dddce08ff88..0a3b8e9dcb1 100644 --- a/app/containers/UIKit/UiKitMessage.stories.tsx +++ b/app/containers/UIKit/UiKitMessage.stories.tsx @@ -1,6 +1,16 @@ +import { type JSX } from 'react'; +import { ScrollView, View } from 'react-native'; + import MessageContext from '../message/Context'; import { UiKitMessage } from '.'; -import { themes } from '../../lib/constants/colors'; +import { themes, colors } from '../../lib/constants/colors'; +import { longText } from '../../../.rnstorybook/utils'; +import { + BASE_ROW_HEIGHT, + BASE_ROW_HEIGHT_CONDENSED, + ResponsiveLayoutContext +} from '../../lib/hooks/useResponsiveLayout/useResponsiveLayout'; +import { ThemeContext, type TSupportedThemes } from '../../theme'; const user = { id: 'y8bd77ptZswPj3EW8', @@ -14,22 +24,33 @@ export default { title: 'UIKit/UiKitMessage', decorators: [ (Story: any) => ( - <MessageContext.Provider + <ResponsiveLayoutContext.Provider value={{ - user, - baseUrl, - onPress: () => {}, - onLongPress: () => {}, - reactionInit: () => {}, - onErrorPress: () => {}, - replyBroadcast: () => {}, - onReactionPress: () => {}, - onDiscussionPress: () => {}, - onReactionLongPress: () => {}, - threadBadgeColor: themes.light.fontInfo + fontScale: 1, + fontScaleLimited: 1, + isLargeFontScale: false, + rowHeight: BASE_ROW_HEIGHT, + rowHeightCondensed: BASE_ROW_HEIGHT_CONDENSED, + width: 350, + height: 800 }}> - <Story /> - </MessageContext.Provider> + <MessageContext.Provider + value={{ + user, + baseUrl, + onPress: () => {}, + onLongPress: () => {}, + reactionInit: () => {}, + onErrorPress: () => {}, + replyBroadcast: () => {}, + onReactionPress: () => {}, + onDiscussionPress: () => {}, + onReactionLongPress: () => {}, + threadBadgeColor: themes.light.fontInfo + }}> + <Story /> + </MessageContext.Provider> + </ResponsiveLayoutContext.Provider> ) ] }; @@ -513,3 +534,206 @@ export const ActionSelect = () => } ]); ActionSelect.storyName = 'Action - Select'; + +const getInfoCardAction = ({ + appId, + blockId, + icon, + label +}: { + appId?: string; + blockId?: string; + icon: string; + label?: string; +}) => ({ + type: 'icon_button', + actionId: 'open-history', + ...(appId ? { appId } : {}), + ...(blockId ? { blockId } : {}), + label: label ?? 'Call history', + icon: { + type: 'icon', + icon, + variant: 'default' + } +}); + +const ThemedStory = ({ theme, story }: { theme: TSupportedThemes; story: () => JSX.Element }) => ( + <ThemeContext.Provider value={{ theme, colors: colors[theme] }}> + <View style={{ padding: 10, gap: 10, backgroundColor: colors[theme].surfaceTint }}>{story()}</View> + </ThemeContext.Provider> +); + +const ThemedStoryInfoCardList = () => ( + <> + {UiKitMessage([ + { + type: 'info_card', + appId: 'media-call-core', + blockId: 'ended-call', + rows: [ + { + background: 'default', + elements: [ + { type: 'icon', icon: 'phone-off', framed: true, variant: 'secondary' }, + { type: 'mrkdwn', text: 'Call ended', i18n: { key: 'Call_ended_bold' } } + ], + action: getInfoCardAction({ appId: 'media-call-core', blockId: 'ended-call', icon: 'info' }) + }, + { + background: 'secondary', + elements: [{ type: 'mrkdwn', text: '*00:06*' }] + } + ] + } + ])} + {UiKitMessage([ + { + type: 'info_card', + appId: 'media-call-core', + blockId: 'transferred-call', + rows: [ + { + background: 'default', + elements: [ + { type: 'icon', icon: 'arrow-forward', framed: true, variant: 'secondary' }, + { type: 'mrkdwn', text: 'Call transferred', i18n: { key: 'Call_transferred_bold' } } + ] + }, + { + background: 'secondary', + elements: [{ type: 'mrkdwn', text: '*00:06*' }] + } + ] + } + ])} + {UiKitMessage([ + { + type: 'info_card', + appId: 'media-call-core', + blockId: 'not-answered-call', + rows: [ + { + background: 'default', + elements: [ + { type: 'icon', icon: 'phone-question-mark', framed: true, variant: 'warning' }, + { type: 'mrkdwn', text: 'Call not answered', i18n: { key: 'Call_not_answered_bold' } } + ], + action: getInfoCardAction({ appId: 'media-call-core', blockId: 'not-answered-call', icon: 'info' }) + } + ] + } + ])} + {UiKitMessage([ + { + type: 'info_card', + appId: 'media-call-core', + blockId: 'failed-call', + rows: [ + { + background: 'default', + elements: [ + { type: 'icon', icon: 'phone-issue', framed: true, variant: 'danger' }, + { type: 'mrkdwn', text: 'Call failed', i18n: { key: 'Call_failed_bold' } } + ] + } + ] + } + ])} + </> +); +export const InfoCard = () => ( + <ScrollView> + <ThemedStory theme={'light'} story={ThemedStoryInfoCardList} /> + <ThemedStory theme={'dark'} story={ThemedStoryInfoCardList} /> + <ThemedStory theme={'black'} story={ThemedStoryInfoCardList} /> + </ScrollView> +); + +InfoCard.storyName = 'UIKit/UiKitMessage/Info Card'; + +export const InfoCardIcons = () => + UiKitMessage([ + { + type: 'info_card', + blockId: 'multiple-icons', + rows: [ + { + background: 'default', + elements: [ + { type: 'plain_text', text: 'Framed icons' }, + { type: 'icon', icon: 'phone-off', variant: 'default', framed: true }, + { type: 'icon', icon: 'clock', variant: 'warning', framed: true }, + { type: 'icon', icon: 'phone-question-mark', variant: 'warning', framed: true }, + { type: 'icon', icon: 'phone-issue', variant: 'danger', framed: true } + ] + }, + { + background: 'secondary', + elements: [ + { type: 'plain_text', text: 'Icons' }, + { type: 'icon', icon: 'phone-off', variant: 'default' }, + { type: 'icon', icon: 'clock', variant: 'warning' }, + { type: 'icon', icon: 'phone-question-mark', variant: 'warning' }, + { type: 'icon', icon: 'phone-issue', variant: 'danger' }, + { type: 'icon', icon: 'info', variant: 'secondary' } + ] + } + ] + } + ]); +InfoCardIcons.storyName = 'Info Card - Icons'; + +export const InfoCardI18n = () => + UiKitMessage([ + { + type: 'info_card', + blockId: 'i18n-keys', + rows: [ + { + background: 'default', + elements: [{ type: 'mrkdwn', text: 'Call ended', i18n: { key: 'Call_ended_bold' } }] + }, + { + background: 'default', + elements: [{ type: 'mrkdwn', text: 'Call failed', i18n: { key: 'Call_failed_bold' } }] + }, + { + background: 'default', + elements: [{ type: 'mrkdwn', text: 'Call not answered', i18n: { key: 'Call_not_answered_bold' } }] + }, + { + background: 'default', + elements: [{ type: 'mrkdwn', text: 'Call transferred', i18n: { key: 'Call_transferred_bold' } }] + } + ] + } + ]); +InfoCardI18n.storyName = 'Info Card - i18n'; + +export const InfoCardLongText = () => + UiKitMessage([ + { + type: 'info_card', + appId: 'media-call-core', + blockId: 'edge-action-no-ids', + rows: [ + { + background: 'default', + elements: [ + { type: 'icon', icon: 'phone-question-mark', variant: 'warning' }, + { + type: 'plain_text', + text: longText + } + ], + action: getInfoCardAction({ icon: 'info', label: 'Details' }) + }, + { + background: 'secondary', + elements: [{ type: 'plain_text', text: longText }] + } + ] + } + ]); +InfoCardLongText.storyName = 'Info Card - Long text'; diff --git a/app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceBaseContainer.tsx b/app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceBaseContainer.tsx index 6fa9c2b14da..cfca79af54f 100644 --- a/app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceBaseContainer.tsx +++ b/app/containers/UIKit/VideoConferenceBlock/components/VideoConferenceBaseContainer.tsx @@ -17,7 +17,7 @@ export const VideoConferenceBaseContainer = ({ variant, children }: VideoConfMes const iconStyle: { [key: string]: { icon: TIconsName; color: string; backgroundColor: string; label: string } } = { ended: { - icon: 'phone-end', + icon: 'phone-off', color: colors.fontSecondaryInfo, backgroundColor: colors.surfaceNeutral, label: i18n.t('Call_ended') diff --git a/app/containers/UIKit/__snapshots__/UiKitMessage.test.tsx.snap b/app/containers/UIKit/__snapshots__/UiKitMessage.test.tsx.snap index e7cc5f0eccd..4b2e2334d86 100644 --- a/app/containers/UIKit/__snapshots__/UiKitMessage.test.tsx.snap +++ b/app/containers/UIKit/__snapshots__/UiKitMessage.test.tsx.snap @@ -2,290 +2,504 @@ exports[`Story Snapshots: ActionButton should match snapshot 1`] = ` [ - <View - accessibilityLabel="Approve" - accessibilityRole="button" - accessibilityState={ - { - "busy": undefined, - "checked": undefined, - "disabled": false, - "expanded": undefined, - "selected": undefined, - } - } - accessibilityValue={ - { - "max": undefined, - "min": undefined, - "now": undefined, - "text": undefined, + <View> + <View + accessibilityLabel="Approve" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } } - } - accessible={true} - collapsable={false} - focusable={true} - onClick={[Function]} - onResponderGrant={[Function]} - onResponderMove={[Function]} - onResponderRelease={[Function]} - onResponderTerminate={[Function]} - onResponderTerminationRequest={[Function]} - onStartShouldSetResponder={[Function]} - style={ - { - "backgroundColor": "#156FF5", - "borderRadius": 4, - "justifyContent": "center", - "marginBottom": 16, - "opacity": 1, - "paddingHorizontal": 16, - "paddingVertical": 14, + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } } - } - > - <Text + accessible={true} + collapsable={false} + focusable={true} + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} style={ - [ - { - "color": "#FFFFFF", - "fontSize": 16, - }, - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontWeight": "500", - "textAlign": "center", - }, - undefined, - ] + { + "backgroundColor": "#156FF5", + "borderRadius": 4, + "justifyContent": "center", + "marginBottom": 16, + "opacity": 1, + "paddingHorizontal": 16, + "paddingVertical": 14, + } } > - Approve - </Text> + <Text + style={ + [ + { + "color": "#FFFFFF", + "fontSize": 16, + }, + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "500", + "textAlign": "center", + }, + undefined, + ] + } + > + Approve + </Text> + </View> </View>, - <View - accessibilityLabel="Deny" - accessibilityRole="button" - accessibilityState={ - { - "busy": undefined, - "checked": undefined, - "disabled": false, - "expanded": undefined, - "selected": undefined, - } - } - accessibilityValue={ - { - "max": undefined, - "min": undefined, - "now": undefined, - "text": undefined, + <View> + <View + accessibilityLabel="Deny" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } } - } - accessible={true} - collapsable={false} - focusable={true} - onClick={[Function]} - onResponderGrant={[Function]} - onResponderMove={[Function]} - onResponderRelease={[Function]} - onResponderTerminate={[Function]} - onResponderTerminationRequest={[Function]} - onStartShouldSetResponder={[Function]} - style={ - { - "backgroundColor": "#E4E7EA", - "borderRadius": 4, - "justifyContent": "center", - "marginBottom": 16, - "opacity": 1, - "paddingHorizontal": 16, - "paddingVertical": 14, + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } } - } - > - <Text + accessible={true} + collapsable={false} + focusable={true} + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} style={ - [ - { - "color": "#2F343D", - "fontSize": 16, - }, - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontWeight": "500", - "textAlign": "center", - }, - undefined, - ] + { + "backgroundColor": "#E4E7EA", + "borderRadius": 4, + "justifyContent": "center", + "marginBottom": 16, + "opacity": 1, + "paddingHorizontal": 16, + "paddingVertical": 14, + } } > - Deny - </Text> + <Text + style={ + [ + { + "color": "#2F343D", + "fontSize": 16, + }, + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "500", + "textAlign": "center", + }, + undefined, + ] + } + > + Deny + </Text> + </View> </View>, - <View - accessibilityLabel="Deny" - accessibilityRole="button" - accessibilityState={ - { - "busy": undefined, - "checked": undefined, - "disabled": false, - "expanded": undefined, - "selected": undefined, + <View> + <View + accessibilityLabel="Deny" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } } - } - accessibilityValue={ - { - "max": undefined, - "min": undefined, - "now": undefined, - "text": undefined, + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } } - } - accessible={true} - collapsable={false} - focusable={true} - onClick={[Function]} - onResponderGrant={[Function]} - onResponderMove={[Function]} - onResponderRelease={[Function]} - onResponderTerminate={[Function]} - onResponderTerminationRequest={[Function]} - onStartShouldSetResponder={[Function]} - style={ - { - "backgroundColor": "#E4E7EA", - "borderRadius": 4, - "justifyContent": "center", - "marginBottom": 16, - "opacity": 1, - "paddingHorizontal": 16, - "paddingVertical": 14, - } - } - > - <Text + accessible={true} + collapsable={false} + focusable={true} + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} style={ - [ - { - "color": "#2F343D", - "fontSize": 16, - }, - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontWeight": "500", - "textAlign": "center", - }, - undefined, - ] + { + "backgroundColor": "#E4E7EA", + "borderRadius": 4, + "justifyContent": "center", + "marginBottom": 16, + "opacity": 1, + "paddingHorizontal": 16, + "paddingVertical": 14, + } } > - Deny - </Text> + <Text + style={ + [ + { + "color": "#2F343D", + "fontSize": 16, + }, + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "500", + "textAlign": "center", + }, + undefined, + ] + } + > + Deny + </Text> + </View> </View>, - <View - accessibilityLabel="Deny" - accessibilityRole="button" - accessibilityState={ - { - "busy": undefined, - "checked": undefined, - "disabled": false, - "expanded": undefined, - "selected": undefined, + <View> + <View + accessibilityLabel="Deny" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } } - } - accessibilityValue={ - { - "max": undefined, - "min": undefined, - "now": undefined, - "text": undefined, + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } } - } - accessible={true} - collapsable={false} - focusable={true} - onClick={[Function]} - onResponderGrant={[Function]} - onResponderMove={[Function]} - onResponderRelease={[Function]} - onResponderTerminate={[Function]} - onResponderTerminationRequest={[Function]} - onStartShouldSetResponder={[Function]} - style={ - { - "backgroundColor": "#E4E7EA", - "borderRadius": 4, - "justifyContent": "center", - "marginBottom": 16, - "opacity": 1, - "paddingHorizontal": 16, - "paddingVertical": 14, + accessible={true} + collapsable={false} + focusable={true} + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "backgroundColor": "#E4E7EA", + "borderRadius": 4, + "justifyContent": "center", + "marginBottom": 16, + "opacity": 1, + "paddingHorizontal": 16, + "paddingVertical": 14, + } } - } - > - <Text + > + <Text + style={ + [ + { + "color": "#2F343D", + "fontSize": 16, + }, + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "500", + "textAlign": "center", + }, + undefined, + ] + } + > + Deny + </Text> + </View> + </View>, + <View> + <View + accessibilityLabel="Deny" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} style={ - [ - { - "color": "#2F343D", - "fontSize": 16, - }, - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontWeight": "500", - "textAlign": "center", - }, - undefined, - ] + { + "backgroundColor": "#E4E7EA", + "borderRadius": 4, + "justifyContent": "center", + "marginBottom": 16, + "opacity": 1, + "paddingHorizontal": 16, + "paddingVertical": 14, + } } > - Deny - </Text> + <Text + style={ + [ + { + "color": "#2F343D", + "fontSize": 16, + }, + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "500", + "textAlign": "center", + }, + undefined, + ] + } + > + Deny + </Text> + </View> </View>, <View - accessibilityLabel="Deny" - accessibilityRole="button" - accessibilityState={ - { - "busy": undefined, - "checked": undefined, - "disabled": false, - "expanded": undefined, - "selected": undefined, - } - } - accessibilityValue={ + style={ { - "max": undefined, - "min": undefined, - "now": undefined, - "text": undefined, + "height": 0, + "overflow": "hidden", } } - accessible={true} - collapsable={false} - focusable={true} - onClick={[Function]} - onResponderGrant={[Function]} - onResponderMove={[Function]} - onResponderRelease={[Function]} - onResponderTerminate={[Function]} + > + <View + accessibilityLabel="Deny" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "backgroundColor": "#E4E7EA", + "borderRadius": 4, + "justifyContent": "center", + "marginBottom": 16, + "opacity": 1, + "paddingHorizontal": 16, + "paddingVertical": 14, + } + } + > + <Text + style={ + [ + { + "color": "#2F343D", + "fontSize": 16, + }, + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "500", + "textAlign": "center", + }, + undefined, + ] + } + > + Deny + </Text> + </View> + </View>, + <View + style={ + { + "height": 0, + "overflow": "hidden", + } + } + > + <View + accessibilityLabel="Deny" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": false, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "backgroundColor": "#E4E7EA", + "borderRadius": 4, + "justifyContent": "center", + "marginBottom": 16, + "opacity": 1, + "paddingHorizontal": 16, + "paddingVertical": 14, + } + } + > + <Text + style={ + [ + { + "color": "#2F343D", + "fontSize": 16, + }, + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "500", + "textAlign": "center", + }, + undefined, + ] + } + > + Deny + </Text> + </View> + </View>, + <View + accessibilityLabel="Show more" + accessibilityRole="button" + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} onResponderTerminationRequest={[Function]} onStartShouldSetResponder={[Function]} style={ { - "backgroundColor": "#E4E7EA", + "backgroundColor": "#156FF5", "borderRadius": 4, "justifyContent": "center", - "marginBottom": 16, + "marginBottom": 12, "opacity": 1, "paddingHorizontal": 16, "paddingVertical": 14, @@ -296,402 +510,4135 @@ exports[`Story Snapshots: ActionButton should match snapshot 1`] = ` style={ [ { - "color": "#2F343D", + "color": "#FFFFFF", "fontSize": 16, }, { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontWeight": "500", - "textAlign": "center", - }, - undefined, - ] - } - > - Deny - </Text> - </View>, - <View - accessibilityLabel="Show more" - accessibilityRole="button" - accessibilityState={ - { - "busy": undefined, - "checked": undefined, - "disabled": undefined, - "expanded": undefined, - "selected": undefined, - } - } - accessibilityValue={ - { - "max": undefined, - "min": undefined, - "now": undefined, - "text": undefined, - } - } - accessible={true} - collapsable={false} - focusable={true} - onClick={[Function]} - onResponderGrant={[Function]} - onResponderMove={[Function]} - onResponderRelease={[Function]} - onResponderTerminate={[Function]} - onResponderTerminationRequest={[Function]} - onStartShouldSetResponder={[Function]} - style={ - { - "backgroundColor": "#156FF5", - "borderRadius": 4, - "justifyContent": "center", - "marginBottom": 12, - "opacity": 1, - "paddingHorizontal": 16, - "paddingVertical": 14, - } - } - > - <Text - style={ - [ + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "500", + "textAlign": "center", + }, + undefined, + ] + } + > + Show more + </Text> + </View>, +] +`; + +exports[`Story Snapshots: ActionSelect should match snapshot 1`] = ` +[ + <View />, + <View />, + <View />, + <View> + <View + style={ + [ + { + "alignSelf": "stretch", + }, + { + "backgroundColor": "#FFFFFF", + "borderColor": "#CBCED1", + "borderRadius": 4, + "borderWidth": 1, + "height": 48, + "justifyContent": "center", + "marginBottom": 16, + "paddingHorizontal": 16, + }, + ] + } + > + <View + accessibilityState={ + { + "busy": undefined, + "checked": undefined, + "disabled": undefined, + "expanded": undefined, + "selected": undefined, + } + } + accessibilityValue={ + { + "max": undefined, + "min": undefined, + "now": undefined, + "text": undefined, + } + } + accessible={true} + collapsable={false} + focusable={true} + onClick={[Function]} + onResponderGrant={[Function]} + onResponderMove={[Function]} + onResponderRelease={[Function]} + onResponderTerminate={[Function]} + onResponderTerminationRequest={[Function]} + onStartShouldSetResponder={[Function]} + style={ + { + "opacity": 1, + } + } + testID="ios_touchable_wrapper" + > + <View + pointerEvents="box-only" + > + <TextInput + editable={false} + style={ + { + "backgroundColor": "transparent", + "color": "#6C727A", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "textAlign": "left", + } + } + testID="text_input" + value="Select an item" + /> + <View + style={ + [ + { + "position": "absolute", + "right": 0, + }, + undefined, + ] + } + testID="icon_container" + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 22, + }, + [ + { + "lineHeight": 22, + }, + false, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + </View> + </View> + </View>, +] +`; + +exports[`Story Snapshots: Fields should match snapshot 1`] = ` +<View + style={ + [ + { + "marginBottom": 8, + }, + { + "justifyContent": "center", + }, + ] + } +> + <Text + style={ + [ + { + "flex": 1, + "padding": 4, + }, + { + "marginVertical": 6, + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + "textAlignVertical": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + *this is plain_text text* + </Text> + </Text> + <Text + style={ + [ + { + "flex": 1, + "padding": 4, + }, + { + "marginVertical": 6, + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + "textAlignVertical": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + *this is plain_text text* + </Text> + </Text> + <Text + style={ + [ + { + "flex": 1, + "padding": 4, + }, + { + "marginVertical": 6, + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + "textAlignVertical": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + *this is plain_text text* + </Text> + </Text> + <Text + style={ + [ + { + "flex": 1, + "padding": 4, + }, + { + "marginVertical": 6, + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + "textAlignVertical": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + *this is plain_text text* + </Text> + </Text> + <Text + style={ + [ + { + "flex": 1, + "padding": 4, + }, + { + "marginVertical": 6, + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + "textAlignVertical": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + *this is plain_text text* + </Text> + </Text> +</View> +`; + +exports[`Story Snapshots: InfoCard should match snapshot 1`] = ` +<RCTScrollView> + <View> + <View + style={ + { + "backgroundColor": "#F7F8FA", + "gap": 10, + "padding": 10, + } + } + > + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#F7F8FA", + "borderColor": "#EBECEF", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#F7F8FA", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call ended" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call ended + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": undefined, + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="00:06" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + 00:06 + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#F7F8FA", + "borderColor": "#EBECEF", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#F7F8FA", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call transferred" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call transferred + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": undefined, + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="00:06" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + 00:06 + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#F7F8FA", + "borderColor": "#EBECEF", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#F7F8FA", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#8E6300", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call not answered" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call not answered + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#F7F8FA", + "borderColor": "#EBECEF", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#F7F8FA", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#9B1325", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call failed" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call failed + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + </View> + <View + style={ + { + "backgroundColor": "#1F2329", + "gap": 10, + "padding": 10, + } + } + > + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#1F2329", + "borderColor": "#2F343D", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#262931", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#1F2329", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#9EA2A8", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#C1C7D0", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call ended" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#C1C7D0", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call ended + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": undefined, + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#C1C7D0", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="00:06" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#C1C7D0", + }, + { + "fontSize": 14, + }, + ] + } + > + 00:06 + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#1F2329", + "borderColor": "#2F343D", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#262931", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#1F2329", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#9EA2A8", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#C1C7D0", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call transferred" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#C1C7D0", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call transferred + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": undefined, + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#C1C7D0", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="00:06" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#C1C7D0", + }, + { + "fontSize": 14, + }, + ] + } + > + 00:06 + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#1F2329", + "borderColor": "#2F343D", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#262931", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#1F2329", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#C7AA66", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#C1C7D0", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call not answered" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#C1C7D0", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call not answered + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#1F2329", + "borderColor": "#2F343D", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#262931", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#1F2329", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D88892", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#C1C7D0", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call failed" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#C1C7D0", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call failed + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + </View> + <View + style={ + { + "backgroundColor": "#16181a", + "gap": 10, + "padding": 10, + } + } + > + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#16181a", + "borderColor": "#2F343D", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#0d0d0d", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#16181a", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#9EA2A8", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#E4E7EA", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call ended" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#E4E7EA", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call ended + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": undefined, + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#E4E7EA", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="00:06" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#E4E7EA", + }, + { + "fontSize": 14, + }, + ] + } + > + 00:06 + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#16181a", + "borderColor": "#2F343D", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#0d0d0d", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#16181a", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#9EA2A8", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#E4E7EA", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call transferred" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#E4E7EA", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call transferred + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": undefined, + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#E4E7EA", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="00:06" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#E4E7EA", + }, + { + "fontSize": 14, + }, + ] + } + > + 00:06 + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#16181a", + "borderColor": "#2F343D", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#0d0d0d", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#16181a", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#C7AA66", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#E4E7EA", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call not answered" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#E4E7EA", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call not answered + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#16181a", + "borderColor": "#2F343D", + }, + ] + } + > + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#0d0d0d", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#16181a", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D88892", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#E4E7EA", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call failed" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#E4E7EA", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call failed + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + </View> + </View> + </View> +</RCTScrollView> +`; + +exports[`Story Snapshots: InfoCardI18n should match snapshot 1`] = ` +<View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#F7F8FA", + "borderColor": "#EBECEF", + }, + ] + } +> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call ended" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call ended + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call failed" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call failed + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call not answered" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call not answered + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Voice call transferred" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "fontSize": 14, + }, + ] + } + > + Voice call transferred + </Text> + </Text> + </Text> + </Text> + </View> + </View> + </View> + </View> +</View> +`; + +exports[`Story Snapshots: InfoCardIcons should match snapshot 1`] = ` +<View + style={ + [ + { + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", + }, + { + "backgroundColor": "#F7F8FA", + "borderColor": "#EBECEF", + }, + ] + } +> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + "textAlignVertical": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Framed icons + </Text> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#F7F8FA", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#F7F8FA", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#8E6300", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#F7F8FA", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#8E6300", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <View + style={ + [ + { + "alignItems": "center", + "borderRadius": 4, + "height": 28, + "justifyContent": "center", + "width": 28, + }, + { + "backgroundColor": "#F7F8FA", + }, + ] + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#9B1325", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + </View> + </View> + <View + style={ + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": undefined, + }, + ] + } + > + <View + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } + > + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + "textAlignVertical": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Icons + </Text> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#2F343D", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#8E6300", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <View + style={ + { + "marginHorizontal": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#8E6300", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <View + style={ { - "color": "#FFFFFF", - "fontSize": 16, - }, + "marginHorizontal": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#D40C26", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + <View + style={ { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontWeight": "500", - "textAlign": "center", - }, - undefined, - ] - } - > - Show more - </Text> - </View>, -] + "marginHorizontal": 4, + } + } + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#6C727A", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> + </View> + </View> +</View> `; -exports[`Story Snapshots: ActionSelect should match snapshot 1`] = ` +exports[`Story Snapshots: InfoCardLongText should match snapshot 1`] = ` <View style={ [ { - "alignSelf": "stretch", + "borderRadius": 4, + "borderWidth": 0.5, + "overflow": "hidden", }, { - "backgroundColor": "#FFFFFF", - "borderColor": "#CBCED1", - "borderRadius": 4, - "borderWidth": 1, - "height": 48, - "justifyContent": "center", - "marginBottom": 16, - "paddingHorizontal": 16, + "backgroundColor": "#F7F8FA", + "borderColor": "#EBECEF", }, ] } > <View - accessibilityState={ - { - "busy": undefined, - "checked": undefined, - "disabled": undefined, - "expanded": undefined, - "selected": undefined, - } - } - accessibilityValue={ - { - "max": undefined, - "min": undefined, - "now": undefined, - "text": undefined, - } - } - accessible={true} - collapsable={false} - focusable={true} - onClick={[Function]} - onResponderGrant={[Function]} - onResponderMove={[Function]} - onResponderRelease={[Function]} - onResponderTerminate={[Function]} - onResponderTerminationRequest={[Function]} - onStartShouldSetResponder={[Function]} style={ - { - "opacity": 1, - } + [ + { + "alignItems": "center", + "flexDirection": "row", + "padding": 16, + }, + { + "backgroundColor": "#FFFFFF", + }, + ] } - testID="ios_touchable_wrapper" > <View - pointerEvents="box-only" + style={ + { + "alignItems": "center", + "flex": 1, + "flexDirection": "row", + "flexWrap": "wrap", + } + } > - <TextInput - editable={false} + <View style={ { - "backgroundColor": "transparent", - "color": "#6C727A", - "fontFamily": "Inter", - "fontSize": 16, - "fontWeight": "400", - "textAlign": "left", + "marginHorizontal": 4, } } - testID="text_input" - value="Select an item" - /> + > + <Text + allowFontScaling={false} + selectable={false} + style={ + [ + { + "color": "#8E6300", + "fontSize": 20, + }, + [ + { + "lineHeight": 20, + }, + undefined, + ], + { + "fontFamily": "custom", + "fontStyle": "normal", + "fontWeight": "normal", + }, + {}, + ] + } + > +  + </Text> + </View> <View style={ - [ - { - "position": "absolute", - "right": 0, - }, - undefined, - ] + { + "marginHorizontal": 4, + } } - testID="icon_container" > <Text - allowFontScaling={false} - selectable={false} style={ [ { - "color": "#6C727A", - "fontSize": 22, + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + "textAlignVertical": "center", }, - [ - { - "lineHeight": 22, - }, - false, - ], { - "fontFamily": "custom", - "fontStyle": "normal", - "fontWeight": "normal", + "color": "#2F343D", }, - {}, ] } > -  + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries </Text> </View> </View> </View> -</View> -`; - -exports[`Story Snapshots: Fields should match snapshot 1`] = ` -<View - style={ - [ - { - "marginBottom": 8, - }, - { - "justifyContent": "center", - }, - ] - } -> - <Text - style={ - [ - { - "flex": 1, - "padding": 4, - }, - { - "marginVertical": 6, - }, - { - "color": "#2F343D", - }, - ] - } - > - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 16, - "fontWeight": "400", - "lineHeight": 22, - "textAlign": "left", - "textAlignVertical": "center", - }, - { - "color": "#2F343D", - }, - ] - } - > - *this is plain_text text* - </Text> - </Text> - <Text - style={ - [ - { - "flex": 1, - "padding": 4, - }, - { - "marginVertical": 6, - }, - { - "color": "#2F343D", - }, - ] - } - > - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 16, - "fontWeight": "400", - "lineHeight": 22, - "textAlign": "left", - "textAlignVertical": "center", - }, - { - "color": "#2F343D", - }, - ] - } - > - *this is plain_text text* - </Text> - </Text> - <Text + <View style={ [ { - "flex": 1, - "padding": 4, - }, - { - "marginVertical": 6, + "alignItems": "center", + "flexDirection": "row", + "padding": 16, }, { - "color": "#2F343D", + "backgroundColor": undefined, }, ] } > - <Text + <View style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 16, - "fontWeight": "400", - "lineHeight": 22, - "textAlign": "left", - "textAlignVertical": "center", - }, - { - "color": "#2F343D", - }, - ] - } - > - *this is plain_text text* - </Text> - </Text> - <Text - style={ - [ { + "alignItems": "center", "flex": 1, - "padding": 4, - }, - { - "marginVertical": 6, - }, - { - "color": "#2F343D", - }, - ] - } - > - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 16, - "fontWeight": "400", - "lineHeight": 22, - "textAlign": "left", - "textAlignVertical": "center", - }, - { - "color": "#2F343D", - }, - ] + "flexDirection": "row", + "flexWrap": "wrap", + } } > - *this is plain_text text* - </Text> - </Text> - <Text - style={ - [ - { - "flex": 1, - "padding": 4, - }, - { - "marginVertical": 6, - }, - { - "color": "#2F343D", - }, - ] - } - > - <Text - style={ - [ - { - "backgroundColor": "transparent", - "fontFamily": "Inter", - "fontSize": 16, - "fontWeight": "400", - "lineHeight": 22, - "textAlign": "left", - "textAlignVertical": "center", - }, + <View + style={ { - "color": "#2F343D", - }, - ] - } - > - *this is plain_text text* - </Text> - </Text> + "marginHorizontal": 4, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + "textAlignVertical": "center", + }, + { + "color": "#2F343D", + }, + ] + } + > + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries + </Text> + </View> + </View> + </View> </View> `; @@ -763,6 +4710,9 @@ exports[`Story Snapshots: Section should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -843,6 +4793,9 @@ exports[`Story Snapshots: SectionButton should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -985,6 +4938,9 @@ exports[`Story Snapshots: SectionDatePicker should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1137,6 +5093,9 @@ exports[`Story Snapshots: SectionMarkdownList should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1155,6 +5114,9 @@ exports[`Story Snapshots: SectionMarkdownList should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1242,6 +5204,9 @@ exports[`Story Snapshots: SectionMarkdownList should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1325,6 +5290,9 @@ exports[`Story Snapshots: SectionMultiSelect should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1464,6 +5432,9 @@ exports[`Story Snapshots: SectionMultiSelect should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1607,6 +5578,9 @@ exports[`Story Snapshots: SectionOverflow should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1757,6 +5731,9 @@ exports[`Story Snapshots: SectionSelect should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > diff --git a/app/containers/UIKit/__snapshots__/UiKitModal.test.tsx.snap b/app/containers/UIKit/__snapshots__/UiKitModal.test.tsx.snap index f56a0b1db77..dca0d71f894 100644 --- a/app/containers/UIKit/__snapshots__/UiKitModal.test.tsx.snap +++ b/app/containers/UIKit/__snapshots__/UiKitModal.test.tsx.snap @@ -173,6 +173,9 @@ exports[`Story Snapshots: ModalActions should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -920,6 +923,9 @@ exports[`Story Snapshots: ModalContextsDividers should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1067,6 +1073,9 @@ exports[`Story Snapshots: ModalContextsDividers should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1214,6 +1223,9 @@ exports[`Story Snapshots: ModalContextsDividers should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -1889,6 +1901,9 @@ exports[`Story Snapshots: ModalFormTextArea should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -2851,6 +2866,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -2869,6 +2887,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -2916,6 +2937,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -2943,6 +2967,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -2961,6 +2988,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3008,6 +3038,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3035,6 +3068,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3053,6 +3089,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3191,6 +3230,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3239,6 +3281,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3326,6 +3371,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3374,6 +3422,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3461,6 +3512,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3509,6 +3563,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3596,6 +3653,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3644,6 +3704,9 @@ exports[`Story Snapshots: ModalSectionAccessories should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3736,6 +3799,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3754,6 +3820,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3820,6 +3889,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3836,6 +3908,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` "lineHeight": 22, "textAlign": "left", }, + { + "fontSize": 14, + }, { "color": "#2F343D", }, @@ -3951,6 +4026,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -3999,6 +4077,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -4081,6 +4162,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -4129,6 +4213,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -4224,6 +4311,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -4272,6 +4362,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -4354,6 +4447,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > @@ -4402,6 +4498,9 @@ exports[`Story Snapshots: ModalSectionSelects should match snapshot 1`] = ` { "color": "#2F343D", }, + { + "fontSize": 14, + }, ] } > diff --git a/app/containers/UIKit/index.tsx b/app/containers/UIKit/index.tsx index aae5e53f061..9f57c0afbde 100644 --- a/app/containers/UIKit/index.tsx +++ b/app/containers/UIKit/index.tsx @@ -27,9 +27,24 @@ import { MultiSelect } from './MultiSelect'; import { Input } from './Input'; import { DatePicker } from './DatePicker'; import { Overflow } from './Overflow'; +import { Icon } from './Icon'; +import { IconButton } from './IconButton'; +import { InfoCard } from './InfoCard'; import { ThemeContext } from '../../theme'; -import { type IActions, type IButton, type IElement, type IInputIndex, type IParser, type ISection } from './interfaces'; +import { + type IActions, + type IButton, + type IContext, + type IElement, + type IIcon, + type IIconButton, + type IInfoCard, + type IInputIndex, + type IParser, + type ISection +} from './interfaces'; import VideoConferenceBlock from './VideoConferenceBlock'; +import I18n from '../../i18n'; const styles = StyleSheet.create({ input: { @@ -52,6 +67,13 @@ const styles = StyleSheet.create({ const plainText = ({ text } = { text: '' }) => text; class MessageParser extends UiKitParserMessage<React.ReactElement> { + constructor() { + super(); + // Compatibility for @rocket.chat/ui-kit@0.39.0 where info_card is exported + // but still missing from message allowed layout block types. + this.allowedLayoutBlockTypes.add('info_card' as any); + } + get current() { return this as unknown as IParser; } @@ -66,15 +88,15 @@ class MessageParser extends UiKitParserMessage<React.ReactElement> { return <Text style={[styles.text, { color: themes[theme].fontDefault }]}>{element.text}</Text>; } - mrkdwn(element: IMarkdown, context: BlockContext) { + mrkdwn(element: IMarkdown, context: BlockContext): React.ReactElement { const isContext = context === BlockContext.CONTEXT; if (isContext) { return <MarkdownPreview msg={element.text} numberOfLines={0} />; } - return <Markdown msg={element.text} />; + return <Markdown msg={element.i18n ? I18n.t(element.i18n.key) : element.text} textStyle={{ fontSize: 14 }} />; } - button(element: IButton, context: BlockContext) { + button(element: IButton, context: BlockContext): React.ReactElement { const { text, value, actionId, style } = element; const [{ loading }, action] = useBlockContext(element, context); return ( @@ -89,25 +111,36 @@ class MessageParser extends UiKitParserMessage<React.ReactElement> { ); } - divider() { + icon(element: IIcon, _context: BlockContext): React.ReactElement { + return <Icon element={element} />; + } + + icon_button(element: IIconButton, context: BlockContext): React.ReactElement { + return <IconButton element={element} context={context} />; + } + + divider(): React.ReactElement { return <Divider />; } - section(args: ISection) { + section(args: ISection): React.ReactElement { return <Section {...args} parser={this.current} />; } - actions(args: IActions) { + actions(args: IActions): React.ReactElement { return <Actions {...args} parser={this.current} />; } - overflow(element: IElement, context: BlockContext) { - const [{ loading }, action] = useBlockContext(element, context); + overflow(element: IElement, context: BlockContext): React.ReactElement { + const [{ loading }, action] = useBlockContext({ ...element, actionId: element.actionId || '' }, context); return <Overflow element={element} context={context} loading={loading} action={action} parser={this.current} />; } - datePicker(element: IElement, context: BlockContext) { - const [{ loading, value, error, language }, action] = useBlockContext(element, context); + datePicker(element: IElement, context: BlockContext): React.ReactElement { + const [{ loading, value, error, language }, action] = useBlockContext( + { ...element, actionId: element.actionId || '' }, + context + ); return ( <DatePicker element={element} @@ -121,32 +154,36 @@ class MessageParser extends UiKitParserMessage<React.ReactElement> { ); } - image(element: IElement, context: BlockContext) { + image(element: IElement, context: BlockContext): React.ReactElement { return <Image element={element} context={context} />; } - context(args: any) { + context(args: IContext): React.ReactElement { const { theme } = useContext(ThemeContext); - return <Context {...args} theme={theme} parser={this} />; + return <Context {...args} theme={theme} parser={this.current} />; + } + + info_card(args: IInfoCard): React.ReactElement { + return <InfoCard {...args} parser={this.current} />; } - multiStaticSelect(element: IElement, context: BlockContext) { - const [{ loading, value }, action] = useBlockContext(element, context); + multiStaticSelect(element: IElement, context: BlockContext): React.ReactElement { + const [{ loading, value }, action] = useBlockContext({ ...element, actionId: element.actionId || '' }, context); const valueFiltered = element?.options?.filter(option => value?.includes(option.value)); return <MultiSelect {...element} value={valueFiltered} onChange={action} context={context} loading={loading} multiselect />; } - staticSelect(element: IElement, context: BlockContext) { - const [{ loading, value }, action] = useBlockContext(element, context); + staticSelect(element: IElement, context: BlockContext): React.ReactElement { + const [{ loading, value }, action] = useBlockContext({ ...element, actionId: element.actionId || '' }, context); return <Select {...element} value={value} onChange={action} loading={loading} />; } - selectInput(element: IElement, context: BlockContext) { - const [{ loading, value }, action] = useBlockContext(element, context); + selectInput(element: IElement, context: BlockContext): React.ReactElement { + const [{ loading, value }, action] = useBlockContext({ ...element, actionId: element.actionId || '' }, context); return <MultiSelect {...element} value={value} onChange={action} context={context} loading={loading} />; } - video_conf(element: IElement & { callId: string }) { + video_conf(element: IElement & { callId: string }): React.ReactElement { return <VideoConferenceBlock callId={element.callId} blockId={element.blockId!} />; } } @@ -166,8 +203,8 @@ class ModalParser extends UiKitParserModal<React.ReactElement> { return this as unknown as IParser; } - input({ element, blockId, appId, label, description, hint }: IInputIndex, context: number) { - const [{ error }] = useBlockContext({ ...element, appId, blockId }, context); + input({ element, blockId, appId, label, description, hint }: IInputIndex, context: number): React.ReactElement { + const [{ error }] = useBlockContext({ ...element, appId, blockId, actionId: element.actionId || '' }, context); const { theme } = useContext(ThemeContext); return ( <Input @@ -182,12 +219,12 @@ class ModalParser extends UiKitParserModal<React.ReactElement> { ); } - image(element: IElement, context: BlockContext) { + image(element: IElement, context: BlockContext): React.ReactElement { return <Image element={element} context={context} />; } - plainInput(element: IElement, context: BlockContext) { - const [{ loading, value, error }, action] = useBlockContext(element, context); + plainInput(element: IElement, context: BlockContext): React.ReactElement { + const [{ loading, value, error }, action] = useBlockContext({ ...element, actionId: element.actionId || '' }, context); const { multiline, actionId, placeholder } = element; return ( <FormTextInput diff --git a/app/containers/UIKit/interactionAdapters.test.ts b/app/containers/UIKit/interactionAdapters.test.ts new file mode 100644 index 00000000000..18785a97c02 --- /dev/null +++ b/app/containers/UIKit/interactionAdapters.test.ts @@ -0,0 +1,93 @@ +import { ActionTypes } from './interfaces'; +import { toServerModalInteractionType, toUserInteraction } from './interactionAdapters'; + +describe('interactionAdapters', () => { + describe('toUserInteraction', () => { + it('maps message block action with required metadata', () => { + const interaction = toUserInteraction({ + type: ActionTypes.ACTION, + actionId: 'action-id', + blockId: 'block-id', + value: 'old-value', + payload: 'new-value', + container: { type: 'message', id: 'container-id' }, + mid: 'message-id', + rid: 'room-id', + triggerId: 'trigger-id' + }); + + expect(interaction).toEqual({ + type: 'blockAction', + actionId: 'action-id', + payload: { + blockId: 'block-id', + value: 'new-value' + }, + container: { + type: 'message', + id: 'container-id' + }, + mid: 'message-id', + rid: 'room-id', + triggerId: 'trigger-id' + }); + }); + + it('maps view block action and defaults blockId', () => { + const interaction = toUserInteraction({ + type: ActionTypes.ACTION, + actionId: 'action-id', + container: { type: 'view', id: 'view-id' }, + value: 'value', + triggerId: 'trigger-id' + }); + + expect(interaction).toEqual({ + type: 'blockAction', + actionId: 'action-id', + payload: { + blockId: 'default', + value: 'value' + }, + container: { + type: 'view', + id: 'view-id' + }, + triggerId: 'trigger-id' + }); + }); + + it('throws when submit interaction has no viewId', () => { + expect(() => + toUserInteraction({ + type: ActionTypes.SUBMIT, + payload: { view: { id: 'view-id', state: {} } }, + triggerId: 'trigger-id' + } as any) + ).toThrow('viewId is required for view interactions'); + }); + + it('throws when close interaction has no viewId', () => { + expect(() => + toUserInteraction({ + type: ActionTypes.CLOSED, + view: { id: 'view-id', state: {} as any } as any, + triggerId: 'trigger-id' + } as any) + ).toThrow('viewId is required for view interactions'); + }); + }); + + describe('toServerModalInteractionType', () => { + it('returns known modal interaction types', () => { + expect(toServerModalInteractionType('modal.open')).toBe('modal.open'); + expect(toServerModalInteractionType('modal.update')).toBe('modal.update'); + expect(toServerModalInteractionType('modal.close')).toBe('modal.close'); + expect(toServerModalInteractionType('errors')).toBe('errors'); + }); + + it('returns null for unknown interaction type', () => { + expect(toServerModalInteractionType('some.other.type')).toBeNull(); + }); + }); +}); diff --git a/app/containers/UIKit/interactionAdapters.ts b/app/containers/UIKit/interactionAdapters.ts new file mode 100644 index 00000000000..e19af85bdb2 --- /dev/null +++ b/app/containers/UIKit/interactionAdapters.ts @@ -0,0 +1,105 @@ +import type { ServerInteraction, UserInteraction } from '@rocket.chat/ui-kit'; + +import { ActionTypes, type ITriggerAction, type IView } from './interfaces'; + +type TServerModalInteraction = Extract<ServerInteraction, { type: 'modal.open' | 'modal.update' | 'modal.close' | 'errors' }>; +type TServerModalInteractionType = TServerModalInteraction['type']; + +const assertViewId = (viewId?: string) => { + if (!viewId) { + throw new Error('viewId is required for view interactions'); + } + + return viewId; +}; + +/** + * Converts a trigger action to a user interaction + */ +export const toUserInteraction = ({ + type, + actionId, + blockId, + value, + container, + mid, + rid, + triggerId, + viewId, + payload, + view, + isCleared +}: ITriggerAction & { triggerId: string }): UserInteraction => { + if (type === ActionTypes.ACTION) { + if (!actionId || !container) { + throw new Error('actionId and container are required for blockAction interaction'); + } + + const blockPayload = { + blockId: blockId || 'default', + value: payload ?? value + }; + + if (container.type === 'message') { + if (!mid || !rid) { + throw new Error('mid and rid are required for message block actions'); + } + + return { + type: 'blockAction', + actionId, + payload: blockPayload, + container: { + type: 'message', + id: container.id + }, + mid, + rid, + triggerId + }; + } + + return { + type: 'blockAction', + actionId, + payload: blockPayload, + container: { + type: 'view', + id: container.id + }, + triggerId + }; + } + + if (type === ActionTypes.SUBMIT) { + return { + type: 'viewSubmit', + viewId: assertViewId(viewId), + payload: payload as any, + triggerId + }; + } + + return { + type: 'viewClosed', + payload: { + viewId: assertViewId(viewId), + view: view as IView & { id: string; state: { [blockId: string]: { [key: string]: unknown } } }, + isCleared + }, + triggerId + }; +}; + +/** + * Converts a server modal interaction type to a user interaction type + * @param {string} value - The server modal interaction type to convert + * @returns {TServerModalInteractionType | null} - The user interaction type + */ +export const toServerModalInteractionType = (value: string): TServerModalInteractionType | null => { + if (value === 'modal.open' || value === 'modal.update' || value === 'modal.close' || value === 'errors') { + return value; + } + + return null; +}; diff --git a/app/containers/UIKit/interfaces.ts b/app/containers/UIKit/interfaces.ts index 7b8a8017bbe..6c51d056187 100644 --- a/app/containers/UIKit/interfaces.ts +++ b/app/containers/UIKit/interfaces.ts @@ -1,147 +1,127 @@ -import { type BlockContext } from '@rocket.chat/ui-kit'; +import type { + BlockContext, + FrameableIconElement, + IconButtonElement, + InfoCardBlock, + Markdown, + ModalView, + PlainText, + ServerInteraction, + ViewBlockActionUserInteraction, + ViewClosedUserInteraction, + ViewSubmitUserInteraction +} from '@rocket.chat/ui-kit'; import { type TSupportedThemes } from '../../theme'; -export enum ElementTypes { - IMAGE = 'image', - BUTTON = 'button', - STATIC_SELECT = 'static_select', - MULTI_STATIC_SELECT = 'multi_static_select', - CONVERSATION_SELECT = 'conversations_select', - CHANNEL_SELECT = 'channels_select', - USER_SELECT = 'users_select', - OVERFLOW = 'overflow', - DATEPICKER = 'datepicker', - PLAIN_TEXT_INPUT = 'plain_text_input', - SECTION = 'section', - DIVIDER = 'divider', - ACTIONS = 'actions', - CONTEXT = 'context', - FIELDS = 'fields', - INPUT = 'input', - PLAIN_TEXT = 'plain_text', - TEXT = 'text', - MARKDOWN = 'mrkdwn' -} - -export enum ActionTypes { - ACTION = 'blockAction', - SUBMIT = 'viewSubmit', - CLOSED = 'viewClosed' -} +export const ActionTypes = { + ACTION: 'blockAction', + SUBMIT: 'viewSubmit', + CLOSED: 'viewClosed' +} as const; -export enum ContainerTypes { - VIEW = 'view', - MESSAGE = 'message' -} +export const ContainerTypes = { + VIEW: 'view', + MESSAGE: 'message' +} as const; -export enum ModalActions { - MODAL = 'modal', - OPEN = 'modal.open', - CLOSE = 'modal.close', - UPDATE = 'modal.update', - ERRORS = 'errors' -} +export const ModalActions = { + MODAL: 'modal', + OPEN: 'modal.open', + CLOSE: 'modal.close', + UPDATE: 'modal.update', + ERRORS: 'errors' +} as const; -export interface IStateView { - [key: string]: { [settings: string]: string | number }; -} - -export interface IView { - appId: string; - type: ModalActions; - id: string; - title: IText; - submit: IButton; - close: IButton; - blocks: Block[]; - showIcon: boolean; - state?: IStateView; -} +export type TActionType = (typeof ActionTypes)[keyof typeof ActionTypes]; +export type TContainerType = (typeof ContainerTypes)[keyof typeof ContainerTypes]; +export type TModalAction = (typeof ModalActions)[keyof typeof ModalActions]; +export type IStateView = ViewSubmitUserInteraction['payload']['view']['state']; +export type IView = ModalView; export interface Block { - type: ElementTypes; - blockId: string; + type: string; + blockId?: string; element?: IElement; label?: string; - appId: string; + appId?: string; optional?: boolean; elements?: IElement[]; } - export interface IElement { - type: ElementTypes; + type: string; placeholder?: IText; - actionId: string; - initialValue?: string; + actionId?: string; + initialValue?: any; options?: Option[]; text?: IText; - value?: string; + value?: any; initialDate?: any; imageUrl?: string; appId?: string; blockId?: string; multiline?: boolean; -} - -export interface IText { - type?: ElementTypes; + icon?: string; + variant?: 'default' | 'danger' | 'secondary' | 'warning'; + framed?: boolean; + label?: string | IText; + url?: string; + callId?: string; +} +export type IText = { + type?: 'plain_text' | 'mrkdwn'; text: string; emoji?: boolean; -} - + i18n?: { + key: string; + args?: { + [key: string]: string | number; + }; + }; +}; export interface Option { text: IText; value: string; imageUrl?: string; } - -export interface IButton { - type: ElementTypes; +export interface IButton extends IElement { + type: 'button'; text: IText; actionId: string; blockId: string; appId: string; - value?: any; style?: any; } export interface IContainer { - type: ContainerTypes; + type: TContainerType; id: string; } -// methods/actions -export interface IUserInteraction { - triggerId: string; - appId?: string; - viewId?: string; - view: IView; -} - -export interface IEmitUserInteraction extends IUserInteraction { - type: ModalActions; -} +type TModalServerInteraction = Extract<ServerInteraction, { type: 'modal.open' | 'modal.update' | 'errors' }>; +export type IUserInteraction = Omit<TModalServerInteraction, 'type'>; +export type IEmitUserInteraction = TModalServerInteraction | ({ type: 'modal' } & IUserInteraction); export interface ITriggerAction { - type: ActionTypes; + type: TActionType; actionId?: string; appId?: string; container?: IContainer; - value?: number; + value?: unknown; blockId?: string; rid?: string; mid?: string; viewId?: string; payload?: any; view?: IView; + isCleared?: boolean; } export interface ITriggerBlockAction { container: IContainer; actionId: string; appId: string; - value: number; + value: unknown; blockId?: string; mid?: string; rid?: string; @@ -165,46 +145,73 @@ export interface ITriggerCancel { isCleared: boolean; } -// UiKit components +type TActionElement = IElement; +type TContextElement = IElement; +type TInputElement = IElement; +export type TElementAccessory = IElement & { blockId?: string; appId?: string }; + export interface IParser { - renderAccessories: (data: TElementAccessory, context: BlockContext, parser: IParser) => JSX.Element; - renderActions: (data: Block, context: BlockContext, parser: IParser) => JSX.Element; - renderContext: (data: IElement, context: BlockContext, parser: IParser) => JSX.Element; - renderInputs: (data: Partial<IElement>, context: BlockContext, parser: IParser) => JSX.Element; - text: (data: IText) => JSX.Element; + renderAccessories: ( + data: TElementAccessory | IElement, + context: BlockContext, + parser?: IParser, + index?: number + ) => JSX.Element | null; + renderActions: (data: TActionElement | IElement, context: BlockContext, parser?: IParser, index?: number) => JSX.Element | null; + renderContext: ( + data: TContextElement | IElement, + context: BlockContext, + parser?: IParser, + index?: number + ) => JSX.Element | null; + renderInputs: (data: TInputElement | IElement, context: BlockContext, parser?: IParser, index?: number) => JSX.Element | null; + text: (data: IText) => JSX.Element | null; + plain_text?: (data: PlainText | IText, context: BlockContext) => JSX.Element | null; + mrkdwn?: (data: Markdown | IText, context: BlockContext) => JSX.Element | null; + icon?: (data: IIcon, context: BlockContext) => JSX.Element | null; + icon_button?: (data: IIconButton, context: BlockContext) => JSX.Element | null; } + export interface IActions extends Block { + blockId?: string; + appId?: string; + elements?: IElement[]; parser?: IParser; } export interface IContext extends Block { + elements?: IElement[]; parser: IParser; + theme?: TSupportedThemes; } -export interface IDatePicker extends Partial<Block> { +export interface IDatePicker { + element: IElement; language: string; - action: Function; - context: number; + action: (params: { value: unknown }) => Promise<void>; + context: BlockContext; loading: boolean; value: string; error: string; } -export interface IInput extends Partial<Block> { +export interface IInput { + element: IElement; parser: IParser; - description: string; - error: string; - hint: string; + label?: string; + description?: string; + error?: string; + hint?: string; theme: TSupportedThemes; } export interface IInputIndex { element: IElement; - blockId: string; - appId: string; - label: IText; - description: IText; - hint: IText; + blockId?: string; + appId?: string; + label?: IText; + description?: IText; + hint?: IText; } export interface IThumb { @@ -216,51 +223,61 @@ export interface IImage { context?: BlockContext; } -// UiKit/Overflow -export interface IOverflow extends Partial<Block> { - action: Function; +export interface IOverflow { + element: IElement; + action: (params: { value: unknown }) => Promise<void>; loading: boolean; parser: IParser; - context: number; + context: BlockContext; } interface PropsOption { - onOptionPress: Function; + onOptionPress: (params: { value: Option['value'] }) => void; parser: IParser; theme: TSupportedThemes; } export interface IOptions extends PropsOption { - options: Option[]; + options: readonly Option[]; } export interface IOption extends PropsOption { option: Option; } -// UiKit/Section -interface IAccessory { - type: ElementTypes; - actionId: string; - value: number; - text: IText; -} - -type TElementAccessory = IAccessory & { blockId: string; appId: string }; export interface IAccessoryComponent { - element: TElementAccessory; + element: TElementAccessory | IElement; parser: IParser; } -export interface ISection { +export interface ISection extends Block { blockId: string; appId: string; text?: IText; - accessory?: IAccessory; + accessory?: IElement; + fields?: IText[]; parser: IParser; - fields?: any[]; } export interface IFields { parser: IParser; theme: TSupportedThemes; - fields: any[]; + fields: readonly IText[]; +} + +export type IIcon = FrameableIconElement & { + variant?: FrameableIconElement['variant']; +}; + +export type IIconButton = Omit<IconButtonElement, 'icon'> & { + icon: IIcon; + label?: string | IText; +}; + +export type IInfoCardRow = InfoCardBlock['rows'][number]; +export interface IInfoCard extends Omit<InfoCardBlock, 'rows'> { + rows: IInfoCardRow[]; + appId?: string; + blockId?: string; + parser: IParser; } +export type IBlockActionForView = ViewBlockActionUserInteraction; +export type IViewClosedInteraction = ViewClosedUserInteraction; diff --git a/app/containers/markdown/Markdown.stories.tsx b/app/containers/markdown/Markdown.stories.tsx index 16472f10e44..1ff74a4fe0b 100644 --- a/app/containers/markdown/Markdown.stories.tsx +++ b/app/containers/markdown/Markdown.stories.tsx @@ -168,3 +168,21 @@ export const Timestamp = () => ( <Markdown msg='R: <t:1735732800:R>' /> </View> ); + +const textStyle = { fontSize: 10, color: 'red' }; +export const TextStyle = () => ( + <View style={styles.container}> + <Markdown + msg='Emphasis: *bold* _italic_ ~strikethrough~ *_bold with italic_* *~bold with strike~* *_~bold with italic and strike~_* _~italic with strike~_' + textStyle={textStyle} + /> + <Markdown msg={msgMentions} mentions={mentions} username='rocket.cat' textStyle={textStyle} /> + <Markdown msg='#test-channel #unknown' channels={[{ _id: '123', name: 'test-channel' }]} textStyle={textStyle} /> + <Markdown + msg={`> This is block quote +this is a normal line`} + textStyle={textStyle} + /> + <Markdown msg='[Markdown link](https://rocket.chat)' textStyle={textStyle} /> + </View> +); diff --git a/app/containers/markdown/Markdown.textStyle.test.tsx b/app/containers/markdown/Markdown.textStyle.test.tsx new file mode 100644 index 00000000000..de15064db86 --- /dev/null +++ b/app/containers/markdown/Markdown.textStyle.test.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react-native'; + +import Markdown from '.'; + +jest.mock('../../lib/hooks/useAppSelector', () => ({ + useAppSelector: jest.fn(() => false) +})); + +jest.mock('../../lib/methods/userPreferences', () => ({ + useUserPreferences: jest.fn(() => [true]) +})); + +describe('Markdown textStyle integration', () => { + it('propagates textStyle to link, mention, hashtag and plain text while preserving link interaction', () => { + const onLinkPress = jest.fn(); + const textStyle = { fontSize: 17 }; + + const { getByLabelText, getByText } = render( + <Markdown + msg='hello [my link](https://rocket.chat) @rocket.cat #general' + textStyle={textStyle} + onLinkPress={onLinkPress} + mentions={[{ _id: 'u1', username: 'rocket.cat', name: 'Rocket Cat', type: 'user' }]} + username='another.user' + channels={[{ _id: 'r1', name: 'general' }]} + /> + ); + + const plainTextNode = getByLabelText('hello '); + const linkNode = getByText('my link'); + const mentionNode = getByText('@rocket.cat'); + const hashtagNode = getByText('#general'); + + expect(plainTextNode.props.style).toEqual(expect.arrayContaining([expect.objectContaining({ fontSize: 17 })])); + expect(linkNode.props.style).toEqual(expect.arrayContaining([expect.objectContaining({ fontSize: 17 })])); + expect(mentionNode.props.style).toEqual(expect.arrayContaining([expect.objectContaining({ fontSize: 17 })])); + expect(hashtagNode.props.style).toEqual(expect.arrayContaining([expect.objectContaining({ fontSize: 17 })])); + + fireEvent.press(linkNode); + + expect(onLinkPress).toHaveBeenCalledWith('https://rocket.chat'); + }); +}); diff --git a/app/containers/markdown/__snapshots__/Markdown.test.tsx.snap b/app/containers/markdown/__snapshots__/Markdown.test.tsx.snap index 0ff288d776a..0d71e644be6 100644 --- a/app/containers/markdown/__snapshots__/Markdown.test.tsx.snap +++ b/app/containers/markdown/__snapshots__/Markdown.test.tsx.snap @@ -4328,6 +4328,1045 @@ exports[`Story Snapshots: Text should match snapshot 1`] = ` </View> `; +exports[`Story Snapshots: TextStyle should match snapshot 1`] = ` +<View + style={ + { + "backgroundColor": "#FFFFFF", + "marginHorizontal": 15, + "marginVertical": 50, + } + } +> + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="Emphasis: " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + Emphasis: + </Text> + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="bold" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + bold + </Text> + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + { + "fontStyle": "italic", + } + } + > + <Text + accessibilityLabel="italic" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + italic + </Text> + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + { + "textDecorationLine": "line-through", + } + } + > + <Text + accessibilityLabel="strikethrough" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + strikethrough + </Text> + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + style={ + { + "fontStyle": "italic", + } + } + > + <Text + accessibilityLabel="bold with italic" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + bold with italic + </Text> + </Text> + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + style={ + { + "textDecorationLine": "line-through", + } + } + > + <Text + accessibilityLabel="bold with strike" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + bold with strike + </Text> + </Text> + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontWeight": "700", + "textAlign": "left", + } + } + > + <Text + style={ + { + "fontStyle": "italic", + } + } + > + <Text + style={ + { + "textDecorationLine": "line-through", + } + } + > + <Text + accessibilityLabel="bold with italic and strike" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + bold with italic and strike + </Text> + </Text> + </Text> + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + { + "fontStyle": "italic", + } + } + > + <Text + style={ + { + "textDecorationLine": "line-through", + } + } + > + <Text + accessibilityLabel="italic with strike" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + italic with strike + </Text> + </Text> + </Text> + </Text> + </Text> + </View> + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + onPress={[Function]} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "textAlign": "left", + }, + { + "color": "red", + "fontSize": 10, + }, + { + "color": "#9B1325", + }, + ] + } + > + rocket.cat + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + onPress={[Function]} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "textAlign": "left", + }, + { + "color": "red", + "fontSize": 10, + }, + { + "color": "#8E6300", + }, + ] + } + > + name1 + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "textAlign": "left", + }, + { + "color": "red", + "fontSize": 10, + }, + { + "color": "#974809", + }, + ] + } + > + all + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "textAlign": "left", + }, + { + "color": "red", + "fontSize": 10, + }, + { + "color": "#974809", + }, + ] + } + > + here + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "red", + "fontSize": 10, + }, + { + "color": "#2F343D", + }, + ] + } + > + @unknown + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "textAlign": "left", + }, + { + "color": "red", + "fontSize": 10, + }, + { + "color": "#8E6300", + }, + ] + } + > + team + </Text> + </Text> + </Text> + </View> + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + onPress={[Function]} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "600", + "textAlign": "left", + }, + { + "color": "red", + "fontSize": 10, + }, + { + "color": "#095AD2", + }, + ] + } + > + test-channel + </Text> + <Text + accessibilityLabel=" " + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + + </Text> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "red", + "fontSize": 10, + }, + { + "color": "#2F343D", + }, + ] + } + > + #unknown + </Text> + </Text> + </Text> + </View> + <View + style={ + { + "gap": 2, + } + } + > + <View + style={ + { + "alignItems": "flex-start", + "flexDirection": "row", + } + } + > + <View + style={ + [ + { + "height": "100%", + "marginRight": 5, + "width": 2, + }, + { + "backgroundColor": "#CBCED1", + }, + ] + } + /> + <View + style={ + { + "flex": 1, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="This is block quote" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + This is block quote + </Text> + </Text> + </Text> + </View> + </View> + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + accessibilityLabel="this is a normal line" + style={ + [ + { + "flexShrink": 1, + "fontSize": 16, + "lineHeight": 22, + }, + { + "color": "#2F343D", + }, + { + "color": "red", + "fontSize": 10, + }, + ] + } + > + this is a normal line + </Text> + </Text> + </Text> + </View> + <View + style={ + { + "gap": 2, + } + } + > + <Text + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "lineHeight": 22, + "textAlign": "left", + }, + { + "color": "#2F343D", + }, + ] + } + > + <Text + style={ + { + "backgroundColor": "transparent", + "flexShrink": 1, + "fontFamily": "Inter", + "fontWeight": "400", + "textAlign": "left", + } + } + > + <Text + onLongPress={[Function]} + onPress={[Function]} + style={ + [ + { + "backgroundColor": "transparent", + "fontFamily": "Inter", + "fontSize": 16, + "fontWeight": "400", + "textAlign": "left", + }, + { + "color": "red", + "fontSize": 10, + }, + { + "color": "#095AD2", + }, + ] + } + > + Markdown link + </Text> + </Text> + </Text> + </View> +</View> +`; + exports[`Story Snapshots: Timestamp should match snapshot 1`] = ` <View style={ diff --git a/app/containers/markdown/components/Plain.tsx b/app/containers/markdown/components/Plain.tsx index cdc70f9476b..000e6f31776 100644 --- a/app/containers/markdown/components/Plain.tsx +++ b/app/containers/markdown/components/Plain.tsx @@ -1,9 +1,10 @@ -import React from 'react'; +import React, { useContext } from 'react'; import { Text } from 'react-native'; import { type Plain as PlainProps } from '@rocket.chat/message-parser'; import { useTheme } from '../../../theme'; import styles from '../styles'; +import MarkdownContext from '../contexts/MarkdownContext'; interface IPlainProps { value: PlainProps['value']; @@ -11,8 +12,9 @@ interface IPlainProps { const Plain = ({ value }: IPlainProps): React.ReactElement => { const { colors } = useTheme(); + const { textStyle } = useContext(MarkdownContext); return ( - <Text accessibilityLabel={value} style={[styles.plainText, { color: colors.fontDefault }]}> + <Text accessibilityLabel={value} style={[styles.plainText, { color: colors.fontDefault }, ...(textStyle ? [textStyle] : [])]}> {value} </Text> ); diff --git a/app/containers/markdown/components/inline/Link.tsx b/app/containers/markdown/components/inline/Link.tsx index 76e8637ad61..ef9a19d314a 100644 --- a/app/containers/markdown/components/inline/Link.tsx +++ b/app/containers/markdown/components/inline/Link.tsx @@ -19,7 +19,7 @@ interface ILinkProps { const Link = ({ value }: ILinkProps) => { const { theme } = useTheme(); - const { onLinkPress } = useContext(MarkdownContext); + const { onLinkPress, textStyle } = useContext(MarkdownContext); const { src, label } = value; const handlePress = () => { if (!src.value) { @@ -37,7 +37,10 @@ const Link = ({ value }: ILinkProps) => { }; return ( - <Text onPress={handlePress} onLongPress={onLongPress} style={[styles.link, { color: themes[theme].fontInfo }]}> + <Text + style={[styles.link, ...(textStyle ? [textStyle] : []), { color: themes[theme].fontInfo }]} + onPress={handlePress} + onLongPress={onLongPress}> {(block => { const blockArray = Array.isArray(block) ? block : [block]; return blockArray.map(blockInArray => { diff --git a/app/containers/markdown/components/mentions/AtMention.tsx b/app/containers/markdown/components/mentions/AtMention.tsx index cf0779c0343..a376aa50bdf 100644 --- a/app/containers/markdown/components/mentions/AtMention.tsx +++ b/app/containers/markdown/components/mentions/AtMention.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { type StyleProp, Text, type TextStyle } from 'react-native'; +import React, { useContext } from 'react'; +import { Text } from 'react-native'; import { useTheme } from '../../../../theme'; import { themes } from '../../../../lib/constants/colors'; @@ -8,18 +8,19 @@ import styles from '../../styles'; import { events, logEvent } from '../../../../lib/methods/helpers/log'; import { type IUserMention } from '../../interfaces'; import { useUserPreferences } from '../../../../lib/methods/userPreferences'; +import MarkdownContext from '../../contexts/MarkdownContext'; interface IAtMention { mention: string; username?: string; navToRoomInfo?: Function; - style?: StyleProp<TextStyle>[]; useRealName?: boolean; mentions?: IUserMention[]; } -const AtMention = React.memo(({ mention, mentions, username, navToRoomInfo, style = [], useRealName }: IAtMention) => { +const AtMention = React.memo(({ mention, mentions, username, navToRoomInfo, useRealName }: IAtMention) => { const { theme } = useTheme(); + const { textStyle } = useContext(MarkdownContext); const [mentionsWithAtSymbol] = useUserPreferences<boolean>(USER_MENTIONS_PREFERENCES_KEY, false); const preffix = mentionsWithAtSymbol ? '@' : ''; if (mention === 'all' || mention === 'here') { @@ -27,10 +28,10 @@ const AtMention = React.memo(({ mention, mentions, username, navToRoomInfo, styl <Text style={[ styles.mention, + ...(textStyle ? [textStyle] : []), { color: themes[theme].statusFontService - }, - ...style + } ]}> {preffix} {mention} @@ -74,14 +75,18 @@ const AtMention = React.memo(({ mention, mentions, username, navToRoomInfo, styl return ( // not enough information on mentions to navigate to team info, so we don't handle onPress - <Text style={[styles.mention, mentionStyle, ...style]} onPress={atMentioned?.type === 'team' ? undefined : handlePress}> + <Text + style={[styles.mention, ...(textStyle ? [textStyle] : []), mentionStyle]} + onPress={atMentioned?.type === 'team' ? undefined : handlePress}> {preffix} {text} </Text> ); } - return <Text style={[styles.text, { color: themes[theme].fontDefault }, ...style]}>{`@${mention}`}</Text>; + return ( + <Text style={[styles.text, ...(textStyle ? [textStyle] : []), { color: themes[theme].fontDefault }]}>{`@${mention}`}</Text> + ); }); export default AtMention; diff --git a/app/containers/markdown/components/mentions/Hashtag.tsx b/app/containers/markdown/components/mentions/Hashtag.tsx index c5d8ffff7ee..047c4a183e2 100644 --- a/app/containers/markdown/components/mentions/Hashtag.tsx +++ b/app/containers/markdown/components/mentions/Hashtag.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { type StyleProp, Text, type TextStyle } from 'react-native'; +import React, { useContext } from 'react'; +import { Text } from 'react-native'; import i18n from '../../../../i18n'; import { themes } from '../../../../lib/constants/colors'; @@ -14,16 +14,17 @@ import { useTheme } from '../../../../theme'; import { sendLoadingEvent } from '../../../Loading'; import { type IUserChannel } from '../../interfaces'; import styles from '../../styles'; +import MarkdownContext from '../../contexts/MarkdownContext'; interface IHashtag { hashtag: string; navToRoomInfo?: Function; - style?: StyleProp<TextStyle>[]; channels?: IUserChannel[]; } -const Hashtag = React.memo(({ hashtag, channels, navToRoomInfo, style = [] }: IHashtag) => { +const Hashtag = React.memo(({ hashtag, channels, navToRoomInfo }: IHashtag) => { const { theme } = useTheme(); + const { textStyle } = useContext(MarkdownContext); const [roomsWithHashTagSymbol] = useUserPreferences<boolean>(ROOM_MENTIONS_PREFERENCES_KEY, false); const isMasterDetail = useAppSelector(state => state.app.isMasterDetail); const preffix = roomsWithHashTagSymbol ? '#' : ''; @@ -56,17 +57,19 @@ const Hashtag = React.memo(({ hashtag, channels, navToRoomInfo, style = [] }: IH <Text style={[ styles.mention, + ...(textStyle ? [textStyle] : []), { color: themes[theme].fontInfo - }, - ...style + } ]} onPress={handlePress}> {`${preffix}${hashtag}`} </Text> ); } - return <Text style={[styles.text, { color: themes[theme].fontDefault }, ...style]}>{`#${hashtag}`}</Text>; + return ( + <Text style={[styles.text, ...(textStyle ? [textStyle] : []), { color: themes[theme].fontDefault }]}>{`#${hashtag}`}</Text> + ); }); export default Hashtag; diff --git a/app/containers/markdown/contexts/MarkdownContext.ts b/app/containers/markdown/contexts/MarkdownContext.ts index 68b327fd02e..d0b07ebc537 100644 --- a/app/containers/markdown/contexts/MarkdownContext.ts +++ b/app/containers/markdown/contexts/MarkdownContext.ts @@ -1,4 +1,5 @@ import React from 'react'; +import { type StyleProp, type TextStyle } from 'react-native'; import { type IUserMention, type IUserChannel } from '../interfaces'; @@ -10,6 +11,7 @@ interface IMarkdownContext { navToRoomInfo?: Function; getCustomEmoji?: Function; onLinkPress?: Function; + textStyle?: StyleProp<TextStyle>; } const defaultState = { @@ -17,7 +19,8 @@ const defaultState = { channels: [], useRealName: false, username: '', - navToRoomInfo: () => {} + navToRoomInfo: () => {}, + textStyle: undefined }; const MarkdownContext = React.createContext<IMarkdownContext>(defaultState); diff --git a/app/containers/markdown/index.tsx b/app/containers/markdown/index.tsx index 5140f89890a..c641b3f4cf8 100644 --- a/app/containers/markdown/index.tsx +++ b/app/containers/markdown/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { View } from 'react-native'; +import { type StyleProp, type TextStyle, View } from 'react-native'; import { parse } from '@rocket.chat/message-parser'; import type { Root } from '@rocket.chat/message-parser'; import isEmpty from 'lodash/isEmpty'; @@ -32,6 +32,7 @@ interface IMarkdownProps { navToRoomInfo?: Function; onLinkPress?: TOnLinkPress; isTranslated?: boolean; + textStyle?: StyleProp<TextStyle>; } const Markdown: React.FC<IMarkdownProps> = ({ @@ -44,7 +45,8 @@ const Markdown: React.FC<IMarkdownProps> = ({ username = '', getCustomEmoji, onLinkPress, - isTranslated + isTranslated, + textStyle }: IMarkdownProps) => { if (!msg) return null; @@ -67,7 +69,8 @@ const Markdown: React.FC<IMarkdownProps> = ({ username, navToRoomInfo, getCustomEmoji, - onLinkPress + onLinkPress, + textStyle }}> {tokens?.map(block => { switch (block.type) { diff --git a/app/i18n/locales/ar.json b/app/i18n/locales/ar.json index 05ea6661682..1e546665cfc 100644 --- a/app/i18n/locales/ar.json +++ b/app/i18n/locales/ar.json @@ -73,7 +73,11 @@ "Browser": "المتصفح", "Busy": "مشغول", "Call_already_ended": "تم انهاء المكالمة بالفعل !", + "Call_ended_bold": "*تم إنهاء مكالمة الصوت*", + "Call_failed_bold": "*فشلت مكالمة الصوت*", + "Call_not_answered_bold": "*لم يتم الرد على مكالمة الصوت*", "Call_room_name": "اتصل بـ {{roomName}}", + "Call_transferred_bold": "*تم تحويل مكالمة الصوت*", "Call_was_canceled_before_being_answered": "تم إلغاء المكالمة قبل الرد عليها", "Cancel": "إلغاء", "Cancel_and_delete_recording": "إلغاء وحذف التسجيل", diff --git a/app/i18n/locales/bn-IN.json b/app/i18n/locales/bn-IN.json index fe56fb6199d..00461f636f3 100644 --- a/app/i18n/locales/bn-IN.json +++ b/app/i18n/locales/bn-IN.json @@ -101,11 +101,15 @@ "Call_already_ended": "কল ইতিমধ্যে শেষ হয়েছে!", "Call_back": "কল ফিরে দিন", "Call_ended": "কল সমাপ্ত", + "Call_ended_bold": "*ভয়েস কল শেষ হয়েছে*", + "Call_failed_bold": "*ভয়েস কল ব্যর্থ হয়েছে*", "Call_issue": "কল সমস্যা", + "Call_not_answered_bold": "*ভয়েস কলের উত্তর দেওয়া হয়নি*", "Call_ongoing": "কল চলছে", "Call_rejected": "কল প্রত্যাখ্যান করা হয়েছে", "Call_room_name": "{{roomName}}-এ কল করুন", "Call_started": "কল শুরু হয়েছে", + "Call_transferred_bold": "*ভয়েস কল স্থানান্তরিত হয়েছে*", "Call_was_canceled_before_being_answered": "কলটি উত্তর দেওয়ার আগে বাতিল করা হয়েছে", "Call_was_not_answered": "কলটি উত্তর দেওয়া হয়নি", "Calling": "কল করছি", diff --git a/app/i18n/locales/cs.json b/app/i18n/locales/cs.json index e6a450ac36e..2dbba085c23 100644 --- a/app/i18n/locales/cs.json +++ b/app/i18n/locales/cs.json @@ -107,11 +107,15 @@ "Call_already_ended": "Volání již ukončeno!", "Call_back": "Zavolat zpět", "Call_ended": "Hovor byl ukončen", + "Call_ended_bold": "*Hlasové volání ukončeno*", + "Call_failed_bold": "*Hlasové volání selhalo*", "Call_issue": "Problém s voláním", + "Call_not_answered_bold": "*Hlasové volání nebylo zodpovězeno*", "Call_ongoing": "Hovor probíhá", "Call_rejected": "Hovor odmítnut", "Call_room_name": "Zavolejte {{roomName}}", "Call_started": "Hovor zahájen", + "Call_transferred_bold": "*Hlasové volání převedeno*", "Call_was_canceled_before_being_answered": "Hovor byl zrušen před přijetím", "Call_was_not_answered": "Volání nebylo přijato", "Calling": "Povolání", diff --git a/app/i18n/locales/de.json b/app/i18n/locales/de.json index 6f5fcb3cf2a..54a8b4c607b 100644 --- a/app/i18n/locales/de.json +++ b/app/i18n/locales/de.json @@ -98,9 +98,13 @@ "Call": "Anruf", "Call_already_ended": "Anruf bereits beendet!", "Call_ended": "Anruf beendet", + "Call_ended_bold": "*Sprachanruf beendet*", + "Call_failed_bold": "*Sprachanruf fehlgeschlagen*", + "Call_not_answered_bold": "*Sprachanruf nicht beantwortet*", "Call_rejected": "Anruf abgelehnt", "Call_room_name": "{{roomName}} anrufen", "Call_started": "Anruf gestartet", + "Call_transferred_bold": "*Sprachanruf übertragen*", "Call_was_canceled_before_being_answered": "Anruf wurde vor der Annahme abgebrochen.", "Call_was_not_answered": "Anruf wurde nicht beantwortet", "Calling": "Rufe …", diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index b6fc371d6de..1424e485c6a 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -107,11 +107,15 @@ "Call_already_ended": "Call already ended!", "Call_back": "Call back", "Call_ended": "Call ended", + "Call_ended_bold": "*Voice call ended*", + "Call_failed_bold": "*Voice call failed*", "Call_issue": "Call issue", + "Call_not_answered_bold": "*Voice call not answered*", "Call_ongoing": "Call ongoing", "Call_rejected": "Call rejected", "Call_room_name": "Call {{roomName}}", "Call_started": "Call started", + "Call_transferred_bold": "*Voice call transferred*", "Call_was_canceled_before_being_answered": "Call was canceled before being answered", "Call_was_not_answered": "Call was not answered", "Calling": "Calling...", diff --git a/app/i18n/locales/es.json b/app/i18n/locales/es.json index bc9252ed24b..ce474956c45 100644 --- a/app/i18n/locales/es.json +++ b/app/i18n/locales/es.json @@ -68,7 +68,11 @@ "Broadcast_hint": "Sólo los usuarios autorizados pueden escribir nuevos mensajes, el resto podrán responder sobre los mismos.", "Busy": "Ocupado", "Call_already_ended": "¡!La llamada ya ha finalizado!", + "Call_ended_bold": "*Llamada de voz finalizada*", + "Call_failed_bold": "*Llamada de voz fallida*", + "Call_not_answered_bold": "*Llamada de voz no contestada*", "Call_room_name": "Llamar a {{roomName}}", + "Call_transferred_bold": "*Llamada de voz transferida*", "Call_was_canceled_before_being_answered": "La llamada fue cancelada antes de ser contestada.", "Cancel": "Cancelar", "Cancel_and_delete_recording": "Cancelar y eliminar grabación", diff --git a/app/i18n/locales/fi.json b/app/i18n/locales/fi.json index 74766801202..9bf7a5015ad 100644 --- a/app/i18n/locales/fi.json +++ b/app/i18n/locales/fi.json @@ -90,7 +90,11 @@ "Call": "Soita", "Call_already_ended": "Puhelu on jo päättynyt!", "Call_ended": "Puhelu päättyi", + "Call_ended_bold": "*Puhelu päättyi*", + "Call_failed_bold": "*Puhelu epäonnistui*", + "Call_not_answered_bold": "*Puheluun ei vastattu*", "Call_room_name": "Kutsu {{roomName}}", + "Call_transferred_bold": "*Puhelu siirretty*", "Call_was_canceled_before_being_answered": "Puhelu peruttiin ennen kuin siihen vastattiin", "Call_was_not_answered": "Puheluun ei vastattu", "Calling": "Soitetaan", diff --git a/app/i18n/locales/fr.json b/app/i18n/locales/fr.json index b0be369a630..972d2b74d05 100644 --- a/app/i18n/locales/fr.json +++ b/app/i18n/locales/fr.json @@ -78,7 +78,11 @@ "Browser": "Navigateur", "Busy": "Occupé", "Call_already_ended": "Appel déjà terminé !", + "Call_ended_bold": "*Appel vocal terminé*", + "Call_failed_bold": "*Appel vocal échoué*", + "Call_not_answered_bold": "*Appel vocal sans réponse*", "Call_room_name": "Appeler {{roomName}}", + "Call_transferred_bold": "*Appel vocal transféré*", "Call_was_canceled_before_being_answered": "L'appel a été annulé avant d'être répondu.", "Cancel": "Annuler", "Cancel_and_delete_recording": "Annuler et supprimer l'enregistrement", diff --git a/app/i18n/locales/hi-IN.json b/app/i18n/locales/hi-IN.json index 110f1725d9a..9f7cfa2d41f 100644 --- a/app/i18n/locales/hi-IN.json +++ b/app/i18n/locales/hi-IN.json @@ -101,11 +101,15 @@ "Call_already_ended": "कॉल पहले ही समाप्त हो गई है!", "Call_back": "कॉल वापस", "Call_ended": "कॉल समाप्त हुई", + "Call_ended_bold": "*वॉइस कॉल समाप्त हुई*", + "Call_failed_bold": "*वॉइस कॉल विफल हो गई*", "Call_issue": "कॉल समस्या", + "Call_not_answered_bold": "*वॉइस कॉल का जवाब नहीं दिया गया*", "Call_ongoing": "कॉल जारी है", "Call_rejected": "कॉल अस्वीकृत", "Call_room_name": "{{roomName}} को कॉल करें", "Call_started": "कॉल शुरू हुई", + "Call_transferred_bold": "*वॉइस कॉल स्थानांतरित हो गई*", "Call_was_canceled_before_being_answered": "उत्तर देने से पहले कॉल रद्द कर दी गई थी।", "Call_was_not_answered": "कॉल का जवाब नहीं दिया गया था", "Calling": "कॉलिंग", diff --git a/app/i18n/locales/hu.json b/app/i18n/locales/hu.json index e43c6178dad..808b52c576f 100644 --- a/app/i18n/locales/hu.json +++ b/app/i18n/locales/hu.json @@ -101,11 +101,15 @@ "Call_already_ended": "A hívásnak már vége!", "Call_back": "Visszahívás", "Call_ended": "Hívás befejezve", + "Call_ended_bold": "*Hanghívás befejezve*", + "Call_failed_bold": "*Hanghívás sikertelen*", "Call_issue": "Hívás kiadás", + "Call_not_answered_bold": "*Hanghívásra nem válaszoltak*", "Call_ongoing": "Hívás folyamatban", "Call_rejected": "Hívás elutasítva", "Call_room_name": "Hívd a(z) {{roomName}}-t!", "Call_started": "Hívás elindítva", + "Call_transferred_bold": "*Hanghívás átirányítva*", "Call_was_canceled_before_being_answered": "A hívást megszakították, mielőtt fogadták volna.", "Call_was_not_answered": "A hívás nem lett fogadva", "Calling": "Hívás", diff --git a/app/i18n/locales/it.json b/app/i18n/locales/it.json index 0255e51c013..842ca1eb51c 100644 --- a/app/i18n/locales/it.json +++ b/app/i18n/locales/it.json @@ -78,7 +78,11 @@ "Browser": "Browser", "Busy": "Occupato", "Call_already_ended": "Chiamata già terminata!", + "Call_ended_bold": "*Chiamata vocale terminata*", + "Call_failed_bold": "*Chiamata vocale fallita*", + "Call_not_answered_bold": "*Chiamata vocale senza risposta*", "Call_room_name": "Chiama {{roomName}}", + "Call_transferred_bold": "*Chiamata vocale trasferita*", "Call_was_canceled_before_being_answered": "La chiamata è stata annullata prima di essere risposta.", "Cancel": "Annulla", "Cancel_and_delete_recording": "Annulla ed elimina la registrazione", diff --git a/app/i18n/locales/ja.json b/app/i18n/locales/ja.json index 50bf3af873e..99a7b3a5316 100644 --- a/app/i18n/locales/ja.json +++ b/app/i18n/locales/ja.json @@ -72,7 +72,11 @@ "Browser": "ブラウザ", "Busy": "取り込み中", "Call_already_ended": "通話は終了しています。", + "Call_ended_bold": "*通話が終了しました*", + "Call_failed_bold": "*通話が失敗しました*", + "Call_not_answered_bold": "*通話が応答されませんでした*", "Call_room_name": "{{roomName}}を呼び出す", + "Call_transferred_bold": "*通話が転送されました*", "Call_was_canceled_before_being_answered": "応答される前に通話がキャンセルされました。", "Cancel": "キャンセル", "Cancel_and_delete_recording": "録音をキャンセルして削除", diff --git a/app/i18n/locales/nl.json b/app/i18n/locales/nl.json index 69500f02958..ed78f0aacc7 100644 --- a/app/i18n/locales/nl.json +++ b/app/i18n/locales/nl.json @@ -78,7 +78,11 @@ "Browser": "Browser", "Busy": "Bezig", "Call_already_ended": "Gesprek al beeïndigd!", + "Call_ended_bold": "*Spraakgesprek beëindigd*", + "Call_failed_bold": "*Spraakgesprek mislukt*", + "Call_not_answered_bold": "*Spraakgesprek niet beantwoord*", "Call_room_name": "Bel {{roomName}}", + "Call_transferred_bold": "*Spraakgesprek overgedragen*", "Call_was_canceled_before_being_answered": "Oproep werd geannuleerd voordat deze werd beantwoord", "Cancel": "Annuleren", "Cancel_and_delete_recording": "Annuleer en verwijder opname", diff --git a/app/i18n/locales/nn.json b/app/i18n/locales/nn.json index 830c4bfc86c..53c3ad2dcab 100644 --- a/app/i18n/locales/nn.json +++ b/app/i18n/locales/nn.json @@ -53,8 +53,12 @@ "Call_again": "Ring igjen", "Call_back": "Ring tilbake", "Call_ended": "Anrop avsluttet", + "Call_ended_bold": "*Stemmesamtale avsluttet*", + "Call_failed_bold": "*Stemmesamtale mislyktes*", + "Call_not_answered_bold": "*Stemmesamtale ikkje svara*", "Call_ongoing": "Samtale pågår", "Call_started": "Samtale startet", + "Call_transferred_bold": "*Stemmesamtale overført*", "Call_was_canceled_before_being_answered": "Samtalen blei avlyst før ho blei svart", "Call_was_not_answered": "Anropet ble ikke besvart", "Calling": "Ringer", diff --git a/app/i18n/locales/no.json b/app/i18n/locales/no.json index a520e093f8e..435d844fbf6 100644 --- a/app/i18n/locales/no.json +++ b/app/i18n/locales/no.json @@ -102,10 +102,15 @@ "Call_already_ended": "Samtalen er allerede avsluttet!", "Call_back": "Ring tilbake", "Call_ended": "Samtale avsluttet", + "Call_ended_bold": "*Stemmesamtale avsluttet*", + "Call_failed_bold": "*Stemmesamtale mislyktes*", "Call_issue": "Problem med anrop", + "Call_not_answered_bold": "*Stemmesamtale ikke besvart*", "Call_ongoing": "Samtale pågår", "Call_rejected": "Anrop avvist", + "Call_room_name": "Ring {{roomName}}", "Call_started": "Samtalen startet", + "Call_transferred_bold": "*Stemmesamtale overført*", "Call_was_canceled_before_being_answered": "Samtalen ble avbrutt før den ble besvart", "Call_was_not_answered": "Anropet ble ikke besvart", "Calling": "Ringer", diff --git a/app/i18n/locales/pt-BR.json b/app/i18n/locales/pt-BR.json index fd7286bad25..202e4fa9767 100644 --- a/app/i18n/locales/pt-BR.json +++ b/app/i18n/locales/pt-BR.json @@ -105,11 +105,15 @@ "Call_already_ended": "A chamada já terminou!", "Call_back": "Ligue de volta", "Call_ended": "Chamada finalizada", + "Call_ended_bold": "*Chamada de voz finalizada*", + "Call_failed_bold": "*Chamada de voz falhou*", "Call_issue": "Chamada com problemas", + "Call_not_answered_bold": "*Chamada de voz não atendida*", "Call_ongoing": "Chamada em andamento", "Call_rejected": "Chamada rejeitada", "Call_room_name": "Chamar {{roomName}}", "Call_started": "Chamada Iniciada", + "Call_transferred_bold": "*Chamada de voz transferida*", "Call_was_canceled_before_being_answered": "A chamada foi cancelada antes de ser atendida.", "Call_was_not_answered": "A chamada não foi atendida", "Calling": "Chamando", diff --git a/app/i18n/locales/pt-PT.json b/app/i18n/locales/pt-PT.json index f854037fcb0..f29eb505e13 100644 --- a/app/i18n/locales/pt-PT.json +++ b/app/i18n/locales/pt-PT.json @@ -71,7 +71,11 @@ "Browser": "Navegador", "Busy": "Ocupado", "Call_already_ended": "Chamada já terminada!", + "Call_ended_bold": "*Chamada de voz terminada*", + "Call_failed_bold": "*Chamada de voz falhou*", + "Call_not_answered_bold": "*Chamada de voz não atendida*", "Call_room_name": "Ligar para {{roomName}}", + "Call_transferred_bold": "*Chamada de voz transferida*", "Call_was_canceled_before_being_answered": "A chamada foi cancelada antes de ser atendida.", "Cancel": "Cancelar", "Cancel_and_delete_recording": "Cancelar e eliminar gravação", diff --git a/app/i18n/locales/ru.json b/app/i18n/locales/ru.json index 9a065cbcd3d..7989d141de6 100644 --- a/app/i18n/locales/ru.json +++ b/app/i18n/locales/ru.json @@ -88,7 +88,11 @@ "Call": "Звонок", "Call_already_ended": "Вызов уже завершен!", "Call_ended": "Звонок завершен", + "Call_ended_bold": "*Голосовой звонок завершен*", + "Call_failed_bold": "*Голосовой звонок не удался*", + "Call_not_answered_bold": "*На голосовой звонок не ответили*", "Call_room_name": "Вызвать {{roomName}}", + "Call_transferred_bold": "*Голосовой звонок переведен*", "Call_was_canceled_before_being_answered": "Звонок был отменен до ответа.", "Call_was_not_answered": "Звонок не был отвечен", "Calling": "Идет вызов", diff --git a/app/i18n/locales/sl-SI.json b/app/i18n/locales/sl-SI.json index a1c6d1e7112..b553fcf87a1 100644 --- a/app/i18n/locales/sl-SI.json +++ b/app/i18n/locales/sl-SI.json @@ -82,7 +82,11 @@ "Browser": "Brskalnik", "Busy": "Zaseden", "Call_already_ended": "Klic je že končan!", + "Call_ended_bold": "*Glasovni klic končan*", + "Call_failed_bold": "*Glasovni klic ni uspel*", + "Call_not_answered_bold": "*Glasovni klic ni bil odgovorjen*", "Call_room_name": "Pokliči {{roomName}}", + "Call_transferred_bold": "*Glasovni klic prenesen*", "Call_was_canceled_before_being_answered": "Klic je bil preklican, preden je bil sprejet.", "Cancel": "Prekliči", "Cancel_and_delete_recording": "Prekliči in izbriši posnetek", diff --git a/app/i18n/locales/sv.json b/app/i18n/locales/sv.json index 94945091575..128ead6427a 100644 --- a/app/i18n/locales/sv.json +++ b/app/i18n/locales/sv.json @@ -90,7 +90,11 @@ "Call": "Ring", "Call_already_ended": "Samtalet är redan avslutat.", "Call_ended": "Samtal avslutat", + "Call_ended_bold": "*Röstsamtal avslutat*", + "Call_failed_bold": "*Röstsamtal misslyckades*", + "Call_not_answered_bold": "*Röstsamtal besvarades inte*", "Call_room_name": "Ring {{roomName}}", + "Call_transferred_bold": "*Röstsamtal överfört*", "Call_was_canceled_before_being_answered": "Samtalet avbröts innan det besvarades", "Call_was_not_answered": "Samtalet besvarades inte", "Calling": "Ringer upp", diff --git a/app/i18n/locales/ta-IN.json b/app/i18n/locales/ta-IN.json index bcfeacc4834..97aa4a2ebc6 100644 --- a/app/i18n/locales/ta-IN.json +++ b/app/i18n/locales/ta-IN.json @@ -101,11 +101,15 @@ "Call_already_ended": "மொபைலைப் போன் அழிந்துவிட்டது!", "Call_back": "பின்னிருக்க", "Call_ended": "அழிந்தது", + "Call_ended_bold": "*குரல் அழைப்பு முடிந்தது*", + "Call_failed_bold": "*குரல் அழைப்பு தோல்வியடைந்தது*", "Call_issue": "கால் கொள்ளை", + "Call_not_answered_bold": "*குரல் அழைப்பிற்கு பதில் அளிக்கப்படவில்லை*", "Call_ongoing": "கால் நடக்கின்றது", "Call_rejected": "குறைந்தது", "Call_room_name": "{{roomName}} அழைக்கவும்", "Call_started": "கால் ஆரம்பம்", + "Call_transferred_bold": "*குரல் அழைப்பு மாற்றப்பட்டது*", "Call_was_canceled_before_being_answered": "அழைப்பு பதிலளிக்கப்படுவதற்கு முன்பு ரத்து செய்யப்பட்டது", "Call_was_not_answered": "அழிந்தது", "Calling": "அழைப்பதில்", diff --git a/app/i18n/locales/te-IN.json b/app/i18n/locales/te-IN.json index b3413bb9253..b37d33c3328 100644 --- a/app/i18n/locales/te-IN.json +++ b/app/i18n/locales/te-IN.json @@ -101,11 +101,15 @@ "Call_already_ended": "కాల్ ఇప్పటివరకు ముగింపుగా ఉంది!", "Call_back": "కాల్ బ్యాక్", "Call_ended": "కాల్ ముగియింది", + "Call_ended_bold": "*వాయిస్ కాల్ ముగిసింది*", + "Call_failed_bold": "*వాయిస్ కాల్ విఫలమైంది*", "Call_issue": "కాల్ సమస్య", + "Call_not_answered_bold": "*వాయిస్ కాల్ జవాబు ఇవ్వబడలేదు*", "Call_ongoing": "కాల్ ప్రవర్తిస్తోంది", "Call_rejected": "కాల్ తిరస్కరించబడింది", "Call_room_name": "{{roomName}} को कॉल करें", "Call_started": "కాల్ ప్రారంభించబడింది", + "Call_transferred_bold": "*వాయిస్ కాల్ బదిలీ చేయబడింది*", "Call_was_canceled_before_being_answered": "కాల్ సమాధానం ఇవ్వబడకముందే రద్దు చేయబడింది", "Call_was_not_answered": "కాల్ సమాధానించబడలేదు", "Calling": "కాల్ చేస్తోంది", diff --git a/app/i18n/locales/tr.json b/app/i18n/locales/tr.json index 20cd7c83df6..4fa8d8d4c0c 100644 --- a/app/i18n/locales/tr.json +++ b/app/i18n/locales/tr.json @@ -72,7 +72,11 @@ "Browser": "Tarayıcı", "Busy": "Meşgul", "Call_already_ended": "Çağrı sona erdi!", + "Call_ended_bold": "*Sesli arama sona erdi*", + "Call_failed_bold": "*Sesli arama başarısız*", + "Call_not_answered_bold": "*Sesli arama cevaplanmadı*", "Call_room_name": "{{roomName}} araması yap", + "Call_transferred_bold": "*Sesli arama aktarıldı*", "Call_was_canceled_before_being_answered": "Çağrı, cevaplanmadan önce iptal edildi", "Cancel": "İptal et", "Cancel_and_delete_recording": "Kaydı iptal et ve sil", diff --git a/app/i18n/locales/zh-CN.json b/app/i18n/locales/zh-CN.json index 1141065daa5..d08e49e1493 100644 --- a/app/i18n/locales/zh-CN.json +++ b/app/i18n/locales/zh-CN.json @@ -72,7 +72,11 @@ "Browser": "浏览器", "Busy": "忙碌", "Call_already_ended": "通话已经结束!", + "Call_ended_bold": "*语音通话已结束*", + "Call_failed_bold": "*语音通话失败*", + "Call_not_answered_bold": "*语音通话未接听*", "Call_room_name": "呼叫{{roomName}}", + "Call_transferred_bold": "*语音通话已转接*", "Call_was_canceled_before_being_answered": "通话在接听前被取消。", "Cancel": "取消", "Cancel_and_delete_recording": "取消并删除录音", diff --git a/app/i18n/locales/zh-TW.json b/app/i18n/locales/zh-TW.json index 6bd89bdc169..5debed3b591 100644 --- a/app/i18n/locales/zh-TW.json +++ b/app/i18n/locales/zh-TW.json @@ -72,7 +72,11 @@ "Browser": "瀏覽器", "Busy": "忙碌", "Call_already_ended": "通話已經結束!", + "Call_ended_bold": "*語音通話已結束*", + "Call_failed_bold": "*語音通話失敗*", + "Call_not_answered_bold": "*語音通話未接聽*", "Call_room_name": "呼叫{{roomName}}", + "Call_transferred_bold": "*語音通話已轉接*", "Call_was_canceled_before_being_answered": "通話在接聽前被取消", "Cancel": "取消", "Cancel_and_delete_recording": "取消並刪除錄音", diff --git a/app/lib/methods/actions.test.ts b/app/lib/methods/actions.test.ts new file mode 100644 index 00000000000..6bf08853022 --- /dev/null +++ b/app/lib/methods/actions.test.ts @@ -0,0 +1,253 @@ +import { ActionTypes, ModalActions } from '../../containers/UIKit/interfaces'; +import { generateTriggerId, handlePayloadUserInteraction, triggerAction } from './actions'; +import EventEmitter from './helpers/events'; +import fetch from './helpers/fetch'; +import Navigation from '../navigation/appNavigation'; + +jest.mock('./helpers', () => ({ + random: jest.fn(() => 'trigger-fixed-id') +})); + +jest.mock('./helpers/fetch', () => jest.fn()); + +jest.mock('./helpers/events', () => ({ + emit: jest.fn() +})); + +jest.mock('../navigation/appNavigation', () => ({ + navigate: jest.fn() +})); + +jest.mock('../services/sdk', () => ({ + __esModule: true, + default: { + current: { + currentLogin: { + userId: 'user-id', + authToken: 'auth-token' + }, + client: { + host: 'https://chat.example.com' + } + } + } +})); + +const mockedFetch = fetch as jest.MockedFunction<typeof fetch>; +const mockedEmit = EventEmitter.emit as jest.MockedFunction<typeof EventEmitter.emit>; +const mockedNavigate = Navigation.navigate as jest.MockedFunction<typeof Navigation.navigate>; + +describe('actions', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('handlePayloadUserInteraction', () => { + it('returns undefined when trigger id is unknown', () => { + expect(handlePayloadUserInteraction(ModalActions.OPEN, { triggerId: 'unknown', viewId: 'view-id' })).toBeUndefined(); + }); + + it('navigates for modal.open and returns modal.open', () => { + const triggerId = generateTriggerId('app-id'); + + const result = handlePayloadUserInteraction(ModalActions.OPEN, { + triggerId, + view: { id: 'view-id' } + }); + + expect(result).toBe(ModalActions.OPEN); + expect(mockedNavigate).toHaveBeenCalledWith('ModalBlockView', { + data: expect.objectContaining({ + appId: 'app-id', + triggerId, + viewId: 'view-id' + }) + }); + }); + }); + + describe('triggerAction', () => { + const actionInput = { + type: ActionTypes.ACTION, + actionId: 'action-id', + appId: 'app-id', + container: { type: 'message', id: 'container-id' } as const, + mid: 'message-id', + rid: 'room-id', + blockId: 'block-id', + value: 'value' + }; + + it('handles modal.open response', async () => { + mockedFetch.mockResolvedValueOnce({ + ok: true, + text: () => + Promise.resolve( + JSON.stringify({ + type: ModalActions.OPEN, + triggerId: 'trigger-fixed-id', + view: { id: 'view-open-id' } + }) + ) + } as Response); + + const result = await triggerAction(actionInput); + + expect(result).toBe(ModalActions.OPEN); + expect(mockedNavigate).toHaveBeenCalledWith('ModalBlockView', { + data: expect.objectContaining({ + appId: 'app-id', + triggerId: 'trigger-fixed-id', + viewId: 'view-open-id' + }) + }); + expect(mockedFetch).toHaveBeenCalledWith( + 'https://chat.example.com/api/apps/ui.interaction/app-id/', + expect.objectContaining({ + method: 'POST', + headers: expect.objectContaining({ + 'X-Auth-Token': 'auth-token', + 'X-User-Id': 'user-id' + }) + }) + ); + }); + + it('handles modal.update response', async () => { + mockedFetch.mockResolvedValueOnce({ + ok: true, + text: () => + Promise.resolve( + JSON.stringify({ + type: ModalActions.UPDATE, + triggerId: 'trigger-fixed-id', + viewId: 'view-update-id' + }) + ) + } as Response); + + const result = await triggerAction(actionInput); + + expect(result).toBe(ModalActions.UPDATE); + expect(mockedEmit).toHaveBeenCalledWith( + 'view-update-id', + expect.objectContaining({ + type: ModalActions.UPDATE, + appId: 'app-id', + triggerId: 'trigger-fixed-id', + viewId: 'view-update-id' + }) + ); + }); + + it('handles errors response', async () => { + mockedFetch.mockResolvedValueOnce({ + ok: true, + text: () => + Promise.resolve( + JSON.stringify({ + type: ModalActions.ERRORS, + triggerId: 'trigger-fixed-id', + viewId: 'view-errors-id' + }) + ) + } as Response); + + const result = await triggerAction(actionInput); + + expect(result).toBe(ModalActions.ERRORS); + expect(mockedEmit).toHaveBeenCalledWith( + 'view-errors-id', + expect.objectContaining({ + type: ModalActions.ERRORS, + appId: 'app-id', + triggerId: 'trigger-fixed-id', + viewId: 'view-errors-id' + }) + ); + }); + + it('returns modal.close for explicit close response', async () => { + mockedFetch.mockResolvedValueOnce({ + ok: true, + text: () => + Promise.resolve( + JSON.stringify({ + type: ModalActions.CLOSE + }) + ) + } as Response); + + const result = await triggerAction(actionInput); + + expect(result).toBe(ModalActions.CLOSE); + }); + + it('returns modal.close for empty response body with ok status', async () => { + mockedFetch.mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve('') + } as Response); + + const result = await triggerAction(actionInput); + + expect(result).toBe(ModalActions.CLOSE); + }); + + it('throws when request is not ok', async () => { + mockedFetch.mockResolvedValueOnce({ + ok: false, + status: 500 + } as Response); + + await expect(triggerAction(actionInput)).rejects.toThrow('Failed to trigger action: 500'); + }); + + it('throws when response body is malformed JSON', async () => { + mockedFetch.mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve('{invalid json}') + } as Response); + + await expect(triggerAction(actionInput)).rejects.toThrow('Invalid JSON response from server'); + }); + + it('throws when response has unknown modal interaction type', async () => { + mockedFetch.mockResolvedValueOnce({ + ok: true, + text: () => + Promise.resolve( + JSON.stringify({ + type: 'unknown.legacy', + triggerId: 'trigger-fixed-id' + }) + ) + } as Response); + + await expect(triggerAction(actionInput)).rejects.toThrow('Unknown modal interaction type: unknown.legacy'); + }); + + it('invalidates trigger id after processing', async () => { + mockedFetch.mockResolvedValueOnce({ + ok: true, + text: () => + Promise.resolve( + JSON.stringify({ + type: ModalActions.UPDATE, + triggerId: 'trigger-fixed-id', + viewId: 'view-id' + }) + ) + } as Response); + + await triggerAction(actionInput); + + const staleResult = handlePayloadUserInteraction(ModalActions.UPDATE, { + triggerId: 'trigger-fixed-id', + viewId: 'view-id' + }); + + expect(staleResult).toBeUndefined(); + }); + }); +}); diff --git a/app/lib/methods/actions.ts b/app/lib/methods/actions.ts index 06f98147847..7945f9ad7a5 100644 --- a/app/lib/methods/actions.ts +++ b/app/lib/methods/actions.ts @@ -1,4 +1,7 @@ -import { type ITriggerAction, type IUserInteraction, ModalActions } from '../../containers/UIKit/interfaces'; +import { type ServerInteraction } from '@rocket.chat/ui-kit'; + +import { type ITriggerAction, ModalActions, type TModalAction } from '../../containers/UIKit/interfaces'; +import { toServerModalInteractionType, toUserInteraction } from '../../containers/UIKit/interactionAdapters'; import EventEmitter from './helpers/events'; import fetch from './helpers/fetch'; import { random } from './helpers'; @@ -20,21 +23,31 @@ export const generateTriggerId = (appId?: string): string => { return triggerId; }; +type THandledServerInteractionType = Extract<ServerInteraction, { type: 'modal.open' | 'modal.update' | 'errors' }>['type']; +type THandledServerPayload = { + triggerId: string; + viewId?: string; + view?: { id?: string }; + appId?: string; + [key: string]: unknown; +}; + export const handlePayloadUserInteraction = ( - type: ModalActions, - { triggerId, ...data }: IUserInteraction -): ModalActions | undefined => { + type: THandledServerInteractionType, + { triggerId, ...data }: THandledServerPayload +): TModalAction | undefined => { if (!triggersId.has(triggerId)) { return; } - const appId = invalidateTriggerId(triggerId); - if (!appId) { + const triggerAppId = invalidateTriggerId(triggerId); + const payloadAppId = data.appId ?? triggerAppId; + if (!payloadAppId) { return; } const { view } = data; - let { viewId } = data; + let { viewId } = data as { viewId?: string }; if (view && view.id) { viewId = view.id; @@ -44,35 +57,35 @@ export const handlePayloadUserInteraction = ( return; } - if ([ModalActions.ERRORS].includes(type)) { + if (type === ModalActions.ERRORS) { EventEmitter.emit(viewId, { + ...data, + appId: payloadAppId, type, triggerId, - viewId, - appId, - ...data - }); + viewId + } as any); return ModalActions.ERRORS; } - if ([ModalActions.UPDATE].includes(type)) { + if (type === ModalActions.UPDATE) { EventEmitter.emit(viewId, { + ...data, + appId: payloadAppId, type, triggerId, - viewId, - appId, - ...data - }); + viewId + } as any); return ModalActions.UPDATE; } - if ([ModalActions.OPEN].includes(type) || [ModalActions.MODAL].includes(type)) { + if (type === ModalActions.OPEN) { Navigation.navigate('ModalBlockView', { data: { + ...data, + appId: payloadAppId, triggerId, - viewId, - appId, - ...data + viewId } }); return ModalActions.OPEN; @@ -81,49 +94,79 @@ export const handlePayloadUserInteraction = ( return ModalActions.CLOSE; }; -export function triggerAction({ type, actionId, appId, rid, mid, viewId, container, ...rest }: ITriggerAction) { - return new Promise<ModalActions | undefined | void>(async (resolve, reject) => { - const triggerId = generateTriggerId(appId); +export async function triggerAction({ + type, + actionId, + appId, + rid, + mid, + viewId, + container, + ...rest +}: ITriggerAction): Promise<TModalAction | undefined | void> { + const triggerId = generateTriggerId(appId); + const payload = rest.payload ?? rest.value; + + try { + const { userId, authToken } = sdk.current.currentLogin; + const { host } = sdk.current.client; + const interaction = toUserInteraction({ + type, + actionId, + appId, + rid, + mid, + viewId, + container, + payload, + blockId: rest.blockId, + value: rest.value, + view: rest.view, + isCleared: rest.isCleared, + triggerId + }); + + // we need to use fetch because this.sdk.post add /v1 to url + const result = await fetch(`${host}/api/apps/ui.interaction/${appId}/`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Auth-Token': authToken, + 'X-User-Id': userId + }, + body: JSON.stringify(interaction) + }); + + if (!result.ok) { + throw new Error(`Failed to trigger action: ${result.status}`); + } - const payload = rest.payload || rest; + const text = await result.text(); + if (!text || text.trim() === '') { + // modal.close has no body, but returns ok status + return ModalActions.CLOSE; + } + let parsed: { type?: string; [key: string]: unknown }; try { - const { userId, authToken } = sdk.current.currentLogin; - const { host } = sdk.current.client; - - // we need to use fetch because this.sdk.post add /v1 to url - const result = await fetch(`${host}/api/apps/ui.interaction/${appId}/`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-Auth-Token': authToken, - 'X-User-Id': userId - }, - body: JSON.stringify({ - type, - actionId, - payload, - container, - mid, - rid, - triggerId, - viewId - }) - }); - - try { - const { type: interactionType, ...data } = await result.json(); - return resolve(handlePayloadUserInteraction(interactionType, data)); - } catch (e) { - // modal.close has no body, so result.json will fail - // but it returns ok status - if (result.ok) { - return resolve(); - } - } - } catch (e) { - // do nothing + parsed = JSON.parse(text); + } catch { + throw new Error('Invalid JSON response from server'); + } + + const { type: interactionType, ...data } = parsed; + const modalType = toServerModalInteractionType(interactionType ?? ''); + if (!modalType) { + throw new Error(`Unknown modal interaction type: ${interactionType ?? 'undefined'}`); } - return reject(); - }); + if (modalType === ModalActions.CLOSE) { + return ModalActions.CLOSE; + } + + return handlePayloadUserInteraction(modalType, data as THandledServerPayload); + } catch (e) { + throw e instanceof Error ? e : new Error('Failed to trigger action'); + } finally { + invalidateTriggerId(triggerId); + } } diff --git a/app/lib/methods/triggerActions.test.ts b/app/lib/methods/triggerActions.test.ts new file mode 100644 index 00000000000..b8010df8910 --- /dev/null +++ b/app/lib/methods/triggerActions.test.ts @@ -0,0 +1,112 @@ +import { ActionTypes, ModalActions } from '../../containers/UIKit/interfaces'; +import Navigation from '../navigation/appNavigation'; +import { triggerAction } from './actions'; +import { triggerBlockAction, triggerCancel, triggerSubmitView } from './triggerActions'; + +jest.mock('../navigation/appNavigation', () => ({ + back: jest.fn() +})); + +jest.mock('./actions', () => ({ + triggerAction: jest.fn() +})); + +const mockedTriggerAction = triggerAction as jest.MockedFunction<typeof triggerAction>; +const mockedBack = Navigation.back as jest.MockedFunction<typeof Navigation.back>; + +describe('triggerActions wrappers', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('triggerSubmitView', () => { + const submitInput = { + viewId: 'view-id', + appId: 'app-id', + payload: { + view: { + id: 'view-id', + state: {} + } + } + }; + + it('passes submit payload to triggerAction', async () => { + mockedTriggerAction.mockResolvedValueOnce(ModalActions.UPDATE); + + await triggerSubmitView(submitInput as any); + + expect(mockedTriggerAction).toHaveBeenCalledWith({ + type: ActionTypes.SUBMIT, + ...submitInput + }); + }); + + it('goes back when triggerAction returns undefined', async () => { + mockedTriggerAction.mockResolvedValueOnce(undefined); + + await triggerSubmitView(submitInput as any); + + expect(mockedBack).toHaveBeenCalledTimes(1); + }); + + it('goes back when triggerAction returns modal.close', async () => { + mockedTriggerAction.mockResolvedValueOnce(ModalActions.CLOSE); + + await triggerSubmitView(submitInput as any); + + expect(mockedBack).toHaveBeenCalledTimes(1); + }); + + it('does not go back for modal.update', async () => { + mockedTriggerAction.mockResolvedValueOnce(ModalActions.UPDATE); + + await triggerSubmitView(submitInput as any); + + expect(mockedBack).not.toHaveBeenCalled(); + }); + + it('does not go back for modal.open', async () => { + mockedTriggerAction.mockResolvedValueOnce(ModalActions.OPEN); + + await triggerSubmitView(submitInput as any); + + expect(mockedBack).not.toHaveBeenCalled(); + }); + }); + + it('passes cancel payload to triggerAction', () => { + const input = { + view: { id: 'view-id' }, + appId: 'app-id', + viewId: 'view-id', + isCleared: false + }; + + triggerCancel(input as any); + + expect(mockedTriggerAction).toHaveBeenCalledWith({ + type: ActionTypes.CLOSED, + ...input + }); + }); + + it('passes block action payload to triggerAction', () => { + const input = { + actionId: 'action-id', + appId: 'app-id', + container: { type: 'message', id: 'container-id' }, + value: 'value', + rid: 'room-id', + mid: 'message-id', + blockId: 'block-id' + }; + + triggerBlockAction(input as any); + + expect(mockedTriggerAction).toHaveBeenCalledWith({ + type: ActionTypes.ACTION, + ...input + }); + }); +}); diff --git a/app/views/CallView/__snapshots__/index.test.tsx.snap b/app/views/CallView/__snapshots__/index.test.tsx.snap index 3ba17f50b68..e8d65ca338e 100644 --- a/app/views/CallView/__snapshots__/index.test.tsx.snap +++ b/app/views/CallView/__snapshots__/index.test.tsx.snap @@ -323,7 +323,7 @@ exports[`Story Snapshots: ConnectedCall should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -1081,7 +1081,7 @@ exports[`Story Snapshots: ConnectingCall should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -1839,7 +1839,7 @@ exports[`Story Snapshots: MutedAndOnHold should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -2593,7 +2593,7 @@ exports[`Story Snapshots: MutedCall should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -3347,7 +3347,7 @@ exports[`Story Snapshots: OnHoldCall should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text @@ -4101,7 +4101,7 @@ exports[`Story Snapshots: SpeakerOn should match snapshot 1`] = ` ] } > -  +  </Text> </View> <Text diff --git a/app/views/CallView/components/CallActionButton.stories.tsx b/app/views/CallView/components/CallActionButton.stories.tsx index b7ccf058e4d..bbe843b4a1b 100644 --- a/app/views/CallView/components/CallActionButton.stories.tsx +++ b/app/views/CallView/components/CallActionButton.stories.tsx @@ -35,7 +35,7 @@ export const ActiveButton = () => ( export const DangerButton = () => ( <Wrapper> - <CallActionButton icon='phone-end' label='End' onPress={() => {}} variant='danger' testID='call-action-button' /> + <CallActionButton icon='phone-off' label='End' onPress={() => {}} variant='danger' testID='call-action-button' /> </Wrapper> ); @@ -54,7 +54,7 @@ export const AllVariants = () => ( </View> <View style={[styles.row, { marginTop: 24 }]}> <CallActionButton icon='message' label='Message' onPress={() => {}} testID='message' /> - <CallActionButton icon='phone-end' label='End' onPress={() => {}} variant='danger' testID='end' /> + <CallActionButton icon='phone-off' label='End' onPress={() => {}} variant='danger' testID='end' /> <CallActionButton icon='kebab' label='More' onPress={() => {}} testID='more' /> </View> </Wrapper> diff --git a/app/views/CallView/components/CallActionButton.test.tsx b/app/views/CallView/components/CallActionButton.test.tsx index 53809927c98..f60c96b3ce8 100644 --- a/app/views/CallView/components/CallActionButton.test.tsx +++ b/app/views/CallView/components/CallActionButton.test.tsx @@ -57,7 +57,7 @@ describe('CallActionButton', () => { it('should render with danger variant', () => { const { getByTestId } = render( - <CallActionButton icon='phone-end' label='End' onPress={onPressMock} variant='danger' testID='call-action-button' /> + <CallActionButton icon='phone-off' label='End' onPress={onPressMock} variant='danger' testID='call-action-button' /> ); expect(getByTestId('call-action-button')).toBeTruthy(); }); diff --git a/app/views/CallView/components/CallButtons.tsx b/app/views/CallView/components/CallButtons.tsx index bd707f286e7..831bc05ffc0 100644 --- a/app/views/CallView/components/CallButtons.tsx +++ b/app/views/CallView/components/CallButtons.tsx @@ -72,7 +72,7 @@ export const CallButtons = () => { <View style={styles.buttonsRow}> <CallActionButton icon='message' label={I18n.t('Message')} onPress={handleMessage} testID='call-view-message' /> <CallActionButton - icon='phone-end' + icon='phone-off' label={isConnecting ? I18n.t('Cancel') : I18n.t('End')} onPress={handleEndCall} variant='danger' diff --git a/app/views/ModalBlockView.tsx b/app/views/ModalBlockView.tsx index dce668416bf..e42f45c7e40 100644 --- a/app/views/ModalBlockView.tsx +++ b/app/views/ModalBlockView.tsx @@ -12,7 +12,7 @@ import ActivityIndicator from '../containers/ActivityIndicator'; import { textParser } from '../containers/UIKit/utils'; import Navigation from '../lib/navigation/appNavigation'; import { type MasterDetailInsideStackParamList } from '../stacks/MasterDetailStack/types'; -import { ContainerTypes, ModalActions } from '../containers/UIKit/interfaces'; +import { ContainerTypes, ModalActions, type TModalAction } from '../containers/UIKit/interfaces'; import { triggerBlockAction, triggerCancel, triggerSubmitView } from '../lib/methods/triggerActions'; import { type IApplicationState } from '../definitions'; import KeyboardView from '../containers/KeyboardView'; @@ -164,8 +164,8 @@ class ModalBlockView extends React.Component<IModalBlockViewProps, IModalBlockVi }); }; - handleUpdate = ({ type, ...data }: { type: ModalActions }) => { - if ([ModalActions.ERRORS].includes(type)) { + handleUpdate = ({ type, ...data }: { type: TModalAction }) => { + if (type === ModalActions.ERRORS) { const { errors }: any = data; this.setState({ errors }); } else { diff --git a/ios/custom.ttf b/ios/custom.ttf index 3151388990e26173f1f0b9471ecf479503da664c..d60bb85fc58b015925b642a282790f4a40a200b7 100644 GIT binary patch delta 2425 zcmcIkYiv|S6rR_eJNLEsxx3xcF0gIy@({Y)UAE;}Ob~guKzYft&_a2%T`3|ZCW{7* z;g`|`kr+dae@ryN6b(O2B#;<m2r&`;LC_xt2-Of@@eyOhGj|~xe`xSAch1Z`GiT13 zne%;f@+v+3Ijta!5HipaL{Y9|b#sgDsWmY24#>70{oUo{+K&bi!gZi`?dl#XL+^kt zd$DWZ@Xm{`wLb^?A%t$BzTWPh>ED?b5gG#>mHJ>ny}&Mmeg^c$zWxJ;-aHL|XzU6? z^z6RD9W%S17#!V%(Cufz$+iCOLuK?cZbIm*9<Z7)(B0qr@vm)ffPNI_50?jr4!}mC ze1o1p_b|S7952PUMwj8%k;)Nz9zBLW0JCIEVmwacNJtvT)fk4_Os3;3)V!2zSZu~& zF`vzZ4KUb{;Wh@VJkQA9#(AlL<aj)jQ`>O94bQ|4a)yUs4{J;9cpkndg?Oe?^$>+h z%HXZ}T(K~t^>-uqEl6oez<gwKx638KeLg8IOI7bO0_=*QWPIj?M7A@dJ1LDQ3d6L{ zF&aH(SkV~cl&d%@3gs1MyAw?<X}KcCF|Cecl~aWfP^iX+{j6z^W0)v9(bIw6v~F^| zagO6Gm>h3fRA<_ZQA`|z4}&?ugy@2Chck`&UXx`tdAcX0E_6bq`(Y!1jxuIyylzob zB|dq9L$+asQSQf>NZN`PtFyGs+`zUJ9AbqMSnLXwzz;-#5^YkpgmR|B9AnX584kJW z_-*4gH}n)YC7A6gM4|H;C)_m^OBKEmWNi^*ESRQn)#KBsqDV*JfM949xD!w1CKn{M zC&jtp3vMdJbioBfqw`NZSYKfX-8oM;0C0xT`{)Wz0eDJ@@qn3RB8Wr&t6&It{*UQ` z*?c-mWjoH#!>xr<qA&~6nk(c2nMg>mgdRYyx}1kHnSYjcGOrThr!`qMRC#a@wfCYW zS^zIl+X1mTo^QD8Qo4#jSOs*ooe`EI%Th64%;mF6OClcdhD<o4Sn{igO9WLSKwFRH zTqT@~i*l7bMX4ys5m7;!@gSMtDu6vKR`*cAy?#ccv!mP#KqA~Se2nONQgBbRR6~hw z9uTLxI%aA$y%+#g_IyeMUoq2x;%5WBap?r7ewtBnVoiZnGd0FIW|(nTS5xh^!kgkM z!X%UtGn+7Lrx|8pqLXf~H+>--)p96#6k~uAQ&itz!d95dV)i&qOPSnYGOolRV|X?m zvV7l?5`>PE;;PD14i(h4<ml8&4I#pyPz)gg!w5vAF~c%zSY+#j0l7mQhm{pg0m|vF zD!B#lm2kAolu#XEC|X1}N?}J5(u~a38iSfyDK(blgi*oVe2tZyWVrSNweEz48Qsme zz>Z2%<MAY$Pi%{VAGkGMKQHZ0EEwjrl$FQ=T&bbiSx=u0@i?Ir0%JiTv|*++tuCh8 zDvt?f_$r)SPL|)Tp4am6e8Vu(o*(*N8qP?73|QU-&P><g`eJaGbpoCWg+rB^uxglM zn$-n{G5W$=+nX!!)&fHwzsr!Zf60$F9KRoa;P%b%#{LCA(vlnz>hGH$O{JFP$djMe zSN?lg-xsQ9{1aGT8|gTkIG*8^{}G&ji%m@Fiu*<9Ax+b3^~FoHT3yqYEU9XX^;%7b zK{WE?^{4B;J$7>SR(sC($bi=w%8jw>4fpzylQ&xN?a>c!oS`G<Z?e%NV-MlVsijAj z{;;fP`7_HuS+SzS>p0ul*m-&7>np!rwSCpK)h~DPt`l89t*KqJWo_-+zO`ShJG}1F z`p)&|*5BMP>yh_19^3fYCUeumO_w$oHy_-5X-j(Rg>8$v!|q?UU*7Rb&z_#Ey*0f@ zcaoi_cA2}b^bPFhyASX2_Po8faqsngQ}#X8-#MxOr2%i?z`(16sH~S)l@IS1`wtFX aH~>_EZQsTX$dubhWCY*#M=M{xh<^iFTtcn@ delta 1369 zcmbu9O>7%Q6vt<Fc6WBx-u2pEuk+!L#)<79xlZgjb|R$)BuZ(%znc$Ni4!L=Nt_Qg zq5-vWfC~tO+C)@U=^-ahtrW=xDuk-2^a!XD<x;@~5<)~;P6&`_VAipV$Prd=cjnD| z`p?_>z1@xP(bb123m^c%09FA4wH-Y*VUq>h>B?vH9v#ml7wr9C&jA1()bE{2o?D=! zLVbM{re<HA{Cw@5N$M{H@WY?!iDW7m`)vk*oh2HNrs)E{%YI4y8`Q5#XO@<4ZqOOn zxeox^oSh$UOiq0lcn^TRRVwl@lU!Z^e?Tt)KPPC`vAJYs;+unpo7BHR<F75upIf4Z z(rf?s%ePO#-8I+(cXO>Uww`?-ZGkrM0Zr4Qu{exHef}Ukv`Sl8v%BD-VHsk70}S~h z^~Lznth!J!*$pfBypAugNoC`(&gS8Dk-X`eF{&2LM(XoXed{A>m7!v`38D(KPf}bA z!x7@vo=F9R?W(ysaD1pzGO;XzjLo<TA&Zbm1XUoas8-8Tm4zrg%R<O7kfvzX*Pq-u zDwF+BIxxr)bID1s#c#2?M5`TRF3w?IQ+SyWn^ab34L}HqRV1n)U<T3MnRvbm$Uu(e zC2V%%<GRLk|5qe;<I3|+JB9n#7CKK^y1_K~h|-LP-4t(pw=By=H8<1>XK$<h2Wf$A zxWLE_T?IOr_dIO^ed3E0@YoND@aogH&?j2B5cb!4LbaYl!j;7?S-*6RWb2EKP*0)z znYYC<@$_l>Af&mOkbijxdzwc$L3kr8F#5S6kvEizq}+t1JWP6g22S={R}>rKoTbKN zsv58d27Ue}*%Wa)8We(YiOKPj6KnOVD6xo>!;R&RkR&yDy<J|}MnsEXwzC%~3ak*K zNd^@QW<ha_qC?`197`bPSR)7F2^3p@R8gL_u{QHXt6%15kYhMR`I#Jqlp1-0C{<dc zz#1@#3m%*6lv6I{F;QYpXGAtN`TT>lI#qQ`B~I>HPBRmWz9lWh+h~+R4o67l5RyeT zVsC=<#aIjp%NcpeA&PE=mW5S=!DttV8Pkrs2y*C?v6}TKKfUSj_6^pIn3{eC23G&F z!Opvb=ZoX|^}QI}&pp`NM7g&forKv`OLNOsYp|`eZKJ)U{o9U}j>nx>yI$$~v^&uK zVNbf}e(z}S-QMlK>b~v%aR03{FPynDP&V+!z~&%3qzpY6t{(0mzLd}sD~YYM+S&Ao zab#_DA^GB1$=Lq*tyEQNEcMky>%{hC|CDR$cDgft@8!fan4X&n&MeJ*F?-E5`(q}N hxs!Q3*F4`le|`SmV)x?K;sGsJ|BdeFrhoYu{tZ^0_bvbc diff --git a/jest.config.js b/jest.config.js index bbaf848b1d1..fb58f54f7f5 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,7 @@ module.exports = { testPathIgnorePatterns: ['e2e', 'node_modules'], transformIgnorePatterns: [ - 'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)' + 'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg|@rocket.chat/ui-kit)' ], preset: './jest.preset.js', coverageDirectory: './coverage/', diff --git a/jest.setup.js b/jest.setup.js index d4cb05917ac..f663e2fc87d 100644 --- a/jest.setup.js +++ b/jest.setup.js @@ -98,16 +98,32 @@ jest.mock('react-native/Libraries/Utilities/useWindowDimensions', () => ({ })) })); -jest.mock('./app/lib/hooks/useResponsiveLayout/useResponsiveLayout', () => ({ - useResponsiveLayout: jest.fn(() => ({ - fontScale: 1, - isLargeFontScale: false, - fontScaleLimited: 1, - rowHeight: 75, - rowHeightCondensed: 60 - })), - FONT_SCALE_LIMIT: 1.3 -})); +jest.mock('./app/lib/hooks/useResponsiveLayout/useResponsiveLayout', () => { + const { createContext } = require('react'); + return { + useResponsiveLayout: jest.fn(() => ({ + fontScale: 1, + isLargeFontScale: false, + fontScaleLimited: 1, + rowHeight: 75, + rowHeightCondensed: 60, + width: 350, + height: 800 + })), + FONT_SCALE_LIMIT: 1.3, + BASE_ROW_HEIGHT: 75, + BASE_ROW_HEIGHT_CONDENSED: 60, + ResponsiveLayoutContext: createContext({ + fontScale: 1, + isLargeFontScale: false, + fontScaleLimited: 1, + rowHeight: 75, + rowHeightCondensed: 60, + width: 350, + height: 800 + }) + }; +}); jest.mock('./app/containers/CustomIcon', () => { const actualNav = jest.requireActual('./app/containers/CustomIcon'); diff --git a/package.json b/package.json index 3e1adde3de5..18940f3348e 100644 --- a/package.json +++ b/package.json @@ -51,8 +51,9 @@ "@rocket.chat/message-parser": "^0.31.31", "@rocket.chat/mobile-crypto": "RocketChat/rocket.chat-mobile-crypto", "@rocket.chat/sdk": "RocketChat/Rocket.Chat.js.SDK#mobile", - "@rocket.chat/ui-kit": "0.31.19", - "bytebuffer": "5.0.1", + "@rocket.chat/ui-kit": "^0.39.0", + "axios": "~0.28.1", + "bytebuffer": "~5.0.1", "color2k": "1.2.4", "dayjs": "^1.11.18", "dequal": "2.0.3", diff --git a/yarn.lock b/yarn.lock index 132ba5a32c9..975d3c6f904 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3526,6 +3526,14 @@ resolved "https://registry.yarnpkg.com/@ide/backoff/-/backoff-1.0.0.tgz#466842c25bd4a4833e0642fab41ccff064010176" integrity sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g== +"@inquirer/external-editor@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@inquirer/external-editor/-/external-editor-1.0.3.tgz#c23988291ee676290fdab3fd306e64010a6d13b8" + integrity sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA== + dependencies: + chardet "^2.1.1" + iconv-lite "^0.7.0" + "@isaacs/balanced-match@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz#3081dadbc3460661b751e7591d7faea5df39dd29" @@ -5044,10 +5052,22 @@ tiny-events "^1.0.1" universal-websocket-client "^1.0.2" -"@rocket.chat/ui-kit@0.31.19": - version "0.31.19" - resolved "https://registry.yarnpkg.com/@rocket.chat/ui-kit/-/ui-kit-0.31.19.tgz#737103123bc7e635382217eef75965b7e0f44703" - integrity sha512-8zRKQ5CoC4hIuYHVheO0d7etX9oizmM18fu99r5s/deciL/0MRWocdb4H/QsmbsNrkKCO6Z6wr7f9zzJCNTRHg== +"@rocket.chat/ui-kit@^0.39.0": + version "0.39.0" + resolved "https://registry.yarnpkg.com/@rocket.chat/ui-kit/-/ui-kit-0.39.0.tgz#6eb656224201cb36b089a2c24da3fc6b35a07d96" + integrity sha512-kdzZsR74DsUNpBQEKyhV8z0jaRsPe4u/VgR9tqHfevP4gQ/dx1GeDtl/LHkw/BADmqTn7nZpwEaelECKhtBNyQ== + dependencies: + typia "~9.7.2" + +"@rtsao/scc@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" + integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== + +"@samchon/openapi@^4.7.1": + version "4.7.2" + resolved "https://registry.yarnpkg.com/@samchon/openapi/-/openapi-4.7.2.tgz#b00c54b587b22e03e454ff58989c4a63144850b3" + integrity sha512-yj6kGWHtKK85wfJXrSmWqLWjfCd98SAvCTsVDlej2s7OfXXHqA4hmgPRNrAPIQRVi00xn26qL1PChjq1MhzlRQ== "@sideway/address@^4.1.5": version "4.1.5" @@ -5085,12 +5105,10 @@ dependencies: "@sinonjs/commons" "^3.0.0" -"@storybook/csf@^0.1.13": - version "0.1.13" - resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.1.13.tgz#c8a9bea2ae518a3d9700546748fa30a8b07f7f80" - integrity sha512-7xOOwCLGB3ebM87eemep89MYRFTko+D8qE7EdAAq74lgdqRR5cOUtYWJLjO2dLtP94nqoOdHJo6MdLLKzg412Q== - dependencies: - type-fest "^2.19.0" +"@standard-schema/spec@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8" + integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w== "@storybook/global@^5.0.0": version "5.0.0" @@ -6153,6 +6171,25 @@ array-includes@^3.1.4, array-includes@^3.1.6, array-includes@^3.1.7: get-intrinsic "^1.2.4" is-string "^1.0.7" +array-includes@^3.1.8, array-includes@^3.1.9: + version "3.1.9" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.9.tgz#1f0ccaa08e90cdbc3eb433210f903ad0f17c3f3a" + integrity sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + define-properties "^1.2.1" + es-abstract "^1.24.0" + es-object-atoms "^1.1.1" + get-intrinsic "^1.3.0" + is-string "^1.1.1" + math-intrinsics "^1.1.0" + +array-timsort@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-timsort/-/array-timsort-1.0.3.tgz#3c9e4199e54fb2b9c3fe5976396a21614ef0d926" + integrity sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ== + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -6847,6 +6884,11 @@ char-regex@^2.0.0: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.1.tgz#6dafdb25f9d3349914079f010ba8d0e6ff9cd01e" integrity sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw== +chardet@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-2.1.1.tgz#5c75593704a642f71ee53717df234031e65373c8" + integrity sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ== + check-error@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" @@ -6935,13 +6977,10 @@ cli-spinners@^2.0.0, cli-spinners@^2.5.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== cliui@^6.0.0: version "6.0.0" @@ -7082,6 +7121,11 @@ commander@9.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-9.2.0.tgz#6e21014b2ed90d8b7c9647230d8b7a94a4a419a9" integrity sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w== +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + commander@^12.0.0: version "12.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" @@ -7117,6 +7161,14 @@ commander@^9.4.1: resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== +comment-json@^4.2.3: + version "4.6.2" + resolved "https://registry.yarnpkg.com/comment-json/-/comment-json-4.6.2.tgz#235d8a908e211855b0068248a794afddb87670af" + integrity sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w== + dependencies: + array-timsort "^1.0.3" + esprima "^4.0.1" + common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -7673,7 +7725,12 @@ dotenv@^16.4.5, dotenv@~16.4.5: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== -dunder-proto@^1.0.1: +drange@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/drange/-/drange-1.1.1.tgz#b2aecec2aab82fcef11dbbd7b9e32b83f8f6c0b8" + integrity sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA== + +dunder-proto@^1.0.0, dunder-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== @@ -8741,6 +8798,13 @@ fdir@^6.5.0: resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -9487,6 +9551,13 @@ iconv-lite@0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +iconv-lite@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.2.tgz#d0bdeac3f12b4835b7359c2ad89c422a4d1cc72e" + integrity sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + idb@7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" @@ -9586,6 +9657,27 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== +inquirer@^8.2.5: + version "8.2.7" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.7.tgz#62f6b931a9b7f8735dc42db927316d8fb6f71de8" + integrity sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA== + dependencies: + "@inquirer/external-editor" "^1.0.0" + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^6.0.1" + internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" @@ -11657,6 +11749,11 @@ ms@2.1.3, ms@^2.1.1, ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -12109,6 +12206,13 @@ package-json-from-dist@^1.0.0: resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== +package-manager-detector@^0.2.0: + version "0.2.11" + resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-0.2.11.tgz#3af0b34f99d86d24af0a0620603d2e1180d05c9c" + integrity sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ== + dependencies: + quansync "^0.2.7" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -12514,6 +12618,11 @@ qs@6.13.0: dependencies: side-channel "^1.0.6" +quansync@^0.2.7: + version "0.2.11" + resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.11.tgz#f9c3adda2e1272e4f8cf3f1457b04cbdb4ee692a" + integrity sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA== + query-string@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" @@ -12546,6 +12655,14 @@ queue@6.0.2: dependencies: inherits "~2.0.3" +randexp@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.5.3.tgz#f31c2de3148b30bdeb84b7c3f59b0ebb9fec3738" + integrity sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w== + dependencies: + drange "^1.0.2" + ret "^0.2.0" + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -13415,6 +13532,11 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +ret@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c" + integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -13446,6 +13568,11 @@ rimraf@~2.6.2: dependencies: glob "^7.1.3" +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -13453,14 +13580,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.5.1: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - -rxjs@^7.8.1: +rxjs@^7.5.5, rxjs@^7.8.1: version "7.8.2" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== @@ -14481,15 +14601,7 @@ throat@^5.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== -through2@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through@^2.3.8: +through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -14787,6 +14899,19 @@ typescript@5.4.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== +typia@~9.7.2: + version "9.7.2" + resolved "https://registry.yarnpkg.com/typia/-/typia-9.7.2.tgz#e6770ae64225de25955f83a2b53ce37147d9e4d2" + integrity sha512-eLIKd0KHZtSvbsA+FYwX+Y0ZBt0BwVGz3GgODQX+6GfGL4DOzKW02LEx62oUZg6vCQX1BL5xyiPXAIdW+Hc51g== + dependencies: + "@samchon/openapi" "^4.7.1" + "@standard-schema/spec" "^1.0.0" + commander "^10.0.0" + comment-json "^4.2.3" + inquirer "^8.2.5" + package-manager-detector "^0.2.0" + randexp "^0.5.3" + typical@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" @@ -15253,7 +15378,7 @@ wordwrapjs@^4.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^6.2.0: +wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==