i18n (#80)
* i18n all the strings * assign file content * download and save language files * load language on startup * load language setting correctly when app launches * fix i18n calls in constants * pin lbryinc commit
This commit is contained in:
parent
1a190fb0fe
commit
184d5d1ec3
74 changed files with 703 additions and 590 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -5649,8 +5649,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lbryinc": {
|
"lbryinc": {
|
||||||
"version": "github:lbryio/lbryinc#27b6fcb8391b54cc9ea4d0a52a6ee536e39aa166",
|
"version": "github:lbryio/lbryinc#9ffb883cc11e36d55a729c65b70c405a4a56d35e",
|
||||||
"from": "github:lbryio/lbryinc#27b6fcb8391b54cc9ea4d0a52a6ee536e39aa166",
|
"from": "github:lbryio/lbryinc#9ffb883cc11e36d55a729c65b70c405a4a56d35e",
|
||||||
"requires": {
|
"requires": {
|
||||||
"reselect": "^3.0.0"
|
"reselect": "^3.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"@expo/vector-icons": "^8.1.0",
|
"@expo/vector-icons": "^8.1.0",
|
||||||
"gfycat-style-urls": "^1.0.3",
|
"gfycat-style-urls": "^1.0.3",
|
||||||
"lbry-redux": "lbryio/lbry-redux#8ac92e3abfa0a9aacdb2fa4a144c3fadc4da6b11",
|
"lbry-redux": "lbryio/lbry-redux#8ac92e3abfa0a9aacdb2fa4a144c3fadc4da6b11",
|
||||||
"lbryinc": "lbryio/lbryinc#27b6fcb8391b54cc9ea4d0a52a6ee536e39aa166",
|
"lbryinc": "lbryio/lbryinc#9ffb883cc11e36d55a729c65b70c405a4a56d35e",
|
||||||
"lodash": ">=4.17.11",
|
"lodash": ">=4.17.11",
|
||||||
"merge": ">=1.2.1",
|
"merge": ">=1.2.1",
|
||||||
"moment": "^2.22.1",
|
"moment": "^2.22.1",
|
||||||
|
|
|
@ -364,7 +364,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();
|
||||||
|
@ -401,7 +401,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);
|
||||||
}
|
}
|
||||||
|
@ -476,7 +476,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,
|
||||||
});
|
});
|
||||||
|
@ -214,7 +214,11 @@ export default class ChannelSelector extends React.PureComponent {
|
||||||
onValueChange={this.handlePickerValueChange}
|
onValueChange={this.handlePickerValueChange}
|
||||||
>
|
>
|
||||||
{pickerItems.map(item => (
|
{pickerItems.map(item => (
|
||||||
<Picker.Item label={item} value={item} key={item} />
|
<Picker.Item
|
||||||
|
label={[Constants.ITEM_ANONYMOUS, Constants.ITEM_CREATE_A_CHANNEL].includes(item) ? __(item) : item}
|
||||||
|
value={item}
|
||||||
|
key={item}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</Picker>
|
</Picker>
|
||||||
|
|
||||||
|
@ -227,7 +231,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 +239,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 +251,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>
|
||||||
|
|
|
@ -77,7 +77,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 +113,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>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ class DrawerContent extends React.PureComponent {
|
||||||
<View key={groupName} style={discoverStyle.menuGroup}>
|
<View key={groupName} style={discoverStyle.menuGroup}>
|
||||||
{groupNames[3] !== groupName && (
|
{groupNames[3] !== groupName && (
|
||||||
<Text key={`${groupName}-title`} style={discoverStyle.menuGroupName}>
|
<Text key={`${groupName}-title`} style={discoverStyle.menuGroupName}>
|
||||||
{groupName}
|
{__(groupName)}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
{menuItems.map(item => {
|
{menuItems.map(item => {
|
||||||
|
@ -150,7 +150,7 @@ class DrawerContent extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
accessible
|
accessible
|
||||||
accessibilityLabel={item.label}
|
accessibilityLabel={__(item.label)}
|
||||||
style={[
|
style={[
|
||||||
discoverStyle.menuItemTouchArea,
|
discoverStyle.menuItemTouchArea,
|
||||||
focused ? discoverStyle.menuItemTouchAreaFocused : null,
|
focused ? discoverStyle.menuItemTouchAreaFocused : null,
|
||||||
|
@ -168,7 +168,7 @@ class DrawerContent extends React.PureComponent {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[discoverStyle.menuItem, focused ? discoverStyle.menuItemFocused : null]}>
|
<Text style={[discoverStyle.menuItem, focused ? discoverStyle.menuItemFocused : null]}>
|
||||||
{item.label}
|
{__(item.label)}
|
||||||
</Text>
|
</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>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -61,6 +61,7 @@ class FileItemMedia extends React.PureComponent {
|
||||||
let style = this.props.style;
|
let style = this.props.style;
|
||||||
const { duration, isResolvingUri, thumbnail, title, resizeMode } = this.props;
|
const { duration, isResolvingUri, thumbnail, title, resizeMode } = this.props;
|
||||||
const atStyle = this.state.autoThumbStyle;
|
const atStyle = this.state.autoThumbStyle;
|
||||||
|
|
||||||
if (this.isThumbnailValid(thumbnail) && !this.state.imageLoadFailed) {
|
if (this.isThumbnailValid(thumbnail) && !this.state.imageLoadFailed) {
|
||||||
if (style == null) {
|
if (style == null) {
|
||||||
style = fileItemMediaStyle.thumbnail;
|
style = fileItemMediaStyle.thumbnail;
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ export default class ModalPicker extends React.PureComponent {
|
||||||
onPress={() => onItemSelected(item)}
|
onPress={() => onItemSelected(item)}
|
||||||
>
|
>
|
||||||
{item.icon && <Icon style={modalPickerStyle.itemIcon} name={item.icon} size={16} />}
|
{item.icon && <Icon style={modalPickerStyle.itemIcon} name={item.icon} size={16} />}
|
||||||
<Text style={modalPickerStyle.itemLabel}>{item.label}</Text>
|
<Text style={modalPickerStyle.itemLabel}>{__(item.label)}</Text>
|
||||||
{selectedItem && selectedItem.name === item.name && (
|
{selectedItem && selectedItem.name === item.name && (
|
||||||
<Icon style={modalPickerStyle.itemSelected} name={'check'} color={Colors.LbryGreen} size={16} />
|
<Icon style={modalPickerStyle.itemSelected} name={'check'} color={Colors.LbryGreen} size={16} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -256,7 +256,7 @@ class UriBar extends React.PureComponent {
|
||||||
this.setSelection();
|
this.setSelection();
|
||||||
}}
|
}}
|
||||||
selectTextOnFocus
|
selectTextOnFocus
|
||||||
placeholder={'Search movies, music, and more'}
|
placeholder={__('Search movies, music, and more')}
|
||||||
underlineColorAndroid={'transparent'}
|
underlineColorAndroid={'transparent'}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
clearButtonMode={'while-editing'}
|
clearButtonMode={'while-editing'}
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 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 style={walletStyle.valueText} numberOfLines={1}>
|
<Text selectable style={walletStyle.valueText} numberOfLines={1}>
|
||||||
{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]}
|
||||||
/>
|
/>
|
||||||
|
|
79
src/i18n.js
Normal file
79
src/i18n.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import { NativeModules, Platform } from 'react-native';
|
||||||
|
import { SETTINGS } from 'lbry-redux';
|
||||||
|
import { doTransifexUpload } from 'lbryinc';
|
||||||
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
|
import RNFS from 'react-native-fs';
|
||||||
|
|
||||||
|
const isProduction = !__DEV__; // eslint-disable-line no-undef
|
||||||
|
let knownMessages = null;
|
||||||
|
|
||||||
|
window.language = NativeModules.UtilityModule.language;
|
||||||
|
window.i18n_messages = window.i18n_messages || {};
|
||||||
|
|
||||||
|
function saveMessage(message) {
|
||||||
|
// file path that won't get wiped if app storage is cleared or the app is uninstalled
|
||||||
|
const messagesFilePath = RNFS.ExternalStorageDirectoryPath + '/lbry-app-strings.json';
|
||||||
|
|
||||||
|
if (knownMessages === null) {
|
||||||
|
RNFS.readFile(messagesFilePath, 'utf8')
|
||||||
|
.then(fileContents => {
|
||||||
|
knownMessages = JSON.parse(fileContents);
|
||||||
|
checkMessageAndSave(message, messagesFilePath);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
knownMessages = {}; // no known messages, initialise the object
|
||||||
|
checkMessageAndSave(message, messagesFilePath);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
checkMessageAndSave(message, messagesFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkMessageAndSave(message, messagesFilePath) {
|
||||||
|
if (!knownMessages[message]) {
|
||||||
|
knownMessages[message] = message;
|
||||||
|
const contents = JSON.stringify(knownMessages, null, 2);
|
||||||
|
|
||||||
|
RNFS.writeFile(messagesFilePath, contents, 'utf8')
|
||||||
|
.then(() => {
|
||||||
|
// successful write
|
||||||
|
// send to transifex (should we do this even if the file doesn't get saved?)
|
||||||
|
// TODO: load token from .env
|
||||||
|
/* doTransifexUpload(
|
||||||
|
contents,
|
||||||
|
'lbry-mobile',
|
||||||
|
'*token*',
|
||||||
|
() => {
|
||||||
|
// successful
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
// failed
|
||||||
|
}
|
||||||
|
); */
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function __(message, tokens) {
|
||||||
|
const w = global.window ? global.window : window;
|
||||||
|
let language = w.language ? w.language : 'en';
|
||||||
|
|
||||||
|
if (!isProduction) {
|
||||||
|
saveMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
const translatedMessage = w.i18n_messages[language] ? w.i18n_messages[language][message] || message : message;
|
||||||
|
|
||||||
|
if (!tokens) {
|
||||||
|
return translatedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return translatedMessage.replace(/%([^%]+)%/g, function($1, $2) {
|
||||||
|
return tokens[$2] || $2;
|
||||||
|
});
|
||||||
|
}
|
|
@ -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 (
|
||||||
|
|
|
@ -67,7 +67,7 @@ class AboutPage extends React.PureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { accessToken, drawerStack, navigation, notify, popDrawerStack, userEmail } = this.props;
|
const { accessToken, drawerStack, navigation, notify, popDrawerStack, userEmail } = this.props;
|
||||||
const loading = 'Loading...';
|
const loading = __('Loading...');
|
||||||
const ver = this.state.versionInfo ? this.state.versionInfo : null;
|
const ver = this.state.versionInfo ? this.state.versionInfo : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -76,20 +76,20 @@ class AboutPage extends React.PureComponent {
|
||||||
<ScrollView style={aboutStyle.scrollContainer}>
|
<ScrollView style={aboutStyle.scrollContainer}>
|
||||||
<Text style={aboutStyle.title}>Content Freedom</Text>
|
<Text style={aboutStyle.title}>Content Freedom</Text>
|
||||||
<Text style={aboutStyle.paragraph}>
|
<Text style={aboutStyle.paragraph}>
|
||||||
LBRY is a free, open, and community-run digital marketplace. It is a decentralized peer-to-peer content
|
{__(
|
||||||
distribution platform for creators to upload and share content, and earn LBRY credits for their effort.
|
'LBRY is a free, open, and community-run digital marketplace. It is a decentralized peer-to-peer content distribution platform for creators to upload and share content, and earn LBRY credits for their effort. Users will be able to find a wide selection of videos, music, ebooks and other digital content they are interested in.'
|
||||||
Users will be able to find a wide selection of videos, music, ebooks and other digital content they are
|
)}
|
||||||
interested in.
|
|
||||||
</Text>
|
</Text>
|
||||||
<View style={aboutStyle.links}>
|
<View style={aboutStyle.links}>
|
||||||
<Link style={aboutStyle.link} href="https://lbry.com/faq/what-is-lbry" text="What is LBRY?" />
|
<Link style={aboutStyle.link} href="https://lbry.com/faq/what-is-lbry" text={__('What is LBRY?')} />
|
||||||
<Link style={aboutStyle.link} href="https://lbry.com/faq/android-basics" text="Android App Basics" />
|
<Link style={aboutStyle.link} href="https://lbry.com/faq/android-basics" text={__('Android App Basics')} />
|
||||||
<Link style={aboutStyle.link} href="https://lbry.com/faq" text="Frequently Asked Questions" />
|
<Link style={aboutStyle.link} href="https://lbry.com/faq" text={__('Frequently Asked Questions')} />
|
||||||
</View>
|
</View>
|
||||||
<Text style={aboutStyle.socialTitle}>Get Social</Text>
|
<Text style={aboutStyle.socialTitle}>Get Social</Text>
|
||||||
<Text style={aboutStyle.paragraph}>
|
<Text style={aboutStyle.paragraph}>
|
||||||
You can interact with the LBRY team and members of the community on Discord, Facebook, Instagram, Twitter or
|
{__(
|
||||||
Reddit.
|
'You can interact with the LBRY team and members of the community on Discord, Facebook, Instagram, Twitter or Reddit.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={aboutStyle.links}>
|
<View style={aboutStyle.links}>
|
||||||
<Link style={aboutStyle.link} href="https://discordapp.com/invite/Z3bERWA" text="Discord" />
|
<Link style={aboutStyle.link} href="https://discordapp.com/invite/Z3bERWA" text="Discord" />
|
||||||
|
@ -99,12 +99,12 @@ class AboutPage extends React.PureComponent {
|
||||||
<Link style={aboutStyle.link} href="https://reddit.com/r/lbry" text="Reddit" />
|
<Link style={aboutStyle.link} href="https://reddit.com/r/lbry" text="Reddit" />
|
||||||
<Link style={aboutStyle.link} href="https://t.me/lbryofficial" text="Telegram" />
|
<Link style={aboutStyle.link} href="https://t.me/lbryofficial" text="Telegram" />
|
||||||
</View>
|
</View>
|
||||||
<Text style={aboutStyle.releaseInfoTitle}>App info</Text>
|
<Text style={aboutStyle.releaseInfoTitle}>{__('App info')}</Text>
|
||||||
{userEmail && userEmail.trim().length > 0 && (
|
{userEmail && userEmail.trim().length > 0 && (
|
||||||
<View style={aboutStyle.verticalRow}>
|
<View style={aboutStyle.verticalRow}>
|
||||||
<View style={aboutStyle.innerRow}>
|
<View style={aboutStyle.innerRow}>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text style={aboutStyle.text}>Connected email</Text>
|
<Text style={aboutStyle.text}>{__('Connected email')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text selectable style={aboutStyle.valueText}>
|
<Text selectable style={aboutStyle.valueText}>
|
||||||
|
@ -116,7 +116,7 @@ class AboutPage extends React.PureComponent {
|
||||||
<Link
|
<Link
|
||||||
style={aboutStyle.listLink}
|
style={aboutStyle.listLink}
|
||||||
href={`http://lbry.com/list/edit/${accessToken}`}
|
href={`http://lbry.com/list/edit/${accessToken}`}
|
||||||
text="Update mailing preferences"
|
text={__('Update mailing preferences')}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
@ -124,7 +124,7 @@ class AboutPage extends React.PureComponent {
|
||||||
|
|
||||||
<View style={aboutStyle.row}>
|
<View style={aboutStyle.row}>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text style={aboutStyle.text}>App version</Text>
|
<Text style={aboutStyle.text}>{__('App version')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text selectable style={aboutStyle.valueText}>
|
<Text selectable style={aboutStyle.valueText}>
|
||||||
|
@ -135,7 +135,7 @@ class AboutPage extends React.PureComponent {
|
||||||
|
|
||||||
<View style={aboutStyle.row}>
|
<View style={aboutStyle.row}>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text style={aboutStyle.text}>LBRY SDK</Text>
|
<Text style={aboutStyle.text}>{__('LBRY SDK')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text selectable style={aboutStyle.valueText}>
|
<Text selectable style={aboutStyle.valueText}>
|
||||||
|
@ -146,7 +146,7 @@ class AboutPage extends React.PureComponent {
|
||||||
|
|
||||||
<View style={aboutStyle.row}>
|
<View style={aboutStyle.row}>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text style={aboutStyle.text}>Platform</Text>
|
<Text style={aboutStyle.text}>{__('Platform')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text selectable style={aboutStyle.valueText}>
|
<Text selectable style={aboutStyle.valueText}>
|
||||||
|
@ -157,7 +157,7 @@ class AboutPage extends React.PureComponent {
|
||||||
|
|
||||||
<View style={aboutStyle.row}>
|
<View style={aboutStyle.row}>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text style={aboutStyle.text}>Installation ID</Text>
|
<Text style={aboutStyle.text}>{__('Installation ID')}</Text>
|
||||||
<Text selectable style={aboutStyle.lineValueText}>
|
<Text selectable style={aboutStyle.lineValueText}>
|
||||||
{this.state.lbryId ? this.state.lbryId : loading}
|
{this.state.lbryId ? this.state.lbryId : loading}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -166,12 +166,12 @@ class AboutPage extends React.PureComponent {
|
||||||
|
|
||||||
<View style={aboutStyle.row}>
|
<View style={aboutStyle.row}>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Text style={aboutStyle.text}>Logs</Text>
|
<Text style={aboutStyle.text}>{__('Logs')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={aboutStyle.col}>
|
<View style={aboutStyle.col}>
|
||||||
<Link
|
<Link
|
||||||
style={aboutStyle.listLink}
|
style={aboutStyle.listLink}
|
||||||
text="Send log"
|
text={__('Send log')}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (NativeModules.UtilityModule) {
|
if (NativeModules.UtilityModule) {
|
||||||
NativeModules.UtilityModule.shareLogFile(error => {
|
NativeModules.UtilityModule.shareLogFile(error => {
|
||||||
|
|
|
@ -74,12 +74,12 @@ class ChannelPage extends React.PureComponent {
|
||||||
<View style={discoverStyle.pickerRow}>
|
<View style={discoverStyle.pickerRow}>
|
||||||
<View style={discoverStyle.leftPickerRow}>
|
<View style={discoverStyle.leftPickerRow}>
|
||||||
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
||||||
<Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
|
<Text style={discoverStyle.tagSortText}>{__(sortByItem.label.split(' ')[0])}</Text>
|
||||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
{Constants.SORT_BY_TOP === sortByItem.name && (
|
{Constants.SORT_BY_TOP === sortByItem.name && (
|
||||||
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
||||||
<Text style={discoverStyle.tagSortText}>{timeItem.label}</Text>
|
<Text style={discoverStyle.tagSortText}>{__(timeItem.label)}</Text>
|
||||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
@ -122,7 +122,7 @@ class ChannelPage extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<View style={channelPageStyle.aboutTab}>
|
<View style={channelPageStyle.aboutTab}>
|
||||||
<View style={channelPageStyle.busyContainer}>
|
<View style={channelPageStyle.busyContainer}>
|
||||||
<Text style={channelPageStyle.infoText}>No information to display.</Text>
|
<Text style={channelPageStyle.infoText}>{__('No information to display.')}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
@ -132,21 +132,21 @@ class ChannelPage extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<View style={channelPageStyle.aboutTab}>
|
<View style={channelPageStyle.aboutTab}>
|
||||||
{!websiteUrl && !email && !description && (
|
{!websiteUrl && !email && !description && (
|
||||||
<EmptyStateView message={"There's nothing here yet.\nPlease check back later."} />
|
<EmptyStateView message={__("There's nothing here yet.\nPlease check back later.")} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(websiteUrl || email || description) && (
|
{(websiteUrl || email || description) && (
|
||||||
<ScrollView style={channelPageStyle.aboutScroll} contentContainerStyle={channelPageStyle.aboutScrollContent}>
|
<ScrollView style={channelPageStyle.aboutScroll} contentContainerStyle={channelPageStyle.aboutScrollContent}>
|
||||||
{websiteUrl && websiteUrl.trim().length > 0 && (
|
{websiteUrl && websiteUrl.trim().length > 0 && (
|
||||||
<View style={channelPageStyle.aboutItem}>
|
<View style={channelPageStyle.aboutItem}>
|
||||||
<Text style={channelPageStyle.aboutTitle}>Website</Text>
|
<Text style={channelPageStyle.aboutTitle}>{__('Website')}</Text>
|
||||||
<Link style={channelPageStyle.aboutText} text={websiteUrl} href={websiteUrl} />
|
<Link style={channelPageStyle.aboutText} text={websiteUrl} href={websiteUrl} />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{email && email.trim().length > 0 && (
|
{email && email.trim().length > 0 && (
|
||||||
<View style={channelPageStyle.aboutItem}>
|
<View style={channelPageStyle.aboutItem}>
|
||||||
<Text style={channelPageStyle.aboutTitle}>Email</Text>
|
<Text style={channelPageStyle.aboutTitle}>{__('Email')}</Text>
|
||||||
<Link style={channelPageStyle.aboutText} text={email} href={`mailto:${email}`} />
|
<Link style={channelPageStyle.aboutText} text={email} href={`mailto:${email}`} />
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -793,8 +793,8 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
|
|
||||||
{currentPhase === Constants.PHASE_LIST && !fetchingChannels && !hasChannels && (
|
{currentPhase === Constants.PHASE_LIST && !fetchingChannels && !hasChannels && (
|
||||||
<EmptyStateView
|
<EmptyStateView
|
||||||
message={'You have not created a channel.\nStart now by creating a new channel!'}
|
message={__('You have not created a channel.\nStart now by creating a new channel!')}
|
||||||
buttonText={'Create a channel'}
|
buttonText={__('Create a channel')}
|
||||||
onButtonPress={this.handleNewChannelPress}
|
onButtonPress={this.handleNewChannelPress}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -807,7 +807,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
<View style={channelCreatorStyle.listFooter}>
|
<View style={channelCreatorStyle.listFooter}>
|
||||||
<Button
|
<Button
|
||||||
style={channelCreatorStyle.createChannelButton}
|
style={channelCreatorStyle.createChannelButton}
|
||||||
text={'Create a channel'}
|
text={__('Create a channel')}
|
||||||
onPress={this.handleNewChannelPress}
|
onPress={this.handleNewChannelPress}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
@ -879,7 +879,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
{this.state.uploadingImage && (
|
{this.state.uploadingImage && (
|
||||||
<View style={channelCreatorStyle.uploadProgress}>
|
<View style={channelCreatorStyle.uploadProgress}>
|
||||||
<ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
|
<ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
|
||||||
<Text style={channelCreatorStyle.uploadText}>Uploading image...</Text>
|
<Text style={channelCreatorStyle.uploadText}>{__('Uploading image...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
@ -911,14 +911,14 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
<View style={channelCreatorStyle.textInputLayout}>
|
<View style={channelCreatorStyle.textInputLayout}>
|
||||||
{(this.state.titleFocused ||
|
{(this.state.titleFocused ||
|
||||||
(this.state.newChannelTitle != null && this.state.newChannelTitle.trim().length > 0)) && (
|
(this.state.newChannelTitle != null && this.state.newChannelTitle.trim().length > 0)) && (
|
||||||
<Text style={channelCreatorStyle.textInputTitle}>Title</Text>
|
<Text style={channelCreatorStyle.textInputTitle}>{__('Title')}</Text>
|
||||||
)}
|
)}
|
||||||
<TextInput
|
<TextInput
|
||||||
editable={canSave && !creatingChannel && !updatingChannel}
|
editable={canSave && !creatingChannel && !updatingChannel}
|
||||||
style={channelCreatorStyle.inputText}
|
style={channelCreatorStyle.inputText}
|
||||||
value={this.state.newChannelTitle}
|
value={this.state.newChannelTitle}
|
||||||
onChangeText={this.handleNewChannelTitleChange}
|
onChangeText={this.handleNewChannelTitleChange}
|
||||||
placeholder={this.state.titleFocused ? '' : 'Title'}
|
placeholder={this.state.titleFocused ? '' : __('Title')}
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
onFocus={() => this.setState({ titleFocused: true })}
|
onFocus={() => this.setState({ titleFocused: true })}
|
||||||
onBlur={() => this.setState({ titleFocused: false })}
|
onBlur={() => this.setState({ titleFocused: false })}
|
||||||
|
@ -928,7 +928,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
<View style={channelCreatorStyle.channelInputLayout}>
|
<View style={channelCreatorStyle.channelInputLayout}>
|
||||||
{(this.state.channelNameFocused ||
|
{(this.state.channelNameFocused ||
|
||||||
(this.state.newChannelName != null && this.state.newChannelName.trim().length > 0)) && (
|
(this.state.newChannelName != null && this.state.newChannelName.trim().length > 0)) && (
|
||||||
<Text style={channelCreatorStyle.textInputTitle}>Channel</Text>
|
<Text style={channelCreatorStyle.textInputTitle}>{__('Channel')}</Text>
|
||||||
)}
|
)}
|
||||||
<View>
|
<View>
|
||||||
<Text style={channelCreatorStyle.channelAt}>@</Text>
|
<Text style={channelCreatorStyle.channelAt}>@</Text>
|
||||||
|
@ -937,7 +937,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
style={channelCreatorStyle.channelNameInput}
|
style={channelCreatorStyle.channelNameInput}
|
||||||
value={this.state.newChannelName}
|
value={this.state.newChannelName}
|
||||||
onChangeText={value => this.handleNewChannelNameChange(value, true)}
|
onChangeText={value => this.handleNewChannelNameChange(value, true)}
|
||||||
placeholder={this.state.channelNameFocused ? '' : 'Channel'}
|
placeholder={this.state.channelNameFocused ? '' : __('Channel')}
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
onFocus={() => this.setState({ channelNameFocused: true })}
|
onFocus={() => this.setState({ channelNameFocused: true })}
|
||||||
onBlur={() => this.setState({ channelNameFocused: false })}
|
onBlur={() => this.setState({ channelNameFocused: false })}
|
||||||
|
@ -948,11 +948,13 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
<Text style={channelCreatorStyle.inlineError}>{newChannelNameError}</Text>
|
<Text style={channelCreatorStyle.inlineError}>{newChannelNameError}</Text>
|
||||||
)}
|
)}
|
||||||
{editMode && (
|
{editMode && (
|
||||||
<Text style={channelCreatorStyle.helpText}>The channel name cannot be changed while editing.</Text>
|
<Text style={channelCreatorStyle.helpText}>
|
||||||
|
{__('The channel name cannot be changed while editing.')}
|
||||||
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<View style={channelCreatorStyle.bidRow}>
|
<View style={channelCreatorStyle.bidRow}>
|
||||||
<Text style={channelCreatorStyle.label}>Deposit</Text>
|
<Text style={channelCreatorStyle.label}>{__('Deposit')}</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
editable={canSave && !creatingChannel && !updatingChannel}
|
editable={canSave && !creatingChannel && !updatingChannel}
|
||||||
style={channelCreatorStyle.bidAmountInput}
|
style={channelCreatorStyle.bidAmountInput}
|
||||||
|
@ -965,7 +967,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
<Text style={channelCreatorStyle.currency}>LBC</Text>
|
<Text style={channelCreatorStyle.currency}>LBC</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={channelCreatorStyle.helpText}>
|
<Text style={channelCreatorStyle.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>
|
</View>
|
||||||
|
|
||||||
|
@ -974,7 +976,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
<View style={channelCreatorStyle.textInputLayout}>
|
<View style={channelCreatorStyle.textInputLayout}>
|
||||||
{(this.state.descriptionFocused ||
|
{(this.state.descriptionFocused ||
|
||||||
(this.state.description != null && this.state.description.trim().length > 0)) && (
|
(this.state.description != null && this.state.description.trim().length > 0)) && (
|
||||||
<Text style={channelCreatorStyle.textInputTitle}>Description</Text>
|
<Text style={channelCreatorStyle.textInputTitle}>{__('Description')}</Text>
|
||||||
)}
|
)}
|
||||||
<TextInput
|
<TextInput
|
||||||
editable={canSave && !creatingChannel && !updatingChannel}
|
editable={canSave && !creatingChannel && !updatingChannel}
|
||||||
|
@ -982,7 +984,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
multiline
|
multiline
|
||||||
value={this.state.description}
|
value={this.state.description}
|
||||||
onChangeText={this.handleDescriptionChange}
|
onChangeText={this.handleDescriptionChange}
|
||||||
placeholder={this.state.descriptionFocused ? '' : 'Description'}
|
placeholder={this.state.descriptionFocused ? '' : __('Description')}
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
onFocus={() => this.setState({ descriptionFocused: true })}
|
onFocus={() => this.setState({ descriptionFocused: true })}
|
||||||
onBlur={() => this.setState({ descriptionFocused: false })}
|
onBlur={() => this.setState({ descriptionFocused: false })}
|
||||||
|
@ -992,14 +994,14 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
<View style={channelCreatorStyle.textInputLayout}>
|
<View style={channelCreatorStyle.textInputLayout}>
|
||||||
{(this.state.websiteFocused ||
|
{(this.state.websiteFocused ||
|
||||||
(this.state.website != null && this.state.website.trim().length > 0)) && (
|
(this.state.website != null && this.state.website.trim().length > 0)) && (
|
||||||
<Text style={channelCreatorStyle.textInputTitle}>Website</Text>
|
<Text style={channelCreatorStyle.textInputTitle}>{__('Website')}</Text>
|
||||||
)}
|
)}
|
||||||
<TextInput
|
<TextInput
|
||||||
editable={canSave && !creatingChannel && !updatingChannel}
|
editable={canSave && !creatingChannel && !updatingChannel}
|
||||||
style={channelCreatorStyle.inputText}
|
style={channelCreatorStyle.inputText}
|
||||||
value={this.state.website}
|
value={this.state.website}
|
||||||
onChangeText={this.handleWebsiteChange}
|
onChangeText={this.handleWebsiteChange}
|
||||||
placeholder={this.state.websiteFocused ? '' : 'Website'}
|
placeholder={this.state.websiteFocused ? '' : __('Website')}
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
onFocus={() => this.setState({ websiteFocused: true })}
|
onFocus={() => this.setState({ websiteFocused: true })}
|
||||||
onBlur={() => this.setState({ websiteFocused: false })}
|
onBlur={() => this.setState({ websiteFocused: false })}
|
||||||
|
@ -1008,14 +1010,14 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
|
|
||||||
<View style={channelCreatorStyle.textInputLayout}>
|
<View style={channelCreatorStyle.textInputLayout}>
|
||||||
{(this.state.emailFocused || (this.state.email != null && this.state.email.trim().length > 0)) && (
|
{(this.state.emailFocused || (this.state.email != null && this.state.email.trim().length > 0)) && (
|
||||||
<Text style={channelCreatorStyle.textInputTitle}>Email</Text>
|
<Text style={channelCreatorStyle.textInputTitle}>{__('Email')}</Text>
|
||||||
)}
|
)}
|
||||||
<TextInput
|
<TextInput
|
||||||
editable={canSave && !creatingChannel && !updatingChannel}
|
editable={canSave && !creatingChannel && !updatingChannel}
|
||||||
style={channelCreatorStyle.inputText}
|
style={channelCreatorStyle.inputText}
|
||||||
value={this.state.email}
|
value={this.state.email}
|
||||||
onChangeText={this.handleEmailChange}
|
onChangeText={this.handleEmailChange}
|
||||||
placeholder={this.state.emailFocused ? '' : 'Email'}
|
placeholder={this.state.emailFocused ? '' : __('Email')}
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
onFocus={() => this.setState({ emailFocused: true })}
|
onFocus={() => this.setState({ emailFocused: true })}
|
||||||
onBlur={() => this.setState({ emailFocused: false })}
|
onBlur={() => this.setState({ emailFocused: false })}
|
||||||
|
@ -1026,7 +1028,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
|
|
||||||
{this.state.showOptionalFields && (
|
{this.state.showOptionalFields && (
|
||||||
<View style={channelCreatorStyle.card}>
|
<View style={channelCreatorStyle.card}>
|
||||||
<Text style={channelCreatorStyle.cardTitle}>Tags</Text>
|
<Text style={channelCreatorStyle.cardTitle}>{__('Tags')}</Text>
|
||||||
<View style={channelCreatorStyle.tagList}>
|
<View style={channelCreatorStyle.tagList}>
|
||||||
{this.state.tags &&
|
{this.state.tags &&
|
||||||
this.state.tags.map(tag => (
|
this.state.tags.map(tag => (
|
||||||
|
@ -1050,7 +1052,7 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
|
|
||||||
<View style={channelCreatorStyle.toggleContainer}>
|
<View style={channelCreatorStyle.toggleContainer}>
|
||||||
<Link
|
<Link
|
||||||
text={this.state.showOptionalFields ? 'Hide optional fields' : 'Show optional fields'}
|
text={this.state.showOptionalFields ? __('Hide optional fields') : __('Show optional fields')}
|
||||||
onPress={this.handleModePressed}
|
onPress={this.handleModePressed}
|
||||||
style={channelCreatorStyle.modeLink}
|
style={channelCreatorStyle.modeLink}
|
||||||
/>
|
/>
|
||||||
|
@ -1062,11 +1064,11 @@ export default class ChannelCreator extends React.PureComponent {
|
||||||
)}
|
)}
|
||||||
{!creatingChannel && !updatingChannel && (
|
{!creatingChannel && !updatingChannel && (
|
||||||
<View style={channelCreatorStyle.buttons}>
|
<View style={channelCreatorStyle.buttons}>
|
||||||
<Link style={channelCreatorStyle.cancelLink} text="Cancel" onPress={this.handleCreateCancel} />
|
<Link style={channelCreatorStyle.cancelLink} text={__('Cancel')} onPress={this.handleCreateCancel} />
|
||||||
<Button
|
<Button
|
||||||
style={channelCreatorStyle.createButton}
|
style={channelCreatorStyle.createButton}
|
||||||
disabled={!canSave || uploadingImage}
|
disabled={!canSave || uploadingImage}
|
||||||
text={editMode ? 'Update' : 'Create'}
|
text={editMode ? __('Update') : __('Create')}
|
||||||
onPress={this.handleCreateChannelClick}
|
onPress={this.handleCreateChannelClick}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -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';
|
||||||
|
@ -176,16 +175,18 @@ class DiscoverPage extends React.PureComponent {
|
||||||
if (!isNaN(lastShownTime) && !isNaN(lastShownCount)) {
|
if (!isNaN(lastShownTime) && !isNaN(lastShownCount)) {
|
||||||
if (now > lastShownTime + Constants.RATING_REMINDER_INTERVAL * lastShownCount) {
|
if (now > lastShownTime + Constants.RATING_REMINDER_INTERVAL * lastShownCount) {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
'Enjoying LBRY?',
|
__('Enjoying LBRY?'),
|
||||||
'Are you enjoying your experience with the LBRY app? You can leave a review for us on the Play Store.',
|
__(
|
||||||
|
'Are you enjoying your experience with the LBRY app? You can leave a review for us on the Play Store.'
|
||||||
|
),
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: 'Never ask again',
|
text: __('Never ask again'),
|
||||||
onPress: () => setClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED, 'true'),
|
onPress: () => setClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED, 'true'),
|
||||||
},
|
},
|
||||||
{ text: 'Maybe later', onPress: () => this.updateRatingReminderShown(lastShownCount) },
|
{ text: __('Maybe later'), onPress: () => this.updateRatingReminderShown(lastShownCount) },
|
||||||
{
|
{
|
||||||
text: 'Rate app',
|
text: __('Rate app'),
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
setClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED, 'true');
|
setClientSetting(Constants.SETTING_RATING_REMINDER_DISABLED, 'true');
|
||||||
Linking.openURL(Constants.PLAY_STORE_URL);
|
Linking.openURL(Constants.PLAY_STORE_URL);
|
||||||
|
@ -212,7 +213,7 @@ class DiscoverPage extends React.PureComponent {
|
||||||
|
|
||||||
buildSections = () => {
|
buildSections = () => {
|
||||||
return this.state.tagCollection.map(tags => ({
|
return this.state.tagCollection.map(tags => ({
|
||||||
title: tags.length === 1 ? tags[0] : 'All tags you follow',
|
title: tags.length === 1 ? tags[0] : __('All tags you follow'),
|
||||||
data: [tags],
|
data: [tags],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
@ -236,7 +237,7 @@ class DiscoverPage extends React.PureComponent {
|
||||||
|
|
||||||
handleTagPress = name => {
|
handleTagPress = name => {
|
||||||
const { navigation, sortByItem } = this.props;
|
const { navigation, sortByItem } = this.props;
|
||||||
if (name.toLowerCase() !== 'all tags you follow') {
|
if (name.toLowerCase() !== __('all tags you follow')) {
|
||||||
navigation.navigate({
|
navigation.navigate({
|
||||||
routeName: Constants.DRAWER_ROUTE_TAG,
|
routeName: Constants.DRAWER_ROUTE_TAG,
|
||||||
key: `tagPage`,
|
key: `tagPage`,
|
||||||
|
@ -255,18 +256,18 @@ class DiscoverPage extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<View style={discoverStyle.listHeader}>
|
<View style={discoverStyle.listHeader}>
|
||||||
<View style={discoverStyle.titleRow}>
|
<View style={discoverStyle.titleRow}>
|
||||||
<Text style={discoverStyle.pageTitle}>Your tags</Text>
|
<Text style={discoverStyle.pageTitle}>{__('Your Tags')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={discoverStyle.pickerRow}>
|
<View style={discoverStyle.pickerRow}>
|
||||||
<View style={discoverStyle.leftPickerRow}>
|
<View style={discoverStyle.leftPickerRow}>
|
||||||
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
||||||
<Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
|
<Text style={discoverStyle.tagSortText}>{__(sortByItem.label.split(' ')[0])}</Text>
|
||||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
{Constants.SORT_BY_TOP === sortByItem.name && (
|
{Constants.SORT_BY_TOP === sortByItem.name && (
|
||||||
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
||||||
<Text style={discoverStyle.tagSortText}>{timeItem.label}</Text>
|
<Text style={discoverStyle.tagSortText}>{__(timeItem.label)}</Text>
|
||||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
@ -274,7 +275,7 @@ class DiscoverPage extends React.PureComponent {
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
style={discoverStyle.customizeLink}
|
style={discoverStyle.customizeLink}
|
||||||
text={'Customize'}
|
text={__('Customize')}
|
||||||
onPress={() => this.setState({ showModalTagSelector: true })}
|
onPress={() => this.setState({ showModalTagSelector: true })}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
@ -290,7 +291,7 @@ class DiscoverPage extends React.PureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={discoverStyle.footer}>
|
<View style={discoverStyle.footer}>
|
||||||
<Text style={discoverStyle.footerTitle}>More tags you follow</Text>
|
<Text style={discoverStyle.footerTitle}>{__('More tags you follow')}</Text>
|
||||||
<View style={discoverStyle.footerTags}>
|
<View style={discoverStyle.footerTags}>
|
||||||
{remainingTags.map(tag => (
|
{remainingTags.map(tag => (
|
||||||
<Text
|
<Text
|
||||||
|
|
|
@ -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';
|
||||||
|
@ -156,7 +156,7 @@ class DownloadsPage extends React.PureComponent {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{!fetching && !hasDownloads && (
|
{!fetching && !hasDownloads && (
|
||||||
<EmptyStateView message={'You do not have any\ndownloaded content on this device.'} />
|
<EmptyStateView message={__('You do not have any\ndownloaded content on this device.')} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<View style={downloadsStyle.subContainer}>
|
<View style={downloadsStyle.subContainer}>
|
||||||
|
|
|
@ -658,7 +658,7 @@ class FilePage extends React.PureComponent {
|
||||||
{isResolvingUri && (
|
{isResolvingUri && (
|
||||||
<View style={filePageStyle.busyContainer}>
|
<View style={filePageStyle.busyContainer}>
|
||||||
<ActivityIndicator size="large" color={Colors.NextLbryGreen} />
|
<ActivityIndicator size="large" color={Colors.NextLbryGreen} />
|
||||||
<Text style={filePageStyle.infoText}>Loading decentralized data...</Text>
|
<Text style={filePageStyle.infoText}>{__('Loading decentralized data...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{claim === null && !isResolvingUri && (
|
{claim === null && !isResolvingUri && (
|
||||||
|
@ -667,15 +667,15 @@ class FilePage extends React.PureComponent {
|
||||||
<EmptyStateView
|
<EmptyStateView
|
||||||
message={
|
message={
|
||||||
isChannel
|
isChannel
|
||||||
? 'It looks like you just created this channel. It will appear in a few minutes.'
|
? __('It looks like you just created this channel. It will appear in a few minutes.')
|
||||||
: 'It looks you just published this content. It will appear in a few minutes.'
|
: __('It looks you just published this content. It will appear in a few minutes.')
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!ownedClaim && (
|
{!ownedClaim && (
|
||||||
<EmptyStateView
|
<EmptyStateView
|
||||||
message={"There's nothing at this location."}
|
message={__("There's nothing at this location.")}
|
||||||
buttonText={'Publish something here'}
|
buttonText={__('Publish something here')}
|
||||||
onButtonPress={() =>
|
onButtonPress={() =>
|
||||||
navigation.navigate({
|
navigation.navigate({
|
||||||
routeName: Constants.DRAWER_ROUTE_PUBLISH,
|
routeName: Constants.DRAWER_ROUTE_PUBLISH,
|
||||||
|
@ -713,10 +713,11 @@ class FilePage extends React.PureComponent {
|
||||||
<View style={filePageStyle.pageContainer}>
|
<View style={filePageStyle.pageContainer}>
|
||||||
<View style={filePageStyle.dmcaContainer}>
|
<View style={filePageStyle.dmcaContainer}>
|
||||||
<Text style={filePageStyle.dmcaText}>
|
<Text style={filePageStyle.dmcaText}>
|
||||||
In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked
|
{__(
|
||||||
access to this content from our applications.
|
'In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
<Link style={filePageStyle.dmcaLink} href="https://lbry.com/faq/dmca" text="Read More" />
|
<Link style={filePageStyle.dmcaLink} href="https://lbry.com/faq/dmca" text={__('Read More')} />
|
||||||
</View>
|
</View>
|
||||||
<UriBar value={uri} navigation={navigation} />
|
<UriBar value={uri} navigation={navigation} />
|
||||||
</View>
|
</View>
|
||||||
|
@ -859,7 +860,7 @@ class FilePage extends React.PureComponent {
|
||||||
source={require('../../assets/gerbil-happy.png')}
|
source={require('../../assets/gerbil-happy.png')}
|
||||||
/>
|
/>
|
||||||
<View style={filePageStyle.unspportedContentTextContainer}>
|
<View style={filePageStyle.unspportedContentTextContainer}>
|
||||||
<Text style={filePageStyle.unsupportedContentTitle}>Unsupported Content</Text>
|
<Text style={filePageStyle.unsupportedContentTitle}>{__('Unsupported Content')}</Text>
|
||||||
<Text style={filePageStyle.unsupportedContentText}>
|
<Text style={filePageStyle.unsupportedContentText}>
|
||||||
Sorry, we are unable to display this content in the app. You can find the file named{' '}
|
Sorry, we are unable to display this content in the app. You can find the file named{' '}
|
||||||
<Text style={filePageStyle.unsupportedContentFilename}>{fileInfo.file_name}</Text> in your
|
<Text style={filePageStyle.unsupportedContentFilename}>{fileInfo.file_name}</Text> in your
|
||||||
|
@ -946,7 +947,7 @@ class FilePage extends React.PureComponent {
|
||||||
style={[filePageStyle.actionButton, filePageStyle.editButton]}
|
style={[filePageStyle.actionButton, filePageStyle.editButton]}
|
||||||
theme={'light'}
|
theme={'light'}
|
||||||
icon={'edit'}
|
icon={'edit'}
|
||||||
text={'Edit'}
|
text={__('Edit')}
|
||||||
onPress={this.onEditPressed}
|
onPress={this.onEditPressed}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -956,7 +957,7 @@ class FilePage extends React.PureComponent {
|
||||||
style={filePageStyle.actionButton}
|
style={filePageStyle.actionButton}
|
||||||
theme={'light'}
|
theme={'light'}
|
||||||
icon={'trash-alt'}
|
icon={'trash-alt'}
|
||||||
text={'Delete'}
|
text={__('Delete')}
|
||||||
onPress={this.onDeletePressed}
|
onPress={this.onDeletePressed}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -969,7 +970,7 @@ class FilePage extends React.PureComponent {
|
||||||
style={filePageStyle.actionButton}
|
style={filePageStyle.actionButton}
|
||||||
icon={'stop'}
|
icon={'stop'}
|
||||||
theme={'light'}
|
theme={'light'}
|
||||||
text={'Stop Download'}
|
text={__('Stop Download')}
|
||||||
onPress={this.onStopDownloadPressed}
|
onPress={this.onStopDownloadPressed}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -1003,7 +1004,7 @@ class FilePage extends React.PureComponent {
|
||||||
<View style={filePageStyle.largeButtonsRow}>
|
<View style={filePageStyle.largeButtonsRow}>
|
||||||
<TouchableOpacity style={filePageStyle.largeButton} onPress={this.handleSharePress}>
|
<TouchableOpacity style={filePageStyle.largeButton} onPress={this.handleSharePress}>
|
||||||
<Icon name={'share-alt'} size={20} style={filePageStyle.largeButtonIcon} />
|
<Icon name={'share-alt'} size={20} style={filePageStyle.largeButtonIcon} />
|
||||||
<Text style={filePageStyle.largeButtonText}>Share</Text>
|
<Text style={filePageStyle.largeButtonText}>{__('Share')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
|
@ -1011,7 +1012,7 @@ class FilePage extends React.PureComponent {
|
||||||
onPress={() => this.setState({ showTipView: true })}
|
onPress={() => this.setState({ showTipView: true })}
|
||||||
>
|
>
|
||||||
<Icon name={'gift'} size={20} style={filePageStyle.largeButtonIcon} />
|
<Icon name={'gift'} size={20} style={filePageStyle.largeButtonIcon} />
|
||||||
<Text style={filePageStyle.largeButtonText}>Tip</Text>
|
<Text style={filePageStyle.largeButtonText}>{__('Tip')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
|
@ -1019,7 +1020,7 @@ class FilePage extends React.PureComponent {
|
||||||
onPress={() => Linking.openURL(`https://lbry.com/dmca/${claim.claim_id}`)}
|
onPress={() => Linking.openURL(`https://lbry.com/dmca/${claim.claim_id}`)}
|
||||||
>
|
>
|
||||||
<Icon name={'flag'} size={20} style={filePageStyle.largeButtonIcon} />
|
<Icon name={'flag'} size={20} style={filePageStyle.largeButtonIcon} />
|
||||||
<Text style={filePageStyle.largeButtonText}>Report</Text>
|
<Text style={filePageStyle.largeButtonText}>{__('Report')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
@ -1045,7 +1046,7 @@ class FilePage extends React.PureComponent {
|
||||||
)}
|
)}
|
||||||
{!channelName && (
|
{!channelName && (
|
||||||
<Text style={filePageStyle.anonChannelName} selectable ellipsizeMode={'tail'}>
|
<Text style={filePageStyle.anonChannelName} selectable ellipsizeMode={'tail'}>
|
||||||
Anonymous
|
{__('Anonymous')}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
<DateTime
|
<DateTime
|
||||||
|
@ -1104,11 +1105,11 @@ class FilePage extends React.PureComponent {
|
||||||
{this.state.sendTipStarted && <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />}
|
{this.state.sendTipStarted && <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />}
|
||||||
<Link
|
<Link
|
||||||
style={[filePageStyle.link, filePageStyle.cancelTipLink]}
|
style={[filePageStyle.link, filePageStyle.cancelTipLink]}
|
||||||
text={'Cancel'}
|
text={__('Cancel')}
|
||||||
onPress={() => this.setState({ showTipView: false })}
|
onPress={() => this.setState({ showTipView: false })}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
text={'Send a tip'}
|
text={__('Send a tip')}
|
||||||
style={[filePageStyle.button, filePageStyle.sendButton]}
|
style={[filePageStyle.button, filePageStyle.sendButton]}
|
||||||
disabled={!canSendTip || this.state.sendTipStarted}
|
disabled={!canSendTip || this.state.sendTipStarted}
|
||||||
onPress={this.handleSendTip}
|
onPress={this.handleSendTip}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doToast } from 'lbry-redux';
|
import { SETTINGS, doToast } from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
doAuthenticate,
|
doAuthenticate,
|
||||||
doCheckSync,
|
doCheckSync,
|
||||||
|
@ -21,6 +21,7 @@ import {
|
||||||
selectUser,
|
selectUser,
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import FirstRun from './view';
|
import FirstRun from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -31,6 +32,7 @@ const select = state => ({
|
||||||
emailNewPending: selectEmailNewIsPending(state),
|
emailNewPending: selectEmailNewIsPending(state),
|
||||||
hasSyncedWallet: selectHasSyncedWallet(state),
|
hasSyncedWallet: selectHasSyncedWallet(state),
|
||||||
getSyncIsPending: selectGetSyncIsPending(state),
|
getSyncIsPending: selectGetSyncIsPending(state),
|
||||||
|
language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state),
|
||||||
syncApplyErrorMessage: selectSyncApplyErrorMessage(state),
|
syncApplyErrorMessage: selectSyncApplyErrorMessage(state),
|
||||||
syncApplyIsPending: selectSyncApplyIsPending(state),
|
syncApplyIsPending: selectSyncApplyIsPending(state),
|
||||||
syncHash: selectSyncHash(state),
|
syncHash: selectSyncHash(state),
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Lbry } from 'lbry-redux';
|
||||||
import { NativeModules, Platform, Text, TextInput, View } from 'react-native';
|
import { NativeModules, Platform, Text, TextInput, View } from 'react-native';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants';
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import firstRunStyle from 'styles/firstRun';
|
import firstRunStyle from 'styles/firstRun';
|
||||||
|
|
||||||
class EmailCollectPage extends React.PureComponent {
|
class EmailCollectPage extends React.PureComponent {
|
||||||
|
@ -44,7 +44,7 @@ class EmailCollectPage extends React.PureComponent {
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<View onLayout={() => onEmailViewLayout('collect')}>
|
<View onLayout={() => onEmailViewLayout('collect')}>
|
||||||
<Text style={firstRunStyle.title}>Setup account</Text>
|
<Text style={firstRunStyle.title}>{__('Setup account')}</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
style={firstRunStyle.emailInput}
|
style={firstRunStyle.emailInput}
|
||||||
placeholder={this.state.placeholder}
|
placeholder={this.state.placeholder}
|
||||||
|
@ -64,10 +64,10 @@ class EmailCollectPage extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Text style={firstRunStyle.paragraph}>
|
<Text style={firstRunStyle.paragraph}>
|
||||||
An account will allow you to earn rewards and keep your account and settings synced.
|
{__('An account will allow you to earn rewards and keep your account and settings synced.')}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={firstRunStyle.infoParagraph}>
|
<Text style={firstRunStyle.infoParagraph}>
|
||||||
This information is disclosed only to LBRY, Inc. and not to the LBRY network.
|
{__('This information is disclosed only to LBRY, Inc. and not to the LBRY network.')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { ActivityIndicator, Linking, NativeModules, Platform, Switch, Text, Text
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants';
|
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';
|
||||||
import firstRunStyle from 'styles/firstRun';
|
import firstRunStyle from 'styles/firstRun';
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class EmailVerifyPage extends React.PureComponent {
|
||||||
const { email, notify, resendVerificationEmail } = this.props;
|
const { email, notify, resendVerificationEmail } = this.props;
|
||||||
resendVerificationEmail(email);
|
resendVerificationEmail(email);
|
||||||
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
|
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
|
||||||
notify({ message: 'Please follow the instructions in the email sent to your address to continue.' });
|
notify({ message: __('Please follow the instructions in the email sent to your address to continue.') });
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -28,10 +28,10 @@ class SkipAccountPage extends React.PureComponent {
|
||||||
<View onLayout={onSkipAccountViewLayout}>
|
<View onLayout={onSkipAccountViewLayout}>
|
||||||
<View style={firstRunStyle.row}>
|
<View style={firstRunStyle.row}>
|
||||||
<Icon name="exclamation-triangle" style={firstRunStyle.titleIcon} size={32} color={Colors.White} />
|
<Icon name="exclamation-triangle" style={firstRunStyle.titleIcon} size={32} color={Colors.White} />
|
||||||
<Text style={firstRunStyle.title}>Are you sure?</Text>
|
<Text style={firstRunStyle.title}>{__('Are you sure?')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={firstRunStyle.paragraph}>
|
<Text style={firstRunStyle.paragraph}>
|
||||||
Without an account, you will not receive rewards, sync and backup services, or security updates.
|
{__('Without an account, you will not receive rewards, sync and backup services, or security updates.')}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<View style={[firstRunStyle.row, firstRunStyle.confirmContainer]}>
|
<View style={[firstRunStyle.row, firstRunStyle.confirmContainer]}>
|
||||||
|
@ -45,8 +45,9 @@ class SkipAccountPage extends React.PureComponent {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<Text style={firstRunStyle.rowParagraph}>
|
<Text style={firstRunStyle.rowParagraph}>
|
||||||
I understand that by uninstalling LBRY I will lose any balances or published content with no recovery option
|
{__(
|
||||||
if it is not backed up manually (see wallet page)
|
'I understand that by uninstalling LBRY I will lose any balances or published content with no recovery option if it is not backed up manually (see wallet page)'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -97,14 +97,16 @@ class WalletPage extends React.PureComponent {
|
||||||
content = (
|
content = (
|
||||||
<View style={firstRunStyle.centered}>
|
<View style={firstRunStyle.centered}>
|
||||||
<ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} />
|
<ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} />
|
||||||
<Text style={firstRunStyle.paragraph}>Retrieving your account information...</Text>
|
<Text style={firstRunStyle.paragraph}>{__('Retrieving your account information...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
} else if (syncApplyStarted || syncApplyIsPending || syncApplyCompleted) {
|
} else if (syncApplyStarted || syncApplyIsPending || syncApplyCompleted) {
|
||||||
content = (
|
content = (
|
||||||
<View style={firstRunStyle.centered}>
|
<View style={firstRunStyle.centered}>
|
||||||
<ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} />
|
<ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} />
|
||||||
<Text style={firstRunStyle.paragraph}>{syncApplyIsPending ? 'Validating password' : 'Synchronizing'}...</Text>
|
<Text style={firstRunStyle.paragraph}>
|
||||||
|
{syncApplyIsPending ? __('Validating password') : __('Synchronizing')}...
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
} else if (hasSyncedWallet && this.state.autoLoginAttempted) {
|
} else if (hasSyncedWallet && this.state.autoLoginAttempted) {
|
||||||
|
@ -114,8 +116,8 @@ class WalletPage extends React.PureComponent {
|
||||||
<Text style={firstRunStyle.title}>Password</Text>
|
<Text style={firstRunStyle.title}>Password</Text>
|
||||||
<Text style={firstRunStyle.paragraph}>
|
<Text style={firstRunStyle.paragraph}>
|
||||||
{hasSyncedWallet
|
{hasSyncedWallet
|
||||||
? 'Please enter the password you used to secure your wallet.'
|
? __('Please enter the password you used to secure your wallet.')
|
||||||
: 'Please enter a password to secure your account and wallet.'}
|
: __('Please enter a password to secure your account and wallet.')}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={firstRunStyle.passwordInputContainer}>
|
<View style={firstRunStyle.passwordInputContainer}>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
@ -148,8 +150,8 @@ class WalletPage extends React.PureComponent {
|
||||||
<View style={firstRunStyle.passwordWarning}>
|
<View style={firstRunStyle.passwordWarning}>
|
||||||
<Text style={firstRunStyle.passwordWarningText}>
|
<Text style={firstRunStyle.passwordWarningText}>
|
||||||
{hasSyncedWallet
|
{hasSyncedWallet
|
||||||
? 'If you did not provide a password, please press Use LBRY to continue.'
|
? __('If you did not provide a password, please press Use LBRY to continue.')
|
||||||
: 'You can proceed without a password, but this is not recommended.'}
|
: __('You can proceed without a password, but this is not recommended.')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
@ -164,7 +166,7 @@ class WalletPage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<Text style={firstRunStyle.infoParagraph}>
|
<Text style={firstRunStyle.infoParagraph}>
|
||||||
Note: for wallet security purposes, LBRY is unable to reset your password.
|
{__('Note: for wallet security purposes, LBRY is unable to reset your password.')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
|
@ -87,8 +87,9 @@ class WelcomePage extends React.PureComponent {
|
||||||
content = (
|
content = (
|
||||||
<View>
|
<View>
|
||||||
<Text style={firstRunStyle.paragraph}>
|
<Text style={firstRunStyle.paragraph}>
|
||||||
The LBRY servers were unreachable at this time. Please check your Internet connection and then restart the
|
{__(
|
||||||
app to try again.
|
'The LBRY servers were unreachable at this time. Please check your Internet connection and then restart the app to try again.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
@ -96,7 +97,7 @@ class WelcomePage extends React.PureComponent {
|
||||||
content = (
|
content = (
|
||||||
<View style={firstRunStyle.centered}>
|
<View style={firstRunStyle.centered}>
|
||||||
<ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} />
|
<ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} />
|
||||||
<Text style={firstRunStyle.paragraph}>Please wait while we get some things ready...</Text>
|
<Text style={firstRunStyle.paragraph}>{__('Please wait while we get some things ready...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,8 +105,9 @@ class WelcomePage extends React.PureComponent {
|
||||||
<View onLayout={onWelcomePageLayout}>
|
<View onLayout={onWelcomePageLayout}>
|
||||||
<Text style={firstRunStyle.title}>Welcome to LBRY.</Text>
|
<Text style={firstRunStyle.title}>Welcome to LBRY.</Text>
|
||||||
<Text style={firstRunStyle.paragraph}>
|
<Text style={firstRunStyle.paragraph}>
|
||||||
LBRY is a community-controlled content platform where you can find and publish videos, music, books, and
|
{__(
|
||||||
more.
|
'LBRY is a community-controlled content platform where you can find and publish videos, music, books, and more.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[firstRunStyle.infoParagraph, firstRunStyle.tosParagraph]}>
|
<Text style={[firstRunStyle.infoParagraph, firstRunStyle.tosParagraph]}>
|
||||||
By continuing, I agree to the{' '}
|
By continuing, I agree to the{' '}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Lbry } from 'lbry-redux';
|
import { SETTINGS, Lbry } from 'lbry-redux';
|
||||||
import { ActivityIndicator, Linking, NativeModules, Text, TouchableOpacity, View } from 'react-native';
|
import { ActivityIndicator, Linking, NativeModules, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import { NavigationActions, StackActions } from 'react-navigation';
|
import { NavigationActions, StackActions } from 'react-navigation';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
|
@ -11,6 +11,7 @@ import EmailCollectPage from './internal/email-collect-page';
|
||||||
import EmailVerifyPage from './internal/email-verify-page';
|
import EmailVerifyPage from './internal/email-verify-page';
|
||||||
import SkipAccountPage from './internal/skip-account-page';
|
import SkipAccountPage from './internal/skip-account-page';
|
||||||
import firstRunStyle from 'styles/firstRun';
|
import firstRunStyle from 'styles/firstRun';
|
||||||
|
import RNFS from 'react-native-fs';
|
||||||
|
|
||||||
class FirstRunScreen extends React.PureComponent {
|
class FirstRunScreen extends React.PureComponent {
|
||||||
static pages = [
|
static pages = [
|
||||||
|
@ -29,6 +30,7 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
enterPasswordTracked: false,
|
enterPasswordTracked: false,
|
||||||
isFirstRun: false,
|
isFirstRun: false,
|
||||||
launchUrl: null,
|
launchUrl: null,
|
||||||
|
languageLoaded: false,
|
||||||
showSkip: false,
|
showSkip: false,
|
||||||
isEmailVerified: false,
|
isEmailVerified: false,
|
||||||
skipAccountConfirmed: false,
|
skipAccountConfirmed: false,
|
||||||
|
@ -36,6 +38,7 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
walletPassword: '',
|
walletPassword: '',
|
||||||
syncApplyStarted: false,
|
syncApplyStarted: false,
|
||||||
syncApplyCompleted: false,
|
syncApplyCompleted: false,
|
||||||
|
language: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -45,7 +48,52 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// FirstRun module should always be present (in order to detect first run status)
|
NativeModules.UtilityModule.getNativeStringSetting(SETTINGS.LANGUAGE, 'en').then(language =>
|
||||||
|
this.loadLanguage(language)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadLanguage = language => {
|
||||||
|
if (!language || language === 'en') {
|
||||||
|
this.checkFirstRun();
|
||||||
|
} else {
|
||||||
|
// Load the current language setting before doing anything
|
||||||
|
const languageFile = RNFS.ExternalDirectoryPath + '/' + language + '.json';
|
||||||
|
RNFS.readFile(languageFile, 'utf8')
|
||||||
|
.then(fileContents => {
|
||||||
|
const json = JSON.parse(fileContents);
|
||||||
|
window.language = language;
|
||||||
|
window.i18n_messages[language] = json;
|
||||||
|
// language exists, so download an update
|
||||||
|
this.downloadLanguageUpdate(language);
|
||||||
|
this.checkFirstRun();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
// language file doesn't exist? maintain the default language
|
||||||
|
this.checkFirstRun();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
downloadLanguageUpdate = language => {
|
||||||
|
fetch('https://lbry.com/i18n/get/lbry-mobile/app-strings/' + language + '.json')
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(j => {
|
||||||
|
window.i18n_messages[language] = j;
|
||||||
|
|
||||||
|
// write the language file to the filesystem
|
||||||
|
const langFilePath = RNFS.ExternalDirectoryPath + '/' + language + '.json';
|
||||||
|
RNFS.writeFile(langFilePath, JSON.stringify(j), 'utf8');
|
||||||
|
|
||||||
|
// update state and client setting
|
||||||
|
window.language = language;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
/* pass */
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
checkFirstRun = () => {
|
||||||
NativeModules.FirstRun.isFirstRun().then(firstRun => {
|
NativeModules.FirstRun.isFirstRun().then(firstRun => {
|
||||||
AsyncStorage.removeItem(Constants.KEY_FIRST_RUN_EMAIL);
|
AsyncStorage.removeItem(Constants.KEY_FIRST_RUN_EMAIL);
|
||||||
AsyncStorage.removeItem(Constants.KEY_EMAIL_VERIFY_PENDING);
|
AsyncStorage.removeItem(Constants.KEY_EMAIL_VERIFY_PENDING);
|
||||||
|
@ -59,7 +107,7 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
this.launchSplashScreen();
|
this.launchSplashScreen();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { emailNewErrorMessage, emailNewPending, syncApplyErrorMessage, syncApplyIsPending, user } = nextProps;
|
const { emailNewErrorMessage, emailNewPending, syncApplyErrorMessage, syncApplyIsPending, user } = nextProps;
|
||||||
|
@ -78,7 +126,7 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
|
|
||||||
if (this.state.syncApplyStarted && !syncApplyIsPending) {
|
if (this.state.syncApplyStarted && !syncApplyIsPending) {
|
||||||
if (syncApplyErrorMessage && syncApplyErrorMessage.trim().length > 0) {
|
if (syncApplyErrorMessage && syncApplyErrorMessage.trim().length > 0) {
|
||||||
notify({ message: syncApplyErrorMessage, isError: true });
|
notify({ message: __(syncApplyErrorMessage), isError: true });
|
||||||
this.setState({ showBottomContainer: true, syncApplyStarted: false, syncApplyCompleted: false });
|
this.setState({ showBottomContainer: true, syncApplyStarted: false, syncApplyCompleted: false });
|
||||||
} else {
|
} else {
|
||||||
this.setState({ syncApplyCompleted: true });
|
this.setState({ syncApplyCompleted: true });
|
||||||
|
@ -97,7 +145,7 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
if (unlocked) {
|
if (unlocked) {
|
||||||
this.closeFinalPage();
|
this.closeFinalPage();
|
||||||
} else {
|
} else {
|
||||||
notify({ message: 'The wallet could not be unlocked at this time. Please restart the app.' });
|
notify({ message: __('The wallet could not be unlocked at this time. Please restart the app.') });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -183,7 +231,7 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT === this.state.currentPage && !this.state.skipAccountConfirmed) {
|
if (Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT === this.state.currentPage && !this.state.skipAccountConfirmed) {
|
||||||
notify({ message: 'Please confirm that you want to use LBRY without creating an account.' });
|
notify({ message: __('Please confirm that you want to use LBRY without creating an account.') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +257,7 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
// validate the email
|
// validate the email
|
||||||
if (!email || email.indexOf('@') === -1) {
|
if (!email || email.indexOf('@') === -1) {
|
||||||
return notify({
|
return notify({
|
||||||
message: 'Please provide a valid email address to continue.',
|
message: __('Please provide a valid email address to continue.'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +382,7 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
emailNewErrorMessage,
|
emailNewErrorMessage,
|
||||||
emailNewPending,
|
emailNewPending,
|
||||||
emailToVerify,
|
emailToVerify,
|
||||||
|
language,
|
||||||
notify,
|
notify,
|
||||||
hasSyncedWallet,
|
hasSyncedWallet,
|
||||||
getSyncIsPending,
|
getSyncIsPending,
|
||||||
|
@ -421,27 +470,27 @@ class FirstRunScreen extends React.PureComponent {
|
||||||
<Text style={firstRunStyle.buttonText}>
|
<Text style={firstRunStyle.buttonText}>
|
||||||
«{' '}
|
«{' '}
|
||||||
{Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT === this.state.currentPage
|
{Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT === this.state.currentPage
|
||||||
? 'Setup account'
|
? __('Setup account')
|
||||||
: 'Change email'}
|
: __('Change email')}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
{!emailNewPending && Constants.FIRST_RUN_PAGE_EMAIL_COLLECT === this.state.currentPage && (
|
{!emailNewPending && Constants.FIRST_RUN_PAGE_EMAIL_COLLECT === this.state.currentPage && (
|
||||||
<TouchableOpacity style={firstRunStyle.leftButton} onPress={this.handleLeftButtonPressed}>
|
<TouchableOpacity style={firstRunStyle.leftButton} onPress={this.handleLeftButtonPressed}>
|
||||||
<Text style={firstRunStyle.smallLeftButtonText}>No, thanks »</Text>
|
<Text style={firstRunStyle.smallLeftButtonText}>{__('No, thanks')} »</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!emailNewPending && (
|
{!emailNewPending && (
|
||||||
<TouchableOpacity style={firstRunStyle.button} onPress={this.handleContinuePressed}>
|
<TouchableOpacity style={firstRunStyle.button} onPress={this.handleContinuePressed}>
|
||||||
{Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT === this.state.currentPage && (
|
{Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT === this.state.currentPage && (
|
||||||
<Text style={firstRunStyle.smallButtonText}>Use LBRY »</Text>
|
<Text style={firstRunStyle.smallButtonText}>{__('Use LBRY')} »</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT !== this.state.currentPage &&
|
{Constants.FIRST_RUN_PAGE_SKIP_ACCOUNT !== this.state.currentPage &&
|
||||||
Constants.FIRST_RUN_PAGE_EMAIL_VERIFY !== this.state.currentPage && (
|
Constants.FIRST_RUN_PAGE_EMAIL_VERIFY !== this.state.currentPage && (
|
||||||
<Text style={firstRunStyle.buttonText}>
|
<Text style={firstRunStyle.buttonText}>
|
||||||
{Constants.FIRST_RUN_PAGE_WALLET === this.state.currentPage ? 'Use LBRY' : 'Continue'} »
|
{Constants.FIRST_RUN_PAGE_WALLET === this.state.currentPage ? __('Use LBRY') : __('Continue')} »
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
|
@ -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',
|
||||||
|
@ -345,7 +345,7 @@ class PublishPage extends React.PureComponent {
|
||||||
|
|
||||||
if (balance < Constants.MINIMUM_TRANSACTION_BALANCE) {
|
if (balance < Constants.MINIMUM_TRANSACTION_BALANCE) {
|
||||||
notify({
|
notify({
|
||||||
message: 'Publishing content requires credits. Press the blue bar to get some for free.',
|
message: __('Publishing content requires credits. Press the blue bar to get some for free.'),
|
||||||
});
|
});
|
||||||
if (this.scrollView) {
|
if (this.scrollView) {
|
||||||
this.scrollView.scrollTo({ x: 0, y: 0, animated: true });
|
this.scrollView.scrollTo({ x: 0, y: 0, animated: true });
|
||||||
|
@ -354,18 +354,18 @@ class PublishPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!title || title.trim().length === 0) {
|
if (!title || title.trim().length === 0) {
|
||||||
notify({ message: 'Please provide a title' });
|
notify({ message: __('Please provide a title') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
notify({ message: 'Please specify an address where people can find your content.' });
|
notify({ message: __('Please specify an address where people can find your content.') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentMedia && !editMode) {
|
if (!currentMedia && !editMode) {
|
||||||
// sanity check. normally shouldn't happen
|
// sanity check. normally shouldn't happen
|
||||||
notify({ message: 'No file selected. Please select a video or take a photo before publishing.' });
|
notify({ message: __('No file selected. Please select a video or take a photo before publishing.') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +403,7 @@ class PublishPage extends React.PureComponent {
|
||||||
pendingPublishSuccess(pendingClaim);
|
pendingPublishSuccess(pendingClaim);
|
||||||
|
|
||||||
notify({
|
notify({
|
||||||
message: `Your content was successfully published to ${this.state.uri}. It will be available in a few mintues.`,
|
message: __('Your content was successfully published. It will be available in a few mintues.'),
|
||||||
});
|
});
|
||||||
clearPublishFormState();
|
clearPublishFormState();
|
||||||
this.setState({ publishStarted: false });
|
this.setState({ publishStarted: false });
|
||||||
|
@ -553,7 +553,7 @@ class PublishPage extends React.PureComponent {
|
||||||
handleThumbnailUploadFailure = err => {
|
handleThumbnailUploadFailure = err => {
|
||||||
const { notify } = this.props;
|
const { notify } = this.props;
|
||||||
this.setState({ uploadThumbnailStarted: false });
|
this.setState({ uploadThumbnailStarted: false });
|
||||||
notify({ message: 'The thumbnail could not be uploaded. Please try again.' });
|
notify({ message: __('The thumbnail could not be uploaded. Please try again.') });
|
||||||
};
|
};
|
||||||
|
|
||||||
onFilePicked = evt => {
|
onFilePicked = evt => {
|
||||||
|
@ -586,7 +586,7 @@ class PublishPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// could not determine the file path
|
// could not determine the file path
|
||||||
notify({ message: 'The path could not be determined. Please try a different file.' });
|
notify({ message: __('The path could not be determined. Please try a different file.') });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -701,7 +701,7 @@ class PublishPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isNameValid(name, false)) {
|
if (!isNameValid(name, false)) {
|
||||||
notify({ message: 'Your content address contains invalid characters' });
|
notify({ message: __('Your content address contains invalid characters') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,7 +731,7 @@ class PublishPage extends React.PureComponent {
|
||||||
updatePublishFormState({ tags: newTags });
|
updatePublishFormState({ tags: newTags });
|
||||||
this.setState({ tags: newTags });
|
this.setState({ tags: newTags });
|
||||||
} else {
|
} else {
|
||||||
notify({ message: __(`You already added the "${tag}" tag.`) });
|
notify({ message: __(`You already added the "${tag}" tag.`) }); // TODO: tokenize i18n
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -868,7 +868,7 @@ class PublishPage extends React.PureComponent {
|
||||||
const { notify } = this.props;
|
const { notify } = this.props;
|
||||||
if (this.state.thumbnailImagePickerOpen || this.state.uploadThumbnailStarted) {
|
if (this.state.thumbnailImagePickerOpen || this.state.uploadThumbnailStarted) {
|
||||||
if (this.state.uploadThumbnailStarted) {
|
if (this.state.uploadThumbnailStarted) {
|
||||||
notify({ message: 'A thumbnail is already being uploaded. Please wait for the upload to finish.' });
|
notify({ message: __('A thumbnail is already being uploaded. Please wait for the upload to finish.') });
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -913,7 +913,7 @@ class PublishPage extends React.PureComponent {
|
||||||
onPress={this.handleRecordVideoPressed}
|
onPress={this.handleRecordVideoPressed}
|
||||||
>
|
>
|
||||||
<Icon name="video" size={48} color={Colors.White} />
|
<Icon name="video" size={48} color={Colors.White} />
|
||||||
<Text style={publishStyle.actionText}>Record</Text>
|
<Text style={publishStyle.actionText}>{__('Record')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<View style={publishStyle.subActions}>
|
<View style={publishStyle.subActions}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
|
@ -924,11 +924,11 @@ class PublishPage extends React.PureComponent {
|
||||||
onPress={this.handleTakePhotoPressed}
|
onPress={this.handleTakePhotoPressed}
|
||||||
>
|
>
|
||||||
<Icon name="camera" size={48} color={Colors.White} />
|
<Icon name="camera" size={48} color={Colors.White} />
|
||||||
<Text style={publishStyle.actionText}>Take a photo</Text>
|
<Text style={publishStyle.actionText}>{__('Take a photo')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={publishStyle.upload} onPress={this.handleUploadPressed}>
|
<TouchableOpacity style={publishStyle.upload} onPress={this.handleUploadPressed}>
|
||||||
<Icon name="file-upload" size={48} color={Colors.White} />
|
<Icon name="file-upload" size={48} color={Colors.White} />
|
||||||
<Text style={publishStyle.actionText}>Upload a file</Text>
|
<Text style={publishStyle.actionText}>{__('Upload a file')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
@ -936,13 +936,13 @@ class PublishPage extends React.PureComponent {
|
||||||
{(loadingVideos || !allThumbnailsChecked) && (
|
{(loadingVideos || !allThumbnailsChecked) && (
|
||||||
<View style={publishStyle.loadingView}>
|
<View style={publishStyle.loadingView}>
|
||||||
<ActivityIndicator size="small" color={Colors.NextLbryGreen} />
|
<ActivityIndicator size="small" color={Colors.NextLbryGreen} />
|
||||||
<Text style={publishStyle.loadingText}>Please wait while we load your videos...</Text>
|
<Text style={publishStyle.loadingText}>{__('Please wait while we load your videos...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{!loadingVideos && (!videos || videos.length === 0) && (
|
{!loadingVideos && (!videos || videos.length === 0) && (
|
||||||
<View style={publishStyle.relativeCentered}>
|
<View style={publishStyle.relativeCentered}>
|
||||||
<Text style={publishStyle.noVideos}>
|
<Text style={publishStyle.noVideos}>
|
||||||
We could not find any videos on your device. Take a photo or record a video to get started.
|
{__('We could not find any videos on your device. Take a photo or record a video to get started.')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
@ -994,7 +994,7 @@ class PublishPage extends React.PureComponent {
|
||||||
{this.state.uploadThumbnailStarted && (
|
{this.state.uploadThumbnailStarted && (
|
||||||
<View style={publishStyle.thumbnailUploadContainer}>
|
<View style={publishStyle.thumbnailUploadContainer}>
|
||||||
<ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
|
<ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
|
||||||
<Text style={publishStyle.thumbnailUploadText}>Uploading thumbnail...</Text>
|
<Text style={publishStyle.thumbnailUploadText}>{__('Uploading thumbnail...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
@ -1003,11 +1003,11 @@ class PublishPage extends React.PureComponent {
|
||||||
<View style={publishStyle.card}>
|
<View style={publishStyle.card}>
|
||||||
<View style={publishStyle.textInputLayout}>
|
<View style={publishStyle.textInputLayout}>
|
||||||
{(this.state.titleFocused || (this.state.title != null && this.state.title.trim().length > 0)) && (
|
{(this.state.titleFocused || (this.state.title != null && this.state.title.trim().length > 0)) && (
|
||||||
<Text style={publishStyle.textInputTitle}>Title</Text>
|
<Text style={publishStyle.textInputTitle}>{__('Title')}</Text>
|
||||||
)}
|
)}
|
||||||
<TextInput
|
<TextInput
|
||||||
editable={this.state.canPublish && !this.state.publishStarted}
|
editable={this.state.canPublish && !this.state.publishStarted}
|
||||||
placeholder={this.state.titleFocused ? '' : 'Title'}
|
placeholder={this.state.titleFocused ? '' : __('Title')}
|
||||||
style={publishStyle.inputText}
|
style={publishStyle.inputText}
|
||||||
value={this.state.title}
|
value={this.state.title}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
|
@ -1021,12 +1021,12 @@ class PublishPage extends React.PureComponent {
|
||||||
<View style={publishStyle.textInputLayout}>
|
<View style={publishStyle.textInputLayout}>
|
||||||
{(this.state.descriptionFocused ||
|
{(this.state.descriptionFocused ||
|
||||||
(this.state.description != null && this.state.description.trim().length > 0)) && (
|
(this.state.description != null && this.state.description.trim().length > 0)) && (
|
||||||
<Text style={publishStyle.textInputTitle}>Description</Text>
|
<Text style={publishStyle.textInputTitle}>{__('Description')}</Text>
|
||||||
)}
|
)}
|
||||||
<TextInput
|
<TextInput
|
||||||
editable={this.state.canPublish && !this.state.publishStarted}
|
editable={this.state.canPublish && !this.state.publishStarted}
|
||||||
multiline
|
multiline
|
||||||
placeholder={this.state.descriptionFocused ? '' : 'Description'}
|
placeholder={this.state.descriptionFocused ? '' : __('Description')}
|
||||||
style={publishStyle.inputText}
|
style={publishStyle.inputText}
|
||||||
value={this.state.description}
|
value={this.state.description}
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
|
@ -1038,7 +1038,7 @@ class PublishPage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={publishStyle.card}>
|
<View style={publishStyle.card}>
|
||||||
<Text style={publishStyle.cardTitle}>Tags</Text>
|
<Text style={publishStyle.cardTitle}>{__('Tags')}</Text>
|
||||||
<View style={publishStyle.tagList}>
|
<View style={publishStyle.tagList}>
|
||||||
{this.state.tags &&
|
{this.state.tags &&
|
||||||
this.state.tags.map(tag => (
|
this.state.tags.map(tag => (
|
||||||
|
@ -1055,7 +1055,7 @@ class PublishPage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={publishStyle.card}>
|
<View style={publishStyle.card}>
|
||||||
<Text style={publishStyle.cardTitle}>Channel</Text>
|
<Text style={publishStyle.cardTitle}>{__('Channel')}</Text>
|
||||||
|
|
||||||
<ChannelSelector
|
<ChannelSelector
|
||||||
enabled={this.state.canPublish && !this.state.publishStarted}
|
enabled={this.state.canPublish && !this.state.publishStarted}
|
||||||
|
@ -1066,14 +1066,16 @@ class PublishPage extends React.PureComponent {
|
||||||
|
|
||||||
<View style={publishStyle.card}>
|
<View style={publishStyle.card}>
|
||||||
<View style={publishStyle.titleRow}>
|
<View style={publishStyle.titleRow}>
|
||||||
<Text style={publishStyle.cardTitle}>Price</Text>
|
<Text style={publishStyle.cardTitle}>{__('Price')}</Text>
|
||||||
<View style={publishStyle.switchTitleRow}>
|
<View style={publishStyle.switchTitleRow}>
|
||||||
<Switch value={this.state.priceSet} onValueChange={value => this.setState({ priceSet: value })} />
|
<Switch value={this.state.priceSet} onValueChange={value => this.setState({ priceSet: value })} />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{!this.state.priceSet && (
|
{!this.state.priceSet && (
|
||||||
<Text style={publishStyle.cardText}>Your content will be free. Press the toggle to set a price.</Text>
|
<Text style={publishStyle.cardText}>
|
||||||
|
{__('Your content will be free. Press the toggle to set a price.')}
|
||||||
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{this.state.priceSet && (
|
{this.state.priceSet && (
|
||||||
|
@ -1103,11 +1105,13 @@ class PublishPage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={publishStyle.card}>
|
<View style={publishStyle.card}>
|
||||||
<Text style={publishStyle.cardTitle}>Content address</Text>
|
<Text style={publishStyle.cardTitle}>{__('Content address')}</Text>
|
||||||
<Text style={publishStyle.helpText}>
|
<Text style={publishStyle.helpText}>
|
||||||
The address where people can find your content (ex. lbry://myvideo).
|
{__('The address where people can find your content (ex. lbry://myvideo). ')}
|
||||||
{this.state.editMode &&
|
{this.state.editMode &&
|
||||||
' You cannot change this address while editing your content. If you wish to use a new address, please republish the content.'}
|
__(
|
||||||
|
'You cannot change this address while editing your content. If you wish to use a new address, please republish the content.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
|
@ -1132,14 +1136,16 @@ class PublishPage extends React.PureComponent {
|
||||||
/>
|
/>
|
||||||
<Text style={publishStyle.currency}>LBC</Text>
|
<Text style={publishStyle.currency}>LBC</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={publishStyle.helpText}>This LBC remains yours and the deposit can be undone at any time.</Text>
|
<Text style={publishStyle.helpText}>
|
||||||
|
{__('This LBC remains yours and the deposit can be undone at any time.')}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{this.state.advancedMode && (
|
{this.state.advancedMode && (
|
||||||
<View style={publishStyle.card}>
|
<View style={publishStyle.card}>
|
||||||
<Text style={publishStyle.cardTitle}>Additional Options</Text>
|
<Text style={publishStyle.cardTitle}>{__('Additional Options')}</Text>
|
||||||
<View>
|
<View>
|
||||||
<Text style={publishStyle.cardText}>Language</Text>
|
<Text style={publishStyle.cardText}>{__('Language')}</Text>
|
||||||
<Picker
|
<Picker
|
||||||
enabled={this.state.canPublish && !this.state.publishStarted}
|
enabled={this.state.canPublish && !this.state.publishStarted}
|
||||||
selectedValue={this.state.language}
|
selectedValue={this.state.language}
|
||||||
|
@ -1148,13 +1154,13 @@ class PublishPage extends React.PureComponent {
|
||||||
onValueChange={this.handleLanguageValueChange}
|
onValueChange={this.handleLanguageValueChange}
|
||||||
>
|
>
|
||||||
{Object.keys(languages).map(lang => (
|
{Object.keys(languages).map(lang => (
|
||||||
<Picker.Item label={languages[lang]} value={lang} key={lang} />
|
<Picker.Item label={__(languages[lang])} value={lang} key={lang} />
|
||||||
))}
|
))}
|
||||||
</Picker>
|
</Picker>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View>
|
<View>
|
||||||
<Text style={publishStyle.cardText}>License</Text>
|
<Text style={publishStyle.cardText}>{__('License')}</Text>
|
||||||
<Picker
|
<Picker
|
||||||
enabled={this.state.canPublish && !this.state.publishStarted}
|
enabled={this.state.canPublish && !this.state.publishStarted}
|
||||||
selectedValue={this.state.license}
|
selectedValue={this.state.license}
|
||||||
|
@ -1162,18 +1168,22 @@ class PublishPage extends React.PureComponent {
|
||||||
itemStyle={publishStyle.pickerItem}
|
itemStyle={publishStyle.pickerItem}
|
||||||
onValueChange={this.handleLicenseValueChange}
|
onValueChange={this.handleLicenseValueChange}
|
||||||
>
|
>
|
||||||
<Picker.Item label={'None'} value={LICENSES.NONE} key={LICENSES.NONE} />
|
<Picker.Item label={__('None')} value={LICENSES.NONE} key={LICENSES.NONE} />
|
||||||
<Picker.Item label={'Public Domain'} value={LICENSES.PUBLIC_DOMAIN} key={LICENSES.PUBLIC_DOMAIN} />
|
<Picker.Item
|
||||||
|
label={__('Public Domain')}
|
||||||
|
value={LICENSES.PUBLIC_DOMAIN}
|
||||||
|
key={LICENSES.PUBLIC_DOMAIN}
|
||||||
|
/>
|
||||||
{LICENSES.CC_LICENSES.map(({ value, url }) => (
|
{LICENSES.CC_LICENSES.map(({ value, url }) => (
|
||||||
<Picker.Item label={value} value={value} key={value} />
|
<Picker.Item label={value} value={value} key={value} />
|
||||||
))}
|
))}
|
||||||
<Picker.Item label={'Copyrighted...'} value={LICENSES.COPYRIGHT} key={LICENSES.COPYRIGHT} />
|
<Picker.Item label={__('Copyrighted...')} value={LICENSES.COPYRIGHT} key={LICENSES.COPYRIGHT} />
|
||||||
<Picker.Item label={'Other...'} value={LICENSES.OTHER} key={LICENSES.OTHER} />
|
<Picker.Item label={__('Other...')} value={LICENSES.OTHER} key={LICENSES.OTHER} />
|
||||||
</Picker>
|
</Picker>
|
||||||
{[LICENSES.COPYRIGHT, LICENSES.OTHER].includes(this.state.license) && (
|
{[LICENSES.COPYRIGHT, LICENSES.OTHER].includes(this.state.license) && (
|
||||||
<TextInput
|
<TextInput
|
||||||
editable={this.state.canPublish && !this.state.publishStarted}
|
editable={this.state.canPublish && !this.state.publishStarted}
|
||||||
placeholder={'License description'}
|
placeholder={__('License description')}
|
||||||
style={publishStyle.inputText}
|
style={publishStyle.inputText}
|
||||||
underlineColorAndroid={Colors.NextLbryGreen}
|
underlineColorAndroid={Colors.NextLbryGreen}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
|
@ -1187,7 +1197,7 @@ class PublishPage extends React.PureComponent {
|
||||||
|
|
||||||
<View style={publishStyle.toggleContainer}>
|
<View style={publishStyle.toggleContainer}>
|
||||||
<Link
|
<Link
|
||||||
text={this.state.advancedMode ? 'Hide extra fields' : 'Show extra fields'}
|
text={this.state.advancedMode ? __('Hide extra fields') : __('Show extra fields')}
|
||||||
onPress={this.handleModePressed}
|
onPress={this.handleModePressed}
|
||||||
style={publishStyle.modeLink}
|
style={publishStyle.modeLink}
|
||||||
/>
|
/>
|
||||||
|
@ -1201,7 +1211,7 @@ class PublishPage extends React.PureComponent {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!this.state.publishStarted && (
|
{!this.state.publishStarted && (
|
||||||
<Link style={publishStyle.cancelLink} text="Cancel" onPress={() => this.showSelector()} />
|
<Link style={publishStyle.cancelLink} text={__('Cancel')} onPress={() => this.showSelector()} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!this.state.publishStarted && (
|
{!this.state.publishStarted && (
|
||||||
|
@ -1209,7 +1219,7 @@ class PublishPage extends React.PureComponent {
|
||||||
<Button
|
<Button
|
||||||
style={publishStyle.publishButton}
|
style={publishStyle.publishButton}
|
||||||
disabled={this.state.uploadThumbnailStarted}
|
disabled={this.state.uploadThumbnailStarted}
|
||||||
text={this.state.editMode ? 'Save changes' : 'Publish'}
|
text={this.state.editMode ? __('Save changes') : __('Publish')}
|
||||||
onPress={this.handlePublishPressed}
|
onPress={this.handlePublishPressed}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
@ -1221,8 +1231,10 @@ class PublishPage extends React.PureComponent {
|
||||||
content = (
|
content = (
|
||||||
<ScrollView style={publishStyle.publishDetails}>
|
<ScrollView style={publishStyle.publishDetails}>
|
||||||
<View style={publishStyle.successContainer}>
|
<View style={publishStyle.successContainer}>
|
||||||
<Text style={publishStyle.successTitle}>Success!</Text>
|
<Text style={publishStyle.successTitle}>{__('Success!')}</Text>
|
||||||
<Text style={publishStyle.successText}>Congratulations! Your content was successfully uploaded.</Text>
|
<Text style={publishStyle.successText}>
|
||||||
|
{__('Congratulations! Your content was successfully uploaded.')}
|
||||||
|
</Text>
|
||||||
<View style={publishStyle.successRow}>
|
<View style={publishStyle.successRow}>
|
||||||
<Link
|
<Link
|
||||||
style={publishStyle.successUrl}
|
style={publishStyle.successUrl}
|
||||||
|
@ -1232,19 +1244,24 @@ class PublishPage extends React.PureComponent {
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
Clipboard.setString(this.state.uri);
|
Clipboard.setString(this.state.uri);
|
||||||
notify({ message: 'Copied.' });
|
notify({ message: __('Copied.') });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon name="clipboard" size={24} color={Colors.LbryGreen} />
|
<Icon name="clipboard" size={24} color={Colors.LbryGreen} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<Text style={publishStyle.successText}>
|
<Text style={publishStyle.successText}>
|
||||||
Your content will be live in a few minutes. In the mean time, feel free to publish more content or explore
|
{__(
|
||||||
the app.
|
'Your content will be live in a few minutes. In the mean time, feel free to publish more content or explore the app.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={publishStyle.actionButtons}>
|
<View style={publishStyle.actionButtons}>
|
||||||
<Button style={publishStyle.publishButton} text="Publish again" onPress={this.handlePublishAgainPressed} />
|
<Button
|
||||||
|
style={publishStyle.publishButton}
|
||||||
|
text={__('Publish again')}
|
||||||
|
onPress={this.handlePublishAgainPressed}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
|
@ -1282,7 +1299,7 @@ class PublishPage extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
notAuthorizedView={
|
notAuthorizedView={
|
||||||
<View style={publishStyle.fullCentered}>
|
<View style={publishStyle.fullCentered}>
|
||||||
<Text style={publishStyle.cameraInfo}>Camera not authorized</Text>
|
<Text style={publishStyle.cameraInfo}>{__('Camera not authorized')}</Text>
|
||||||
</View>
|
</View>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
@ -107,7 +106,8 @@ class RewardsPage extends React.PureComponent {
|
||||||
<View style={[rewardStyle.card, rewardStyle.verification]}>
|
<View style={[rewardStyle.card, rewardStyle.verification]}>
|
||||||
<Text style={rewardStyle.title}>Manual Reward Verification</Text>
|
<Text style={rewardStyle.title}>Manual Reward Verification</Text>
|
||||||
<Text style={rewardStyle.text}>
|
<Text style={rewardStyle.text}>
|
||||||
You need to be manually verified before you can start claiming rewards. Please request to be verified on the{' '}
|
__('You need to be manually verified before you can start claiming rewards.') Please request to be verified
|
||||||
|
on the{' '}
|
||||||
<Link
|
<Link
|
||||||
style={rewardStyle.greenLink}
|
style={rewardStyle.greenLink}
|
||||||
href="https://discordapp.com/invite/Z3bERWA"
|
href="https://discordapp.com/invite/Z3bERWA"
|
||||||
|
@ -130,13 +130,15 @@ class RewardsPage extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<View style={rewardStyle.busyContainer}>
|
<View style={rewardStyle.busyContainer}>
|
||||||
<ActivityIndicator size="large" color={Colors.NextLbryGreen} />
|
<ActivityIndicator size="large" color={Colors.NextLbryGreen} />
|
||||||
<Text style={rewardStyle.infoText}>Fetching rewards...</Text>
|
<Text style={rewardStyle.infoText}>{__('Fetching rewards...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
} else if (user === null) {
|
} else if (user === null) {
|
||||||
return (
|
return (
|
||||||
<View style={rewardStyle.busyContainer}>
|
<View style={rewardStyle.busyContainer}>
|
||||||
<Text style={rewardStyle.infoText}>This app is unable to earn rewards due to an authentication failure.</Text>
|
<Text style={rewardStyle.infoText}>
|
||||||
|
{__('This app is unable to earn rewards due to an authentication failure.')}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ class SearchPage extends React.PureComponent {
|
||||||
{showTagResult && (
|
{showTagResult && (
|
||||||
<TouchableOpacity style={searchStyle.tagResultItem} onPress={() => this.handleTagResultPressed(query)}>
|
<TouchableOpacity style={searchStyle.tagResultItem} onPress={() => this.handleTagResultPressed(query)}>
|
||||||
<Text style={searchStyle.tagResultTitle}>#{query.toLowerCase()}</Text>
|
<Text style={searchStyle.tagResultTitle}>#{query.toLowerCase()}</Text>
|
||||||
<Text style={searchStyle.tagResultDescription}>Explore content for this tag</Text>
|
<Text style={searchStyle.tagResultDescription}>{__('Explore content for this tag')}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { SETTINGS } from 'lbry-redux';
|
import { SETTINGS, doToast } from 'lbry-redux';
|
||||||
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
import { doPushDrawerStack, doPopDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||||
import { doSetClientSetting } from 'redux/actions/settings';
|
import { doSetClientSetting } from 'redux/actions/settings';
|
||||||
import { selectCurrentRoute, selectDrawerStack } from 'redux/selectors/drawer';
|
import { selectCurrentRoute, selectDrawerStack } from 'redux/selectors/drawer';
|
||||||
|
@ -12,6 +12,7 @@ const select = state => ({
|
||||||
currentRoute: selectCurrentRoute(state),
|
currentRoute: selectCurrentRoute(state),
|
||||||
drawerStack: selectDrawerStack(state),
|
drawerStack: selectDrawerStack(state),
|
||||||
keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state),
|
keepDaemonRunning: makeSelectClientSetting(SETTINGS.KEEP_DAEMON_RUNNING)(state),
|
||||||
|
language: makeSelectClientSetting(SETTINGS.LANGUAGE)(state),
|
||||||
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state),
|
showNsfw: makeSelectClientSetting(SETTINGS.SHOW_NSFW)(state),
|
||||||
showUriBarSuggestions: makeSelectClientSetting(SETTINGS.SHOW_URI_BAR_SUGGESTIONS)(state),
|
showUriBarSuggestions: makeSelectClientSetting(SETTINGS.SHOW_URI_BAR_SUGGESTIONS)(state),
|
||||||
receiveSubscriptionNotifications: makeSelectClientSetting(SETTINGS.RECEIVE_SUBSCRIPTION_NOTIFICATIONS)(state),
|
receiveSubscriptionNotifications: makeSelectClientSetting(SETTINGS.RECEIVE_SUBSCRIPTION_NOTIFICATIONS)(state),
|
||||||
|
@ -21,6 +22,7 @@ const select = state => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
|
notify: data => dispatch(doToast(data)),
|
||||||
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SETTINGS)),
|
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_SETTINGS)),
|
||||||
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
||||||
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
|
setClientSetting: (key, value) => dispatch(doSetClientSetting(key, value)),
|
||||||
|
|
|
@ -1,12 +1,33 @@
|
||||||
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 { ActivityIndicator, Picker, Platform, Text, View, ScrollView, Switch, NativeModules } from 'react-native';
|
||||||
import { __, navigateBack } from 'utils/helper';
|
import { navigateBack } from 'utils/helper';
|
||||||
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
|
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';
|
||||||
|
import RNFS from 'react-native-fs';
|
||||||
import settingsStyle from 'styles/settings';
|
import settingsStyle from 'styles/settings';
|
||||||
|
|
||||||
|
const languageOptions = [
|
||||||
|
{ code: 'default', name: 'Use device language' },
|
||||||
|
{ code: 'en', name: 'English' },
|
||||||
|
{ code: 'gu', name: 'Gujarati' },
|
||||||
|
{ code: 'hi', name: 'Hindi' },
|
||||||
|
{ code: 'id', name: 'Indonesian' },
|
||||||
|
{ code: 'it', name: 'Italian' },
|
||||||
|
{ code: 'ms', name: 'Malay' },
|
||||||
|
{ code: 'tr', name: 'Turkish' },
|
||||||
|
{ code: 'pl', name: 'Polish' },
|
||||||
|
{ code: 'pt', name: 'Portuguese' },
|
||||||
|
{ code: 'es', name: 'Spanish' },
|
||||||
|
];
|
||||||
|
|
||||||
class SettingsPage extends React.PureComponent {
|
class SettingsPage extends React.PureComponent {
|
||||||
|
state = {
|
||||||
|
downloadingLanguage: false,
|
||||||
|
};
|
||||||
|
|
||||||
static navigationOptions = {
|
static navigationOptions = {
|
||||||
title: 'Settings',
|
title: 'Settings',
|
||||||
};
|
};
|
||||||
|
@ -53,17 +74,70 @@ class SettingsPage extends React.PureComponent {
|
||||||
return value === null || value === undefined ? defaultValue : value;
|
return value === null || value === undefined ? defaultValue : value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleLanguageValueChange = value => {
|
||||||
|
const { notify, setClientSetting } = this.props;
|
||||||
|
|
||||||
|
let language;
|
||||||
|
if (value === 'default') {
|
||||||
|
language =
|
||||||
|
Platform.OS === 'android'
|
||||||
|
? NativeModules.I18nManager.localeIdentifier
|
||||||
|
: NativeModules.SettingsManager.settings.AppleLocale;
|
||||||
|
language = language ? language.substring(0, 2) : 'en';
|
||||||
|
} else {
|
||||||
|
language = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the local filesystem for the language first? Or download remote strings first?
|
||||||
|
|
||||||
|
// download and save the language file
|
||||||
|
this.setState({ downloadingLanguage: true }, () => {
|
||||||
|
fetch('https://lbry.com/i18n/get/lbry-mobile/app-strings/' + language + '.json')
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(j => {
|
||||||
|
window.i18n_messages[language] = j;
|
||||||
|
|
||||||
|
// write the language file to the filesystem
|
||||||
|
const langFilePath = RNFS.ExternalDirectoryPath + '/' + language + '.json';
|
||||||
|
RNFS.writeFile(langFilePath, JSON.stringify(j), 'utf8');
|
||||||
|
|
||||||
|
// save the setting outside redux because when the first component mounts, the redux value isn't loaded yet
|
||||||
|
// so we have to load it from native settings
|
||||||
|
NativeModules.UtilityModule.setNativeStringSetting(SETTINGS.LANGUAGE, value);
|
||||||
|
|
||||||
|
// update state and client setting
|
||||||
|
window.language = language;
|
||||||
|
setClientSetting(SETTINGS.LANGUAGE, value);
|
||||||
|
|
||||||
|
this.setState({ downloadingLanguage: false });
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
notify({ message: __('Failed to load %language% translations.', { language: language }), isError: true });
|
||||||
|
this.setState({ downloadingLanguage: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleBackPressed = () => {
|
||||||
|
const { navigation, notify, drawerStack, popDrawerStack } = this.props;
|
||||||
|
|
||||||
|
if (this.state.downloadingLanguage) {
|
||||||
|
notify({ message: 'Please wait for the language file to finish downloading' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateBack(navigation, drawerStack, popDrawerStack);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
backgroundPlayEnabled,
|
backgroundPlayEnabled,
|
||||||
drawerStack,
|
|
||||||
keepDaemonRunning,
|
keepDaemonRunning,
|
||||||
navigation,
|
|
||||||
popDrawerStack,
|
|
||||||
receiveSubscriptionNotifications,
|
receiveSubscriptionNotifications,
|
||||||
receiveRewardNotifications,
|
receiveRewardNotifications,
|
||||||
receiveInterestsNotifications,
|
receiveInterestsNotifications,
|
||||||
receiveCreatorNotifications,
|
receiveCreatorNotifications,
|
||||||
|
language,
|
||||||
showNsfw,
|
showNsfw,
|
||||||
showUriBarSuggestions,
|
showUriBarSuggestions,
|
||||||
setClientSetting,
|
setClientSetting,
|
||||||
|
@ -78,14 +152,14 @@ class SettingsPage extends React.PureComponent {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={settingsStyle.container}>
|
<View style={settingsStyle.container}>
|
||||||
<PageHeader title={'Settings'} onBackPressed={() => navigateBack(navigation, drawerStack, popDrawerStack)} />
|
<PageHeader title={__('Settings')} onBackPressed={this.handleBackPressed} />
|
||||||
<ScrollView style={settingsStyle.scrollContainer}>
|
<ScrollView style={settingsStyle.scrollContainer}>
|
||||||
<Text style={settingsStyle.sectionTitle}>Content</Text>
|
<Text style={settingsStyle.sectionTitle}>{__('Content')}</Text>
|
||||||
<View style={settingsStyle.row}>
|
<View style={settingsStyle.row}>
|
||||||
<View style={settingsStyle.switchText}>
|
<View style={settingsStyle.switchText}>
|
||||||
<Text style={settingsStyle.label}>Enable background media playback</Text>
|
<Text style={settingsStyle.label}>{__('Enable background media playback')}</Text>
|
||||||
<Text style={settingsStyle.description}>
|
<Text style={settingsStyle.description}>
|
||||||
Enable this option to play audio or video in the background when the app is suspended.
|
{__('Enable this option to play audio or video in the background when the app is suspended.')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={settingsStyle.switchContainer}>
|
<View style={settingsStyle.switchContainer}>
|
||||||
|
@ -96,9 +170,30 @@ class SettingsPage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
<Text style={settingsStyle.sectionTitle}>{__('Language')}</Text>
|
||||||
|
<View style={settingsStyle.pickerRow}>
|
||||||
|
<View style={settingsStyle.pickerText}>
|
||||||
|
<Text style={settingsStyle.label}>{__('Choose language')}</Text>
|
||||||
|
</View>
|
||||||
|
<View style={settingsStyle.pickerContainer}>
|
||||||
|
{this.state.downloadingLanguage && <ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />}
|
||||||
|
<Picker
|
||||||
|
enabled={!this.state.downloadingLanguage}
|
||||||
|
selectedValue={language || 'default'}
|
||||||
|
style={settingsStyle.languagePicker}
|
||||||
|
itemStyle={settingsStyle.languagePickerItem}
|
||||||
|
onValueChange={this.handleLanguageValueChange}
|
||||||
|
>
|
||||||
|
{languageOptions.map(option => (
|
||||||
|
<Picker.Item label={__(option.name)} value={option.code} key={option.code} />
|
||||||
|
))}
|
||||||
|
</Picker>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
<View style={settingsStyle.row}>
|
<View style={settingsStyle.row}>
|
||||||
<View style={settingsStyle.switchText}>
|
<View style={settingsStyle.switchText}>
|
||||||
<Text style={settingsStyle.label}>Show mature content</Text>
|
<Text style={settingsStyle.label}>{__('Show mature content')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={settingsStyle.switchContainer}>
|
<View style={settingsStyle.switchContainer}>
|
||||||
<Switch value={showNsfw} onValueChange={value => setClientSetting(SETTINGS.SHOW_NSFW, value)} />
|
<Switch value={showNsfw} onValueChange={value => setClientSetting(SETTINGS.SHOW_NSFW, value)} />
|
||||||
|
@ -169,10 +264,10 @@ class SettingsPage extends React.PureComponent {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<View style={settingsStyle.sectionDivider} />
|
<View style={settingsStyle.sectionDivider} />
|
||||||
<Text style={settingsStyle.sectionTitle}>Search</Text>
|
<Text style={settingsStyle.sectionTitle}>{__('Search')}</Text>
|
||||||
<View style={settingsStyle.row}>
|
<View style={settingsStyle.row}>
|
||||||
<View style={settingsStyle.switchText}>
|
<View style={settingsStyle.switchText}>
|
||||||
<Text style={settingsStyle.label}>Show URL suggestions</Text>
|
<Text style={settingsStyle.label}>{__('Show URL suggestions')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={settingsStyle.switchContainer}>
|
<View style={settingsStyle.switchContainer}>
|
||||||
<Switch
|
<Switch
|
||||||
|
@ -183,13 +278,16 @@ class SettingsPage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={settingsStyle.sectionDivider} />
|
<View style={settingsStyle.sectionDivider} />
|
||||||
<Text style={settingsStyle.sectionTitle}>Other</Text>
|
<Text style={settingsStyle.sectionTitle}>{__('Other')}</Text>
|
||||||
<View style={settingsStyle.row}>
|
<View style={settingsStyle.row}>
|
||||||
<View style={settingsStyle.switchText}>
|
<View style={settingsStyle.switchText}>
|
||||||
<Text style={settingsStyle.label}>Keep the daemon background service running after closing the app</Text>
|
<Text style={settingsStyle.label}>
|
||||||
|
{__('Keep the SDK background service running after closing the app')}
|
||||||
|
</Text>
|
||||||
<Text style={settingsStyle.description}>
|
<Text style={settingsStyle.description}>
|
||||||
Enable this option for quicker app launch and to keep the synchronisation with the blockchain up to
|
{__(
|
||||||
date.
|
'Enable this option for quicker app launch and to keep the synchronisation with the blockchain up to date.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={settingsStyle.switchContainer}>
|
<View style={settingsStyle.switchContainer}>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doBalanceSubscribe, doUpdateBlockHeight, doPopulateSharedUserState, doToast } from 'lbry-redux';
|
import { SETTINGS, doBalanceSubscribe, doUpdateBlockHeight, doPopulateSharedUserState, doToast } from 'lbry-redux';
|
||||||
import {
|
import {
|
||||||
doAuthenticate,
|
doAuthenticate,
|
||||||
doBlackListedOutpointsSubscribe,
|
doBlackListedOutpointsSubscribe,
|
||||||
|
|
|
@ -13,12 +13,10 @@ import PropTypes from 'prop-types';
|
||||||
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 splashStyle from 'styles/splash';
|
import splashStyle from 'styles/splash';
|
||||||
|
import RNFS from 'react-native-fs';
|
||||||
|
|
||||||
const BLOCK_HEIGHT_INTERVAL = 1000 * 60 * 2.5; // every 2.5 minutes
|
const BLOCK_HEIGHT_INTERVAL = 1000 * 60 * 2.5; // every 2.5 minutes
|
||||||
|
|
||||||
const testingNetwork = 'Testing network';
|
|
||||||
const waitingForResolution = 'Waiting for name resolution';
|
|
||||||
|
|
||||||
class SplashScreen extends React.PureComponent {
|
class SplashScreen extends React.PureComponent {
|
||||||
static navigationOptions = {
|
static navigationOptions = {
|
||||||
title: 'Splash',
|
title: 'Splash',
|
||||||
|
@ -27,8 +25,8 @@ class SplashScreen extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
accountUnlockFailed: false,
|
accountUnlockFailed: false,
|
||||||
daemonReady: false,
|
daemonReady: false,
|
||||||
details: 'Starting up',
|
details: __('Starting up'),
|
||||||
message: 'Connecting',
|
message: __('Connecting'),
|
||||||
isRunning: false,
|
isRunning: false,
|
||||||
isLagging: false,
|
isLagging: false,
|
||||||
launchUrl: null,
|
launchUrl: null,
|
||||||
|
@ -69,13 +67,13 @@ class SplashScreen extends React.PureComponent {
|
||||||
try {
|
try {
|
||||||
verifyUserEmail(verification.token, verification.recaptcha);
|
verifyUserEmail(verification.token, verification.recaptcha);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = 'Invalid Verification Token';
|
const message = __('Invalid Verification Token');
|
||||||
verifyUserEmailFailure(message);
|
verifyUserEmailFailure(message);
|
||||||
notify({ message });
|
notify({ message });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
notify({
|
notify({
|
||||||
message: 'Invalid Verification URI',
|
message: __('Invalid Verification URI'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -195,16 +193,16 @@ class SplashScreen extends React.PureComponent {
|
||||||
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(password => {
|
NativeModules.UtilityModule.getSecureValue(Constants.KEY_WALLET_PASSWORD).then(password => {
|
||||||
if ((secureWalletStatus.is_encrypted && !secureWalletStatus.is_locked) || secureWalletStatus.is_locked) {
|
if ((secureWalletStatus.is_encrypted && !secureWalletStatus.is_locked) || secureWalletStatus.is_locked) {
|
||||||
this.setState({
|
this.setState({
|
||||||
message: 'Unlocking account',
|
message: __('Unlocking account'),
|
||||||
details: 'Decrypting wallet',
|
details: __('Decrypting wallet'),
|
||||||
});
|
});
|
||||||
|
|
||||||
// unlock the wallet and then finish the splash screen
|
// unlock the wallet and then finish the splash screen
|
||||||
Lbry.wallet_unlock({ password: password || '' }).then(unlocked => {
|
Lbry.wallet_unlock({ password: password || '' }).then(unlocked => {
|
||||||
if (unlocked) {
|
if (unlocked) {
|
||||||
this.setState({
|
this.setState({
|
||||||
message: testingNetwork,
|
message: __('Testing network'),
|
||||||
details: waitingForResolution,
|
details: __('Waiting for name resolution'),
|
||||||
});
|
});
|
||||||
this.finishSplashScreen();
|
this.finishSplashScreen();
|
||||||
} else {
|
} else {
|
||||||
|
@ -213,8 +211,8 @@ class SplashScreen extends React.PureComponent {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
message: testingNetwork,
|
message: __('Testing network'),
|
||||||
details: waitingForResolution,
|
details: __('Waiting for name resolution'),
|
||||||
});
|
});
|
||||||
this.finishSplashScreen();
|
this.finishSplashScreen();
|
||||||
}
|
}
|
||||||
|
@ -239,20 +237,20 @@ class SplashScreen extends React.PureComponent {
|
||||||
if (blockchainHeaders && blockchainHeaders.downloading_headers) {
|
if (blockchainHeaders && blockchainHeaders.downloading_headers) {
|
||||||
const downloadProgress = blockchainHeaders.download_progress ? blockchainHeaders.download_progress : 0;
|
const downloadProgress = blockchainHeaders.download_progress ? blockchainHeaders.download_progress : 0;
|
||||||
this.setState({
|
this.setState({
|
||||||
message: 'Blockchain Sync',
|
message: __('Blockchain Sync'),
|
||||||
details: `Catching up with the blockchain (${downloadProgress}%)`,
|
details: `Catching up with the blockchain (${downloadProgress}%)`, // TODO: i18n tokenization
|
||||||
});
|
});
|
||||||
} else if (walletStatus && walletStatus.blocks_behind > 0) {
|
} else if (walletStatus && walletStatus.blocks_behind > 0) {
|
||||||
const behind = walletStatus.blocks_behind;
|
const behind = walletStatus.blocks_behind;
|
||||||
const behindText = behind + ' block' + (behind === 1 ? '' : 's') + ' behind';
|
const behindText = behind + ' block' + (behind === 1 ? '' : 's') + ' behind'; // TODO: i18n tokenization
|
||||||
this.setState({
|
this.setState({
|
||||||
message: 'Blockchain Sync',
|
message: __('Blockchain Sync'),
|
||||||
details: behindText,
|
details: behindText,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
message: 'Network Loading',
|
message: __('Network Loading'),
|
||||||
details: 'Initializing LBRY service',
|
details: __('Initializing LBRY service'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,9 +290,10 @@ class SplashScreen extends React.PureComponent {
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
this.setState({
|
this.setState({
|
||||||
isLagging: true,
|
isLagging: true,
|
||||||
message: 'Connection Failure',
|
message: __('Connection Failure'),
|
||||||
details:
|
details: __(
|
||||||
'We could not establish a connection to the daemon. Your data connection may be preventing LBRY from connecting. Contact hello@lbry.com if you think this is a software bug.',
|
'We could not establish a connection to the SDK. Your data connection may be preventing LBRY from connecting. Contact hello@lbry.com if you think this is a software bug.'
|
||||||
|
),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -315,8 +314,8 @@ class SplashScreen extends React.PureComponent {
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
accountUnlockFailed: false,
|
accountUnlockFailed: false,
|
||||||
message: testingNetwork,
|
message: __('Testing network'),
|
||||||
details: waitingForResolution,
|
details: __('Waiting for name resolution'),
|
||||||
},
|
},
|
||||||
() => this.finishSplashScreen()
|
() => this.finishSplashScreen()
|
||||||
);
|
);
|
||||||
|
@ -328,19 +327,22 @@ class SplashScreen extends React.PureComponent {
|
||||||
if (accountUnlockFailed) {
|
if (accountUnlockFailed) {
|
||||||
return (
|
return (
|
||||||
<View style={splashStyle.container}>
|
<View style={splashStyle.container}>
|
||||||
<Text style={splashStyle.errorTitle}>Oops! Something went wrong.</Text>
|
<Text style={splashStyle.errorTitle}>{__('Oops! Something went wrong.')}</Text>
|
||||||
<Text style={splashStyle.paragraph}>
|
<Text style={splashStyle.paragraph}>
|
||||||
Your wallet failed to unlock, which means you may not be able to play any videos or access your funds.
|
{__(
|
||||||
|
'Your wallet failed to unlock, which means you may not be able to play any videos or access your funds.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={splashStyle.paragraph}>
|
<Text style={splashStyle.paragraph}>
|
||||||
You can try to fix this by tapping Stop on the LBRY service notification and starting the app again. If the
|
{__(
|
||||||
problem continues, you may have to reinstall the app and restore your account.
|
'You can try to fix this by tapping Stop on the LBRY service notification and starting the app again. If the problem continues, you may have to reinstall the app and restore your account.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
style={splashStyle.continueButton}
|
style={splashStyle.continueButton}
|
||||||
theme={'light'}
|
theme={'light'}
|
||||||
text={'Continue anyway'}
|
text={__('Continue anyway')}
|
||||||
onPress={this.handleContinueAnywayPressed}
|
onPress={this.handleContinueAnywayPressed}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -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';
|
||||||
|
@ -149,7 +149,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
<View style={subscriptionsStyle.container}>
|
<View style={subscriptionsStyle.container}>
|
||||||
<UriBar navigation={navigation} belowOverlay={this.state.showSortPicker} />
|
<UriBar navigation={navigation} belowOverlay={this.state.showSortPicker} />
|
||||||
<View style={subscriptionsStyle.titleRow}>
|
<View style={subscriptionsStyle.titleRow}>
|
||||||
<Text style={subscriptionsStyle.pageTitle}>Channels you follow</Text>
|
<Text style={subscriptionsStyle.pageTitle}>{__('Channels you follow')}</Text>
|
||||||
</View>
|
</View>
|
||||||
{!this.state.showingSuggestedSubs && hasSubscriptions && (
|
{!this.state.showingSuggestedSubs && hasSubscriptions && (
|
||||||
<View style={subscriptionsStyle.pickerRow}>
|
<View style={subscriptionsStyle.pickerRow}>
|
||||||
|
@ -158,7 +158,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
style={subscriptionsStyle.tagSortBy}
|
style={subscriptionsStyle.tagSortBy}
|
||||||
onPress={() => this.setState({ showSortPicker: true })}
|
onPress={() => this.setState({ showSortPicker: true })}
|
||||||
>
|
>
|
||||||
<Text style={subscriptionsStyle.tagSortText}>{currentSortByItem.label.split(' ')[0]}</Text>
|
<Text style={subscriptionsStyle.tagSortText}>{__(currentSortByItem.label.split(' ')[0])}</Text>
|
||||||
<Icon style={subscriptionsStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={subscriptionsStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
style={subscriptionsStyle.tagSortBy}
|
style={subscriptionsStyle.tagSortBy}
|
||||||
onPress={() => this.setState({ showTimePicker: true })}
|
onPress={() => this.setState({ showTimePicker: true })}
|
||||||
>
|
>
|
||||||
<Text style={subscriptionsStyle.tagSortText}>{timeItem.label}</Text>
|
<Text style={subscriptionsStyle.tagSortText}>{__(timeItem.label)}</Text>
|
||||||
<Icon style={subscriptionsStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={subscriptionsStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
@ -175,7 +175,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
style={subscriptionsStyle.suggestedLink}
|
style={subscriptionsStyle.suggestedLink}
|
||||||
text={'Suggested'}
|
text={__('Suggested')}
|
||||||
onPress={() => this.setState({ showModalSuggestedSubs: true })}
|
onPress={() => this.setState({ showModalSuggestedSubs: true })}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
@ -207,7 +207,9 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
<View style={subscriptionsStyle.suggestedSubsContainer}>
|
<View style={subscriptionsStyle.suggestedSubsContainer}>
|
||||||
{!hasSubscriptions && (
|
{!hasSubscriptions && (
|
||||||
<View style={subscriptionsStyle.infoArea}>
|
<View style={subscriptionsStyle.infoArea}>
|
||||||
<Text style={subscriptionsStyle.infoText}>You are not subscribed to any channels at the moment.</Text>
|
<Text style={subscriptionsStyle.infoText}>
|
||||||
|
{__('You are not subscribed to any channels at the moment.')}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -218,7 +220,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
</Text>
|
</Text>
|
||||||
<Button
|
<Button
|
||||||
style={subscriptionsStyle.button}
|
style={subscriptionsStyle.button}
|
||||||
text={'View my subscriptions'}
|
text={__('View my subscriptions')}
|
||||||
onPress={() => this.setState({ showingSuggestedSubs: false })}
|
onPress={() => this.setState({ showingSuggestedSubs: false })}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -105,12 +105,12 @@ class TagPage extends React.PureComponent {
|
||||||
<View style={discoverStyle.pickerRow}>
|
<View style={discoverStyle.pickerRow}>
|
||||||
<View style={discoverStyle.leftPickerRow}>
|
<View style={discoverStyle.leftPickerRow}>
|
||||||
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
<TouchableOpacity style={discoverStyle.tagSortBy} onPress={() => this.setState({ showSortPicker: true })}>
|
||||||
<Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
|
<Text style={discoverStyle.tagSortText}>{__(sortByItem.label.split(' ')[0])}</Text>
|
||||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
{Constants.SORT_BY_TOP === sortByItem.name && (
|
{Constants.SORT_BY_TOP === sortByItem.name && (
|
||||||
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
||||||
<Text style={discoverStyle.tagSortText}>{timeItem.label}</Text>
|
<Text style={discoverStyle.tagSortText}>{__(timeItem.label)}</Text>
|
||||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
@ -118,7 +118,7 @@ class TagPage extends React.PureComponent {
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
style={discoverStyle.customizeLink}
|
style={discoverStyle.customizeLink}
|
||||||
text={this.isFollowingTag(tag) ? 'Unfollow' : 'Follow'}
|
text={this.isFollowingTag(tag) ? __('Unfollow') : __('Follow')}
|
||||||
onPress={this.handleFollowTagToggle}
|
onPress={this.handleFollowTagToggle}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
|
@ -51,10 +51,12 @@ class TransactionHistoryPage extends React.PureComponent {
|
||||||
{fetchingTransactions && (
|
{fetchingTransactions && (
|
||||||
<View style={walletStyle.loadingContainer}>
|
<View style={walletStyle.loadingContainer}>
|
||||||
<ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
|
<ActivityIndicator size={'small'} color={Colors.NextLbryGreen} />
|
||||||
<Text style={walletStyle.loadingText}>Loading transactions...</Text>
|
<Text style={walletStyle.loadingText}>{__('Loading transactions...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{!fetchingTransactions && transactions.length === 0 && <EmptyStateView message={'No transactions to list.'} />}
|
{!fetchingTransactions && transactions.length === 0 && (
|
||||||
|
<EmptyStateView message={__('No transactions to list.')} />
|
||||||
|
)}
|
||||||
<ScrollView style={walletStyle.transactionHistoryScroll}>
|
<ScrollView style={walletStyle.transactionHistoryScroll}>
|
||||||
<View style={walletStyle.historyList}>
|
<View style={walletStyle.historyList}>
|
||||||
{!fetchingTransactions && transactions && transactions.length > 0 && (
|
{!fetchingTransactions && transactions && transactions.length > 0 && (
|
||||||
|
|
|
@ -92,7 +92,7 @@ class TrendingPage extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<View style={discoverStyle.listHeader}>
|
<View style={discoverStyle.listHeader}>
|
||||||
<View style={discoverStyle.titleRow}>
|
<View style={discoverStyle.titleRow}>
|
||||||
<Text style={discoverStyle.pageTitle}>All content</Text>
|
<Text style={discoverStyle.pageTitle}>{__('All Content')}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={discoverStyle.pickerRow}>
|
<View style={discoverStyle.pickerRow}>
|
||||||
<View style={discoverStyle.leftPickerRow}>
|
<View style={discoverStyle.leftPickerRow}>
|
||||||
|
@ -100,24 +100,24 @@ class TrendingPage extends React.PureComponent {
|
||||||
style={discoverStyle.allTagSortBy}
|
style={discoverStyle.allTagSortBy}
|
||||||
onPress={() => this.setState({ showSortPicker: true })}
|
onPress={() => this.setState({ showSortPicker: true })}
|
||||||
>
|
>
|
||||||
<Text style={discoverStyle.tagSortText}>{sortByItem.label.split(' ')[0]}</Text>
|
<Text style={discoverStyle.tagSortText}>{__(sortByItem.label.split(' ')[0])}</Text>
|
||||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<Text style={discoverStyle.pickerLabel}>for</Text>
|
<Text style={discoverStyle.pickerLabel}>{__('for')}</Text>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={discoverStyle.allTagSortBy}
|
style={discoverStyle.allTagSortBy}
|
||||||
onPress={() => this.setState({ showTrendingForPicker: true })}
|
onPress={() => this.setState({ showTrendingForPicker: true })}
|
||||||
>
|
>
|
||||||
<Text style={discoverStyle.tagSortText}>{currentTrendingForItem.label.split(' ')[0]}</Text>
|
<Text style={discoverStyle.tagSortText}>{__(currentTrendingForItem.label.split(' ')[0])}</Text>
|
||||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
{sortByTop && <Text style={discoverStyle.pickerLabel}>from</Text>}
|
{sortByTop && <Text style={discoverStyle.pickerLabel}>{__('from')}</Text>}
|
||||||
|
|
||||||
{sortByTop && (
|
{sortByTop && (
|
||||||
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
<TouchableOpacity style={discoverStyle.tagTime} onPress={() => this.setState({ showTimePicker: true })}>
|
||||||
<Text style={discoverStyle.tagSortText}>{timeItem.label}</Text>
|
<Text style={discoverStyle.tagSortText}>{__(timeItem.label)}</Text>
|
||||||
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
<Icon style={discoverStyle.tagSortIcon} name={'sort-down'} size={14} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)}
|
)}
|
||||||
|
@ -126,7 +126,7 @@ class TrendingPage extends React.PureComponent {
|
||||||
{TRENDING_FOR_ITEMS[1].name === currentTrendingForItem.name && (
|
{TRENDING_FOR_ITEMS[1].name === currentTrendingForItem.name && (
|
||||||
<Link
|
<Link
|
||||||
style={discoverStyle.customizeLink}
|
style={discoverStyle.customizeLink}
|
||||||
text={'Customize'}
|
text={__('Customize')}
|
||||||
onPress={() => this.setState({ showModalTagSelector: true })}
|
onPress={() => this.setState({ showModalTagSelector: true })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -170,7 +170,7 @@ class TrendingPage extends React.PureComponent {
|
||||||
)}
|
)}
|
||||||
{showTrendingForPicker && (
|
{showTrendingForPicker && (
|
||||||
<ModalPicker
|
<ModalPicker
|
||||||
title={'Filter for'}
|
title={__('Filter for')}
|
||||||
onOverlayPress={() => this.setState({ showTrendingForPicker: false })}
|
onOverlayPress={() => this.setState({ showTrendingForPicker: false })}
|
||||||
onItemSelected={this.handleTrendingForItemSelected}
|
onItemSelected={this.handleTrendingForItemSelected}
|
||||||
selectedItem={currentTrendingForItem}
|
selectedItem={currentTrendingForItem}
|
||||||
|
|
|
@ -49,7 +49,7 @@ class EmailVerifyPage extends React.PureComponent {
|
||||||
if (setEmailVerificationPhase) {
|
if (setEmailVerificationPhase) {
|
||||||
setEmailVerificationPhase(true);
|
setEmailVerificationPhase(true);
|
||||||
}
|
}
|
||||||
// notify({ message: 'Please follow the instructions in the email sent to your address to continue.' });
|
// notify({ message: __('Please follow the instructions in the email sent to your address to continue.') });
|
||||||
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
|
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ class EmailVerifyPage extends React.PureComponent {
|
||||||
const { email } = this.state;
|
const { email } = this.state;
|
||||||
if (!email || email.trim().length === 0 || email.indexOf('@') === -1) {
|
if (!email || email.trim().length === 0 || email.indexOf('@') === -1) {
|
||||||
return notify({
|
return notify({
|
||||||
message: 'Please provide a valid email address to continue.',
|
message: __('Please provide a valid email address to continue.'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class EmailVerifyPage extends React.PureComponent {
|
||||||
// resend verification email if there was one previously set (and it wasn't changed)
|
// resend verification email if there was one previously set (and it wasn't changed)
|
||||||
resendVerificationEmail(this.state.email);
|
resendVerificationEmail(this.state.email);
|
||||||
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
|
AsyncStorage.setItem(Constants.KEY_EMAIL_VERIFY_PENDING, 'true');
|
||||||
notify({ message: 'Please follow the instructions in the email sent to your address to continue.' });
|
notify({ message: __('Please follow the instructions in the email sent to your address to continue.') });
|
||||||
};
|
};
|
||||||
|
|
||||||
onEditPressed = () => {
|
onEditPressed = () => {
|
||||||
|
@ -110,7 +110,7 @@ class EmailVerifyPage extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<View style={firstRunStyle.container}>
|
<View style={firstRunStyle.container}>
|
||||||
<Text style={rewardStyle.verificationTitle}>
|
<Text style={rewardStyle.verificationTitle}>
|
||||||
{Constants.PHASE_COLLECTION === this.state.phase ? 'Email' : 'Verify Email'}
|
{Constants.PHASE_COLLECTION === this.state.phase ? __('Email') : __('Verify Email')}
|
||||||
</Text>
|
</Text>
|
||||||
{Constants.PHASE_COLLECTION === this.state.phase && (
|
{Constants.PHASE_COLLECTION === this.state.phase && (
|
||||||
<View>
|
<View>
|
||||||
|
@ -138,7 +138,7 @@ class EmailVerifyPage extends React.PureComponent {
|
||||||
<Button
|
<Button
|
||||||
style={rewardStyle.verificationButton}
|
style={rewardStyle.verificationButton}
|
||||||
theme={'light'}
|
theme={'light'}
|
||||||
text={'Send verification email'}
|
text={__('Send verification email')}
|
||||||
onPress={this.onSendVerificationPressed}
|
onPress={this.onSendVerificationPressed}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -162,10 +162,10 @@ class EmailVerifyPage extends React.PureComponent {
|
||||||
<Button
|
<Button
|
||||||
style={rewardStyle.verificationButton}
|
style={rewardStyle.verificationButton}
|
||||||
theme={'light'}
|
theme={'light'}
|
||||||
text={'Resend'}
|
text={__('Resend')}
|
||||||
onPress={this.onResendPressed}
|
onPress={this.onResendPressed}
|
||||||
/>
|
/>
|
||||||
<Link style={rewardStyle.verificationLink} text={'Edit'} onPress={this.onEditPressed} />
|
<Link style={rewardStyle.verificationLink} text={__('Edit')} onPress={this.onEditPressed} />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants';
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import firstRunStyle from 'styles/firstRun';
|
import firstRunStyle from 'styles/firstRun';
|
||||||
import rewardStyle from 'styles/reward';
|
import rewardStyle from 'styles/reward';
|
||||||
|
|
||||||
|
@ -22,8 +22,9 @@ class ManualVerifyPage extends React.PureComponent {
|
||||||
<View style={firstRunStyle.container}>
|
<View style={firstRunStyle.container}>
|
||||||
<Text style={rewardStyle.verificationTitle}>Manual Reward Verification</Text>
|
<Text style={rewardStyle.verificationTitle}>Manual Reward Verification</Text>
|
||||||
<Text style={firstRunStyle.spacedParagraph}>
|
<Text style={firstRunStyle.spacedParagraph}>
|
||||||
This account must undergo review before you can participate in the rewards program. This can take anywhere
|
{__(
|
||||||
from several minutes to several days.
|
'This account must undergo review before you can participate in the rewards program. This can take anywhere from several minutes to several days.'
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={firstRunStyle.spacedParagraph}>
|
<Text style={firstRunStyle.spacedParagraph}>
|
||||||
If you continue to see this message, please request to be verified on the{' '}
|
If you continue to see this message, please request to be verified on the{' '}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants';
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import CountryPicker from 'react-native-country-picker-modal';
|
import CountryPicker from 'react-native-country-picker-modal';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
|
@ -149,10 +149,10 @@ class PhoneVerifyPage extends React.PureComponent {
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<View style={rewardStyle.phoneVerificationContainer}>
|
<View style={rewardStyle.phoneVerificationContainer}>
|
||||||
{this.state.phase == Constants.PHASE_COLLECTION && (
|
{this.state.phase === Constants.PHASE_COLLECTION && (
|
||||||
<View>
|
<View>
|
||||||
<Text style={[rewardStyle.bottomMarginMedium, firstRunStyle.paragraph]}>
|
<Text style={[rewardStyle.bottomMarginMedium, firstRunStyle.paragraph]}>
|
||||||
Please provide a phone number to prevent fraud.
|
{__('Please provide a phone number to prevent fraud.')}
|
||||||
</Text>
|
</Text>
|
||||||
<PhoneInput
|
<PhoneInput
|
||||||
ref={ref => {
|
ref={ref => {
|
||||||
|
@ -237,9 +237,9 @@ class PhoneVerifyPage extends React.PureComponent {
|
||||||
this.picker = picker;
|
this.picker = picker;
|
||||||
}}
|
}}
|
||||||
cca2={this.state.cca2}
|
cca2={this.state.cca2}
|
||||||
filterable={true}
|
filterable
|
||||||
onChange={value => this.selectCountry(value)}
|
onChange={value => this.selectCountry(value)}
|
||||||
showCallingCode={true}
|
showCallingCode
|
||||||
translation="eng"
|
translation="eng"
|
||||||
>
|
>
|
||||||
<View />
|
<View />
|
||||||
|
|
|
@ -67,7 +67,7 @@ class SyncVerifyPage extends React.PureComponent {
|
||||||
|
|
||||||
if (this.state.syncApplyStarted && !syncApplyIsPending) {
|
if (this.state.syncApplyStarted && !syncApplyIsPending) {
|
||||||
if (syncApplyErrorMessage && syncApplyErrorMessage.trim().length > 0) {
|
if (syncApplyErrorMessage && syncApplyErrorMessage.trim().length > 0) {
|
||||||
notify({ message: syncApplyErrorMessage, isError: true });
|
notify({ message: __(syncApplyErrorMessage), isError: true });
|
||||||
this.setState({ syncApplyStarted: false, autoLoginFlow: false });
|
this.setState({ syncApplyStarted: false, autoLoginFlow: false });
|
||||||
} else {
|
} else {
|
||||||
// password successfully verified
|
// password successfully verified
|
||||||
|
@ -111,7 +111,7 @@ class SyncVerifyPage extends React.PureComponent {
|
||||||
navigation.goBack();
|
navigation.goBack();
|
||||||
} else {
|
} else {
|
||||||
if (notifyUnlockFailed) {
|
if (notifyUnlockFailed) {
|
||||||
notify({ message: 'The wallet could not be unlocked at this time. Please restart the app.' });
|
notify({ message: __('The wallet could not be unlocked at this time. Please restart the app.') });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -136,11 +136,11 @@ class SyncVerifyPage extends React.PureComponent {
|
||||||
let paragraph;
|
let paragraph;
|
||||||
if (!hasSyncedWallet) {
|
if (!hasSyncedWallet) {
|
||||||
paragraph = (
|
paragraph = (
|
||||||
<Text style={firstRunStyle.paragraph}>Please enter a password to secure your account and wallet.</Text>
|
<Text style={firstRunStyle.paragraph}>{__('Please enter a password to secure your account and wallet.')}</Text>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
paragraph = (
|
paragraph = (
|
||||||
<Text style={firstRunStyle.paragraph}>Please enter the password you used to secure your wallet.</Text>
|
<Text style={firstRunStyle.paragraph}>{__('Please enter the password you used to secure your wallet.')}</Text>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ class SyncVerifyPage extends React.PureComponent {
|
||||||
content = (
|
content = (
|
||||||
<View style={firstRunStyle.centered}>
|
<View style={firstRunStyle.centered}>
|
||||||
<ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} />
|
<ActivityIndicator size="large" color={Colors.White} style={firstRunStyle.waiting} />
|
||||||
<Text style={firstRunStyle.paragraph}>Retrieving your account information...</Text>
|
<Text style={firstRunStyle.paragraph}>{__('Retrieving your account information...')}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
} else if (this.state.autoLoginFlow && (syncApplyIsPending || this.state.syncApplyCompleted)) {
|
} else if (this.state.autoLoginFlow && (syncApplyIsPending || this.state.syncApplyCompleted)) {
|
||||||
|
@ -164,7 +164,7 @@ class SyncVerifyPage extends React.PureComponent {
|
||||||
} else if (hasSyncedWallet && this.state.autoLoginAttempted) {
|
} else if (hasSyncedWallet && this.state.autoLoginAttempted) {
|
||||||
content = (
|
content = (
|
||||||
<View>
|
<View>
|
||||||
<Text style={rewardStyle.verificationTitle}>Wallet Sync</Text>
|
<Text style={rewardStyle.verificationTitle}>{__('Wallet Sync')}</Text>
|
||||||
{paragraph}
|
{paragraph}
|
||||||
<View style={firstRunStyle.passwordInputContainer}>
|
<View style={firstRunStyle.passwordInputContainer}>
|
||||||
<TextInput
|
<TextInput
|
||||||
|
@ -198,8 +198,8 @@ class SyncVerifyPage extends React.PureComponent {
|
||||||
<View style={firstRunStyle.passwordWarning}>
|
<View style={firstRunStyle.passwordWarning}>
|
||||||
<Text style={firstRunStyle.passwordWarningText}>
|
<Text style={firstRunStyle.passwordWarningText}>
|
||||||
{hasSyncedWallet
|
{hasSyncedWallet
|
||||||
? 'If you did not provide a password, please press Use LBRY to continue.'
|
? __('If you did not provide a password, please press Use LBRY to continue.')
|
||||||
: 'You can proceed without a password, but this is not recommended.'}
|
: __('You can proceed without a password, but this is not recommended.')}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
@ -214,7 +214,7 @@ class SyncVerifyPage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<Text style={firstRunStyle.infoParagraph}>
|
<Text style={firstRunStyle.infoParagraph}>
|
||||||
Note: for wallet security purposes, LBRY is unable to reset your password.
|
{__('Note: for wallet security purposes, LBRY is unable to reset your password.')}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<View style={rewardStyle.buttonContainer}>
|
<View style={rewardStyle.buttonContainer}>
|
||||||
|
@ -222,7 +222,7 @@ class SyncVerifyPage extends React.PureComponent {
|
||||||
<Button
|
<Button
|
||||||
style={rewardStyle.verificationButton}
|
style={rewardStyle.verificationButton}
|
||||||
theme={'light'}
|
theme={'light'}
|
||||||
text={signInFlow ? 'Use LBRY' : 'Enable sync'}
|
text={signInFlow ? __('Use LBRY') : __('Enable sync')}
|
||||||
onPress={this.onEnableSyncPressed}
|
onPress={this.onEnableSyncPressed}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -11,6 +11,10 @@ const channelSelectorStyle = StyleSheet.create({
|
||||||
height: 52,
|
height: 52,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
},
|
},
|
||||||
|
channelPickerItem: {
|
||||||
|
fontFamily: 'Inter-UI-Regular',
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
bidRow: {
|
bidRow: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
|
|
@ -28,6 +28,14 @@ const settingsStyle = StyleSheet.create({
|
||||||
width: '25%',
|
width: '25%',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
|
pickerText: {
|
||||||
|
width: '40%',
|
||||||
|
},
|
||||||
|
pickerContainer: {
|
||||||
|
width: '60%',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
},
|
||||||
label: {
|
label: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontFamily: 'Inter-UI-Regular',
|
fontFamily: 'Inter-UI-Regular',
|
||||||
|
@ -54,6 +62,20 @@ const settingsStyle = StyleSheet.create({
|
||||||
sectionDivider: {
|
sectionDivider: {
|
||||||
marginTop: 24,
|
marginTop: 24,
|
||||||
},
|
},
|
||||||
|
languagePicker: {
|
||||||
|
width: '85%',
|
||||||
|
},
|
||||||
|
languagePickerItem: {
|
||||||
|
fontFamily: 'Inter-UI-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
pickerRow: {
|
||||||
|
marginBottom: 24,
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default settingsStyle;
|
export default settingsStyle;
|
||||||
|
|
Loading…
Reference in a new issue