fix publishing bugs
This commit is contained in:
parent
ffccc124d0
commit
fc412e4282
11 changed files with 148 additions and 55 deletions
|
@ -12,7 +12,7 @@
|
|||
"base-64": "^0.1.0",
|
||||
"@expo/vector-icons": "^8.1.0",
|
||||
"gfycat-style-urls": "^1.0.3",
|
||||
"lbry-redux": "lbryio/lbry-redux#4e5e51b99b730cc834747edb9fd7d87d47a7d4f9",
|
||||
"lbry-redux": "lbryio/lbry-redux#1a8ce5ee1397e101f2a015f1c3a9050c15ca6157",
|
||||
"lbryinc": "lbryio/lbryinc#430c280789a5031c2e49ca5bf8a7d90ccccc4cdb",
|
||||
"lodash": ">=4.17.11",
|
||||
"merge": ">=1.2.1",
|
||||
|
@ -20,7 +20,7 @@
|
|||
"react": "16.8.6",
|
||||
"react-native": "0.59.10",
|
||||
"@react-native-community/async-storage": "^1.5.1",
|
||||
"react-native-camera": "^2.11.0",
|
||||
"react-native-camera": "^2.11.1",
|
||||
"react-native-country-picker-modal": "^0.6.2",
|
||||
"react-native-document-picker": "^2.3.0",
|
||||
"react-native-exception-handler": "2.9.0",
|
||||
|
@ -31,7 +31,7 @@
|
|||
"react-native-password-strength-meter": "^0.0.2",
|
||||
"react-native-phone-input": "lbryio/react-native-phone-input",
|
||||
"react-native-super-grid": "^3.0.4",
|
||||
"react-native-vector-icons": "^6.4.2",
|
||||
"react-native-vector-icons": "^6.6.0",
|
||||
"react-native-video": "lbryio/react-native-video#exoplayer-lbry-android",
|
||||
"react-navigation": "^3.11.0",
|
||||
"react-navigation-redux-helpers": "^3.0.2",
|
||||
|
|
|
@ -41,7 +41,9 @@ export default class ChannelSelector extends React.PureComponent {
|
|||
this.setState({ showCreateChannel: true });
|
||||
} else {
|
||||
this.handleCreateCancel();
|
||||
this.handleChannelChange(Constants.ITEM_ANONYMOUS === itemValue ? CLAIM_VALUES.CHANNEL_ANONYMOUS : itemValue);
|
||||
this.handleChannelChange(
|
||||
Constants.ITEM_ANONYMOUS === itemValue.name ? { name: CLAIM_VALUES.CHANNEL_ANONYMOUS } : itemValue
|
||||
);
|
||||
}
|
||||
this.setState({ currentSelectedValue: itemValue });
|
||||
};
|
||||
|
@ -49,18 +51,18 @@ export default class ChannelSelector extends React.PureComponent {
|
|||
handleChannelChange = value => {
|
||||
const { onChannelChange } = this.props;
|
||||
const { newChannelBid } = this.state;
|
||||
const channel = value;
|
||||
const channel = value.name;
|
||||
|
||||
if (channel === CLAIM_VALUES.CHANNEL_NEW) {
|
||||
this.setState({ addingChannel: true });
|
||||
if (onChannelChange) {
|
||||
onChannelChange(channel);
|
||||
onChannelChange(value);
|
||||
}
|
||||
this.handleNewChannelBidChange(newChannelBid);
|
||||
} else {
|
||||
this.setState({ addingChannel: false });
|
||||
if (onChannelChange) {
|
||||
onChannelChange(channel);
|
||||
onChannelChange(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -68,14 +70,22 @@ export default class ChannelSelector extends React.PureComponent {
|
|||
handleNewChannelNameChange = value => {
|
||||
const { notify } = this.props;
|
||||
|
||||
let newChannelName = value;
|
||||
let newChannelName = value,
|
||||
newChannelNameError = '';
|
||||
|
||||
if (newChannelName.startsWith('@')) {
|
||||
newChannelName = newChannelName.slice(1);
|
||||
}
|
||||
|
||||
if (newChannelName.trim().length > 0 && !isURIValid(newChannelName)) {
|
||||
newChannelNameError = 'Your channel name contains invalid characters.';
|
||||
} else if (this.channelExists(newChannelName)) {
|
||||
newChannelNameError = 'You have already created a channel with the same name.';
|
||||
}
|
||||
|
||||
this.setState({
|
||||
newChannelName,
|
||||
newChannelNameError,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -167,6 +177,7 @@ export default class ChannelSelector extends React.PureComponent {
|
|||
const pickerItems = [{ name: Constants.ITEM_ANONYMOUS }, { name: Constants.ITEM_CREATE_A_CHANNEL }].concat(
|
||||
channels
|
||||
);
|
||||
|
||||
const {
|
||||
newChannelName,
|
||||
newChannelNameError,
|
||||
|
@ -175,6 +186,7 @@ export default class ChannelSelector extends React.PureComponent {
|
|||
creatingChannel,
|
||||
createChannelError,
|
||||
addingChannel,
|
||||
showCreateChannel,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
|
@ -186,11 +198,11 @@ export default class ChannelSelector extends React.PureComponent {
|
|||
onValueChange={this.handlePickerValueChange}
|
||||
>
|
||||
{pickerItems.map(item => (
|
||||
<Picker.Item label={item.name} value={item.name} key={item.name} />
|
||||
<Picker.Item label={item.name} value={item} key={item.name} />
|
||||
))}
|
||||
</Picker>
|
||||
|
||||
{this.state.showCreateChannel && (
|
||||
{showCreateChannel && (
|
||||
<View style={channelSelectorStyle.createChannelContainer}>
|
||||
<View style={channelSelectorStyle.channelInputContainer}>
|
||||
<Text style={channelSelectorStyle.channelAt}>@</Text>
|
||||
|
@ -203,11 +215,14 @@ export default class ChannelSelector extends React.PureComponent {
|
|||
underlineColorAndroid={Colors.NextLbryGreen}
|
||||
/>
|
||||
</View>
|
||||
{newChannelNameError.length > 0 && (
|
||||
<Text style={channelSelectorStyle.inlineError}>{newChannelNameError}</Text>
|
||||
)}
|
||||
<View style={channelSelectorStyle.bidRow}>
|
||||
<Text style={channelSelectorStyle.label}>Deposit</Text>
|
||||
<TextInput
|
||||
style={channelSelectorStyle.bidAmountInput}
|
||||
value={String(this.state.newChannelBid)}
|
||||
value={String(newChannelBid)}
|
||||
onChangeText={this.handleNewChannelBidChange}
|
||||
placeholder={'0.00'}
|
||||
keyboardType={'number-pad'}
|
||||
|
@ -226,7 +241,7 @@ export default class ChannelSelector extends React.PureComponent {
|
|||
<Link style={channelSelectorStyle.cancelLink} text="Cancel" onPress={this.handleCreateCancel} />
|
||||
<Button
|
||||
style={channelSelectorStyle.createButton}
|
||||
disabled={!(this.state.newChannelName.trim().length > 0 && this.state.newChannelBid > 0)}
|
||||
disabled={!(newChannelName.trim().length > 0 && newChannelBid > 0)}
|
||||
text="Create"
|
||||
onPress={this.handleCreateChannelClick}
|
||||
/>
|
||||
|
|
|
@ -251,11 +251,17 @@ class DiscoverPage extends React.PureComponent {
|
|||
</View>
|
||||
);
|
||||
|
||||
sectionListFooter = () => (
|
||||
sectionListFooter = () => {
|
||||
const { remainingTags } = this.state;
|
||||
if (remainingTags.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={discoverStyle.footer}>
|
||||
<Text style={discoverStyle.footerTitle}>More tags you follow</Text>
|
||||
<View style={discoverStyle.footerTags}>
|
||||
{this.state.remainingTags.map(tag => (
|
||||
{remainingTags.map(tag => (
|
||||
<Text
|
||||
key={tag}
|
||||
style={[discoverStyle.categoryName, discoverStyle.footerTag]}
|
||||
|
@ -267,6 +273,7 @@ class DiscoverPage extends React.PureComponent {
|
|||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
renderSectionListItem = ({ item, index, section }) => (
|
||||
<ClaimList
|
||||
|
|
|
@ -1,23 +1,28 @@
|
|||
import { connect } from 'react-redux';
|
||||
import {
|
||||
doFileList,
|
||||
doFetchClaimListMine,
|
||||
selectFileInfosDownloaded,
|
||||
selectDownloadedUris,
|
||||
selectMyClaimsWithoutChannels,
|
||||
selectIsFetchingClaimListMine,
|
||||
selectIsFetchingFileList,
|
||||
} from 'lbry-redux';
|
||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||
import { selectCurrentRoute } from 'redux/selectors/drawer';
|
||||
import Constants from 'constants';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import DownloadsPage from './view';
|
||||
|
||||
const select = state => ({
|
||||
claims: selectMyClaimsWithoutChannels(state),
|
||||
currentRoute: selectCurrentRoute(state),
|
||||
fileInfos: selectFileInfosDownloaded(state),
|
||||
fetching: selectIsFetchingFileList(state),
|
||||
downloadedUris: selectDownloadedUris(state),
|
||||
fetching: selectIsFetchingFileList(state) || selectIsFetchingClaimListMine(state),
|
||||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
fetchMyClaims: () => dispatch(doFetchClaimListMine()),
|
||||
fileList: () => dispatch(doFileList()),
|
||||
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_MY_LBRY)),
|
||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Lbry, buildURI } from 'lbry-redux';
|
||||
import { Lbry, buildURI, normalizeURI } from 'lbry-redux';
|
||||
import { ActivityIndicator, Button, FlatList, Text, TextInput, View, ScrollView } from 'react-native';
|
||||
import { navigateToUri, uriFromFileInfo } from 'utils/helper';
|
||||
import Colors from 'styles/colors';
|
||||
|
@ -31,9 +31,10 @@ class DownloadsPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
onComponentFocused = () => {
|
||||
const { fileList, pushDrawerStack, setPlayerVisible } = this.props;
|
||||
const { fetchMyClaims, fileList, pushDrawerStack, setPlayerVisible } = this.props;
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
fetchMyClaims();
|
||||
fileList();
|
||||
};
|
||||
|
||||
|
@ -49,9 +50,16 @@ class DownloadsPage extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
getFilteredUris = () => {
|
||||
const { claims, downloadedUris } = this.props;
|
||||
const claimUris = claims.map(claim => normalizeURI(`${claim.name}#${claim.claim_id}`));
|
||||
return downloadedUris.filter(uri => !claimUris.includes(uri));
|
||||
};
|
||||
|
||||
render() {
|
||||
const { fetching, fileInfos, navigation } = this.props;
|
||||
const hasDownloads = fileInfos && Object.values(fileInfos).length > 0;
|
||||
const { fetching, claims, downloadedUris, fileInfos, navigation } = this.props;
|
||||
const filteredUris = this.getFilteredUris();
|
||||
const hasDownloads = filteredUris && filteredUris.length > 0;
|
||||
|
||||
return (
|
||||
<View style={downloadsStyle.container}>
|
||||
|
@ -63,12 +71,12 @@ class DownloadsPage extends React.PureComponent {
|
|||
</Text>
|
||||
</View>
|
||||
)}
|
||||
{fetching && !hasDownloads && (
|
||||
{fetching && (
|
||||
<View style={downloadsStyle.busyContainer}>
|
||||
<ActivityIndicator size="large" color={Colors.NextLbryGreen} style={downloadsStyle.loading} />
|
||||
</View>
|
||||
)}
|
||||
{hasDownloads && (
|
||||
{!fetching && hasDownloads && (
|
||||
<View style={downloadsStyle.subContainer}>
|
||||
<StorageStatsCard fileInfos={fileInfos} />
|
||||
<FlatList
|
||||
|
@ -77,13 +85,13 @@ class DownloadsPage extends React.PureComponent {
|
|||
renderItem={({ item }) => (
|
||||
<FileListItem
|
||||
style={fileListStyle.item}
|
||||
uri={uriFromFileInfo(item)}
|
||||
uri={item}
|
||||
navigation={navigation}
|
||||
onPress={() => navigateToUri(navigation, uriFromFileInfo(item), { autoplay: true })}
|
||||
onPress={() => navigateToUri(navigation, item, { autoplay: true })}
|
||||
/>
|
||||
)}
|
||||
data={fileInfos}
|
||||
keyExtractor={(item, index) => item.outpoint}
|
||||
data={downloadedUris}
|
||||
keyExtractor={(item, index) => item}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
|
|
|
@ -114,6 +114,7 @@ class PublishPage extends React.PureComponent {
|
|||
price: 0,
|
||||
uri: null,
|
||||
tags: [],
|
||||
selectedChannel: null,
|
||||
uploadedThumbnailUri: null,
|
||||
|
||||
// other
|
||||
|
@ -210,16 +211,13 @@ class PublishPage extends React.PureComponent {
|
|||
return;
|
||||
}
|
||||
|
||||
const publishTags = tags.slice();
|
||||
const publishParams = {
|
||||
filePath: currentMedia.filePath,
|
||||
bid: bid || 0.1,
|
||||
tags: publishTags,
|
||||
title: title || '',
|
||||
thumbnail: thumbnail,
|
||||
thumbnail,
|
||||
description: description || '',
|
||||
language,
|
||||
nsfw: publishTags.some(tag => MATURE_TAGS.includes(tag)),
|
||||
license,
|
||||
licenseUrl: '',
|
||||
otherLicenseDescription: '',
|
||||
|
@ -227,9 +225,13 @@ class PublishPage extends React.PureComponent {
|
|||
contentIsFree: !priceSet,
|
||||
fee: { currency: 'LBC', price },
|
||||
uri: uri || undefined,
|
||||
channel_name: CLAIM_VALUES.CHANNEL_ANONYMOUS === channelName ? undefined : channelName,
|
||||
channel: CLAIM_VALUES.CHANNEL_ANONYMOUS === channelName ? null : channelName,
|
||||
isStillEditing: false,
|
||||
claim: null,
|
||||
claim: {
|
||||
value: {
|
||||
tags,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.setState({ publishStarted: true }, () => publish(publishParams));
|
||||
|
@ -241,7 +243,7 @@ class PublishPage extends React.PureComponent {
|
|||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { currentRoute, publishFormValues } = nextProps;
|
||||
const { currentRoute: prevRoute } = this.props;
|
||||
const { currentRoute: prevRoute, notify } = this.props;
|
||||
|
||||
if (Constants.DRAWER_ROUTE_PUBLISH === currentRoute && currentRoute !== prevRoute) {
|
||||
this.onComponentFocused();
|
||||
|
@ -257,6 +259,7 @@ class PublishPage extends React.PureComponent {
|
|||
this.setState({ publishStarted: false, currentPhase: Constants.PHASE_PUBLISH });
|
||||
} else if (publishFormValues.publishError) {
|
||||
// TODO: Display error if any
|
||||
notify({ message: 'Your content could not be published at this time. Please try again.' });
|
||||
}
|
||||
|
||||
if (!publishFormValues.publishing && this.state.publishStarted) {
|
||||
|
@ -279,7 +282,7 @@ class PublishPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
formatNameForTitle = title => {
|
||||
return title.replace(regexInvalidURI, '-').toLowerCase();
|
||||
return title.replace(new RegExp(regexInvalidURI.source, regexInvalidURI.flags + 'g'), '-').toLowerCase();
|
||||
};
|
||||
|
||||
showSelector() {
|
||||
|
@ -311,6 +314,7 @@ class PublishPage extends React.PureComponent {
|
|||
price: 0,
|
||||
uri: null,
|
||||
tags: [],
|
||||
selectedChannel: null,
|
||||
uploadedThumbnailUri: null,
|
||||
},
|
||||
() => {
|
||||
|
@ -442,10 +446,10 @@ class PublishPage extends React.PureComponent {
|
|||
this.setState({ uri });
|
||||
};
|
||||
|
||||
handleChannelChanged = channel => {
|
||||
this.setState({ channelName: channel });
|
||||
const uri = this.getNewUri(name, this.state.channelName);
|
||||
this.setState({ uri });
|
||||
handleChannelChange = channel => {
|
||||
const { name } = this.state;
|
||||
const uri = this.getNewUri(name, channel.name);
|
||||
this.setState({ uri, channelName: channel.name, selectedChannel: channel });
|
||||
};
|
||||
|
||||
handleAddTag = tag => {
|
||||
|
@ -787,6 +791,13 @@ class PublishPage extends React.PureComponent {
|
|||
/>
|
||||
</View>
|
||||
|
||||
<View style={publishStyle.warning}>
|
||||
<Text style={publishStyle.warningText}>
|
||||
Please ensure that you have filled everything correctly as you cannot edit published content in this
|
||||
release. This feature will be available in a future release.
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={publishStyle.actionButtons}>
|
||||
{(this.state.publishStarted || publishFormValues.publishing) && (
|
||||
<View style={publishStyle.progress}>
|
||||
|
@ -850,6 +861,7 @@ class PublishPage extends React.PureComponent {
|
|||
{this.state.canUseCamera && this.state.showCameraOverlay && (
|
||||
<View style={publishStyle.cameraOverlay}>
|
||||
<RNCamera
|
||||
captureAudio={this.state.videoRecordingMode}
|
||||
style={publishStyle.fullCamera}
|
||||
ref={ref => {
|
||||
this.camera = ref;
|
||||
|
@ -868,6 +880,11 @@ class PublishPage extends React.PureComponent {
|
|||
buttonPositive: 'OK',
|
||||
buttonNegative: 'Cancel',
|
||||
}}
|
||||
notAuthorizedView={
|
||||
<View style={publishStyle.fullCentered}>
|
||||
<Text style={publishStyle.cameraInfo}>Camera not authorized</Text>
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={[
|
||||
|
@ -876,7 +893,7 @@ class PublishPage extends React.PureComponent {
|
|||
]}
|
||||
>
|
||||
<View style={publishStyle.controlsRow}>
|
||||
<TouchableOpacity onPress={this.handleCloseCameraPressed}>
|
||||
<TouchableOpacity onPress={this.handleCloseCameraPressed} style={publishStyle.backButtonControl}>
|
||||
<Icon name="arrow-left" size={28} color={Colors.White} />
|
||||
</TouchableOpacity>
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { doCheckPendingPublishes, selectMyClaimUrisWithoutChannels, selectIsFetchingClaimListMine } from 'lbry-redux';
|
||||
import {
|
||||
doCheckPendingPublishes,
|
||||
doFetchClaimListMine,
|
||||
selectMyClaimUrisWithoutChannels,
|
||||
selectIsFetchingClaimListMine,
|
||||
} from 'lbry-redux';
|
||||
import { doPushDrawerStack, doSetPlayerVisible } from 'redux/actions/drawer';
|
||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||
import PublishesPage from './view';
|
||||
|
@ -10,6 +15,7 @@ const select = state => ({
|
|||
});
|
||||
|
||||
const perform = dispatch => ({
|
||||
fetchMyClaims: () => dispatch(doFetchClaimListMine()),
|
||||
checkPendingPublishes: () => dispatch(doCheckPendingPublishes()),
|
||||
pushDrawerStack: () => dispatch(doPushDrawerStack(Constants.DRAWER_ROUTE_PUBLISHES)),
|
||||
setPlayerVisible: () => dispatch(doSetPlayerVisible(false)),
|
||||
|
|
|
@ -28,10 +28,11 @@ class PublishesPage extends React.PureComponent {
|
|||
}
|
||||
|
||||
onComponentFocused = () => {
|
||||
const { checkPendingPublishes, pushDrawerStack, setPlayerVisible } = this.props;
|
||||
const { checkPendingPublishes, fetchMyClaims, pushDrawerStack, setPlayerVisible } = this.props;
|
||||
|
||||
pushDrawerStack();
|
||||
setPlayerVisible();
|
||||
fetchMyClaims();
|
||||
checkPendingPublishes();
|
||||
};
|
||||
|
||||
|
|
|
@ -88,7 +88,6 @@ export const doNativeSearch = (
|
|||
dispatch(batchActions(...actions));
|
||||
})
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
dispatch({
|
||||
type: ACTIONS.SEARCH_FAIL,
|
||||
});
|
||||
|
|
|
@ -65,6 +65,12 @@ const channelSelectorStyle = StyleSheet.create({
|
|||
createButton: {
|
||||
backgroundColor: Colors.NextLbryGreen,
|
||||
},
|
||||
inlineError: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 12,
|
||||
color: Colors.Red,
|
||||
marginTop: 2,
|
||||
},
|
||||
});
|
||||
|
||||
export default channelSelectorStyle;
|
||||
|
|
|
@ -229,6 +229,9 @@ const publishStyle = StyleSheet.create({
|
|||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
backButtonControl: {
|
||||
flex: 0.1,
|
||||
},
|
||||
mainControlsRow: {
|
||||
flex: 0.8,
|
||||
flexDirection: 'row',
|
||||
|
@ -237,6 +240,7 @@ const publishStyle = StyleSheet.create({
|
|||
},
|
||||
switchCameraToggle: {
|
||||
marginRight: 48,
|
||||
color: Colors.White,
|
||||
},
|
||||
cameraAction: {
|
||||
width: 72,
|
||||
|
@ -267,6 +271,12 @@ const publishStyle = StyleSheet.create({
|
|||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
warning: {
|
||||
marginTop: 24,
|
||||
marginLeft: 16,
|
||||
marginRight: 16,
|
||||
alignItems: 'center',
|
||||
},
|
||||
rewardDriverCard: {
|
||||
alignItems: 'center',
|
||||
backgroundColor: Colors.BrighterLbryGreen,
|
||||
|
@ -336,6 +346,15 @@ const publishStyle = StyleSheet.create({
|
|||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
fullCentered: {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
noPublishes: {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
|
@ -375,6 +394,16 @@ const publishStyle = StyleSheet.create({
|
|||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 16,
|
||||
},
|
||||
cameraInfo: {
|
||||
color: Colors.White,
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 16,
|
||||
},
|
||||
warningText: {
|
||||
fontFamily: 'Inter-UI-Regular',
|
||||
fontSize: 14,
|
||||
color: Colors.DescriptionGrey,
|
||||
},
|
||||
});
|
||||
|
||||
export default publishStyle;
|
||||
|
|
Loading…
Reference in a new issue