Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ux improvements to publish modal #1998

Merged
merged 9 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion public/locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"unselectAll": "Unselect all",
"generate": "Generate",
"publish": "Publish",
"downloadCar": "Download as CAR"
"downloadCar": "Download as CAR",
"done": "Done"
},
"cliModal": {
"description": "Paste the following into your terminal to do this task in IPFS via the command line. Remember that you'll need to replace placeholders with your specific parameters."
Expand Down
1 change: 1 addition & 0 deletions public/locales/en/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
"publishUnderKey": "Select key for publishing:",
"help": "Go to Settings to learn about IPNS and create more keys.",
"publishedUnderKey": "Successfully published under the key:",
"linkCopied": "Link copied!",
"sharingPrompt": "Copy the link below and share it with others. The IPNS address will resolve as long as your node remains available on the network once a day to refresh the IPNS record.",
"pleaseWait": "Please wait while the initial 20 copies of the updated IPNS record are stored with the help of DHT peers…"
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/progress-bar/ProgressBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ ProgressBar.propTypes = {
width: PropTypes.string,
height: PropTypes.string,
br: PropTypes.string,
progress: PropTypes.number.isRequired
time: PropTypes.number,
progress: PropTypes.number
}

ProgressBar.defaultProps = {
Expand Down
53 changes: 41 additions & 12 deletions src/files/modals/publish-modal/PublishModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import Icon from '../../../icons/StrokeSpeaker'
import { connect } from 'redux-bundler-react'
import Radio from '../../../components/radio/Radio'
import ProgressBar from '../../../components/progress-bar/ProgressBar'
import GlyphCopy from '../../../icons/GlyphCopy'
import GlyphTick from '../../../icons/GlyphTick'
import './PublishModal.css'

const PublishModal = ({ t, tReady, onLeave, onSubmit, file, ipnsKeys, publicGateway, className, doFetchIpnsKeys, doUpdateExpectedPublishTime, expectedPublishTime, ...props }) => {
Expand All @@ -16,6 +18,7 @@ const PublishModal = ({ t, tReady, onLeave, onSubmit, file, ipnsKeys, publicGate
const [selectedKey, setSelectedKey] = useState({ name: '', id: '' })
const [link, setLink] = useState('')
const [start, setStart] = useState(null)
const [copied, setCopied] = useState(false)

useEffect(() => {
setDisabled(selectedKey.name === '' || start !== null)
Expand All @@ -25,6 +28,13 @@ const PublishModal = ({ t, tReady, onLeave, onSubmit, file, ipnsKeys, publicGate
doFetchIpnsKeys()
}, [doFetchIpnsKeys])

useEffect(() => {
if (copied) {
const timeoutId = setTimeout(() => setCopied(false), 2000)
return () => clearTimeout(timeoutId)
}
}, [copied])

const changeKey = (key) => {
setLink('')
setError(null)
Expand All @@ -51,17 +61,34 @@ const PublishModal = ({ t, tReady, onLeave, onSubmit, file, ipnsKeys, publicGate
if (link) {
return (
<div>
<div className='tl pv3'>{t('publishModal.publishedUnderKey')}<br/>
<span className='f6 charcoal-muted monospace'>{selectedKey.name}</span><br/>
<span className='f6 charcoal-muted monospace'>{selectedKey.id}</span>
<div className='tl pv3'>{t('publishModal.publishedUnderKey')}
<div className='f6 mv2 charcoal-muted monospace'>
<a target='_blank' rel='noopener noreferrer' className='link' href={link}>{selectedKey.name}</a>
</div>
<div className='f6 charcoal-muted monospace truncate'>
<a target='_blank' rel='noopener noreferrer' className='link' href={link}>{selectedKey.id}</a>
</div>
</div>
<p className='charcoal tl center'>{t('publishModal.sharingPrompt')}</p>
<div className='flex center pb2'>
<div className='flex center mb2 relative'>
<input
value={link}
readOnly
className={'input-reset flex-grow-1 charcoal-muted ba b--black-20 br1 pa2 mr2 focus-outline'}
className={'input-reset flex-grow-1 charcoal-muted ba b--black-20 br1 pa2 focus-outline'}
style={{ color: `rgba(128, 133, 145, ${copied ? 0.6 : 1})` }}
type='text' />

<div className='absolute h2 pl2 flex items-center' style={{ right: '4px', top: '50%', transform: 'translateY(-50%)', background: 'linear-gradient(90deg, rgba(255, 255, 255, 0.35), #ffffff 10%, #ffffff 100%)' }} >
{ copied
? <>
<span className="charcoal-muted strong f5">{t('publishModal.linkCopied')}</span>
<GlyphTick className='fill-aqua w2' />
</>
: <CopyToClipboard text={link} onCopy={() => setCopied(true)}>
<GlyphCopy className='fill-charcoal-muted w2 h2 pointer' />
</CopyToClipboard>
}
</div>
</div>
</div>
)
Expand Down Expand Up @@ -96,18 +123,20 @@ const PublishModal = ({ t, tReady, onLeave, onSubmit, file, ipnsKeys, publicGate
return (
<Modal {...props} className={className} onCancel={onLeave} >
<ModalBody Icon={Icon} title={t('publishModal.title')}>
<div className='tl pv3'>{t('publishModal.cidToPublish')}<br/><span className='f6 charcoal-muted monospace'>{file.cid.toString()}</span></div>
<div className='tl pv3'>
{t('publishModal.cidToPublish')}
<div className='f6 mt1 charcoal-muted monospace'>{file.cid.toString()}</div>
</div>
{modalBody()}
</ModalBody>

<ModalActions>
<Button className='ma2 tc' bg='bg-gray' onClick={onLeave}>{t('app:actions.cancel')}</Button>

{ link
? <CopyToClipboard text={link} onCopy={onLeave}>
<Button className='ma2 tc'>{t('app:actions.copy')}</Button>
</CopyToClipboard>
: <Button className='ma2 tc' bg='bg-teal' disabled={disabled} onClick={publish}>{t('app:actions.publish')}</Button>
? <Button className='ma2 tc ml-auto' onClick={onLeave}>{t('app:actions.done')}</Button>
: <>
<Button className='ma2 tc' bg='bg-gray' onClick={onLeave}>{t('app:actions.cancel')}</Button>
<Button className='ma2 tc' bg='bg-teal' disabled={disabled} onClick={publish}>{t('app:actions.publish')}</Button>
</>
}

</ModalActions>
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/ipns.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ test.describe('IPNS publishing', () => {
await ipfs.swarm.connect(peeraddr)
await page.click(publishButton)
await page.waitForSelector('text=Successfully published')
await page.click('button:has-text("Copy")')
await page.click('button:has-text("Done")')
// confirm IPNS record in local store points at the CID
const { id } = (await ipfs.key.list()).filter(k => k.name === keyName)[0]
for await (const name of ipfs.name.resolve(`/ipns/${id}`, { recursive: true })) {
Expand Down