feat navigation: style checkboxes in navigation
feat preferences: Show Hidden Files and Show Directories First options working
This commit is contained in:
parent
0ae06a77ae
commit
100dc03813
@ -12,11 +12,11 @@ Please read the Features section below and issues to make sure your issue is not
|
|||||||
- [x] Refresh
|
- [x] Refresh
|
||||||
- [x] Rename Files
|
- [x] Rename Files
|
||||||
- [x] Error dialogs
|
- [x] Error dialogs
|
||||||
|
- [x] Show / Hide hidden files
|
||||||
|
- [x] Show directories first
|
||||||
- [ ] Create new files and directories
|
- [ ] Create new files and directories
|
||||||
- [ ] File Size
|
- [ ] File Size
|
||||||
- [ ] Directory Child Count
|
- [ ] Directory Child Count
|
||||||
- [ ] Show / Hide hidden files
|
|
||||||
- [ ] Show directories first
|
|
||||||
- [ ] File Preview
|
- [ ] File Preview
|
||||||
- [ ] Filter Files
|
- [ ] Filter Files
|
||||||
- [ ] Different views (List, Icons, etc)
|
- [ ] Different views (List, Icons, etc)
|
||||||
|
817
build/main.js
817
build/main.js
File diff suppressed because it is too large
Load Diff
@ -101,6 +101,23 @@ input {
|
|||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
}
|
}
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
input[type="checkbox"]::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
input[type="checkbox"]::before:checked {
|
||||||
|
background: #63b0cd;
|
||||||
|
}
|
||||||
.file,
|
.file,
|
||||||
.directory {
|
.directory {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -230,6 +247,28 @@ nav li:last-of-type {
|
|||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
nav li label {
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
nav li label::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
float: right;
|
||||||
|
margin-right: 13px;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid #9b9b93;
|
||||||
|
}
|
||||||
|
nav li input {
|
||||||
|
clear: right;
|
||||||
|
float: right;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
nav li input:checked + label::after {
|
||||||
|
background: #63b0cd;
|
||||||
|
}
|
||||||
nav i {
|
nav i {
|
||||||
display: block;
|
display: block;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
Binary file not shown.
8
src/js/actions/settings.js
Normal file
8
src/js/actions/settings.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { SETTINGS } from 'actions/types';
|
||||||
|
|
||||||
|
export default function(props) {
|
||||||
|
return {
|
||||||
|
type: SETTINGS,
|
||||||
|
...props
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,8 @@ const TYPES = {
|
|||||||
|
|
||||||
DIALOG: Symbol('DEBUG'),
|
DIALOG: Symbol('DEBUG'),
|
||||||
|
|
||||||
|
SETTINGS: Symbol('SETTINGS'),
|
||||||
|
|
||||||
SEARCH: Symbol('SEARCH')
|
SEARCH: Symbol('SEARCH')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ import React, { Component } from 'react';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import File from './file';
|
import File from './file';
|
||||||
import Directory from './directory';
|
import Directory from './directory';
|
||||||
|
import store from 'store';
|
||||||
|
import { type } from 'utils';
|
||||||
|
|
||||||
@connect(props)
|
@connect(props)
|
||||||
export default class FileList extends Component {
|
export default class FileList extends Component {
|
||||||
@ -12,8 +14,24 @@ export default class FileList extends Component {
|
|||||||
render() {
|
render() {
|
||||||
let { files } = this.props;
|
let { files } = this.props;
|
||||||
|
|
||||||
|
let settings = store.getState().get('settings');
|
||||||
|
|
||||||
|
if (settings.showDirectoriesFirst) {
|
||||||
|
files = files.sort((a, b) => {
|
||||||
|
if (type(a) === 'Directory') return -1;
|
||||||
|
if (type(b) === 'Directory') return 1;
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!settings.showHiddenFiles) {
|
||||||
|
files = files.filter(file => {
|
||||||
|
return file.name[0] !== '.';
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let els = files.map((file, index) => {
|
let els = files.map((file, index) => {
|
||||||
if (fileType(file) === 'File') {
|
if (type(file) === 'File') {
|
||||||
return <File key={index} index={index} name={file.name} />;
|
return <File key={index} index={index} name={file.name} />;
|
||||||
} else {
|
} else {
|
||||||
return <Directory key={index} index={index} name={file.name} />
|
return <Directory key={index} index={index} name={file.name} />
|
||||||
@ -40,7 +58,3 @@ async function getFiles(dir) {
|
|||||||
|
|
||||||
return await root.getFilesAndDirectories();
|
return await root.getFilesAndDirectories();
|
||||||
}
|
}
|
||||||
|
|
||||||
function fileType(file) {
|
|
||||||
return Object.prototype.toString.call(file).slice(8, -1);
|
|
||||||
}
|
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { hide } from 'actions/navigation';
|
import { hide } from 'actions/navigation';
|
||||||
|
import camelCase from 'lodash/string/camelCase';
|
||||||
|
import updateSettings from 'actions/settings';
|
||||||
|
import store from 'store';
|
||||||
|
|
||||||
@connect(props)
|
@connect(props)
|
||||||
export default class Navigation extends Component {
|
export default class Navigation extends Component {
|
||||||
render() {
|
render() {
|
||||||
|
let { settings } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className={this.props.active ? 'active' : ''}>
|
<nav className={this.props.active ? 'active' : ''}>
|
||||||
<i onClick={this.hide.bind(this)} />
|
<i onClick={this.hide.bind(this)} />
|
||||||
@ -22,9 +27,15 @@ export default class Navigation extends Component {
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Preferences</p>
|
<p>Preferences</p>
|
||||||
<ul>
|
<ul onChange={this.onChange.bind(this)}>
|
||||||
<li>Show Hidden Files <input type='checkbox' /></li>
|
<li>
|
||||||
<li>Show Directories First <input type='checkbox' /></li>
|
<input type='checkbox' id='showHiddenFiles' defaultChecked={settings.showHiddenFiles} />
|
||||||
|
<label htmlFor='showHiddenFiles'>Show Hidden Files</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input id='showDirectoriesFirst' type='checkbox' defaultChecked={settings.showDirectoriesFirst} />
|
||||||
|
<label htmlFor='showDirectoriesFirst'>Show Directories First</label>
|
||||||
|
</li>
|
||||||
<li>Advanced Preferences</li>
|
<li>Advanced Preferences</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
@ -34,10 +45,24 @@ export default class Navigation extends Component {
|
|||||||
hide() {
|
hide() {
|
||||||
this.props.dispatch(hide());
|
this.props.dispatch(hide());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onChange(e) {
|
||||||
|
if (e.target.nodeName.toLowerCase() !== 'input') return;
|
||||||
|
|
||||||
|
let key = e.target.id;
|
||||||
|
let value = this.props.settings[key];
|
||||||
|
|
||||||
|
let action = updateSettings({
|
||||||
|
[key]: e.target.checked
|
||||||
|
});
|
||||||
|
|
||||||
|
store.dispatch(action);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function props(store) {
|
function props(store) {
|
||||||
return {
|
return {
|
||||||
active: store.get('navigation')
|
active: store.get('navigation'),
|
||||||
|
settings: store.get('settings')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import navigation from './navigation';
|
|||||||
import activeFile from './active-file';
|
import activeFile from './active-file';
|
||||||
import menu from './menu';
|
import menu from './menu';
|
||||||
import dialog from './dialog';
|
import dialog from './dialog';
|
||||||
|
import settings from './settings';
|
||||||
|
|
||||||
export default function(state = new Immutable.Map(), action) {
|
export default function(state = new Immutable.Map(), action) {
|
||||||
console.log('action', action);
|
console.log('action', action);
|
||||||
@ -15,6 +16,7 @@ export default function(state = new Immutable.Map(), action) {
|
|||||||
files: files(state.get('files'), action),
|
files: files(state.get('files'), action),
|
||||||
activeFile: activeFile(state.get('activeFile'), action),
|
activeFile: activeFile(state.get('activeFile'), action),
|
||||||
navigation: navigation(state.get('navigation'), action),
|
navigation: navigation(state.get('navigation'), action),
|
||||||
|
settings: settings(state.get('settings'), action),
|
||||||
fileMenu: menu(state, action, 'fileMenu'),
|
fileMenu: menu(state, action, 'fileMenu'),
|
||||||
directoryMenu: menu(state, action, 'directoryMenu'),
|
directoryMenu: menu(state, action, 'directoryMenu'),
|
||||||
renameDialog: dialog(state, action, 'renameDialog'),
|
renameDialog: dialog(state, action, 'renameDialog'),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { CHANGE_DIRECTORY, REFRESH } from 'actions/types';
|
import { CHANGE_DIRECTORY, REFRESH, SETTINGS } from 'actions/types';
|
||||||
import listFiles from 'actions/list-files';
|
import listFiles from 'actions/list-files';
|
||||||
import { children } from 'api/files';
|
import { children } from 'api/files';
|
||||||
import store from 'store';
|
import store from 'store';
|
||||||
@ -11,7 +11,7 @@ export default function(state = '', action) {
|
|||||||
return action.dir;
|
return action.dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === REFRESH) {
|
if (action.type === REFRESH || action.type === SETTINGS) {
|
||||||
children(state).then(files => {
|
children(state).then(files => {
|
||||||
store.dispatch(listFiles(files));
|
store.dispatch(listFiles(files));
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,6 @@ export default function(state = [], action) {
|
|||||||
return action.files;
|
return action.files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (action.type === RENAME_FILE) {
|
if (action.type === RENAME_FILE) {
|
||||||
let file = state[action.file];
|
let file = state[action.file];
|
||||||
|
|
||||||
|
15
src/js/reducers/settings.js
Normal file
15
src/js/reducers/settings.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { SETTINGS } from 'actions/types';
|
||||||
|
import omit from 'lodash/object/omit';
|
||||||
|
|
||||||
|
const DEFAULT = {
|
||||||
|
showHiddenFiles: false,
|
||||||
|
showDirectoriesFirst: true
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function(state = DEFAULT, action) {
|
||||||
|
if (action.type === SETTINGS) {
|
||||||
|
return Object.assign({}, state, omit(action, 'type'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
@ -7,7 +7,6 @@ import dialogs from './dialogs';
|
|||||||
|
|
||||||
const DEFAULT = new Immutable.Map(Object.assign({
|
const DEFAULT = new Immutable.Map(Object.assign({
|
||||||
dir: '',
|
dir: '',
|
||||||
files: []
|
|
||||||
}, dialogs, menus));
|
}, dialogs, menus));
|
||||||
|
|
||||||
let store = createStore(reducers, DEFAULT);
|
let store = createStore(reducers, DEFAULT);
|
||||||
|
@ -52,6 +52,39 @@ nav {
|
|||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
clear: left;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
margin-right: 13px;
|
||||||
|
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
border: 1px solid @overlay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
clear: right;
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + label::after {
|
||||||
|
background: @blue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
|
@ -13,3 +13,28 @@ input {
|
|||||||
|
|
||||||
.light-medium;
|
.light-medium;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
border: 1px solid @gray;
|
||||||
|
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
background: @blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user