@staffbase/plugins-client-sdk 2.0.1 → 3.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,12 +2,12 @@
2
2
  * Bundle of @staffbase/plugins-client-sdk
3
3
  * @file Staffbase plugins client SDK for JavaScript
4
4
  * @see https://github.com/Staffbase/plugins-client-sdk#readme
5
- * @version 2.0.0
5
+ * @version 3.0.0-alpha.2
6
6
  *
7
7
  * @author Stefan Staude <stefan.staude@staffbase.com>
8
8
  * @author Daniel Große <daniel.grosse@staffbase.com>
9
9
  *
10
- * @copyright 2023
10
+ * @copyright 2026
11
11
  * @license Apache-2.0
12
12
  */
13
13
 
@@ -42,6 +42,8 @@ var loglevel = {
42
42
  var undefinedType = "undefined";
43
43
  var isIE = typeof window !== undefinedType && typeof window.navigator !== undefinedType && /Trident\/|MSIE /.test(window.navigator.userAgent);
44
44
  var logMethods = ["trace", "debug", "info", "warn", "error"];
45
+ var _loggersByName = {};
46
+ var defaultLogger = null;
45
47
 
46
48
  // Cross-browser bind equivalent that works at least back to IE6
47
49
  function bindMethod(obj, methodName) {
@@ -94,23 +96,31 @@ var loglevel = {
94
96
 
95
97
  // These private functions always need `this` to be set properly
96
98
 
97
- function replaceLoggingMethods(level, loggerName) {
99
+ function replaceLoggingMethods() {
98
100
  /*jshint validthis:true */
101
+ var level = this.getLevel();
102
+
103
+ // Replace the actual methods.
99
104
  for (var i = 0; i < logMethods.length; i++) {
100
105
  var methodName = logMethods[i];
101
- this[methodName] = i < level ? noop : this.methodFactory(methodName, level, loggerName);
106
+ this[methodName] = i < level ? noop : this.methodFactory(methodName, level, this.name);
102
107
  }
103
108
 
104
109
  // Define log.log as an alias for log.debug
105
110
  this.log = this.debug;
111
+
112
+ // Return any important warnings.
113
+ if (typeof console === undefinedType && level < this.levels.SILENT) {
114
+ return "No console available for logging";
115
+ }
106
116
  }
107
117
 
108
118
  // In old IE versions, the console isn't present until you first open it.
109
119
  // We build realMethod() replacements here that regenerate logging methods
110
- function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {
120
+ function enableLoggingWhenConsoleArrives(methodName) {
111
121
  return function () {
112
122
  if (typeof console !== undefinedType) {
113
- replaceLoggingMethods.call(this, level, loggerName);
123
+ replaceLoggingMethods.call(this);
114
124
  this[methodName].apply(this, arguments);
115
125
  }
116
126
  };
@@ -118,14 +128,34 @@ var loglevel = {
118
128
 
119
129
  // By default, we use closely bound real methods wherever possible, and
120
130
  // otherwise we wait for a console to appear, and then try again.
121
- function defaultMethodFactory(methodName, level, loggerName) {
131
+ function defaultMethodFactory(methodName, _level, _loggerName) {
122
132
  /*jshint validthis:true */
123
133
  return realMethod(methodName) || enableLoggingWhenConsoleArrives.apply(this, arguments);
124
134
  }
125
- function Logger(name, defaultLevel, factory) {
135
+ function Logger(name, factory) {
136
+ // Private instance variables.
126
137
  var self = this;
127
- var currentLevel;
128
- defaultLevel = defaultLevel == null ? "WARN" : defaultLevel;
138
+ /**
139
+ * The level inherited from a parent logger (or a global default). We
140
+ * cache this here rather than delegating to the parent so that it stays
141
+ * in sync with the actual logging methods that we have installed (the
142
+ * parent could change levels but we might not have rebuilt the loggers
143
+ * in this child yet).
144
+ * @type {number}
145
+ */
146
+ var inheritedLevel;
147
+ /**
148
+ * The default level for this logger, if any. If set, this overrides
149
+ * `inheritedLevel`.
150
+ * @type {number|null}
151
+ */
152
+ var defaultLevel;
153
+ /**
154
+ * A user-specific level for this logger. If set, this overrides
155
+ * `defaultLevel`.
156
+ * @type {number|null}
157
+ */
158
+ var userLevel;
129
159
  var storageKey = "loglevel";
130
160
  if (typeof name === "string") {
131
161
  storageKey += ":" + name;
@@ -158,9 +188,10 @@ var loglevel = {
158
188
  if (typeof storedLevel === undefinedType) {
159
189
  try {
160
190
  var cookie = window.document.cookie;
161
- var location = cookie.indexOf(encodeURIComponent(storageKey) + "=");
191
+ var cookieName = encodeURIComponent(storageKey);
192
+ var location = cookie.indexOf(cookieName + "=");
162
193
  if (location !== -1) {
163
- storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];
194
+ storedLevel = /^([^;]+)/.exec(cookie.slice(location + cookieName.length + 1))[1];
164
195
  }
165
196
  } catch (ignore) {}
166
197
  }
@@ -177,7 +208,6 @@ var loglevel = {
177
208
  // Use localStorage if available
178
209
  try {
179
210
  window.localStorage.removeItem(storageKey);
180
- return;
181
211
  } catch (ignore) {}
182
212
 
183
213
  // Use session cookie as fallback
@@ -185,6 +215,17 @@ var loglevel = {
185
215
  window.document.cookie = encodeURIComponent(storageKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC";
186
216
  } catch (ignore) {}
187
217
  }
218
+ function normalizeLevel(input) {
219
+ var level = input;
220
+ if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
221
+ level = self.levels[level.toUpperCase()];
222
+ }
223
+ if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
224
+ return level;
225
+ } else {
226
+ throw new TypeError("log.setLevel() called with invalid level: " + input);
227
+ }
228
+ }
188
229
 
189
230
  /*
190
231
  *
@@ -203,46 +244,60 @@ var loglevel = {
203
244
  };
204
245
  self.methodFactory = factory || defaultMethodFactory;
205
246
  self.getLevel = function () {
206
- return currentLevel;
247
+ if (userLevel != null) {
248
+ return userLevel;
249
+ } else if (defaultLevel != null) {
250
+ return defaultLevel;
251
+ } else {
252
+ return inheritedLevel;
253
+ }
207
254
  };
208
255
  self.setLevel = function (level, persist) {
209
- if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
210
- level = self.levels[level.toUpperCase()];
211
- }
212
- if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
213
- currentLevel = level;
214
- if (persist !== false) {
215
- // defaults to true
216
- persistLevelIfPossible(level);
217
- }
218
- replaceLoggingMethods.call(self, level, name);
219
- if (typeof console === undefinedType && level < self.levels.SILENT) {
220
- return "No console available for logging";
221
- }
222
- } else {
223
- throw "log.setLevel() called with invalid level: " + level;
256
+ userLevel = normalizeLevel(level);
257
+ if (persist !== false) {
258
+ // defaults to true
259
+ persistLevelIfPossible(userLevel);
224
260
  }
261
+
262
+ // NOTE: in v2, this should call rebuild(), which updates children.
263
+ return replaceLoggingMethods.call(self);
225
264
  };
226
265
  self.setDefaultLevel = function (level) {
227
- defaultLevel = level;
266
+ defaultLevel = normalizeLevel(level);
228
267
  if (!getPersistedLevel()) {
229
268
  self.setLevel(level, false);
230
269
  }
231
270
  };
232
271
  self.resetLevel = function () {
233
- self.setLevel(defaultLevel, false);
272
+ userLevel = null;
234
273
  clearPersistedLevel();
274
+ replaceLoggingMethods.call(self);
275
+ };
276
+ self.enableAll = function (persist) {
277
+ self.setLevel(self.levels.TRACE, persist);
235
278
  };
236
279
  self.disableAll = function (persist) {
237
280
  self.setLevel(self.levels.SILENT, persist);
238
281
  };
282
+ self.rebuild = function () {
283
+ if (defaultLogger !== self) {
284
+ inheritedLevel = normalizeLevel(defaultLogger.getLevel());
285
+ }
286
+ replaceLoggingMethods.call(self);
287
+ if (defaultLogger === self) {
288
+ for (var childName in _loggersByName) {
289
+ _loggersByName[childName].rebuild();
290
+ }
291
+ }
292
+ };
239
293
 
240
- // Initialize with the right level
294
+ // Initialize all the internal levels.
295
+ inheritedLevel = normalizeLevel(defaultLogger ? defaultLogger.getLevel() : "WARN");
241
296
  var initialLevel = getPersistedLevel();
242
- if (initialLevel == null) {
243
- initialLevel = defaultLevel;
297
+ if (initialLevel != null) {
298
+ userLevel = normalizeLevel(initialLevel);
244
299
  }
245
- self.setLevel(initialLevel, false);
300
+ replaceLoggingMethods.call(self);
246
301
  }
247
302
 
248
303
  /*
@@ -251,15 +306,14 @@ var loglevel = {
251
306
  *
252
307
  */
253
308
 
254
- var defaultLogger = new Logger();
255
- var _loggersByName = {};
309
+ defaultLogger = new Logger();
256
310
  defaultLogger.getLogger = function getLogger(name) {
257
311
  if (typeof name !== "symbol" && typeof name !== "string" || name === "") {
258
312
  throw new TypeError("You must supply a name when creating a logger.");
259
313
  }
260
314
  var logger = _loggersByName[name];
261
315
  if (!logger) {
262
- logger = _loggersByName[name] = new Logger(name, defaultLogger.getLevel(), defaultLogger.methodFactory);
316
+ logger = _loggersByName[name] = new Logger(name, defaultLogger.methodFactory);
263
317
  }
264
318
  return logger;
265
319
  };
@@ -345,7 +399,8 @@ const commands = {
345
399
  nativeShare: 'nativeShareDialog',
346
400
  langInfos: 'getLanguageInfos',
347
401
  branchDefaultLang: 'getBranchDefaultLanguage',
348
- prefContentLang: 'getPreferredContentLocale'
402
+ prefContentLang: 'getPreferredContentLocale',
403
+ userContentLocale: 'getUserContentLocale'
349
404
  };
350
405
 
351
406
  /**
@@ -443,6 +498,12 @@ var locales = {
443
498
  name: 'English',
444
499
  localizedName: 'English'
445
500
  },
501
+ enGB: {
502
+ key: 'enGB',
503
+ locale: 'en_GB',
504
+ name: 'English (United Kingdom)',
505
+ localizedName: 'English (United Kingdom)'
506
+ },
446
507
  es: {
447
508
  key: 'es',
448
509
  locale: 'es_ES',
@@ -934,7 +995,17 @@ const getPreferredContentLocale$2 = content => {
934
995
  }
935
996
  };
936
997
 
937
- let connection$2 = null;
998
+ /**
999
+ * Get the current user's content locale, fallback to branch default locale
1000
+ *
1001
+ * @return {String} the user's content locale
1002
+ */
1003
+ const getUserContentLocale$2 = () => {
1004
+ const locale = getBranchDefaultLanguage$2().locale;
1005
+ return locale;
1006
+ };
1007
+
1008
+ let connection$1 = null;
938
1009
  const fallbackKickIn = 500;
939
1010
 
940
1011
  /**
@@ -944,17 +1015,17 @@ const fallbackKickIn = 500;
944
1015
  * after the time specified in fallbackKickIn runs out.
945
1016
  * @return {Promise<function>} An appropriate send function
946
1017
  */
947
- var fallback = (() => {
948
- if (connection$2) {
949
- return connection$2;
1018
+ var fallback = () => {
1019
+ if (connection$1) {
1020
+ return connection$1;
950
1021
  }
951
- connection$2 = new Promise(resolve => {
1022
+ connection$1 = new Promise(resolve => {
952
1023
  setTimeout(function () {
953
- resolve(sendMessage$3);
1024
+ resolve(sendMessage$2);
954
1025
  }, fallbackKickIn);
955
1026
  });
956
- return connection$2;
957
- });
1027
+ return connection$1;
1028
+ };
958
1029
 
959
1030
  /**
960
1031
  * Send a SDK command to the Staffbase App.
@@ -965,7 +1036,7 @@ var fallback = (() => {
965
1036
  * @return {Promise<any>} which awaits the response of the Staffbase App
966
1037
  * @throws {Error} on commands not supported by protocol
967
1038
  */
968
- const sendMessage$3 = async function (cmd) {
1039
+ const sendMessage$2 = async function (cmd) {
969
1040
  for (var _len = arguments.length, payload = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
970
1041
  payload[_key - 1] = arguments[_key];
971
1042
  }
@@ -988,6 +1059,8 @@ const sendMessage$3 = async function (cmd) {
988
1059
  return getBranchDefaultLanguage$2();
989
1060
  case commands.prefContentLang:
990
1061
  return getPreferredContentLocale$2.apply(null, payload);
1062
+ case commands.userContentLocale:
1063
+ return getUserContentLocale$2();
991
1064
  case commands.nativeUpload:
992
1065
  case commands.nativeShare:
993
1066
  return unSupported();
@@ -1010,7 +1083,6 @@ var protocol = {
1010
1083
  // send this to call a function in the frontend
1011
1084
  ERROR: 'ERROR' // receive this when something goes wrong
1012
1085
  };
1013
-
1014
1086
  const invocationMapping = {
1015
1087
  [commands.openLink]: 'openLink',
1016
1088
  [commands.nativeUpload]: 'nativeFileUpload',
@@ -1073,11 +1145,9 @@ const create = () => {
1073
1145
  *
1074
1146
  * @param {string} id of the promise
1075
1147
  * @param {any} msg the message which will will be passed to resolve
1076
- *
1077
- * @throws {Error} on unknown id
1078
1148
  */
1079
1149
  const resolve = (id, msg) => {
1080
- if (!(id in promiseMap)) throw new Error('Tried to resolve an unknown [' + id + '] promise.');
1150
+ if (!(id in promiseMap)) return;
1081
1151
  promiseMap[id].resolve(msg);
1082
1152
  delete promiseMap[id];
1083
1153
  };
@@ -1087,10 +1157,9 @@ const resolve = (id, msg) => {
1087
1157
  *
1088
1158
  * @param {string} id of the promise
1089
1159
  * @param {any} err the error which will will be passed to reject
1090
- * @throws {Error} on unknown id
1091
1160
  */
1092
1161
  const reject = (id, err) => {
1093
- if (!(id in promiseMap)) throw new Error('Tried to reject an unknown [' + id + '] promise.');
1162
+ if (!(id in promiseMap)) return;
1094
1163
  promiseMap[id].reject(err);
1095
1164
  delete promiseMap[id];
1096
1165
  };
@@ -1125,7 +1194,7 @@ const get = id => {
1125
1194
  * @static
1126
1195
  * @return {StaticValueStore}
1127
1196
  */
1128
- const dataStore$1 = _ref => {
1197
+ const dataStore = _ref => {
1129
1198
  let {
1130
1199
  platform,
1131
1200
  language
@@ -1140,26 +1209,53 @@ const dataStore$1 = _ref => {
1140
1209
  branchDefaultLanguage: language.branchDefaultLanguage
1141
1210
  };
1142
1211
  };
1143
- let connection$1 = null;
1212
+ let connection = null;
1144
1213
  const targetOrigin = '*';
1145
1214
 
1146
1215
  /**
1147
1216
  * Connect to the Staffbase App.
1148
1217
  *
1149
- * Create a connection to a Staffbase app 3.6
1150
- * @return {Promise<function>} An appropriate send function
1218
+ * Create a connection to a Staffbase app
1219
+ * Tries to reconnect until an answer is received
1220
+ *
1221
+ * @return {Promise<Function>} An appropriate send function
1151
1222
  */
1152
- const connect$2 = () => {
1153
- if (connection$1) {
1154
- return connection$1;
1223
+ const connect$1 = () => {
1224
+ if (connection) {
1225
+ return connection;
1155
1226
  }
1156
1227
  const connectId = create();
1157
- connection$1 = get(connectId).then(function (payload) {
1158
- return sendMessage$2(dataStore$1(payload));
1228
+ let timeout;
1229
+ const delayFactor = 1.2;
1230
+ connection = get(connectId).then(payload => {
1231
+ window.clearTimeout(timeout);
1232
+ return sendMessage$1(dataStore(payload));
1159
1233
  });
1160
1234
  window.addEventListener('message', receiveMessage);
1161
- window.parent.postMessage([protocol.HELLO, connectId, []], targetOrigin);
1162
- return connection$1;
1235
+ const recurringConnect = function () {
1236
+ let delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 500;
1237
+ timeout = window.setTimeout(() => {
1238
+ if (delay < 1200) {
1239
+ recurringConnect(delay * delayFactor);
1240
+ } else {
1241
+ reject(connectId, 'No answer from Staffbase App');
1242
+ disconnect();
1243
+ }
1244
+ }, delay);
1245
+ window.parent.postMessage([protocol.HELLO, connectId, []], targetOrigin);
1246
+ };
1247
+ recurringConnect();
1248
+ return connection;
1249
+ };
1250
+
1251
+ /**
1252
+ * Disconnect from the Staffbase App
1253
+ *
1254
+ * Only useful for tests.
1255
+ */
1256
+ const disconnect = () => {
1257
+ window.removeEventListener('message', receiveMessage);
1258
+ connection = null;
1163
1259
  };
1164
1260
 
1165
1261
  /**
@@ -1211,7 +1307,7 @@ const receiveMessage = async evt => {
1211
1307
  * @return {Promise<any>} which awaits the response of the Staffbase App
1212
1308
  * @throws {Error} on commands not supported by protocol
1213
1309
  */
1214
- const sendMessage$2 = store => async function (cmd) {
1310
+ const sendMessage$1 = store => async function (cmd) {
1215
1311
  switch (cmd) {
1216
1312
  case commands.version:
1217
1313
  case commands.native:
@@ -1228,7 +1324,7 @@ const sendMessage$2 = store => async function (cmd) {
1228
1324
  for (var _len = arguments.length, payload = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1229
1325
  payload[_key - 1] = arguments[_key];
1230
1326
  }
1231
- return sendInvocationCall$1(create())(invocationMapping[cmd], payload);
1327
+ return sendInvocationCall(create())(invocationMapping[cmd], payload);
1232
1328
  default:
1233
1329
  throw new Error('Command ' + cmd + ' not supported by driver');
1234
1330
  }
@@ -1243,164 +1339,16 @@ const sendMessage$2 = store => async function (cmd) {
1243
1339
  *
1244
1340
  * @return {Promise}
1245
1341
  */
1246
- const sendInvocationCall$1 = promiseID => (process, args) => {
1342
+ const sendInvocationCall = promiseID => (process, args) => {
1247
1343
  window.parent.postMessage([protocol.INVOCATION, promiseID, process, args], targetOrigin);
1248
1344
  return get(promiseID);
1249
1345
  };
1250
1346
 
1251
- let connection = null;
1252
- let outMsgQueue = [];
1253
-
1254
- /**
1255
- * Simple store solution to make the initial data available
1256
- * as static values
1257
- *
1258
- * @param {InitialValues} initial the initial data from the frontend
1259
- * @static
1260
- * @return {StaticValueStore}
1261
- */
1262
- const dataStore = _ref => {
1263
- let {
1264
- platform,
1265
- language
1266
- } = _ref;
1267
- return {
1268
- mobile: platform.mobile,
1269
- version: platform.version,
1270
- native: platform.native,
1271
- ios: platform.native === 'ios',
1272
- android: platform.native === 'android',
1273
- langInfos: language,
1274
- branchDefaultLang: language.branchDefaultLanguage
1275
- };
1276
- };
1277
- window.Staffbase = window.Staffbase || {};
1278
- window.Staffbase.plugins = {
1279
- getMessages: multiMessageProvider,
1280
- putMessage: singleMessageReceiver
1281
- };
1282
-
1283
- /**
1284
- * Connect to the Staffbase App.
1285
- *
1286
- * Create a connection to a Staffbase app 3.6 from a native tab
1287
- * @return {Promise<function>} An appropriate send function
1288
- */
1289
- const connect$1 = () => {
1290
- if (connection) {
1291
- return connection;
1292
- }
1293
- const connectId = create();
1294
- connection = get(connectId).then(function (payload) {
1295
- return sendMessage$1(dataStore(payload));
1296
- });
1297
- outMsgQueue.push([protocol.HELLO, connectId, []]);
1298
- return connection;
1299
- };
1300
-
1301
- /**
1302
- * A function which returns an array of messages
1303
- *
1304
- * The return value holds all messages in the order the were
1305
- * received over time by sendMessage
1306
- *
1307
- * @return {Array} ordered list of messages
1308
- */
1309
- function multiMessageProvider() {
1310
- const queueRef = outMsgQueue;
1311
- if (queueRef.length) ;
1312
- outMsgQueue = [];
1313
- return queueRef;
1314
- }
1315
-
1316
- /**
1317
- * A function which can receive a single message.
1318
- *
1319
- * Can be attached to window.onPostMessage
1320
- * @param {Array} msg Staffbase 3.6 message
1321
- */
1322
- function singleMessageReceiver(msg) {
1323
- let type;
1324
- let id;
1325
- let payload;
1326
-
1327
- // safe destructure
1328
- try {
1329
- [type, id, payload] = msg;
1330
- switch (type) {
1331
- case protocol.SUCCESS:
1332
- resolve(id, payload);
1333
- break;
1334
- case protocol.ERROR:
1335
- reject(id, payload);
1336
- break;
1337
- default:
1338
- // even thought catch-ignore is a bad style
1339
- // there may be other participants listening
1340
- // to messages in a different format so we
1341
- // silently ignore here
1342
- return;
1343
- }
1344
- } catch (e) {
1345
- // even thought catch-ignore is a bad style
1346
- // there may be other participants listening
1347
- // to messages in a different format so we
1348
- // silently ignore here
1349
- return;
1350
- }
1351
- }
1352
-
1353
- /**
1354
- * Send a SDK command to the Staffbase App.
1355
- *
1356
- * Translates SDK commands into protocol native commands.
1357
- * @param {StaticValueStore} store the store object
1358
- * @param {String} cmd an SDK command
1359
- * @param {array} payload for the command
1360
- * @return {Promise<any>} which awaits the response of the Staffbase App
1361
- * @throws {Error} on commands not supported by protocol
1362
- */
1363
- const sendMessage$1 = store => async function (cmd) {
1364
- switch (cmd) {
1365
- case commands.version:
1366
- case commands.native:
1367
- case commands.mobile:
1368
- case commands.ios:
1369
- case commands.android:
1370
- case commands.langInfos:
1371
- case commands.branchDefaultLang:
1372
- return store[reversedCommands[cmd]];
1373
- case commands.openLink:
1374
- case commands.prefContentLang:
1375
- for (var _len = arguments.length, payload = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1376
- payload[_key - 1] = arguments[_key];
1377
- }
1378
- return sendInvocationCall(invocationMapping[cmd], payload);
1379
- default:
1380
- throw new Error('Command ' + cmd + ' not supported by driver');
1381
- }
1382
- };
1383
-
1384
- /**
1385
- * Create a promise and send an invocation call to the frontend
1386
- *
1387
- * @param {string} process the name of the process to call
1388
- * @param {array} args an array of arguments
1389
- *
1390
- * @return {Promise}
1391
- */
1392
- const sendInvocationCall = (process, args) => {
1393
- const promiseID = create();
1394
- outMsgQueue.push([protocol.INVOCATION, promiseID, process, args]);
1395
- return get(promiseID);
1396
- };
1397
-
1398
1347
  let connector;
1399
1348
  const connect = async () => {
1400
- const putMessageConnection = connect$1();
1401
- const postMessageConnection = connect$2();
1349
+ const postMessageConnection = connect$1();
1402
1350
  const fallbackConnection = fallback();
1403
- const realConnectionBucket = [putMessageConnection, postMessageConnection];
1351
+ const realConnectionBucket = [postMessageConnection];
1404
1352
  const fallbackConnectionBucket = realConnectionBucket.concat(fallbackConnection);
1405
1353
 
1406
1354
  // Wait on the real communication and replace the connector with
@@ -1570,6 +1518,15 @@ const getPreferredContentLocale$1 = async content => {
1570
1518
  return sendMessage(commands.prefContentLang, content);
1571
1519
  };
1572
1520
 
1521
+ /**
1522
+ * Get the default content language configured for the branch.
1523
+ *
1524
+ * @return {Promise<Object>}
1525
+ */
1526
+ const getUserContentLocale$1 = async () => {
1527
+ return sendMessage(commands.langInfos).then(res => res.userContentLocale);
1528
+ };
1529
+
1573
1530
  /**
1574
1531
  * Compare [semver](https://semver.org/) version strings to find greater, equal or lesser.
1575
1532
  * This library supports the full semver specification, including comparing versions with different number of digits like `1.0.0`, `1.0`, `1`, and pre-release versions like `1.0.0-alpha`.
@@ -1669,6 +1626,7 @@ const canDownload = async () => {
1669
1626
  * Interface exports
1670
1627
  */
1671
1628
 
1629
+
1672
1630
  /**
1673
1631
  * Check if device is able to perform a download.
1674
1632
  * @function
@@ -1775,6 +1733,13 @@ const getContentLanguages = async () => getContentLanguages$1();
1775
1733
  */
1776
1734
  const getPreferredContentLocale = async content => getPreferredContentLocale$1(content);
1777
1735
 
1736
+ /**
1737
+ * Get the current user's content locale, fallback to branch default locale
1738
+ * @function
1739
+ * @return {Promise<any>}
1740
+ */
1741
+ const getUserContentLocale = async () => getUserContentLocale$1();
1742
+
1778
1743
  /**
1779
1744
  * Open a share dialog on native devices
1780
1745
  *
@@ -1799,6 +1764,7 @@ exports.getBranchDefaultLanguage = getBranchDefaultLanguage;
1799
1764
  exports.getBranchLanguages = getBranchLanguages;
1800
1765
  exports.getContentLanguages = getContentLanguages;
1801
1766
  exports.getPreferredContentLocale = getPreferredContentLocale;
1767
+ exports.getUserContentLocale = getUserContentLocale;
1802
1768
  exports.isAndroidDevice = isAndroidDevice;
1803
1769
  exports.isIosDevice = isIosDevice;
1804
1770
  exports.isMobileApp = isMobileApp;