i18n #80
32
app-strings.json
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"Content Interests": "Content Interests",
|
||||||
|
"Suggested channels": "Suggested channels",
|
||||||
|
"You might also like": "You might also like",
|
||||||
|
"Follow": "Follow",
|
||||||
|
"About": "About",
|
||||||
|
"Sign In": "Sign In",
|
||||||
|
"SIGN IN": "SIGN IN",
|
||||||
|
"FREE": "FREE",
|
||||||
|
"Anonymous": "Anonymous",
|
||||||
|
"An account with LBRY Inc. allows you to earn rewards, backup your wallet, and keep everything synced.": "An account with LBRY Inc. allows you to earn rewards, backup your wallet, and keep everything synced.",
|
||||||
|
"Without an account, you assume all responsibility for securing your wallet and LBRY data.": "Without an account, you assume all responsibility for securing your wallet and LBRY data.",
|
||||||
|
"Skip Account": "Skip Account",
|
||||||
|
"Sign Up": "Sign Up",
|
||||||
|
"Balance": "Balance",
|
||||||
|
"You currently have": "You currently have",
|
||||||
|
"Receive Credits": "Receive Credits",
|
||||||
|
"Use this wallet address to receive credits sent by another user (or yourself).": "Use this wallet address to receive credits sent by another user (or yourself).",
|
||||||
|
"Get new address": "Get new address",
|
||||||
|
"You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.": "You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.",
|
||||||
|
"Send Credits": "Send Credits",
|
||||||
|
"Recipient address": "Recipient address",
|
||||||
|
"Amount": "Amount",
|
||||||
|
"View All": "View All",
|
||||||
|
"Looks like you don't have any recent transactions.": "Looks like you don't have any recent transactions.",
|
||||||
|
"Wallet Sync": "Wallet Sync",
|
||||||
|
"Sync status": "Sync status",
|
||||||
|
"Off": "Off",
|
||||||
|
"Manual backup": "Manual backup",
|
||||||
|
"Sync FAQ": "Sync FAQ",
|
||||||
|
"Fetching transactions...": "Fetching transactions..."
|
||||||
|
}
|
|
@ -363,7 +363,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
this.setState({ verifyPending: false });
|
this.setState({ verifyPending: false });
|
||||||
|
|
||||||
NativeModules.Firebase.track('email_verified', { email: user.primary_email });
|
NativeModules.Firebase.track('email_verified', { email: user.primary_email });
|
||||||
ToastAndroid.show('Your email address was successfully verified.', ToastAndroid.LONG);
|
ToastAndroid.show(__('Your email address was successfully verified.'), ToastAndroid.LONG);
|
||||||
|
|
||||||
// get user settings after email verification
|
// get user settings after email verification
|
||||||
this.getUserSettings();
|
this.getUserSettings();
|
||||||
|
@ -400,7 +400,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
this.setState({ emailVerifyDone: true });
|
this.setState({ emailVerifyDone: true });
|
||||||
const message = emailVerifyErrorMessage
|
const message = emailVerifyErrorMessage
|
||||||
? String(emailVerifyErrorMessage)
|
? String(emailVerifyErrorMessage)
|
||||||
: 'Your email address was successfully verified.';
|
: __('Your email address was successfully verified.');
|
||||||
if (!emailVerifyErrorMessage) {
|
if (!emailVerifyErrorMessage) {
|
||||||
AsyncStorage.removeItem(Constants.KEY_FIRST_RUN_EMAIL);
|
AsyncStorage.removeItem(Constants.KEY_FIRST_RUN_EMAIL);
|
||||||
}
|
}
|
||||||
|
@ -455,7 +455,7 @@ class AppWithNavigationState extends React.Component {
|
||||||
try {
|
try {
|
||||||
dispatch(doUserEmailVerify(verification.token, verification.recaptcha));
|
dispatch(doUserEmailVerify(verification.token, verification.recaptcha));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = 'Invalid Verification Token';
|
const message = __('Invalid Verification Token');
|
||||||
dispatch(doUserEmailVerifyFailure(message));
|
dispatch(doUserEmailVerifyFailure(message));
|
||||||
dispatch(doToast({ message }));
|
dispatch(doToast({ message }));
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default class Address extends React.PureComponent<Props> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[walletStyle.row, style]}>
|
<View style={[walletStyle.row, style]}>
|
||||||
<Text selectable={true} numberOfLines={1} style={walletStyle.address}>
|
<Text selectable numberOfLines={1} style={walletStyle.address}>
|
||||||
{address || ''}
|
{address || ''}
|
||||||
</Text>
|
</Text>
|
||||||
<Button
|
<Button
|
||||||
|
@ -24,7 +24,7 @@ export default class Address extends React.PureComponent<Props> {
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
Clipboard.setString(address);
|
Clipboard.setString(address);
|
||||||
doToast({
|
doToast({
|
||||||
message: 'Address copied',
|
message: __('Address copied'),
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import CategoryList from './view';
|
|
||||||
|
|
||||||
export default connect()(CategoryList);
|
|
|
@ -1,39 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import NavigationActions from 'react-navigation';
|
|
||||||
import { FlatList, Text, View } from 'react-native';
|
|
||||||
import { normalizeURI } from 'lbry-redux';
|
|
||||||
import FileItem from '/component/fileItem';
|
|
||||||
import discoverStyle from 'styles/discover';
|
|
||||||
|
|
||||||
class CategoryList extends React.PureComponent {
|
|
||||||
render() {
|
|
||||||
const { category, categoryMap, navigation } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FlatList
|
|
||||||
style={discoverStyle.horizontalScrollContainer}
|
|
||||||
contentContainerStyle={discoverStyle.horizontalScrollPadding}
|
|
||||||
initialNumToRender={3}
|
|
||||||
maxToRenderPerBatch={3}
|
|
||||||
removeClippedSubviews={true}
|
|
||||||
renderItem={({ item }) => (
|
|
||||||
<FileItem
|
|
||||||
style={discoverStyle.fileItem}
|
|
||||||
mediaStyle={discoverStyle.fileItemMedia}
|
|
||||||
key={item}
|
|
||||||
uri={normalizeURI(item)}
|
|
||||||
navigation={navigation}
|
|
||||||
showDetails={true}
|
|
||||||
compactView={false}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
horizontal={true}
|
|
||||||
showsHorizontalScrollIndicator={false}
|
|
||||||
data={categoryMap[category]}
|
|
||||||
keyExtractor={(item, index) => item}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CategoryList;
|
|
|
@ -63,7 +63,7 @@ export default class ChannelIconItem extends React.PureComponent {
|
||||||
>
|
>
|
||||||
{isPlaceholder && (
|
{isPlaceholder && (
|
||||||
<View style={channelIconStyle.centered}>
|
<View style={channelIconStyle.centered}>
|
||||||
<Text style={channelIconStyle.placeholderText}>ALL</Text>
|
<Text style={channelIconStyle.placeholderText}>{__('ALL')}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{!isPlaceholder && thumbnail && (
|
{!isPlaceholder && thumbnail && (
|
||||||
|
|
|
@ -12,7 +12,9 @@ class ChannelRewardsDriver extends React.PureComponent<Props> {
|
||||||
<TouchableOpacity style={publishStyle.rewardDriverCard} onPress={() => navigation.navigate('Rewards')}>
|
<TouchableOpacity style={publishStyle.rewardDriverCard} onPress={() => navigation.navigate('Rewards')}>
|
||||||
<Icon name="award" size={16} style={publishStyle.rewardIcon} />
|
<Icon name="award" size={16} style={publishStyle.rewardIcon} />
|
||||||
<Text style={publishStyle.rewardDriverText}>
|
<Text style={publishStyle.rewardDriverText}>
|
||||||
Channel creation requires credits.{'\n'}Tap here to get some for free.
|
{__('Channel creation requires credits.')}
|
||||||
|
{'\n'}
|
||||||
|
{__('Tap here to get some for free.')}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -87,9 +87,9 @@ export default class ChannelSelector extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newChannelName.trim().length > 0 && !isNameValid(newChannelName)) {
|
if (newChannelName.trim().length > 0 && !isNameValid(newChannelName)) {
|
||||||
newChannelNameError = 'Your channel name contains invalid characters.';
|
newChannelNameError = __('Your channel name contains invalid characters.');
|
||||||
} else if (this.channelExists(newChannelName)) {
|
} else if (this.channelExists(newChannelName)) {
|
||||||
newChannelNameError = 'You have already created a channel with the same name.';
|
newChannelNameError = __('You have already created a channel with the same name.');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -122,17 +122,17 @@ export default class ChannelSelector extends React.PureComponent {
|
||||||
const { newChannelBid, newChannelName } = this.state;
|
const { newChannelBid, newChannelName } = this.state;
|
||||||
|
|
||||||
if (newChannelName.trim().length === 0 || !isNameValid(newChannelName.substr(1), false)) {
|
if (newChannelName.trim().length === 0 || !isNameValid(newChannelName.substr(1), false)) {
|
||||||
notify({ message: 'Your channel name contains invalid characters.' });
|
notify({ message: __('Your channel name contains invalid characters.') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.channelExists(newChannelName)) {
|
if (this.channelExists(newChannelName)) {
|
||||||
notify({ message: 'You have already created a channel with the same name.' });
|
notify({ message: __('You have already created a channel with the same name.') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newChannelBid > balance) {
|
if (newChannelBid > balance) {
|
||||||
notify({ message: 'Deposit cannot be higher than your balance' });
|
notify({ message: __('Deposit cannot be higher than your balance') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ export default class ChannelSelector extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
const failure = () => {
|
const failure = () => {
|
||||||
notify({ message: 'Unable to create channel due to an internal error.' });
|
notify({ message: __('Unable to create channel due to an internal error.') });
|
||||||
this.setState({
|
this.setState({
|
||||||
creatingChannel: false,
|
creatingChannel: false,
|
||||||
});
|
});
|
||||||
|
@ -227,7 +227,7 @@ export default class ChannelSelector extends React.PureComponent {
|
||||||
style={channelSelectorStyle.channelNameInput}
|
style={channelSelectorStyle.channelNameInput}
|
||||||
value={this.state.newChannelName}
|
value={this.state.newChannelName}
|
||||||
onChangeText={this.handleNewChannelNameChange}
|
onChangeText={this.handleNewChannelNameChange}
|
||||||
placeholder={'Channel name'}
|
placeholder={__('Channel name')}
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
@ -235,7 +235,7 @@ export default class ChannelSelector extends React.PureComponent {
|
||||||
<Text style={channelSelectorStyle.inlineError}>{newChannelNameError}</Text>
|
<Text style={channelSelectorStyle.inlineError}>{newChannelNameError}</Text>
|
||||||
)}
|
)}
|
||||||
<View style={channelSelectorStyle.bidRow}>
|
<View style={channelSelectorStyle.bidRow}>
|
||||||
<Text style={channelSelectorStyle.label}>Deposit</Text>
|
<Text style={channelSelectorStyle.label}>{__('Deposit')}</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
style={channelSelectorStyle.bidAmountInput}
|
style={channelSelectorStyle.bidAmountInput}
|
||||||
value={String(newChannelBid)}
|
value={String(newChannelBid)}
|
||||||
|
@ -247,18 +247,18 @@ export default class ChannelSelector extends React.PureComponent {
|
||||||
<Text style={channelSelectorStyle.currency}>LBC</Text>
|
<Text style={channelSelectorStyle.currency}>LBC</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={channelSelectorStyle.helpText}>
|
<Text style={channelSelectorStyle.helpText}>
|
||||||
This LBC remains yours. It is a deposit to reserve the name and can be undone at any time.
|
{__('This LBC remains yours. It is a deposit to reserve the name and can be undone at any time.')}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<View style={channelSelectorStyle.buttonContainer}>
|
<View style={channelSelectorStyle.buttonContainer}>
|
||||||
{creatingChannel && <ActivityIndicator size={'small'} color={Colors.LbryGreen} />}
|
{creatingChannel && <ActivityIndicator size={'small'} color={Colors.LbryGreen} />}
|
||||||
{!creatingChannel && (
|
{!creatingChannel && (
|
||||||
<View style={channelSelectorStyle.buttons}>
|
<View style={channelSelectorStyle.buttons}>
|
||||||
<Link style={channelSelectorStyle.cancelLink} text="Cancel" onPress={this.handleCreateCancel} />
|
<Link style={channelSelectorStyle.cancelLink} text={__('Cancel')} onPress={this.handleCreateCancel} />
|
||||||
<Button
|
<Button
|
||||||
style={channelSelectorStyle.createButton}
|
style={channelSelectorStyle.createButton}
|
||||||
disabled={!(newChannelName.trim().length > 0 && newChannelBid > 0)}
|
disabled={!(newChannelName.trim().length > 0 && newChannelBid > 0)}
|
||||||
text="Create"
|
text={__('Create')}
|
||||||
onPress={this.handleCreateChannelClick}
|
onPress={this.handleCreateChannelClick}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -155,7 +155,9 @@ class ClaimList extends React.PureComponent {
|
||||||
|
|
||||||
verticalListEmptyComponent = () => {
|
verticalListEmptyComponent = () => {
|
||||||
return (
|
return (
|
||||||
<Text style={claimListStyle.noContentText}>No content to display at this time. Please check back later.</Text>
|
<Text style={claimListStyle.noContentText}>
|
||||||
|
{__('No content to display at this time. Please check back later.')}
|
||||||
|
</Text>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ class CustomRewardCard extends React.PureComponent<Props> {
|
||||||
if (error && error.trim().length > 0) {
|
if (error && error.trim().length > 0) {
|
||||||
notify({ message: error });
|
notify({ message: error });
|
||||||
} else {
|
} else {
|
||||||
notify({ message: 'Reward successfully claimed!' });
|
notify({ message: __('Reward successfully claimed!') });
|
||||||
this.setState({ rewardCode: '' });
|
this.setState({ rewardCode: '' });
|
||||||
}
|
}
|
||||||
this.setState({ claimStarted: false });
|
this.setState({ claimStarted: false });
|
||||||
|
@ -37,12 +37,12 @@ class CustomRewardCard extends React.PureComponent<Props> {
|
||||||
if (showVerification) {
|
if (showVerification) {
|
||||||
showVerification();
|
showVerification();
|
||||||
}
|
}
|
||||||
notify({ message: 'Unfortunately, you are not eligible to claim this reward at this time.' });
|
notify({ message: __('Unfortunately, you are not eligible to claim this reward at this time.') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rewardCode || rewardCode.trim().length === 0) {
|
if (!rewardCode || rewardCode.trim().length === 0) {
|
||||||
notify({ message: 'Please enter a reward code to claim.' });
|
notify({ message: __('Please enter a reward code to claim.') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +60,9 @@ class CustomRewardCard extends React.PureComponent<Props> {
|
||||||
{rewardIsPending && <ActivityIndicator size="small" color={Colors.NextLbryGreen} />}
|
{rewardIsPending && <ActivityIndicator size="small" color={Colors.NextLbryGreen} />}
|
||||||
</View>
|
</View>
|
||||||
<View style={rewardStyle.midCol}>
|
<View style={rewardStyle.midCol}>
|
||||||
<Text style={rewardStyle.rewardTitle}>Custom Code</Text>
|
<Text style={rewardStyle.rewardTitle}>{__('Custom Code')}</Text>
|
||||||
<Text style={rewardStyle.rewardDescription}>
|
<Text style={rewardStyle.rewardDescription}>
|
||||||
Are you a supermodel or rockstar that received a custom reward code? Claim it here.
|
{__('Are you a supermodel or rockstar that received a custom reward code? Claim it here.')}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<View>
|
<View>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DrawerItems, SafeAreaView } from 'react-navigation';
|
import { DrawerItems, SafeAreaView } from 'react-navigation';
|
||||||
import { Image, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
import { Image, ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||||
|
import { __ } from 'i18n';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
|
@ -9,23 +10,23 @@ import discoverStyle from 'styles/discover';
|
||||||
|
|
||||||
const groupedMenuItems = {
|
const groupedMenuItems = {
|
||||||
'Find content': [
|
'Find content': [
|
||||||
{ icon: 'hashtag', label: 'Your Tags', route: Constants.DRAWER_ROUTE_DISCOVER },
|
{ icon: 'hashtag', label: __('Your Tags'), route: Constants.DRAWER_ROUTE_DISCOVER },
|
||||||
{ icon: 'heart', solid: true, label: 'Subscriptions', route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS },
|
{ icon: 'heart', solid: true, label: __('Subscriptions'), route: Constants.DRAWER_ROUTE_SUBSCRIPTIONS },
|
||||||
{ icon: 'globe-americas', label: 'All Content', route: Constants.DRAWER_ROUTE_TRENDING },
|
{ icon: 'globe-americas', label: __('All Content'), route: Constants.DRAWER_ROUTE_TRENDING },
|
||||||
],
|
],
|
||||||
'Your content': [
|
'Your content': [
|
||||||
{ icon: 'at', label: 'Channels', route: Constants.DRAWER_ROUTE_CHANNEL_CREATOR },
|
{ icon: 'at', label: __('Channels'), route: Constants.DRAWER_ROUTE_CHANNEL_CREATOR },
|
||||||
{ icon: 'download', label: 'Library', route: Constants.DRAWER_ROUTE_MY_LBRY },
|
{ icon: 'download', label: __('Library'), route: Constants.DRAWER_ROUTE_MY_LBRY },
|
||||||
{ icon: 'cloud-upload-alt', label: 'Publishes', route: Constants.DRAWER_ROUTE_PUBLISHES },
|
{ icon: 'cloud-upload-alt', label: __('Publishes'), route: Constants.DRAWER_ROUTE_PUBLISHES },
|
||||||
{ icon: 'upload', label: 'New Publish', route: Constants.DRAWER_ROUTE_PUBLISH },
|
{ icon: 'upload', label: __('New Publish'), route: Constants.DRAWER_ROUTE_PUBLISH },
|
||||||
],
|
],
|
||||||
Wallet: [
|
Wallet: [
|
||||||
{ icon: 'wallet', label: 'Wallet', route: Constants.DRAWER_ROUTE_WALLET },
|
{ icon: 'wallet', label: __('Wallet'), route: Constants.DRAWER_ROUTE_WALLET },
|
||||||
{ icon: 'award', label: 'Rewards', route: Constants.DRAWER_ROUTE_REWARDS },
|
{ icon: 'award', label: __('Rewards'), route: Constants.DRAWER_ROUTE_REWARDS },
|
||||||
],
|
],
|
||||||
Settings: [
|
Settings: [
|
||||||
{ icon: 'cog', label: 'Settings', route: Constants.DRAWER_ROUTE_SETTINGS },
|
{ icon: 'cog', label: __('Settings'), route: Constants.DRAWER_ROUTE_SETTINGS },
|
||||||
{ icon: 'info', label: 'About', route: Constants.DRAWER_ROUTE_ABOUT },
|
{ icon: 'info', label: __('About'), route: Constants.DRAWER_ROUTE_ABOUT },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ class DrawerContent extends React.PureComponent {
|
||||||
<Button
|
<Button
|
||||||
style={discoverStyle.signInButton}
|
style={discoverStyle.signInButton}
|
||||||
theme={'light'}
|
theme={'light'}
|
||||||
text={'Sign in'}
|
text={__('Sign in')}
|
||||||
onPress={this.launchSignInFlow}
|
onPress={this.launchSignInFlow}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -113,12 +114,12 @@ class DrawerContent extends React.PureComponent {
|
||||||
{!signedIn && (
|
{!signedIn && (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
accessible
|
accessible
|
||||||
accessibilityLabel={'Sign In'}
|
accessibilityLabel={__('Sign In')}
|
||||||
onPress={this.launchSignInFlow}
|
onPress={this.launchSignInFlow}
|
||||||
delayPressIn={0}
|
delayPressIn={0}
|
||||||
style={[discoverStyle.signInMenuItem, discoverStyle.signInMenuItemButton]}
|
style={[discoverStyle.signInMenuItem, discoverStyle.signInMenuItemButton]}
|
||||||
>
|
>
|
||||||
<Text style={discoverStyle.signInMenuItemButtonText}>SIGN IN</Text>
|
<Text style={discoverStyle.signInMenuItemButtonText}>{__('SIGN IN')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,8 @@ class FileDownloadButton extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
//this.checkAvailability(nextProps.uri);
|
// this.checkAvailability(nextProps.uri);
|
||||||
//this.restartDownload(nextProps);
|
// this.restartDownload(nextProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
restartDownload(props) {
|
restartDownload(props) {
|
||||||
|
@ -50,13 +50,11 @@ class FileDownloadButton extends React.PureComponent {
|
||||||
|
|
||||||
if ((fileInfo && !fileInfo.stopped) || loading || downloading) {
|
if ((fileInfo && !fileInfo.stopped) || loading || downloading) {
|
||||||
const progress = fileInfo && fileInfo.written_bytes ? (fileInfo.written_bytes / fileInfo.total_bytes) * 100 : 0,
|
const progress = fileInfo && fileInfo.written_bytes ? (fileInfo.written_bytes / fileInfo.total_bytes) * 100 : 0,
|
||||||
label = fileInfo ? progress.toFixed(0) + '% complete' : 'Connecting...';
|
label = fileInfo ? progress.toFixed(0) + '% complete' : __('Connecting...');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[style, fileDownloadButtonStyle.container]}>
|
<View style={[style, fileDownloadButtonStyle.container]}>
|
||||||
<View
|
<View style={{ width: `${progress}%`, backgroundColor: '#ff0000', position: 'absolute', left: 0, top: 0 }} />
|
||||||
style={{ width: `${progress}%`, backgroundColor: '#ff0000', position: 'absolute', left: 0, top: 0 }}
|
|
||||||
></View>
|
|
||||||
<Text style={fileDownloadButtonStyle.text}>{label}</Text>
|
<Text style={fileDownloadButtonStyle.text}>{label}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
@ -64,14 +62,14 @@ class FileDownloadButton extends React.PureComponent {
|
||||||
if (!costInfo) {
|
if (!costInfo) {
|
||||||
return (
|
return (
|
||||||
<View style={[style, fileDownloadButtonStyle.container]}>
|
<View style={[style, fileDownloadButtonStyle.container]}>
|
||||||
<Text style={fileDownloadButtonStyle.text}>Fetching cost info...</Text>
|
<Text style={fileDownloadButtonStyle.text}>{__('Fetching cost info...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
icon={isPlayable ? 'play' : null}
|
icon={isPlayable ? 'play' : null}
|
||||||
text={isPlayable ? 'Play' : isViewable ? 'View' : 'Download'}
|
text={isPlayable ? __('Play') : isViewable ? __('View') : __('Download')}
|
||||||
onLayout={onButtonLayout}
|
onLayout={onButtonLayout}
|
||||||
style={[style, fileDownloadButtonStyle.container]}
|
style={[style, fileDownloadButtonStyle.container]}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
@ -98,7 +96,7 @@ class FileDownloadButton extends React.PureComponent {
|
||||||
style={[style, fileDownloadButtonStyle.container]}
|
style={[style, fileDownloadButtonStyle.container]}
|
||||||
onPress={openFile}
|
onPress={openFile}
|
||||||
>
|
>
|
||||||
<Text style={fileDownloadButtonStyle.text}>{isViewable ? 'View' : 'Open'}</Text>
|
<Text style={fileDownloadButtonStyle.text}>{isViewable ? __('View') : __('Open')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ class FileItem extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!channelName && !isResolvingUri && <Text style={discoverStyle.anonChannelName}>Anonymous</Text>}
|
{!channelName && !isResolvingUri && <Text style={discoverStyle.anonChannelName}>{__('Anonymous')}</Text>}
|
||||||
<DateTime style={discoverStyle.dateTime} textStyle={discoverStyle.dateTimeText} timeAgo uri={uri} />
|
<DateTime style={discoverStyle.dateTime} textStyle={discoverStyle.dateTimeText} timeAgo uri={uri} />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -189,7 +189,7 @@ class FileListItem extends React.PureComponent {
|
||||||
|
|
||||||
{featuredResult && !isResolving && !claim && (
|
{featuredResult && !isResolving && !claim && (
|
||||||
<View style={fileListStyle.titleContainer}>
|
<View style={fileListStyle.titleContainer}>
|
||||||
<Text style={fileListStyle.featuredTitle}>Nothing here. Publish something!</Text>
|
<Text style={fileListStyle.featuredTitle}>{__('Nothing here. Publish something!')}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,16 @@ class CreditAmount extends React.PureComponent {
|
||||||
|
|
||||||
let amountText;
|
let amountText;
|
||||||
if (this.props.showFree && parseFloat(this.props.amount) === 0) {
|
if (this.props.showFree && parseFloat(this.props.amount) === 0) {
|
||||||
amountText = 'FREE';
|
amountText = __('FREE');
|
||||||
} else {
|
} else {
|
||||||
if (this.props.label) {
|
if (this.props.label) {
|
||||||
const label =
|
const label =
|
||||||
typeof this.props.label === 'string' ? this.props.label : parseFloat(amount) == 1 ? 'credit' : 'credits';
|
typeof this.props.label === 'string'
|
||||||
|
? this.props.label
|
||||||
|
: parseFloat(amount) === 1
|
||||||
|
? __('credit')
|
||||||
|
: __('credits');
|
||||||
|
// TODO: handling singular / plural in other languages?
|
||||||
|
|
||||||
amountText = `${formattedAmount} ${label}`;
|
amountText = `${formattedAmount} ${label}`;
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,14 +62,14 @@ class CreditAmount extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*{this.props.isEstimate ? (
|
/* {this.props.isEstimate ? (
|
||||||
<span
|
<span
|
||||||
className="credit-amount__estimate"
|
className="credit-amount__estimate"
|
||||||
title={__('This is an estimate and does not include data fees')}
|
title={__('This is an estimate and does not include data fees')}
|
||||||
>
|
>
|
||||||
*
|
*
|
||||||
</span>
|
</span>
|
||||||
) : null}*/
|
) : null} */
|
||||||
return <Text style={style}>{amountText}</Text>;
|
return <Text style={style}>{amountText}</Text>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ class FileRewardsDriver extends React.PureComponent<Props> {
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={filePageStyle.rewardDriverCard} onPress={() => navigation.navigate('Rewards')}>
|
<TouchableOpacity style={filePageStyle.rewardDriverCard} onPress={() => navigation.navigate('Rewards')}>
|
||||||
<Icon name="award" size={16} style={filePageStyle.rewardDriverIcon} />
|
<Icon name="award" size={16} style={filePageStyle.rewardDriverIcon} />
|
||||||
<Text style={filePageStyle.rewardDriverText}>Earn some credits to access this content.</Text>
|
<Text style={filePageStyle.rewardDriverText}>{__('Earn some credits to access this content.')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default class ModalSuggestedSubcriptions extends React.PureComponent {
|
||||||
<TouchableOpacity style={[modalStyle.container, subscriptionsStyle.modalContainer]} activeOpacity={1}>
|
<TouchableOpacity style={[modalStyle.container, subscriptionsStyle.modalContainer]} activeOpacity={1}>
|
||||||
<SuggestedSubscriptions inModal navigation={navigation} />
|
<SuggestedSubscriptions inModal navigation={navigation} />
|
||||||
<View style={modalStyle.buttons}>
|
<View style={modalStyle.buttons}>
|
||||||
<Button style={modalStyle.doneButton} text={'Done'} onPress={onDonePress} />
|
<Button style={modalStyle.doneButton} text={__('Done')} onPress={onDonePress} />
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
|
@ -8,7 +8,6 @@ import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Tag from 'component/tag';
|
import Tag from 'component/tag';
|
||||||
import TagSearch from 'component/tagSearch';
|
import TagSearch from 'component/tagSearch';
|
||||||
import modalTagSelectorStyle from 'styles/modalTagSelector';
|
import modalTagSelectorStyle from 'styles/modalTagSelector';
|
||||||
import { __ } from 'utils/helper';
|
|
||||||
|
|
||||||
const minimumTags = 2;
|
const minimumTags = 2;
|
||||||
|
|
||||||
|
@ -57,7 +56,7 @@ export default class ModalTagSelector extends React.PureComponent {
|
||||||
<TouchableOpacity style={modalTagSelectorStyle.overlay} activeOpacity={1} onPress={onOverlayPress}>
|
<TouchableOpacity style={modalTagSelectorStyle.overlay} activeOpacity={1} onPress={onOverlayPress}>
|
||||||
<TouchableOpacity style={modalTagSelectorStyle.container} activeOpacity={1}>
|
<TouchableOpacity style={modalTagSelectorStyle.container} activeOpacity={1}>
|
||||||
<View style={modalTagSelectorStyle.titleRow}>
|
<View style={modalTagSelectorStyle.titleRow}>
|
||||||
<Text style={modalTagSelectorStyle.title}>Customize your tags</Text>
|
<Text style={modalTagSelectorStyle.title}>{__('Customize your tags')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={modalTagSelectorStyle.tagList}>
|
<View style={modalTagSelectorStyle.tagList}>
|
||||||
{tags &&
|
{tags &&
|
||||||
|
@ -73,7 +72,7 @@ export default class ModalTagSelector extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
<TagSearch handleAddTag={this.handleAddTag} selectedTags={tags} />
|
<TagSearch handleAddTag={this.handleAddTag} selectedTags={tags} />
|
||||||
<View style={modalTagSelectorStyle.buttons}>
|
<View style={modalTagSelectorStyle.buttons}>
|
||||||
<Button style={modalTagSelectorStyle.doneButton} text={'Done'} onPress={onDonePress} />
|
<Button style={modalTagSelectorStyle.doneButton} text={__('Done')} onPress={onDonePress} />
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
|
@ -7,7 +7,7 @@ class NsfwOverlay extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={discoverStyle.overlay} activeOpacity={1} onPress={this.props.onPress}>
|
<TouchableOpacity style={discoverStyle.overlay} activeOpacity={1} onPress={this.props.onPress}>
|
||||||
<Text style={discoverStyle.overlayText}>
|
<Text style={discoverStyle.overlayText}>
|
||||||
This content is Not Safe For Work. To view adult content, please change your Settings.
|
{__('This content is Not Safe For Work. To view adult content, please change your Settings.')}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,7 +12,9 @@ class PublishRewardsDriver extends React.PureComponent<Props> {
|
||||||
<TouchableOpacity style={publishStyle.rewardDriverCard} onPress={() => navigation.navigate('Rewards')}>
|
<TouchableOpacity style={publishStyle.rewardDriverCard} onPress={() => navigation.navigate('Rewards')}>
|
||||||
<Icon name="award" size={16} style={publishStyle.rewardIcon} />
|
<Icon name="award" size={16} style={publishStyle.rewardIcon} />
|
||||||
<Text style={publishStyle.rewardDriverText}>
|
<Text style={publishStyle.rewardDriverText}>
|
||||||
Publishing requires credits.{'\n'}Tap here to get some for free.
|
{__('Publishing requires credits.')}
|
||||||
|
{'\n'}
|
||||||
|
{__('Tap here to get some for free.')}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -34,7 +34,7 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
notify({ message: errorMessage });
|
notify({ message: errorMessage });
|
||||||
clearError(reward);
|
clearError(reward);
|
||||||
} else {
|
} else {
|
||||||
notify({ message: 'Reward successfully claimed!' });
|
notify({ message: __('Reward successfully claimed!') });
|
||||||
}
|
}
|
||||||
this.setState({ claimStarted: false });
|
this.setState({ claimStarted: false });
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
if (showVerification) {
|
if (showVerification) {
|
||||||
showVerification();
|
showVerification();
|
||||||
}
|
}
|
||||||
notify({ message: 'Unfortunately, you are not eligible to claim this reward at this time.' });
|
notify({ message: __('Unfortunately, you are not eligible to claim this reward at this time.') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
style={rewardStyle.link}
|
style={rewardStyle.link}
|
||||||
href={`https://explorer.lbry.com/tx/${reward.transaction_id}`}
|
href={`https://explorer.lbry.com/tx/${reward.transaction_id}`}
|
||||||
text={reward.transaction_id.substring(0, 7)}
|
text={reward.transaction_id.substring(0, 7)}
|
||||||
error={'The transaction URL could not be opened'}
|
error={__('The transaction URL could not be opened')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -40,18 +40,24 @@ class RewardEnrolment extends React.Component {
|
||||||
|
|
||||||
<View style={rewardStyle.onboarding}>
|
<View style={rewardStyle.onboarding}>
|
||||||
<Text style={rewardStyle.enrollDescText}>
|
<Text style={rewardStyle.enrollDescText}>
|
||||||
LBRY credits allow you to purchase content, publish content, and influence the network.{'\n\n'}
|
{__('LBRY credits allow you to purchase content, publish content, and influence the network.')}
|
||||||
You get credits for free for providing an email address and taking other basic actions.{'\n\n'}
|
{'\n\n'}
|
||||||
<Link style={rewardStyle.learnMoreLink} text={'Learn more'} onPress={this.onLearnMorePressed} />.
|
{__('You get credits for free for providing an email address and taking other basic actions.')}
|
||||||
|
{'\n\n'}
|
||||||
|
<Link style={rewardStyle.learnMoreLink} text={__('Learn more')} onPress={this.onLearnMorePressed} />.
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={rewardStyle.buttonRow}>
|
<View style={rewardStyle.buttonRow}>
|
||||||
<Link style={rewardStyle.notInterestedLink} text={'Not interested'} onPress={this.onNotInterestedPressed} />
|
<Link
|
||||||
|
style={rewardStyle.notInterestedLink}
|
||||||
|
text={__('Not interested')}
|
||||||
|
onPress={this.onNotInterestedPressed}
|
||||||
|
/>
|
||||||
<Button
|
<Button
|
||||||
style={rewardStyle.enrollButton}
|
style={rewardStyle.enrollButton}
|
||||||
theme={'light'}
|
theme={'light'}
|
||||||
text={'Get started'}
|
text={__('Get started')}
|
||||||
onPress={this.onEnrollPressed}
|
onPress={this.onEnrollPressed}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { doToast } from 'lbry-redux';
|
|
||||||
import { doRewardList, selectUnclaimedRewardValue, selectFetchingRewards, selectUser } from 'lbryinc';
|
|
||||||
import RewardSummary from './view';
|
|
||||||
|
|
||||||
const select = state => ({
|
|
||||||
unclaimedRewardAmount: selectUnclaimedRewardValue(state),
|
|
||||||
fetching: selectFetchingRewards(state),
|
|
||||||
user: selectUser(state),
|
|
||||||
});
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
fetchRewards: () => dispatch(doRewardList()),
|
|
||||||
notify: data => dispatch(doToast(data)),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
select,
|
|
||||||
perform
|
|
||||||
)(RewardSummary);
|
|
|
@ -1,82 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { NativeModules, Text, TouchableOpacity, View } from 'react-native';
|
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
|
||||||
import Button from 'component/button';
|
|
||||||
import Colors from 'styles/colors';
|
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
|
||||||
import rewardStyle from 'styles/reward';
|
|
||||||
|
|
||||||
class RewardSummary extends React.Component {
|
|
||||||
static itemKey = 'rewardSummaryDismissed';
|
|
||||||
|
|
||||||
state = {
|
|
||||||
actionsLeft: 0,
|
|
||||||
dismissed: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.props.fetchRewards();
|
|
||||||
|
|
||||||
AsyncStorage.getItem(RewardSummary.itemKey).then(isDismissed => {
|
|
||||||
if (isDismissed === 'true') {
|
|
||||||
this.setState({ dismissed: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
const { user } = this.props;
|
|
||||||
let actionsLeft = 0;
|
|
||||||
if (!user || !user.has_verified_email) {
|
|
||||||
actionsLeft++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user || !user.is_identity_verified) {
|
|
||||||
actionsLeft++;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ actionsLeft });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onDismissPressed = () => {
|
|
||||||
AsyncStorage.setItem(RewardSummary.itemKey, 'true');
|
|
||||||
this.setState({ dismissed: true });
|
|
||||||
this.props.notify({
|
|
||||||
message: 'You can always claim your rewards from the Rewards page.',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSummaryPressed = () => {
|
|
||||||
const { showVerification } = this.props;
|
|
||||||
if (showVerification) {
|
|
||||||
showVerification();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { fetching, navigation, unclaimedRewardAmount, user } = this.props;
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
this.state.dismissed ||
|
|
||||||
(user && user.is_reward_approved) ||
|
|
||||||
this.state.actionsLeft === 0 ||
|
|
||||||
unclaimedRewardAmount === 0
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TouchableOpacity style={rewardStyle.summaryContainer} onPress={this.handleSummaryPressed}>
|
|
||||||
<View style={rewardStyle.summaryRow}>
|
|
||||||
<Icon name="award" size={36} color={Colors.White} />
|
|
||||||
<Text style={rewardStyle.summaryText}>{unclaimedRewardAmount} available credits</Text>
|
|
||||||
</View>
|
|
||||||
<Button style={rewardStyle.dismissButton} theme={'light'} text={'Dismiss'} onPress={this.onDismissPressed} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default RewardSummary;
|
|
|
@ -1,19 +0,0 @@
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { NativeModules } from 'react-native';
|
|
||||||
import { doSearch, doUpdateSearchQuery } from 'lbry-redux';
|
|
||||||
import SearchInput from './view';
|
|
||||||
|
|
||||||
const perform = dispatch => ({
|
|
||||||
search: search => {
|
|
||||||
if (NativeModules.Firebase) {
|
|
||||||
NativeModules.Firebase.track('search', { query: search });
|
|
||||||
}
|
|
||||||
return dispatch(doSearch(search));
|
|
||||||
},
|
|
||||||
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query, false)),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
null,
|
|
||||||
perform
|
|
||||||
)(SearchInput);
|
|
|
@ -1,41 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { TextInput } from 'react-native';
|
|
||||||
|
|
||||||
class SearchInput extends React.PureComponent {
|
|
||||||
static INPUT_TIMEOUT = 500;
|
|
||||||
|
|
||||||
state = {
|
|
||||||
changeTextTimeout: -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChangeText = text => {
|
|
||||||
clearTimeout(this.state.changeTextTimeout);
|
|
||||||
if (!text || text.trim().length < 2) {
|
|
||||||
// only perform a search if 2 or more characters have been input
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { search, updateSearchQuery } = this.props;
|
|
||||||
updateSearchQuery(text);
|
|
||||||
|
|
||||||
let timeout = setTimeout(() => {
|
|
||||||
search(text);
|
|
||||||
}, SearchInput.INPUT_TIMEOUT);
|
|
||||||
this.setState({ changeTextTimeout: timeout });
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { style, value } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TextInput
|
|
||||||
style={style}
|
|
||||||
placeholder="Search"
|
|
||||||
underlineColorAndroid="transparent"
|
|
||||||
value={value}
|
|
||||||
onChangeText={text => this.handleChangeText(text)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SearchInput;
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { normalizeURI, parseURI } from 'lbry-redux';
|
import { normalizeURI, parseURI } from 'lbry-redux';
|
||||||
import { ActivityIndicator, Platform, Switch, Text, TouchableOpacity, View } from 'react-native';
|
import { ActivityIndicator, Platform, Switch, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import { formatBytes } from '../../utils/helper';
|
import { formatBytes } from 'utils/helper';
|
||||||
import Colors from '../../styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import storageStatsStyle from '../../styles/storageStats';
|
import storageStatsStyle from 'styles/storageStats';
|
||||||
|
|
||||||
class StorageStatsCard extends React.PureComponent {
|
class StorageStatsCard extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
|
@ -98,28 +98,28 @@ class StorageStatsCard extends React.PureComponent {
|
||||||
{this.state.totalAudioBytes > 0 && (
|
{this.state.totalAudioBytes > 0 && (
|
||||||
<View style={[storageStatsStyle.row, storageStatsStyle.legendItem]}>
|
<View style={[storageStatsStyle.row, storageStatsStyle.legendItem]}>
|
||||||
<View style={[storageStatsStyle.legendBox, storageStatsStyle.audioDistribution]} />
|
<View style={[storageStatsStyle.legendBox, storageStatsStyle.audioDistribution]} />
|
||||||
<Text style={storageStatsStyle.legendText}>Audio</Text>
|
<Text style={storageStatsStyle.legendText}>{__('Audio')}</Text>
|
||||||
<Text style={storageStatsStyle.legendSize}>{formatBytes(this.state.totalAudioBytes, 2)}</Text>
|
<Text style={storageStatsStyle.legendSize}>{formatBytes(this.state.totalAudioBytes, 2)}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{this.state.totalImageBytes > 0 && (
|
{this.state.totalImageBytes > 0 && (
|
||||||
<View style={[storageStatsStyle.row, storageStatsStyle.legendItem]}>
|
<View style={[storageStatsStyle.row, storageStatsStyle.legendItem]}>
|
||||||
<View style={[storageStatsStyle.legendBox, storageStatsStyle.imageDistribution]} />
|
<View style={[storageStatsStyle.legendBox, storageStatsStyle.imageDistribution]} />
|
||||||
<Text style={storageStatsStyle.legendText}>Images</Text>
|
<Text style={storageStatsStyle.legendText}>{__('Images')}</Text>
|
||||||
<Text style={storageStatsStyle.legendSize}>{formatBytes(this.state.totalImageBytes, 2)}</Text>
|
<Text style={storageStatsStyle.legendSize}>{formatBytes(this.state.totalImageBytes, 2)}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{this.state.totalVideoBytes > 0 && (
|
{this.state.totalVideoBytes > 0 && (
|
||||||
<View style={[storageStatsStyle.row, storageStatsStyle.legendItem]}>
|
<View style={[storageStatsStyle.row, storageStatsStyle.legendItem]}>
|
||||||
<View style={[storageStatsStyle.legendBox, storageStatsStyle.videoDistribution]} />
|
<View style={[storageStatsStyle.legendBox, storageStatsStyle.videoDistribution]} />
|
||||||
<Text style={storageStatsStyle.legendText}>Videos</Text>
|
<Text style={storageStatsStyle.legendText}>{__('Videos')}</Text>
|
||||||
<Text style={storageStatsStyle.legendSize}>{formatBytes(this.state.totalVideoBytes, 2)}</Text>
|
<Text style={storageStatsStyle.legendSize}>{formatBytes(this.state.totalVideoBytes, 2)}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{this.state.totalOtherBytes > 0 && (
|
{this.state.totalOtherBytes > 0 && (
|
||||||
<View style={[storageStatsStyle.row, storageStatsStyle.legendItem]}>
|
<View style={[storageStatsStyle.row, storageStatsStyle.legendItem]}>
|
||||||
<View style={[storageStatsStyle.legendBox, storageStatsStyle.otherDistribution]} />
|
<View style={[storageStatsStyle.legendBox, storageStatsStyle.otherDistribution]} />
|
||||||
<Text style={storageStatsStyle.legendText}>Other</Text>
|
<Text style={storageStatsStyle.legendText}>{__('Other')}</Text>
|
||||||
<Text style={storageStatsStyle.legendSize}>{formatBytes(this.state.totalOtherBytes, 2)}</Text>
|
<Text style={storageStatsStyle.legendSize}>{formatBytes(this.state.totalOtherBytes, 2)}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ActivityIndicator, SectionList, Text, View } from 'react-native';
|
import { ActivityIndicator, SectionList, Text, View } from 'react-native';
|
||||||
import { MATURE_TAGS, createNormalizedClaimSearchKey, normalizeURI } from 'lbry-redux';
|
import { MATURE_TAGS, createNormalizedClaimSearchKey, normalizeURI } from 'lbry-redux';
|
||||||
import { __, navigateToUri } from 'utils/helper';
|
import { navigateToUri } from 'utils/helper';
|
||||||
import SubscribeButton from 'component/subscribeButton';
|
import SubscribeButton from 'component/subscribeButton';
|
||||||
import SuggestedSubscriptionItem from 'component/suggestedSubscriptionItem';
|
import SuggestedSubscriptionItem from 'component/suggestedSubscriptionItem';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
|
|
|
@ -89,7 +89,7 @@ export default class TagSearch extends React.PureComponent {
|
||||||
</KeyboardAvoidingView>
|
</KeyboardAvoidingView>
|
||||||
{showNsfwTags && (
|
{showNsfwTags && (
|
||||||
<View style={tagStyle.nsfwTagsContainer}>
|
<View style={tagStyle.nsfwTagsContainer}>
|
||||||
<Text style={tagStyle.nsfwTagsTitle}>Mature tags</Text>
|
<Text style={tagStyle.nsfwTagsTitle}>{__('Mature tags')}</Text>
|
||||||
<View style={tagStyle.tagResultsList}>
|
<View style={tagStyle.tagResultsList}>
|
||||||
{MATURE_TAGS.map(tag => (
|
{MATURE_TAGS.map(tag => (
|
||||||
<Tag
|
<Tag
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, View, Linking } from 'react-native';
|
import { Text, View, Linking } from 'react-native';
|
||||||
import { buildURI, formatCredits } from 'lbry-redux';
|
import { buildURI, formatCredits } from 'lbry-redux';
|
||||||
import { navigateToUri } from '../../../utils/helper';
|
import { navigateToUri } from 'utils/helper';
|
||||||
import Link from '../../link';
|
import Link from 'component/link';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import transactionListStyle from '../../../styles/transactionList';
|
import transactionListStyle from 'styles/transactionList';
|
||||||
|
|
||||||
class TransactionListItem extends React.PureComponent {
|
class TransactionListItem extends React.PureComponent {
|
||||||
capitalize(string: string) {
|
capitalize(string: string) {
|
||||||
|
@ -43,14 +43,14 @@ class TransactionListItem extends React.PureComponent {
|
||||||
style={transactionListStyle.smallLink}
|
style={transactionListStyle.smallLink}
|
||||||
text={txid.substring(0, 8)}
|
text={txid.substring(0, 8)}
|
||||||
href={`https://explorer.lbry.com/tx/${txid}`}
|
href={`https://explorer.lbry.com/tx/${txid}`}
|
||||||
error={'The transaction URL could not be opened'}
|
error={__('The transaction URL could not be opened')}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={transactionListStyle.col}>
|
<View style={transactionListStyle.col}>
|
||||||
{date ? (
|
{date ? (
|
||||||
<Text style={transactionListStyle.smallText}>{moment(date).format('MMM D')}</Text>
|
<Text style={transactionListStyle.smallText}>{moment(date).format('MMM D')}</Text>
|
||||||
) : (
|
) : (
|
||||||
<Text style={transactionListStyle.smallText}>Pending</Text>
|
<Text style={transactionListStyle.smallText}>{__('Pending')}</Text>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -47,7 +47,7 @@ class TransactionList extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{!transactionList.length && (
|
{!transactionList.length && (
|
||||||
<Text style={transactionListStyle.noTransactions}>{emptyMessage || 'No transactions to list.'}</Text>
|
<Text style={transactionListStyle.noTransactions}>{emptyMessage || __('No transactions to list.')}</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!!transactionList.length && (
|
{!!transactionList.length && (
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
// import BusyIndicator from 'component/common/busy-indicator';
|
// import BusyIndicator from 'component/common/busy-indicator';
|
||||||
import { Text, View } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import Button from '../button';
|
import Button from 'component/button';
|
||||||
import Link from '../link';
|
import Link from 'component/link';
|
||||||
import TransactionList from '../transactionList';
|
import TransactionList from 'component/transactionList';
|
||||||
import type { Transaction } from '../transactionList/view';
|
import type { Transaction } from 'component/transactionList/view';
|
||||||
import walletStyle from '../../styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
fetchTransactions: () => void,
|
fetchTransactions: () => void,
|
||||||
|
@ -27,14 +27,14 @@ class TransactionListRecent extends React.PureComponent<Props> {
|
||||||
<View style={walletStyle.transactionsCard}>
|
<View style={walletStyle.transactionsCard}>
|
||||||
<View style={[walletStyle.row, walletStyle.transactionsHeader]}>
|
<View style={[walletStyle.row, walletStyle.transactionsHeader]}>
|
||||||
<Text style={walletStyle.transactionsTitle}>Recent Transactions</Text>
|
<Text style={walletStyle.transactionsTitle}>Recent Transactions</Text>
|
||||||
<Link style={walletStyle.link} navigation={navigation} text={'View All'} href={'#TransactionHistory'} />
|
<Link style={walletStyle.link} navigation={navigation} text={__('View All')} href={'#TransactionHistory'} />
|
||||||
</View>
|
</View>
|
||||||
{fetchingTransactions && <Text style={walletStyle.infoText}>Fetching transactions...</Text>}
|
{fetchingTransactions && <Text style={walletStyle.infoText}>{__('Fetching transactions...')}</Text>}
|
||||||
{!fetchingTransactions && (
|
{!fetchingTransactions && (
|
||||||
<TransactionList
|
<TransactionList
|
||||||
navigation={navigation}
|
navigation={navigation}
|
||||||
transactions={transactions.slice(0, 5)}
|
transactions={transactions.slice(0, 5)}
|
||||||
emptyMessage={"Looks like you don't have any recent transactions."}
|
emptyMessage={__("Looks like you don't have any recent transactions.")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -27,21 +27,22 @@ class WalletAddress extends React.PureComponent<Props> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={walletStyle.card}>
|
<View style={walletStyle.card}>
|
||||||
<Text style={walletStyle.title}>Receive Credits</Text>
|
<Text style={walletStyle.title}>{__('Receive Credits')}</Text>
|
||||||
<Text style={[walletStyle.text, walletStyle.bottomMarginMedium]}>
|
<Text style={[walletStyle.text, walletStyle.bottomMarginMedium]}>
|
||||||
Use this wallet address to receive credits sent by another user (or yourself).
|
{__('Use this wallet address to receive credits sent by another user (or yourself).')}
|
||||||
</Text>
|
</Text>
|
||||||
<Address address={receiveAddress} style={walletStyle.bottomMarginSmall} />
|
<Address address={receiveAddress} style={walletStyle.bottomMarginSmall} />
|
||||||
<Button
|
<Button
|
||||||
style={[walletStyle.button, walletStyle.bottomMarginLarge]}
|
style={[walletStyle.button, walletStyle.bottomMarginLarge]}
|
||||||
icon={'sync'}
|
icon={'sync'}
|
||||||
text={'Get new address'}
|
text={__('Get new address')}
|
||||||
onPress={getNewAddress}
|
onPress={getNewAddress}
|
||||||
disabled={gettingNewAddress}
|
disabled={gettingNewAddress}
|
||||||
/>
|
/>
|
||||||
<Text style={walletStyle.smallText}>
|
<Text style={walletStyle.smallText}>
|
||||||
You can generate a new address at any time, and any previous addresses will continue to work. Using multiple
|
{__(
|
||||||
addresses can be helpful for keeping track of incoming payments from multiple sources.
|
'You can generate a new address at any time, and any previous addresses will continue to work. Using multiple addresses can be helpful for keeping track of incoming payments from multiple sources.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,8 +16,8 @@ class WalletBalance extends React.PureComponent<Props> {
|
||||||
return (
|
return (
|
||||||
<View style={walletStyle.balanceCard}>
|
<View style={walletStyle.balanceCard}>
|
||||||
<Image style={walletStyle.balanceBackground} resizeMode={'cover'} source={require('../../assets/stripe.png')} />
|
<Image style={walletStyle.balanceBackground} resizeMode={'cover'} source={require('../../assets/stripe.png')} />
|
||||||
<Text style={walletStyle.balanceTitle}>Balance</Text>
|
<Text style={walletStyle.balanceTitle}>{__('Balance')}</Text>
|
||||||
<Text style={walletStyle.balanceCaption}>You currently have</Text>
|
<Text style={walletStyle.balanceCaption}>{__('You currently have')}</Text>
|
||||||
<Text style={walletStyle.balance}>
|
<Text style={walletStyle.balance}>
|
||||||
{(balance || balance === 0) && formatCredits(parseFloat(balance), 2) + ' LBC'}
|
{(balance || balance === 0) && formatCredits(parseFloat(balance), 2) + ' LBC'}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -38,24 +38,24 @@ class WalletSend extends React.PureComponent<Props> {
|
||||||
const { address, amount } = this.state;
|
const { address, amount } = this.state;
|
||||||
if (address && !regexAddress.test(address)) {
|
if (address && !regexAddress.test(address)) {
|
||||||
notify({
|
notify({
|
||||||
message: 'The recipient address is not a valid LBRY address.',
|
message: __('The recipient address is not a valid LBRY address.'),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount > balance) {
|
if (amount > balance) {
|
||||||
notify({
|
notify({
|
||||||
message: 'Insufficient credits',
|
message: __('Insufficient credits'),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount && address) {
|
if (amount && address) {
|
||||||
// Show confirmation before send
|
// Show confirmation before send
|
||||||
Alert.alert('Send LBC', `Are you sure you want to send ${amount} LBC to ${address}?`, [
|
Alert.alert(__('Send LBC'), `Are you sure you want to send ${amount} LBC to ${address}?`, [
|
||||||
{ text: 'No' },
|
{ text: __('No') },
|
||||||
{
|
{
|
||||||
text: 'Yes',
|
text: __('Yes'),
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
sendToAddress(address, parseFloat(amount));
|
sendToAddress(address, parseFloat(amount));
|
||||||
this.setState({ address: null, amount: null });
|
this.setState({ address: null, amount: null });
|
||||||
|
@ -69,7 +69,7 @@ class WalletSend extends React.PureComponent<Props> {
|
||||||
if (this.state.addressChanged && !this.state.addressValid) {
|
if (this.state.addressChanged && !this.state.addressValid) {
|
||||||
const { notify } = this.props;
|
const { notify } = this.props;
|
||||||
notify({
|
notify({
|
||||||
message: 'The recipient address is not a valid LBRY address.',
|
message: __('The recipient address is not a valid LBRY address.'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -87,8 +87,8 @@ class WalletSend extends React.PureComponent<Props> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={walletStyle.card}>
|
<View style={walletStyle.card}>
|
||||||
<Text style={walletStyle.title}>Send Credits</Text>
|
<Text style={walletStyle.title}>{__('Send Credits')}</Text>
|
||||||
<Text style={walletStyle.text}>Recipient address</Text>
|
<Text style={walletStyle.text}>{__('Recipient address')}</Text>
|
||||||
<View style={[walletStyle.row, walletStyle.bottomMarginMedium]}>
|
<View style={[walletStyle.row, walletStyle.bottomMarginMedium]}>
|
||||||
<TextInput
|
<TextInput
|
||||||
onChangeText={value =>
|
onChangeText={value =>
|
||||||
|
@ -112,7 +112,7 @@ class WalletSend extends React.PureComponent<Props> {
|
||||||
onPress={() => Clipboard.getString().then(value => this.setState({ address: value, addressChanged: true }))}
|
onPress={() => Clipboard.getString().then(value => this.setState({ address: value, addressChanged: true }))}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<Text style={walletStyle.text}>Amount</Text>
|
<Text style={walletStyle.text}>{__('Amount')}</Text>
|
||||||
<View style={walletStyle.row}>
|
<View style={walletStyle.row}>
|
||||||
<View style={walletStyle.amountRow}>
|
<View style={walletStyle.amountRow}>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|
|
@ -34,15 +34,22 @@ class WalletSignIn extends React.Component {
|
||||||
|
|
||||||
<View style={walletStyle.onboarding}>
|
<View style={walletStyle.onboarding}>
|
||||||
<Text style={walletStyle.onboardingText}>
|
<Text style={walletStyle.onboardingText}>
|
||||||
An account with LBRY Inc. allows you to earn rewards, backup your wallet, and keep everything synced..
|
{__(
|
||||||
|
'An account with LBRY Inc. allows you to earn rewards, backup your wallet, and keep everything synced.'
|
||||||
|
)}
|
||||||
{'\n\n'}
|
{'\n\n'}
|
||||||
Without an account, you assume all responsibility for securing your wallet and LBRY data.{'\n\n'}
|
{__('Without an account, you assume all responsibility for securing your wallet and LBRY data.')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={walletStyle.buttonRow}>
|
<View style={walletStyle.buttonRow}>
|
||||||
<Link style={walletStyle.continueLink} text={'Skip Account'} onPress={this.onContinuePressed} />
|
<Link style={walletStyle.continueLink} text={__('Skip Account')} onPress={this.onContinuePressed} />
|
||||||
<Button style={walletStyle.signInButton} theme={'light'} text={'Sign Up'} onPress={this.onSignInPressed} />
|
<Button
|
||||||
|
style={walletStyle.signInButton}
|
||||||
|
theme={'light'}
|
||||||
|
text={__('Sign Up')}
|
||||||
|
onPress={this.onSignInPressed}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Alert, NativeModules, Switch, Text, View } from 'react-native';
|
import { Alert, NativeModules, Switch, Text, View } from 'react-native';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Constants from 'constants';
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import walletStyle from 'styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
|
|
||||||
|
@ -15,15 +15,15 @@ class WalletSyncDriver extends React.PureComponent<Props> {
|
||||||
// turning off
|
// turning off
|
||||||
// set deviceWalletSynced to false (if confirmed)
|
// set deviceWalletSynced to false (if confirmed)
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
'Disable wallet sync',
|
__('Disable wallet sync'),
|
||||||
'Are you sure you want to turn off wallet sync?',
|
__('Are you sure you want to turn off wallet sync?'),
|
||||||
[
|
[
|
||||||
{ text: 'No' },
|
{ text: __('No') },
|
||||||
{
|
{
|
||||||
text: 'Yes',
|
text: __('Yes'),
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
setClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED, false);
|
setClientSetting(Constants.SETTING_DEVICE_WALLET_SYNCED, false);
|
||||||
notify({ message: 'Wallet sync was successfully disabled.' });
|
notify({ message: __('Wallet sync was successfully disabled.') });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -37,14 +37,14 @@ class WalletSyncDriver extends React.PureComponent<Props> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={walletStyle.syncDriverCard}>
|
<View style={walletStyle.syncDriverCard}>
|
||||||
<Text style={walletStyle.syncDriverTitle}>Wallet Sync</Text>
|
<Text style={walletStyle.syncDriverTitle}>{__('Wallet Sync')}</Text>
|
||||||
<View style={walletStyle.switchRow}>
|
<View style={walletStyle.switchRow}>
|
||||||
<View style={walletStyle.tableCol}>
|
<View style={walletStyle.tableCol}>
|
||||||
<Text style={walletStyle.labelText}>Sync status</Text>
|
<Text style={walletStyle.labelText}>{__('Sync status')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={walletStyle.tableColRow}>
|
<View style={walletStyle.tableColRow}>
|
||||||
<Text selectable={true} style={walletStyle.valueText}>
|
<Text selectable style={walletStyle.valueText}>
|
||||||
{deviceWalletSynced ? 'On' : 'Off'}
|
{deviceWalletSynced ? __('On') : __('Off')}
|
||||||
</Text>
|
</Text>
|
||||||
<Switch
|
<Switch
|
||||||
style={walletStyle.syncSwitch}
|
style={walletStyle.syncSwitch}
|
||||||
|
@ -56,11 +56,11 @@ class WalletSyncDriver extends React.PureComponent<Props> {
|
||||||
{deviceWalletSynced && (
|
{deviceWalletSynced && (
|
||||||
<View style={walletStyle.tableRow}>
|
<View style={walletStyle.tableRow}>
|
||||||
<View style={walletStyle.tableCol}>
|
<View style={walletStyle.tableCol}>
|
||||||
<Text style={walletStyle.labelText}>Connected email</Text>
|
<Text style={walletStyle.labelText}>{__('Connected email')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={walletStyle.tableCol}>
|
<View style={walletStyle.tableCol}>
|
||||||
<Text selectable={true} style={walletStyle.valueText}>
|
<Text selectable style={walletStyle.valueText}>
|
||||||
{userEmail ? userEmail : 'No connected email'}
|
{userEmail || __('No connected email')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
@ -69,7 +69,7 @@ class WalletSyncDriver extends React.PureComponent<Props> {
|
||||||
<View style={walletStyle.linkRow}>
|
<View style={walletStyle.linkRow}>
|
||||||
<View style={walletStyle.tableCol}>
|
<View style={walletStyle.tableCol}>
|
||||||
<Link
|
<Link
|
||||||
text="Manual backup"
|
text={__('Manual backup')}
|
||||||
href="https://lbry.com/faq/how-to-backup-wallet#android"
|
href="https://lbry.com/faq/how-to-backup-wallet#android"
|
||||||
style={walletStyle.syncDriverLink}
|
style={walletStyle.syncDriverLink}
|
||||||
/>
|
/>
|
||||||
|
@ -77,7 +77,7 @@ class WalletSyncDriver extends React.PureComponent<Props> {
|
||||||
<View style={walletStyle.rightTableCol}>
|
<View style={walletStyle.rightTableCol}>
|
||||||
{!deviceWalletSynced && (
|
{!deviceWalletSynced && (
|
||||||
<Link
|
<Link
|
||||||
text="Sync FAQ"
|
text={__('Sync FAQ')}
|
||||||
href="https://lbry.com/faq/how-to-backup-wallet#sync"
|
href="https://lbry.com/faq/how-to-backup-wallet#sync"
|
||||||
style={[walletStyle.syncDriverLink, walletStyle.rightLink]}
|
style={[walletStyle.syncDriverLink, walletStyle.rightLink]}
|
||||||
/>
|
/>
|
||||||
|
|
66
src/i18n.js
Normal file
|
@ -0,0 +1,66 @@
|
||||||
No, the commented code can be removed. No, the commented code can be removed.
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
import { NativeModules, Platform } from 'react-native';
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
import RNFS from 'react-native-fs';
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
const isProduction = !__DEV__; // eslint-disable-line no-undef
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
let knownMessages = null;
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
window.i18n_messages = window.i18n_messages || {};
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
function saveMessage(message) {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
const messagesFilePath = RNFS.ExternalDirectoryPath + '/app-strings.json';
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
console.log(messagesFilePath);
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
if (knownMessages === null) {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
RNFS.readFile(messagesFilePath, 'utf8')
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
.then(fileContents => {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
knownMessages = JSON.parse(fileContents);
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
checkMessageAndSave(message, messagesFilePath);
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
})
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
.catch(err => {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
knownMessages = {}; // no known messages, initialise the object
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
checkMessageAndSave(message, messagesFilePath);
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
});
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
} else {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
checkMessageAndSave(message, messagesFilePath);
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
}
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
}
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
function checkMessageAndSave(message, messagesFilePath) {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
if (!knownMessages[message]) {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
knownMessages[message] = message;
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
RNFS.writeFile(messagesFilePath, JSON.stringify(knownMessages, null, 2), 'utf8')
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
.then(() => {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
// successful write
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
})
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
.catch(err => {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
if (err) {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
throw err;
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
}
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
});
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
}
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
}
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
export function __(message, tokens) {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
let language =
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
Platform.OS === 'android'
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
? NativeModules.I18nManager.localeIdentifier
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
: NativeModules.SettingsManager.settings.AppleLocale;
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
language = language ? language.substring(0, 2) : 'en';
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
console.log('LANG=' + language);
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
if (!isProduction) {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
saveMessage(message);
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
}
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
const translatedMessage = window.i18n_messages[language]
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
? window.i18n_messages[language][message] || message
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
: message;
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
if (!tokens) {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
return translatedMessage;
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
}
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
return translatedMessage.replace(/%([^%]+)%/g, function($1, $2) {
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
return tokens[$2] || $2;
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
});
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|||||||
|
}
|
||||||
do you want this here? do you want this here?
No, the commented code can be removed. No, the commented code can be removed.
|
|
@ -40,6 +40,7 @@ import AppWithNavigationState, {
|
||||||
reactNavigationMiddleware,
|
reactNavigationMiddleware,
|
||||||
} from 'component/AppNavigator';
|
} from 'component/AppNavigator';
|
||||||
import { REHYDRATE, PURGE, persistCombineReducers, persistStore } from 'redux-persist';
|
import { REHYDRATE, PURGE, persistCombineReducers, persistStore } from 'redux-persist';
|
||||||
|
import { __ } from 'i18n';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import getStoredStateMigrateV4 from 'redux-persist/lib/integration/getStoredStateMigrateV4';
|
import getStoredStateMigrateV4 from 'redux-persist/lib/integration/getStoredStateMigrateV4';
|
||||||
import FilesystemStorage from 'redux-persist-filesystem-storage';
|
import FilesystemStorage from 'redux-persist-filesystem-storage';
|
||||||
|
@ -51,6 +52,8 @@ import drawerReducer from 'redux/reducers/drawer';
|
||||||
import settingsReducer from 'redux/reducers/settings';
|
import settingsReducer from 'redux/reducers/settings';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
|
|
||||||
|
window.__ = __;
|
||||||
|
|
||||||
const globalExceptionHandler = (error, isFatal) => {
|
const globalExceptionHandler = (error, isFatal) => {
|
||||||
if (error && NativeModules.Firebase) {
|
if (error && NativeModules.Firebase) {
|
||||||
NativeModules.Firebase.logException(isFatal, error.message ? error.message : 'No message', JSON.stringify(error));
|
NativeModules.Firebase.logException(isFatal, error.message ? error.message : 'No message', JSON.stringify(error));
|
||||||
|
@ -201,9 +204,6 @@ const persistor = persistStore(store, persistOptions, err => {
|
||||||
});
|
});
|
||||||
window.persistor = persistor;
|
window.persistor = persistor;
|
||||||
|
|
||||||
// TODO: Find i18n module that is compatible with react-native
|
|
||||||
global.__ = str => str;
|
|
||||||
|
|
||||||
class LBRYApp extends React.Component {
|
class LBRYApp extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -11,10 +11,9 @@ import {
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { DEFAULT_FOLLOWED_TAGS, Lbry, normalizeURI, parseURI } from 'lbry-redux';
|
import { DEFAULT_FOLLOWED_TAGS, Lbry, normalizeURI, parseURI } from 'lbry-redux';
|
||||||
import { __, formatTagTitle, getOrderBy } from 'utils/helper';
|
import { formatTagTitle, getOrderBy } from 'utils/helper';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import CategoryList from 'component/categoryList';
|
|
||||||
import ClaimList from 'component/claimList';
|
import ClaimList from 'component/claimList';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
View,
|
View,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { __, navigateToUri, uriFromFileInfo } from 'utils/helper';
|
import { navigateToUri, uriFromFileInfo } from 'utils/helper';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import PageHeader from 'component/pageHeader';
|
import PageHeader from 'component/pageHeader';
|
||||||
|
@ -116,12 +116,12 @@ class DownloadsPage extends React.PureComponent {
|
||||||
|
|
||||||
// show confirm alert
|
// show confirm alert
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
__('Delete files'),
|
'Delete files',
|
||||||
__('Are you sure you want to delete the selected content?'),
|
'Are you sure you want to delete the selected content?',
|
||||||
[
|
[
|
||||||
{ text: __('No') },
|
{ text: 'No' },
|
||||||
{
|
{
|
||||||
text: __('Yes'),
|
text: 'Yes',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
const uris = Object.keys(selectedClaimsMap);
|
const uris = Object.keys(selectedClaimsMap);
|
||||||
uris.forEach(uri => {
|
uris.forEach(uri => {
|
||||||
|
|
|
@ -45,7 +45,7 @@ import Tag from 'component/tag';
|
||||||
import TagSearch from 'component/tagSearch';
|
import TagSearch from 'component/tagSearch';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import publishStyle from 'styles/publish';
|
import publishStyle from 'styles/publish';
|
||||||
import { __, navigateToUri, logPublish, uploadImageAsset } from 'utils/helper';
|
import { navigateToUri, logPublish, uploadImageAsset } from 'utils/helper';
|
||||||
|
|
||||||
const languages = {
|
const languages = {
|
||||||
en: 'English',
|
en: 'English',
|
||||||
|
|
|
@ -8,7 +8,7 @@ import FileListItem from 'component/fileListItem';
|
||||||
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
import FloatingWalletBalance from 'component/floatingWalletBalance';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import publishStyle from 'styles/publish';
|
import publishStyle from 'styles/publish';
|
||||||
import { __, navigateToUri } from 'utils/helper';
|
import { navigateToUri } from 'utils/helper';
|
||||||
|
|
||||||
class PublishesPage extends React.PureComponent {
|
class PublishesPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import CustomRewardCard from 'component/customRewardCard';
|
||||||
import PageHeader from 'component/pageHeader';
|
import PageHeader from 'component/pageHeader';
|
||||||
import RewardCard from 'component/rewardCard';
|
import RewardCard from 'component/rewardCard';
|
||||||
import RewardEnrolment from 'component/rewardEnrolment';
|
import RewardEnrolment from 'component/rewardEnrolment';
|
||||||
import RewardSummary from 'component/rewardSummary';
|
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import rewardStyle from 'styles/reward';
|
import rewardStyle from 'styles/reward';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SETTINGS } from 'lbry-redux';
|
import { SETTINGS } from 'lbry-redux';
|
||||||
import { Text, View, ScrollView, Switch, NativeModules } from 'react-native';
|
import { Text, View, ScrollView, Switch, NativeModules } from 'react-native';
|
||||||
import { __, navigateBack } from 'utils/helper';
|
import { navigateBack } from 'utils/helper';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import PageHeader from 'component/pageHeader';
|
import PageHeader from 'component/pageHeader';
|
||||||
import settingsStyle from 'styles/settings';
|
import settingsStyle from 'styles/settings';
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { buildURI, parseURI } from 'lbry-redux';
|
import { buildURI, parseURI } from 'lbry-redux';
|
||||||
import { __, getOrderBy } from 'utils/helper';
|
import { getOrderBy } from 'utils/helper';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
|
do you want this here?