maint: support 0.31 SDK (#113)
* maint: support 0.31 SDK resolve param changed from uri/uris, to urls. * feat: stop daemon sdk call * fix: ffffffffff webpack bug https://github.com/nulogy/design-system/pull/132
This commit is contained in:
parent
e94de32487
commit
ec1d5bd41a
4 changed files with 184 additions and 186 deletions
357
dist/bundle.js
vendored
357
dist/bundle.js
vendored
|
@ -7,7 +7,7 @@
|
|||
var a = factory();
|
||||
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
||||
}
|
||||
})(window, function() {
|
||||
})((typeof self !== 'undefined' ? self : this), function() {
|
||||
return /******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
@ -1279,96 +1279,96 @@ var ACTIONS = _interopRequireWildcard(_action_types);
|
|||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
/*
|
||||
Toasts:
|
||||
- First-in, first-out queue
|
||||
- Simple messages that are shown in response to user interactions
|
||||
- Never saved
|
||||
- If they are the result of errors, use the isError flag when creating
|
||||
- For errors that should interrupt user behavior, use Error
|
||||
/*
|
||||
Toasts:
|
||||
- First-in, first-out queue
|
||||
- Simple messages that are shown in response to user interactions
|
||||
- Never saved
|
||||
- If they are the result of errors, use the isError flag when creating
|
||||
- For errors that should interrupt user behavior, use Error
|
||||
*/
|
||||
/*:: export type ToastParams = {
|
||||
message: string,
|
||||
title?: string,
|
||||
linkText?: string,
|
||||
linkTarget?: string,
|
||||
isError?: boolean,
|
||||
/*:: export type ToastParams = {
|
||||
message: string,
|
||||
title?: string,
|
||||
linkText?: string,
|
||||
linkTarget?: string,
|
||||
isError?: boolean,
|
||||
};*/ // @flow
|
||||
|
||||
/*:: export type Toast = {
|
||||
id: string,
|
||||
params: ToastParams,
|
||||
/*:: export type Toast = {
|
||||
id: string,
|
||||
params: ToastParams,
|
||||
};*/
|
||||
|
||||
|
||||
/*
|
||||
Notifications:
|
||||
- List of notifications based on user interactions/app notifications
|
||||
- Always saved, but can be manually deleted
|
||||
- Can happen in the background, or because of user interaction (ex: publish confirmed)
|
||||
/*
|
||||
Notifications:
|
||||
- List of notifications based on user interactions/app notifications
|
||||
- Always saved, but can be manually deleted
|
||||
- Can happen in the background, or because of user interaction (ex: publish confirmed)
|
||||
*/
|
||||
/*:: export type DoToast = {
|
||||
type: ACTIONS.CREATE_TOAST,
|
||||
data: Toast,
|
||||
/*:: export type DoToast = {
|
||||
type: ACTIONS.CREATE_TOAST,
|
||||
data: Toast,
|
||||
};*/
|
||||
/*:: export type Notification = {
|
||||
id: string, // Unique id
|
||||
dateCreated: number,
|
||||
isRead: boolean, // Used to display "new" notifications that a user hasn't seen yet
|
||||
source?: string, // The type/area an notification is from. Used for sorting (ex: publishes, transactions)
|
||||
// We may want to use priority/isDismissed in the future to specify how urgent a notification is
|
||||
// and if the user should see it immediately
|
||||
// isDissmied: boolean,
|
||||
// priority?: number
|
||||
/*:: export type Notification = {
|
||||
id: string, // Unique id
|
||||
dateCreated: number,
|
||||
isRead: boolean, // Used to display "new" notifications that a user hasn't seen yet
|
||||
source?: string, // The type/area an notification is from. Used for sorting (ex: publishes, transactions)
|
||||
// We may want to use priority/isDismissed in the future to specify how urgent a notification is
|
||||
// and if the user should see it immediately
|
||||
// isDissmied: boolean,
|
||||
// priority?: number
|
||||
};*/
|
||||
/*:: export type DoNotification = {
|
||||
type: ACTIONS.CREATE_NOTIFICATION,
|
||||
data: Notification,
|
||||
/*:: export type DoNotification = {
|
||||
type: ACTIONS.CREATE_NOTIFICATION,
|
||||
data: Notification,
|
||||
};*/
|
||||
/*:: export type DoEditNotification = {
|
||||
type: ACTIONS.EDIT_NOTIFICATION,
|
||||
data: {
|
||||
id: string,
|
||||
isRead: boolean,
|
||||
// In the future we can add `isDismissed` if we decide to show notifications as they come in
|
||||
// Similar to Facebook's notifications in the corner of the screen
|
||||
// isDismissed: boolean,
|
||||
},
|
||||
/*:: export type DoEditNotification = {
|
||||
type: ACTIONS.EDIT_NOTIFICATION,
|
||||
data: {
|
||||
id: string,
|
||||
isRead: boolean,
|
||||
// In the future we can add `isDismissed` if we decide to show notifications as they come in
|
||||
// Similar to Facebook's notifications in the corner of the screen
|
||||
// isDismissed: boolean,
|
||||
},
|
||||
};*/
|
||||
|
||||
|
||||
/*
|
||||
Errors:
|
||||
- First-in, first-out queue
|
||||
- Errors that should interupt user behavior
|
||||
- For errors that can be shown without interrupting a user, use Toast with the isError flag
|
||||
/*
|
||||
Errors:
|
||||
- First-in, first-out queue
|
||||
- Errors that should interupt user behavior
|
||||
- For errors that can be shown without interrupting a user, use Toast with the isError flag
|
||||
*/
|
||||
/*:: export type DoDeleteNotification = {
|
||||
type: ACTIONS.DELETE_NOTIFICATION,
|
||||
data: {
|
||||
id: string, // The id to delete
|
||||
},
|
||||
/*:: export type DoDeleteNotification = {
|
||||
type: ACTIONS.DELETE_NOTIFICATION,
|
||||
data: {
|
||||
id: string, // The id to delete
|
||||
},
|
||||
};*/
|
||||
/*:: export type Error = {
|
||||
title: string,
|
||||
text: string,
|
||||
/*:: export type Error = {
|
||||
title: string,
|
||||
text: string,
|
||||
};*/
|
||||
/*:: export type DoError = {
|
||||
type: ACTIONS.CREATE_ERROR,
|
||||
data: Error,
|
||||
/*:: export type DoError = {
|
||||
type: ACTIONS.CREATE_ERROR,
|
||||
data: Error,
|
||||
};*/
|
||||
|
||||
|
||||
/*
|
||||
NotificationState
|
||||
/*
|
||||
NotificationState
|
||||
*/
|
||||
/*:: export type DoDismissError = {
|
||||
type: ACTIONS.DISMISS_ERROR,
|
||||
/*:: export type DoDismissError = {
|
||||
type: ACTIONS.DISMISS_ERROR,
|
||||
};*/
|
||||
/*:: export type NotificationState = {
|
||||
notifications: Array<Notification>,
|
||||
errors: Array<Error>,
|
||||
toasts: Array<Toast>,
|
||||
/*:: export type NotificationState = {
|
||||
notifications: Array<Notification>,
|
||||
errors: Array<Error>,
|
||||
toasts: Array<Toast>,
|
||||
};*/
|
||||
|
||||
/***/ }),
|
||||
|
@ -1630,27 +1630,27 @@ var claimIdMaxLength = 40;
|
|||
var regexInvalidURI = exports.regexInvalidURI = /[^A-Za-z0-9-]/g;
|
||||
var regexAddress = exports.regexAddress = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/;
|
||||
|
||||
/**
|
||||
* Parses a LBRY name into its component parts. Throws errors with user-friendly
|
||||
* messages for invalid names.
|
||||
*
|
||||
* N.B. that "name" indicates the value in the name position of the URI. For
|
||||
* claims for channel content, this will actually be the channel name, and
|
||||
* the content name is in the path (e.g. lbry://@channel/content)
|
||||
*
|
||||
* In most situations, you'll want to use the contentName and channelName keys
|
||||
* and ignore the name key.
|
||||
*
|
||||
* Returns a dictionary with keys:
|
||||
* - name (string): The value in the "name" position in the URI. Note that this
|
||||
* could be either content name or channel name; see above.
|
||||
* - path (string, if persent)
|
||||
* - claimSequence (int, if present)
|
||||
* - bidPosition (int, if present)
|
||||
* - claimId (string, if present)
|
||||
* - isChannel (boolean)
|
||||
* - contentName (string): For anon claims, the name; for channel claims, the path
|
||||
* - channelName (string, if present): Channel name without @
|
||||
/**
|
||||
* Parses a LBRY name into its component parts. Throws errors with user-friendly
|
||||
* messages for invalid names.
|
||||
*
|
||||
* N.B. that "name" indicates the value in the name position of the URI. For
|
||||
* claims for channel content, this will actually be the channel name, and
|
||||
* the content name is in the path (e.g. lbry://@channel/content)
|
||||
*
|
||||
* In most situations, you'll want to use the contentName and channelName keys
|
||||
* and ignore the name key.
|
||||
*
|
||||
* Returns a dictionary with keys:
|
||||
* - name (string): The value in the "name" position in the URI. Note that this
|
||||
* could be either content name or channel name; see above.
|
||||
* - path (string, if persent)
|
||||
* - claimSequence (int, if present)
|
||||
* - bidPosition (int, if present)
|
||||
* - claimId (string, if present)
|
||||
* - isChannel (boolean)
|
||||
* - contentName (string): For anon claims, the name; for channel claims, the path
|
||||
* - channelName (string, if present): Channel name without @
|
||||
*/
|
||||
function parseURI(URI) {
|
||||
var requireProto = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||||
|
@ -1758,10 +1758,10 @@ function parseURI(URI) {
|
|||
}, contentName ? { contentName: contentName } : {}, channelName ? { channelName: channelName } : {}, claimSequence ? { claimSequence: parseInt(claimSequence, 10) } : {}, bidPosition ? { bidPosition: parseInt(bidPosition, 10) } : {}, claimId ? { claimId: claimId } : {}, path ? { path: path } : {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an object in the same format returned by parse() and builds a URI.
|
||||
*
|
||||
* The channelName key will accept names with or without the @ prefix.
|
||||
/**
|
||||
* Takes an object in the same format returned by parse() and builds a URI.
|
||||
*
|
||||
* The channelName key will accept names with or without the @ prefix.
|
||||
*/
|
||||
function buildURI(URIObj) {
|
||||
var includeProto = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
||||
|
@ -1956,9 +1956,11 @@ module.exports = v4;
|
|||
// and inconsistent support for the `crypto` API. We do the best we can via
|
||||
// feature-detection
|
||||
|
||||
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation.
|
||||
var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) ||
|
||||
(typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto));
|
||||
// getRandomValues needs to be invoked in a context where "this" is a Crypto
|
||||
// implementation. Also, find the complete implementation of crypto on IE11.
|
||||
var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
|
||||
(typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
|
||||
|
||||
if (getRandomValues) {
|
||||
// WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
|
||||
var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
|
||||
|
@ -2001,14 +2003,15 @@ for (var i = 0; i < 256; ++i) {
|
|||
function bytesToUuid(buf, offset) {
|
||||
var i = offset || 0;
|
||||
var bth = byteToHex;
|
||||
return bth[buf[i++]] + bth[buf[i++]] +
|
||||
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
||||
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
||||
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
||||
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
||||
bth[buf[i++]] + bth[buf[i++]] +
|
||||
bth[buf[i++]] + bth[buf[i++]] +
|
||||
bth[buf[i++]] + bth[buf[i++]];
|
||||
// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
|
||||
return ([bth[buf[i++]], bth[buf[i++]],
|
||||
bth[buf[i++]], bth[buf[i++]], '-',
|
||||
bth[buf[i++]], bth[buf[i++]], '-',
|
||||
bth[buf[i++]], bth[buf[i++]], '-',
|
||||
bth[buf[i++]], bth[buf[i++]], '-',
|
||||
bth[buf[i++]], bth[buf[i++]],
|
||||
bth[buf[i++]], bth[buf[i++]],
|
||||
bth[buf[i++]], bth[buf[i++]]]).join('');
|
||||
}
|
||||
|
||||
module.exports = bytesToUuid;
|
||||
|
@ -2091,7 +2094,7 @@ function doResolveUris(uris) {
|
|||
});
|
||||
|
||||
var resolveInfo = {};
|
||||
_lbry2.default.resolve({ uris: urisToResolve }).then(function (result) {
|
||||
_lbry2.default.resolve({ urls: urisToResolve }).then(function (result) {
|
||||
Object.entries(result).forEach(function (_ref) {
|
||||
var _ref2 = _slicedToArray(_ref, 2),
|
||||
uri = _ref2[0],
|
||||
|
@ -2412,6 +2415,9 @@ Lbry.file_set_status = function () {
|
|||
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
return daemonCallWithResult('file_set_status', params);
|
||||
};
|
||||
Lbry.stop = function () {
|
||||
return daemonCallWithResult('stop', {});
|
||||
};
|
||||
|
||||
// claims
|
||||
Lbry.claim_list_by_channel = function () {
|
||||
|
@ -2547,12 +2553,7 @@ Lbry.resolve = function () {
|
|||
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
return new Promise(function (resolve, reject) {
|
||||
apiCall('resolve', params, function (data) {
|
||||
if ('uri' in params) {
|
||||
// If only a single URI was requested, don't nest the results in an object
|
||||
resolve(data && data[params.uri] ? data[params.uri] : {});
|
||||
} else {
|
||||
resolve(data || {});
|
||||
}
|
||||
resolve(data || {});
|
||||
}, reject);
|
||||
});
|
||||
};
|
||||
|
@ -6175,12 +6176,12 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
|
|||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
// @flow
|
||||
/*:: import type {
|
||||
NotificationState,
|
||||
DoToast,
|
||||
DoNotification,
|
||||
DoEditNotification,
|
||||
DoDeleteNotification,
|
||||
/*:: import type {
|
||||
NotificationState,
|
||||
DoToast,
|
||||
DoNotification,
|
||||
DoEditNotification,
|
||||
DoDeleteNotification,
|
||||
} from 'types/Notification';*/
|
||||
|
||||
|
||||
|
@ -6315,44 +6316,44 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
|
|||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
/*:: type SearchSuccess = {
|
||||
type: ACTIONS.SEARCH_SUCCESS,
|
||||
data: {
|
||||
query: string,
|
||||
uris: Array<string>,
|
||||
},
|
||||
/*:: type SearchSuccess = {
|
||||
type: ACTIONS.SEARCH_SUCCESS,
|
||||
data: {
|
||||
query: string,
|
||||
uris: Array<string>,
|
||||
},
|
||||
};*/
|
||||
/*:: type UpdateSearchQuery = {
|
||||
type: ACTIONS.UPDATE_SEARCH_QUERY,
|
||||
data: {
|
||||
query: string,
|
||||
},
|
||||
/*:: type UpdateSearchQuery = {
|
||||
type: ACTIONS.UPDATE_SEARCH_QUERY,
|
||||
data: {
|
||||
query: string,
|
||||
},
|
||||
};*/
|
||||
/*:: type SearchSuggestion = {
|
||||
value: string,
|
||||
shorthand: string,
|
||||
type: string,
|
||||
/*:: type SearchSuggestion = {
|
||||
value: string,
|
||||
shorthand: string,
|
||||
type: string,
|
||||
};*/
|
||||
/*:: type UpdateSearchSuggestions = {
|
||||
type: ACTIONS.UPDATE_SEARCH_SUGGESTIONS,
|
||||
data: {
|
||||
query: string,
|
||||
suggestions: Array<SearchSuggestion>,
|
||||
},
|
||||
/*:: type UpdateSearchSuggestions = {
|
||||
type: ACTIONS.UPDATE_SEARCH_SUGGESTIONS,
|
||||
data: {
|
||||
query: string,
|
||||
suggestions: Array<SearchSuggestion>,
|
||||
},
|
||||
};*/
|
||||
/*:: type SearchState = {
|
||||
isActive: boolean,
|
||||
searchQuery: string,
|
||||
suggestions: Array<SearchSuggestion>,
|
||||
urisByQuery: {},
|
||||
/*:: type SearchState = {
|
||||
isActive: boolean,
|
||||
searchQuery: string,
|
||||
suggestions: Array<SearchSuggestion>,
|
||||
urisByQuery: {},
|
||||
};*/
|
||||
/*:: type HistoryNavigate = {
|
||||
type: ACTIONS.HISTORY_NAVIGATE,
|
||||
data: {
|
||||
url: string,
|
||||
index?: number,
|
||||
scrollY?: number,
|
||||
},
|
||||
/*:: type HistoryNavigate = {
|
||||
type: ACTIONS.HISTORY_NAVIGATE,
|
||||
data: {
|
||||
url: string,
|
||||
index?: number,
|
||||
scrollY?: number,
|
||||
},
|
||||
};*/
|
||||
|
||||
|
||||
|
@ -6442,32 +6443,32 @@ var buildDraftTransaction = function buildDraftTransaction() {
|
|||
|
||||
// TODO: Split into common success and failure types
|
||||
// See details in https://github.com/lbryio/lbry/issues/1307
|
||||
/*:: type ActionResult = {
|
||||
type: any,
|
||||
result: any,
|
||||
/*:: type ActionResult = {
|
||||
type: any,
|
||||
result: any,
|
||||
};*/
|
||||
/*:: type WalletState = {
|
||||
balance: any,
|
||||
blocks: any,
|
||||
latestBlock: number,
|
||||
transactions: any,
|
||||
fetchingTransactions: boolean,
|
||||
gettingNewAddress: boolean,
|
||||
draftTransaction: any,
|
||||
sendingSupport: boolean,
|
||||
walletIsEncrypted: boolean,
|
||||
walletEncryptPending: boolean,
|
||||
walletEncryptSucceded: ?boolean,
|
||||
walletEncryptResult: ?boolean,
|
||||
walletDecryptPending: boolean,
|
||||
walletDecryptSucceded: ?boolean,
|
||||
walletDecryptResult: ?boolean,
|
||||
walletUnlockPending: boolean,
|
||||
walletUnlockSucceded: ?boolean,
|
||||
walletUnlockResult: ?boolean,
|
||||
walletLockPending: boolean,
|
||||
walletLockSucceded: ?boolean,
|
||||
walletLockResult: ?boolean,
|
||||
/*:: type WalletState = {
|
||||
balance: any,
|
||||
blocks: any,
|
||||
latestBlock: number,
|
||||
transactions: any,
|
||||
fetchingTransactions: boolean,
|
||||
gettingNewAddress: boolean,
|
||||
draftTransaction: any,
|
||||
sendingSupport: boolean,
|
||||
walletIsEncrypted: boolean,
|
||||
walletEncryptPending: boolean,
|
||||
walletEncryptSucceded: ?boolean,
|
||||
walletEncryptResult: ?boolean,
|
||||
walletDecryptPending: boolean,
|
||||
walletDecryptSucceded: ?boolean,
|
||||
walletDecryptResult: ?boolean,
|
||||
walletUnlockPending: boolean,
|
||||
walletUnlockSucceded: ?boolean,
|
||||
walletUnlockResult: ?boolean,
|
||||
walletLockPending: boolean,
|
||||
walletLockSucceded: ?boolean,
|
||||
walletLockResult: ?boolean,
|
||||
};*/
|
||||
|
||||
|
||||
|
@ -6954,7 +6955,7 @@ Object.defineProperty(exports, "__esModule", {
|
|||
value: true
|
||||
});
|
||||
/* hardcoded names still exist for these in reducers/settings.js - only discovered when debugging */
|
||||
/* Many SETTINGS are stored in the localStorage by their name -
|
||||
/* Many SETTINGS are stored in the localStorage by their name -
|
||||
be careful about changing the value of a SETTINGS constant, as doing so can invalidate existing SETTINGS */
|
||||
var CREDIT_REQUIRED_ACKNOWLEDGED = exports.CREDIT_REQUIRED_ACKNOWLEDGED = 'credit_required_acknowledged';
|
||||
var NEW_USER_ACKNOWLEDGED = exports.NEW_USER_ACKNOWLEDGED = 'welcome_acknowledged';
|
||||
|
|
|
@ -70,6 +70,7 @@ Lbry.status = (params = {}) => daemonCallWithResult('status', params);
|
|||
Lbry.version = () => daemonCallWithResult('version', {});
|
||||
Lbry.file_delete = (params = {}) => daemonCallWithResult('file_delete', params);
|
||||
Lbry.file_set_status = (params = {}) => daemonCallWithResult('file_set_status', params);
|
||||
Lbry.stop = () => daemonCallWithResult('stop', {});
|
||||
|
||||
// claims
|
||||
Lbry.claim_list_by_channel = (params = {}) => daemonCallWithResult('claim_list_by_channel', params);
|
||||
|
@ -189,12 +190,7 @@ Lbry.resolve = (params = {}) =>
|
|||
'resolve',
|
||||
params,
|
||||
data => {
|
||||
if ('uri' in params) {
|
||||
// If only a single URI was requested, don't nest the results in an object
|
||||
resolve(data && data[params.uri] ? data[params.uri] : {});
|
||||
} else {
|
||||
resolve(data || {});
|
||||
}
|
||||
resolve(data || {});
|
||||
},
|
||||
reject
|
||||
);
|
||||
|
|
|
@ -32,7 +32,7 @@ export function doResolveUris(uris, returnCachedClaims = false) {
|
|||
});
|
||||
|
||||
const resolveInfo = {};
|
||||
Lbry.resolve({ uris: urisToResolve }).then(result => {
|
||||
Lbry.resolve({ urls: urisToResolve }).then(result => {
|
||||
Object.entries(result).forEach(([uri, uriResolveInfo]) => {
|
||||
const fallbackResolveInfo = {
|
||||
claim: null,
|
||||
|
|
|
@ -8,7 +8,8 @@ module.exports = {
|
|||
output: {
|
||||
filename: 'bundle.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
libraryTarget: 'umd'
|
||||
libraryTarget: 'umd',
|
||||
globalObject: `(typeof self !== 'undefined' ? self : this)`
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
|
|
Loading…
Reference in a new issue