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: add react-virtualized to the files list #957

Merged
merged 19 commits into from
Feb 25, 2019
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
2 changes: 1 addition & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class App extends Component {
const { route: Page, ipfsReady, routeInfo: { url }, navbarIsOpen, connectDropTarget, isOver } = this.props

return connectDropTarget(
<div className='sans-serif' onClick={navHelper(this.props.doUpdateUrl)}>
<div className='sans-serif h-100' onClick={navHelper(this.props.doUpdateUrl)}>
{/* Tinted overlay that appears when dragging and dropping an item */}
{ isOver && <div className='w-100 h-100 top-0 left-0 absolute' style={{ background: 'rgba(99, 202, 210, 0.2)' }} /> }
<div className='flex-l' style={{ minHeight: '100vh' }}>
Expand Down
21 changes: 7 additions & 14 deletions src/bundles/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { join, dirname } from 'path'
import { createSelector } from 'redux-bundler'
import { getDownloadLink, getShareableLink, filesToStreams } from '../lib/files'
import countDirs from '../lib/count-dirs'
import ms from 'milliseconds'

const isMac = navigator.userAgent.indexOf('Mac') !== -1

Expand Down Expand Up @@ -104,6 +103,7 @@ const fetchFiles = make(actions.FETCH, async (ipfs, id, { store }) => {
// Otherwise get the directory info
const res = await ipfs.files.ls(path, { l: true }) || []
const files = []
const showStats = res.length < 100

for (const f of res) {
let file = {
Expand All @@ -112,7 +112,7 @@ const fetchFiles = make(actions.FETCH, async (ipfs, id, { store }) => {
type: f.type === 0 ? 'file' : 'directory'
}

if (file.type === 'directory') {
if (showStats && file.type === 'directory') {
file = {
...file,
...await ipfs.files.stat(file.path)
Expand Down Expand Up @@ -149,7 +149,6 @@ const defaultState = {
}

export default (opts = {}) => {
opts.staleAfter = opts.staleAfter || ms.minutes(1)
opts.baseUrl = opts.baseUrl || '/files'

return {
Expand Down Expand Up @@ -350,17 +349,6 @@ export default (opts = {}) => {
dispatch({ type: 'FILES_UPDATE_SORT', payload: { by, asc } })
},

reactFilesFetch: createSelector(
'selectFiles',
'selectFilesIsFetching',
'selectAppTime',
(files, isFetching, appTime) => {
if (!isFetching && files && appTime - files.fetched >= opts.staleAfter) {
return { actionCreator: 'doFilesFetch' }
}
}
),

selectFiles: (state) => {
const { pageContent, sorting } = state.files

Expand Down Expand Up @@ -390,6 +378,11 @@ export default (opts = {}) => {

selectFilesIsFetching: (state) => state.files.pending.some(a => a.type === actions.FETCH),

selectShowLoadingAnimation: (state) => {
const pending = state.files.pending.find(a => a.type === actions.FETCH)
return pending ? (Date.now() - pending.start) > 1000 : false
fsdiogo marked this conversation as resolved.
Show resolved Hide resolved
},

selectFilesSorting: (state) => state.files.sorting,

selectWriteFilesProgress: (state) => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/checkbox/Checkbox.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
left: -99999px;
}

.Checkbox > input:checked ~ span:first-of-type svg {
.Checkbox input:checked ~ span:first-of-type svg {
opacity: 1;
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/checkbox/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const Checkbox = ({ className, label, disabled, checked, onChange, ...props }) =
return (
<label className={className} {...props}>
<input className='absolute' type='checkbox' checked={checked} disabled={disabled} onChange={change} />
<span className='dib v-mid br1 w1 h1 mr1'>
<span className='dib v-mid br1 w1 h1 pointer'>
<Tick className='w1 h1 o-0 fill-aqua' viewBox='25 25 50 50' />
</span>
<span className='v-mid pl2'>
Expand Down
12 changes: 8 additions & 4 deletions src/components/loading-animation/LoadingAnimation.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
.LoadingAnimation {
position: relative;
overflow: hidden;
opacity: 0.4;
background-color: #f0f6fa;
opacity: 0.2;
height: 100%;
}

.LoadingAnimation .Checkbox span {
opacity: 1 !important;
}

.LoadingAnimationSwipe::after {
Expand All @@ -24,10 +28,10 @@

@keyframes LoadingAnimationSwipe {
0% {
transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0) skew(-20deg);
}

100% {
transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0) skew(0);
}
}
60 changes: 51 additions & 9 deletions src/components/loading-animation/LoadingAnimation.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,58 @@
import React from 'react'
import { translate } from 'react-i18next'
// Components
import GlyphDots from '../../icons/GlyphDots'
import Checkbox from '../../components/checkbox/Checkbox'
import FileIcon from '../../files/file-icon/FileIcon'
// Styles
import './LoadingAnimation.css'

const LoadingAnimation = ({ loading, children }) => {
if (!loading) return children
const FakeHeader = ({ t }) => (
<header className='gray pv2 flex items-center flex-none'>
<div className='pa2 w2'><Checkbox disabled /></div>
<div className='ph2 f6 flex-auto'>{t('fileName')}</div>
<div className='pl2 pr4 tr f6 flex-none dn db-l'>{t('size')}</div>
<div className='pa2' style={{ width: '2.5rem' }} />
</header>
)

return (
<div className='LoadingAnimation'>
<div className='LoadingAnimationSwipe'>
{ children }
const FakeFile = ({ nameWidth }) => (
<div className='b--light-gray relative flex items-center bt' style={{ height: 55 }}>
<div className='pa2 w2'>
<Checkbox disabled />
</div>
<div className='relative pointer flex items-center flex-grow-1 ph2 pv1 w-40'>
<div className='dib flex-shrink-0 mr2'>
<FileIcon cls='fill-charcoal' />
</div>
<div className='w-100'>
<div className={`w-${nameWidth} br1 bg-charcoal-muted f7`}>&nbsp;</div>
<div className='w-80 br1 mt1 bg-gray f7 o-70'>&nbsp;</div>
</div>
</div>
)
}
<div className='size mr4 pl2 pr4 flex-none dn db-l br1 tr f7 bg-gray'>&nbsp;</div>
<div className='ph2' style={{ width: '2.5rem' }}>
<GlyphDots className='fill-gray-muted pointer' />
</div>
</div>
)

const LoadingAnimation = ({ t }) => (
<div className='LoadingAnimation'>
<div className='LoadingAnimationSwipe'>
<FakeHeader t={t} />
<FakeFile nameWidth={50} />
<FakeFile nameWidth={40} />
<FakeFile nameWidth={60} />
<FakeFile nameWidth={30} />
<FakeFile nameWidth={50} />
<FakeFile nameWidth={60} />
<FakeFile nameWidth={70} />
<FakeFile nameWidth={40} />
<FakeFile nameWidth={30} />
<FakeFile nameWidth={50} />
</div>
</div>
)

export default LoadingAnimation
export default translate('files')(LoadingAnimation)
12 changes: 7 additions & 5 deletions src/files/context-menu/ContextMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import StrokeDownload from '../../icons/StrokeDownload'
class ContextMenu extends React.Component {
static propTypes = {
isOpen: PropTypes.bool,
isUpperDir: PropTypes.bool,
handleClick: PropTypes.func,
translateX: PropTypes.number,
translateY: PropTypes.number,
Expand All @@ -32,6 +33,7 @@ class ContextMenu extends React.Component {

static defaultProps = {
isOpen: false,
isUpperDir: false,
top: 0,
left: 0,
right: 'auto',
Expand All @@ -51,7 +53,7 @@ class ContextMenu extends React.Component {
}

render () {
const { t, onRename, onDelete, onDownload, onInspect, onShare, translateX, translateY, className, showDots } = this.props
const { t, onRename, onDelete, onDownload, onInspect, onShare, translateX, translateY, className, showDots, isUpperDir } = this.props

return (
<Dropdown className={className}>
Expand All @@ -64,19 +66,19 @@ class ContextMenu extends React.Component {
translateY={-translateY}
open={this.props.isOpen}
onDismiss={this.props.handleClick}>
{ onDelete &&
{ !isUpperDir && onDelete &&
<Option onClick={this.wrap('onDelete')}>
<StrokeTrash className='w2 mr2 fill-aqua' />
{t('actions.delete')}
</Option>
}
{ onRename &&
{ !isUpperDir && onRename &&
<Option onClick={this.wrap('onRename')}>
<StrokePencil className='w2 mr2 fill-aqua' />
{t('actions.rename')}
</Option>
}
{ onDownload &&
{ !isUpperDir && onDownload &&
<Option onClick={this.wrap('onDownload')}>
<StrokeDownload className='w2 mr2 fill-aqua' />
{t('actions.download')}
Expand All @@ -94,7 +96,7 @@ class ContextMenu extends React.Component {
{t('actions.copyHash')}
</Option>
</CopyToClipboard>
{ onShare &&
{ !isUpperDir && onShare &&
<Option onClick={this.wrap('onShare')}>
<StrokeShare className='w2 mr2 fill-aqua' />
{t('actions.share')}
Expand Down
16 changes: 8 additions & 8 deletions src/files/file-icon/FileIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@ import DocText from '../../icons/GlyphDocText'

const style = { width: 36 }

export default function FileIcon ({ name, type }) {
export default function FileIcon ({ name, type, cls = '' }) {
if (type === 'directory') {
return <Folder className=' fill-aqua' style={style} />
return <Folder className={`fill-aqua ${cls}`} style={style} />
}

switch (typeFromExt(name)) {
case 'audio':
return <DocMusic className='fill-aqua' style={style} />
return <DocMusic className={`fill-aqua ${cls}`} style={style} />
case 'calc':
return <DocCalc className='fill-aqua' style={style} />
return <DocCalc className={`fill-aqua ${cls}`} style={style} />
case 'video':
return <DocMovie className='fill-aqua' style={style} />
return <DocMovie className={`fill-aqua ${cls}`} style={style} />
case 'text':
return <DocText className='fill-aqua' style={style} />
return <DocText className={`fill-aqua ${cls}`} style={style} />
case 'image':
return <DocPicture className='fill-aqua' style={style} />
return <DocPicture className={`fill-aqua ${cls}`} style={style} />
default:
return <Doc className='fill-aqua' style={style} />
return <Doc className={`fill-aqua ${cls}`} style={style} />
}
}
17 changes: 14 additions & 3 deletions src/files/file/File.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import PropTypes from 'prop-types'
import { join, basename } from 'path'
import filesize from 'filesize'
import classnames from 'classnames'
// React DnD
import { DropTarget, DragSource } from 'react-dnd'
import { NativeTypes } from 'react-dnd-html5-backend'
Expand Down Expand Up @@ -59,7 +60,7 @@ class File extends React.Component {
styles = {}
} = this.props

let className = 'File b--light-gray hide-child-l relative flex items-center bt'
let className = 'File b--light-gray relative flex items-center bt'

if (selected) {
className += ' selected'
Expand All @@ -78,13 +79,23 @@ class File extends React.Component {
styles.borderTop = '1px solid #eee'
}

size = filesize(cumulativeSize || size, { round: 0 })
styles.height = 55
styles.overflow = 'hidden'

size = (type === 'directory' && !cumulativeSize)
? '―'
: filesize(cumulativeSize || size, { round: 0 })

const select = (select) => onSelect(name, select)

const checkBoxCls = classnames({
'o-70 glow': !cantSelect,
'o-1': selected || focused
}, ['pl2 w2'])

const element = connectDropTarget(
<div className={className} style={styles} onContextMenu={this.handleCtxRightClick}>
<div className='child float-on-left-l pa2 w2' style={(selected || focused) ? { opacity: '1' } : null}>
<div className={checkBoxCls}>
<Checkbox disabled={cantSelect} checked={selected} onChange={select} />
</div>
{connectDragPreview(
Expand Down
Loading