diff --git a/dist/bundle.es.js b/dist/bundle.es.js index b477130..2a9f916 100644 --- a/dist/bundle.es.js +++ b/dist/bundle.es.js @@ -2,12 +2,9 @@ Object.defineProperty(exports, '__esModule', { value: true }); -function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } - require('proxy-polyfill'); var uuid = require('uuid'); var reselect = require('reselect'); -var fromEntries = _interopDefault(require('@ungap/from-entries')); const MINIMUM_PUBLISH_BID = 0.00000001; @@ -137,9 +134,6 @@ const ABANDON_CLAIM_SUCCEEDED = 'ABANDON_CLAIM_SUCCEEDED'; const FETCH_CHANNEL_LIST_STARTED = 'FETCH_CHANNEL_LIST_STARTED'; const FETCH_CHANNEL_LIST_COMPLETED = 'FETCH_CHANNEL_LIST_COMPLETED'; const FETCH_CHANNEL_LIST_FAILED = 'FETCH_CHANNEL_LIST_FAILED'; -const FETCH_COLLECTION_LIST_STARTED = 'FETCH_COLLECTION_LIST_STARTED'; -const FETCH_COLLECTION_LIST_COMPLETED = 'FETCH_COLLECTION_LIST_COMPLETED'; -const FETCH_COLLECTION_LIST_FAILED = 'FETCH_COLLECTION_LIST_FAILED'; const CREATE_CHANNEL_STARTED = 'CREATE_CHANNEL_STARTED'; const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED'; const CREATE_CHANNEL_FAILED = 'CREATE_CHANNEL_FAILED'; @@ -149,7 +143,6 @@ const UPDATE_CHANNEL_FAILED = 'UPDATE_CHANNEL_FAILED'; const IMPORT_CHANNEL_STARTED = 'IMPORT_CHANNEL_STARTED'; const IMPORT_CHANNEL_COMPLETED = 'IMPORT_CHANNEL_COMPLETED'; const IMPORT_CHANNEL_FAILED = 'IMPORT_CHANNEL_FAILED'; -const CLEAR_CHANNEL_ERRORS = 'CLEAR_CHANNEL_ERRORS'; const PUBLISH_STARTED = 'PUBLISH_STARTED'; const PUBLISH_COMPLETED = 'PUBLISH_COMPLETED'; const PUBLISH_FAILED = 'PUBLISH_FAILED'; @@ -168,6 +161,7 @@ const CLAIM_REPOST_STARTED = 'CLAIM_REPOST_STARTED'; const CLAIM_REPOST_COMPLETED = 'CLAIM_REPOST_COMPLETED'; const CLAIM_REPOST_FAILED = 'CLAIM_REPOST_FAILED'; const CLEAR_REPOST_ERROR = 'CLEAR_REPOST_ERROR'; +const CLEAR_CHANNEL_ERRORS = 'CLEAR_CHANNEL_ERRORS'; const CHECK_PUBLISH_NAME_STARTED = 'CHECK_PUBLISH_NAME_STARTED'; const CHECK_PUBLISH_NAME_COMPLETED = 'CHECK_PUBLISH_NAME_COMPLETED'; const UPDATE_PENDING_CLAIMS = 'UPDATE_PENDING_CLAIMS'; @@ -180,27 +174,6 @@ const PURCHASE_LIST_STARTED = 'PURCHASE_LIST_STARTED'; const PURCHASE_LIST_COMPLETED = 'PURCHASE_LIST_COMPLETED'; const PURCHASE_LIST_FAILED = 'PURCHASE_LIST_FAILED'; -const COLLECTION_PUBLISH_STARTED = 'COLLECTION_PUBLISH_STARTED'; -const COLLECTION_PUBLISH_COMPLETED = 'COLLECTION_PUBLISH_COMPLETED'; -const COLLECTION_PUBLISH_FAILED = 'COLLECTION_PUBLISH_FAILED'; -const COLLECTION_PUBLISH_UPDATE_STARTED = 'COLLECTION_PUBLISH_UPDATE_STARTED'; -const COLLECTION_PUBLISH_UPDATE_COMPLETED = 'COLLECTION_PUBLISH_UPDATE_COMPLETED'; -const COLLECTION_PUBLISH_UPDATE_FAILED = 'COLLECTION_PUBLISH_UPDATE_FAILED'; -const COLLECTION_PUBLISH_ABANDON_STARTED = 'COLLECTION_PUBLISH_ABANDON_STARTED'; -const COLLECTION_PUBLISH_ABANDON_COMPLETED = 'COLLECTION_PUBLISH_ABANDON_COMPLETED'; -const COLLECTION_PUBLISH_ABANDON_FAILED = 'COLLECTION_PUBLISH_ABANDON_FAILED'; -const CLEAR_COLLECTION_ERRORS = 'CLEAR_COLLECTION_ERRORS'; -const COLLECTION_ITEMS_RESOLVE_STARTED = 'COLLECTION_ITEMS_RESOLVE_STARTED'; -const COLLECTION_ITEMS_RESOLVE_COMPLETED = 'COLLECTION_ITEMS_RESOLVE_COMPLETED'; -const COLLECTION_ITEMS_RESOLVE_FAILED = 'COLLECTION_ITEMS_RESOLVE_FAILED'; -const COLLECTION_NEW = 'COLLECTION_NEW'; -const COLLECTION_DELETE = 'COLLECTION_DELETE'; -const COLLECTION_PENDING = 'COLLECTION_PENDING'; -const COLLECTION_EDIT = 'COLLECTION_EDIT'; -const COLLECTION_COPY = 'COLLECTION_COPY'; -const COLLECTION_SAVE = 'COLLECTION_SAVE'; -const COLLECTION_ERROR = 'COLLECTION_ERROR'; - // Comments const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED'; const COMMENT_LIST_COMPLETED = 'COMMENT_LIST_COMPLETED'; @@ -436,9 +409,6 @@ var action_types = /*#__PURE__*/Object.freeze({ FETCH_CHANNEL_LIST_STARTED: FETCH_CHANNEL_LIST_STARTED, FETCH_CHANNEL_LIST_COMPLETED: FETCH_CHANNEL_LIST_COMPLETED, FETCH_CHANNEL_LIST_FAILED: FETCH_CHANNEL_LIST_FAILED, - FETCH_COLLECTION_LIST_STARTED: FETCH_COLLECTION_LIST_STARTED, - FETCH_COLLECTION_LIST_COMPLETED: FETCH_COLLECTION_LIST_COMPLETED, - FETCH_COLLECTION_LIST_FAILED: FETCH_COLLECTION_LIST_FAILED, CREATE_CHANNEL_STARTED: CREATE_CHANNEL_STARTED, CREATE_CHANNEL_COMPLETED: CREATE_CHANNEL_COMPLETED, CREATE_CHANNEL_FAILED: CREATE_CHANNEL_FAILED, @@ -448,7 +418,6 @@ var action_types = /*#__PURE__*/Object.freeze({ IMPORT_CHANNEL_STARTED: IMPORT_CHANNEL_STARTED, IMPORT_CHANNEL_COMPLETED: IMPORT_CHANNEL_COMPLETED, IMPORT_CHANNEL_FAILED: IMPORT_CHANNEL_FAILED, - CLEAR_CHANNEL_ERRORS: CLEAR_CHANNEL_ERRORS, PUBLISH_STARTED: PUBLISH_STARTED, PUBLISH_COMPLETED: PUBLISH_COMPLETED, PUBLISH_FAILED: PUBLISH_FAILED, @@ -467,6 +436,7 @@ var action_types = /*#__PURE__*/Object.freeze({ CLAIM_REPOST_COMPLETED: CLAIM_REPOST_COMPLETED, CLAIM_REPOST_FAILED: CLAIM_REPOST_FAILED, CLEAR_REPOST_ERROR: CLEAR_REPOST_ERROR, + CLEAR_CHANNEL_ERRORS: CLEAR_CHANNEL_ERRORS, CHECK_PUBLISH_NAME_STARTED: CHECK_PUBLISH_NAME_STARTED, CHECK_PUBLISH_NAME_COMPLETED: CHECK_PUBLISH_NAME_COMPLETED, UPDATE_PENDING_CLAIMS: UPDATE_PENDING_CLAIMS, @@ -478,26 +448,6 @@ var action_types = /*#__PURE__*/Object.freeze({ PURCHASE_LIST_STARTED: PURCHASE_LIST_STARTED, PURCHASE_LIST_COMPLETED: PURCHASE_LIST_COMPLETED, PURCHASE_LIST_FAILED: PURCHASE_LIST_FAILED, - COLLECTION_PUBLISH_STARTED: COLLECTION_PUBLISH_STARTED, - COLLECTION_PUBLISH_COMPLETED: COLLECTION_PUBLISH_COMPLETED, - COLLECTION_PUBLISH_FAILED: COLLECTION_PUBLISH_FAILED, - COLLECTION_PUBLISH_UPDATE_STARTED: COLLECTION_PUBLISH_UPDATE_STARTED, - COLLECTION_PUBLISH_UPDATE_COMPLETED: COLLECTION_PUBLISH_UPDATE_COMPLETED, - COLLECTION_PUBLISH_UPDATE_FAILED: COLLECTION_PUBLISH_UPDATE_FAILED, - COLLECTION_PUBLISH_ABANDON_STARTED: COLLECTION_PUBLISH_ABANDON_STARTED, - COLLECTION_PUBLISH_ABANDON_COMPLETED: COLLECTION_PUBLISH_ABANDON_COMPLETED, - COLLECTION_PUBLISH_ABANDON_FAILED: COLLECTION_PUBLISH_ABANDON_FAILED, - CLEAR_COLLECTION_ERRORS: CLEAR_COLLECTION_ERRORS, - COLLECTION_ITEMS_RESOLVE_STARTED: COLLECTION_ITEMS_RESOLVE_STARTED, - COLLECTION_ITEMS_RESOLVE_COMPLETED: COLLECTION_ITEMS_RESOLVE_COMPLETED, - COLLECTION_ITEMS_RESOLVE_FAILED: COLLECTION_ITEMS_RESOLVE_FAILED, - COLLECTION_NEW: COLLECTION_NEW, - COLLECTION_DELETE: COLLECTION_DELETE, - COLLECTION_PENDING: COLLECTION_PENDING, - COLLECTION_EDIT: COLLECTION_EDIT, - COLLECTION_COPY: COLLECTION_COPY, - COLLECTION_SAVE: COLLECTION_SAVE, - COLLECTION_ERROR: COLLECTION_ERROR, COMMENT_LIST_STARTED: COMMENT_LIST_STARTED, COMMENT_LIST_COMPLETED: COMMENT_LIST_COMPLETED, COMMENT_LIST_FAILED: COMMENT_LIST_FAILED, @@ -719,7 +669,7 @@ const INSTANT_PURCHASE_MAX = 'instant_purchase_max'; const THEME = 'theme'; const THEMES = 'themes'; const AUTOMATIC_DARK_MODE_ENABLED = 'automatic_dark_mode_enabled'; -const AUTOPLAY_MEDIA = 'autoplay'; +const AUTOPLAY = 'autoplay'; const AUTOPLAY_NEXT = 'autoplay_next'; const OS_NOTIFICATIONS_ENABLED = 'os_notifications_enabled'; const AUTO_DOWNLOAD = 'auto_download'; @@ -735,8 +685,6 @@ const ENABLE_PUBLISH_PREVIEW = 'enable-publish-preview'; const TILE_LAYOUT = 'tile_layout'; const VIDEO_THEATER_MODE = 'video_theater_mode'; const VIDEO_PLAYBACK_RATE = 'video_playback_rate'; -const CUSTOM_COMMENTS_SERVER_ENABLED = 'custom_comments_server_enabled'; -const CUSTOM_COMMENTS_SERVER_URL = 'custom_comments_server_url'; // mobile settings const BACKGROUND_PLAY_ENABLED = 'backgroundPlayEnabled'; @@ -770,7 +718,7 @@ var settings = /*#__PURE__*/Object.freeze({ THEME: THEME, THEMES: THEMES, AUTOMATIC_DARK_MODE_ENABLED: AUTOMATIC_DARK_MODE_ENABLED, - AUTOPLAY_MEDIA: AUTOPLAY_MEDIA, + AUTOPLAY: AUTOPLAY, AUTOPLAY_NEXT: AUTOPLAY_NEXT, OS_NOTIFICATIONS_ENABLED: OS_NOTIFICATIONS_ENABLED, AUTO_DOWNLOAD: AUTO_DOWNLOAD, @@ -786,8 +734,6 @@ var settings = /*#__PURE__*/Object.freeze({ TILE_LAYOUT: TILE_LAYOUT, VIDEO_THEATER_MODE: VIDEO_THEATER_MODE, VIDEO_PLAYBACK_RATE: VIDEO_PLAYBACK_RATE, - CUSTOM_COMMENTS_SERVER_ENABLED: CUSTOM_COMMENTS_SERVER_ENABLED, - CUSTOM_COMMENTS_SERVER_URL: CUSTOM_COMMENTS_SERVER_URL, BACKGROUND_PLAY_ENABLED: BACKGROUND_PLAY_ENABLED, FOREGROUND_NOTIFICATION_ENABLED: FOREGROUND_NOTIFICATION_ENABLED, KEEP_DAEMON_RUNNING: KEEP_DAEMON_RUNNING, @@ -1040,44 +986,13 @@ var daemon_settings = /*#__PURE__*/Object.freeze({ const SDK_SYNC_KEYS = [LBRYUM_SERVERS, SHARE_USAGE_DATA]; // CLIENT -const CLIENT_SYNC_KEYS = [SHOW_MATURE, HIDE_REPOSTS, SHOW_ANONYMOUS, INSTANT_PURCHASE_ENABLED, INSTANT_PURCHASE_MAX, THEME, AUTOPLAY_MEDIA, AUTOPLAY_NEXT, HIDE_BALANCE, HIDE_SPLASH_ANIMATION, FLOATING_PLAYER, DARK_MODE_TIMES, AUTOMATIC_DARK_MODE_ENABLED, LANGUAGE]; +const CLIENT_SYNC_KEYS = [SHOW_MATURE, HIDE_REPOSTS, SHOW_ANONYMOUS, INSTANT_PURCHASE_ENABLED, INSTANT_PURCHASE_MAX, THEME, AUTOPLAY, HIDE_BALANCE, HIDE_SPLASH_ANIMATION, FLOATING_PLAYER, DARK_MODE_TIMES, AUTOMATIC_DARK_MODE_ENABLED]; var shared_preferences = /*#__PURE__*/Object.freeze({ SDK_SYNC_KEYS: SDK_SYNC_KEYS, CLIENT_SYNC_KEYS: CLIENT_SYNC_KEYS }); -const COLLECTION_ID = 'lid'; -const COLLECTION_INDEX = 'linx'; - -const COL_TYPE_PLAYLIST = 'playlist'; -const COL_TYPE_CHANNELS = 'channelList'; - -const WATCH_LATER_ID = 'watchlater'; -const FAVORITES_ID = 'favorites'; -const FAVORITE_CHANNELS_ID = 'favoriteChannels'; -const BUILTIN_LISTS = [WATCH_LATER_ID, FAVORITES_ID, FAVORITE_CHANNELS_ID]; - -const COL_KEY_EDITED = 'edited'; -const COL_KEY_UNPUBLISHED = 'unpublished'; -const COL_KEY_PENDING = 'pending'; -const COL_KEY_SAVED = 'saved'; - -var collections = /*#__PURE__*/Object.freeze({ - COLLECTION_ID: COLLECTION_ID, - COLLECTION_INDEX: COLLECTION_INDEX, - COL_TYPE_PLAYLIST: COL_TYPE_PLAYLIST, - COL_TYPE_CHANNELS: COL_TYPE_CHANNELS, - WATCH_LATER_ID: WATCH_LATER_ID, - FAVORITES_ID: FAVORITES_ID, - FAVORITE_CHANNELS_ID: FAVORITE_CHANNELS_ID, - BUILTIN_LISTS: BUILTIN_LISTS, - COL_KEY_EDITED: COL_KEY_EDITED, - COL_KEY_UNPUBLISHED: COL_KEY_UNPUBLISHED, - COL_KEY_PENDING: COL_KEY_PENDING, - COL_KEY_SAVED: COL_KEY_SAVED -}); - const DEFAULT_FOLLOWED_TAGS = ['art', 'automotive', 'blockchain', 'comedy', 'economics', 'education', 'gaming', 'music', 'news', 'science', 'sports', 'technology']; const MATURE_TAGS = ['porn', 'porno', 'nsfw', 'mature', 'xxx', 'sex', 'creampie', 'blowjob', 'handjob', 'vagina', 'boobs', 'big boobs', 'big dick', 'pussy', 'cumshot', 'anal', 'hard fucking', 'ass', 'fuck', 'hentai']; @@ -1170,10 +1085,6 @@ const Lbry = { support_create: params => daemonCallWithResult('support_create', params), support_list: params => daemonCallWithResult('support_list', params), stream_repost: params => daemonCallWithResult('stream_repost', params), - collection_resolve: params => daemonCallWithResult('collection_resolve', params), - collection_list: params => daemonCallWithResult('collection_list', params), - collection_create: params => daemonCallWithResult('collection_create', params), - collection_update: params => daemonCallWithResult('collection_update', params), // File fetching and manipulation file_list: (params = {}) => daemonCallWithResult('file_list', params), @@ -1197,7 +1108,6 @@ const Lbry = { utxo_release: (params = {}) => daemonCallWithResult('utxo_release', params), support_abandon: (params = {}) => daemonCallWithResult('support_abandon', params), purchase_list: (params = {}) => daemonCallWithResult('purchase_list', params), - txo_list: (params = {}) => daemonCallWithResult('txo_list', params), sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params), sync_apply: (params = {}) => daemonCallWithResult('sync_apply', params), @@ -1480,7 +1390,7 @@ const channelNameMinLength = 1; const claimIdMaxLength = 40; // see https://spec.lbry.com/#urls -const regexInvalidURI = /[ =&#:$@%?;/\\"<>%{}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u; +const regexInvalidURI = /[ =&#:$@%?;/\\"<>%\{\}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u; const regexAddress = /^(b|r)(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; const regexPartProtocol = '^((?:lbry://)?)'; const regexPartStreamOrChannelName = '([^:$#/]*)'; @@ -1488,11 +1398,6 @@ const regexPartModifierSeparator = '([:$#]?)([^/]*)'; const queryStringBreaker = '^([\\S]+)([?][\\S]*)'; const separateQuerystring = new RegExp(queryStringBreaker); -const MOD_SEQUENCE_SEPARATOR = '*'; -const MOD_CLAIM_ID_SEPARATOR_OLD = '#'; -const MOD_CLAIM_ID_SEPARATOR = ':'; -const MOD_BID_POSITION_SEPARATOR = '$'; - /** * Parses a LBRY name into its component parts. Throws errors with user-friendly * messages for invalid names. @@ -1594,11 +1499,11 @@ function parseURIModifier(modSeperator, modValue) { throw new Error(__(`No modifier provided after separator %modSeperator%.`, { modSeperator })); } - if (modSeperator === MOD_CLAIM_ID_SEPARATOR || MOD_CLAIM_ID_SEPARATOR_OLD) { + if (modSeperator === '#') { claimId = modValue; - } else if (modSeperator === MOD_SEQUENCE_SEPARATOR) { + } else if (modSeperator === ':') { claimSequence = modValue; - } else if (modSeperator === MOD_BID_POSITION_SEPARATOR) { + } else if (modSeperator === '$') { bidPosition = modValue; } } @@ -1729,25 +1634,6 @@ function convertToShareLink(URL) { }, true, 'https://open.lbry.com/'); } -function splitBySeparator(uri) { - const protocolLength = 7; - return uri.startsWith('lbry://') ? uri.slice(protocolLength).split(/[#:*]/) : uri.split(/#:\*\$/); -} - -function isURIEqual(uriA, uriB) { - const parseA = parseURI(normalizeURI(uriA)); - const parseB = parseURI(normalizeURI(uriB)); - if (parseA.isChannel) { - if (parseB.isChannel && parseA.channelClaimId === parseB.channelClaimId) { - return true; - } - } else if (parseA.streamClaimId === parseB.streamClaimId) { - return true; - } else { - return false; - } -} - /* eslint-disable */ // underscore's deep equal function // https://github.com/jashkenas/underscore/blob/master/underscore.js#L1189 @@ -1869,14 +1755,10 @@ function extractUserState(rawObj) { coin_swap_codes, settings, app_welcome_version, - sharing_3P, - unpublishedCollections, - editedCollections, - builtinCollections, - savedCollections + sharing_3P } = rawObj.value; - return _extends$1({}, subscriptions ? { subscriptions } : {}, following ? { following } : {}, tags ? { tags } : {}, blocked ? { blocked } : {}, coin_swap_codes ? { coin_swap_codes } : {}, settings ? { settings } : {}, app_welcome_version ? { app_welcome_version } : {}, sharing_3P ? { sharing_3P } : {}, unpublishedCollections ? { unpublishedCollections } : {}, editedCollections ? { editedCollections } : {}, builtinCollections ? { builtinCollections } : {}, savedCollections ? { savedCollections } : {}); + return _extends$1({}, subscriptions ? { subscriptions } : {}, following ? { following } : {}, tags ? { tags } : {}, blocked ? { blocked } : {}, coin_swap_codes ? { coin_swap_codes } : {}, settings ? { settings } : {}, app_welcome_version ? { app_welcome_version } : {}, sharing_3P ? { sharing_3P } : {}); } return {}; @@ -1892,11 +1774,7 @@ function doPopulateSharedUserState(sharedSettings) { coin_swap_codes, settings, app_welcome_version, - sharing_3P, - unpublishedCollections, - editedCollections, - builtinCollections, - savedCollections + sharing_3P } = extractUserState(sharedSettings); dispatch({ type: USER_STATE_POPULATE, @@ -1908,11 +1786,7 @@ function doPopulateSharedUserState(sharedSettings) { coinSwapCodes: coin_swap_codes, settings, welcomeVersion: app_welcome_version, - allowAnalytics: sharing_3P, - unpublishedCollections, - editedCollections, - builtinCollections, - savedCollections + allowAnalytics: sharing_3P } }); }; @@ -1976,10 +1850,9 @@ function doPreferenceGet(key, success, fail) { // -const RUN_PREFERENCES_DELAY_MS = 2000; const SHARED_PREFERENCE_VERSION = '0.1'; let oldShared = {}; -let timeout; + const buildSharedStateMiddleware = (actions, sharedStateFilters, sharedStateCb) => ({ getState, dispatch @@ -1990,41 +1863,38 @@ const buildSharedStateMiddleware = (actions, sharedStateFilters, sharedStateCb) if (!actions.includes(action.type) || typeof action === 'function') { return next(action); } - clearTimeout(timeout); + const actionResult = next(action); // Call `getState` after calling `next` to ensure the state has updated in response to the action - function runPreferences() { - const nextState = getState(); - const syncEnabled = nextState.settings && nextState.settings.clientSettings && nextState.settings.clientSettings.enable_sync; - const hasVerifiedEmail = nextState.user && nextState.user.user && nextState.user.user.has_verified_email; - const preferenceKey = syncEnabled && hasVerifiedEmail ? 'shared' : 'local'; - const shared = {}; + const nextState = getState(); + const syncEnabled = nextState.settings && nextState.settings.clientSettings && nextState.settings.clientSettings.enable_sync; + const hasVerifiedEmail = nextState.user && nextState.user.user && nextState.user.user.has_verified_email; + const preferenceKey = syncEnabled && hasVerifiedEmail ? 'shared' : 'local'; + const shared = {}; - Object.keys(sharedStateFilters).forEach(key => { - const filter = sharedStateFilters[key]; - const { source, property, transform } = filter; - let value = nextState[source][property]; - if (transform) { - value = transform(value); - } - - shared[key] = value; - }); - - if (!isEqual(oldShared, shared)) { - // only update if the preference changed from last call in the same session - oldShared = shared; - dispatch(doPreferenceSet(preferenceKey, shared, SHARED_PREFERENCE_VERSION)); + Object.keys(sharedStateFilters).forEach(key => { + const filter = sharedStateFilters[key]; + const { source, property, transform } = filter; + let value = nextState[source][property]; + if (transform) { + value = transform(value); } - if (sharedStateCb) { - // Pass dispatch to the callback to consumers can dispatch actions in response to preference set - sharedStateCb({ dispatch, getState }); - } - clearTimeout(timeout); - return actionResult; + shared[key] = value; + }); + + if (!isEqual(oldShared, shared)) { + // only update if the preference changed from last call in the same session + oldShared = shared; + dispatch(doPreferenceSet(preferenceKey, shared, SHARED_PREFERENCE_VERSION)); } - timeout = setTimeout(runPreferences, RUN_PREFERENCES_DELAY_MS); + + if (sharedStateCb) { + // Pass dispatch to the callback to consumers can dispatch actions in response to preference set + sharedStateCb({ dispatch, getState }); + } + + return actionResult; }; // @@ -2405,13 +2275,7 @@ var _extends$3 = Object.assign || function (target) { for (var i = 1; i < argume const selectState$1 = state => state.claims || {}; -const selectById = reselect.createSelector(selectState$1, state => state.byId || {}); - -const selectPendingClaimsById = reselect.createSelector(selectState$1, state => state.pendingById || {}); - -const selectClaimsById = reselect.createSelector(selectById, selectPendingClaimsById, (byId, pendingById) => { - return Object.assign(byId, pendingById); // do I need merged to keep metadata? -}); +const selectClaimsById = reselect.createSelector(selectState$1, state => state.byId || {}); const selectClaimIdsByUri = reselect.createSelector(selectState$1, state => state.claimsByUri || {}); @@ -2446,25 +2310,19 @@ const selectClaimsByUri = reselect.createSelector(selectClaimIdsByUri, selectCla const selectAllClaimsByChannel = reselect.createSelector(selectState$1, state => state.paginatedClaimsByChannel || {}); -const selectPendingIds = reselect.createSelector(selectState$1, state => Object.keys(state.pendingById) || []); +const selectPendingIds = reselect.createSelector(selectState$1, state => state.pendingIds || []); -const selectPendingClaims = reselect.createSelector(selectPendingClaimsById, pendingById => Object.values(pendingById)); +const selectPendingClaims = reselect.createSelector(selectPendingIds, selectClaimsById, (pendingIds, byId) => pendingIds.map(id => byId[id])); -const makeSelectClaimIsPending = uri => reselect.createSelector(selectClaimIdsByUri, selectPendingClaimsById, (idsByUri, pendingById) => { +const makeSelectClaimIsPending = uri => reselect.createSelector(selectClaimIdsByUri, selectPendingIds, (idsByUri, pendingIds) => { const claimId = idsByUri[normalizeURI(uri)]; if (claimId) { - return Boolean(pendingById[claimId]); + return pendingIds.some(i => i === claimId); } return false; }); -const makeSelectClaimIdIsPending = claimId => reselect.createSelector(selectPendingClaimsById, pendingById => { - return Boolean(pendingById[claimId]); -}); - -const makeSelectClaimIdForUri = uri => reselect.createSelector(selectClaimIdsByUri, claimIds => claimIds[uri]); - const selectReflectingById = reselect.createSelector(selectState$1, state => state.reflectingById); const makeSelectClaimForClaimId = claimId => reselect.createSelector(selectClaimsById, byId => byId[claimId]); @@ -2495,7 +2353,7 @@ const makeSelectClaimForUri = (uri, returnRepost = true) => reselect.createSelec const channelUrl = claim.signing_channel && (claim.signing_channel.canonical_url || claim.signing_channel.permanent_url); return _extends$3({}, repostedClaim, { - repost_url: normalizeURI(uri), + repost_url: uri, repost_channel_url: channelUrl, repost_bid_amount: claim && claim.meta && claim.meta.effective_amount }); @@ -2593,18 +2451,25 @@ const makeSelectClaimsInChannelForPage = (uri, page) => reselect.createSelector( return claimIds.map(claimId => byId[claimId]); }); -// THIS IS LEFT OVER FROM ONE TAB CHANNEL_CONTENT const makeSelectTotalClaimsInChannelSearch = uri => reselect.createSelector(selectClaimsById, selectAllClaimsByChannel, (byId, allClaims) => { const byChannel = allClaims[uri] || {}; return byChannel['itemCount']; }); -// THIS IS LEFT OVER FROM ONE_TAB CHANNEL CONTENT const makeSelectTotalPagesInChannelSearch = uri => reselect.createSelector(selectClaimsById, selectAllClaimsByChannel, (byId, allClaims) => { const byChannel = allClaims[uri] || {}; return byChannel['pageCount']; }); +const makeSelectClaimsInChannelForCurrentPageState = uri => reselect.createSelector(selectClaimsById, selectAllClaimsByChannel, selectCurrentChannelPage, (byId, allClaims, page) => { + const byChannel = allClaims[uri] || {}; + const claimIds = byChannel[page || 1]; + + if (!claimIds) return claimIds; + + return claimIds.map(claimId => byId[claimId]); +}); + const makeSelectMetadataForUri = uri => reselect.createSelector(makeSelectClaimForUri(uri), claim => { const metadata = claim && claim.value; return metadata || (claim === undefined ? undefined : null); @@ -2670,7 +2535,7 @@ const selectMyClaims = reselect.createSelector(selectMyActiveClaims, selectClaim return [...claims]; }); -const selectMyClaimsWithoutChannels = reselect.createSelector(selectMyClaims, myClaims => myClaims.filter(claim => claim && !claim.name.match(/^@/)).sort((a, b) => a.timestamp - b.timestamp)); +const selectMyClaimsWithoutChannels = reselect.createSelector(selectMyClaims, myClaims => myClaims.filter(claim => !claim.name.match(/^@/)).sort((a, b) => a.timestamp - b.timestamp)); const selectMyClaimUrisWithoutChannels = reselect.createSelector(selectMyClaimsWithoutChannels, myClaims => { return myClaims.sort((a, b) => { @@ -2698,8 +2563,6 @@ const selectMyClaimsOutpoints = reselect.createSelector(selectMyClaims, myClaims const selectFetchingMyChannels = reselect.createSelector(selectState$1, state => state.fetchingMyChannels); -const selectFetchingMyCollections = reselect.createSelector(selectState$1, state => state.fetchingMyCollections); - const selectMyChannelClaims = reselect.createSelector(selectState$1, selectClaimsById, (state, byId) => { const ids = state.myChannelClaims; if (!ids) { @@ -2719,8 +2582,6 @@ const selectMyChannelClaims = reselect.createSelector(selectState$1, selectClaim const selectMyChannelUrls = reselect.createSelector(selectMyChannelClaims, claims => claims ? claims.map(claim => claim.canonical_url || claim.permanent_url) : undefined); -const selectMyCollectionIds = reselect.createSelector(selectState$1, state => state.myCollectionClaims); - const selectResolvingUris = reselect.createSelector(selectState$1, state => state.resolvingUris || []); const selectChannelImportPending = reselect.createSelector(selectState$1, state => state.pendingChannelImport); @@ -2731,24 +2592,34 @@ const selectPlayingUri = reselect.createSelector(selectState$1, state => state.p const selectChannelClaimCounts = reselect.createSelector(selectState$1, state => state.channelClaimCounts || {}); -const makeSelectPendingClaimForUri = uri => reselect.createSelector(selectPendingClaimsById, pendingById => { +const makeSelectPendingClaimForUri = uri => reselect.createSelector(selectPendingIds, selectClaimsById, (pending, claims) => { + let uriIsChannel; let uriStreamName; let uriChannelName; try { - ({ streamName: uriStreamName, channelName: uriChannelName } = parseURI(uri)); + ({ + isChannel: uriIsChannel, + streamName: uriStreamName, + channelName: uriChannelName + } = parseURI(uri)); } catch (e) { return null; } - const pendingClaims = Object.values(pendingById); + const pendingClaims = pending.map(id => claims[id]); const matchingClaim = pendingClaims.find(claim => { - return claim.normalized_name === uriChannelName || claim.normalized_name === uriStreamName; + const { streamName, channelName, isChannel } = parseURI(claim.permanent_url); + if (isChannel) { + return channelName === uriChannelName; + } else { + return streamName === uriStreamName; + } }); return matchingClaim || null; }); -const makeSelectTotalItemsForChannel = uri => reselect.createSelector(selectChannelClaimCounts, byUri => byUri && byUri[normalizeURI(uri)]); +const makeSelectTotalItemsForChannel = uri => reselect.createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri]); -const makeSelectTotalPagesForChannel = (uri, pageSize = 10) => reselect.createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri] && Math.ceil(byUri[normalizeURI(uri)] / pageSize)); +const makeSelectTotalPagesForChannel = (uri, pageSize = 10) => reselect.createSelector(selectChannelClaimCounts, byUri => byUri && byUri[uri] && Math.ceil(byUri[uri] / pageSize)); const makeSelectNsfwCountFromUris = uris => reselect.createSelector(selectClaimsByUri, claims => uris.reduce((acc, uri) => { const claim = claims[uri]; @@ -2758,6 +2629,21 @@ const makeSelectNsfwCountFromUris = uris => reselect.createSelector(selectClaims return acc; }, 0)); +const makeSelectNsfwCountForChannel = uri => reselect.createSelector(selectClaimsById, selectAllClaimsByChannel, selectCurrentChannelPage, (byId, allClaims, page) => { + const byChannel = allClaims[uri] || {}; + const claimIds = byChannel[page || 1]; + + if (!claimIds) return 0; + + return claimIds.reduce((acc, claimId) => { + const claim = byId[claimId]; + if (isClaimNsfw(claim)) { + return acc + 1; + } + return acc; + }, 0); +}); + const makeSelectOmittedCountForChannel = uri => reselect.createSelector(makeSelectTotalItemsForChannel(uri), makeSelectTotalClaimsInChannelSearch(uri), (claimsInChannel, claimsInSearch) => { if (claimsInChannel && typeof claimsInSearch === 'number' && claimsInSearch >= 0) { return claimsInChannel - claimsInSearch; @@ -2911,14 +2797,6 @@ const makeSelectStakedLevelForChannelUri = uri => reselect.createSelector(makeSe return level; }); -const selectUpdatingCollection = reselect.createSelector(selectState$1, state => state.updatingCollection); - -const selectUpdateCollectionError = reselect.createSelector(selectState$1, state => state.updateCollectionError); - -const selectCreatingCollection = reselect.createSelector(selectState$1, state => state.creatingCollection); - -const selectCreateCollectionError = reselect.createSelector(selectState$1, state => state.createCollectionError); - function numberWithCommas(x) { var parts = x.toString().split('.'); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ','); @@ -3028,8 +2906,9 @@ function doBalanceSubscribe() { }; } -function doFetchTransactions(page = 1, pageSize = 999999) { +function doFetchTransactions(page = 1, pageSize = 99999) { return dispatch => { + dispatch(doFetchSupports()); dispatch({ type: FETCH_TRANSACTIONS_STARTED }); @@ -3111,6 +2990,23 @@ function doUpdateTxoPageParams(params) { }; } +function doFetchSupports(page = 1, pageSize = 99999) { + return dispatch => { + dispatch({ + type: FETCH_SUPPORTS_STARTED + }); + + lbryProxy.support_list({ page, page_size: pageSize }).then(result => { + dispatch({ + type: FETCH_SUPPORTS_COMPLETED, + data: { + supports: result.items + } + }); + }); + }; +} + function doFetchUtxoCounts() { return (() => { var _ref = _asyncToGenerator(function* (dispatch) { @@ -3296,7 +3192,7 @@ function doSetDraftTransactionAddress(address) { }; } -function doSendTip(params, isSupport, successCallback, errorCallback, shouldNotify = true) { +function doSendTip(params, isSupport, successCallback, errorCallback) { return (dispatch, getState) => { const state = getState(); const balance = selectBalance(state); @@ -3312,21 +3208,19 @@ function doSendTip(params, isSupport, successCallback, errorCallback, shouldNoti return; } - const success = response => { - if (shouldNotify) { - dispatch(doToast({ - message: shouldSupport ? __('You deposited %amount% LBRY Credits as a support!', { amount: params.amount }) : __('You sent %amount% LBRY Credits as a tip, Mahalo!', { amount: params.amount }), - linkText: __('History'), - linkTarget: '/wallet' - })); - } + const success = () => { + dispatch(doToast({ + message: shouldSupport ? __('You deposited %amount% LBRY Credits as a support!', { amount: params.amount }) : __('You sent %amount% LBRY Credits as a tip, Mahalo!', { amount: params.amount }), + linkText: __('History'), + linkTarget: '/wallet' + })); dispatch({ type: SUPPORT_TRANSACTION_COMPLETED }); if (successCallback) { - successCallback(response); + successCallback(); } }; @@ -3622,192 +3516,10 @@ function batchActions(...actions) { }; } -// - -const selectState$2 = state => state.collections; - -const selectSavedCollectionIds = reselect.createSelector(selectState$2, collectionState => collectionState.saved); - -const selectBuiltinCollections = reselect.createSelector(selectState$2, state => state.builtin); -const selectResolvedCollections = reselect.createSelector(selectState$2, state => state.resolved); - -const selectMyUnpublishedCollections = reselect.createSelector(selectState$2, state => state.unpublished); - -const selectMyEditedCollections = reselect.createSelector(selectState$2, state => state.edited); - -const selectPendingCollections = reselect.createSelector(selectState$2, state => state.pending); - -const makeSelectEditedCollectionForId = id => reselect.createSelector(selectMyEditedCollections, eLists => eLists[id]); - -const makeSelectPendingCollectionForId = id => reselect.createSelector(selectPendingCollections, pending => pending[id]); - -const makeSelectPublishedCollectionForId = id => reselect.createSelector(selectResolvedCollections, rLists => rLists[id]); - -const makeSelectUnpublishedCollectionForId = id => reselect.createSelector(selectMyUnpublishedCollections, rLists => rLists[id]); - -const makeSelectCollectionIsMine = id => reselect.createSelector(selectMyCollectionIds, selectMyUnpublishedCollections, selectBuiltinCollections, (publicIds, privateIds, builtinIds) => { - return Boolean(publicIds.includes(id) || privateIds[id] || builtinIds[id]); -}); - -const selectMyPublishedCollections = reselect.createSelector(selectResolvedCollections, selectPendingCollections, selectMyEditedCollections, selectMyCollectionIds, (resolved, pending, edited, myIds) => { - // all resolved in myIds, plus those in pending and edited - const myPublishedCollections = fromEntries(Object.entries(pending).concat(Object.entries(resolved).filter(([key, val]) => myIds.includes(key) && - // $FlowFixMe - !pending[key]))); - // now add in edited: - Object.entries(edited).forEach(([id, item]) => { - myPublishedCollections[id] = item; - }); - return myPublishedCollections; -}); - -const selectMyPublishedMixedCollections = reselect.createSelector(selectMyPublishedCollections, published => { - const myCollections = fromEntries( - // $FlowFixMe - Object.entries(published).filter(([key, collection]) => { - // $FlowFixMe - return collection.type === 'collection'; - })); - return myCollections; -}); - -const selectMyPublishedPlaylistCollections = reselect.createSelector(selectMyPublishedCollections, published => { - const myCollections = fromEntries( - // $FlowFixMe - Object.entries(published).filter(([key, collection]) => { - // $FlowFixMe - return collection.type === 'playlist'; - })); - return myCollections; -}); - -const makeSelectMyPublishedCollectionForId = id => reselect.createSelector(selectMyPublishedCollections, myPublishedCollections => myPublishedCollections[id]); - -// export const selectSavedCollections = createSelector( -// selectResolvedCollections, -// selectSavedCollectionIds, -// (resolved, myIds) => { -// const mySavedCollections = fromEntries( -// Object.entries(resolved).filter(([key, val]) => myIds.includes(key)) -// ); -// return mySavedCollections; -// } -// ); - -const makeSelectIsResolvingCollectionForId = id => reselect.createSelector(selectState$2, state => { - return state.isResolvingCollectionById[id]; -}); - -const makeSelectCollectionForId = id => reselect.createSelector(selectBuiltinCollections, selectResolvedCollections, selectMyUnpublishedCollections, selectMyEditedCollections, selectPendingCollections, (bLists, rLists, uLists, eLists, pLists) => { - const collection = bLists[id] || uLists[id] || eLists[id] || pLists[id] || rLists[id]; - return collection; -}); - -const makeSelectClaimUrlInCollection = url => reselect.createSelector(selectBuiltinCollections, selectMyPublishedCollections, selectMyUnpublishedCollections, selectMyEditedCollections, selectPendingCollections, (bLists, myRLists, uLists, eLists, pLists) => { - const collections = [bLists, uLists, eLists, myRLists, pLists]; - const itemsInCollections = []; - collections.map(list => { - Object.entries(list).forEach(([key, value]) => { - // $FlowFixMe - value.items.map(item => { - itemsInCollections.push(item); - }); - }); - }); - return itemsInCollections.includes(url); -}); - -const makeSelectCollectionForIdHasClaimUrl = (id, url) => reselect.createSelector(makeSelectCollectionForId(id), collection => collection && collection.items.includes(url)); - -const makeSelectUrlsForCollectionId = id => reselect.createSelector(makeSelectCollectionForId(id), collection => collection && collection.items); - -const makeSelectClaimIdsForCollectionId = id => reselect.createSelector(makeSelectCollectionForId(id), collection => { - const items = collection && collection.items || []; - const ids = items.map(item => { - const { claimId } = parseURI(item); - return claimId; - }); - return ids; -}); - -const makeSelectIndexForUrlInCollection = (url, id) => reselect.createSelector(state => state.content.shuffleList, makeSelectUrlsForCollectionId(id), makeSelectClaimForUri(url), (shuffleState, urls, claim) => { - const shuffleUrls = shuffleState && shuffleState.collectionId === id && shuffleState.newUrls; - const listUrls = shuffleUrls || urls; - - const index = listUrls && listUrls.findIndex(u => u === url); - if (index > -1) { - return index; - } else if (claim) { - const index = listUrls && listUrls.findIndex(u => u === claim.permanent_url); - if (index > -1) return index; - return claim; - } - return null; -}); - -const makeSelectPreviousUrlForCollectionAndUrl = (id, url) => reselect.createSelector(state => state.content.shuffleList, state => state.content.loopList, makeSelectIndexForUrlInCollection(url, id), makeSelectUrlsForCollectionId(id), (shuffleState, loopState, index, urls) => { - const loopList = loopState && loopState.collectionId === id && loopState.loop; - const shuffleUrls = shuffleState && shuffleState.collectionId === id && shuffleState.newUrls; - - if (index > -1) { - const listUrls = shuffleUrls || urls; - let nextUrl; - if (index === 0 && loopList) { - nextUrl = listUrls[listUrls.length - 1]; - } else { - nextUrl = listUrls[index - 1]; - } - return nextUrl || null; - } else { - return null; - } -}); - -const makeSelectNextUrlForCollectionAndUrl = (id, url) => reselect.createSelector(state => state.content.shuffleList, state => state.content.loopList, makeSelectIndexForUrlInCollection(url, id), makeSelectUrlsForCollectionId(id), (shuffleState, loopState, index, urls) => { - const loopList = loopState && loopState.collectionId === id && loopState.loop; - const shuffleUrls = shuffleState && shuffleState.collectionId === id && shuffleState.newUrls; - - if (index > -1) { - const listUrls = shuffleUrls || urls; - // We'll get the next playble url - let remainingUrls = listUrls.slice(index + 1); - if (!remainingUrls.length && loopList) { - remainingUrls = listUrls.slice(0); - } - const nextUrl = remainingUrls && remainingUrls[0]; - return nextUrl || null; - } else { - return null; - } -}); - -const makeSelectNameForCollectionId = id => reselect.createSelector(makeSelectCollectionForId(id), collection => { - return collection && collection.name || ''; -}); - -const makeSelectCountForCollectionId = id => reselect.createSelector(makeSelectCollectionForId(id), collection => { - if (collection) { - if (collection.itemCount !== undefined) { - return collection.itemCount; - } - let itemCount = 0; - collection.items.map(item => { - if (item) { - itemCount += 1; - } - }); - return itemCount; - } - return null; -}); - var _extends$5 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _asyncToGenerator$1(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } -let onChannelConfirmCallback; -let checkPendingInterval; - function doResolveUris(uris, returnCachedClaims = false, resolveReposts = true) { return (dispatch, getState) => { const normalizedUris = uris.map(normalizeURI); @@ -3841,8 +3553,6 @@ function doResolveUris(uris, returnCachedClaims = false, resolveReposts = true) const resolveInfo = {}; - const collectionIds = []; - return lbryProxy.resolve(_extends$5({ urls: urisToResolve }, options)).then((() => { var _ref = _asyncToGenerator$1(function* (result) { let repostedResults = {}; @@ -3859,7 +3569,6 @@ function doResolveUris(uris, returnCachedClaims = false, resolveReposts = true) // https://github.com/facebook/flow/issues/2221 if (uriResolveInfo) { if (uriResolveInfo.error) { - // $FlowFixMe resolveInfo[uri] = _extends$5({}, fallbackResolveInfo); } else { if (checkReposts) { @@ -3876,10 +3585,6 @@ function doResolveUris(uris, returnCachedClaims = false, resolveReposts = true) result.channel = uriResolveInfo; // $FlowFixMe result.claimsInChannel = uriResolveInfo.meta.claims_in_channel; - } else if (uriResolveInfo.value_type === 'collection') { - result.collection = uriResolveInfo; - // $FlowFixMe - collectionIds.push(uriResolveInfo.claim_id); } else { result.stream = uriResolveInfo; if (uriResolveInfo.signing_channel) { @@ -3908,11 +3613,6 @@ function doResolveUris(uris, returnCachedClaims = false, resolveReposts = true) type: RESOLVE_URIS_COMPLETED, data: { resolveInfo } }); - - if (collectionIds.length) { - dispatch(doFetchItemsInCollections({ collectionIds: collectionIds, pageSize: 5 })); - } - return result; }); @@ -4146,7 +3846,7 @@ function doClearChannelErrors() { }; } -function doCreateChannel(name, amount, optionalParams, onConfirm) { +function doCreateChannel(name, amount, optionalParams, cb) { return dispatch => { dispatch({ type: CREATE_CHANNEL_STARTED @@ -4200,7 +3900,7 @@ function doCreateChannel(name, amount, optionalParams, onConfirm) { claims: [channelClaim] } }); - dispatch(doCheckPendingClaims(onConfirm)); + dispatch(doCheckPendingClaims(cb)); return channelClaim; }).catch(error => { dispatch({ @@ -4241,6 +3941,7 @@ function doUpdateChannel(params, cb) { } // we'll need to remove these once we add locations/channels to channel page edit/create options + if (channelClaim && channelClaim.value && channelClaim.value.locations) { updateParams.locations = channelClaim.value.locations; } @@ -4274,7 +3975,7 @@ function doImportChannel(certificate) { type: IMPORT_CHANNEL_STARTED }); - return lbryProxy.channel_import({ channel_data: certificate }).then(() => { + return lbryProxy.channel_import({ channel_data: certificate }).then(result => { dispatch({ type: IMPORT_CHANNEL_COMPLETED }); @@ -4311,35 +4012,6 @@ function doFetchChannelListMine(page = 1, pageSize = 99999, resolve = true) { }; } -function doFetchCollectionListMine(page = 1, pageSize = 99999) { - return dispatch => { - dispatch({ - type: FETCH_COLLECTION_LIST_STARTED - }); - - const callback = response => { - const { items } = response; - dispatch({ - type: FETCH_COLLECTION_LIST_COMPLETED, - data: { claims: items } - }); - dispatch(doFetchItemsInCollections({ - collectionIds: items.map(claim => claim.claim_id), - page_size: 5 - })); - }; - - const failure = error => { - dispatch({ - type: FETCH_COLLECTION_LIST_FAILED, - data: error - }); - }; - - lbryProxy.collection_list({ page, page_size: pageSize, resolve_claims: 1, resolve: true }).then(callback, failure); - }; -} - function doClaimSearch(options = { no_totals: true, page_size: 10, @@ -4371,7 +4043,7 @@ function doClaimSearch(options = { pageSize: options.page_size } }); - return resolveInfo; + return true; }; const failure = function (err) { @@ -4396,6 +4068,7 @@ function doClaimSearch(options = { function doRepost(options) { return dispatch => { + // $FlowFixMe return new Promise(resolve => { dispatch({ type: CLAIM_REPOST_STARTED @@ -4435,151 +4108,6 @@ function doRepost(options) { }; } -function doCollectionPublish(options, localId) { - return dispatch => { - // $FlowFixMe - - const params = { - name: options.name, - bid: creditsToString(options.bid), - title: options.title, - thumbnail_url: options.thumbnail_url, - description: options.description, - tags: [], - languages: options.languages || [], - locations: [], - blocking: true, - claims: options.claims - }; - - if (options.tags) { - params['tags'] = options.tags.map(tag => tag.name); - } - - if (options.channel_id) { - params['channel_id'] = options.channel_id; - } - - return new Promise(resolve => { - dispatch({ - type: COLLECTION_PUBLISH_STARTED - }); - - function success(response) { - const collectionClaim = response.outputs[0]; - dispatch(batchActions({ - type: COLLECTION_PUBLISH_COMPLETED, - data: { claimId: collectionClaim.claim_id } - }, - // move unpublished collection to pending collection with new publish id - // recent publish won't resolve this second. handle it in checkPending - { - type: UPDATE_PENDING_CLAIMS, - data: { - claims: [collectionClaim] - } - })); - dispatch({ - type: COLLECTION_PENDING, - data: { localId: localId, claimId: collectionClaim.claim_id } - }); - dispatch(doCheckPendingClaims()); - dispatch(doFetchCollectionListMine(1, 10)); - return resolve(collectionClaim); - } - - function failure(error) { - dispatch({ - type: COLLECTION_PUBLISH_FAILED, - data: { - error: error.message - } - }); - } - - return lbryProxy.collection_create(params).then(success, failure); - }); - }; -} - -function doCollectionPublishUpdate(options, isBackgroundUpdate) { - return (dispatch, getState) => { - // TODO: implement one click update - - const updateParams = isBackgroundUpdate ? { - blocking: true, - claim_id: options.claim_id, - clear_claims: true - } : { - bid: creditsToString(options.bid), - title: options.title, - thumbnail_url: options.thumbnail_url, - description: options.description, - tags: [], - languages: options.languages || [], - locations: [], - blocking: true, - claim_id: options.claim_id, - clear_claims: true, - replace: true - }; - - if (isBackgroundUpdate && updateParams.claim_id) { - const state = getState(); - updateParams['claims'] = makeSelectClaimIdsForCollectionId(updateParams.claim_id)(state); - } else if (options.claims) { - updateParams['claims'] = options.claims; - } - - if (options.tags) { - updateParams['tags'] = options.tags.map(tag => tag.name); - } - - if (options.channel_id) { - updateParams['channel_id'] = options.channel_id; - } - - return new Promise(resolve => { - dispatch({ - type: COLLECTION_PUBLISH_UPDATE_STARTED - }); - - function success(response) { - const collectionClaim = response.outputs[0]; - dispatch({ - type: COLLECTION_PUBLISH_UPDATE_COMPLETED, - data: { - collectionClaim - } - }); - dispatch({ - type: COLLECTION_PENDING, - data: { claimId: collectionClaim.claim_id } - }); - dispatch({ - type: UPDATE_PENDING_CLAIMS, - data: { - claims: [collectionClaim] - } - }); - dispatch(doCheckPendingClaims()); - return resolve(collectionClaim); - } - - function failure(error) { - dispatch({ - type: COLLECTION_PUBLISH_UPDATE_FAILED, - data: { - error: error.message - } - }); - } - - return lbryProxy.collection_update(updateParams).then(success, failure); - }); - }; -} - function doCheckPublishNameAvailability(name) { return dispatch => { dispatch({ @@ -4642,530 +4170,51 @@ function doPurchaseList(page = 1, pageSize = PAGE_SIZE) { }; } -const doCheckPendingClaims = onChannelConfirmed => (dispatch, getState) => { - if (onChannelConfirmed) { - onChannelConfirmCallback = onChannelConfirmed; - } - clearInterval(checkPendingInterval); - const checkTxoList = () => { +const doCheckPendingClaims = onConfirmed => (dispatch, getState) => { + let claimCheckInterval; + + const checkClaimList = () => { const state = getState(); - const pendingById = Object.assign({}, selectPendingClaimsById(state)); - const pendingTxos = Object.values(pendingById).map(p => p.txid); - // use collections - const pendingCollections = selectPendingCollections(state); - if (pendingTxos.length) { - lbryProxy.txo_list({ txid: pendingTxos }).then(result => { - const txos = result.items; - const idsToConfirm = []; - txos.forEach(txo => { - if (txo.claim_id && txo.confirmations > 0) { - idsToConfirm.push(txo.claim_id); - delete pendingById[txo.claim_id]; + const pendingIdSet = new Set(selectPendingIds(state)); + lbryProxy.claim_list({ page: 1, page_size: 10 }).then(result => { + const claims = result.items; + const claimsToConfirm = []; + claims.forEach(claim => { + const { claim_id: claimId } = claim; + if (claim.confirmations > 0 && pendingIdSet.has(claimId)) { + pendingIdSet.delete(claimId); + claimsToConfirm.push(claim); + if (onConfirmed) { + onConfirmed(claim); } - }); - return { idsToConfirm, pendingById }; - }).then(results => { - const { idsToConfirm, pendingById } = results; - if (idsToConfirm.length) { - return lbryProxy.claim_list({ claim_id: idsToConfirm, resolve: true }).then(results => { - const claims = results.items; - const collectionIds = claims.filter(c => c.value_type === 'collection').map(c => c.claim_id); - dispatch({ - type: UPDATE_CONFIRMED_CLAIMS, - data: { - claims: claims, - pending: pendingById - } - }); - if (collectionIds.length) { - dispatch(doFetchItemsInCollections({ - collectionIds - })); - } - const channelClaims = claims.filter(claim => claim.value_type === 'channel'); - if (channelClaims.length && onChannelConfirmCallback) { - channelClaims.forEach(claim => onChannelConfirmCallback(claim)); - } - if (Object.keys(pendingById).length === 0) { - clearInterval(checkPendingInterval); - } - }); } }); - } else { - clearInterval(checkPendingInterval); - } + if (claimsToConfirm.length) { + dispatch({ + type: UPDATE_CONFIRMED_CLAIMS, + data: { + claims: claimsToConfirm + } + }); + } + return pendingIdSet.size; + }).then(len => { + if (!len) { + clearInterval(claimCheckInterval); + } + }); }; - // do something with onConfirmed (typically get blocklist for channel) - checkPendingInterval = setInterval(() => { - checkTxoList(); + + claimCheckInterval = setInterval(() => { + checkClaimList(); }, 30000); }; -function _asyncToGenerator$2(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } +const selectState$2 = state => state.fileInfo || {}; -const getTimestamp = () => { - return Math.floor(Date.now() / 1000); -}; +const selectFileInfosByOutpoint = reselect.createSelector(selectState$2, state => state.byOutpoint || {}); -const FETCH_BATCH_SIZE = 50; - -const doLocalCollectionCreate = (name, collectionItems, type, sourceId) => dispatch => { - return dispatch({ - type: COLLECTION_NEW, - data: { - entry: { - id: uuid.v4(), // start with a uuid, this becomes a claimId after publish - name: name, - updatedAt: getTimestamp(), - items: collectionItems || [], - sourceId: sourceId, - type: type - } - } - }); -}; - -const doCollectionDelete = (id, colKey = undefined) => (dispatch, getState) => { - const state = getState(); - const claim = makeSelectClaimForClaimId(id)(state); - const collectionDelete = () => dispatch({ - type: COLLECTION_DELETE, - data: { - id: id, - collectionKey: colKey - } - }); - if (claim && !colKey) { - // could support "abandon, but keep" later - const { txid, nout } = claim; - return dispatch(doAbandonClaim(txid, nout, collectionDelete)); - } - return collectionDelete(); -}; - -// Given a collection, save its collectionId to be resolved and displayed in Library -// export const doCollectionSave = ( -// id: string, -// ) => (dispatch: Dispatch) => { -// return dispatch({ -// type: ACTIONS.COLLECTION_SAVE, -// data: { -// id: id, -// }, -// }); -// }; - -// Given a collection and name, copy it to a local private collection with a name -// export const doCollectionCopy = ( -// id: string, -// ) => (dispatch: Dispatch) => { -// return dispatch({ -// type: ACTIONS.COLLECTION_COPY, -// data: { -// id: id, -// }, -// }); -// }; - -const doFetchItemsInCollections = (resolveItemsOptions, resolveStartedCallback) => (() => { - var _ref = _asyncToGenerator$2(function* (dispatch, getState) { - let fetchItemsForCollectionClaim = (() => { - var _ref2 = _asyncToGenerator$2(function* (claim, pageSize) { - const totalItems = claim.value.claims && claim.value.claims.length; - const claimId = claim.claim_id; - const itemOrder = claim.value.claims; - - const sortResults = function (items, claimList) { - const newItems = []; - claimList.forEach(function (id) { - const index = items.findIndex(function (i) { - return i.claim_id === id; - }); - if (index >= 0) { - newItems.push(items[index]); - } - }); - /* - This will return newItems[] of length less than total_items below - if one or more of the claims has been abandoned. That's ok for now. - */ - return newItems; - }; - - const mergeBatches = function (arrayOfResults, claimList) { - const mergedResults = { - items: [], - total_items: 0 - }; - arrayOfResults.forEach(function (result) { - mergedResults.items = mergedResults.items.concat(result.items); - mergedResults.total_items = result.total_items; - }); - - mergedResults.items = sortResults(mergedResults.items, claimList); - return mergedResults; - }; - - try { - const batchSize = pageSize || FETCH_BATCH_SIZE; - const batches = []; - - for (let i = 0; i < Math.ceil(totalItems / batchSize); i++) { - batches[i] = lbryProxy.claim_search({ - claim_ids: claim.value.claims, - page: i + 1, - page_size: batchSize, - no_totals: true - }); - } - const itemsInBatches = yield Promise.all(batches); - const result = mergeBatches(itemsInBatches, itemOrder); - - // $FlowFixMe - const itemsById = { claimId: claimId }; - if (result.items) { - itemsById.items = result.items; - } else { - itemsById.items = null; - } - return itemsById; - } catch (e) { - return { - claimId: claimId, - items: null - }; - } - }); - - return function fetchItemsForCollectionClaim(_x3, _x4) { - return _ref2.apply(this, arguments); - }; - })(); - - /* - 1) make sure all the collection claims are loaded into claims reducer, search/resolve if necessary. - 2) get the item claims for each - 3) format and make sure they're in the order as in the claim - 4) Build the collection objects and update collections reducer - 5) Update redux claims reducer - */ - let state = getState(); - const { collectionIds, pageSize } = resolveItemsOptions; - - dispatch({ - type: COLLECTION_ITEMS_RESOLVE_STARTED, - data: { ids: collectionIds } - }); - - if (resolveStartedCallback) resolveStartedCallback(); - - const collectionIdsToSearch = collectionIds.filter(function (claimId) { - return !state.claims.byId[claimId]; - }); - - if (collectionIdsToSearch.length) { - yield dispatch(doClaimSearch({ claim_ids: collectionIdsToSearch, page: 1, page_size: 9999 })); - } - - const stateAfterClaimSearch = getState(); - - function formatForClaimActions(resultClaimsByUri) { - const formattedClaims = {}; - Object.entries(resultClaimsByUri).forEach(([uri, uriResolveInfo]) => { - // Flow has terrible Object.entries support - // https://github.com/facebook/flow/issues/2221 - if (uriResolveInfo) { - let result = {}; - if (uriResolveInfo.value_type === 'channel') { - result.channel = uriResolveInfo; - // $FlowFixMe - result.claimsInChannel = uriResolveInfo.meta.claims_in_channel; - // ALSO SKIP COLLECTIONS - } else if (uriResolveInfo.value_type === 'collection') { - result.collection = uriResolveInfo; - } else { - result.stream = uriResolveInfo; - if (uriResolveInfo.signing_channel) { - result.channel = uriResolveInfo.signing_channel; - result.claimsInChannel = uriResolveInfo.signing_channel.meta && uriResolveInfo.signing_channel.meta.claims_in_channel || 0; - } - } - // $FlowFixMe - formattedClaims[uri] = result; - } - }); - return formattedClaims; - } - - const invalidCollectionIds = []; - const promisedCollectionItemFetches = []; - collectionIds.forEach(function (collectionId) { - const claim = makeSelectClaimForClaimId(collectionId)(stateAfterClaimSearch); - if (!claim) { - invalidCollectionIds.push(collectionId); - } else { - promisedCollectionItemFetches.push(fetchItemsForCollectionClaim(claim, pageSize)); - } - }); - - // $FlowFixMe - const collectionItemsById = yield Promise.all(promisedCollectionItemFetches); - - const newCollectionObjectsById = {}; - const resolvedItemsByUrl = {}; - collectionItemsById.forEach(function (entry) { - // $FlowFixMe - const collectionItems = entry.items; - const collectionId = entry.claimId; - if (collectionItems) { - const claim = makeSelectClaimForClaimId(collectionId)(stateAfterClaimSearch); - - const editedCollection = makeSelectEditedCollectionForId(collectionId)(stateAfterClaimSearch); - const { name, timestamp, value } = claim || {}; - const { title } = value; - const valueTypes = new Set(); - const streamTypes = new Set(); - - let newItems = []; - let isPlaylist; - - if (collectionItems) { - collectionItems.forEach(function (collectionItem) { - newItems.push(collectionItem.permanent_url); - valueTypes.add(collectionItem.value_type); - if (collectionItem.value.stream_type) { - streamTypes.add(collectionItem.value.stream_type); - } - resolvedItemsByUrl[collectionItem.canonical_url] = collectionItem; - }); - isPlaylist = valueTypes.size === 1 && valueTypes.has('stream') && (streamTypes.size === 1 && (streamTypes.has('audio') || streamTypes.has('video')) || streamTypes.size === 2 && streamTypes.has('audio') && streamTypes.has('video')); - } - - newCollectionObjectsById[collectionId] = { - items: newItems, - id: collectionId, - name: title || name, - itemCount: claim.value.claims.length, - type: isPlaylist ? 'playlist' : 'collection', - updatedAt: timestamp - }; - - if (editedCollection && timestamp > editedCollection['updatedAt']) { - dispatch({ - type: COLLECTION_DELETE, - data: { - id: collectionId, - collectionKey: 'edited' - } - }); - } - } else { - invalidCollectionIds.push(collectionId); - } - }); - const formattedClaimsByUri = formatForClaimActions(collectionItemsById); - - dispatch({ - type: RESOLVE_URIS_COMPLETED, - data: { resolveInfo: formattedClaimsByUri } - }); - - dispatch({ - type: COLLECTION_ITEMS_RESOLVE_COMPLETED, - data: { - resolvedCollections: newCollectionObjectsById, - failedCollectionIds: invalidCollectionIds - } - }); - }); - - return function (_x, _x2) { - return _ref.apply(this, arguments); - }; -})(); - -const doFetchItemsInCollection = (options, cb) => { - const { collectionId, pageSize } = options; - const newOptions = { - collectionIds: [collectionId] - }; - if (pageSize) newOptions.pageSize = pageSize; - return doFetchItemsInCollections(newOptions, cb); -}; - -const doCollectionEdit = (collectionId, params) => (() => { - var _ref3 = _asyncToGenerator$2(function* (dispatch, getState) { - const state = getState(); - const collection = makeSelectCollectionForId(collectionId)(state); - const editedCollection = makeSelectEditedCollectionForId(collectionId)(state); - const unpublishedCollection = makeSelectUnpublishedCollectionForId(collectionId)(state); - const publishedCollection = makeSelectPublishedCollectionForId(collectionId)(state); // needs to be published only - - const generateCollectionItemsFromSearchResult = function (results) { - return Object.values(results) - // $FlowFixMe - .reduce(function (acc, cur) { - let url; - if (cur.stream) { - url = cur.stream.permanent_url; - } else if (cur.channel) { - url = cur.channel.permanent_url; - } else if (cur.collection) { - url = cur.collection.permanent_url; - } else { - return acc; - } - acc.push(url); - return acc; - }, []); - }; - - if (!collection) { - return dispatch({ - type: COLLECTION_ERROR, - data: { - message: 'collection does not exist' - } - }); - } - - let currentItems = collection.items ? collection.items.concat() : []; - const { claims: passedClaims, order, claimIds, replace, remove, type } = params; - - const collectionType = type || collection.type; - let newItems = currentItems; - - if (passedClaims) { - if (remove) { - const passedUrls = passedClaims.map(function (claim) { - return claim.permanent_url; - }); - // $FlowFixMe // need this? - newItems = currentItems.filter(function (item) { - return !passedUrls.includes(item); - }); - } else { - passedClaims.forEach(function (claim) { - return newItems.push(claim.permanent_url); - }); - } - } - - if (claimIds) { - const batches = []; - if (claimIds.length > 50) { - for (let i = 0; i < Math.ceil(claimIds.length / 50); i++) { - batches[i] = claimIds.slice(i * 50, (i + 1) * 50); - } - } else { - batches[0] = claimIds; - } - const resultArray = yield Promise.all(batches.map(function (batch) { - let options = { claim_ids: batch, page: 1, page_size: 50 }; - return dispatch(doClaimSearch(options)); - })); - - const searchResults = Object.assign({}, ...resultArray); - - if (replace) { - newItems = generateCollectionItemsFromSearchResult(searchResults); - } else { - newItems = currentItems.concat(generateCollectionItemsFromSearchResult(searchResults)); - } - } - - if (order) { - const [movedItem] = currentItems.splice(order.from, 1); - currentItems.splice(order.to, 0, movedItem); - } - - // console.log('p&e', publishedCollection.items, newItems, publishedCollection.items.join(','), newItems.join(',')) - if (editedCollection) { - // delete edited if newItems are the same as publishedItems - if (publishedCollection.items.join(',') === newItems.join(',')) { - dispatch({ - type: COLLECTION_DELETE, - data: { - id: collectionId, - collectionKey: 'edited' - } - }); - } else { - dispatch({ - type: COLLECTION_EDIT, - data: { - id: collectionId, - collectionKey: 'edited', - collection: { - items: newItems, - id: collectionId, - name: params.name || collection.name, - updatedAt: getTimestamp(), - type: collectionType - } - } - }); - } - } else if (publishedCollection) { - dispatch({ - type: COLLECTION_EDIT, - data: { - id: collectionId, - collectionKey: 'edited', - collection: { - items: newItems, - id: collectionId, - name: params.name || collection.name, - updatedAt: getTimestamp(), - type: collectionType - } - } - }); - } else if (BUILTIN_LISTS.includes(collectionId)) { - dispatch({ - type: COLLECTION_EDIT, - data: { - id: collectionId, - collectionKey: 'builtin', - collection: { - items: newItems, - id: collectionId, - name: params.name || collection.name, - updatedAt: getTimestamp(), - type: collectionType - } - } - }); - } else if (unpublishedCollection) { - dispatch({ - type: COLLECTION_EDIT, - data: { - id: collectionId, - collectionKey: 'unpublished', - collection: { - items: newItems, - id: collectionId, - name: params.name || collection.name, - updatedAt: getTimestamp(), - type: collectionType - } - } - }); - } - return true; - }); - - return function (_x5, _x6) { - return _ref3.apply(this, arguments); - }; -})(); - -const selectState$3 = state => state.fileInfo || {}; - -const selectFileInfosByOutpoint = reselect.createSelector(selectState$3, state => state.byOutpoint || {}); - -const selectIsFetchingFileList = reselect.createSelector(selectState$3, state => state.isFetchingFileList); +const selectIsFetchingFileList = reselect.createSelector(selectState$2, state => state.isFetchingFileList); const selectIsFetchingFileListDownloadedOrPublished = reselect.createSelector(selectIsFetchingFileList, selectIsFetchingClaimListMine, (isFetchingFileList, isFetchingClaimListMine) => isFetchingFileList || isFetchingClaimListMine); @@ -5175,14 +4224,14 @@ const makeSelectFileInfoForUri = uri => reselect.createSelector(selectClaimsByUr return outpoint ? byOutpoint[outpoint] : undefined; }); -const selectDownloadingByOutpoint = reselect.createSelector(selectState$3, state => state.downloadingByOutpoint || {}); +const selectDownloadingByOutpoint = reselect.createSelector(selectState$2, state => state.downloadingByOutpoint || {}); const makeSelectDownloadingForUri = uri => reselect.createSelector(selectDownloadingByOutpoint, makeSelectFileInfoForUri(uri), (byOutpoint, fileInfo) => { if (!fileInfo) return false; return byOutpoint[fileInfo.outpoint]; }); -const selectUrisLoading = reselect.createSelector(selectState$3, state => state.fetching || {}); +const selectUrisLoading = reselect.createSelector(selectState$2, state => state.fetching || {}); const makeSelectLoadingForUri = uri => reselect.createSelector(selectUrisLoading, makeSelectClaimForUri(uri), (fetchingByOutpoint, claim) => { if (!claim) { @@ -5236,9 +4285,9 @@ const selectTotalDownloadProgress = reselect.createSelector(selectDownloadingFil return -1; }); -const selectFileListPublishedSort = reselect.createSelector(selectState$3, state => state.fileListPublishedSort); +const selectFileListPublishedSort = reselect.createSelector(selectState$2, state => state.fileListPublishedSort); -const selectFileListDownloadedSort = reselect.createSelector(selectState$3, state => state.fileListDownloadedSort); +const selectFileListDownloadedSort = reselect.createSelector(selectState$2, state => state.fileListDownloadedSort); const selectDownloadedUris = reselect.createSelector(selectFileInfosDownloaded, // We should use permament_url but it doesn't exist in file_list @@ -5491,10 +4540,10 @@ var _extends$6 = Object.assign || function (target) { for (var i = 1; i < argume function _objectWithoutProperties$2(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } -const selectState$4 = state => state.publish || {}; +const selectState$3 = state => state.publish || {}; // Is the current uri the same as the uri they clicked "edit" on -const selectIsStillEditing = reselect.createSelector(selectState$4, publishState => { +const selectIsStillEditing = reselect.createSelector(selectState$3, publishState => { const { editingURI, uri } = publishState; if (!editingURI || !uri) { @@ -5519,10 +4568,9 @@ const selectIsStillEditing = reselect.createSelector(selectState$4, publishState return currentName === editName; }); -const selectPublishFormValues = reselect.createSelector(selectState$4, state => state.settings, selectIsStillEditing, (publishState, settingsState, isStillEditing) => { - const { languages } = publishState, - formValues = _objectWithoutProperties$2(publishState, ['languages']); - const language = languages && languages.length && languages[0]; +const selectPublishFormValues = reselect.createSelector(selectState$3, state => state.settings, selectIsStillEditing, (publishState, settingsState, isStillEditing) => { + const { pendingPublish, language } = publishState, + formValues = _objectWithoutProperties$2(publishState, ['pendingPublish', 'language']); const { clientSettings } = settingsState; const { language: languageSet } = clientSettings; @@ -5536,7 +4584,7 @@ const selectPublishFormValues = reselect.createSelector(selectState$4, state => return _extends$6({}, formValues, { language: actualLanguage }); }); -const makeSelectPublishFormValue = item => reselect.createSelector(selectState$4, state => state[item]); +const makeSelectPublishFormValue = item => reselect.createSelector(selectState$3, state => state[item]); const selectMyClaimForUri = reselect.createSelector(selectPublishFormValues, selectIsStillEditing, selectClaimsById, selectMyClaimsWithoutChannels, ({ editingURI, uri }, isStillEditing, claimsById, myClaims) => { const { channelName: contentName, streamName: claimName } = parseURI(uri); @@ -5549,7 +4597,7 @@ const selectMyClaimForUri = reselect.createSelector(selectPublishFormValues, sel return isStillEditing ? claimsById[editClaimId] : myClaims.find(claim => !contentName ? claim.name === claimName : claim.name === contentName || claim.name === claimName); }); -const selectIsResolvingPublishUris = reselect.createSelector(selectState$4, selectResolvingUris, ({ uri, name }, resolvingUris) => { +const selectIsResolvingPublishUris = reselect.createSelector(selectState$3, selectResolvingUris, ({ uri, name }, resolvingUris) => { if (uri) { const isResolvingUri = resolvingUris.includes(uri); const { isChannel } = parseURI(uri); @@ -5566,7 +4614,7 @@ const selectIsResolvingPublishUris = reselect.createSelector(selectState$4, sele return false; }); -const selectTakeOverAmount = reselect.createSelector(selectState$4, selectMyClaimForUri, selectClaimsByUri, ({ name }, myClaimForUri, claimsByUri) => { +const selectTakeOverAmount = reselect.createSelector(selectState$3, selectMyClaimForUri, selectClaimsByUri, ({ name }, myClaimForUri, claimsByUri) => { if (!name) { return null; } @@ -5591,14 +4639,13 @@ const selectTakeOverAmount = reselect.createSelector(selectState$4, selectMyClai var _extends$7 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; -function _asyncToGenerator$3(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } +function _asyncToGenerator$2(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } const doResetThumbnailStatus = () => dispatch => { dispatch({ type: UPDATE_PUBLISH_FORM, data: { - thumbnailPath: '', - thumbnailError: undefined + thumbnailPath: '' } }); @@ -5633,7 +4680,7 @@ const doUpdatePublishForm = publishFormValue => dispatch => dispatch({ data: _extends$7({}, publishFormValue) }); -const doUploadThumbnail = (filePath, thumbnailBlob, fsAdapter, fs, path, cb) => dispatch => { +const doUploadThumbnail = (filePath, thumbnailBlob, fsAdapter, fs, path) => dispatch => { const downMessage = __('Thumbnail upload service may be down, try again later.'); let thumbnail, fileExt, fileName, fileType; @@ -5655,29 +4702,18 @@ const doUploadThumbnail = (filePath, thumbnailBlob, fsAdapter, fs, path, cb) => }, doError(error))); }; - dispatch({ - type: UPDATE_PUBLISH_FORM, - data: { - thumbnailError: undefined - } - }); - const doUpload = data => { return fetch(SPEECH_PUBLISH, { method: 'POST', body: data }).then(res => res.text()).then(text => text.length ? JSON.parse(text) : {}).then(json => { - if (!json.success) return uploadError(json.message || downMessage); - if (cb) { - cb(json.data.serveUrl); - } - return dispatch({ + return json.success ? dispatch({ type: UPDATE_PUBLISH_FORM, data: { uploadThumbnailStatus: COMPLETE, thumbnail: json.data.serveUrl } - }); + }) : uploadError(json.message || downMessage); }).catch(err => { let message = err.message; @@ -5761,8 +4797,7 @@ const doPrepareEdit = (claim, uri, fileInfo, fs) => dispatch => { description, fee, languages, - releaseTime: release_time, - releaseTimeEdited: undefined, + release_time: release_time ? Number(release_time) * 1000 : undefined, thumbnail: thumbnail ? thumbnail.url : null, title, uri, @@ -5813,7 +4848,7 @@ const doPublish = (success, fail, preview) => (dispatch, getState) => { filePath, description, language, - releaseTimeEdited, + releaseTime, license, licenseUrl, useLBRYUploader, @@ -5885,8 +4920,8 @@ const doPublish = (success, fail, preview) => (dispatch, getState) => { } // Set release time to curret date. On edits, keep original release/transaction time as release_time - if (releaseTimeEdited) { - publishPayload.release_time = releaseTimeEdited; + if (releaseTime) { + publishPayload.release_time = Number(Math.round(new Date(releaseTime) / 1000)); } else if (myClaimForUriEditing && myClaimForUriEditing.value.release_time) { publishPayload.release_time = Number(myClaimForUri.value.release_time); } else if (myClaimForUriEditing && myClaimForUriEditing.timestamp) { @@ -5949,7 +4984,7 @@ const doCheckReflectingFiles = () => (dispatch, getState) => { let reflectorCheckInterval; const checkFileList = (() => { - var _ref = _asyncToGenerator$3(function* () { + var _ref = _asyncToGenerator$2(function* () { const state = getState(); const reflectingById = selectReflectingById(state); const ids = Object.keys(reflectingById); @@ -6082,7 +5117,6 @@ const defaultState = { fetchingChannelClaims: {}, resolvingUris: [], myChannelClaims: undefined, - myCollectionClaims: [], myClaims: undefined, myPurchases: undefined, myPurchasesPageNumber: undefined, @@ -6091,22 +5125,17 @@ const defaultState = { fetchingMyPurchases: false, fetchingMyPurchasesError: undefined, fetchingMyChannels: false, - fetchingMyCollections: false, abandoningById: {}, - pendingById: {}, + pendingIds: [], reflectingById: {}, claimSearchError: false, claimSearchByQuery: {}, claimSearchByQueryLastPageReached: {}, fetchingClaimSearchByQuery: {}, updateChannelError: '', - updateCollectionError: '', updatingChannel: false, creatingChannel: false, createChannelError: undefined, - updatingCollection: false, - creatingCollection: false, - createCollectionError: undefined, pendingChannelImport: false, repostLoading: false, repostError: undefined, @@ -6122,22 +5151,24 @@ const defaultState = { }; function handleClaimAction(state, action) { - const { resolveInfo } = action.data; + const { + resolveInfo + } = action.data; const byUri = Object.assign({}, state.claimsByUri); const byId = Object.assign({}, state.byId); const channelClaimCounts = Object.assign({}, state.channelClaimCounts); - const pendingById = state.pendingById; + const pendingIds = state.pendingIds; let newResolvingUrls = new Set(state.resolvingUris); let myClaimIds = new Set(state.myClaims); Object.entries(resolveInfo).forEach(([url, resolveResponse]) => { // $FlowFixMe - const { claimsInChannel, stream, channel: channelFromResolve, collection } = resolveResponse; + const { claimsInChannel, stream, channel: channelFromResolve } = resolveResponse; const channel = channelFromResolve || stream && stream.signing_channel; if (stream) { - if (pendingById[stream.claim_id]) { + if (pendingIds.includes(stream.claim_id)) { byId[stream.claim_id] = mergeClaims(stream, byId[stream.claim_id]); } else { byId[stream.claim_id] = stream; @@ -6167,37 +5198,20 @@ function handleClaimAction(state, action) { channelClaimCounts[channel.canonical_url] = claimsInChannel; } - if (pendingById[channel.claim_id]) { + if (pendingIds.includes(channel.claim_id)) { byId[channel.claim_id] = mergeClaims(channel, byId[channel.claim_id]); } else { byId[channel.claim_id] = channel; } - + // Also add the permanent_url here until lighthouse returns canonical_url for search results byUri[channel.permanent_url] = channel.claim_id; byUri[channel.canonical_url] = channel.claim_id; newResolvingUrls.delete(channel.canonical_url); newResolvingUrls.delete(channel.permanent_url); } - if (collection) { - if (pendingById[collection.claim_id]) { - byId[collection.claim_id] = mergeClaims(collection, byId[collection.claim_id]); - } else { - byId[collection.claim_id] = collection; - } - byUri[url] = collection.claim_id; - byUri[collection.canonical_url] = collection.claim_id; - byUri[collection.permanent_url] = collection.claim_id; - newResolvingUrls.delete(collection.canonical_url); - newResolvingUrls.delete(collection.permanent_url); - - if (collection.is_my_output) { - myClaimIds.add(collection.claim_id); - } - } - newResolvingUrls.delete(url); - if (!stream && !channel && !collection && !pendingById[byUri[url]]) { + if (!stream && !channel && !pendingIds.includes(byUri[url])) { byUri[url] = null; } }); @@ -6237,33 +5251,34 @@ reducers[FETCH_CLAIM_LIST_MINE_STARTED] = state => Object.assign({}, state, { }); reducers[FETCH_CLAIM_LIST_MINE_COMPLETED] = (state, action) => { - const { result } = action.data; + const { result, resolve } = action.data; const claims = result.items; const page = result.page; const totalItems = result.total_items; const byId = Object.assign({}, state.byId); const byUri = Object.assign({}, state.claimsByUri); - const pendingById = Object.assign({}, state.pendingById); + const pendingIds = state.pendingIds || []; let myClaimIds = new Set(state.myClaims); let urlsForCurrentPage = []; + const pendingIdSet = new Set(pendingIds); + claims.forEach(claim => { - const { permanent_url: permanentUri, claim_id: claimId, canonical_url: canonicalUri } = claim; + const { permanent_url: permanentUri, claim_id: claimId } = claim; if (claim.type && claim.type.match(/claim|update/)) { urlsForCurrentPage.push(permanentUri); if (claim.confirmations < 1) { - pendingById[claimId] = claim; - if (byId[claimId]) { - byId[claimId] = mergeClaims(claim, byId[claimId]); - } else { - byId[claimId] = claim; - } + pendingIdSet.add(claimId); + } else if (!resolve && pendingIdSet.has(claimId) && claim.confirmations > 0) { + pendingIdSet.delete(claimId); + } + if (pendingIds.includes(claimId)) { + byId[claimId] = mergeClaims(claim, byId[claimId]); } else { byId[claimId] = claim; } byUri[permanentUri] = claimId; - byUri[canonicalUri] = claimId; myClaimIds.add(claimId); } }); @@ -6272,7 +5287,7 @@ reducers[FETCH_CLAIM_LIST_MINE_COMPLETED] = (state, action) => { isFetchingClaimListMine: false, myClaims: Array.from(myClaimIds), byId, - pendingById, + pendingIds: Array.from(pendingIdSet), claimsByUri: byUri, myClaimsPageResults: urlsForCurrentPage, myClaimsPageNumber: page, @@ -6284,8 +5299,9 @@ reducers[FETCH_CHANNEL_LIST_STARTED] = state => Object.assign({}, state, { fetch reducers[FETCH_CHANNEL_LIST_COMPLETED] = (state, action) => { const { claims } = action.data; + const myClaims = state.myClaims || []; let myClaimIds = new Set(state.myClaims); - const pendingById = Object.assign({}, state.pendingById); + const pendingIds = state.pendingIds || []; let myChannelClaims; const byId = Object.assign({}, state.byId); const byUri = Object.assign({}, state.claimsByUri); @@ -6298,12 +5314,7 @@ reducers[FETCH_CHANNEL_LIST_COMPLETED] = (state, action) => { myChannelClaims = new Set(state.myChannelClaims); claims.forEach(claim => { const { claims_in_channel: claimsInChannel } = claim.meta; - const { - canonical_url: canonicalUrl, - permanent_url: permanentUrl, - claim_id: claimId, - confirmations - } = claim; + const { canonical_url: canonicalUrl, permanent_url: permanentUrl, claim_id: claimId } = claim; byUri[canonicalUrl] = claimId; byUri[permanentUrl] = claimId; @@ -6312,14 +5323,7 @@ reducers[FETCH_CHANNEL_LIST_COMPLETED] = (state, action) => { // $FlowFixMe myChannelClaims.add(claimId); - if (confirmations < 1) { - pendingById[claimId] = claim; - if (byId[claimId]) { - byId[claimId] = mergeClaims(claim, byId[claimId]); - } else { - byId[claimId] = claim; - } - } else { + if (!pendingIds.some(c => c === claimId)) { byId[claimId] = claim; } myClaimIds.add(claimId); @@ -6328,7 +5332,6 @@ reducers[FETCH_CHANNEL_LIST_COMPLETED] = (state, action) => { return Object.assign({}, state, { byId, - pendingById, claimsByUri: byUri, channelClaimCounts, fetchingMyChannels: false, @@ -6343,63 +5346,6 @@ reducers[FETCH_CHANNEL_LIST_FAILED] = (state, action) => { }); }; -reducers[FETCH_COLLECTION_LIST_STARTED] = state => _extends$9({}, state, { - fetchingMyCollections: true -}); - -reducers[FETCH_COLLECTION_LIST_COMPLETED] = (state, action) => { - const { claims } = action.data; - const myClaims = state.myClaims || []; - let myClaimIds = new Set(myClaims); - const pendingById = Object.assign({}, state.pendingById); - let myCollectionClaimsSet = new Set([]); - const byId = Object.assign({}, state.byId); - const byUri = Object.assign({}, state.claimsByUri); - - if (claims.length) { - myCollectionClaimsSet = new Set(state.myCollectionClaims); - claims.forEach(claim => { - const { - canonical_url: canonicalUrl, - permanent_url: permanentUrl, - claim_id: claimId, - confirmations - } = claim; - - byUri[canonicalUrl] = claimId; - byUri[permanentUrl] = claimId; - - // $FlowFixMe - myCollectionClaimsSet.add(claimId); - // we don't want to overwrite a pending result with a resolve - if (confirmations < 1) { - pendingById[claimId] = claim; - if (byId[claimId]) { - byId[claimId] = mergeClaims(claim, byId[claimId]); - } else { - byId[claimId] = claim; - } - } else { - byId[claimId] = claim; - } - myClaimIds.add(claimId); - }); - } - - return _extends$9({}, state, { - byId, - pendingById, - claimsByUri: byUri, - fetchingMyCollections: false, - myCollectionClaims: Array.from(myCollectionClaimsSet), - myClaims: myClaimIds ? Array.from(myClaimIds) : null - }); -}; - -reducers[FETCH_COLLECTION_LIST_FAILED] = state => { - return _extends$9({}, state, { fetchingMyCollections: false }); -}; - reducers[FETCH_CHANNEL_CLAIMS_STARTED] = (state, action) => { const { uri, page } = action.data; const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims); @@ -6474,8 +5420,9 @@ reducers[ABANDON_CLAIM_STARTED] = (state, action) => { reducers[UPDATE_PENDING_CLAIMS] = (state, action) => { const { claims: pendingClaims } = action.data; const byId = Object.assign({}, state.byId); - const pendingById = Object.assign({}, state.pendingById); const byUri = Object.assign({}, state.claimsByUri); + const pendingIds = state.pendingIds; + const pendingIdSet = new Set(pendingIds); let myClaimIds = new Set(state.myClaims); const myChannelClaims = new Set(state.myChannelClaims); @@ -6483,7 +5430,7 @@ reducers[UPDATE_PENDING_CLAIMS] = (state, action) => { pendingClaims.forEach(claim => { let newClaim; const { permanent_url: uri, claim_id: claimId, type, value_type: valueType } = claim; - pendingById[claimId] = claim; // make sure we don't need to merge? + pendingIdSet.add(claimId); const oldClaim = byId[claimId]; if (oldClaim && oldClaim.canonical_url) { newClaim = mergeClaims(oldClaim, claim); @@ -6503,22 +5450,21 @@ reducers[UPDATE_PENDING_CLAIMS] = (state, action) => { return Object.assign({}, state, { myClaims: Array.from(myClaimIds), byId, - pendingById, myChannelClaims: Array.from(myChannelClaims), - claimsByUri: byUri + claimsByUri: byUri, + pendingIds: Array.from(pendingIdSet) }); }; reducers[UPDATE_CONFIRMED_CLAIMS] = (state, action) => { - const { - claims: confirmedClaims, - pending: pendingClaims - } = action.data; + const { claims: confirmedClaims } = action.data; const byId = Object.assign({}, state.byId); const byUri = Object.assign({}, state.claimsByUri); - // + const pendingIds = state.pendingIds; + const pendingIdSet = new Set(pendingIds); + confirmedClaims.forEach(claim => { - const { claim_id: claimId, type } = claim; + const { permanent_url: permanentUri, claim_id: claimId, type } = claim; let newClaim = claim; const oldClaim = byId[claimId]; if (oldClaim && oldClaim.canonical_url) { @@ -6526,10 +5472,11 @@ reducers[UPDATE_CONFIRMED_CLAIMS] = (state, action) => { } if (type && type.match(/claim|update|channel/)) { byId[claimId] = newClaim; + pendingIdSet.delete(claimId); } }); return Object.assign({}, state, { - pendingById: pendingClaims, + pendingIds: Array.from(pendingIdSet), byId, claimsByUri: byUri }); @@ -6541,7 +5488,6 @@ reducers[ABANDON_CLAIM_SUCCEEDED] = (state, action) => { const newMyClaims = state.myClaims ? state.myClaims.slice() : []; const newMyChannelClaims = state.myChannelClaims ? state.myChannelClaims.slice() : []; const claimsByUri = Object.assign({}, state.claimsByUri); - const newMyCollectionClaims = state.myCollectionClaims ? state.myCollectionClaims.slice() : []; Object.keys(claimsByUri).forEach(uri => { if (claimsByUri[uri] === claimId) { @@ -6550,14 +5496,12 @@ reducers[ABANDON_CLAIM_SUCCEEDED] = (state, action) => { }); const myClaims = newMyClaims.filter(i => i !== claimId); const myChannelClaims = newMyChannelClaims.filter(i => i !== claimId); - const myCollectionClaims = newMyCollectionClaims.filter(i => i !== claimId); delete byId[claimId]; return Object.assign({}, state, { myClaims, myChannelClaims, - myCollectionClaims, byId, claimsByUri }); @@ -6607,59 +5551,6 @@ reducers[UPDATE_CHANNEL_FAILED] = (state, action) => { }); }; -reducers[CLEAR_COLLECTION_ERRORS] = state => _extends$9({}, state, { - createCollectionError: null, - updateCollectionError: null -}); - -reducers[COLLECTION_PUBLISH_STARTED] = state => _extends$9({}, state, { - creatingCollection: true, - createCollectionError: null -}); - -reducers[COLLECTION_PUBLISH_COMPLETED] = (state, action) => { - const myCollections = state.myCollectionClaims || []; - const myClaims = state.myClaims || []; - const { claimId } = action.data; - let myClaimIds = new Set(myClaims); - let myCollectionClaimsSet = new Set(myCollections); - myClaimIds.add(claimId); - myCollectionClaimsSet.add(claimId); - return Object.assign({}, state, { - creatingCollection: false, - myClaims: Array.from(myClaimIds), - myCollectionClaims: Array.from(myCollectionClaimsSet) - }); -}; - -reducers[COLLECTION_PUBLISH_FAILED] = (state, action) => { - return Object.assign({}, state, { - creatingCollection: false, - createCollectionError: action.data.error - }); -}; - -reducers[COLLECTION_PUBLISH_UPDATE_STARTED] = (state, action) => { - return Object.assign({}, state, { - updateCollectionError: '', - updatingCollection: true - }); -}; - -reducers[COLLECTION_PUBLISH_UPDATE_COMPLETED] = (state, action) => { - return Object.assign({}, state, { - updateCollectionError: '', - updatingCollection: false - }); -}; - -reducers[COLLECTION_PUBLISH_UPDATE_FAILED] = (state, action) => { - return Object.assign({}, state, { - updateCollectionError: action.data.error, - updatingCollection: false - }); -}; - reducers[IMPORT_CHANNEL_STARTED] = state => Object.assign({}, state, { pendingChannelImports: true }); reducers[IMPORT_CHANNEL_COMPLETED] = state => Object.assign({}, state, { pendingChannelImports: false }); @@ -7176,11 +6067,9 @@ const defaultState$4 = { thumbnail_url: '', thumbnailPath: '', uploadThumbnailStatus: API_DOWN, - thumbnailError: undefined, description: '', language: '', releaseTime: undefined, - releaseTimeEdited: undefined, nsfw: false, channel: CHANNEL_ANONYMOUS, channelId: '', @@ -7687,229 +6576,11 @@ const walletReducer = handleActions({ }) }, defaultState$5); -var _extends$e = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -const getTimestamp$1 = () => { - return Math.floor(Date.now() / 1000); -}; - -const defaultState$6 = { - builtin: { - watchlater: { - items: [], - id: WATCH_LATER_ID, - name: 'Watch Later', - updatedAt: getTimestamp$1(), - type: COL_TYPE_PLAYLIST - }, - favorites: { - items: [], - id: FAVORITES_ID, - name: 'Favorites', - type: COL_TYPE_PLAYLIST, - updatedAt: getTimestamp$1() - } - }, - resolved: {}, - unpublished: {}, // sync - edited: {}, - pending: {}, - saved: [], - isResolvingCollectionById: {}, - error: null -}; - -const collectionsReducer = handleActions({ - [COLLECTION_NEW]: (state, action) => { - const { entry: params } = action.data; // { id:, items: Array<string>} - // entry - const newListTemplate = { - id: params.id, - name: params.name, - items: [], - updatedAt: getTimestamp$1(), - type: params.type - }; - - const newList = Object.assign({}, newListTemplate, _extends$e({}, params)); - const { unpublished: lists } = state; - const newLists = Object.assign({}, lists, { [params.id]: newList }); - - return _extends$e({}, state, { - unpublished: newLists - }); - }, - - [COLLECTION_DELETE]: (state, action) => { - const { id, collectionKey } = action.data; - const { edited: editList, unpublished: unpublishedList, pending: pendingList } = state; - const newEditList = Object.assign({}, editList); - const newUnpublishedList = Object.assign({}, unpublishedList); - - const newPendingList = Object.assign({}, pendingList); - - if (collectionKey && state[collectionKey] && state[collectionKey][id]) { - const newList = Object.assign({}, state[collectionKey]); - delete newList[id]; - return _extends$e({}, state, { - [collectionKey]: newList - }); - } else { - if (newEditList[id]) { - delete newEditList[id]; - } else if (newUnpublishedList[id]) { - delete newUnpublishedList[id]; - } else if (newPendingList[id]) { - delete newPendingList[id]; - } - } - return _extends$e({}, state, { - edited: newEditList, - unpublished: newUnpublishedList, - pending: newPendingList - }); - }, - - [COLLECTION_PENDING]: (state, action) => { - const { localId, claimId } = action.data; - const { - resolved: resolvedList, - edited: editList, - unpublished: unpublishedList, - pending: pendingList - } = state; - - const newEditList = Object.assign({}, editList); - const newResolvedList = Object.assign({}, resolvedList); - const newUnpublishedList = Object.assign({}, unpublishedList); - const newPendingList = Object.assign({}, pendingList); - - if (localId) { - // new publish - newPendingList[claimId] = Object.assign({}, newUnpublishedList[localId] || {}); - delete newUnpublishedList[localId]; - } else { - // edit update - newPendingList[claimId] = Object.assign({}, newEditList[claimId] || newResolvedList[claimId]); - delete newEditList[claimId]; - } - - return _extends$e({}, state, { - edited: newEditList, - unpublished: newUnpublishedList, - pending: newPendingList - }); - }, - - [COLLECTION_EDIT]: (state, action) => { - const { id, collectionKey, collection } = action.data; - - if (BUILTIN_LISTS.includes(id)) { - const { builtin: lists } = state; - return _extends$e({}, state, { - [collectionKey]: _extends$e({}, lists, { [id]: collection }) - }); - } - - if (collectionKey === 'edited') { - const { edited: lists } = state; - return _extends$e({}, state, { - edited: _extends$e({}, lists, { [id]: collection }) - }); - } - const { unpublished: lists } = state; - return _extends$e({}, state, { - unpublished: _extends$e({}, lists, { [id]: collection }) - }); - }, - - [COLLECTION_ERROR]: (state, action) => { - return Object.assign({}, state, { - error: action.data.message - }); - }, - - [COLLECTION_ITEMS_RESOLVE_STARTED]: (state, action) => { - const { ids } = action.data; - const { isResolvingCollectionById } = state; - const newResolving = Object.assign({}, isResolvingCollectionById); - ids.forEach(id => { - newResolving[id] = true; - }); - return Object.assign({}, state, _extends$e({}, state, { - error: '', - isResolvingCollectionById: newResolving - })); - }, - [USER_STATE_POPULATE]: (state, action) => { - const { - builtinCollections, - savedCollections, - unpublishedCollections, - editedCollections - } = action.data; - return _extends$e({}, state, { - edited: editedCollections || state.edited, - unpublished: unpublishedCollections || state.unpublished, - builtin: builtinCollections || state.builtin, - saved: savedCollections || state.saved - }); - }, - [COLLECTION_ITEMS_RESOLVE_COMPLETED]: (state, action) => { - const { resolvedCollections, failedCollectionIds } = action.data; - const { pending, edited, isResolvingCollectionById, resolved } = state; - const newPending = Object.assign({}, pending); - const newEdited = Object.assign({}, edited); - const newResolved = Object.assign({}, resolved, resolvedCollections); - - const resolvedIds = Object.keys(resolvedCollections); - const newResolving = Object.assign({}, isResolvingCollectionById); - if (resolvedCollections && Object.keys(resolvedCollections).length) { - resolvedIds.forEach(resolvedId => { - if (newEdited[resolvedId]) { - if (newEdited[resolvedId]['updatedAt'] < resolvedCollections[resolvedId]['updatedAt']) { - delete newEdited[resolvedId]; - } - } - delete newResolving[resolvedId]; - if (newPending[resolvedId]) { - delete newPending[resolvedId]; - } - }); - } - - if (failedCollectionIds && Object.keys(failedCollectionIds).length) { - failedCollectionIds.forEach(failedId => { - delete newResolving[failedId]; - }); - } - - return Object.assign({}, state, _extends$e({}, state, { - pending: newPending, - resolved: newResolved, - edited: newEdited, - isResolvingCollectionById: newResolving - })); - }, - [COLLECTION_ITEMS_RESOLVE_FAILED]: (state, action) => { - const { ids } = action.data; - const { isResolvingCollectionById } = state; - const newResolving = Object.assign({}, isResolvingCollectionById); - ids.forEach(id => { - delete newResolving[id]; - }); - return Object.assign({}, state, _extends$e({}, state, { - isResolvingCollectionById: newResolving, - error: action.data.message - })); - } -}, defaultState$6); - // -const selectState$5 = state => state.content || {}; +const selectState$4 = state => state.content || {}; -const makeSelectContentPositionForUri = uri => reselect.createSelector(selectState$5, makeSelectClaimForUri(uri), (state, claim) => { +const makeSelectContentPositionForUri = uri => reselect.createSelector(selectState$4, makeSelectClaimForUri(uri), (state, claim) => { if (!claim) { return null; } @@ -7918,14 +6589,14 @@ const makeSelectContentPositionForUri = uri => reselect.createSelector(selectSta return state.positions[id] ? state.positions[id][outpoint] : null; }); -var _extends$f = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; +var _extends$e = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; -const selectState$6 = state => state.notifications || {}; +const selectState$5 = state => state.notifications || {}; -const selectToast = reselect.createSelector(selectState$6, state => { +const selectToast = reselect.createSelector(selectState$5, state => { if (state.toasts.length) { const { id, params } = state.toasts[0]; - return _extends$f({ + return _extends$e({ id }, params); } @@ -7933,7 +6604,7 @@ const selectToast = reselect.createSelector(selectState$6, state => { return null; }); -const selectError = reselect.createSelector(selectState$6, state => { +const selectError = reselect.createSelector(selectState$5, state => { if (state.errors.length) { const { error } = state.errors[0]; return { @@ -7947,7 +6618,6 @@ const selectError = reselect.createSelector(selectState$6, state => { exports.ABANDON_STATES = abandon_states; exports.ACTIONS = action_types; exports.CLAIM_VALUES = claim; -exports.COLLECTIONS_CONSTS = collections; exports.DAEMON_SETTINGS = daemon_settings; exports.DEFAULT_FOLLOWED_TAGS = DEFAULT_FOLLOWED_TAGS; exports.DEFAULT_KNOWN_TAGS = DEFAULT_KNOWN_TAGS; @@ -7969,7 +6639,6 @@ exports.batchActions = batchActions; exports.buildSharedStateMiddleware = buildSharedStateMiddleware; exports.buildURI = buildURI; exports.claimsReducer = claimsReducer; -exports.collectionsReducer = collectionsReducer; exports.contentReducer = contentReducer; exports.convertToShareLink = convertToShareLink; exports.createNormalizedClaimSearchKey = createNormalizedClaimSearchKey; @@ -7987,10 +6656,6 @@ exports.doClearPublish = doClearPublish; exports.doClearPurchasedUriSuccess = doClearPurchasedUriSuccess; exports.doClearRepostError = doClearRepostError; exports.doClearSupport = doClearSupport; -exports.doCollectionDelete = doCollectionDelete; -exports.doCollectionEdit = doCollectionEdit; -exports.doCollectionPublish = doCollectionPublish; -exports.doCollectionPublishUpdate = doCollectionPublishUpdate; exports.doCreateChannel = doCreateChannel; exports.doDismissError = doDismissError; exports.doDismissToast = doDismissToast; @@ -7998,11 +6663,8 @@ exports.doError = doError; exports.doFetchChannelListMine = doFetchChannelListMine; exports.doFetchClaimListMine = doFetchClaimListMine; exports.doFetchClaimsByChannel = doFetchClaimsByChannel; -exports.doFetchCollectionListMine = doFetchCollectionListMine; exports.doFetchFileInfo = doFetchFileInfo; exports.doFetchFileInfos = doFetchFileInfos; -exports.doFetchItemsInCollection = doFetchItemsInCollection; -exports.doFetchItemsInCollections = doFetchItemsInCollections; exports.doFetchTransactions = doFetchTransactions; exports.doFetchTxoPage = doFetchTxoPage; exports.doFetchUtxoCounts = doFetchUtxoCounts; @@ -8010,7 +6672,6 @@ exports.doFileGet = doFileGet; exports.doFileList = doFileList; exports.doGetNewAddress = doGetNewAddress; exports.doImportChannel = doImportChannel; -exports.doLocalCollectionCreate = doLocalCollectionCreate; exports.doPopulateSharedUserState = doPopulateSharedUserState; exports.doPreferenceGet = doPreferenceGet; exports.doPreferenceSet = doPreferenceSet; @@ -8049,7 +6710,6 @@ exports.formatFullPrice = formatFullPrice; exports.isClaimNsfw = isClaimNsfw; exports.isNameValid = isNameValid; exports.isURIClaimable = isURIClaimable; -exports.isURIEqual = isURIEqual; exports.isURIValid = isURIValid; exports.makeSelectAbandoningClaimById = makeSelectAbandoningClaimById; exports.makeSelectAmountForUri = makeSelectAmountForUri; @@ -8059,36 +6719,26 @@ exports.makeSelectChannelPermUrlForClaimUri = makeSelectChannelPermUrlForClaimUr exports.makeSelectClaimForClaimId = makeSelectClaimForClaimId; exports.makeSelectClaimForUri = makeSelectClaimForUri; exports.makeSelectClaimHasSource = makeSelectClaimHasSource; -exports.makeSelectClaimIdForUri = makeSelectClaimIdForUri; -exports.makeSelectClaimIdIsPending = makeSelectClaimIdIsPending; -exports.makeSelectClaimIdsForCollectionId = makeSelectClaimIdsForCollectionId; exports.makeSelectClaimIsMine = makeSelectClaimIsMine; exports.makeSelectClaimIsNsfw = makeSelectClaimIsNsfw; exports.makeSelectClaimIsPending = makeSelectClaimIsPending; exports.makeSelectClaimIsStreamPlaceholder = makeSelectClaimIsStreamPlaceholder; -exports.makeSelectClaimUrlInCollection = makeSelectClaimUrlInCollection; exports.makeSelectClaimWasPurchased = makeSelectClaimWasPurchased; +exports.makeSelectClaimsInChannelForCurrentPageState = makeSelectClaimsInChannelForCurrentPageState; exports.makeSelectClaimsInChannelForPage = makeSelectClaimsInChannelForPage; -exports.makeSelectCollectionForId = makeSelectCollectionForId; -exports.makeSelectCollectionForIdHasClaimUrl = makeSelectCollectionForIdHasClaimUrl; -exports.makeSelectCollectionIsMine = makeSelectCollectionIsMine; exports.makeSelectContentPositionForUri = makeSelectContentPositionForUri; exports.makeSelectContentTypeForUri = makeSelectContentTypeForUri; -exports.makeSelectCountForCollectionId = makeSelectCountForCollectionId; exports.makeSelectCoverForUri = makeSelectCoverForUri; exports.makeSelectDateForUri = makeSelectDateForUri; exports.makeSelectDownloadPathForUri = makeSelectDownloadPathForUri; exports.makeSelectDownloadingForUri = makeSelectDownloadingForUri; -exports.makeSelectEditedCollectionForId = makeSelectEditedCollectionForId; exports.makeSelectEffectiveAmountForUri = makeSelectEffectiveAmountForUri; exports.makeSelectFetchingChannelClaims = makeSelectFetchingChannelClaims; exports.makeSelectFileInfoForUri = makeSelectFileInfoForUri; exports.makeSelectFileNameForUri = makeSelectFileNameForUri; exports.makeSelectFilePartlyDownloaded = makeSelectFilePartlyDownloaded; exports.makeSelectFilteredTransactionsForPage = makeSelectFilteredTransactionsForPage; -exports.makeSelectIndexForUrlInCollection = makeSelectIndexForUrlInCollection; exports.makeSelectIsAbandoningClaimForUri = makeSelectIsAbandoningClaimForUri; -exports.makeSelectIsResolvingCollectionForId = makeSelectIsResolvingCollectionForId; exports.makeSelectIsUriResolving = makeSelectIsUriResolving; exports.makeSelectLatestTransactions = makeSelectLatestTransactions; exports.makeSelectLoadingForUri = makeSelectLoadingForUri; @@ -8096,20 +6746,15 @@ exports.makeSelectMediaTypeForUri = makeSelectMediaTypeForUri; exports.makeSelectMetadataForUri = makeSelectMetadataForUri; exports.makeSelectMetadataItemForUri = makeSelectMetadataItemForUri; exports.makeSelectMyChannelPermUrlForName = makeSelectMyChannelPermUrlForName; -exports.makeSelectMyPublishedCollectionForId = makeSelectMyPublishedCollectionForId; exports.makeSelectMyPurchasesForPage = makeSelectMyPurchasesForPage; exports.makeSelectMyStreamUrlsForPage = makeSelectMyStreamUrlsForPage; -exports.makeSelectNameForCollectionId = makeSelectNameForCollectionId; -exports.makeSelectNextUrlForCollectionAndUrl = makeSelectNextUrlForCollectionAndUrl; +exports.makeSelectNsfwCountForChannel = makeSelectNsfwCountForChannel; exports.makeSelectNsfwCountFromUris = makeSelectNsfwCountFromUris; exports.makeSelectOmittedCountForChannel = makeSelectOmittedCountForChannel; exports.makeSelectPendingAmountByUri = makeSelectPendingAmountByUri; exports.makeSelectPendingClaimForUri = makeSelectPendingClaimForUri; -exports.makeSelectPendingCollectionForId = makeSelectPendingCollectionForId; exports.makeSelectPermanentUrlForUri = makeSelectPermanentUrlForUri; -exports.makeSelectPreviousUrlForCollectionAndUrl = makeSelectPreviousUrlForCollectionAndUrl; exports.makeSelectPublishFormValue = makeSelectPublishFormValue; -exports.makeSelectPublishedCollectionForId = makeSelectPublishedCollectionForId; exports.makeSelectReflectingClaimForUri = makeSelectReflectingClaimForUri; exports.makeSelectSearchDownloadUrlsCount = makeSelectSearchDownloadUrlsCount; exports.makeSelectSearchDownloadUrlsForPage = makeSelectSearchDownloadUrlsForPage; @@ -8126,9 +6771,7 @@ exports.makeSelectTotalItemsForChannel = makeSelectTotalItemsForChannel; exports.makeSelectTotalPagesForChannel = makeSelectTotalPagesForChannel; exports.makeSelectTotalPagesInChannelSearch = makeSelectTotalPagesInChannelSearch; exports.makeSelectTotalStakedAmountForChannelUri = makeSelectTotalStakedAmountForChannelUri; -exports.makeSelectUnpublishedCollectionForId = makeSelectUnpublishedCollectionForId; exports.makeSelectUriIsStreamable = makeSelectUriIsStreamable; -exports.makeSelectUrlsForCollectionId = makeSelectUrlsForCollectionId; exports.normalizeURI = normalizeURI; exports.notificationsReducer = notificationsReducer; exports.parseQueryParams = parseQueryParams; @@ -8144,7 +6787,6 @@ exports.selectAllFetchingChannelClaims = selectAllFetchingChannelClaims; exports.selectAllMyClaimsByOutpoint = selectAllMyClaimsByOutpoint; exports.selectBalance = selectBalance; exports.selectBlocks = selectBlocks; -exports.selectBuiltinCollections = selectBuiltinCollections; exports.selectChannelClaimCounts = selectChannelClaimCounts; exports.selectChannelImportPending = selectChannelImportPending; exports.selectClaimIdsByUri = selectClaimIdsByUri; @@ -8154,9 +6796,7 @@ exports.selectClaimsBalance = selectClaimsBalance; exports.selectClaimsById = selectClaimsById; exports.selectClaimsByUri = selectClaimsByUri; exports.selectCreateChannelError = selectCreateChannelError; -exports.selectCreateCollectionError = selectCreateCollectionError; exports.selectCreatingChannel = selectCreatingChannel; -exports.selectCreatingCollection = selectCreatingCollection; exports.selectCurrentChannelPage = selectCurrentChannelPage; exports.selectDownloadUrlsCount = selectDownloadUrlsCount; exports.selectDownloadedUris = selectDownloadedUris; @@ -8171,7 +6811,6 @@ exports.selectFetchingClaimSearch = selectFetchingClaimSearch; exports.selectFetchingClaimSearchByQuery = selectFetchingClaimSearchByQuery; exports.selectFetchingMyChannels = selectFetchingMyChannels; exports.selectFetchingMyClaimsPageError = selectFetchingMyClaimsPageError; -exports.selectFetchingMyCollections = selectFetchingMyCollections; exports.selectFetchingMyPurchasesError = selectFetchingMyPurchasesError; exports.selectFetchingTxosError = selectFetchingTxosError; exports.selectFileInfosByOutpoint = selectFileInfosByOutpoint; @@ -8207,15 +6846,9 @@ exports.selectMyClaimsPageItemCount = selectMyClaimsPageItemCount; exports.selectMyClaimsPageNumber = selectMyClaimsPageNumber; exports.selectMyClaimsRaw = selectMyClaimsRaw; exports.selectMyClaimsWithoutChannels = selectMyClaimsWithoutChannels; -exports.selectMyCollectionIds = selectMyCollectionIds; -exports.selectMyEditedCollections = selectMyEditedCollections; -exports.selectMyPublishedCollections = selectMyPublishedCollections; -exports.selectMyPublishedMixedCollections = selectMyPublishedMixedCollections; -exports.selectMyPublishedPlaylistCollections = selectMyPublishedPlaylistCollections; exports.selectMyPurchases = selectMyPurchases; exports.selectMyPurchasesCount = selectMyPurchasesCount; exports.selectMyStreamUrlsCount = selectMyStreamUrlsCount; -exports.selectMyUnpublishedCollections = selectMyUnpublishedCollections; exports.selectPendingClaims = selectPendingClaims; exports.selectPendingConsolidateTxid = selectPendingConsolidateTxid; exports.selectPendingIds = selectPendingIds; @@ -8231,9 +6864,7 @@ exports.selectReflectingById = selectReflectingById; exports.selectRepostError = selectRepostError; exports.selectRepostLoading = selectRepostLoading; exports.selectReservedBalance = selectReservedBalance; -exports.selectResolvedCollections = selectResolvedCollections; exports.selectResolvingUris = selectResolvingUris; -exports.selectSavedCollectionIds = selectSavedCollectionIds; exports.selectSupportsBalance = selectSupportsBalance; exports.selectSupportsByOutpoint = selectSupportsByOutpoint; exports.selectTakeOverAmount = selectTakeOverAmount; @@ -8251,9 +6882,7 @@ exports.selectTxoPage = selectTxoPage; exports.selectTxoPageNumber = selectTxoPageNumber; exports.selectTxoPageParams = selectTxoPageParams; exports.selectUpdateChannelError = selectUpdateChannelError; -exports.selectUpdateCollectionError = selectUpdateCollectionError; exports.selectUpdatingChannel = selectUpdatingChannel; -exports.selectUpdatingCollection = selectUpdatingCollection; exports.selectUrisLoading = selectUrisLoading; exports.selectUtxoCounts = selectUtxoCounts; exports.selectWalletDecryptPending = selectWalletDecryptPending; @@ -8267,6 +6896,5 @@ exports.selectWalletState = selectWalletState; exports.selectWalletUnlockPending = selectWalletUnlockPending; exports.selectWalletUnlockResult = selectWalletUnlockResult; exports.selectWalletUnlockSucceeded = selectWalletUnlockSucceeded; -exports.splitBySeparator = splitBySeparator; exports.toQueryString = toQueryString; exports.walletReducer = walletReducer; diff --git a/dist/flow-typed/Claim.js b/dist/flow-typed/Claim.js index e03eeae..655a4bc 100644 --- a/dist/flow-typed/Claim.js +++ b/dist/flow-typed/Claim.js @@ -1,15 +1,11 @@ // @flow -declare type Claim = StreamClaim | ChannelClaim | CollectionClaim; +declare type Claim = StreamClaim | ChannelClaim; declare type ChannelClaim = GenericClaim & { value: ChannelMetadata, }; -declare type CollectionClaim = GenericClaim & { - value: CollectionMetadata, -}; - declare type StreamClaim = GenericClaim & { value: StreamMetadata, }; @@ -34,7 +30,7 @@ declare type GenericClaim = { short_url: string, // permanent_url with short id, no channel txid: string, // unique tx id type: 'claim' | 'update' | 'support', - value_type: 'stream' | 'channel' | 'collection', + value_type: 'stream' | 'channel', signing_channel?: ChannelClaim, reposted_claim?: GenericClaim, repost_channel_url?: string, @@ -78,10 +74,6 @@ declare type ChannelMetadata = GenericMetadata & { featured?: Array<string>, }; -declare type CollectionMetadata = GenericMetadata & { - claims: Array<string>, -} - declare type StreamMetadata = GenericMetadata & { license?: string, // License "title" ex: Creative Commons, Custom copyright license_url?: string, // Link to full license @@ -144,71 +136,3 @@ declare type PurchaseReceipt = { txid: string, type: 'purchase', }; - -declare type ClaimActionResolveInfo = { - [string]: { - stream: ?StreamClaim, - channel: ?ChannelClaim, - claimsInChannel: ?number, - collection: ?CollectionClaim, - }, -} - -declare type ChannelUpdateParams = { - claim_id: string, - bid?: string, - title?: string, - cover_url?: string, - thumbnail_url?: string, - description?: string, - website_url?: string, - email?: string, - tags?: Array<string>, - replace?: boolean, - languages?: Array<string>, - locations?: Array<string>, - blocking?: boolean, -} - -declare type ChannelPublishParams = { - name: string, - bid: string, - blocking?: true, - title?: string, - cover_url?: string, - thumbnail_url?: string, - description?: string, - website_url?: string, - email?: string, - tags?: Array<string>, - languages?: Array<string>, -} - -declare type CollectionUpdateParams = { - claim_id: string, - claim_ids?: Array<string>, - bid?: string, - title?: string, - cover_url?: string, - thumbnail_url?: string, - description?: string, - website_url?: string, - email?: string, - tags?: Array<string>, - replace?: boolean, - languages?: Array<string>, - locations?: Array<string>, - blocking?: boolean, -} - -declare type CollectionPublishParams = { - name: string, - bid: string, - claim_ids: Array<string>, - blocking?: true, - title?: string, - thumbnail_url?: string, - description?: string, - tags?: Array<string>, - languages?: Array<string>, -} diff --git a/dist/flow-typed/Collections.js b/dist/flow-typed/Collections.js deleted file mode 100644 index f70825a..0000000 --- a/dist/flow-typed/Collections.js +++ /dev/null @@ -1,34 +0,0 @@ -declare type Collection = { - id: string, - items: Array<?string>, - name: string, - type: string, - updatedAt: number, - totalItems?: number, - sourceId?: string, // if copied, claimId of original collection -}; - -declare type CollectionState = { - unpublished: CollectionGroup, - resolved: CollectionGroup, - pending: CollectionGroup, - edited: CollectionGroup, - builtin: CollectionGroup, - saved: Array<string>, - isResolvingCollectionById: { [string]: boolean }, - error?: string | null, -}; - -declare type CollectionGroup = { - [string]: Collection, -} - -declare type CollectionEditParams = { - claims?: Array<Claim>, - remove?: boolean, - claimIds?: Array<string>, - replace?: boolean, - order?: { from: number, to: number }, - type?: string, - name?: string, -} diff --git a/dist/flow-typed/Lbry.js b/dist/flow-typed/Lbry.js index 2fd2ac6..326b3c6 100644 --- a/dist/flow-typed/Lbry.js +++ b/dist/flow-typed/Lbry.js @@ -75,7 +75,7 @@ declare type BalanceResponse = { declare type ResolveResponse = { // Keys are the url(s) passed to resolve - [string]: { error?: {}, stream?: StreamClaim, channel?: ChannelClaim, collection?: CollectionClaim, claimsInChannel?: number }, + [string]: { error?: {}, stream?: StreamClaim, channel?: ChannelClaim, claimsInChannel?: number }, }; declare type GetResponse = FileListItem & { error?: string }; @@ -124,6 +124,14 @@ declare type ChannelUpdateResponse = GenericTxResponse & { declare type CommentCreateResponse = Comment; declare type CommentUpdateResponse = Comment; +declare type CommentListResponse = { + items: Array<Comment>, + page: number, + page_size: number, + total_items: number, + total_pages: number, +}; + declare type MyReactions = { // Keys are the commentId [string]: Array<string>, @@ -170,37 +178,6 @@ declare type ChannelSignResponse = { signing_ts: string, }; -declare type CollectionCreateResponse = { - outputs: Array<Claim>, - page: number, - page_size: number, - total_items: number, - total_pages: number, -} - -declare type CollectionListResponse = { - items: Array<Claim>, - page: number, - page_size: number, - total_items: number, - total_pages: number, -}; - -declare type CollectionResolveResponse = { - items: Array<Claim>, - total_items: number, -}; - -declare type CollectionResolveOptions = { - claim_id: string, -}; - -declare type CollectionListOptions = { - page: number, - page_size: number, - resolve?: boolean, -}; - declare type FileListResponse = { items: Array<FileListItem>, page: number, @@ -319,10 +296,6 @@ declare type LbryTypes = { support_abandon: (params: {}) => Promise<SupportAbandonResponse>, stream_repost: (params: StreamRepostOptions) => Promise<StreamRepostResponse>, purchase_list: (params: PurchaseListOptions) => Promise<PurchaseListResponse>, - collection_resolve: (params: CollectionResolveOptions) => Promise<CollectionResolveResponse>, - collection_list: (params: CollectionListOptions) => Promise<CollectionListResponse>, - collection_create: (params: {}) => Promise<CollectionCreateResponse>, - collection_update: (params: {}) => Promise<CollectionCreateResponse>, // File fetching and manipulation file_list: (params: {}) => Promise<FileListResponse>, @@ -335,6 +308,8 @@ declare type LbryTypes = { preference_set: (params: {}) => Promise<any>, // Commenting + comment_list: (params: {}) => Promise<CommentListResponse>, + comment_create: (params: {}) => Promise<CommentCreateResponse>, comment_update: (params: {}) => Promise<CommentUpdateResponse>, comment_hide: (params: {}) => Promise<CommentHideResponse>, comment_abandon: (params: {}) => Promise<CommentAbandonResponse>, @@ -351,7 +326,6 @@ declare type LbryTypes = { address_unused: (params: {}) => Promise<string>, // New address address_list: (params: {}) => Promise<string>, transaction_list: (params: {}) => Promise<TxListResponse>, - txo_list: (params: {}) => Promise<any>, // Sync sync_hash: (params: {}) => Promise<string>, diff --git a/dist/flow-typed/npm/from-entries.js b/dist/flow-typed/npm/from-entries.js deleted file mode 100644 index ce92b81..0000000 --- a/dist/flow-typed/npm/from-entries.js +++ /dev/null @@ -1,5 +0,0 @@ -// @flow - -declare module '@ungap/from-entries' { - declare module.exports: any; -} diff --git a/flow-typed/Claim.js b/flow-typed/Claim.js index e03eeae..655a4bc 100644 --- a/flow-typed/Claim.js +++ b/flow-typed/Claim.js @@ -1,15 +1,11 @@ // @flow -declare type Claim = StreamClaim | ChannelClaim | CollectionClaim; +declare type Claim = StreamClaim | ChannelClaim; declare type ChannelClaim = GenericClaim & { value: ChannelMetadata, }; -declare type CollectionClaim = GenericClaim & { - value: CollectionMetadata, -}; - declare type StreamClaim = GenericClaim & { value: StreamMetadata, }; @@ -34,7 +30,7 @@ declare type GenericClaim = { short_url: string, // permanent_url with short id, no channel txid: string, // unique tx id type: 'claim' | 'update' | 'support', - value_type: 'stream' | 'channel' | 'collection', + value_type: 'stream' | 'channel', signing_channel?: ChannelClaim, reposted_claim?: GenericClaim, repost_channel_url?: string, @@ -78,10 +74,6 @@ declare type ChannelMetadata = GenericMetadata & { featured?: Array<string>, }; -declare type CollectionMetadata = GenericMetadata & { - claims: Array<string>, -} - declare type StreamMetadata = GenericMetadata & { license?: string, // License "title" ex: Creative Commons, Custom copyright license_url?: string, // Link to full license @@ -144,71 +136,3 @@ declare type PurchaseReceipt = { txid: string, type: 'purchase', }; - -declare type ClaimActionResolveInfo = { - [string]: { - stream: ?StreamClaim, - channel: ?ChannelClaim, - claimsInChannel: ?number, - collection: ?CollectionClaim, - }, -} - -declare type ChannelUpdateParams = { - claim_id: string, - bid?: string, - title?: string, - cover_url?: string, - thumbnail_url?: string, - description?: string, - website_url?: string, - email?: string, - tags?: Array<string>, - replace?: boolean, - languages?: Array<string>, - locations?: Array<string>, - blocking?: boolean, -} - -declare type ChannelPublishParams = { - name: string, - bid: string, - blocking?: true, - title?: string, - cover_url?: string, - thumbnail_url?: string, - description?: string, - website_url?: string, - email?: string, - tags?: Array<string>, - languages?: Array<string>, -} - -declare type CollectionUpdateParams = { - claim_id: string, - claim_ids?: Array<string>, - bid?: string, - title?: string, - cover_url?: string, - thumbnail_url?: string, - description?: string, - website_url?: string, - email?: string, - tags?: Array<string>, - replace?: boolean, - languages?: Array<string>, - locations?: Array<string>, - blocking?: boolean, -} - -declare type CollectionPublishParams = { - name: string, - bid: string, - claim_ids: Array<string>, - blocking?: true, - title?: string, - thumbnail_url?: string, - description?: string, - tags?: Array<string>, - languages?: Array<string>, -} diff --git a/flow-typed/Collections.js b/flow-typed/Collections.js deleted file mode 100644 index f70825a..0000000 --- a/flow-typed/Collections.js +++ /dev/null @@ -1,34 +0,0 @@ -declare type Collection = { - id: string, - items: Array<?string>, - name: string, - type: string, - updatedAt: number, - totalItems?: number, - sourceId?: string, // if copied, claimId of original collection -}; - -declare type CollectionState = { - unpublished: CollectionGroup, - resolved: CollectionGroup, - pending: CollectionGroup, - edited: CollectionGroup, - builtin: CollectionGroup, - saved: Array<string>, - isResolvingCollectionById: { [string]: boolean }, - error?: string | null, -}; - -declare type CollectionGroup = { - [string]: Collection, -} - -declare type CollectionEditParams = { - claims?: Array<Claim>, - remove?: boolean, - claimIds?: Array<string>, - replace?: boolean, - order?: { from: number, to: number }, - type?: string, - name?: string, -} diff --git a/flow-typed/Lbry.js b/flow-typed/Lbry.js index 2fd2ac6..326b3c6 100644 --- a/flow-typed/Lbry.js +++ b/flow-typed/Lbry.js @@ -75,7 +75,7 @@ declare type BalanceResponse = { declare type ResolveResponse = { // Keys are the url(s) passed to resolve - [string]: { error?: {}, stream?: StreamClaim, channel?: ChannelClaim, collection?: CollectionClaim, claimsInChannel?: number }, + [string]: { error?: {}, stream?: StreamClaim, channel?: ChannelClaim, claimsInChannel?: number }, }; declare type GetResponse = FileListItem & { error?: string }; @@ -124,6 +124,14 @@ declare type ChannelUpdateResponse = GenericTxResponse & { declare type CommentCreateResponse = Comment; declare type CommentUpdateResponse = Comment; +declare type CommentListResponse = { + items: Array<Comment>, + page: number, + page_size: number, + total_items: number, + total_pages: number, +}; + declare type MyReactions = { // Keys are the commentId [string]: Array<string>, @@ -170,37 +178,6 @@ declare type ChannelSignResponse = { signing_ts: string, }; -declare type CollectionCreateResponse = { - outputs: Array<Claim>, - page: number, - page_size: number, - total_items: number, - total_pages: number, -} - -declare type CollectionListResponse = { - items: Array<Claim>, - page: number, - page_size: number, - total_items: number, - total_pages: number, -}; - -declare type CollectionResolveResponse = { - items: Array<Claim>, - total_items: number, -}; - -declare type CollectionResolveOptions = { - claim_id: string, -}; - -declare type CollectionListOptions = { - page: number, - page_size: number, - resolve?: boolean, -}; - declare type FileListResponse = { items: Array<FileListItem>, page: number, @@ -319,10 +296,6 @@ declare type LbryTypes = { support_abandon: (params: {}) => Promise<SupportAbandonResponse>, stream_repost: (params: StreamRepostOptions) => Promise<StreamRepostResponse>, purchase_list: (params: PurchaseListOptions) => Promise<PurchaseListResponse>, - collection_resolve: (params: CollectionResolveOptions) => Promise<CollectionResolveResponse>, - collection_list: (params: CollectionListOptions) => Promise<CollectionListResponse>, - collection_create: (params: {}) => Promise<CollectionCreateResponse>, - collection_update: (params: {}) => Promise<CollectionCreateResponse>, // File fetching and manipulation file_list: (params: {}) => Promise<FileListResponse>, @@ -335,6 +308,8 @@ declare type LbryTypes = { preference_set: (params: {}) => Promise<any>, // Commenting + comment_list: (params: {}) => Promise<CommentListResponse>, + comment_create: (params: {}) => Promise<CommentCreateResponse>, comment_update: (params: {}) => Promise<CommentUpdateResponse>, comment_hide: (params: {}) => Promise<CommentHideResponse>, comment_abandon: (params: {}) => Promise<CommentAbandonResponse>, @@ -351,7 +326,6 @@ declare type LbryTypes = { address_unused: (params: {}) => Promise<string>, // New address address_list: (params: {}) => Promise<string>, transaction_list: (params: {}) => Promise<TxListResponse>, - txo_list: (params: {}) => Promise<any>, // Sync sync_hash: (params: {}) => Promise<string>, diff --git a/flow-typed/npm/from-entries.js b/flow-typed/npm/from-entries.js deleted file mode 100644 index ce92b81..0000000 --- a/flow-typed/npm/from-entries.js +++ /dev/null @@ -1,5 +0,0 @@ -// @flow - -declare module '@ungap/from-entries' { - declare module.exports: any; -} diff --git a/package.json b/package.json index dc6bc25..00a2b2a 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "test": "jest" }, "dependencies": { - "@ungap/from-entries": "^0.2.1", "proxy-polyfill": "0.1.6", "reselect": "^3.0.0", "uuid": "^8.3.1" diff --git a/src/constants/action_types.js b/src/constants/action_types.js index bf16da2..5e3f672 100644 --- a/src/constants/action_types.js +++ b/src/constants/action_types.js @@ -102,9 +102,6 @@ export const ABANDON_CLAIM_SUCCEEDED = 'ABANDON_CLAIM_SUCCEEDED'; export const FETCH_CHANNEL_LIST_STARTED = 'FETCH_CHANNEL_LIST_STARTED'; export const FETCH_CHANNEL_LIST_COMPLETED = 'FETCH_CHANNEL_LIST_COMPLETED'; export const FETCH_CHANNEL_LIST_FAILED = 'FETCH_CHANNEL_LIST_FAILED'; -export const FETCH_COLLECTION_LIST_STARTED = 'FETCH_COLLECTION_LIST_STARTED'; -export const FETCH_COLLECTION_LIST_COMPLETED = 'FETCH_COLLECTION_LIST_COMPLETED'; -export const FETCH_COLLECTION_LIST_FAILED = 'FETCH_COLLECTION_LIST_FAILED'; export const CREATE_CHANNEL_STARTED = 'CREATE_CHANNEL_STARTED'; export const CREATE_CHANNEL_COMPLETED = 'CREATE_CHANNEL_COMPLETED'; export const CREATE_CHANNEL_FAILED = 'CREATE_CHANNEL_FAILED'; @@ -114,7 +111,6 @@ export const UPDATE_CHANNEL_FAILED = 'UPDATE_CHANNEL_FAILED'; export const IMPORT_CHANNEL_STARTED = 'IMPORT_CHANNEL_STARTED'; export const IMPORT_CHANNEL_COMPLETED = 'IMPORT_CHANNEL_COMPLETED'; export const IMPORT_CHANNEL_FAILED = 'IMPORT_CHANNEL_FAILED'; -export const CLEAR_CHANNEL_ERRORS = 'CLEAR_CHANNEL_ERRORS'; export const PUBLISH_STARTED = 'PUBLISH_STARTED'; export const PUBLISH_COMPLETED = 'PUBLISH_COMPLETED'; export const PUBLISH_FAILED = 'PUBLISH_FAILED'; @@ -133,6 +129,7 @@ export const CLAIM_REPOST_STARTED = 'CLAIM_REPOST_STARTED'; export const CLAIM_REPOST_COMPLETED = 'CLAIM_REPOST_COMPLETED'; export const CLAIM_REPOST_FAILED = 'CLAIM_REPOST_FAILED'; export const CLEAR_REPOST_ERROR = 'CLEAR_REPOST_ERROR'; +export const CLEAR_CHANNEL_ERRORS = 'CLEAR_CHANNEL_ERRORS'; export const CHECK_PUBLISH_NAME_STARTED = 'CHECK_PUBLISH_NAME_STARTED'; export const CHECK_PUBLISH_NAME_COMPLETED = 'CHECK_PUBLISH_NAME_COMPLETED'; export const UPDATE_PENDING_CLAIMS = 'UPDATE_PENDING_CLAIMS'; @@ -145,27 +142,6 @@ export const PURCHASE_LIST_STARTED = 'PURCHASE_LIST_STARTED'; export const PURCHASE_LIST_COMPLETED = 'PURCHASE_LIST_COMPLETED'; export const PURCHASE_LIST_FAILED = 'PURCHASE_LIST_FAILED'; -export const COLLECTION_PUBLISH_STARTED = 'COLLECTION_PUBLISH_STARTED'; -export const COLLECTION_PUBLISH_COMPLETED = 'COLLECTION_PUBLISH_COMPLETED'; -export const COLLECTION_PUBLISH_FAILED = 'COLLECTION_PUBLISH_FAILED'; -export const COLLECTION_PUBLISH_UPDATE_STARTED = 'COLLECTION_PUBLISH_UPDATE_STARTED'; -export const COLLECTION_PUBLISH_UPDATE_COMPLETED = 'COLLECTION_PUBLISH_UPDATE_COMPLETED'; -export const COLLECTION_PUBLISH_UPDATE_FAILED = 'COLLECTION_PUBLISH_UPDATE_FAILED'; -export const COLLECTION_PUBLISH_ABANDON_STARTED = 'COLLECTION_PUBLISH_ABANDON_STARTED'; -export const COLLECTION_PUBLISH_ABANDON_COMPLETED = 'COLLECTION_PUBLISH_ABANDON_COMPLETED'; -export const COLLECTION_PUBLISH_ABANDON_FAILED = 'COLLECTION_PUBLISH_ABANDON_FAILED'; -export const CLEAR_COLLECTION_ERRORS = 'CLEAR_COLLECTION_ERRORS'; -export const COLLECTION_ITEMS_RESOLVE_STARTED = 'COLLECTION_ITEMS_RESOLVE_STARTED'; -export const COLLECTION_ITEMS_RESOLVE_COMPLETED = 'COLLECTION_ITEMS_RESOLVE_COMPLETED'; -export const COLLECTION_ITEMS_RESOLVE_FAILED = 'COLLECTION_ITEMS_RESOLVE_FAILED'; -export const COLLECTION_NEW = 'COLLECTION_NEW'; -export const COLLECTION_DELETE = 'COLLECTION_DELETE'; -export const COLLECTION_PENDING = 'COLLECTION_PENDING'; -export const COLLECTION_EDIT = 'COLLECTION_EDIT'; -export const COLLECTION_COPY = 'COLLECTION_COPY'; -export const COLLECTION_SAVE = 'COLLECTION_SAVE'; -export const COLLECTION_ERROR = 'COLLECTION_ERROR'; - // Comments export const COMMENT_LIST_STARTED = 'COMMENT_LIST_STARTED'; export const COMMENT_LIST_COMPLETED = 'COMMENT_LIST_COMPLETED'; diff --git a/src/constants/collections.js b/src/constants/collections.js deleted file mode 100644 index 0f2d111..0000000 --- a/src/constants/collections.js +++ /dev/null @@ -1,15 +0,0 @@ -export const COLLECTION_ID = 'lid'; -export const COLLECTION_INDEX = 'linx'; - -export const COL_TYPE_PLAYLIST = 'playlist'; -export const COL_TYPE_CHANNELS = 'channelList'; - -export const WATCH_LATER_ID = 'watchlater'; -export const FAVORITES_ID = 'favorites'; -export const FAVORITE_CHANNELS_ID = 'favoriteChannels'; -export const BUILTIN_LISTS = [WATCH_LATER_ID, FAVORITES_ID, FAVORITE_CHANNELS_ID]; - -export const COL_KEY_EDITED = 'edited'; -export const COL_KEY_UNPUBLISHED = 'unpublished'; -export const COL_KEY_PENDING = 'pending'; -export const COL_KEY_SAVED = 'saved'; diff --git a/src/constants/settings.js b/src/constants/settings.js index cfcc15e..cef17d8 100644 --- a/src/constants/settings.js +++ b/src/constants/settings.js @@ -23,7 +23,7 @@ export const INSTANT_PURCHASE_MAX = 'instant_purchase_max'; export const THEME = 'theme'; export const THEMES = 'themes'; export const AUTOMATIC_DARK_MODE_ENABLED = 'automatic_dark_mode_enabled'; -export const AUTOPLAY_MEDIA = 'autoplay'; +export const AUTOPLAY = 'autoplay'; export const AUTOPLAY_NEXT = 'autoplay_next'; export const OS_NOTIFICATIONS_ENABLED = 'os_notifications_enabled'; export const AUTO_DOWNLOAD = 'auto_download'; @@ -39,8 +39,6 @@ export const ENABLE_PUBLISH_PREVIEW = 'enable-publish-preview'; export const TILE_LAYOUT = 'tile_layout'; export const VIDEO_THEATER_MODE = 'video_theater_mode'; export const VIDEO_PLAYBACK_RATE = 'video_playback_rate'; -export const CUSTOM_COMMENTS_SERVER_ENABLED = 'custom_comments_server_enabled'; -export const CUSTOM_COMMENTS_SERVER_URL = 'custom_comments_server_url'; // mobile settings export const BACKGROUND_PLAY_ENABLED = 'backgroundPlayEnabled'; diff --git a/src/constants/shared_preferences.js b/src/constants/shared_preferences.js index 9778352..bf4d46b 100644 --- a/src/constants/shared_preferences.js +++ b/src/constants/shared_preferences.js @@ -21,12 +21,10 @@ export const CLIENT_SYNC_KEYS = [ SETTINGS.INSTANT_PURCHASE_ENABLED, SETTINGS.INSTANT_PURCHASE_MAX, SETTINGS.THEME, - SETTINGS.AUTOPLAY_MEDIA, - SETTINGS.AUTOPLAY_NEXT, + SETTINGS.AUTOPLAY, SETTINGS.HIDE_BALANCE, SETTINGS.HIDE_SPLASH_ANIMATION, SETTINGS.FLOATING_PLAYER, SETTINGS.DARK_MODE_TIMES, SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, - SETTINGS.LANGUAGE, ]; diff --git a/src/index.js b/src/index.js index 079665f..d412d83 100644 --- a/src/index.js +++ b/src/index.js @@ -12,7 +12,6 @@ import * as TXO_LIST from 'constants/txo_list'; import * as SPEECH_URLS from 'constants/speech_urls'; import * as DAEMON_SETTINGS from 'constants/daemon_settings'; import * as SHARED_PREFERENCES from 'constants/shared_preferences'; -import * as COLLECTIONS_CONSTS from 'constants/collections'; import { DEFAULT_KNOWN_TAGS, DEFAULT_FOLLOWED_TAGS, MATURE_TAGS } from 'constants/tags'; import Lbry, { apiCall } from 'lbry'; import LbryFirst from 'lbry-first'; @@ -36,7 +35,6 @@ export { MATURE_TAGS, SPEECH_URLS, SHARED_PREFERENCES, - COLLECTIONS_CONSTS, }; // common @@ -52,8 +50,6 @@ export { isURIClaimable, isNameValid, convertToShareLink, - splitBySeparator, - isURIEqual, } from 'lbryURI'; // middlware @@ -61,13 +57,6 @@ export { buildSharedStateMiddleware } from 'redux/middleware/shared-state'; // actions export { doToast, doDismissToast, doError, doDismissError } from 'redux/actions/notifications'; -export { - doLocalCollectionCreate, - doFetchItemsInCollection, - doFetchItemsInCollections, - doCollectionEdit, - doCollectionDelete, -} from 'redux/actions/collections'; export { doFetchClaimsByChannel, @@ -77,7 +66,6 @@ export { doResolveUris, doResolveUri, doFetchChannelListMine, - doFetchCollectionListMine, doCreateChannel, doUpdateChannel, doClaimSearch, @@ -88,8 +76,6 @@ export { doCheckPublishNameAvailability, doPurchaseList, doCheckPendingClaims, - doCollectionPublish, - doCollectionPublishUpdate, } from 'redux/actions/claims'; export { doClearPurchasedUriSuccess, doPurchaseUri, doFileGet } from 'redux/actions/file'; @@ -154,39 +140,11 @@ export { fileInfoReducer } from 'redux/reducers/file_info'; export { notificationsReducer } from 'redux/reducers/notifications'; export { publishReducer } from 'redux/reducers/publish'; export { walletReducer } from 'redux/reducers/wallet'; -export { collectionsReducer } from 'redux/reducers/collections'; // selectors export { makeSelectContentPositionForUri } from 'redux/selectors/content'; export { selectToast, selectError } from 'redux/selectors/notifications'; -export { - selectSavedCollectionIds, - selectBuiltinCollections, - selectResolvedCollections, - selectMyUnpublishedCollections, - selectMyEditedCollections, - selectMyPublishedCollections, - selectMyPublishedMixedCollections, - selectMyPublishedPlaylistCollections, - makeSelectEditedCollectionForId, - makeSelectPendingCollectionForId, - makeSelectPublishedCollectionForId, - makeSelectCollectionIsMine, - makeSelectMyPublishedCollectionForId, - makeSelectUnpublishedCollectionForId, - makeSelectCollectionForId, - makeSelectClaimUrlInCollection, - makeSelectUrlsForCollectionId, - makeSelectClaimIdsForCollectionId, - makeSelectNameForCollectionId, - makeSelectCountForCollectionId, - makeSelectIsResolvingCollectionForId, - makeSelectIndexForUrlInCollection, - makeSelectPreviousUrlForCollectionAndUrl, - makeSelectNextUrlForCollectionAndUrl, - makeSelectCollectionForIdHasClaimUrl, -} from 'redux/selectors/collections'; export { makeSelectClaimForUri, @@ -213,6 +171,7 @@ export { makeSelectTotalItemsForChannel, makeSelectTotalPagesForChannel, makeSelectNsfwCountFromUris, + makeSelectNsfwCountForChannel, makeSelectOmittedCountForChannel, makeSelectClaimIsNsfw, makeSelectChannelForClaimUri, @@ -220,6 +179,7 @@ export { makeSelectMyChannelPermUrlForName, makeSelectClaimIsPending, makeSelectReflectingClaimForUri, + makeSelectClaimsInChannelForCurrentPageState, makeSelectShortUrlForUri, makeSelectCanonicalUrlForUri, makeSelectPermanentUrlForUri, @@ -249,8 +209,6 @@ export { selectAllMyClaimsByOutpoint, selectMyClaimsOutpoints, selectFetchingMyChannels, - selectFetchingMyCollections, - selectMyCollectionIds, selectMyChannelClaims, selectResolvingUris, selectPlayingUri, @@ -279,12 +237,6 @@ export { selectFetchingMyPurchasesError, selectMyPurchasesCount, selectPurchaseUriSuccess, - makeSelectClaimIdForUri, - selectUpdatingCollection, - selectUpdateCollectionError, - selectCreatingCollection, - selectCreateCollectionError, - makeSelectClaimIdIsPending, } from 'redux/selectors/claims'; export { diff --git a/src/lbry.js b/src/lbry.js index a7828d9..bfa20eb 100644 --- a/src/lbry.js +++ b/src/lbry.js @@ -90,10 +90,6 @@ const Lbry: LbryTypes = { support_create: params => daemonCallWithResult('support_create', params), support_list: params => daemonCallWithResult('support_list', params), stream_repost: params => daemonCallWithResult('stream_repost', params), - collection_resolve: params => daemonCallWithResult('collection_resolve', params), - collection_list: params => daemonCallWithResult('collection_list', params), - collection_create: params => daemonCallWithResult('collection_create', params), - collection_update: params => daemonCallWithResult('collection_update', params), // File fetching and manipulation file_list: (params = {}) => daemonCallWithResult('file_list', params), @@ -117,7 +113,6 @@ const Lbry: LbryTypes = { utxo_release: (params = {}) => daemonCallWithResult('utxo_release', params), support_abandon: (params = {}) => daemonCallWithResult('support_abandon', params), purchase_list: (params = {}) => daemonCallWithResult('purchase_list', params), - txo_list: (params = {}) => daemonCallWithResult('txo_list', params), sync_hash: (params = {}) => daemonCallWithResult('sync_hash', params), sync_apply: (params = {}) => daemonCallWithResult('sync_apply', params), diff --git a/src/lbryURI.js b/src/lbryURI.js index 02e13c4..ee91388 100644 --- a/src/lbryURI.js +++ b/src/lbryURI.js @@ -4,7 +4,7 @@ const channelNameMinLength = 1; const claimIdMaxLength = 40; // see https://spec.lbry.com/#urls -export const regexInvalidURI = /[ =&#:$@%?;/\\"<>%{}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u; +export const regexInvalidURI = /[ =&#:$@%?;/\\"<>%\{\}|^~[\]`\u{0000}-\u{0008}\u{000b}-\u{000c}\u{000e}-\u{001F}\u{D800}-\u{DFFF}\u{FFFE}-\u{FFFF}]/u; export const regexAddress = /^(b|r)(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; const regexPartProtocol = '^((?:lbry://)?)'; const regexPartStreamOrChannelName = '([^:$#/]*)'; @@ -12,11 +12,6 @@ const regexPartModifierSeparator = '([:$#]?)([^/]*)'; const queryStringBreaker = '^([\\S]+)([?][\\S]*)'; const separateQuerystring = new RegExp(queryStringBreaker); -const MOD_SEQUENCE_SEPARATOR = '*'; -const MOD_CLAIM_ID_SEPARATOR_OLD = '#'; -const MOD_CLAIM_ID_SEPARATOR = ':'; -const MOD_BID_POSITION_SEPARATOR = '$'; - /** * Parses a LBRY name into its component parts. Throws errors with user-friendly * messages for invalid names. @@ -149,11 +144,11 @@ function parseURIModifier(modSeperator: ?string, modValue: ?string) { throw new Error(__(`No modifier provided after separator %modSeperator%.`, { modSeperator })); } - if (modSeperator === MOD_CLAIM_ID_SEPARATOR || MOD_CLAIM_ID_SEPARATOR_OLD) { + if (modSeperator === '#') { claimId = modValue; - } else if (modSeperator === MOD_SEQUENCE_SEPARATOR) { + } else if (modSeperator === ':') { claimSequence = modValue; - } else if (modSeperator === MOD_BID_POSITION_SEPARATOR) { + } else if (modSeperator === '$') { bidPosition = modValue; } } @@ -325,22 +320,3 @@ export function convertToShareLink(URL: string) { 'https://open.lbry.com/' ); } - -export function splitBySeparator(uri: string) { - const protocolLength = 7; - return uri.startsWith('lbry://') ? uri.slice(protocolLength).split(/[#:*]/) : uri.split(/#:\*\$/); -} - -export function isURIEqual(uriA: string, uriB: string) { - const parseA = parseURI(normalizeURI(uriA)); - const parseB = parseURI(normalizeURI(uriB)); - if (parseA.isChannel) { - if (parseB.isChannel && parseA.channelClaimId === parseB.channelClaimId) { - return true; - } - } else if (parseA.streamClaimId === parseB.streamClaimId) { - return true; - } else { - return false; - } -} diff --git a/src/redux/actions/claims.js b/src/redux/actions/claims.js index 9bb92af..cd0cb6d 100644 --- a/src/redux/actions/claims.js +++ b/src/redux/actions/claims.js @@ -10,27 +10,16 @@ import { selectClaimsByUri, selectMyChannelClaims, selectPendingIds, - selectPendingClaimsById, + selectClaimsById, } from 'redux/selectors/claims'; - import { doFetchTxoPage } from 'redux/actions/wallet'; import { selectSupportsByOutpoint } from 'redux/selectors/wallet'; import { creditsToString } from 'util/format-credits'; import { batchActions } from 'util/batch-actions'; import { createNormalizedClaimSearchKey } from 'util/claim'; import { PAGE_SIZE } from 'constants/claim'; -import { - selectPendingCollections, - makeSelectClaimIdsForCollectionId, -} from 'redux/selectors/collections'; -import { - doFetchItemsInCollection, - doFetchItemsInCollections, - doCollectionDelete, -} from 'redux/actions/collections'; -let onChannelConfirmCallback; -let checkPendingInterval; +type ResolveEntries = Array<[string, GenericClaim]>; export function doResolveUris( uris: Array<string>, @@ -72,12 +61,9 @@ export function doResolveUris( stream: ?StreamClaim, channel: ?ChannelClaim, claimsInChannel: ?number, - collection: ?CollectionClaim, }, } = {}; - const collectionIds: Array<string> = []; - return Lbry.resolve({ urls: urisToResolve, ...options }).then( async(result: ResolveResponse) => { let repostedResults = {}; @@ -94,7 +80,6 @@ export function doResolveUris( // https://github.com/facebook/flow/issues/2221 if (uriResolveInfo) { if (uriResolveInfo.error) { - // $FlowFixMe resolveInfo[uri] = { ...fallbackResolveInfo }; } else { if (checkReposts) { @@ -111,10 +96,6 @@ export function doResolveUris( result.channel = uriResolveInfo; // $FlowFixMe result.claimsInChannel = uriResolveInfo.meta.claims_in_channel; - } else if (uriResolveInfo.value_type === 'collection') { - result.collection = uriResolveInfo; - // $FlowFixMe - collectionIds.push(uriResolveInfo.claim_id); } else { result.stream = uriResolveInfo; if (uriResolveInfo.signing_channel) { @@ -146,11 +127,6 @@ export function doResolveUris( type: ACTIONS.RESOLVE_URIS_COMPLETED, data: { resolveInfo }, }); - - if (collectionIds.length) { - dispatch(doFetchItemsInCollections({ collectionIds: collectionIds, pageSize: 5 })); - } - return result; } ); @@ -407,7 +383,7 @@ export function doClearChannelErrors() { }; } -export function doCreateChannel(name: string, amount: number, optionalParams: any, onConfirm: any) { +export function doCreateChannel(name: string, amount: number, optionalParams: any, cb: any) { return (dispatch: Dispatch) => { dispatch({ type: ACTIONS.CREATE_CHANNEL_STARTED, @@ -423,7 +399,7 @@ export function doCreateChannel(name: string, amount: number, optionalParams: an description?: string, website_url?: string, email?: string, - tags?: Array<Tag>, + tags?: Array<string>, languages?: Array<string>, } = { name, @@ -474,7 +450,7 @@ export function doCreateChannel(name: string, amount: number, optionalParams: an claims: [channelClaim], }, }); - dispatch(doCheckPendingClaims(onConfirm)); + dispatch(doCheckPendingClaims(cb)); return channelClaim; }) .catch(error => { @@ -517,6 +493,7 @@ export function doUpdateChannel(params: any, cb: any) { } // we'll need to remove these once we add locations/channels to channel page edit/create options + if (channelClaim && channelClaim.value && channelClaim.value.locations) { updateParams.locations = channelClaim.value.locations; } @@ -554,7 +531,7 @@ export function doImportChannel(certificate: string) { }); return Lbry.channel_import({ channel_data: certificate }) - .then(() => { + .then((result: string) => { dispatch({ type: ACTIONS.IMPORT_CHANNEL_COMPLETED, }); @@ -596,45 +573,11 @@ export function doFetchChannelListMine( }; } -export function doFetchCollectionListMine(page: number = 1, pageSize: number = 99999) { - return (dispatch: Dispatch) => { - dispatch({ - type: ACTIONS.FETCH_COLLECTION_LIST_STARTED, - }); - - const callback = (response: CollectionListResponse) => { - const { items } = response; - dispatch({ - type: ACTIONS.FETCH_COLLECTION_LIST_COMPLETED, - data: { claims: items }, - }); - dispatch( - doFetchItemsInCollections({ - collectionIds: items.map(claim => claim.claim_id), - page_size: 5, - }) - ); - }; - - const failure = error => { - dispatch({ - type: ACTIONS.FETCH_COLLECTION_LIST_FAILED, - data: error, - }); - }; - - Lbry.collection_list({ page, page_size: pageSize, resolve_claims: 1, resolve: true }).then( - callback, - failure - ); - }; -} - export function doClaimSearch( options: { page_size: number, page: number, - no_totals?: boolean, + no_totals: boolean, any_tags?: Array<string>, claim_ids?: Array<string>, channel_ids?: Array<string>, @@ -675,7 +618,7 @@ export function doClaimSearch( pageSize: options.page_size, }, }); - return resolveInfo; + return true; }; const failure = err => { @@ -695,7 +638,8 @@ export function doClaimSearch( } export function doRepost(options: StreamRepostOptions) { - return (dispatch: Dispatch): Promise<any> => { + return (dispatch: Dispatch) => { + // $FlowFixMe return new Promise(resolve => { dispatch({ type: ACTIONS.CLAIM_REPOST_STARTED, @@ -735,209 +679,6 @@ export function doRepost(options: StreamRepostOptions) { }; } -export function doCollectionPublish( - options: { - name: string, - bid: string, - blocking: true, - title?: string, - channel_id?: string, - thumbnail_url?: string, - description?: string, - tags?: Array<Tag>, - languages?: Array<string>, - claims: Array<string>, - }, - localId: string -) { - return (dispatch: Dispatch): Promise<any> => { - // $FlowFixMe - - const params: { - name: string, - bid: string, - channel_id?: string, - blocking?: true, - title?: string, - thumbnail_url?: string, - description?: string, - tags?: Array<string>, - languages?: Array<string>, - claims: Array<string>, - } = { - name: options.name, - bid: creditsToString(options.bid), - title: options.title, - thumbnail_url: options.thumbnail_url, - description: options.description, - tags: [], - languages: options.languages || [], - locations: [], - blocking: true, - claims: options.claims, - }; - - if (options.tags) { - params['tags'] = options.tags.map(tag => tag.name); - } - - if (options.channel_id) { - params['channel_id'] = options.channel_id; - } - - return new Promise(resolve => { - dispatch({ - type: ACTIONS.COLLECTION_PUBLISH_STARTED, - }); - - function success(response) { - const collectionClaim = response.outputs[0]; - dispatch( - batchActions( - { - type: ACTIONS.COLLECTION_PUBLISH_COMPLETED, - data: { claimId: collectionClaim.claim_id }, - }, - // move unpublished collection to pending collection with new publish id - // recent publish won't resolve this second. handle it in checkPending - { - type: ACTIONS.UPDATE_PENDING_CLAIMS, - data: { - claims: [collectionClaim], - }, - } - ) - ); - dispatch({ - type: ACTIONS.COLLECTION_PENDING, - data: { localId: localId, claimId: collectionClaim.claim_id }, - }); - dispatch(doCheckPendingClaims()); - dispatch(doFetchCollectionListMine(1, 10)); - return resolve(collectionClaim); - } - - function failure(error) { - dispatch({ - type: ACTIONS.COLLECTION_PUBLISH_FAILED, - data: { - error: error.message, - }, - }); - } - - return Lbry.collection_create(params).then(success, failure); - }); - }; -} - -export function doCollectionPublishUpdate( - options: { - bid?: string, - blocking?: true, - title?: string, - thumbnail_url?: string, - description?: string, - claim_id: string, - tags?: Array<Tag>, - languages?: Array<string>, - claims?: Array<string>, - channel_id?: string, - }, - isBackgroundUpdate?: boolean -) { - return (dispatch: Dispatch, getState: GetState): Promise<any> => { - // TODO: implement one click update - - const updateParams: { - bid?: string, - blocking?: true, - title?: string, - thumbnail_url?: string, - channel_id?: string, - description?: string, - claim_id: string, - tags?: Array<string>, - languages?: Array<string>, - claims?: Array<string>, - clear_claims: boolean, - replace?: boolean, - } = isBackgroundUpdate - ? { - blocking: true, - claim_id: options.claim_id, - clear_claims: true, - } - : { - bid: creditsToString(options.bid), - title: options.title, - thumbnail_url: options.thumbnail_url, - description: options.description, - tags: [], - languages: options.languages || [], - locations: [], - blocking: true, - claim_id: options.claim_id, - clear_claims: true, - replace: true, - }; - - if (isBackgroundUpdate && updateParams.claim_id) { - const state = getState(); - updateParams['claims'] = makeSelectClaimIdsForCollectionId(updateParams.claim_id)(state); - } else if (options.claims) { - updateParams['claims'] = options.claims; - } - - if (options.tags) { - updateParams['tags'] = options.tags.map(tag => tag.name); - } - - if (options.channel_id) { - updateParams['channel_id'] = options.channel_id; - } - - return new Promise(resolve => { - dispatch({ - type: ACTIONS.COLLECTION_PUBLISH_UPDATE_STARTED, - }); - - function success(response) { - const collectionClaim = response.outputs[0]; - dispatch({ - type: ACTIONS.COLLECTION_PUBLISH_UPDATE_COMPLETED, - data: { - collectionClaim, - }, - }); - dispatch({ - type: ACTIONS.COLLECTION_PENDING, - data: { claimId: collectionClaim.claim_id }, - }); - dispatch({ - type: ACTIONS.UPDATE_PENDING_CLAIMS, - data: { - claims: [collectionClaim], - }, - }); - dispatch(doCheckPendingClaims()); - return resolve(collectionClaim); - } - - function failure(error) { - dispatch({ - type: ACTIONS.COLLECTION_PUBLISH_UPDATE_FAILED, - data: { - error: error.message, - }, - }); - } - - return Lbry.collection_update(updateParams).then(success, failure); - }); - }; -} - export function doCheckPublishNameAvailability(name: string) { return (dispatch: Dispatch) => { dispatch({ @@ -1000,71 +741,47 @@ export function doPurchaseList(page: number = 1, pageSize: number = PAGE_SIZE) { }; } -export const doCheckPendingClaims = (onChannelConfirmed: Function) => ( +export const doCheckPendingClaims = (onConfirmed: Function) => ( dispatch: Dispatch, getState: GetState ) => { - if (onChannelConfirmed) { - onChannelConfirmCallback = onChannelConfirmed; - } - clearInterval(checkPendingInterval); - const checkTxoList = () => { + let claimCheckInterval; + + const checkClaimList = () => { const state = getState(); - const pendingById = Object.assign({}, selectPendingClaimsById(state)); - const pendingTxos = (Object.values(pendingById): any).map(p => p.txid); - // use collections - const pendingCollections = selectPendingCollections(state); - if (pendingTxos.length) { - Lbry.txo_list({ txid: pendingTxos }) - .then(result => { - const txos = result.items; - const idsToConfirm = []; - txos.forEach(txo => { - if (txo.claim_id && txo.confirmations > 0) { - idsToConfirm.push(txo.claim_id); - delete pendingById[txo.claim_id]; + const pendingIdSet = new Set(selectPendingIds(state)); + Lbry.claim_list({ page: 1, page_size: 10 }) + .then(result => { + const claims = result.items; + const claimsToConfirm = []; + claims.forEach(claim => { + const { claim_id: claimId } = claim; + if (claim.confirmations > 0 && pendingIdSet.has(claimId)) { + pendingIdSet.delete(claimId); + claimsToConfirm.push(claim); + if (onConfirmed) { + onConfirmed(claim); } - }); - return { idsToConfirm, pendingById }; - }) - .then(results => { - const { idsToConfirm, pendingById } = results; - if (idsToConfirm.length) { - return Lbry.claim_list({ claim_id: idsToConfirm, resolve: true }).then(results => { - const claims = results.items; - const collectionIds = claims - .filter(c => c.value_type === 'collection') - .map(c => c.claim_id); - dispatch({ - type: ACTIONS.UPDATE_CONFIRMED_CLAIMS, - data: { - claims: claims, - pending: pendingById, - }, - }); - if (collectionIds.length) { - dispatch( - doFetchItemsInCollections({ - collectionIds, - }) - ); - } - const channelClaims = claims.filter(claim => claim.value_type === 'channel'); - if (channelClaims.length && onChannelConfirmCallback) { - channelClaims.forEach(claim => onChannelConfirmCallback(claim)); - } - if (Object.keys(pendingById).length === 0) { - clearInterval(checkPendingInterval); - } - }); } }); - } else { - clearInterval(checkPendingInterval); - } + if (claimsToConfirm.length) { + dispatch({ + type: ACTIONS.UPDATE_CONFIRMED_CLAIMS, + data: { + claims: claimsToConfirm, + }, + }); + } + return pendingIdSet.size; + }) + .then(len => { + if (!len) { + clearInterval(claimCheckInterval); + } + }); }; - // do something with onConfirmed (typically get blocklist for channel) - checkPendingInterval = setInterval(() => { - checkTxoList(); + + claimCheckInterval = setInterval(() => { + checkClaimList(); }, 30000); }; diff --git a/src/redux/actions/collections.js b/src/redux/actions/collections.js deleted file mode 100644 index 1f310fe..0000000 --- a/src/redux/actions/collections.js +++ /dev/null @@ -1,495 +0,0 @@ -// @flow -import * as ACTIONS from 'constants/action_types'; -import { v4 as uuid } from 'uuid'; -import Lbry from 'lbry'; -import { doClaimSearch, doAbandonClaim } from 'redux/actions/claims'; -import { makeSelectClaimForClaimId } from 'redux/selectors/claims'; -import { - makeSelectCollectionForId, - // makeSelectPublishedCollectionForId, // for "save" or "copy" action - makeSelectMyPublishedCollectionForId, - makeSelectPublishedCollectionForId, - makeSelectUnpublishedCollectionForId, - makeSelectEditedCollectionForId, -} from 'redux/selectors/collections'; -import * as COLS from 'constants/collections'; - -const getTimestamp = () => { - return Math.floor(Date.now() / 1000); -}; - -const FETCH_BATCH_SIZE = 50; - -export const doLocalCollectionCreate = ( - name: string, - collectionItems: Array<string>, - type: string, - sourceId: string -) => (dispatch: Dispatch) => { - return dispatch({ - type: ACTIONS.COLLECTION_NEW, - data: { - entry: { - id: uuid(), // start with a uuid, this becomes a claimId after publish - name: name, - updatedAt: getTimestamp(), - items: collectionItems || [], - sourceId: sourceId, - type: type, - }, - }, - }); -}; - -export const doCollectionDelete = (id: string, colKey: ?string = undefined) => ( - dispatch: Dispatch, - getState: GetState -) => { - const state = getState(); - const claim = makeSelectClaimForClaimId(id)(state); - const collectionDelete = () => - dispatch({ - type: ACTIONS.COLLECTION_DELETE, - data: { - id: id, - collectionKey: colKey, - }, - }); - if (claim && !colKey) { - // could support "abandon, but keep" later - const { txid, nout } = claim; - return dispatch(doAbandonClaim(txid, nout, collectionDelete)); - } - return collectionDelete(); -}; - -// Given a collection, save its collectionId to be resolved and displayed in Library -// export const doCollectionSave = ( -// id: string, -// ) => (dispatch: Dispatch) => { -// return dispatch({ -// type: ACTIONS.COLLECTION_SAVE, -// data: { -// id: id, -// }, -// }); -// }; - -// Given a collection and name, copy it to a local private collection with a name -// export const doCollectionCopy = ( -// id: string, -// ) => (dispatch: Dispatch) => { -// return dispatch({ -// type: ACTIONS.COLLECTION_COPY, -// data: { -// id: id, -// }, -// }); -// }; - -export const doFetchItemsInCollections = ( - resolveItemsOptions: { - collectionIds: Array<string>, - pageSize?: number, - }, - resolveStartedCallback?: () => void -) => async(dispatch: Dispatch, getState: GetState) => { - /* - 1) make sure all the collection claims are loaded into claims reducer, search/resolve if necessary. - 2) get the item claims for each - 3) format and make sure they're in the order as in the claim - 4) Build the collection objects and update collections reducer - 5) Update redux claims reducer - */ - let state = getState(); - const { collectionIds, pageSize } = resolveItemsOptions; - - dispatch({ - type: ACTIONS.COLLECTION_ITEMS_RESOLVE_STARTED, - data: { ids: collectionIds }, - }); - - if (resolveStartedCallback) resolveStartedCallback(); - - const collectionIdsToSearch = collectionIds.filter(claimId => !state.claims.byId[claimId]); - - if (collectionIdsToSearch.length) { - await dispatch(doClaimSearch({ claim_ids: collectionIdsToSearch, page: 1, page_size: 9999 })); - } - - const stateAfterClaimSearch = getState(); - - async function fetchItemsForCollectionClaim(claim: CollectionClaim, pageSize?: number) { - const totalItems = claim.value.claims && claim.value.claims.length; - const claimId = claim.claim_id; - const itemOrder = claim.value.claims; - - const sortResults = (items: Array<Claim>, claimList) => { - const newItems: Array<Claim> = []; - claimList.forEach(id => { - const index = items.findIndex(i => i.claim_id === id); - if (index >= 0) { - newItems.push(items[index]); - } - }); - /* - This will return newItems[] of length less than total_items below - if one or more of the claims has been abandoned. That's ok for now. - */ - return newItems; - }; - - const mergeBatches = ( - arrayOfResults: Array<{ items: Array<Claim>, total_items: number }>, - claimList: Array<string> - ) => { - const mergedResults: { items: Array<Claim>, total_items: number } = { - items: [], - total_items: 0, - }; - arrayOfResults.forEach(result => { - mergedResults.items = mergedResults.items.concat(result.items); - mergedResults.total_items = result.total_items; - }); - - mergedResults.items = sortResults(mergedResults.items, claimList); - return mergedResults; - }; - - try { - const batchSize = pageSize || FETCH_BATCH_SIZE; - const batches: Array<Promise<any>> = []; - - for (let i = 0; i < Math.ceil(totalItems / batchSize); i++) { - batches[i] = Lbry.claim_search({ - claim_ids: claim.value.claims, - page: i + 1, - page_size: batchSize, - no_totals: true, - }); - } - const itemsInBatches = await Promise.all(batches); - const result = mergeBatches(itemsInBatches, itemOrder); - - // $FlowFixMe - const itemsById: { claimId: string, items?: ?Array<GenericClaim> } = { claimId: claimId }; - if (result.items) { - itemsById.items = result.items; - } else { - itemsById.items = null; - } - return itemsById; - } catch (e) { - return { - claimId: claimId, - items: null, - }; - } - } - - function formatForClaimActions(resultClaimsByUri) { - const formattedClaims = {}; - Object.entries(resultClaimsByUri).forEach(([uri, uriResolveInfo]) => { - // Flow has terrible Object.entries support - // https://github.com/facebook/flow/issues/2221 - if (uriResolveInfo) { - let result = {}; - if (uriResolveInfo.value_type === 'channel') { - result.channel = uriResolveInfo; - // $FlowFixMe - result.claimsInChannel = uriResolveInfo.meta.claims_in_channel; - // ALSO SKIP COLLECTIONS - } else if (uriResolveInfo.value_type === 'collection') { - result.collection = uriResolveInfo; - } else { - result.stream = uriResolveInfo; - if (uriResolveInfo.signing_channel) { - result.channel = uriResolveInfo.signing_channel; - result.claimsInChannel = - (uriResolveInfo.signing_channel.meta && - uriResolveInfo.signing_channel.meta.claims_in_channel) || - 0; - } - } - // $FlowFixMe - formattedClaims[uri] = result; - } - }); - return formattedClaims; - } - - const invalidCollectionIds = []; - const promisedCollectionItemFetches = []; - collectionIds.forEach(collectionId => { - const claim = makeSelectClaimForClaimId(collectionId)(stateAfterClaimSearch); - if (!claim) { - invalidCollectionIds.push(collectionId); - } else { - promisedCollectionItemFetches.push(fetchItemsForCollectionClaim(claim, pageSize)); - } - }); - - // $FlowFixMe - const collectionItemsById: Array<{ - claimId: string, - items: ?Array<GenericClaim>, - }> = await Promise.all(promisedCollectionItemFetches); - - const newCollectionObjectsById = {}; - const resolvedItemsByUrl = {}; - collectionItemsById.forEach(entry => { - // $FlowFixMe - const collectionItems: Array<any> = entry.items; - const collectionId = entry.claimId; - if (collectionItems) { - const claim = makeSelectClaimForClaimId(collectionId)(stateAfterClaimSearch); - - const editedCollection = makeSelectEditedCollectionForId(collectionId)(stateAfterClaimSearch); - const { name, timestamp, value } = claim || {}; - const { title } = value; - const valueTypes = new Set(); - const streamTypes = new Set(); - - let newItems = []; - let isPlaylist; - - if (collectionItems) { - collectionItems.forEach(collectionItem => { - newItems.push(collectionItem.permanent_url); - valueTypes.add(collectionItem.value_type); - if (collectionItem.value.stream_type) { - streamTypes.add(collectionItem.value.stream_type); - } - resolvedItemsByUrl[collectionItem.canonical_url] = collectionItem; - }); - isPlaylist = - valueTypes.size === 1 && - valueTypes.has('stream') && - ((streamTypes.size === 1 && (streamTypes.has('audio') || streamTypes.has('video'))) || - (streamTypes.size === 2 && (streamTypes.has('audio') && streamTypes.has('video')))); - } - - newCollectionObjectsById[collectionId] = { - items: newItems, - id: collectionId, - name: title || name, - itemCount: claim.value.claims.length, - type: isPlaylist ? 'playlist' : 'collection', - updatedAt: timestamp, - }; - - if (editedCollection && timestamp > editedCollection['updatedAt']) { - dispatch({ - type: ACTIONS.COLLECTION_DELETE, - data: { - id: collectionId, - collectionKey: 'edited', - }, - }); - } - } else { - invalidCollectionIds.push(collectionId); - } - }); - const formattedClaimsByUri = formatForClaimActions(collectionItemsById); - - dispatch({ - type: ACTIONS.RESOLVE_URIS_COMPLETED, - data: { resolveInfo: formattedClaimsByUri }, - }); - - dispatch({ - type: ACTIONS.COLLECTION_ITEMS_RESOLVE_COMPLETED, - data: { - resolvedCollections: newCollectionObjectsById, - failedCollectionIds: invalidCollectionIds, - }, - }); -}; - -export const doFetchItemsInCollection = ( - options: { collectionId: string, pageSize?: number }, - cb?: () => void -) => { - const { collectionId, pageSize } = options; - const newOptions: { collectionIds: Array<string>, pageSize?: number } = { - collectionIds: [collectionId], - }; - if (pageSize) newOptions.pageSize = pageSize; - return doFetchItemsInCollections(newOptions, cb); -}; - -export const doCollectionEdit = (collectionId: string, params: CollectionEditParams) => async( - dispatch: Dispatch, - getState: GetState -) => { - const state = getState(); - const collection: Collection = makeSelectCollectionForId(collectionId)(state); - const editedCollection: Collection = makeSelectEditedCollectionForId(collectionId)(state); - const unpublishedCollection: Collection = makeSelectUnpublishedCollectionForId(collectionId)( - state - ); - const publishedCollection: Collection = makeSelectPublishedCollectionForId(collectionId)(state); // needs to be published only - - const generateCollectionItemsFromSearchResult = results => { - return ( - Object.values(results) - // $FlowFixMe - .reduce( - ( - acc, - cur: { - stream: ?StreamClaim, - channel: ?ChannelClaim, - claimsInChannel: ?number, - collection: ?CollectionClaim, - } - ) => { - let url; - if (cur.stream) { - url = cur.stream.permanent_url; - } else if (cur.channel) { - url = cur.channel.permanent_url; - } else if (cur.collection) { - url = cur.collection.permanent_url; - } else { - return acc; - } - acc.push(url); - return acc; - }, - [] - ) - ); - }; - - if (!collection) { - return dispatch({ - type: ACTIONS.COLLECTION_ERROR, - data: { - message: 'collection does not exist', - }, - }); - } - - let currentItems = collection.items ? collection.items.concat() : []; - const { claims: passedClaims, order, claimIds, replace, remove, type } = params; - - const collectionType = type || collection.type; - let newItems: Array<?string> = currentItems; - - if (passedClaims) { - if (remove) { - const passedUrls = passedClaims.map(claim => claim.permanent_url); - // $FlowFixMe // need this? - newItems = currentItems.filter((item: string) => !passedUrls.includes(item)); - } else { - passedClaims.forEach(claim => newItems.push(claim.permanent_url)); - } - } - - if (claimIds) { - const batches = []; - if (claimIds.length > 50) { - for (let i = 0; i < Math.ceil(claimIds.length / 50); i++) { - batches[i] = claimIds.slice(i * 50, (i + 1) * 50); - } - } else { - batches[0] = claimIds; - } - const resultArray = await Promise.all( - batches.map(batch => { - let options = { claim_ids: batch, page: 1, page_size: 50 }; - return dispatch(doClaimSearch(options)); - }) - ); - - const searchResults = Object.assign({}, ...resultArray); - - if (replace) { - newItems = generateCollectionItemsFromSearchResult(searchResults); - } else { - newItems = currentItems.concat(generateCollectionItemsFromSearchResult(searchResults)); - } - } - - if (order) { - const [movedItem] = currentItems.splice(order.from, 1); - currentItems.splice(order.to, 0, movedItem); - } - - // console.log('p&e', publishedCollection.items, newItems, publishedCollection.items.join(','), newItems.join(',')) - if (editedCollection) { - // delete edited if newItems are the same as publishedItems - if (publishedCollection.items.join(',') === newItems.join(',')) { - dispatch({ - type: ACTIONS.COLLECTION_DELETE, - data: { - id: collectionId, - collectionKey: 'edited', - }, - }); - } else { - dispatch({ - type: ACTIONS.COLLECTION_EDIT, - data: { - id: collectionId, - collectionKey: 'edited', - collection: { - items: newItems, - id: collectionId, - name: params.name || collection.name, - updatedAt: getTimestamp(), - type: collectionType, - }, - }, - }); - } - } else if (publishedCollection) { - dispatch({ - type: ACTIONS.COLLECTION_EDIT, - data: { - id: collectionId, - collectionKey: 'edited', - collection: { - items: newItems, - id: collectionId, - name: params.name || collection.name, - updatedAt: getTimestamp(), - type: collectionType, - }, - }, - }); - } else if (COLS.BUILTIN_LISTS.includes(collectionId)) { - dispatch({ - type: ACTIONS.COLLECTION_EDIT, - data: { - id: collectionId, - collectionKey: 'builtin', - collection: { - items: newItems, - id: collectionId, - name: params.name || collection.name, - updatedAt: getTimestamp(), - type: collectionType, - }, - }, - }); - } else if (unpublishedCollection) { - dispatch({ - type: ACTIONS.COLLECTION_EDIT, - data: { - id: collectionId, - collectionKey: 'unpublished', - collection: { - items: newItems, - id: collectionId, - name: params.name || collection.name, - updatedAt: getTimestamp(), - type: collectionType, - }, - }, - }); - } - return true; -}; diff --git a/src/redux/actions/publish.js b/src/redux/actions/publish.js index 239a9bd..4732ebd 100644 --- a/src/redux/actions/publish.js +++ b/src/redux/actions/publish.js @@ -21,7 +21,6 @@ export const doResetThumbnailStatus = () => (dispatch: Dispatch) => { type: ACTIONS.UPDATE_PUBLISH_FORM, data: { thumbnailPath: '', - thumbnailError: undefined, }, }); @@ -69,8 +68,7 @@ export const doUploadThumbnail = ( thumbnailBlob?: File, fsAdapter?: any, fs?: any, - path?: any, - cb?: (string) => void + path?: any ) => (dispatch: Dispatch) => { const downMessage = __('Thumbnail upload service may be down, try again later.'); let thumbnail, fileExt, fileName, fileType; @@ -98,13 +96,6 @@ export const doUploadThumbnail = ( ); }; - dispatch({ - type: ACTIONS.UPDATE_PUBLISH_FORM, - data: { - thumbnailError: undefined, - }, - }); - const doUpload = data => { return fetch(SPEECH_PUBLISH, { method: 'POST', @@ -113,17 +104,15 @@ export const doUploadThumbnail = ( .then(res => res.text()) .then(text => (text.length ? JSON.parse(text) : {})) .then(json => { - if (!json.success) return uploadError(json.message || downMessage); - if (cb) { - cb(json.data.serveUrl); - } - return dispatch({ - type: ACTIONS.UPDATE_PUBLISH_FORM, - data: { - uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE, - thumbnail: json.data.serveUrl, - }, - }); + return json.success + ? dispatch({ + type: ACTIONS.UPDATE_PUBLISH_FORM, + data: { + uploadThumbnailStatus: THUMBNAIL_STATUSES.COMPLETE, + thumbnail: json.data.serveUrl, + }, + }) + : uploadError(json.message || downMessage); }) .catch(err => { let message = err.message; @@ -211,8 +200,7 @@ export const doPrepareEdit = (claim: StreamClaim, uri: string, fileInfo: FileLis description, fee, languages, - releaseTime: release_time, - releaseTimeEdited: undefined, + release_time: release_time ? Number(release_time) * 1000 : undefined, thumbnail: thumbnail ? thumbnail.url : null, title, uri, @@ -266,7 +254,7 @@ export const doPublish = (success: Function, fail: Function, preview: Function) filePath, description, language, - releaseTimeEdited, + releaseTime, license, licenseUrl, useLBRYUploader, @@ -359,8 +347,8 @@ export const doPublish = (success: Function, fail: Function, preview: Function) } // Set release time to curret date. On edits, keep original release/transaction time as release_time - if (releaseTimeEdited) { - publishPayload.release_time = releaseTimeEdited; + if (releaseTime) { + publishPayload.release_time = Number(Math.round(new Date(releaseTime) / 1000)); } else if (myClaimForUriEditing && myClaimForUriEditing.value.release_time) { publishPayload.release_time = Number(myClaimForUri.value.release_time); } else if (myClaimForUriEditing && myClaimForUriEditing.timestamp) { diff --git a/src/redux/actions/sync.js b/src/redux/actions/sync.js index 3808004..14c7f00 100644 --- a/src/redux/actions/sync.js +++ b/src/redux/actions/sync.js @@ -13,10 +13,6 @@ type SharedData = { settings?: any, app_welcome_version?: number, sharing_3P?: boolean, - unpublishedCollections: CollectionGroup, - editedCollections: CollectionGroup, - builtinCollections: CollectionGroup, - savedCollections: Array<string>, }, }; @@ -31,10 +27,6 @@ function extractUserState(rawObj: SharedData) { settings, app_welcome_version, sharing_3P, - unpublishedCollections, - editedCollections, - builtinCollections, - savedCollections, } = rawObj.value; return { @@ -46,10 +38,6 @@ function extractUserState(rawObj: SharedData) { ...(settings ? { settings } : {}), ...(app_welcome_version ? { app_welcome_version } : {}), ...(sharing_3P ? { sharing_3P } : {}), - ...(unpublishedCollections ? { unpublishedCollections } : {}), - ...(editedCollections ? { editedCollections } : {}), - ...(builtinCollections ? { builtinCollections } : {}), - ...(savedCollections ? { savedCollections } : {}), }; } @@ -67,10 +55,6 @@ export function doPopulateSharedUserState(sharedSettings: any) { settings, app_welcome_version, sharing_3P, - unpublishedCollections, - editedCollections, - builtinCollections, - savedCollections, } = extractUserState(sharedSettings); dispatch({ type: ACTIONS.USER_STATE_POPULATE, @@ -83,10 +67,6 @@ export function doPopulateSharedUserState(sharedSettings: any) { settings, welcomeVersion: app_welcome_version, allowAnalytics: sharing_3P, - unpublishedCollections, - editedCollections, - builtinCollections, - savedCollections, }, }); }; diff --git a/src/redux/actions/wallet.js b/src/redux/actions/wallet.js index 9c06ea9..8d73e90 100644 --- a/src/redux/actions/wallet.js +++ b/src/redux/actions/wallet.js @@ -61,8 +61,9 @@ export function doBalanceSubscribe() { }; } -export function doFetchTransactions(page = 1, pageSize = 999999) { +export function doFetchTransactions(page = 1, pageSize = 99999) { return dispatch => { + dispatch(doFetchSupports()); dispatch({ type: ACTIONS.FETCH_TRANSACTIONS_STARTED, }); @@ -348,7 +349,7 @@ export function doSetDraftTransactionAddress(address) { }; } -export function doSendTip(params, isSupport, successCallback, errorCallback, shouldNotify = true) { +export function doSendTip(params, isSupport, successCallback, errorCallback) { return (dispatch, getState) => { const state = getState(); const balance = selectBalance(state); @@ -367,25 +368,23 @@ export function doSendTip(params, isSupport, successCallback, errorCallback, sho return; } - const success = response => { - if (shouldNotify) { - dispatch( - doToast({ - message: shouldSupport - ? __('You deposited %amount% LBRY Credits as a support!', { amount: params.amount }) - : __('You sent %amount% LBRY Credits as a tip, Mahalo!', { amount: params.amount }), - linkText: __('History'), - linkTarget: '/wallet', - }) - ); - } + const success = () => { + dispatch( + doToast({ + message: shouldSupport + ? __('You deposited %amount% LBRY Credits as a support!', { amount: params.amount }) + : __('You sent %amount% LBRY Credits as a tip, Mahalo!', { amount: params.amount }), + linkText: __('History'), + linkTarget: '/wallet', + }) + ); dispatch({ type: ACTIONS.SUPPORT_TRANSACTION_COMPLETED, }); if (successCallback) { - successCallback(response); + successCallback(); } }; diff --git a/src/redux/middleware/shared-state.js b/src/redux/middleware/shared-state.js index 031e9a4..e4a8c4f 100644 --- a/src/redux/middleware/shared-state.js +++ b/src/redux/middleware/shared-state.js @@ -2,10 +2,9 @@ import isEqual from 'util/deep-equal'; import { doPreferenceSet } from 'redux/actions/sync'; -const RUN_PREFERENCES_DELAY_MS = 2000; const SHARED_PREFERENCE_VERSION = '0.1'; let oldShared = {}; -let timeout; + export const buildSharedStateMiddleware = ( actions: Array<string>, sharedStateFilters: {}, @@ -23,43 +22,40 @@ export const buildSharedStateMiddleware = ( if (!actions.includes(action.type) || typeof action === 'function') { return next(action); } - clearTimeout(timeout); + const actionResult = next(action); // Call `getState` after calling `next` to ensure the state has updated in response to the action - function runPreferences() { - const nextState: { user: any, settings: any } = getState(); - const syncEnabled = - nextState.settings && - nextState.settings.clientSettings && - nextState.settings.clientSettings.enable_sync; - const hasVerifiedEmail = - nextState.user && nextState.user.user && nextState.user.user.has_verified_email; - const preferenceKey = syncEnabled && hasVerifiedEmail ? 'shared' : 'local'; - const shared = {}; + const nextState: { user: any, settings: any } = getState(); + const syncEnabled = + nextState.settings && + nextState.settings.clientSettings && + nextState.settings.clientSettings.enable_sync; + const hasVerifiedEmail = + nextState.user && nextState.user.user && nextState.user.user.has_verified_email; + const preferenceKey = syncEnabled && hasVerifiedEmail ? 'shared' : 'local'; + const shared = {}; - Object.keys(sharedStateFilters).forEach(key => { - const filter = sharedStateFilters[key]; - const { source, property, transform } = filter; - let value = nextState[source][property]; - if (transform) { - value = transform(value); - } - - shared[key] = value; - }); - - if (!isEqual(oldShared, shared)) { - // only update if the preference changed from last call in the same session - oldShared = shared; - dispatch(doPreferenceSet(preferenceKey, shared, SHARED_PREFERENCE_VERSION)); + Object.keys(sharedStateFilters).forEach(key => { + const filter = sharedStateFilters[key]; + const { source, property, transform } = filter; + let value = nextState[source][property]; + if (transform) { + value = transform(value); } - if (sharedStateCb) { - // Pass dispatch to the callback to consumers can dispatch actions in response to preference set - sharedStateCb({ dispatch, getState }); - } - clearTimeout(timeout); - return actionResult; + shared[key] = value; + }); + + if (!isEqual(oldShared, shared)) { + // only update if the preference changed from last call in the same session + oldShared = shared; + dispatch(doPreferenceSet(preferenceKey, shared, SHARED_PREFERENCE_VERSION)); } - timeout = setTimeout(runPreferences, RUN_PREFERENCES_DELAY_MS); + + if (sharedStateCb) { + // Pass dispatch to the callback to consumers can dispatch actions in response to preference set + sharedStateCb({ dispatch, getState }); + } + + return actionResult; }; diff --git a/src/redux/reducers/claims.js b/src/redux/reducers/claims.js index 410e032..1b77d3a 100644 --- a/src/redux/reducers/claims.js +++ b/src/redux/reducers/claims.js @@ -13,20 +13,17 @@ import mergeClaim from 'util/merge-claim'; type State = { createChannelError: ?string, - createCollectionError: ?string, channelClaimCounts: { [string]: number }, claimsByUri: { [string]: string }, byId: { [string]: Claim }, - pendingById: { [string]: Claim }, // keep pending claims resolvingUris: Array<string>, + pendingIds: Array<string>, reflectingById: { [string]: ReflectingUpdate }, myClaims: ?Array<string>, myChannelClaims: ?Array<string>, - myCollectionClaims: ?Array<string>, abandoningById: { [string]: boolean }, fetchingChannelClaims: { [string]: number }, fetchingMyChannels: boolean, - fetchingMyCollections: boolean, fetchingClaimSearchByQuery: { [string]: boolean }, purchaseUriSuccess: boolean, myPurchases: ?Array<string>, @@ -37,7 +34,6 @@ type State = { claimSearchByQuery: { [string]: Array<string> }, claimSearchByQueryLastPageReached: { [string]: Array<boolean> }, creatingChannel: boolean, - creatingCollection: boolean, paginatedClaimsByChannel: { [string]: { all: Array<string>, @@ -47,9 +43,7 @@ type State = { }, }, updateChannelError: ?string, - updateCollectionError: ?string, updatingChannel: boolean, - updatingCollection: boolean, pendingChannelImport: string | boolean, repostLoading: boolean, repostError: ?string, @@ -72,7 +66,6 @@ const defaultState = { fetchingChannelClaims: {}, resolvingUris: [], myChannelClaims: undefined, - myCollectionClaims: [], myClaims: undefined, myPurchases: undefined, myPurchasesPageNumber: undefined, @@ -81,22 +74,17 @@ const defaultState = { fetchingMyPurchases: false, fetchingMyPurchasesError: undefined, fetchingMyChannels: false, - fetchingMyCollections: false, abandoningById: {}, - pendingById: {}, + pendingIds: [], reflectingById: {}, claimSearchError: false, claimSearchByQuery: {}, claimSearchByQueryLastPageReached: {}, fetchingClaimSearchByQuery: {}, updateChannelError: '', - updateCollectionError: '', updatingChannel: false, creatingChannel: false, createChannelError: undefined, - updatingCollection: false, - creatingCollection: false, - createCollectionError: undefined, pendingChannelImport: false, repostLoading: false, repostError: undefined, @@ -112,22 +100,30 @@ const defaultState = { }; function handleClaimAction(state: State, action: any): State { - const { resolveInfo }: ClaimActionResolveInfo = action.data; + const { + resolveInfo, + }: { + [string]: { + stream: ?StreamClaim, + channel: ?ChannelClaim, + claimsInChannel: ?number, + }, + } = action.data; const byUri = Object.assign({}, state.claimsByUri); const byId = Object.assign({}, state.byId); const channelClaimCounts = Object.assign({}, state.channelClaimCounts); - const pendingById = state.pendingById; + const pendingIds = state.pendingIds; let newResolvingUrls = new Set(state.resolvingUris); let myClaimIds = new Set(state.myClaims); Object.entries(resolveInfo).forEach(([url: string, resolveResponse: ResolveResponse]) => { // $FlowFixMe - const { claimsInChannel, stream, channel: channelFromResolve, collection } = resolveResponse; + const { claimsInChannel, stream, channel: channelFromResolve } = resolveResponse; const channel = channelFromResolve || (stream && stream.signing_channel); if (stream) { - if (pendingById[stream.claim_id]) { + if (pendingIds.includes(stream.claim_id)) { byId[stream.claim_id] = mergeClaim(stream, byId[stream.claim_id]); } else { byId[stream.claim_id] = stream; @@ -157,37 +153,20 @@ function handleClaimAction(state: State, action: any): State { channelClaimCounts[channel.canonical_url] = claimsInChannel; } - if (pendingById[channel.claim_id]) { + if (pendingIds.includes(channel.claim_id)) { byId[channel.claim_id] = mergeClaim(channel, byId[channel.claim_id]); } else { byId[channel.claim_id] = channel; } - + // Also add the permanent_url here until lighthouse returns canonical_url for search results byUri[channel.permanent_url] = channel.claim_id; byUri[channel.canonical_url] = channel.claim_id; newResolvingUrls.delete(channel.canonical_url); newResolvingUrls.delete(channel.permanent_url); } - if (collection) { - if (pendingById[collection.claim_id]) { - byId[collection.claim_id] = mergeClaim(collection, byId[collection.claim_id]); - } else { - byId[collection.claim_id] = collection; - } - byUri[url] = collection.claim_id; - byUri[collection.canonical_url] = collection.claim_id; - byUri[collection.permanent_url] = collection.claim_id; - newResolvingUrls.delete(collection.canonical_url); - newResolvingUrls.delete(collection.permanent_url); - - if (collection.is_my_output) { - myClaimIds.add(collection.claim_id); - } - } - newResolvingUrls.delete(url); - if (!stream && !channel && !collection && !pendingById[byUri[url]]) { + if (!stream && !channel && !pendingIds.includes(byUri[url])) { byUri[url] = null; } }); @@ -230,33 +209,34 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_STARTED] = (state: State): State => }); reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any): State => { - const { result }: { result: ClaimListResponse } = action.data; + const { result, resolve }: { result: ClaimListResponse, resolve: boolean } = action.data; const claims = result.items; const page = result.page; const totalItems = result.total_items; const byId = Object.assign({}, state.byId); const byUri = Object.assign({}, state.claimsByUri); - const pendingById = Object.assign({}, state.pendingById); + const pendingIds = state.pendingIds || []; let myClaimIds = new Set(state.myClaims); let urlsForCurrentPage = []; + const pendingIdSet = new Set(pendingIds); + claims.forEach((claim: Claim) => { - const { permanent_url: permanentUri, claim_id: claimId, canonical_url: canonicalUri } = claim; + const { permanent_url: permanentUri, claim_id: claimId } = claim; if (claim.type && claim.type.match(/claim|update/)) { urlsForCurrentPage.push(permanentUri); if (claim.confirmations < 1) { - pendingById[claimId] = claim; - if (byId[claimId]) { - byId[claimId] = mergeClaim(claim, byId[claimId]); - } else { - byId[claimId] = claim; - } + pendingIdSet.add(claimId); + } else if (!resolve && pendingIdSet.has(claimId) && claim.confirmations > 0) { + pendingIdSet.delete(claimId); + } + if (pendingIds.includes(claimId)) { + byId[claimId] = mergeClaim(claim, byId[claimId]); } else { byId[claimId] = claim; } byUri[permanentUri] = claimId; - byUri[canonicalUri] = claimId; myClaimIds.add(claimId); } }); @@ -265,7 +245,7 @@ reducers[ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED] = (state: State, action: any): isFetchingClaimListMine: false, myClaims: Array.from(myClaimIds), byId, - pendingById, + pendingIds: Array.from(pendingIdSet), claimsByUri: byUri, myClaimsPageResults: urlsForCurrentPage, myClaimsPageNumber: page, @@ -278,8 +258,9 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_STARTED] = (state: State): State => reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): State => { const { claims }: { claims: Array<ChannelClaim> } = action.data; + const myClaims = state.myClaims || []; let myClaimIds = new Set(state.myClaims); - const pendingById = Object.assign({}, state.pendingById); + const pendingIds = state.pendingIds || []; let myChannelClaims; const byId = Object.assign({}, state.byId); const byUri = Object.assign({}, state.claimsByUri); @@ -293,12 +274,7 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St claims.forEach(claim => { const { meta } = claim; const { claims_in_channel: claimsInChannel } = claim.meta; - const { - canonical_url: canonicalUrl, - permanent_url: permanentUrl, - claim_id: claimId, - confirmations, - } = claim; + const { canonical_url: canonicalUrl, permanent_url: permanentUrl, claim_id: claimId } = claim; byUri[canonicalUrl] = claimId; byUri[permanentUrl] = claimId; @@ -307,14 +283,7 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St // $FlowFixMe myChannelClaims.add(claimId); - if (confirmations < 1) { - pendingById[claimId] = claim; - if (byId[claimId]) { - byId[claimId] = mergeClaim(claim, byId[claimId]); - } else { - byId[claimId] = claim; - } - } else { + if (!pendingIds.some(c => c === claimId)) { byId[claimId] = claim; } myClaimIds.add(claimId); @@ -323,7 +292,6 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_COMPLETED] = (state: State, action: any): St return Object.assign({}, state, { byId, - pendingById, claimsByUri: byUri, channelClaimCounts, fetchingMyChannels: false, @@ -338,66 +306,6 @@ reducers[ACTIONS.FETCH_CHANNEL_LIST_FAILED] = (state: State, action: any): State }); }; -reducers[ACTIONS.FETCH_COLLECTION_LIST_STARTED] = (state: State): State => ({ - ...state, - fetchingMyCollections: true, -}); - -reducers[ACTIONS.FETCH_COLLECTION_LIST_COMPLETED] = (state: State, action: any): State => { - const { claims }: { claims: Array<CollectionClaim> } = action.data; - const myClaims = state.myClaims || []; - let myClaimIds = new Set(myClaims); - const pendingById = Object.assign({}, state.pendingById); - let myCollectionClaimsSet = new Set([]); - const byId = Object.assign({}, state.byId); - const byUri = Object.assign({}, state.claimsByUri); - - if (claims.length) { - myCollectionClaimsSet = new Set(state.myCollectionClaims); - claims.forEach(claim => { - const { meta } = claim; - const { - canonical_url: canonicalUrl, - permanent_url: permanentUrl, - claim_id: claimId, - confirmations, - } = claim; - - byUri[canonicalUrl] = claimId; - byUri[permanentUrl] = claimId; - - // $FlowFixMe - myCollectionClaimsSet.add(claimId); - // we don't want to overwrite a pending result with a resolve - if (confirmations < 1) { - pendingById[claimId] = claim; - if (byId[claimId]) { - byId[claimId] = mergeClaim(claim, byId[claimId]); - } else { - byId[claimId] = claim; - } - } else { - byId[claimId] = claim; - } - myClaimIds.add(claimId); - }); - } - - return { - ...state, - byId, - pendingById, - claimsByUri: byUri, - fetchingMyCollections: false, - myCollectionClaims: Array.from(myCollectionClaimsSet), - myClaims: myClaimIds ? Array.from(myClaimIds) : null, - }; -}; - -reducers[ACTIONS.FETCH_COLLECTION_LIST_FAILED] = (state: State): State => { - return { ...state, fetchingMyCollections: false }; -}; - reducers[ACTIONS.FETCH_CHANNEL_CLAIMS_STARTED] = (state: State, action: any): State => { const { uri, page } = action.data; const fetchingChannelClaims = Object.assign({}, state.fetchingChannelClaims); @@ -479,8 +387,9 @@ reducers[ACTIONS.ABANDON_CLAIM_STARTED] = (state: State, action: any): State => reducers[ACTIONS.UPDATE_PENDING_CLAIMS] = (state: State, action: any): State => { const { claims: pendingClaims }: { claims: Array<Claim> } = action.data; const byId = Object.assign({}, state.byId); - const pendingById = Object.assign({}, state.pendingById); const byUri = Object.assign({}, state.claimsByUri); + const pendingIds = state.pendingIds; + const pendingIdSet = new Set(pendingIds); let myClaimIds = new Set(state.myClaims); const myChannelClaims = new Set(state.myChannelClaims); @@ -488,7 +397,7 @@ reducers[ACTIONS.UPDATE_PENDING_CLAIMS] = (state: State, action: any): State => pendingClaims.forEach((claim: Claim) => { let newClaim; const { permanent_url: uri, claim_id: claimId, type, value_type: valueType } = claim; - pendingById[claimId] = claim; // make sure we don't need to merge? + pendingIdSet.add(claimId); const oldClaim = byId[claimId]; if (oldClaim && oldClaim.canonical_url) { newClaim = mergeClaim(oldClaim, claim); @@ -508,22 +417,21 @@ reducers[ACTIONS.UPDATE_PENDING_CLAIMS] = (state: State, action: any): State => return Object.assign({}, state, { myClaims: Array.from(myClaimIds), byId, - pendingById, myChannelClaims: Array.from(myChannelClaims), claimsByUri: byUri, + pendingIds: Array.from(pendingIdSet), }); }; reducers[ACTIONS.UPDATE_CONFIRMED_CLAIMS] = (state: State, action: any): State => { - const { - claims: confirmedClaims, - pending: pendingClaims, - }: { claims: Array<Claim>, pending: { [string]: Claim } } = action.data; + const { claims: confirmedClaims }: { claims: Array<Claim> } = action.data; const byId = Object.assign({}, state.byId); const byUri = Object.assign({}, state.claimsByUri); - // + const pendingIds = state.pendingIds; + const pendingIdSet = new Set(pendingIds); + confirmedClaims.forEach((claim: GenericClaim) => { - const { claim_id: claimId, type } = claim; + const { permanent_url: permanentUri, claim_id: claimId, type } = claim; let newClaim = claim; const oldClaim = byId[claimId]; if (oldClaim && oldClaim.canonical_url) { @@ -531,10 +439,11 @@ reducers[ACTIONS.UPDATE_CONFIRMED_CLAIMS] = (state: State, action: any): State = } if (type && type.match(/claim|update|channel/)) { byId[claimId] = newClaim; + pendingIdSet.delete(claimId); } }); return Object.assign({}, state, { - pendingById: pendingClaims, + pendingIds: Array.from(pendingIdSet), byId, claimsByUri: byUri, }); @@ -546,7 +455,6 @@ reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = (state: State, action: any): State = const newMyClaims = state.myClaims ? state.myClaims.slice() : []; const newMyChannelClaims = state.myChannelClaims ? state.myChannelClaims.slice() : []; const claimsByUri = Object.assign({}, state.claimsByUri); - const newMyCollectionClaims = state.myCollectionClaims ? state.myCollectionClaims.slice() : []; Object.keys(claimsByUri).forEach(uri => { if (claimsByUri[uri] === claimId) { @@ -555,14 +463,12 @@ reducers[ACTIONS.ABANDON_CLAIM_SUCCEEDED] = (state: State, action: any): State = }); const myClaims = newMyClaims.filter(i => i !== claimId); const myChannelClaims = newMyChannelClaims.filter(i => i !== claimId); - const myCollectionClaims = newMyCollectionClaims.filter(i => i !== claimId); delete byId[claimId]; return Object.assign({}, state, { myClaims, myChannelClaims, - myCollectionClaims, byId, claimsByUri, }); @@ -614,61 +520,6 @@ reducers[ACTIONS.UPDATE_CHANNEL_FAILED] = (state: State, action: any): State => }); }; -reducers[ACTIONS.CLEAR_COLLECTION_ERRORS] = (state: State): State => ({ - ...state, - createCollectionError: null, - updateCollectionError: null, -}); - -reducers[ACTIONS.COLLECTION_PUBLISH_STARTED] = (state: State): State => ({ - ...state, - creatingCollection: true, - createCollectionError: null, -}); - -reducers[ACTIONS.COLLECTION_PUBLISH_COMPLETED] = (state: State, action: any): State => { - const myCollections = state.myCollectionClaims || []; - const myClaims = state.myClaims || []; - const { claimId } = action.data; - let myClaimIds = new Set(myClaims); - let myCollectionClaimsSet = new Set(myCollections); - myClaimIds.add(claimId); - myCollectionClaimsSet.add(claimId); - return Object.assign({}, state, { - creatingCollection: false, - myClaims: Array.from(myClaimIds), - myCollectionClaims: Array.from(myCollectionClaimsSet), - }); -}; - -reducers[ACTIONS.COLLECTION_PUBLISH_FAILED] = (state: State, action: any): State => { - return Object.assign({}, state, { - creatingCollection: false, - createCollectionError: action.data.error, - }); -}; - -reducers[ACTIONS.COLLECTION_PUBLISH_UPDATE_STARTED] = (state: State, action: any): State => { - return Object.assign({}, state, { - updateCollectionError: '', - updatingCollection: true, - }); -}; - -reducers[ACTIONS.COLLECTION_PUBLISH_UPDATE_COMPLETED] = (state: State, action: any): State => { - return Object.assign({}, state, { - updateCollectionError: '', - updatingCollection: false, - }); -}; - -reducers[ACTIONS.COLLECTION_PUBLISH_UPDATE_FAILED] = (state: State, action: any): State => { - return Object.assign({}, state, { - updateCollectionError: action.data.error, - updatingCollection: false, - }); -}; - reducers[ACTIONS.IMPORT_CHANNEL_STARTED] = (state: State): State => Object.assign({}, state, { pendingChannelImports: true }); diff --git a/src/redux/reducers/collections.js b/src/redux/reducers/collections.js deleted file mode 100644 index 39aac44..0000000 --- a/src/redux/reducers/collections.js +++ /dev/null @@ -1,239 +0,0 @@ -// @flow -import { handleActions } from 'util/redux-utils'; -import * as ACTIONS from 'constants/action_types'; -import * as COLS from 'constants/collections'; - -const getTimestamp = () => { - return Math.floor(Date.now() / 1000); -}; - -const defaultState: CollectionState = { - builtin: { - watchlater: { - items: [], - id: COLS.WATCH_LATER_ID, - name: 'Watch Later', - updatedAt: getTimestamp(), - type: COLS.COL_TYPE_PLAYLIST, - }, - favorites: { - items: [], - id: COLS.FAVORITES_ID, - name: 'Favorites', - type: COLS.COL_TYPE_PLAYLIST, - updatedAt: getTimestamp(), - }, - }, - resolved: {}, - unpublished: {}, // sync - edited: {}, - pending: {}, - saved: [], - isResolvingCollectionById: {}, - error: null, -}; - -const collectionsReducer = handleActions( - { - [ACTIONS.COLLECTION_NEW]: (state, action) => { - const { entry: params } = action.data; // { id:, items: Array<string>} - // entry - const newListTemplate = { - id: params.id, - name: params.name, - items: [], - updatedAt: getTimestamp(), - type: params.type, - }; - - const newList = Object.assign({}, newListTemplate, { ...params }); - const { unpublished: lists } = state; - const newLists = Object.assign({}, lists, { [params.id]: newList }); - - return { - ...state, - unpublished: newLists, - }; - }, - - [ACTIONS.COLLECTION_DELETE]: (state, action) => { - const { id, collectionKey } = action.data; - const { edited: editList, unpublished: unpublishedList, pending: pendingList } = state; - const newEditList = Object.assign({}, editList); - const newUnpublishedList = Object.assign({}, unpublishedList); - - const newPendingList = Object.assign({}, pendingList); - - if (collectionKey && state[collectionKey] && state[collectionKey][id]) { - const newList = Object.assign({}, state[collectionKey]); - delete newList[id]; - return { - ...state, - [collectionKey]: newList, - }; - } else { - if (newEditList[id]) { - delete newEditList[id]; - } else if (newUnpublishedList[id]) { - delete newUnpublishedList[id]; - } else if (newPendingList[id]) { - delete newPendingList[id]; - } - } - return { - ...state, - edited: newEditList, - unpublished: newUnpublishedList, - pending: newPendingList, - }; - }, - - [ACTIONS.COLLECTION_PENDING]: (state, action) => { - const { localId, claimId } = action.data; - const { - resolved: resolvedList, - edited: editList, - unpublished: unpublishedList, - pending: pendingList, - } = state; - - const newEditList = Object.assign({}, editList); - const newResolvedList = Object.assign({}, resolvedList); - const newUnpublishedList = Object.assign({}, unpublishedList); - const newPendingList = Object.assign({}, pendingList); - - if (localId) { - // new publish - newPendingList[claimId] = Object.assign({}, newUnpublishedList[localId] || {}); - delete newUnpublishedList[localId]; - } else { - // edit update - newPendingList[claimId] = Object.assign( - {}, - newEditList[claimId] || newResolvedList[claimId] - ); - delete newEditList[claimId]; - } - - return { - ...state, - edited: newEditList, - unpublished: newUnpublishedList, - pending: newPendingList, - }; - }, - - [ACTIONS.COLLECTION_EDIT]: (state, action) => { - const { id, collectionKey, collection } = action.data; - - if (COLS.BUILTIN_LISTS.includes(id)) { - const { builtin: lists } = state; - return { - ...state, - [collectionKey]: { ...lists, [id]: collection }, - }; - } - - if (collectionKey === 'edited') { - const { edited: lists } = state; - return { - ...state, - edited: { ...lists, [id]: collection }, - }; - } - const { unpublished: lists } = state; - return { - ...state, - unpublished: { ...lists, [id]: collection }, - }; - }, - - [ACTIONS.COLLECTION_ERROR]: (state, action) => { - return Object.assign({}, state, { - error: action.data.message, - }); - }, - - [ACTIONS.COLLECTION_ITEMS_RESOLVE_STARTED]: (state, action) => { - const { ids } = action.data; - const { isResolvingCollectionById } = state; - const newResolving = Object.assign({}, isResolvingCollectionById); - ids.forEach(id => { - newResolving[id] = true; - }); - return Object.assign({}, state, { - ...state, - error: '', - isResolvingCollectionById: newResolving, - }); - }, - [ACTIONS.USER_STATE_POPULATE]: (state, action) => { - const { - builtinCollections, - savedCollections, - unpublishedCollections, - editedCollections, - } = action.data; - return { - ...state, - edited: editedCollections || state.edited, - unpublished: unpublishedCollections || state.unpublished, - builtin: builtinCollections || state.builtin, - saved: savedCollections || state.saved, - }; - }, - [ACTIONS.COLLECTION_ITEMS_RESOLVE_COMPLETED]: (state, action) => { - const { resolvedCollections, failedCollectionIds } = action.data; - const { pending, edited, isResolvingCollectionById, resolved } = state; - const newPending = Object.assign({}, pending); - const newEdited = Object.assign({}, edited); - const newResolved = Object.assign({}, resolved, resolvedCollections); - - const resolvedIds = Object.keys(resolvedCollections); - const newResolving = Object.assign({}, isResolvingCollectionById); - if (resolvedCollections && Object.keys(resolvedCollections).length) { - resolvedIds.forEach(resolvedId => { - if (newEdited[resolvedId]) { - if (newEdited[resolvedId]['updatedAt'] < resolvedCollections[resolvedId]['updatedAt']) { - delete newEdited[resolvedId]; - } - } - delete newResolving[resolvedId]; - if (newPending[resolvedId]) { - delete newPending[resolvedId]; - } - }); - } - - if (failedCollectionIds && Object.keys(failedCollectionIds).length) { - failedCollectionIds.forEach(failedId => { - delete newResolving[failedId]; - }); - } - - return Object.assign({}, state, { - ...state, - pending: newPending, - resolved: newResolved, - edited: newEdited, - isResolvingCollectionById: newResolving, - }); - }, - [ACTIONS.COLLECTION_ITEMS_RESOLVE_FAILED]: (state, action) => { - const { ids } = action.data; - const { isResolvingCollectionById } = state; - const newResolving = Object.assign({}, isResolvingCollectionById); - ids.forEach(id => { - delete newResolving[id]; - }); - return Object.assign({}, state, { - ...state, - isResolvingCollectionById: newResolving, - error: action.data.message, - }); - }, - }, - defaultState -); - -export { collectionsReducer }; diff --git a/src/redux/reducers/publish.js b/src/redux/reducers/publish.js index 794c43d..e89564d 100644 --- a/src/redux/reducers/publish.js +++ b/src/redux/reducers/publish.js @@ -22,11 +22,9 @@ type PublishState = { thumbnail_url: string, thumbnailPath: string, uploadThumbnailStatus: string, - thumbnailError: ?boolean, description: string, language: string, - releaseTime: ?number, - releaseTimeEdited: ?number, + releaseTime: ?string, channel: string, channelId: ?string, name: string, @@ -57,11 +55,9 @@ const defaultState: PublishState = { thumbnail_url: '', thumbnailPath: '', uploadThumbnailStatus: THUMBNAIL_STATUSES.API_DOWN, - thumbnailError: undefined, description: '', language: '', releaseTime: undefined, - releaseTimeEdited: undefined, nsfw: false, channel: CHANNEL_ANONYMOUS, channelId: '', diff --git a/src/redux/selectors/claims.js b/src/redux/selectors/claims.js index f5a03ed..d7b151d 100644 --- a/src/redux/selectors/claims.js +++ b/src/redux/selectors/claims.js @@ -1,5 +1,5 @@ // @flow -import { normalizeURI, parseURI } from 'lbryURI'; +import { normalizeURI, buildURI, parseURI } from 'lbryURI'; import { selectSupportsByOutpoint } from 'redux/selectors/wallet'; import { createSelector } from 'reselect'; import { isClaimNsfw, filterClaims } from 'util/claim'; @@ -7,24 +7,11 @@ import * as CLAIM from 'constants/claim'; const selectState = state => state.claims || {}; -export const selectById = createSelector( +export const selectClaimsById = createSelector( selectState, state => state.byId || {} ); -export const selectPendingClaimsById = createSelector( - selectState, - state => state.pendingById || {} -); - -export const selectClaimsById = createSelector( - selectById, - selectPendingClaimsById, - (byId, pendingById) => { - return Object.assign(byId, pendingById); // do I need merged to keep metadata? - } -); - export const selectClaimIdsByUri = createSelector( selectState, state => state.claimsByUri || {} @@ -85,42 +72,29 @@ export const selectAllClaimsByChannel = createSelector( export const selectPendingIds = createSelector( selectState, - state => Object.keys(state.pendingById) || [] + state => state.pendingIds || [] ); export const selectPendingClaims = createSelector( - selectPendingClaimsById, - pendingById => Object.values(pendingById) + selectPendingIds, + selectClaimsById, + (pendingIds, byId) => pendingIds.map(id => byId[id]) ); export const makeSelectClaimIsPending = (uri: string) => createSelector( selectClaimIdsByUri, - selectPendingClaimsById, - (idsByUri, pendingById) => { + selectPendingIds, + (idsByUri, pendingIds) => { const claimId = idsByUri[normalizeURI(uri)]; if (claimId) { - return Boolean(pendingById[claimId]); + return pendingIds.some(i => i === claimId); } return false; } ); -export const makeSelectClaimIdIsPending = (claimId: string) => - createSelector( - selectPendingClaimsById, - pendingById => { - return Boolean(pendingById[claimId]); - } - ); - -export const makeSelectClaimIdForUri = (uri: string) => - createSelector( - selectClaimIdsByUri, - claimIds => claimIds[uri] - ); - export const selectReflectingById = createSelector( selectState, state => state.reflectingById @@ -165,7 +139,7 @@ export const makeSelectClaimForUri = (uri: string, returnRepost: boolean = true) return { ...repostedClaim, - repost_url: normalizeURI(uri), + repost_url: uri, repost_channel_url: channelUrl, repost_bid_amount: claim && claim.meta && claim.meta.effective_amount, }; @@ -299,8 +273,8 @@ export const makeSelectMyPurchasesForPage = (query: ?string, page: number = 1) = const end = Number(page) * Number(CLAIM.PAGE_SIZE); return matchingFileInfos && matchingFileInfos.length ? matchingFileInfos - .slice(start, end) - .map(fileInfo => fileInfo.canonical_url || fileInfo.permanent_url) + .slice(start, end) + .map(fileInfo => fileInfo.canonical_url || fileInfo.permanent_url) : []; } ); @@ -338,7 +312,6 @@ export const makeSelectClaimsInChannelForPage = (uri: string, page?: number) => } ); -// THIS IS LEFT OVER FROM ONE TAB CHANNEL_CONTENT export const makeSelectTotalClaimsInChannelSearch = (uri: string) => createSelector( selectClaimsById, @@ -349,7 +322,6 @@ export const makeSelectTotalClaimsInChannelSearch = (uri: string) => } ); -// THIS IS LEFT OVER FROM ONE_TAB CHANNEL CONTENT export const makeSelectTotalPagesInChannelSearch = (uri: string) => createSelector( selectClaimsById, @@ -360,6 +332,21 @@ export const makeSelectTotalPagesInChannelSearch = (uri: string) => } ); +export const makeSelectClaimsInChannelForCurrentPageState = (uri: string) => + createSelector( + selectClaimsById, + selectAllClaimsByChannel, + selectCurrentChannelPage, + (byId, allClaims, page) => { + const byChannel = allClaims[uri] || {}; + const claimIds = byChannel[page || 1]; + + if (!claimIds) return claimIds; + + return claimIds.map(claimId => byId[claimId]); + } + ); + export const makeSelectMetadataForUri = (uri: string) => createSelector( makeSelectClaimForUri(uri), @@ -393,8 +380,8 @@ export const makeSelectDateForUri = (uri: string) => (claim.value.release_time ? claim.value.release_time * 1000 : claim.meta && claim.meta.creation_timestamp - ? claim.meta.creation_timestamp * 1000 - : null); + ? claim.meta.creation_timestamp * 1000 + : null); if (!timestamp) { return undefined; } @@ -500,9 +487,7 @@ export const selectMyClaims = createSelector( export const selectMyClaimsWithoutChannels = createSelector( selectMyClaims, myClaims => - myClaims - .filter(claim => claim && !claim.name.match(/^@/)) - .sort((a, b) => a.timestamp - b.timestamp) + myClaims.filter(claim => !claim.name.match(/^@/)).sort((a, b) => a.timestamp - b.timestamp) ); export const selectMyClaimUrisWithoutChannels = createSelector( @@ -546,11 +531,6 @@ export const selectFetchingMyChannels = createSelector( state => state.fetchingMyChannels ); -export const selectFetchingMyCollections = createSelector( - selectState, - state => state.fetchingMyCollections -); - export const selectMyChannelClaims = createSelector( selectState, selectClaimsById, @@ -577,11 +557,6 @@ export const selectMyChannelUrls = createSelector( claims => (claims ? claims.map(claim => claim.canonical_url || claim.permanent_url) : undefined) ); -export const selectMyCollectionIds = createSelector( - selectState, - state => state.myCollectionClaims -); - export const selectResolvingUris = createSelector( selectState, state => state.resolvingUris || [] @@ -610,18 +585,31 @@ export const selectChannelClaimCounts = createSelector( export const makeSelectPendingClaimForUri = (uri: string) => createSelector( - selectPendingClaimsById, - pendingById => { + selectPendingIds, + selectClaimsById, + (pending, claims) => { + let validUri; + let uriIsChannel; let uriStreamName; let uriChannelName; try { - ({ streamName: uriStreamName, channelName: uriChannelName } = parseURI(uri)); + ({ + isChannel: uriIsChannel, + streamName: uriStreamName, + channelName: uriChannelName, + } = parseURI(uri)); + validUri = true; } catch (e) { return null; } - const pendingClaims = (Object.values(pendingById): any); - const matchingClaim = pendingClaims.find((claim: GenericClaim) => { - return claim.normalized_name === uriChannelName || claim.normalized_name === uriStreamName; + const pendingClaims = pending.map(id => claims[id]); + const matchingClaim = pendingClaims.find(claim => { + const { streamName, channelName, isChannel } = parseURI(claim.permanent_url); + if (isChannel) { + return channelName === uriChannelName; + } else { + return streamName === uriStreamName; + } }); return matchingClaim || null; } @@ -630,13 +618,13 @@ export const makeSelectPendingClaimForUri = (uri: string) => export const makeSelectTotalItemsForChannel = (uri: string) => createSelector( selectChannelClaimCounts, - byUri => byUri && byUri[normalizeURI(uri)] + byUri => byUri && byUri[uri] ); export const makeSelectTotalPagesForChannel = (uri: string, pageSize: number = 10) => createSelector( selectChannelClaimCounts, - byUri => byUri && byUri[uri] && Math.ceil(byUri[normalizeURI(uri)] / pageSize) + byUri => byUri && byUri[uri] && Math.ceil(byUri[uri] / pageSize) ); export const makeSelectNsfwCountFromUris = (uris: Array<string>) => @@ -652,6 +640,27 @@ export const makeSelectNsfwCountFromUris = (uris: Array<string>) => }, 0) ); +export const makeSelectNsfwCountForChannel = (uri: string) => + createSelector( + selectClaimsById, + selectAllClaimsByChannel, + selectCurrentChannelPage, + (byId, allClaims, page) => { + const byChannel = allClaims[uri] || {}; + const claimIds = byChannel[page || 1]; + + if (!claimIds) return 0; + + return claimIds.reduce((acc, claimId) => { + const claim = byId[claimId]; + if (isClaimNsfw(claim)) { + return acc + 1; + } + return acc; + }, 0); + } + ); + export const makeSelectOmittedCountForChannel = (uri: string) => createSelector( makeSelectTotalItemsForChannel(uri), @@ -731,6 +740,14 @@ export const makeSelectTagsForUri = (uri: string) => } ); +export const makeSelectChannelTagsForUri = (uri: string) => + createSelector( + makeSelectMetadataForUri(uri), + (metadata: ?GenericMetadata) => { + return (metadata && metadata.tags) || []; + } + ); + export const selectFetchingClaimSearchByQuery = createSelector( selectState, state => state.fetchingClaimSearchByQuery || {} @@ -900,23 +917,3 @@ export const makeSelectStakedLevelForChannelUri = (uri: string) => return level; } ); - -export const selectUpdatingCollection = createSelector( - selectState, - state => state.updatingCollection -); - -export const selectUpdateCollectionError = createSelector( - selectState, - state => state.updateCollectionError -); - -export const selectCreatingCollection = createSelector( - selectState, - state => state.creatingCollection -); - -export const selectCreateCollectionError = createSelector( - selectState, - state => state.createCollectionError -); diff --git a/src/redux/selectors/collections.js b/src/redux/selectors/collections.js deleted file mode 100644 index 0970688..0000000 --- a/src/redux/selectors/collections.js +++ /dev/null @@ -1,311 +0,0 @@ -// @flow -import fromEntries from '@ungap/from-entries'; -import { createSelector } from 'reselect'; -import { - selectMyCollectionIds, - makeSelectClaimForUri, - selectClaimsByUri, -} from 'redux/selectors/claims'; -import { parseURI } from 'lbryURI'; - -const selectState = (state: { collections: CollectionState }) => state.collections; - -export const selectSavedCollectionIds = createSelector( - selectState, - collectionState => collectionState.saved -); - -export const selectBuiltinCollections = createSelector( - selectState, - state => state.builtin -); -export const selectResolvedCollections = createSelector( - selectState, - state => state.resolved -); - -export const selectMyUnpublishedCollections = createSelector( - selectState, - state => state.unpublished -); - -export const selectMyEditedCollections = createSelector( - selectState, - state => state.edited -); - -export const selectPendingCollections = createSelector( - selectState, - state => state.pending -); - -export const makeSelectEditedCollectionForId = (id: string) => - createSelector( - selectMyEditedCollections, - eLists => eLists[id] - ); - -export const makeSelectPendingCollectionForId = (id: string) => - createSelector( - selectPendingCollections, - pending => pending[id] - ); - -export const makeSelectPublishedCollectionForId = (id: string) => - createSelector( - selectResolvedCollections, - rLists => rLists[id] - ); - -export const makeSelectUnpublishedCollectionForId = (id: string) => - createSelector( - selectMyUnpublishedCollections, - rLists => rLists[id] - ); - -export const makeSelectCollectionIsMine = (id: string) => - createSelector( - selectMyCollectionIds, - selectMyUnpublishedCollections, - selectBuiltinCollections, - (publicIds, privateIds, builtinIds) => { - return Boolean(publicIds.includes(id) || privateIds[id] || builtinIds[id]); - } - ); - -export const selectMyPublishedCollections = createSelector( - selectResolvedCollections, - selectPendingCollections, - selectMyEditedCollections, - selectMyCollectionIds, - (resolved, pending, edited, myIds) => { - // all resolved in myIds, plus those in pending and edited - const myPublishedCollections = fromEntries( - Object.entries(pending).concat( - Object.entries(resolved).filter( - ([key, val]) => - myIds.includes(key) && - // $FlowFixMe - !pending[key] - ) - ) - ); - // now add in edited: - Object.entries(edited).forEach(([id, item]) => { - myPublishedCollections[id] = item; - }); - return myPublishedCollections; - } -); - -export const selectMyPublishedMixedCollections = createSelector( - selectMyPublishedCollections, - published => { - const myCollections = fromEntries( - // $FlowFixMe - Object.entries(published).filter(([key, collection]) => { - // $FlowFixMe - return collection.type === 'collection'; - }) - ); - return myCollections; - } -); - -export const selectMyPublishedPlaylistCollections = createSelector( - selectMyPublishedCollections, - published => { - const myCollections = fromEntries( - // $FlowFixMe - Object.entries(published).filter(([key, collection]) => { - // $FlowFixMe - return collection.type === 'playlist'; - }) - ); - return myCollections; - } -); - -export const makeSelectMyPublishedCollectionForId = (id: string) => - createSelector( - selectMyPublishedCollections, - myPublishedCollections => myPublishedCollections[id] - ); - -// export const selectSavedCollections = createSelector( -// selectResolvedCollections, -// selectSavedCollectionIds, -// (resolved, myIds) => { -// const mySavedCollections = fromEntries( -// Object.entries(resolved).filter(([key, val]) => myIds.includes(key)) -// ); -// return mySavedCollections; -// } -// ); - -export const makeSelectIsResolvingCollectionForId = (id: string) => - createSelector( - selectState, - state => { - return state.isResolvingCollectionById[id]; - } - ); - -export const makeSelectCollectionForId = (id: string) => - createSelector( - selectBuiltinCollections, - selectResolvedCollections, - selectMyUnpublishedCollections, - selectMyEditedCollections, - selectPendingCollections, - (bLists, rLists, uLists, eLists, pLists) => { - const collection = bLists[id] || uLists[id] || eLists[id] || pLists[id] || rLists[id]; - return collection; - } - ); - -export const makeSelectClaimUrlInCollection = (url: string) => - createSelector( - selectBuiltinCollections, - selectMyPublishedCollections, - selectMyUnpublishedCollections, - selectMyEditedCollections, - selectPendingCollections, - (bLists, myRLists, uLists, eLists, pLists) => { - const collections = [bLists, uLists, eLists, myRLists, pLists]; - const itemsInCollections = []; - collections.map(list => { - Object.entries(list).forEach(([key, value]) => { - // $FlowFixMe - value.items.map(item => { - itemsInCollections.push(item); - }); - }); - }); - return itemsInCollections.includes(url); - } - ); - -export const makeSelectCollectionForIdHasClaimUrl = (id: string, url: string) => - createSelector( - makeSelectCollectionForId(id), - collection => collection && collection.items.includes(url) - ); - -export const makeSelectUrlsForCollectionId = (id: string) => - createSelector( - makeSelectCollectionForId(id), - collection => collection && collection.items - ); - -export const makeSelectClaimIdsForCollectionId = (id: string) => - createSelector( - makeSelectCollectionForId(id), - collection => { - const items = (collection && collection.items) || []; - const ids = items.map(item => { - const { claimId } = parseURI(item); - return claimId; - }); - return ids; - } - ); - -export const makeSelectIndexForUrlInCollection = (url: string, id: string) => - createSelector( - state => state.content.shuffleList, - makeSelectUrlsForCollectionId(id), - makeSelectClaimForUri(url), - (shuffleState, urls, claim) => { - const shuffleUrls = shuffleState && shuffleState.collectionId === id && shuffleState.newUrls; - const listUrls = shuffleUrls || urls; - - const index = listUrls && listUrls.findIndex(u => u === url); - if (index > -1) { - return index; - } else if (claim) { - const index = listUrls && listUrls.findIndex(u => u === claim.permanent_url); - if (index > -1) return index; - return claim; - } - return null; - } - ); - -export const makeSelectPreviousUrlForCollectionAndUrl = (id: string, url: string) => - createSelector( - state => state.content.shuffleList, - state => state.content.loopList, - makeSelectIndexForUrlInCollection(url, id), - makeSelectUrlsForCollectionId(id), - (shuffleState, loopState, index, urls) => { - const loopList = loopState && loopState.collectionId === id && loopState.loop; - const shuffleUrls = shuffleState && shuffleState.collectionId === id && shuffleState.newUrls; - - if (index > -1) { - const listUrls = shuffleUrls || urls; - let nextUrl; - if (index === 0 && loopList) { - nextUrl = listUrls[listUrls.length - 1]; - } else { - nextUrl = listUrls[index - 1]; - } - return nextUrl || null; - } else { - return null; - } - } - ); - -export const makeSelectNextUrlForCollectionAndUrl = (id: string, url: string) => - createSelector( - state => state.content.shuffleList, - state => state.content.loopList, - makeSelectIndexForUrlInCollection(url, id), - makeSelectUrlsForCollectionId(id), - (shuffleState, loopState, index, urls) => { - const loopList = loopState && loopState.collectionId === id && loopState.loop; - const shuffleUrls = shuffleState && shuffleState.collectionId === id && shuffleState.newUrls; - - if (index > -1) { - const listUrls = shuffleUrls || urls; - // We'll get the next playble url - let remainingUrls = listUrls.slice(index + 1); - if (!remainingUrls.length && loopList) { - remainingUrls = listUrls.slice(0); - } - const nextUrl = remainingUrls && remainingUrls[0]; - return nextUrl || null; - } else { - return null; - } - } - ); - -export const makeSelectNameForCollectionId = (id: string) => - createSelector( - makeSelectCollectionForId(id), - collection => { - return (collection && collection.name) || ''; - } - ); - -export const makeSelectCountForCollectionId = (id: string) => - createSelector( - makeSelectCollectionForId(id), - collection => { - if (collection) { - if (collection.itemCount !== undefined) { - return collection.itemCount; - } - let itemCount = 0; - collection.items.map(item => { - if (item) { - itemCount += 1; - } - }); - return itemCount; - } - return null; - } - ); diff --git a/src/redux/selectors/publish.js b/src/redux/selectors/publish.js index a3a44a2..90c1c8d 100644 --- a/src/redux/selectors/publish.js +++ b/src/redux/selectors/publish.js @@ -43,8 +43,7 @@ export const selectPublishFormValues = createSelector( state => state.settings, selectIsStillEditing, (publishState, settingsState, isStillEditing) => { - const { languages, ...formValues } = publishState; - const language = languages && languages.length && languages[0]; + const { pendingPublish, language, ...formValues } = publishState; const { clientSettings } = settingsState; const { language: languageSet } = clientSettings; diff --git a/yarn.lock b/yarn.lock index af93714..3a5974d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1411,11 +1411,6 @@ dependencies: "@types/yargs-parser" "*" -"@ungap/from-entries@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@ungap/from-entries/-/from-entries-0.2.1.tgz#7e86196b8b2e99d73106a8f25c2a068326346354" - integrity sha512-CAqefTFAfnUPwYqsWHXpOxHaq1Zo5UQ3m9Zm2p09LggGe57rqHoBn3c++xcoomzXKynAUuiBMDUCQvKMnXjUpA== - abab@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"