Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. import { DOMParser } from '@xmldom/xmldom';
  2. import { atob, btoa } from 'abab';
  3. import { NativeModules, Platform } from 'react-native';
  4. import BackgroundTimer from 'react-native-background-timer';
  5. import { TextDecoder, TextEncoder } from 'text-encoding';
  6. import 'promise.allsettled/auto'; // Promise.allSettled.
  7. import 'promise.withresolvers/auto'; // Promise.withResolvers.
  8. import 'react-native-url-polyfill/auto'; // Complete URL polyfill.
  9. import Storage from './Storage';
  10. const { AppInfo } = NativeModules;
  11. /**
  12. * Implements an absolute minimum of the common logic of
  13. * {@code Document.querySelector} and {@code Element.querySelector}. Implements
  14. * the most simple of selectors necessary to satisfy the call sites at the time
  15. * of this writing (i.e. Select by tagName).
  16. *
  17. * @param {Node} node - The Node which is the root of the tree to query.
  18. * @param {string} selectors - The group of CSS selectors to match on.
  19. * @returns {Element} - The first Element which is a descendant of the specified
  20. * node and matches the specified group of selectors.
  21. */
  22. function _querySelector(node, selectors) {
  23. let element = null;
  24. node && _visitNode(node, n => {
  25. if (n.nodeType === 1 /* ELEMENT_NODE */
  26. && n.nodeName === selectors) {
  27. element = n;
  28. return true;
  29. }
  30. return false;
  31. });
  32. return element;
  33. }
  34. /**
  35. * Visits each Node in the tree of a specific root Node (using depth-first
  36. * traversal) and invokes a specific callback until the callback returns true.
  37. *
  38. * @param {Node} node - The root Node which represents the tree of Nodes to
  39. * visit.
  40. * @param {Function} callback - The callback to invoke with each visited Node.
  41. * @returns {boolean} - True if the specified callback returned true for a Node
  42. * (at which point the visiting stopped); otherwise, false.
  43. */
  44. function _visitNode(node, callback) {
  45. if (callback(node)) {
  46. return true;
  47. }
  48. /* eslint-disable no-param-reassign, no-extra-parens */
  49. if ((node = node.firstChild)) {
  50. do {
  51. if (_visitNode(node, callback)) {
  52. return true;
  53. }
  54. } while ((node = node.nextSibling));
  55. }
  56. /* eslint-enable no-param-reassign, no-extra-parens */
  57. return false;
  58. }
  59. (global => {
  60. // DOMParser
  61. //
  62. // Required by:
  63. // - lib-jitsi-meet requires this if using WebSockets
  64. global.DOMParser = DOMParser;
  65. // addEventListener
  66. //
  67. // Required by:
  68. // - jQuery
  69. if (typeof global.addEventListener === 'undefined') {
  70. // eslint-disable-next-line no-empty-function
  71. global.addEventListener = () => {};
  72. }
  73. // removeEventListener
  74. //
  75. // Required by:
  76. // - features/base/conference/middleware
  77. if (typeof global.removeEventListener === 'undefined') {
  78. // eslint-disable-next-line no-empty-function
  79. global.removeEventListener = () => {};
  80. }
  81. // document
  82. //
  83. // Required by:
  84. // - jQuery
  85. // - Strophe
  86. if (typeof global.document === 'undefined') {
  87. const document
  88. = new DOMParser().parseFromString(
  89. '<html><head></head><body></body></html>',
  90. 'text/xml');
  91. // document.addEventListener
  92. //
  93. // Required by:
  94. // - jQuery
  95. if (typeof document.addEventListener === 'undefined') {
  96. // eslint-disable-next-line no-empty-function
  97. document.addEventListener = () => {};
  98. }
  99. // document.cookie
  100. //
  101. // Required by:
  102. // - herment
  103. if (typeof document.cookie === 'undefined') {
  104. document.cookie = '';
  105. }
  106. // document.implementation.createHTMLDocument
  107. //
  108. // Required by:
  109. // - jQuery
  110. if (typeof document.implementation.createHTMLDocument === 'undefined') {
  111. document.implementation.createHTMLDocument = function(title = '') {
  112. const htmlDocument
  113. = new DOMParser().parseFromString(
  114. `<html>
  115. <head><title>${title}</title></head>
  116. <body></body>
  117. </html>`,
  118. 'text/xml');
  119. Object.defineProperty(htmlDocument, 'body', {
  120. get() {
  121. return htmlDocument.getElementsByTagName('body')[0];
  122. }
  123. });
  124. return htmlDocument;
  125. };
  126. }
  127. // Element.querySelector
  128. //
  129. // Required by:
  130. // - lib-jitsi-meet/modules/xmpp
  131. const elementPrototype
  132. = Object.getPrototypeOf(document.documentElement);
  133. if (elementPrototype) {
  134. if (typeof elementPrototype.querySelector === 'undefined') {
  135. elementPrototype.querySelector = function(selectors) {
  136. return _querySelector(this, selectors);
  137. };
  138. }
  139. // Element.remove
  140. //
  141. // Required by:
  142. // - lib-jitsi-meet ChatRoom#onPresence parsing
  143. if (typeof elementPrototype.remove === 'undefined') {
  144. elementPrototype.remove = function() {
  145. if (this.parentNode !== null) {
  146. this.parentNode.removeChild(this);
  147. }
  148. };
  149. }
  150. // Element.innerHTML
  151. //
  152. // Required by:
  153. // - jQuery's .append method
  154. if (!elementPrototype.hasOwnProperty('innerHTML')) {
  155. Object.defineProperty(elementPrototype, 'innerHTML', {
  156. get() {
  157. return this.childNodes.toString();
  158. },
  159. set(innerHTML) {
  160. // MDN says: removes all of element's children, parses
  161. // the content string and assigns the resulting nodes as
  162. // children of the element.
  163. // Remove all of element's children.
  164. this.textContent = '';
  165. // Parse the content string.
  166. const d
  167. = new DOMParser().parseFromString(
  168. `<div>${innerHTML}</div>`,
  169. 'text/xml');
  170. // Assign the resulting nodes as children of the
  171. // element.
  172. const documentElement = d.documentElement;
  173. let child;
  174. // eslint-disable-next-line no-cond-assign
  175. while (child = documentElement.firstChild) {
  176. this.appendChild(child);
  177. }
  178. }
  179. });
  180. }
  181. // Element.children
  182. //
  183. // Required by:
  184. // - lib-jitsi-meet ChatRoom#onPresence parsing
  185. if (!elementPrototype.hasOwnProperty('children')) {
  186. Object.defineProperty(elementPrototype, 'children', {
  187. get() {
  188. const nodes = this.childNodes;
  189. const children = [];
  190. let i = 0;
  191. let node = nodes[i];
  192. while (node) {
  193. if (node.nodeType === 1) {
  194. children.push(node);
  195. }
  196. i += 1;
  197. node = nodes[i];
  198. }
  199. return children;
  200. }
  201. });
  202. }
  203. }
  204. global.document = document;
  205. }
  206. // location
  207. if (typeof global.location === 'undefined') {
  208. global.location = {
  209. href: '',
  210. // Required by:
  211. // - lib-jitsi-meet/modules/xmpp/xmpp.js
  212. search: ''
  213. };
  214. }
  215. const { navigator } = global;
  216. if (navigator) {
  217. // userAgent
  218. //
  219. // Required by:
  220. // - lib-jitsi-meet/modules/browser/BrowserDetection.js
  221. // React Native version
  222. const { reactNativeVersion } = Platform.constants;
  223. const rnVersion
  224. = `react-native/${reactNativeVersion.major}.${reactNativeVersion.minor}.${reactNativeVersion.patch}`;
  225. // (OS version)
  226. const os = `${Platform.OS.toLowerCase()}/${Platform.Version}`;
  227. // SDK
  228. const liteTxt = AppInfo.isLiteSDK ? '-lite' : '';
  229. const sdkVersion = `JitsiMeetSDK/${AppInfo.sdkVersion}${liteTxt}`;
  230. const parts = [
  231. navigator.userAgent ?? '',
  232. sdkVersion,
  233. os,
  234. rnVersion
  235. ];
  236. navigator.userAgent = parts.filter(Boolean).join(' ');
  237. }
  238. // WebRTC
  239. require('./webrtc');
  240. // Performance API
  241. // RN only provides the now() method, since the polyfill refers the global
  242. // performance object itself we extract it here to avoid infinite recursion.
  243. const performanceNow = global.performance.now;
  244. const perf = require('react-native-performance');
  245. global.performance = perf.default;
  246. global.performance.now = performanceNow;
  247. global.PerformanceObserver = perf.PerformanceObserver;
  248. // Timers
  249. //
  250. // React Native's timers won't run while the app is in the background, this
  251. // is a known limitation. Replace them with a background-friendly alternative.
  252. if (Platform.OS === 'android') {
  253. global.clearTimeout = BackgroundTimer.clearTimeout.bind(BackgroundTimer);
  254. global.clearInterval = BackgroundTimer.clearInterval.bind(BackgroundTimer);
  255. global.setInterval = BackgroundTimer.setInterval.bind(BackgroundTimer);
  256. global.setTimeout = (fn, ms = 0) => BackgroundTimer.setTimeout(fn, ms);
  257. }
  258. // localStorage
  259. if (typeof global.localStorage === 'undefined') {
  260. global.localStorage = new Storage('@jitsi-meet/');
  261. }
  262. // sessionStorage
  263. //
  264. // Required by:
  265. // - herment
  266. // - Strophe
  267. if (typeof global.sessionStorage === 'undefined') {
  268. global.sessionStorage = new Storage();
  269. }
  270. global.TextDecoder = TextDecoder;
  271. global.TextEncoder = TextEncoder;
  272. // atob
  273. //
  274. // Required by:
  275. // - Strophe
  276. if (typeof global.atob === 'undefined') {
  277. global.atob = atob;
  278. }
  279. // btoa
  280. //
  281. // Required by:
  282. // - Strophe
  283. if (typeof global.btoa === 'undefined') {
  284. global.btoa = btoa;
  285. }
  286. })(global || window || this); // eslint-disable-line no-invalid-this