feat search: search files, depth-first
feat files.view: Open files using Web Activities feat copy/paste: Copy and Paste/Move files fix filters: add "all" filter which clears filters out
This commit is contained in:
@@ -8,6 +8,8 @@ import menu from './menu';
|
||||
import dialog from './dialog';
|
||||
import settings from './settings';
|
||||
import selectView from './select-view';
|
||||
import spinner from './spinner';
|
||||
import search from './search';
|
||||
|
||||
export default function(state = new Immutable.Map(), action) {
|
||||
console.log('action', action);
|
||||
@@ -15,6 +17,8 @@ export default function(state = new Immutable.Map(), action) {
|
||||
lwd: lwd(state, action), // last working directory
|
||||
cwd: cwd(state.get('cwd'), action),
|
||||
files: files(state.get('files'), action),
|
||||
search: search(state.get('search'), action),
|
||||
spinner: spinner(state.get('spinner'), action),
|
||||
selectView: selectView(state.get('selectView'), action),
|
||||
activeFile: activeFile(state.get('activeFile'), action),
|
||||
navigation: navigation(state.get('navigation'), action),
|
||||
@@ -26,5 +30,6 @@ export default function(state = new Immutable.Map(), action) {
|
||||
deleteDialog: dialog(state, action, 'deleteDialog'),
|
||||
errorDialog: dialog(state, action, 'errorDialog'),
|
||||
createDialog: dialog(state, action, 'createDialog'),
|
||||
searchDialog: dialog(state, action, 'searchDialog')
|
||||
});
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { CHANGE_DIRECTORY, REFRESH, SETTINGS } from 'actions/types';
|
||||
import listFiles from 'actions/list-files';
|
||||
import { children } from 'api/files';
|
||||
import store from 'store';
|
||||
import { reportError } from 'utils';
|
||||
import { listFiles } from 'actions/files-view';
|
||||
|
||||
export default function(state = '', action) {
|
||||
if (action.type === CHANGE_DIRECTORY) {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { LIST_FILES, RENAME_FILE, DELETE_FILE, CREATE_FILE } from 'actions/types';
|
||||
import { LIST_FILES, RENAME_FILE, DELETE_FILE, CREATE_FILE, MOVE_FILE, COPY_FILE, SEARCH } from 'actions/types';
|
||||
import { refresh } from 'actions/files-view';
|
||||
import { move, remove, sdcard, createFile, createDirectory } from 'api/files';
|
||||
import { move, remove, sdcard, createFile, createDirectory, copy } from 'api/files';
|
||||
import { show } from 'actions/dialog';
|
||||
import store, { bind } from 'store';
|
||||
import { reportError, type } from 'utils';
|
||||
@@ -8,8 +8,8 @@ import { reportError, type } from 'utils';
|
||||
let boundRefresh = bind(refresh());
|
||||
|
||||
export default function(state = [], action) {
|
||||
if (action.type === LIST_FILES) {
|
||||
|
||||
if (action.type === LIST_FILES) {
|
||||
let settings = store.getState().get('settings');
|
||||
|
||||
if (settings.showDirectoriesFirst) {
|
||||
@@ -22,7 +22,16 @@ export default function(state = [], action) {
|
||||
if (!settings.showHiddenFiles) {
|
||||
action.files = action.files.filter(file => {
|
||||
return file.name[0] !== '.';
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (settings.filter) {
|
||||
action.files = action.files.filter(file => {
|
||||
if (type(file) === 'Directory') return true;
|
||||
|
||||
let fileType = file.type.slice(0, file.type.indexOf('/'));
|
||||
return fileType === settings.filter;
|
||||
});
|
||||
}
|
||||
|
||||
return action.files;
|
||||
@@ -36,34 +45,45 @@ export default function(state = [], action) {
|
||||
}
|
||||
|
||||
if (action.type === RENAME_FILE) {
|
||||
let file = state[action.file];
|
||||
let all = Promise.all(action.file.map(file => {
|
||||
return move(file, (file.path || '') + action.name);
|
||||
}));
|
||||
|
||||
move(file, (file.path || '') + action.name).then(boundRefresh, reportError);
|
||||
all.then(boundRefresh, reportError);
|
||||
return state;
|
||||
}
|
||||
|
||||
if (action.type === MOVE_FILE) {
|
||||
let all = Promise.all(action.file.map(file => {
|
||||
return move(file, action.newPath + '/' + file.name);
|
||||
}));
|
||||
|
||||
all.then(boundRefresh, reportError);
|
||||
return state;
|
||||
}
|
||||
|
||||
if (action.type === COPY_FILE) {
|
||||
let all = Promise.all(action.file.map(file => {
|
||||
return copy(file, action.newPath + '/' + file.name);
|
||||
}));
|
||||
|
||||
all.then(boundRefresh, reportError);
|
||||
return state;
|
||||
}
|
||||
|
||||
if (action.type === DELETE_FILE) {
|
||||
let copy = state.slice(0);
|
||||
let all = Promise.all(action.file.map(file => {
|
||||
let path = ((file.path || '') + file.name).replace(/^\//, '');
|
||||
return remove(path, true);
|
||||
}))
|
||||
|
||||
if (action.file.length) {
|
||||
for (let index of action.file) {
|
||||
del(state, index);
|
||||
}
|
||||
|
||||
copy = copy.filter((a, i) => action.file.indexOf(i) === -1);
|
||||
} else {
|
||||
del(state, action.file);
|
||||
copy.splice(action.file, 1);
|
||||
}
|
||||
|
||||
return copy;
|
||||
all.then(boundRefresh, reportError);
|
||||
return state;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function del(state, index) {
|
||||
let file = state[index];
|
||||
return remove((file.path || '') + '/' + file.name).catch(reportError);
|
||||
function mov(file, newPath) {
|
||||
return
|
||||
}
|
||||
|
50
src/js/reducers/search.js
Normal file
50
src/js/reducers/search.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import { SEARCH } from 'actions/types';
|
||||
import store from 'store';
|
||||
import { reportError } from 'utils';
|
||||
import { listFiles } from 'actions/files-view';
|
||||
import { children } from 'api/files';
|
||||
import { type } from 'utils';
|
||||
|
||||
export default function(state = '', action) {
|
||||
if (action.type === SEARCH) {
|
||||
search(action.keywords);
|
||||
|
||||
return action.keywords;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function search(keywords) {
|
||||
if (!keywords) {
|
||||
let cwd = store.getState().get('cwd');
|
||||
console.log(cwd);
|
||||
children(cwd, true).then(files => {
|
||||
store.dispatch(listFiles(files));
|
||||
}, reportError);
|
||||
return '';
|
||||
}
|
||||
let keys = keywords.split(' ');
|
||||
|
||||
// We don't want to show all the currently visible files from the
|
||||
// first iteration
|
||||
let once = true;
|
||||
children('/', true).then(function showResults(files) {
|
||||
if (!store.getState().get('search')) return;
|
||||
|
||||
let current = once ? [] : store.getState().get('files');
|
||||
once = false;
|
||||
|
||||
let filtered = files.filter(file => {
|
||||
if (type(file) === 'Directory') {
|
||||
let path = (file.path + file.name).replace(/^\//, '');
|
||||
children(path, true).then(showResults, reportError);
|
||||
}
|
||||
return keys.some(key => {
|
||||
return file.name.indexOf(key) > -1;
|
||||
});
|
||||
});
|
||||
|
||||
store.dispatch(listFiles(current.concat(filtered)));
|
||||
}, reportError);
|
||||
}
|
21
src/js/reducers/spinner.js
Normal file
21
src/js/reducers/spinner.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { SPINNER, CHANGE_DIRECTORY, LIST_FILES, REFRESH, DIALOG, CREATE_FILE, DELETE_FILE } from 'actions/types';
|
||||
|
||||
export default function(state = false, action) {
|
||||
if (action.type === SPINNER) {
|
||||
return action.active === 'toggle' ? !state : action.active;
|
||||
}
|
||||
|
||||
if (action.type === DIALOG && action.id === 'errorDialog') {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (action.type) {
|
||||
case CHANGE_DIRECTORY:
|
||||
case REFRESH:
|
||||
return true;
|
||||
case LIST_FILES:
|
||||
return false;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
Reference in New Issue
Block a user