sync reducer stuff

bring tags into app repo

prevent prefset until prefsReady

prefs ready on sign up

prefsReady-desktop
This commit is contained in:
jessop 2020-10-05 14:31:51 -04:00 committed by Sean Yesmunt
parent f54a0de797
commit 9d4f7dc642
38 changed files with 925 additions and 146 deletions

View file

@ -1348,6 +1348,9 @@
"Create a channel": "Create a channel",
"Credit Details": "Credit Details",
"LBRY Credits": "LBRY Credits",
"Mark all as read": "Mark all as read",
"Log in to %SITE_NAME% to earn rewards From Inviting Your Friends": "Log in to %SITE_NAME% to earn rewards From Inviting Your Friends",
"Confirming...": "Confirming...",
"Pinned by @%channel%": "Pinned by @%channel%",
"Pinned by creator": "Pinned by creator",
"Claim Your %reward_amount% Credit Invite Reward": "Claim Your %reward_amount% Credit Invite Reward",

View file

@ -9,7 +9,7 @@ import { doFetchChannelListMine, SETTINGS } from 'lbry-redux';
import { makeSelectClientSetting, selectLoadedLanguages, selectThemePath } from 'redux/selectors/settings';
import { selectIsUpgradeAvailable, selectAutoUpdateDownloaded, selectModal } from 'redux/selectors/app';
import { doGetWalletSyncPreference, doSetLanguage } from 'redux/actions/settings';
import { doSyncSubscribe } from 'redux/actions/syncwrapper';
import { doSyncSubscribe } from 'redux/actions/sync';
import {
doDownloadUpgradeRequested,
doSignIn,

View file

@ -5,8 +5,8 @@ import {
selectClaimSearchByQueryLastPageReached,
selectFetchingClaimSearch,
SETTINGS,
selectFollowedTags,
} from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import { selectBlockedChannels } from 'redux/selectors/blocked';
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
import { makeSelectClientSetting } from 'redux/selectors/settings';

View file

@ -1,5 +1,6 @@
import { connect } from 'react-redux';
import { selectFetchingClaimSearch, SETTINGS, selectFollowedTags } from 'lbry-redux';
import { selectFetchingClaimSearch, SETTINGS } from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { doSetClientSetting } from 'redux/actions/settings';

View file

@ -1,5 +1,6 @@
import { connect } from 'react-redux';
import { makeSelectTagsForUri, selectFollowedTags } from 'lbry-redux';
import { makeSelectTagsForUri } from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import ClaimTags from './view';
const select = (state, props) => ({
@ -7,7 +8,4 @@ const select = (state, props) => ({
followedTags: selectFollowedTags(state),
});
export default connect(
select,
null
)(ClaimTags);
export default connect(select, null)(ClaimTags);

View file

@ -1,6 +1,7 @@
import { connect } from 'react-redux';
import { selectSubscriptions } from 'redux/selectors/subscriptions';
import { selectFollowedTags, selectPurchaseUriSuccess, doClearPurchasedUriSuccess, SETTINGS } from 'lbry-redux';
import { selectPurchaseUriSuccess, doClearPurchasedUriSuccess, SETTINGS } from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import { selectUserVerifiedEmail, selectUser } from 'redux/selectors/user';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { doSignOut } from 'redux/actions/app';

View file

@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import { selectGetSyncIsPending, selectSyncApplyPasswordError } from 'redux/selectors/sync';
import { doGetSyncDesktop } from 'redux/actions/syncwrapper';
import { doGetSyncDesktop } from 'redux/actions/sync';
import { selectUserEmail } from 'redux/selectors/user';
import { doSetClientSetting } from 'redux/actions/settings';
import { doSignOut, doHandleSyncComplete } from 'redux/actions/app';

View file

@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import { selectUnfollowedTags, selectFollowedTags, doReplaceTags, doAddTag, doDeleteTag } from 'lbry-redux';
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
import { selectUnfollowedTags, selectFollowedTags } from 'redux/selectors/tags';
import { doToggleTagFollowDesktop, doAddTag, doDeleteTag } from 'redux/actions/tags';
import DiscoveryFirstRun from './view';
const select = (state, props) => ({
@ -8,12 +8,8 @@ const select = (state, props) => ({
followedTags: selectFollowedTags(state),
});
export default connect(
select,
{
doToggleTagFollowDesktop,
doAddTag,
doDeleteTag,
doReplaceTags,
}
)(DiscoveryFirstRun);
export default connect(select, {
doToggleTagFollowDesktop,
doAddTag,
doDeleteTag,
})(DiscoveryFirstRun);

View file

@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import { selectUnfollowedTags, selectFollowedTags, doReplaceTags, doAddTag, doDeleteTag } from 'lbry-redux';
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
import { selectUnfollowedTags, selectFollowedTags } from 'redux/selectors/tags';
import { doToggleTagFollowDesktop, doAddTag, doDeleteTag } from 'redux/actions/tags';
import DiscoveryFirstRun from './view';
const select = (state, props) => ({
@ -8,12 +8,8 @@ const select = (state, props) => ({
followedTags: selectFollowedTags(state),
});
export default connect(
select,
{
doToggleTagFollowDesktop,
doAddTag,
doDeleteTag,
doReplaceTags,
}
)(DiscoveryFirstRun);
export default connect(select, {
doToggleTagFollowDesktop,
doAddTag,
doDeleteTag,
})(DiscoveryFirstRun);

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux';
import { selectFollowedTags } from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import { selectSubscriptions } from 'redux/selectors/subscriptions';
import { doChannelSubscribe } from 'redux/actions/subscriptions';
import UserChannelFollowIntro from './view';
@ -13,7 +13,4 @@ const perform = dispatch => ({
channelSubscribe: uri => dispatch(doChannelSubscribe(uri)),
});
export default connect(
select,
perform
)(UserChannelFollowIntro);
export default connect(select, perform)(UserChannelFollowIntro);

View file

@ -22,6 +22,8 @@ import {
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { selectInterestedInYoutubeSync } from 'redux/selectors/app';
import { doToggleInterestedInYoutubeSync } from 'redux/actions/app';
import { doSetPrefsReady } from 'redux/actions/sync';
import UserSignIn from './view';
const select = state => ({
@ -63,6 +65,7 @@ const perform = dispatch => ({
),
setClientSetting: (setting, value, pushToPrefs) => dispatch(doSetClientSetting(setting, value, pushToPrefs)),
doToggleInterestedInYoutubeSync: () => dispatch(doToggleInterestedInYoutubeSync()),
setPrefsReady: () => dispatch(doSetPrefsReady()),
});
export default connect(select, perform)(UserSignIn);

View file

@ -45,6 +45,7 @@ type Props = {
rewardsAcknowledged: boolean,
interestedInYoutubeSync: boolean,
doToggleInterestedInYoutubeSync: () => void,
setPrefsReady: () => void,
};
function UserSignUp(props: Props) {
@ -70,6 +71,7 @@ function UserSignUp(props: Props) {
setClientSetting,
interestedInYoutubeSync,
doToggleInterestedInYoutubeSync,
setPrefsReady,
} = props;
const {
location: { search, pathname },
@ -133,9 +135,10 @@ function UserSignUp(props: Props) {
React.useEffect(() => {
if (hasVerifiedEmail) {
setPrefsReady();
setSettingAndSync(SETTINGS.FIRST_RUN_STARTED, true);
}
}, [hasVerifiedEmail]);
}, [hasVerifiedEmail, setPrefsReady]);
React.useEffect(() => {
// Don't claim the reward if sync is enabled until after a sync has been completed successfully

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux';
import { selectFollowedTags } from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import UserTagFollowIntro from './view';
const select = state => ({

View file

@ -279,6 +279,11 @@ export const COMMENT_SET_CHANNEL = 'COMMENT_SET_CHANNEL';
// Blocked channels
export const TOGGLE_BLOCK_CHANNEL = 'TOGGLE_BLOCK_CHANNEL';
// Tags
export const TOGGLE_TAG_FOLLOW = 'TOGGLE_TAG_FOLLOW';
export const TAG_ADD = 'TAG_ADD';
export const TAG_DELETE = 'TAG_DELETE';
// Notifications
export const WS_CONNECT = 'WS_CONNECT';
export const WS_DISCONNECT = 'WS_DISCONNECT';
@ -290,6 +295,7 @@ export const GET_SYNC_FAILED = 'GET_SYNC_FAILED';
export const SET_SYNC_STARTED = 'SET_SYNC_STARTED';
export const SET_SYNC_FAILED = 'SET_SYNC_FAILED';
export const SET_SYNC_COMPLETED = 'SET_SYNC_COMPLETED';
export const SET_PREFS_READY = 'SET_PREFS_READY';
export const SET_DEFAULT_ACCOUNT = 'SET_DEFAULT_ACCOUNT';
export const SYNC_APPLY_STARTED = 'SYNC_APPLY_STARTED';
export const SYNC_APPLY_COMPLETED = 'SYNC_APPLY_COMPLETED';

546
ui/constants/tags.js Normal file
View file

@ -0,0 +1,546 @@
export const DEFAULT_FOLLOWED_TAGS = [
'art',
'automotive',
'blockchain',
'comedy',
'economics',
'education',
'gaming',
'music',
'news',
'science',
'sports',
'technology',
];
export 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',
];
const DEFAULT_ENGLISH_KNOWN_TAGS = [
'free speech',
'censorship',
'gaming',
'pop culture',
'entertainment',
'technology',
'music',
'funny',
'education',
'learning',
'news',
'gameplay',
'nature',
'beliefs',
'comedy',
'games',
'film & animation',
'game',
'weapons',
'blockchain',
'video game',
'sports',
'walkthrough',
'lbrytvpaidbeta',
'art',
'pc',
'minecraft',
'playthrough',
'economics',
'automotive',
'play',
'tutorial',
'twitch',
'how to',
'ps4',
'bitcoin',
'fortnite',
'commentary',
'lets play',
'fun',
'politics',
'travel',
'food',
'science',
'xbox',
'liberal',
'democrat',
'progressive',
'survival',
'non-profits',
'activism',
'cryptocurrency',
'playstation',
'nintendo',
'government',
'steam',
'podcast',
'gamer',
'horror',
'conservative',
'reaction',
'trailer',
'love',
'cnn',
'republican',
'political',
'hangoutsonair',
'hoa',
'msnbc',
'cbs',
'anime',
'donald trump',
'fiction',
'fox news',
'crypto',
'ethereum',
'call of duty',
'android',
'multiplayer',
'epic',
'rpg',
'adventure',
'secular talk',
'btc',
'atheist',
'atheism',
'video games',
'ps3',
'cod',
'online',
'agnostic',
'movie',
'fps',
'lets',
'mod',
'world',
'reviews',
'sharefactory',
'space',
'pokemon',
'stream',
'hilarious',
'lol',
'sony',
'god',
'dance',
'pvp',
'tech',
'strategy',
'zombies',
'fail',
'film',
'xbox360',
'animation',
'unboxing',
'money',
'wwe',
'mods',
'indie',
'pubg',
'ios',
'history',
'rap',
'mobile',
'trump',
'hack',
'flat earth',
'trap',
'humor',
'vlogging',
'fox',
'news radio',
'facebook',
'edm',
'fitness',
'vaping',
'hip hop',
'secular',
'jesus',
'song',
'vape',
'guitar',
'remix',
'mining',
'daily',
'diy',
'pets',
'videogame',
'death',
'funny moments',
'religion',
'media',
'viral',
'war',
'nbc',
'freedom',
'gold',
'family',
'meme',
'zombie',
'photography',
'chill',
'sniper',
'computer',
'iphone',
'dragon',
'bible',
'pro',
'overwatch',
'litecoin',
'gta',
'house',
'fire',
'bass',
'truth',
'crash',
'mario',
'league of legends',
'wii',
'mmorpg',
'health',
'marvel',
'racing',
'apple',
'instrumental',
'earth',
'destiny',
'satire',
'race',
'training',
'electronic',
'boss',
'roblox',
'family friendly',
'california',
'react',
'christian',
'mmo',
'twitter',
'help',
'star',
'cars',
'random',
'top 10',
'ninja',
'guns',
'linux',
'lessons',
'vegan',
'future',
'dota 2',
'studio',
'star wars',
'shooting',
'nasa',
'rock',
'league',
'subscribe',
'water',
'gta v',
'car',
'samsung',
'music video',
'skyrim',
'dog',
'comics',
'shooter game',
'bo3',
'halloween',
'liberty',
'eth',
'conspiracy',
'knife',
'fashion',
'stories',
'vapor',
'nvidia',
'cute',
'beat',
'nintendo switch',
'fantasy',
'christmas',
'world of warcraft',
'industry',
'cartoon',
'garden',
'animals',
'windows',
'happy',
'magic',
'memes',
'design',
'tactical',
'fallout 4',
'puzzle',
'parody',
'rv',
'beats',
'building',
'disney',
'drone',
'ps2',
'beach',
'metal',
'christianity',
'business',
'mix',
'bo2',
'cover',
'senate',
'4k',
'united states',
'final',
'hero',
'playing',
'dlc',
'ubisoft',
'halo',
'pc gaming',
'raw',
'investing',
'online learning',
'software',
'ark',
'mojang',
'console',
'battle royale',
'canon',
'microsoft',
'camping',
'ufo',
'progressive talk',
'switch',
'fpv',
'arcade',
'school',
'driving',
'bodybuilding',
'drama',
'retro',
'science fiction',
'eggs',
'australia',
'modded',
'rainbow',
'gamers',
'resident evil',
'drawing',
'brasil',
'england',
'hillary clinton',
'singing',
'final fantasy',
'hiphop',
'video blog',
'mature',
'quad',
'noob',
'simulation',
'illuminati',
'poetry',
'dayz',
'manga',
'howto',
'insane',
'press',
'special',
'church',
'ico',
'weird',
'libertarian',
'crafting',
'level',
'comic',
'sandbox',
'daily vlog',
'outdoor',
'black ops',
'sound',
'christ',
'duty',
'juvenile fiction',
'pc game',
'how-to',
'ww2',
'creepy',
'artist',
'galaxy',
'destiny 2',
'new music',
'quest',
'lee',
'pacman',
'super smash bros',
'day',
'survival horror',
'patreon',
'bitcoin price',
'trending',
'open world',
'wii u',
'dope',
'reaper',
'sniping',
'dubstep',
'truck',
'planet',
'dc',
'amazon',
'spirituality',
'universe',
'video game culture',
'community',
'cat',
'aliens',
'tourism',
'altcoins',
'style',
'travel trailer',
'rda',
'gun',
'secret',
'far cry 5',
'auto',
'culture',
'dj',
'mw2',
'lord',
'full time rving',
'role-playing game',
'prank',
'grand theft auto',
'master',
'wrestling',
'sci-fi',
'workout',
'ghost',
'fake news',
'silly',
'season',
'bo4',
'trading',
'extreme',
'economy',
'combat',
'plays',
'muslim',
'pubg mobile',
'clips',
'bo1',
'paypal',
'sims',
'exploration',
'light',
'ripple',
'paranormal',
'football',
'capcom',
'rta',
'discord',
'batman',
'player',
'server',
'anarchy',
'military',
'playlist',
'cosplay',
'rv park',
'rant',
'edit',
'germany',
'reading',
'chris',
'flash',
'loot',
'bitcoin gratis',
'game reviews',
'movies',
'stupid',
'latest news',
'squad gameplay',
'guru',
'timelapse',
'black ops 3',
'holiday',
'soul',
'motivation',
'mw3',
'vacation',
'sega',
'19th century',
'pop',
'sims 4',
'post',
'smok',
'island',
'scotland',
'paladins',
'warrior',
'creepypasta',
'role-playing',
'solar',
'vr',
'animal',
'peace',
'consciousness',
'dota',
'audio',
'mass effect',
'humour',
'first look',
'videogames',
'future bass',
'freestyle',
'hardcore',
'portugal',
'dantdm',
'teaser',
'lbry',
'coronavirus',
'2020protests',
'covidcuts',
'covid-19',
'LBRYFoundationBoardCandidacy',
];
const DEFAULT_SPANISH_KNOWN_TAGS = [
'español',
'tecnología',
'criptomonedas',
'economía',
'bitcoin',
'educación',
'videojuegos',
'música',
'noticias',
'ciencia',
'deportes',
'latinoamérica',
'latam',
'conspiración',
'humor',
'política',
'tutoriales',
];
export const DEFAULT_KNOWN_TAGS = [...DEFAULT_ENGLISH_KNOWN_TAGS, ...DEFAULT_SPANISH_KNOWN_TAGS];

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux';
import { selectFollowedTags } from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import { selectBlockedChannels } from 'redux/selectors/blocked';
import { selectSubscriptions } from 'redux/selectors/subscriptions';
import ChannelsFollowingManagePage from './view';

View file

@ -1,7 +1,8 @@
import * as CS from 'constants/claim_search';
import { connect } from 'react-redux';
import { makeSelectClaimForUri, selectFollowedTags, doResolveUri, SETTINGS } from 'lbry-redux';
import { makeSelectClaimForUri, doResolveUri, SETTINGS } from 'lbry-redux';
import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectFollowedTags } from 'redux/selectors/tags';
import { doToggleTagFollowDesktop } from 'redux/actions/tags';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import Tags from './view';

View file

@ -1,6 +1,6 @@
import * as SETTINGS from 'constants/settings';
import { connect } from 'react-redux';
import { selectFollowedTags } from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectSubscriptions } from 'redux/selectors/subscriptions';
import { makeSelectClientSetting } from 'redux/selectors/settings';

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux';
import { selectFollowedTags } from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectSubscriptions } from 'redux/selectors/subscriptions';
import DiscoverPage from './view';

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux';
import { selectFollowedTags } from 'lbry-redux';
import { selectFollowedTags } from 'redux/selectors/tags';
import { selectSubscriptions, selectSuggestedChannels } from 'redux/selectors/subscriptions';
import { doFetchRecommendedSubscriptions } from 'redux/actions/subscriptions';
@ -11,9 +11,6 @@ const select = state => ({
suggestedSubscriptions: selectSuggestedChannels(state),
});
export default connect(
select,
{
doFetchRecommendedSubscriptions,
}
)(TagsEdit);
export default connect(select, {
doFetchRecommendedSubscriptions,
})(TagsEdit);

View file

@ -1,8 +1,9 @@
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import { claimsReducer, fileInfoReducer, walletReducer, tagsReducer, publishReducer } from 'lbry-redux';
import { claimsReducer, fileInfoReducer, walletReducer, publishReducer } from 'lbry-redux';
import { costInfoReducer, blacklistReducer, filteredReducer, homepageReducer, statsReducer, webReducer } from 'lbryinc';
import appReducer from 'redux/reducers/app';
import tagsReducer from 'redux/reducers/tags';
import contentReducer from 'redux/reducers/content';
import settingsReducer from 'redux/reducers/settings';
import subscriptionsReducer from 'redux/reducers/subscriptions';

View file

@ -18,12 +18,13 @@ import {
doClearPublish,
doPreferenceGet,
doClearSupport,
selectFollowedTagsList,
SHARED_PREFERENCES,
DAEMON_SETTINGS,
SETTINGS,
} from 'lbry-redux';
import { selectFollowedTagsList } from 'redux/selectors/tags';
import { doToast, doError, doNotificationList } from 'redux/actions/notifications';
import Native from 'native';
import {
doFetchDaemonSettings,
@ -47,7 +48,7 @@ import {
import { selectDaemonSettings, makeSelectClientSetting } from 'redux/selectors/settings';
import { selectUser } from 'redux/selectors/user';
// import { selectDaemonSettings } from 'redux/selectors/settings';
import { doSyncSubscribe } from 'redux/actions/syncwrapper';
import { doSyncSubscribe, doSetPrefsReady } from 'redux/actions/sync';
import { doAuthenticate } from 'redux/actions/user';
import { lbrySettings as config, version as appVersion } from 'package.json';
import analytics, { SHARE_INTERNAL } from 'analytics';
@ -90,13 +91,6 @@ export function doUpdateDownloadProgress(percent) {
};
}
export function doSetSyncLock(lock) {
return {
type: ACTIONS.SET_SYNC_LOCK,
data: lock,
};
}
export function doSkipUpgrade() {
return {
type: ACTIONS.SKIP_UPGRADE,
@ -340,6 +334,16 @@ export function doAlertError(errorList) {
};
}
export function doAlertWaitingForSync() {
return dispatch =>
dispatch(
doToast({
message: __('Hold on, we are setting up your account'),
isError: false,
})
);
}
export function doDaemonReady() {
return (dispatch, getState) => {
const state = getState();
@ -628,6 +632,8 @@ export function doGetAndPopulatePreferences() {
});
}
// @endif
} else {
dispatch(doSetPrefsReady());
}
return true;
}

View file

@ -1,9 +1,20 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import { selectPrefsReady } from 'redux/selectors/sync';
import { doAlertWaitingForSync } from 'redux/actions/app';
export const doToggleBlockChannel = (uri: string) => ({
type: ACTIONS.TOGGLE_BLOCK_CHANNEL,
data: {
uri,
},
});
export const doToggleBlockChannel = (uri: string) => (dispatch: Dispatch, getState: GetState) => {
const state = getState();
const ready = selectPrefsReady(state);
if (!ready) {
return dispatch(doAlertWaitingForSync());
}
dispatch({
type: ACTIONS.TOGGLE_BLOCK_CHANNEL,
data: {
uri,
},
});
};

View file

@ -13,7 +13,7 @@ import {
import { doError } from 'redux/actions/notifications';
import { push } from 'connected-react-router';
import analytics from 'analytics';
import { doOpenModal } from './app';
import { doOpenModal } from 'redux/actions/app';
export const doPublishDesktop = (filePath: string, preview?: boolean) => (dispatch: Dispatch, getState: () => {}) => {
const publishPreview = previewResponse => {

View file

@ -2,7 +2,7 @@
import { Lbryio } from 'lbryinc';
import * as ACTIONS from 'constants/action_types';
import * as REACTION_TYPES from 'constants/reactions';
import { makeSelectMyReactionForUri } from '../selectors/reactions';
import { makeSelectMyReactionForUri } from 'redux/selectors/reactions';
import { makeSelectClaimForUri } from 'lbry-redux';
export const doFetchReactions = (claimId: string) => (dispatch: Dispatch) => {

View file

@ -5,8 +5,9 @@ import analytics from 'analytics';
import SUPPORTED_LANGUAGES from 'constants/supported_languages';
import { launcher } from 'util/autoLaunch';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { doGetSyncDesktop, doSyncUnsubscribe } from 'redux/actions/syncwrapper';
import { doGetAndPopulatePreferences, doSetSyncLock } from 'redux/actions/app';
import { doGetSyncDesktop, doSyncUnsubscribe, doSetSyncLock } from 'redux/actions/sync';
import { doAlertWaitingForSync, doGetAndPopulatePreferences } from 'redux/actions/app';
import { selectPrefsReady } from 'redux/selectors/sync';
const { DEFAULT_LANGUAGE } = require('config');
const { SDK_SYNC_KEYS } = SHARED_PREFERENCES;
@ -57,10 +58,18 @@ export function doGetDaemonStatus() {
}
export function doClearDaemonSetting(key) {
return dispatch => {
return (dispatch, getState) => {
const state = getState();
const ready = selectPrefsReady(state);
if (!ready) {
return dispatch(doAlertWaitingForSync());
}
const clearKey = {
key,
};
// not if syncLocked
Lbry.settings_clear(clearKey).then(defaultSettings => {
if (SDK_SYNC_KEYS.includes(key)) {
dispatch({
@ -85,7 +94,14 @@ export function doClearDaemonSetting(key) {
}
// if doPopulate is applying settings, we don't want to cause a loop; doNotDispatch = true.
export function doSetDaemonSetting(key, value, doNotDispatch = false) {
return dispatch => {
return (dispatch, getState) => {
const state = getState();
const ready = selectPrefsReady(state);
if (!ready) {
return dispatch(doAlertWaitingForSync());
}
const newSettings = {
key,
value: !value && value !== false ? null : value,
@ -123,7 +139,14 @@ export function doSaveCustomWalletServers(servers) {
}
export function doSetClientSetting(key, value, pushPrefs) {
return dispatch => {
return (dispatch, getState) => {
const state = getState();
const ready = selectPrefsReady(state);
if (!ready) {
return dispatch(doAlertWaitingForSync());
}
dispatch({
type: ACTIONS.CLIENT_SETTING_CHANGED,
data: {

View file

@ -5,6 +5,7 @@ import { Lbryio } from 'lbryinc';
import { doClaimRewardType } from 'redux/actions/rewards';
import { selectUnreadByChannel } from 'redux/selectors/subscriptions';
import { parseURI } from 'lbry-redux';
import { doAlertWaitingForSync } from 'redux/actions/app';
export const doSetViewMode = (viewMode: ViewMode) => (dispatch: Dispatch) =>
dispatch({
@ -123,7 +124,13 @@ export const doRemoveUnreadSubscription = (channelUri: string, readUri: string)
export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dispatch, getState: GetState) => {
const {
settings: { daemonSettings },
sync: { prefsReady: ready },
} = getState();
if (!ready) {
return dispatch(doAlertWaitingForSync());
}
const { share_usage_data: shareSetting } = daemonSettings;
const isSharingData = shareSetting || IS_WEB;
@ -153,7 +160,13 @@ export const doChannelSubscribe = (subscription: Subscription) => (dispatch: Dis
export const doChannelUnsubscribe = (subscription: Subscription) => (dispatch: Dispatch, getState: GetState) => {
const {
settings: { daemonSettings },
sync: { prefsReady: ready },
} = getState();
if (!ready) {
return dispatch(doAlertWaitingForSync());
}
const { share_usage_data: shareSetting } = daemonSettings;
const isSharingData = shareSetting || IS_WEB;

View file

@ -1,6 +1,14 @@
import * as ACTIONS from 'constants/action_types';
import { Lbryio } from 'lbryinc';
import { Lbry, doWalletEncrypt, doWalletDecrypt } from 'lbry-redux';
import { SETTINGS, Lbry, doWalletEncrypt, doWalletDecrypt } from 'lbry-redux';
import { selectGetSyncIsPending, selectSetSyncIsPending, selectSyncIsLocked } from 'redux/selectors/sync';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { getSavedPassword } from 'util/saved-passwords';
import { doAnalyticsTagSync, doHandleSyncComplete } from 'redux/actions/app';
import { selectUserVerifiedEmail } from 'redux/selectors/user';
let syncTimer = null;
const SYNC_INTERVAL = 1000 * 60 * 5; // 5 minutes
export function doSetDefaultAccount(success, failure) {
return dispatch => {
@ -77,6 +85,52 @@ export function doSetSync(oldHash, newHash, data) {
};
}
export const doGetSyncDesktop = (cb?, password) => (dispatch, getState) => {
const state = getState();
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
const getSyncPending = selectGetSyncIsPending(state);
const setSyncPending = selectSetSyncIsPending(state);
const syncLocked = selectSyncIsLocked(state);
return getSavedPassword().then(savedPassword => {
const passwordArgument = password || password === '' ? password : savedPassword === null ? '' : savedPassword;
if (syncEnabled && !getSyncPending && !setSyncPending && !syncLocked) {
return dispatch(doGetSync(passwordArgument, cb));
}
});
};
export function doSyncSubscribe() {
return (dispatch, getState) => {
if (syncTimer) clearInterval(syncTimer);
const state = getState();
const hasVerifiedEmail = selectUserVerifiedEmail(state);
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
const syncLocked = selectSyncIsLocked(state);
if (hasVerifiedEmail && syncEnabled && !syncLocked) {
dispatch(doGetSyncDesktop((error, hasNewData) => dispatch(doHandleSyncComplete(error, hasNewData))));
dispatch(doAnalyticsTagSync());
syncTimer = setInterval(() => {
const state = getState();
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
if (syncEnabled) {
dispatch(doGetSyncDesktop((error, hasNewData) => dispatch(doHandleSyncComplete(error, hasNewData))));
dispatch(doAnalyticsTagSync());
}
}, SYNC_INTERVAL);
}
};
}
export function doSyncUnsubscribe() {
return dispatch => {
if (syncTimer) {
clearInterval(syncTimer);
}
};
}
export function doGetSync(passedPassword, callback) {
const password = passedPassword === null || passedPassword === undefined ? '' : passedPassword;
@ -280,3 +334,17 @@ export function doSyncEncryptAndDecrypt(oldPassword, newPassword, encrypt) {
.catch(console.error); // eslint-disable-line
};
}
export function doSetSyncLock(lock) {
return {
type: ACTIONS.SET_SYNC_LOCK,
data: lock,
};
}
export function doSetPrefsReady() {
return {
type: ACTIONS.SET_PREFS_READY,
data: true,
};
}

View file

@ -1,58 +0,0 @@
// @flow
import { doGetSync } from 'redux/actions/sync';
import { selectGetSyncIsPending, selectSetSyncIsPending } from 'redux/selectors/sync';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import { getSavedPassword } from 'util/saved-passwords';
import { doAnalyticsTagSync, doHandleSyncComplete } from 'redux/actions/app';
import { selectSyncIsLocked } from 'redux/selectors/app';
import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { SETTINGS } from 'lbry-redux';
let syncTimer = null;
const SYNC_INTERVAL = 1000 * 60 * 5; // 5 minutes
export const doGetSyncDesktop = (cb?: () => void, password?: string) => (dispatch: Dispatch, getState: GetState) => {
const state = getState();
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
const getSyncPending = selectGetSyncIsPending(state);
const setSyncPending = selectSetSyncIsPending(state);
const syncLocked = selectSyncIsLocked(state);
return getSavedPassword().then(savedPassword => {
const passwordArgument = password || password === '' ? password : savedPassword === null ? '' : savedPassword;
if (syncEnabled && !getSyncPending && !setSyncPending && !syncLocked) {
return dispatch(doGetSync(passwordArgument, cb));
}
});
};
export function doSyncSubscribe() {
return (dispatch: Dispatch, getState: GetState) => {
if (syncTimer) clearInterval(syncTimer);
const state = getState();
const hasVerifiedEmail = selectUserVerifiedEmail(state);
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
const syncLocked = selectSyncIsLocked(state);
if (hasVerifiedEmail && syncEnabled && !syncLocked) {
dispatch(doGetSyncDesktop((error, hasNewData) => dispatch(doHandleSyncComplete(error, hasNewData))));
dispatch(doAnalyticsTagSync());
syncTimer = setInterval(() => {
const state = getState();
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
if (syncEnabled) {
dispatch(doGetSyncDesktop((error, hasNewData) => dispatch(doHandleSyncComplete(error, hasNewData))));
dispatch(doAnalyticsTagSync());
}
}, SYNC_INTERVAL);
}
};
}
export function doSyncUnsubscribe() {
return (dispatch: Dispatch) => {
if (syncTimer) {
clearInterval(syncTimer);
}
};
}

View file

@ -1,15 +1,42 @@
// @flow
import { doToggleTagFollow, selectFollowedTagsList } from 'lbry-redux';
import { selectFollowedTagsList } from 'redux/selectors/tags';
import { selectPrefsReady } from 'redux/selectors/sync';
import * as ACTIONS from 'constants/action_types';
import analytics from 'analytics';
import { doAlertWaitingForSync } from 'redux/actions/app';
export const doToggleTagFollowDesktop = (name: string) => (dispatch: Dispatch, getState: GetState) => {
dispatch(doToggleTagFollow(name));
const state = getState();
const tags = selectFollowedTagsList(state);
const ready = selectPrefsReady(state);
if (!ready) {
return dispatch(doAlertWaitingForSync());
}
dispatch({
type: ACTIONS.TOGGLE_TAG_FOLLOW,
data: {
name,
},
});
const stringOfTags = tags.join(',');
if (stringOfTags) {
analytics.apiSyncTags({ content_tags: stringOfTags });
}
};
export const doAddTag = (name: string) => ({
type: ACTIONS.TAG_ADD,
data: {
name,
},
});
export const doDeleteTag = (name: string) => ({
type: ACTIONS.TAG_DELETE,
data: {
name,
},
});

View file

@ -42,7 +42,6 @@ export type AppState = {
welcomeVersion: number,
allowAnalytics: boolean,
hasNavigated: boolean,
syncLocked: boolean,
interestedInYoutubeSync: boolean,
};
@ -78,7 +77,6 @@ const defaultState: AppState = {
welcomeVersion: 0.0,
allowAnalytics: false,
hasNavigated: false,
syncLocked: false,
interestedInYoutubeSync: false,
};
@ -113,11 +111,6 @@ reducers[ACTIONS.DAEMON_READY] = state =>
daemonReady: true,
});
reducers[ACTIONS.SET_SYNC_LOCK] = (state, action) =>
Object.assign({}, state, {
syncLocked: action.data,
});
reducers[ACTIONS.PASSWORD_SAVED] = (state, action) =>
Object.assign({}, state, {
isPasswordSaved: action.data,

View file

@ -144,6 +144,12 @@ export default handleActions(
action: { data: { subscriptions: ?Array<string> } }
) => {
const { subscriptions } = action.data;
const incomingSubscriptions = Array.isArray(subscriptions) && subscriptions.length;
if (!incomingSubscriptions) {
return {
...state,
};
}
let newSubscriptions;
if (!subscriptions) {

View file

@ -1,4 +1,5 @@
import * as ACTIONS from 'constants/action_types';
import { ACTIONS as LBRY_REDUX_ACTIONS } from 'lbry-redux';
const reducers = {};
const defaultState = {
@ -12,15 +13,35 @@ const defaultState = {
syncApplyPasswordError: false,
getSyncIsPending: false,
setSyncIsPending: false,
prefsReady: false,
syncLocked: false,
hashChanged: false,
};
reducers[LBRY_REDUX_ACTIONS.USER_STATE_POPULATE] = state => {
const { syncReady } = state;
if (!syncReady) {
return Object.assign({}, state, {
prefsReady: true,
});
} else {
return Object.assign({}, state);
}
};
reducers[ACTIONS.SET_PREFS_READY] = (state, action) => Object.assign({}, state, { prefsReady: action.data });
reducers[ACTIONS.GET_SYNC_STARTED] = state =>
Object.assign({}, state, {
getSyncIsPending: true,
getSyncErrorMessage: null,
});
reducers[ACTIONS.SET_SYNC_LOCK] = (state, action) =>
Object.assign({}, state, {
syncLocked: action.data,
});
reducers[ACTIONS.GET_SYNC_COMPLETED] = (state, action) =>
Object.assign({}, state, {
syncHash: action.data.syncHash,

82
ui/redux/reducers/tags.js Normal file
View file

@ -0,0 +1,82 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import { ACTIONS as LBRY_REDUX_ACTIONS, DEFAULT_KNOWN_TAGS, DEFAULT_FOLLOWED_TAGS } from 'lbry-redux';
import { handleActions } from 'util/redux-utils';
function getDefaultKnownTags() {
return DEFAULT_FOLLOWED_TAGS.concat(DEFAULT_KNOWN_TAGS).reduce(
(tagsMap, tag) => ({
...tagsMap,
[tag]: { name: tag },
}),
{}
);
}
const defaultState: TagState = {
followedTags: [],
knownTags: getDefaultKnownTags(),
};
export default handleActions(
{
[ACTIONS.TOGGLE_TAG_FOLLOW]: (state: TagState, action: TagAction): TagState => {
const { followedTags } = state;
const { name } = action.data;
let newFollowedTags = followedTags.slice();
if (newFollowedTags.includes(name)) {
newFollowedTags = newFollowedTags.filter(tag => tag !== name);
} else {
newFollowedTags.push(name);
}
return {
...state,
followedTags: newFollowedTags,
};
},
[ACTIONS.TAG_ADD]: (state: TagState, action: TagAction) => {
const { knownTags } = state;
const { name } = action.data;
let newKnownTags = { ...knownTags };
newKnownTags[name] = { name };
return {
...state,
knownTags: newKnownTags,
};
},
[ACTIONS.TAG_DELETE]: (state: TagState, action: TagAction) => {
const { knownTags, followedTags } = state;
const { name } = action.data;
let newKnownTags = { ...knownTags };
delete newKnownTags[name];
const newFollowedTags = followedTags.filter(tag => tag !== name);
return {
...state,
knownTags: newKnownTags,
followedTags: newFollowedTags,
};
},
[LBRY_REDUX_ACTIONS.USER_STATE_POPULATE]: (state: TagState, action: { data: { tags: ?Array<string> } }) => {
const { tags } = action.data;
if (Array.isArray(tags)) {
return {
...state,
followedTags: tags,
};
}
return {
...state,
};
},
},
defaultState
);

View file

@ -81,6 +81,4 @@ export const selectScrollStartingPosition = createSelector(selectState, state =>
export const selectIsPasswordSaved = createSelector(selectState, state => state.isPasswordSaved);
export const selectSyncIsLocked = createSelector(selectState, state => state.syncLocked);
export const selectInterestedInYoutubeSync = createSelector(selectState, state => state.interestedInYoutubeSync);

View file

@ -23,3 +23,7 @@ export const selectSyncApplyIsPending = createSelector(selectState, state => sta
export const selectSyncApplyErrorMessage = createSelector(selectState, state => state.syncApplyErrorMessage);
export const selectSyncApplyPasswordError = createSelector(selectState, state => state.syncApplyPasswordError);
export const selectSyncIsLocked = createSelector(selectState, state => state.syncLocked);
export const selectPrefsReady = createSelector(selectState, state => state.prefsReady);

View file

@ -0,0 +1,36 @@
// @flow
import { createSelector } from 'reselect';
const selectState = (state: { tags: TagState }) => state.tags || {};
export const selectKnownTagsByName = createSelector(selectState, (state: TagState): KnownTags => state.knownTags);
export const selectFollowedTagsList = createSelector(selectState, (state: TagState): Array<string> =>
state.followedTags.filter(tag => typeof tag === 'string')
);
export const selectFollowedTags = createSelector(selectFollowedTagsList, (followedTags: Array<string>): Array<Tag> =>
followedTags.map(tag => ({ name: tag.toLowerCase() })).sort((a, b) => a.name.localeCompare(b.name))
);
export const selectUnfollowedTags = createSelector(
selectKnownTagsByName,
selectFollowedTagsList,
(tagsByName: KnownTags, followedTags: Array<string>): Array<Tag> => {
const followedTagsSet = new Set(followedTags);
let tagsToReturn = [];
Object.keys(tagsByName).forEach(key => {
if (!followedTagsSet.has(key)) {
const { name } = tagsByName[key];
tagsToReturn.push({ name: name.toLowerCase() });
}
});
return tagsToReturn;
}
);
export const makeSelectIsFollowingTag = (tag: string) =>
createSelector(selectFollowedTags, followedTags => {
return followedTags.some(followedTag => followedTag.name === tag.toLowerCase());
});

View file

@ -10,7 +10,7 @@ import { createMemoryHistory, createBrowserHistory } from 'history';
import { routerMiddleware } from 'connected-react-router';
import createRootReducer from './reducers';
import { Lbry, buildSharedStateMiddleware, ACTIONS as LBRY_REDUX_ACTIONS } from 'lbry-redux';
import { doSyncSubscribe } from 'redux/actions/syncwrapper';
import { doSyncSubscribe } from 'redux/actions/sync';
import { getAuthToken } from 'util/saved-passwords';
import { generateInitialUrl } from 'util/url';
import { X_LBRY_AUTH_TOKEN } from 'constants/token';
@ -120,7 +120,7 @@ const triggerSharedStateActions = [
ACTIONS.CHANNEL_SUBSCRIBE,
ACTIONS.CHANNEL_UNSUBSCRIBE,
ACTIONS.TOGGLE_BLOCK_CHANNEL,
LBRY_REDUX_ACTIONS.TOGGLE_TAG_FOLLOW,
ACTIONS.TOGGLE_TAG_FOLLOW,
LBRY_REDUX_ACTIONS.CREATE_CHANNEL_COMPLETED,
ACTIONS.SYNC_CLIENT_SETTINGS,
// Disabled until we can overwrite preferences