@staffbase/plugins-client-sdk 2.0.1 → 3.0.0-beta.4

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 2024
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
  /**
@@ -934,7 +989,17 @@ const getPreferredContentLocale$2 = content => {
934
989
  }
935
990
  };
936
991
 
937
- let connection$2 = null;
992
+ /**
993
+ * Get the current user's content locale, fallback to branch default locale
994
+ *
995
+ * @return {String} the user's content locale
996
+ */
997
+ const getUserContentLocale$2 = () => {
998
+ const locale = getBranchDefaultLanguage$2().locale;
999
+ return locale;
1000
+ };
1001
+
1002
+ let connection$1 = null;
938
1003
  const fallbackKickIn = 500;
939
1004
 
940
1005
  /**
@@ -945,15 +1010,15 @@ const fallbackKickIn = 500;
945
1010
  * @return {Promise<function>} An appropriate send function
946
1011
  */
947
1012
  var fallback = (() => {
948
- if (connection$2) {
949
- return connection$2;
1013
+ if (connection$1) {
1014
+ return connection$1;
950
1015
  }
951
- connection$2 = new Promise(resolve => {
1016
+ connection$1 = new Promise(resolve => {
952
1017
  setTimeout(function () {
953
- resolve(sendMessage$3);
1018
+ resolve(sendMessage$2);
954
1019
  }, fallbackKickIn);
955
1020
  });
956
- return connection$2;
1021
+ return connection$1;
957
1022
  });
958
1023
 
959
1024
  /**
@@ -965,7 +1030,7 @@ var fallback = (() => {
965
1030
  * @return {Promise<any>} which awaits the response of the Staffbase App
966
1031
  * @throws {Error} on commands not supported by protocol
967
1032
  */
968
- const sendMessage$3 = async function (cmd) {
1033
+ const sendMessage$2 = async function (cmd) {
969
1034
  for (var _len = arguments.length, payload = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
970
1035
  payload[_key - 1] = arguments[_key];
971
1036
  }
@@ -988,6 +1053,8 @@ const sendMessage$3 = async function (cmd) {
988
1053
  return getBranchDefaultLanguage$2();
989
1054
  case commands.prefContentLang:
990
1055
  return getPreferredContentLocale$2.apply(null, payload);
1056
+ case commands.userContentLocale:
1057
+ return getUserContentLocale$2();
991
1058
  case commands.nativeUpload:
992
1059
  case commands.nativeShare:
993
1060
  return unSupported();
@@ -1010,7 +1077,6 @@ var protocol = {
1010
1077
  // send this to call a function in the frontend
1011
1078
  ERROR: 'ERROR' // receive this when something goes wrong
1012
1079
  };
1013
-
1014
1080
  const invocationMapping = {
1015
1081
  [commands.openLink]: 'openLink',
1016
1082
  [commands.nativeUpload]: 'nativeFileUpload',
@@ -1073,11 +1139,9 @@ const create = () => {
1073
1139
  *
1074
1140
  * @param {string} id of the promise
1075
1141
  * @param {any} msg the message which will will be passed to resolve
1076
- *
1077
- * @throws {Error} on unknown id
1078
1142
  */
1079
1143
  const resolve = (id, msg) => {
1080
- if (!(id in promiseMap)) throw new Error('Tried to resolve an unknown [' + id + '] promise.');
1144
+ if (!(id in promiseMap)) return;
1081
1145
  promiseMap[id].resolve(msg);
1082
1146
  delete promiseMap[id];
1083
1147
  };
@@ -1087,10 +1151,9 @@ const resolve = (id, msg) => {
1087
1151
  *
1088
1152
  * @param {string} id of the promise
1089
1153
  * @param {any} err the error which will will be passed to reject
1090
- * @throws {Error} on unknown id
1091
1154
  */
1092
1155
  const reject = (id, err) => {
1093
- if (!(id in promiseMap)) throw new Error('Tried to reject an unknown [' + id + '] promise.');
1156
+ if (!(id in promiseMap)) return;
1094
1157
  promiseMap[id].reject(err);
1095
1158
  delete promiseMap[id];
1096
1159
  };
@@ -1125,7 +1188,7 @@ const get = id => {
1125
1188
  * @static
1126
1189
  * @return {StaticValueStore}
1127
1190
  */
1128
- const dataStore$1 = _ref => {
1191
+ const dataStore = _ref => {
1129
1192
  let {
1130
1193
  platform,
1131
1194
  language
@@ -1140,26 +1203,53 @@ const dataStore$1 = _ref => {
1140
1203
  branchDefaultLanguage: language.branchDefaultLanguage
1141
1204
  };
1142
1205
  };
1143
- let connection$1 = null;
1206
+ let connection = null;
1144
1207
  const targetOrigin = '*';
1145
1208
 
1146
1209
  /**
1147
1210
  * Connect to the Staffbase App.
1148
1211
  *
1149
- * Create a connection to a Staffbase app 3.6
1150
- * @return {Promise<function>} An appropriate send function
1212
+ * Create a connection to a Staffbase app
1213
+ * Tries to reconnect until an answer is received
1214
+ *
1215
+ * @return {Promise<Function>} An appropriate send function
1151
1216
  */
1152
- const connect$2 = () => {
1153
- if (connection$1) {
1154
- return connection$1;
1217
+ const connect$1 = () => {
1218
+ if (connection) {
1219
+ return connection;
1155
1220
  }
1156
1221
  const connectId = create();
1157
- connection$1 = get(connectId).then(function (payload) {
1158
- return sendMessage$2(dataStore$1(payload));
1222
+ let timeout;
1223
+ const delayFactor = 1.2;
1224
+ connection = get(connectId).then(payload => {
1225
+ window.clearTimeout(timeout);
1226
+ return sendMessage$1(dataStore(payload));
1159
1227
  });
1160
1228
  window.addEventListener('message', receiveMessage);
1161
- window.parent.postMessage([protocol.HELLO, connectId, []], targetOrigin);
1162
- return connection$1;
1229
+ const recurringConnect = function () {
1230
+ let delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 500;
1231
+ timeout = window.setTimeout(() => {
1232
+ if (delay < 1200) {
1233
+ recurringConnect(delay * delayFactor);
1234
+ } else {
1235
+ reject(connectId, 'No answer from Staffbase App');
1236
+ disconnect();
1237
+ }
1238
+ }, delay);
1239
+ window.parent.postMessage([protocol.HELLO, connectId, []], targetOrigin);
1240
+ };
1241
+ recurringConnect();
1242
+ return connection;
1243
+ };
1244
+
1245
+ /**
1246
+ * Disconnect from the Staffbase App
1247
+ *
1248
+ * Only useful for tests.
1249
+ */
1250
+ const disconnect = () => {
1251
+ window.removeEventListener('message', receiveMessage);
1252
+ connection = null;
1163
1253
  };
1164
1254
 
1165
1255
  /**
@@ -1211,7 +1301,7 @@ const receiveMessage = async evt => {
1211
1301
  * @return {Promise<any>} which awaits the response of the Staffbase App
1212
1302
  * @throws {Error} on commands not supported by protocol
1213
1303
  */
1214
- const sendMessage$2 = store => async function (cmd) {
1304
+ const sendMessage$1 = store => async function (cmd) {
1215
1305
  switch (cmd) {
1216
1306
  case commands.version:
1217
1307
  case commands.native:
@@ -1228,7 +1318,7 @@ const sendMessage$2 = store => async function (cmd) {
1228
1318
  for (var _len = arguments.length, payload = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
1229
1319
  payload[_key - 1] = arguments[_key];
1230
1320
  }
1231
- return sendInvocationCall$1(create())(invocationMapping[cmd], payload);
1321
+ return sendInvocationCall(create())(invocationMapping[cmd], payload);
1232
1322
  default:
1233
1323
  throw new Error('Command ' + cmd + ' not supported by driver');
1234
1324
  }
@@ -1243,164 +1333,16 @@ const sendMessage$2 = store => async function (cmd) {
1243
1333
  *
1244
1334
  * @return {Promise}
1245
1335
  */
1246
- const sendInvocationCall$1 = promiseID => (process, args) => {
1336
+ const sendInvocationCall = promiseID => (process, args) => {
1247
1337
  window.parent.postMessage([protocol.INVOCATION, promiseID, process, args], targetOrigin);
1248
1338
  return get(promiseID);
1249
1339
  };
1250
1340
 
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
1341
  let connector;
1399
1342
  const connect = async () => {
1400
- const putMessageConnection = connect$1();
1401
- const postMessageConnection = connect$2();
1343
+ const postMessageConnection = connect$1();
1402
1344
  const fallbackConnection = fallback();
1403
- const realConnectionBucket = [putMessageConnection, postMessageConnection];
1345
+ const realConnectionBucket = [postMessageConnection];
1404
1346
  const fallbackConnectionBucket = realConnectionBucket.concat(fallbackConnection);
1405
1347
 
1406
1348
  // Wait on the real communication and replace the connector with
@@ -1570,6 +1512,15 @@ const getPreferredContentLocale$1 = async content => {
1570
1512
  return sendMessage(commands.prefContentLang, content);
1571
1513
  };
1572
1514
 
1515
+ /**
1516
+ * Get the default content language configured for the branch.
1517
+ *
1518
+ * @return {Promise<Object>}
1519
+ */
1520
+ const getUserContentLocale$1 = async () => {
1521
+ return sendMessage(commands.langInfos).then(res => res.userContentLocale);
1522
+ };
1523
+
1573
1524
  /**
1574
1525
  * Compare [semver](https://semver.org/) version strings to find greater, equal or lesser.
1575
1526
  * 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 +1620,7 @@ const canDownload = async () => {
1669
1620
  * Interface exports
1670
1621
  */
1671
1622
 
1623
+
1672
1624
  /**
1673
1625
  * Check if device is able to perform a download.
1674
1626
  * @function
@@ -1775,6 +1727,13 @@ const getContentLanguages = async () => getContentLanguages$1();
1775
1727
  */
1776
1728
  const getPreferredContentLocale = async content => getPreferredContentLocale$1(content);
1777
1729
 
1730
+ /**
1731
+ * Get the current user's content locale, fallback to branch default locale
1732
+ * @function
1733
+ * @return {Promise<any>}
1734
+ */
1735
+ const getUserContentLocale = async () => getUserContentLocale$1();
1736
+
1778
1737
  /**
1779
1738
  * Open a share dialog on native devices
1780
1739
  *
@@ -1799,6 +1758,7 @@ exports.getBranchDefaultLanguage = getBranchDefaultLanguage;
1799
1758
  exports.getBranchLanguages = getBranchLanguages;
1800
1759
  exports.getContentLanguages = getContentLanguages;
1801
1760
  exports.getPreferredContentLocale = getPreferredContentLocale;
1761
+ exports.getUserContentLocale = getUserContentLocale;
1802
1762
  exports.isAndroidDevice = isAndroidDevice;
1803
1763
  exports.isIosDevice = isIosDevice;
1804
1764
  exports.isMobileApp = isMobileApp;