fix rename: Fixed Renaming Directories not working properly
feat dialogs.error: Added Error dialogs to show errors
This commit is contained in:
parent
4967c03eed
commit
ffb7c68510
@ -10,7 +10,8 @@ Please read the Features section below and issues to make sure your issue is not
|
|||||||
- [x] Breadcrumb
|
- [x] Breadcrumb
|
||||||
- [x] Delete Files
|
- [x] Delete Files
|
||||||
- [x] Refresh
|
- [x] Refresh
|
||||||
- [ ] Rename Files
|
- [x] Rename Files
|
||||||
|
- [x] Error dialogs
|
||||||
- [ ] Create new files and directories
|
- [ ] Create new files and directories
|
||||||
- [ ] Different views (List, Icons, etc)
|
- [ ] Different views (List, Icons, etc)
|
||||||
- [ ] Share Files
|
- [ ] Share Files
|
||||||
|
1577
build/main.js
1577
build/main.js
File diff suppressed because it is too large
Load Diff
@ -44,6 +44,7 @@
|
|||||||
"grunt-fxos": "^0.1.2",
|
"grunt-fxos": "^0.1.2",
|
||||||
"grunt-task-loader": "^0.6.0",
|
"grunt-task-loader": "^0.6.0",
|
||||||
"less-plugin-clean-css": "^1.5.1",
|
"less-plugin-clean-css": "^1.5.1",
|
||||||
|
"lodash": "^3.10.1",
|
||||||
"react": "^0.13.3",
|
"react": "^0.13.3",
|
||||||
"react-redux": "^1.0.1",
|
"react-redux": "^1.0.1",
|
||||||
"redux": "^1.0.1",
|
"redux": "^1.0.1",
|
||||||
|
@ -1,32 +1,33 @@
|
|||||||
import { DIALOG } from 'actions/types';
|
import { DIALOG } from 'actions/types';
|
||||||
|
|
||||||
export function show(id) {
|
export function show(id, props = {}) {
|
||||||
return {
|
return {
|
||||||
type: DIALOG,
|
type: DIALOG,
|
||||||
active: true,
|
active: true,
|
||||||
id
|
id, ...props
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hide(id) {
|
export function hide(id, props = {}) {
|
||||||
return {
|
return {
|
||||||
type: DIALOG,
|
type: DIALOG,
|
||||||
active: false,
|
active: false,
|
||||||
id
|
id, ...props
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggle(id) {
|
export function toggle(id, props = {}) {
|
||||||
return {
|
return {
|
||||||
type: DIALOG,
|
type: DIALOG,
|
||||||
active: 'toggle',
|
active: 'toggle',
|
||||||
id
|
id, ...props
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hideAll() {
|
export function hideAll(props = {}) {
|
||||||
return {
|
return {
|
||||||
type: DIALOG,
|
type: DIALOG,
|
||||||
active: false
|
active: false,
|
||||||
|
...props
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,33 @@
|
|||||||
import { MENU } from 'actions/types';
|
import { MENU } from 'actions/types';
|
||||||
|
|
||||||
export function show(id, x, y) {
|
export function show(id, props = {}) {
|
||||||
return {
|
return {
|
||||||
type: MENU,
|
type: MENU,
|
||||||
active: true,
|
active: true,
|
||||||
id, x, y
|
id, ...props
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hide(id) {
|
export function hide(id, props = {}) {
|
||||||
return {
|
return {
|
||||||
type: MENU,
|
type: MENU,
|
||||||
active: false,
|
active: false,
|
||||||
id
|
id, ...props
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggle(id, x, y) {
|
export function toggle(id, props = {}) {
|
||||||
return {
|
return {
|
||||||
type: MENU,
|
type: MENU,
|
||||||
active: 'toggle',
|
active: 'toggle',
|
||||||
id, x, y
|
id, ...props
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hideAll() {
|
export function hideAll(props = {}) {
|
||||||
return {
|
return {
|
||||||
type: MENU,
|
type: MENU,
|
||||||
active: false
|
active: false,
|
||||||
|
...props
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ export function sdcard() {
|
|||||||
if (SD_CACHE) return SD_CACHE;
|
if (SD_CACHE) return SD_CACHE;
|
||||||
|
|
||||||
SD_CACHE = navigator.getDeviceStorage('sdcard');
|
SD_CACHE = navigator.getDeviceStorage('sdcard');
|
||||||
|
window.sdcard = SD_CACHE;
|
||||||
return SD_CACHE;
|
return SD_CACHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,13 +14,14 @@ export async function root() {
|
|||||||
if (ROOT_CACHE) return ROOT_CACHE;
|
if (ROOT_CACHE) return ROOT_CACHE;
|
||||||
|
|
||||||
ROOT_CACHE = await sdcard().getRoot();
|
ROOT_CACHE = await sdcard().getRoot();
|
||||||
|
window.root = ROOT_CACHE;
|
||||||
return ROOT_CACHE;
|
return ROOT_CACHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFile(dir = '/') {
|
export async function getFile(dir = '/') {
|
||||||
let parent = await root();
|
let parent = await root();
|
||||||
|
|
||||||
if (dir === '/' || !dir) return root();
|
if (dir === '/' || !dir) return parent;
|
||||||
|
|
||||||
return await parent.get(dir);
|
return await parent.get(dir);
|
||||||
}
|
}
|
||||||
@ -53,33 +55,42 @@ export async function createFile(...args) {
|
|||||||
export async function createDirectory(...args) {
|
export async function createDirectory(...args) {
|
||||||
let parent = await root();
|
let parent = await root();
|
||||||
|
|
||||||
return await parent.createDirectory(...args);
|
return parent.createDirectory(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function rename(file, newName) {
|
export async function move(file, newPath) {
|
||||||
let path = (file.path || '').slice(1); // remove starting slash
|
let path = (file.path || '').replace(/^\//, ''); // remove starting slash
|
||||||
let oldPath = (path + file.name);
|
let oldPath = path + file.name;
|
||||||
let newPath = path + newName;
|
|
||||||
|
newPath = newPath.replace(/^\//, '');
|
||||||
|
|
||||||
let target = await getFile(oldPath);
|
let target = await getFile(oldPath);
|
||||||
|
let parent = await root();
|
||||||
|
|
||||||
if (type(target) === 'Directory') {
|
if (type(target) === 'Directory') {
|
||||||
await createDirectory(newPath);
|
await parent.createDirectory(newPath);
|
||||||
let childs = await target.getFilesAndDirectories();
|
let childs = await target.getFilesAndDirectories();
|
||||||
|
|
||||||
for (let child of childs) {
|
for (let child of childs) {
|
||||||
await rename(child, newPath + '/' + child.name);
|
if (type(child) === 'File') {
|
||||||
|
child.path = oldPath + '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
target.delete();
|
await move(child, newPath + '/' + child.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
await parent.remove(oldPath);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
let content = await readFile(fullpath);
|
let content = await readFile(oldPath);
|
||||||
|
|
||||||
let blob = new Blob([content], {type: target.type});
|
let blob = new Blob([content], {type: target.type});
|
||||||
|
|
||||||
sdcard().delete(fullpath);
|
return new Promise((resolve, reject) => {
|
||||||
|
let request = sdcard().addNamed(blob, newPath);
|
||||||
sdcard().addNamed(blob, path + newName);
|
request.onsuccess = resolve;
|
||||||
|
request.onerror = reject;
|
||||||
|
request.onabort = reject;
|
||||||
|
}).then(() => sdcard().delete(oldPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ export default class Directory extends Component {
|
|||||||
|
|
||||||
let left = x + width / 2 - MENU_WIDTH / 2,
|
let left = x + width / 2 - MENU_WIDTH / 2,
|
||||||
top = y + height / 2 + MENU_TOP_SPACE;
|
top = y + height / 2 + MENU_TOP_SPACE;
|
||||||
store.dispatch(show('directoryMenu', left, top));
|
store.dispatch(show('directoryMenu', {style: {left, top}}));
|
||||||
store.dispatch(active(this.props.index));
|
store.dispatch(active(this.props.index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ export default class File extends Component {
|
|||||||
|
|
||||||
let left = x + width / 2 - MENU_WIDTH / 2,
|
let left = x + width / 2 - MENU_WIDTH / 2,
|
||||||
top = y + height / 2 + MENU_TOP_SPACE;
|
top = y + height / 2 + MENU_TOP_SPACE;
|
||||||
store.dispatch(show('fileMenu', left, top));
|
store.dispatch(show('fileMenu', {style: {left, top}}));
|
||||||
store.dispatch(active(this.props.index));
|
store.dispatch(active(this.props.index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ let DirectoryMenu = connect(state => state.get('directoryMenu'))(Menu);
|
|||||||
|
|
||||||
let RenameDialog = connect(state => state.get('renameDialog'))(Dialog);
|
let RenameDialog = connect(state => state.get('renameDialog'))(Dialog);
|
||||||
let DeleteDialog = connect(state => state.get('deleteDialog'))(Dialog);
|
let DeleteDialog = connect(state => state.get('deleteDialog'))(Dialog);
|
||||||
|
let ErrorDialog = connect(state => state.get('errorDialog'))(Dialog);
|
||||||
|
|
||||||
export default class Root extends Component {
|
export default class Root extends Component {
|
||||||
render() {
|
render() {
|
||||||
@ -36,6 +37,7 @@ export default class Root extends Component {
|
|||||||
|
|
||||||
<RenameDialog />
|
<RenameDialog />
|
||||||
<DeleteDialog />
|
<DeleteDialog />
|
||||||
|
<ErrorDialog />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -44,5 +44,12 @@ export default {
|
|||||||
className: 'success'
|
className: 'success'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
errorDialog: {
|
||||||
|
title: 'Error',
|
||||||
|
buttons: [{
|
||||||
|
text: 'Continue',
|
||||||
|
action: bind(hideAll())
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ export default function(state = new Immutable.Map(), 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'),
|
||||||
deleteDialog: dialog(state, action, 'deleteDialog')
|
deleteDialog: dialog(state, action, 'deleteDialog'),
|
||||||
|
errorDialog: dialog(state, action, 'errorDialog')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { DIALOG } from 'actions/types';
|
import { DIALOG } from 'actions/types';
|
||||||
import Immutable from 'immutable';
|
import Immutable from 'immutable';
|
||||||
|
import omit from 'lodash/object/omit';
|
||||||
|
|
||||||
export default function(state = new Immutable.Map({}), action, id) {
|
export default function(state = new Immutable.Map({}), action, id) {
|
||||||
if (action.type === DIALOG) {
|
if (action.type === DIALOG) {
|
||||||
|
let useful = omit(action, ['id', 'type'])
|
||||||
// action applied to all dialogs
|
// action applied to all dialogs
|
||||||
if (!action.id) {
|
if (!action.id) {
|
||||||
return Object.assign({}, state.get(id), {active: action.active});
|
return Object.assign({}, state.get(id), useful);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.id !== id) return state.get(id);
|
if (action.id !== id) return state.get(id);
|
||||||
@ -13,9 +15,7 @@ export default function(state = new Immutable.Map({}), action, id) {
|
|||||||
let target = state.get(action.id);
|
let target = state.get(action.id);
|
||||||
let active = action.active === 'toggle' ? !target.get('active') : action.active;
|
let active = action.active === 'toggle' ? !target.get('active') : action.active;
|
||||||
|
|
||||||
let style = Object.assign({}, state.style, {left: action.x, top: action.y});
|
return Object.assign({}, target, useful);
|
||||||
|
|
||||||
return Object.assign({}, target, { style, active });
|
|
||||||
} else {
|
} else {
|
||||||
return state.get(id);
|
return state.get(id);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { LIST_FILES, RENAME_FILE, DELETE_FILE } from 'actions/types';
|
import { LIST_FILES, RENAME_FILE, DELETE_FILE } from 'actions/types';
|
||||||
import { refresh } from 'actions/files-view';
|
import { refresh } from 'actions/files-view';
|
||||||
import { rename, sdcard } from 'api/files';
|
import { move, sdcard } from 'api/files';
|
||||||
|
import { show } from 'actions/dialog';
|
||||||
|
import store from 'store';
|
||||||
|
|
||||||
export default function(state = [], action) {
|
export default function(state = [], action) {
|
||||||
if (action.type === LIST_FILES) {
|
if (action.type === LIST_FILES) {
|
||||||
@ -11,7 +13,10 @@ export default function(state = [], action) {
|
|||||||
if (action.type === RENAME_FILE) {
|
if (action.type === RENAME_FILE) {
|
||||||
let file = state[action.file];
|
let file = state[action.file];
|
||||||
|
|
||||||
rename(file, action.name).then(refresh);
|
move(file, (file.path || '') + action.name).then(refresh, err => {
|
||||||
|
let action = show('errorDialog', {description: err.message});
|
||||||
|
store.dispatch(action);
|
||||||
|
});
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { MENU } from 'actions/types';
|
import { MENU } from 'actions/types';
|
||||||
import Immutable from 'immutable';
|
import Immutable from 'immutable';
|
||||||
|
import omit from 'lodash/object/omit';
|
||||||
|
|
||||||
export default function(state = new Immutable.Map({}), action, id) {
|
export default function(state = new Immutable.Map({}), action, id) {
|
||||||
if (action.type === MENU) {
|
if (action.type === MENU) {
|
||||||
|
let useful = omit(action, ['id', 'type'])
|
||||||
// action applied to all menus
|
// action applied to all menus
|
||||||
if (!action.id) {
|
if (!action.id) {
|
||||||
return Object.assign({}, state.get(id), {active: action.active});
|
return Object.assign({}, state.get(id), useful);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.id !== id) return state.get(id);
|
if (action.id !== id) return state.get(id);
|
||||||
@ -13,9 +15,7 @@ export default function(state = new Immutable.Map({}), action, id) {
|
|||||||
let target = state.get(action.id);
|
let target = state.get(action.id);
|
||||||
let active = action.active === 'toggle' ? !target.get('active') : action.active;
|
let active = action.active === 'toggle' ? !target.get('active') : action.active;
|
||||||
|
|
||||||
let style = Object.assign({}, state.style, {left: action.x, top: action.y});
|
return Object.assign({}, target, useful);
|
||||||
|
|
||||||
return Object.assign({}, target, { style, active });
|
|
||||||
} else {
|
} else {
|
||||||
return state.get(id);
|
return state.get(id);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user