+
+ {input}
+ {label}
+
{this.props.name}
{this.props.children} items
@@ -37,4 +52,16 @@ export default class Directory extends Component {
store.dispatch(show('directoryMenu', {style: {left, top}}));
store.dispatch(active(this.props.index));
}
+
+ select() {
+ let current = (store.getState().get('activeFile') || []).slice(0);
+ let index = this.props.index;
+
+ if (current.indexOf(index) > -1) {
+ current.splice(current.indexOf(index), 1);
+ } else {
+ current.push(index)
+ }
+ store.dispatch(active(current));
+ }
}
diff --git a/src/js/components/file-list.js b/src/js/components/file-list.js
index 5f2b6be..c774fdc 100644
--- a/src/js/components/file-list.js
+++ b/src/js/components/file-list.js
@@ -12,29 +12,16 @@ export default class FileList extends Component {
}
render() {
- let { files } = this.props;
-
+ let { files, selectView, activeFile } = this.props;
+ activeFile = activeFile || [];
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 selected = activeFile.indexOf(index) > -1;
if (type(file) === 'File') {
- return
;
+ return
;
} else {
- return
+ return
}
});
@@ -48,7 +35,9 @@ export default class FileList extends Component {
function props(state) {
return {
- files: state.get('files')
+ files: state.get('files'),
+ selectView: state.get('selectView'),
+ activeFile: state.get('activeFile')
}
}
diff --git a/src/js/components/file.js b/src/js/components/file.js
index 30e2561..cb160e1 100644
--- a/src/js/components/file.js
+++ b/src/js/components/file.js
@@ -13,9 +13,25 @@ export default class File extends Component {
}
render() {
+ let checkId = `file-${this.props.index}`;
+
+ let input, label;
+ if (this.props.selectView) {
+ input =
;
+ label =
;
+ }
+
+ let clickHandler = this.props.selectView ? this.select.bind(this)
+ : null;
+
return (
+
+ {input}
+ {label}
+
{this.props.name}
{humanSize(this.props.size)}
@@ -34,4 +50,16 @@ export default class File extends Component {
store.dispatch(show('fileMenu', {style: {left, top}}));
store.dispatch(active(this.props.index));
}
+
+ select() {
+ let current = (store.getState().get('activeFile') || []).slice(0);
+ let index = this.props.index;
+
+ if (current.indexOf(index) > -1) {
+ current.splice(current.indexOf(index), 1);
+ } else {
+ current.push(index)
+ }
+ store.dispatch(active(current));
+ }
}
diff --git a/src/js/components/root.js b/src/js/components/root.js
index 8121471..bf9c163 100644
--- a/src/js/components/root.js
+++ b/src/js/components/root.js
@@ -18,6 +18,7 @@ window.changedir = changedir;
let FileMenu = connect(state => state.get('fileMenu'))(Menu);
let DirectoryMenu = connect(state => state.get('directoryMenu'))(Menu);
+let MoreMenu = connect(state => state.get('moreMenu'))(Menu);
let RenameDialog = connect(state => state.get('renameDialog'))(Dialog);
let DeleteDialog = connect(state => state.get('deleteDialog'))(Dialog);
@@ -36,6 +37,7 @@ export default class Root extends Component {
+
@@ -46,7 +48,12 @@ export default class Root extends Component {
}
touchStart(e) {
- if (!e.target.closest('.menu')) {
+ let active = document.querySelector('.active');
+ let inside = e.target.closest('.menu') || e.target.closest('.dialog');
+ if (!inside && active) {
+ e.preventDefault();
+ e.stopPropagation();
+
store.dispatch(hideAllMenus());
store.dispatch(hideAllDialogs());
}
diff --git a/src/js/components/toolbar.js b/src/js/components/toolbar.js
index 31340f9..4c39f66 100644
--- a/src/js/components/toolbar.js
+++ b/src/js/components/toolbar.js
@@ -1,7 +1,9 @@
import React, { Component } from 'react';
-import { toggle as toggleView, refresh } from 'actions/files-view';
+import { toggle as toggleView, refresh, selectView } from 'actions/files-view';
import { show as showDialog } from 'actions/dialog';
+import { show as showMenu } from 'actions/menu';
import store, { bind } from 'store';
+import { MENU_WIDTH } from './menu';
export default class Toolbar extends Component {
render() {
@@ -10,14 +12,21 @@ export default class Toolbar extends Component {
-
-
+
+
);
}
showMore() {
+ let rect = React.findDOMNode(this.refs.more).getBoundingClientRect();
+ let {x, y, width, height} = rect;
+ let left = x + width - MENU_WIDTH,
+ top = y + height;
+
+ let transform = 'translate(0, -100%)';
+ store.dispatch(showMenu('moreMenu', {style: {left, top, transform}}));
}
newFile() {
diff --git a/src/js/dialogs.js b/src/js/dialogs.js
index a4d1b2a..f44b6b1 100644
--- a/src/js/dialogs.js
+++ b/src/js/dialogs.js
@@ -1,6 +1,6 @@
import React from 'react';
import { hide, hideAll } from 'actions/dialog';
-import { rename, deleteFile, create } from 'actions/file';
+import { rename, deleteFile, create, active } from 'actions/file';
import store, { bind } from 'store';
export default {
@@ -18,6 +18,7 @@ export default {
let action = create(cwd + input.value);
this.props.dispatch(action);
this.props.dispatch(hideAll());
+ this.props.dispatch(active());
}
},
{
@@ -29,6 +30,7 @@ export default {
let action = create(cwd + input.value, true);
this.props.dispatch(action);
this.props.dispatch(hideAll());
+ this.props.dispatch(active());
}
}
]
@@ -50,6 +52,7 @@ export default {
let activeFile = store.getState().get('activeFile');
this.props.dispatch(rename(activeFile, input.value))
this.props.dispatch(hideAll());
+ this.props.dispatch(active());
},
className: 'success'
}
@@ -69,6 +72,7 @@ export default {
let activeFile = store.getState().get('activeFile');
this.props.dispatch(deleteFile(activeFile));
this.props.dispatch(hideAll());
+ this.props.dispatch(active());
},
className: 'success'
}
diff --git a/src/js/libs/l10n.js b/src/js/libs/l10n.js
deleted file mode 100644
index cfc5c51..0000000
--- a/src/js/libs/l10n.js
+++ /dev/null
@@ -1,1571 +0,0 @@
-// This is the Gaia version of l20n: https://github.com/l20n/l20n.js
-// l20n is Apache 2.0 licensed: https://github.com/l20n/l20n.js/blob/master/LICENSE
-// You can find the latest build for Gaia here: https://github.com/mozilla-b2g/gaia/blob/master/shared/js/l10n.js
-(function(window, undefined) {
- 'use strict';
-
- /* jshint validthis:true */
- function L10nError(message, id, loc) {
- this.name = 'L10nError';
- this.message = message;
- this.id = id;
- this.loc = loc;
- }
- L10nError.prototype = Object.create(Error.prototype);
- L10nError.prototype.constructor = L10nError;
-
-
- /* jshint browser:true */
-
- var io = {
- load: function load(url, callback, sync) {
- var xhr = new XMLHttpRequest();
-
- if (xhr.overrideMimeType) {
- xhr.overrideMimeType('text/plain');
- }
-
- xhr.open('GET', url, !sync);
-
- xhr.addEventListener('load', function io_load(e) {
- if (e.target.status === 200 || e.target.status === 0) {
- callback(null, e.target.responseText);
- } else {
- callback(new L10nError('Not found: ' + url));
- }
- });
- xhr.addEventListener('error', callback);
- xhr.addEventListener('timeout', callback);
-
- // the app: protocol throws on 404, see https://bugzil.la/827243
- try {
- xhr.send(null);
- } catch (e) {
- callback(new L10nError('Not found: ' + url));
- }
- },
-
- loadJSON: function loadJSON(url, callback) {
- var xhr = new XMLHttpRequest();
-
- if (xhr.overrideMimeType) {
- xhr.overrideMimeType('application/json');
- }
-
- xhr.open('GET', url);
-
- xhr.responseType = 'json';
- xhr.addEventListener('load', function io_loadjson(e) {
- if (e.target.status === 200 || e.target.status === 0) {
- callback(null, e.target.response);
- } else {
- callback(new L10nError('Not found: ' + url));
- }
- });
- xhr.addEventListener('error', callback);
- xhr.addEventListener('timeout', callback);
-
- // the app: protocol throws on 404, see https://bugzil.la/827243
- try {
- xhr.send(null);
- } catch (e) {
- callback(new L10nError('Not found: ' + url));
- }
- }
- };
-
- function EventEmitter() {}
-
- EventEmitter.prototype.emit = function ee_emit() {
- if (!this._listeners) {
- return;
- }
-
- var args = Array.prototype.slice.call(arguments);
- var type = args.shift();
- if (!this._listeners[type]) {
- return;
- }
-
- var typeListeners = this._listeners[type].slice();
- for (var i = 0; i < typeListeners.length; i++) {
- typeListeners[i].apply(this, args);
- }
- };
-
- EventEmitter.prototype.addEventListener = function ee_add(type, listener) {
- if (!this._listeners) {
- this._listeners = {};
- }
- if (!(type in this._listeners)) {
- this._listeners[type] = [];
- }
- this._listeners[type].push(listener);
- };
-
- EventEmitter.prototype.removeEventListener = function ee_rm(type, listener) {
- if (!this._listeners) {
- return;
- }
-
- var typeListeners = this._listeners[type];
- var pos = typeListeners.indexOf(listener);
- if (pos === -1) {
- return;
- }
-
- typeListeners.splice(pos, 1);
- };
-
-
- function getPluralRule(lang) {
- var locales2rules = {
- 'af': 3,
- 'ak': 4,
- 'am': 4,
- 'ar': 1,
- 'asa': 3,
- 'az': 0,
- 'be': 11,
- 'bem': 3,
- 'bez': 3,
- 'bg': 3,
- 'bh': 4,
- 'bm': 0,
- 'bn': 3,
- 'bo': 0,
- 'br': 20,
- 'brx': 3,
- 'bs': 11,
- 'ca': 3,
- 'cgg': 3,
- 'chr': 3,
- 'cs': 12,
- 'cy': 17,
- 'da': 3,
- 'de': 3,
- 'dv': 3,
- 'dz': 0,
- 'ee': 3,
- 'el': 3,
- 'en': 3,
- 'eo': 3,
- 'es': 3,
- 'et': 3,
- 'eu': 3,
- 'fa': 0,
- 'ff': 5,
- 'fi': 3,
- 'fil': 4,
- 'fo': 3,
- 'fr': 5,
- 'fur': 3,
- 'fy': 3,
- 'ga': 8,
- 'gd': 24,
- 'gl': 3,
- 'gsw': 3,
- 'gu': 3,
- 'guw': 4,
- 'gv': 23,
- 'ha': 3,
- 'haw': 3,
- 'he': 2,
- 'hi': 4,
- 'hr': 11,
- 'hu': 0,
- 'id': 0,
- 'ig': 0,
- 'ii': 0,
- 'is': 3,
- 'it': 3,
- 'iu': 7,
- 'ja': 0,
- 'jmc': 3,
- 'jv': 0,
- 'ka': 0,
- 'kab': 5,
- 'kaj': 3,
- 'kcg': 3,
- 'kde': 0,
- 'kea': 0,
- 'kk': 3,
- 'kl': 3,
- 'km': 0,
- 'kn': 0,
- 'ko': 0,
- 'ksb': 3,
- 'ksh': 21,
- 'ku': 3,
- 'kw': 7,
- 'lag': 18,
- 'lb': 3,
- 'lg': 3,
- 'ln': 4,
- 'lo': 0,
- 'lt': 10,
- 'lv': 6,
- 'mas': 3,
- 'mg': 4,
- 'mk': 16,
- 'ml': 3,
- 'mn': 3,
- 'mo': 9,
- 'mr': 3,
- 'ms': 0,
- 'mt': 15,
- 'my': 0,
- 'nah': 3,
- 'naq': 7,
- 'nb': 3,
- 'nd': 3,
- 'ne': 3,
- 'nl': 3,
- 'nn': 3,
- 'no': 3,
- 'nr': 3,
- 'nso': 4,
- 'ny': 3,
- 'nyn': 3,
- 'om': 3,
- 'or': 3,
- 'pa': 3,
- 'pap': 3,
- 'pl': 13,
- 'ps': 3,
- 'pt': 3,
- 'rm': 3,
- 'ro': 9,
- 'rof': 3,
- 'ru': 11,
- 'rwk': 3,
- 'sah': 0,
- 'saq': 3,
- 'se': 7,
- 'seh': 3,
- 'ses': 0,
- 'sg': 0,
- 'sh': 11,
- 'shi': 19,
- 'sk': 12,
- 'sl': 14,
- 'sma': 7,
- 'smi': 7,
- 'smj': 7,
- 'smn': 7,
- 'sms': 7,
- 'sn': 3,
- 'so': 3,
- 'sq': 3,
- 'sr': 11,
- 'ss': 3,
- 'ssy': 3,
- 'st': 3,
- 'sv': 3,
- 'sw': 3,
- 'syr': 3,
- 'ta': 3,
- 'te': 3,
- 'teo': 3,
- 'th': 0,
- 'ti': 4,
- 'tig': 3,
- 'tk': 3,
- 'tl': 4,
- 'tn': 3,
- 'to': 0,
- 'tr': 0,
- 'ts': 3,
- 'tzm': 22,
- 'uk': 11,
- 'ur': 3,
- 've': 3,
- 'vi': 0,
- 'vun': 3,
- 'wa': 4,
- 'wae': 3,
- 'wo': 0,
- 'xh': 3,
- 'xog': 3,
- 'yo': 0,
- 'zh': 0,
- 'zu': 3
- };
-
- // utility functions for plural rules methods
- function isIn(n, list) {
- return list.indexOf(n) !== -1;
- }
- function isBetween(n, start, end) {
- return start <= n && n <= end;
- }
-
- // list of all plural rules methods:
- // map an integer to the plural form name to use
- var pluralRules = {
- '0': function() {
- return 'other';
- },
- '1': function(n) {
- if ((isBetween((n % 100), 3, 10))) {
- return 'few';
- }
- if (n === 0) {
- return 'zero';
- }
- if ((isBetween((n % 100), 11, 99))) {
- return 'many';
- }
- if (n === 2) {
- return 'two';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '2': function(n) {
- if (n !== 0 && (n % 10) === 0) {
- return 'many';
- }
- if (n === 2) {
- return 'two';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '3': function(n) {
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '4': function(n) {
- if ((isBetween(n, 0, 1))) {
- return 'one';
- }
- return 'other';
- },
- '5': function(n) {
- if ((isBetween(n, 0, 2)) && n !== 2) {
- return 'one';
- }
- return 'other';
- },
- '6': function(n) {
- if (n === 0) {
- return 'zero';
- }
- if ((n % 10) === 1 && (n % 100) !== 11) {
- return 'one';
- }
- return 'other';
- },
- '7': function(n) {
- if (n === 2) {
- return 'two';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '8': function(n) {
- if ((isBetween(n, 3, 6))) {
- return 'few';
- }
- if ((isBetween(n, 7, 10))) {
- return 'many';
- }
- if (n === 2) {
- return 'two';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '9': function(n) {
- if (n === 0 || n !== 1 && (isBetween((n % 100), 1, 19))) {
- return 'few';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '10': function(n) {
- if ((isBetween((n % 10), 2, 9)) && !(isBetween((n % 100), 11, 19))) {
- return 'few';
- }
- if ((n % 10) === 1 && !(isBetween((n % 100), 11, 19))) {
- return 'one';
- }
- return 'other';
- },
- '11': function(n) {
- if ((isBetween((n % 10), 2, 4)) && !(isBetween((n % 100), 12, 14))) {
- return 'few';
- }
- if ((n % 10) === 0 ||
- (isBetween((n % 10), 5, 9)) ||
- (isBetween((n % 100), 11, 14))) {
- return 'many';
- }
- if ((n % 10) === 1 && (n % 100) !== 11) {
- return 'one';
- }
- return 'other';
- },
- '12': function(n) {
- if ((isBetween(n, 2, 4))) {
- return 'few';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '13': function(n) {
- if ((isBetween((n % 10), 2, 4)) && !(isBetween((n % 100), 12, 14))) {
- return 'few';
- }
- if (n !== 1 && (isBetween((n % 10), 0, 1)) ||
- (isBetween((n % 10), 5, 9)) ||
- (isBetween((n % 100), 12, 14))) {
- return 'many';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '14': function(n) {
- if ((isBetween((n % 100), 3, 4))) {
- return 'few';
- }
- if ((n % 100) === 2) {
- return 'two';
- }
- if ((n % 100) === 1) {
- return 'one';
- }
- return 'other';
- },
- '15': function(n) {
- if (n === 0 || (isBetween((n % 100), 2, 10))) {
- return 'few';
- }
- if ((isBetween((n % 100), 11, 19))) {
- return 'many';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '16': function(n) {
- if ((n % 10) === 1 && n !== 11) {
- return 'one';
- }
- return 'other';
- },
- '17': function(n) {
- if (n === 3) {
- return 'few';
- }
- if (n === 0) {
- return 'zero';
- }
- if (n === 6) {
- return 'many';
- }
- if (n === 2) {
- return 'two';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '18': function(n) {
- if (n === 0) {
- return 'zero';
- }
- if ((isBetween(n, 0, 2)) && n !== 0 && n !== 2) {
- return 'one';
- }
- return 'other';
- },
- '19': function(n) {
- if ((isBetween(n, 2, 10))) {
- return 'few';
- }
- if ((isBetween(n, 0, 1))) {
- return 'one';
- }
- return 'other';
- },
- '20': function(n) {
- if ((isBetween((n % 10), 3, 4) || ((n % 10) === 9)) && !(
- isBetween((n % 100), 10, 19) ||
- isBetween((n % 100), 70, 79) ||
- isBetween((n % 100), 90, 99)
- )) {
- return 'few';
- }
- if ((n % 1000000) === 0 && n !== 0) {
- return 'many';
- }
- if ((n % 10) === 2 && !isIn((n % 100), [12, 72, 92])) {
- return 'two';
- }
- if ((n % 10) === 1 && !isIn((n % 100), [11, 71, 91])) {
- return 'one';
- }
- return 'other';
- },
- '21': function(n) {
- if (n === 0) {
- return 'zero';
- }
- if (n === 1) {
- return 'one';
- }
- return 'other';
- },
- '22': function(n) {
- if ((isBetween(n, 0, 1)) || (isBetween(n, 11, 99))) {
- return 'one';
- }
- return 'other';
- },
- '23': function(n) {
- if ((isBetween((n % 10), 1, 2)) || (n % 20) === 0) {
- return 'one';
- }
- return 'other';
- },
- '24': function(n) {
- if ((isBetween(n, 3, 10) || isBetween(n, 13, 19))) {
- return 'few';
- }
- if (isIn(n, [2, 12])) {
- return 'two';
- }
- if (isIn(n, [1, 11])) {
- return 'one';
- }
- return 'other';
- }
- };
-
- // return a function that gives the plural form name for a given integer
- var index = locales2rules[lang.replace(/-.*$/, '')];
- if (!(index in pluralRules)) {
- return function() { return 'other'; };
- }
- return pluralRules[index];
- }
-
-
-
-
- var nestedProps = ['style', 'dataset'];
-
- var parsePatterns;
-
- function parse(ctx, source) {
- var ast = {};
-
- if (!parsePatterns) {
- parsePatterns = {
- comment: /^\s*#|^\s*$/,
- entity: /^([^=\s]+)\s*=\s*(.+)$/,
- multiline: /[^\\]\\$/,
- macro: /\{\[\s*(\w+)\(([^\)]*)\)\s*\]\}/i,
- unicode: /\\u([0-9a-fA-F]{1,4})/g,
- entries: /[\r\n]+/,
- controlChars: /\\([\\\n\r\t\b\f\{\}\"\'])/g
- };
- }
-
- var entries = source.split(parsePatterns.entries);
- for (var i = 0; i < entries.length; i++) {
- var line = entries[i];
-
- if (parsePatterns.comment.test(line)) {
- continue;
- }
-
- while (parsePatterns.multiline.test(line) && i < entries.length) {
- line = line.slice(0, -1) + entries[++i].trim();
- }
-
- var entityMatch = line.match(parsePatterns.entity);
- if (entityMatch) {
- try {
- parseEntity(entityMatch[1], entityMatch[2], ast);
- } catch (e) {
- if (ctx) {
- ctx._emitter.emit('error', e);
- } else {
- throw e;
- }
- }
- }
- }
- return ast;
- }
-
- function setEntityValue(id, attr, key, value, ast) {
- var obj = ast;
- var prop = id;
-
- if (attr) {
- if (!(id in obj)) {
- obj[id] = {};
- }
- if (typeof(obj[id]) === 'string') {
- obj[id] = {'_': obj[id]};
- }
- obj = obj[id];
- prop = attr;
- }
-
- if (!key) {
- obj[prop] = value;
- return;
- }
-
- if (!(prop in obj)) {
- obj[prop] = {'_': {}};
- } else if (typeof(obj[prop]) === 'string') {
- obj[prop] = {'_index': parseMacro(obj[prop]), '_': {}};
- }
- obj[prop]._[key] = value;
- }
-
- function parseEntity(id, value, ast) {
- var name, key;
-
- var pos = id.indexOf('[');
- if (pos !== -1) {
- name = id.substr(0, pos);
- key = id.substring(pos + 1, id.length - 1);
- } else {
- name = id;
- key = null;
- }
-
- var nameElements = name.split('.');
-
- var attr;
- if (nameElements.length > 1) {
- var attrElements = [];
- attrElements.push(nameElements.pop());
- if (nameElements.length > 1) {
- // Usually the last dot separates an attribute from an id
- //
- // In case when there are more than one dot in the id
- // and the second to last item is "style" or "dataset" then the last two
- // items are becoming the attribute.
- //
- // ex.
- // id.style.color = foo =>
- //
- // id:
- // style.color: foo
- //
- // id.other.color = foo =>
- //
- // id.other:
- // color: foo
- if (nestedProps.indexOf(nameElements[nameElements.length - 1]) !== -1) {
- attrElements.push(nameElements.pop());
- }
- }
- name = nameElements.join('.');
- attr = attrElements.reverse().join('.');
- } else {
- attr = null;
- }
-
- setEntityValue(name, attr, key, unescapeString(value), ast);
- }
-
- function unescapeControlCharacters(str) {
- return str.replace(parsePatterns.controlChars, '$1');
- }
-
- function unescapeUnicode(str) {
- return str.replace(parsePatterns.unicode, function(match, token) {
- return unescape('%u' + '0000'.slice(token.length) + token);
- });
- }
-
- function unescapeString(str) {
- if (str.lastIndexOf('\\') !== -1) {
- str = unescapeControlCharacters(str);
- }
- return unescapeUnicode(str);
- }
-
- function parseMacro(str) {
- var match = str.match(parsePatterns.macro);
- if (!match) {
- throw new L10nError('Malformed macro');
- }
- return [match[1], match[2]];
- }
-
-
-
- var MAX_PLACEABLE_LENGTH = 2500;
- var MAX_PLACEABLES = 100;
- var rePlaceables = /\{\{\s*(.+?)\s*\}\}/g;
-
- function Entity(id, node, env) {
- this.id = id;
- this.env = env;
- // the dirty guard prevents cyclic or recursive references from other
- // Entities; see Entity.prototype.resolve
- this.dirty = false;
- if (typeof node === 'string') {
- this.value = node;
- } else {
- // it's either a hash or it has attrs, or both
- for (var key in node) {
- if (node.hasOwnProperty(key) && key[0] !== '_') {
- if (!this.attributes) {
- this.attributes = {};
- }
- this.attributes[key] = new Entity(this.id + '.' + key, node[key],
- env);
- }
- }
- this.value = node._ || null;
- this.index = node._index;
- }
- }
-
- Entity.prototype.resolve = function E_resolve(ctxdata) {
- if (this.dirty) {
- return undefined;
- }
-
- this.dirty = true;
- var val;
- // if resolve fails, we want the exception to bubble up and stop the whole
- // resolving process; however, we still need to clean up the dirty flag
- try {
- val = resolve(ctxdata, this.env, this.value, this.index);
- } finally {
- this.dirty = false;
- }
- return val;
- };
-
- Entity.prototype.toString = function E_toString(ctxdata) {
- try {
- return this.resolve(ctxdata);
- } catch (e) {
- return undefined;
- }
- };
-
- Entity.prototype.valueOf = function E_valueOf(ctxdata) {
- if (!this.attributes) {
- return this.toString(ctxdata);
- }
-
- var entity = {
- value: this.toString(ctxdata),
- attributes: {}
- };
-
- for (var key in this.attributes) {
- if (this.attributes.hasOwnProperty(key)) {
- entity.attributes[key] = this.attributes[key].toString(ctxdata);
- }
- }
-
- return entity;
- };
-
- function subPlaceable(ctxdata, env, match, id) {
- if (ctxdata && ctxdata.hasOwnProperty(id) &&
- (typeof ctxdata[id] === 'string' ||
- (typeof ctxdata[id] === 'number' && !isNaN(ctxdata[id])))) {
- return ctxdata[id];
- }
-
- if (env.hasOwnProperty(id)) {
- if (!(env[id] instanceof Entity)) {
- env[id] = new Entity(id, env[id], env);
- }
- var value = env[id].resolve(ctxdata);
- if (typeof value === 'string') {
- // prevent Billion Laughs attacks
- if (value.length >= MAX_PLACEABLE_LENGTH) {
- throw new L10nError('Too many characters in placeable (' +
- value.length + ', max allowed is ' +
- MAX_PLACEABLE_LENGTH + ')');
- }
- return value;
- }
- }
- return match;
- }
-
- function interpolate(ctxdata, env, str) {
- var placeablesCount = 0;
- var value = str.replace(rePlaceables, function(match, id) {
- // prevent Quadratic Blowup attacks
- if (placeablesCount++ >= MAX_PLACEABLES) {
- throw new L10nError('Too many placeables (' + placeablesCount +
- ', max allowed is ' + MAX_PLACEABLES + ')');
- }
- return subPlaceable(ctxdata, env, match, id);
- });
- placeablesCount = 0;
- return value;
- }
-
- function resolve(ctxdata, env, expr, index) {
- if (typeof expr === 'string') {
- return interpolate(ctxdata, env, expr);
- }
-
- if (typeof expr === 'boolean' ||
- typeof expr === 'number' ||
- !expr) {
- return expr;
- }
-
- // otherwise, it's a dict
-
- if (index && ctxdata && ctxdata.hasOwnProperty(index[1])) {
- var argValue = ctxdata[index[1]];
-
- // special cases for zero, one, two if they are defined on the hash
- if (argValue === 0 && 'zero' in expr) {
- return resolve(ctxdata, env, expr.zero);
- }
- if (argValue === 1 && 'one' in expr) {
- return resolve(ctxdata, env, expr.one);
- }
- if (argValue === 2 && 'two' in expr) {
- return resolve(ctxdata, env, expr.two);
- }
-
- var selector = env.__plural(argValue);
- if (expr.hasOwnProperty(selector)) {
- return resolve(ctxdata, env, expr[selector]);
- }
- }
-
- // if there was no index or no selector was found, try 'other'
- if ('other' in expr) {
- return resolve(ctxdata, env, expr.other);
- }
-
- return undefined;
- }
-
- function compile(env, ast) {
- env = env || {};
- for (var id in ast) {
- if (ast.hasOwnProperty(id)) {
- env[id] = new Entity(id, ast[id], env);
- }
- }
- return env;
- }
-
-
-
- function Locale(id, ctx) {
- this.id = id;
- this.ctx = ctx;
- this.isReady = false;
- this.entries = {
- __plural: getPluralRule(id)
- };
- }
-
- Locale.prototype.getEntry = function L_getEntry(id) {
- /* jshint -W093 */
-
- var entries = this.entries;
-
- if (!entries.hasOwnProperty(id)) {
- return undefined;
- }
-
- if (entries[id] instanceof Entity) {
- return entries[id];
- }
-
- return entries[id] = new Entity(id, entries[id], entries);
- };
-
- Locale.prototype.build = function L_build(callback) {
- var sync = !callback;
- var ctx = this.ctx;
- var self = this;
-
- var l10nLoads = ctx.resLinks.length;
-
- function onL10nLoaded(err) {
- if (err) {
- ctx._emitter.emit('error', err);
- }
- if (--l10nLoads <= 0) {
- self.isReady = true;
- if (callback) {
- callback();
- }
- }
- }
-
- if (l10nLoads === 0) {
- onL10nLoaded();
- return;
- }
-
- function onJSONLoaded(err, json) {
- if (!err && json) {
- self.addAST(json);
- }
- onL10nLoaded(err);
- }
-
- function onPropLoaded(err, source) {
- if (!err && source) {
- var ast = parse(ctx, source);
- self.addAST(ast);
- }
- onL10nLoaded(err);
- }
-
-
- for (var i = 0; i < ctx.resLinks.length; i++) {
- var path = ctx.resLinks[i].replace('{{locale}}', this.id);
- var type = path.substr(path.lastIndexOf('.') + 1);
-
- switch (type) {
- case 'json':
- io.loadJSON(path, onJSONLoaded, sync);
- break;
- case 'properties':
- io.load(path, onPropLoaded, sync);
- break;
- }
- }
- };
-
- Locale.prototype.addAST = function(ast) {
- for (var id in ast) {
- if (ast.hasOwnProperty(id)) {
- this.entries[id] = ast[id];
- }
- }
- };
-
- Locale.prototype.getEntity = function(id, ctxdata) {
- var entry = this.getEntry(id);
-
- if (!entry) {
- return null;
- }
- return entry.valueOf(ctxdata);
- };
-
-
-
- function Context(id) {
-
- this.id = id;
- this.isReady = false;
- this.isLoading = false;
-
- this.supportedLocales = [];
- this.resLinks = [];
- this.locales = {};
-
- this._emitter = new EventEmitter();
-
-
- // Getting translations
-
- function getWithFallback(id) {
- /* jshint -W084 */
-
- if (!this.isReady) {
- throw new L10nError('Context not ready');
- }
-
- var cur = 0;
- var loc;
- var locale;
- while (loc = this.supportedLocales[cur]) {
- locale = this.getLocale(loc);
- if (!locale.isReady) {
- // build without callback, synchronously
- locale.build(null);
- }
- var entry = locale.getEntry(id);
- if (entry === undefined) {
- cur++;
- warning.call(this, new L10nError(id + ' not found in ' + loc, id,
- loc));
- continue;
- }
- return entry;
- }
-
- error.call(this, new L10nError(id + ' not found', id));
- return null;
- }
-
- this.get = function get(id, ctxdata) {
- var entry = getWithFallback.call(this, id);
- if (entry === null) {
- return '';
- }
-
- return entry.toString(ctxdata) || '';
- };
-
- this.getEntity = function getEntity(id, ctxdata) {
- var entry = getWithFallback.call(this, id);
- if (entry === null) {
- return null;
- }
-
- return entry.valueOf(ctxdata);
- };
-
-
- // Helpers
-
- this.getLocale = function getLocale(code) {
- /* jshint -W093 */
-
- var locales = this.locales;
- if (locales[code]) {
- return locales[code];
- }
-
- return locales[code] = new Locale(code, this);
- };
-
-
- // Getting ready
-
- function negotiate(available, requested, defaultLocale) {
- if (available.indexOf(requested[0]) === -1 ||
- requested[0] === defaultLocale) {
- return [defaultLocale];
- } else {
- return [requested[0], defaultLocale];
- }
- }
-
- function freeze(supported) {
- var locale = this.getLocale(supported[0]);
- if (locale.isReady) {
- setReady.call(this, supported);
- } else {
- locale.build(setReady.bind(this, supported));
- }
- }
-
- function setReady(supported) {
- this.supportedLocales = supported;
- this.isReady = true;
- this._emitter.emit('ready');
- }
-
- this.requestLocales = function requestLocales() {
- if (this.isLoading && !this.isReady) {
- throw new L10nError('Context not ready');
- }
-
- this.isLoading = true;
- var requested = Array.prototype.slice.call(arguments);
-
- var supported = negotiate(requested.concat('en-US'), requested, 'en-US');
- freeze.call(this, supported);
- };
-
-
- // Events
-
- this.addEventListener = function addEventListener(type, listener) {
- this._emitter.addEventListener(type, listener);
- };
-
- this.removeEventListener = function removeEventListener(type, listener) {
- this._emitter.removeEventListener(type, listener);
- };
-
- this.ready = function ready(callback) {
- if (this.isReady) {
- setTimeout(callback);
- }
- this.addEventListener('ready', callback);
- };
-
- this.once = function once(callback) {
- /* jshint -W068 */
- if (this.isReady) {
- setTimeout(callback);
- return;
- }
-
- var callAndRemove = (function() {
- this.removeEventListener('ready', callAndRemove);
- callback();
- }).bind(this);
- this.addEventListener('ready', callAndRemove);
- };
-
-
- // Errors
-
- function warning(e) {
- this._emitter.emit('warning', e);
- return e;
- }
-
- function error(e) {
- this._emitter.emit('error', e);
- return e;
- }
- }
-
-
- /* jshint -W104 */
-
- var DEBUG = false;
- var isPretranslated = false;
- var rtlList = ['ar', 'he', 'fa', 'ps', 'qps-plocm', 'ur'];
-
- // Public API
-
- navigator.mozL10n = {
- ctx: new Context(),
- get: function get(id, ctxdata) {
- return navigator.mozL10n.ctx.get(id, ctxdata);
- },
- localize: function localize(element, id, args) {
- return localizeElement.call(navigator.mozL10n, element, id, args);
- },
- translate: function translate(element) {
- return translateFragment.call(navigator.mozL10n, element);
- },
- ready: function ready(callback) {
- return navigator.mozL10n.ctx.ready(callback);
- },
- once: function once(callback) {
- return navigator.mozL10n.ctx.once(callback);
- },
- get readyState() {
- return navigator.mozL10n.ctx.isReady ? 'complete' : 'loading';
- },
- language: {
- set code(lang) {
- navigator.mozL10n.ctx.requestLocales(lang);
- },
- get code() {
- return navigator.mozL10n.ctx.supportedLocales[0];
- },
- get direction() {
- return getDirection(navigator.mozL10n.ctx.supportedLocales[0]);
- }
- },
- _getInternalAPI: function() {
- return {
- Error: L10nError,
- Context: Context,
- Locale: Locale,
- Entity: Entity,
- getPluralRule: getPluralRule,
- rePlaceables: rePlaceables,
- getTranslatableChildren: getTranslatableChildren,
- getL10nAttributes: getL10nAttributes,
- loadINI: loadINI,
- fireLocalizedEvent: fireLocalizedEvent,
- parse: parse,
- compile: compile
- };
- }
- };
-
- navigator.mozL10n.ctx.ready(onReady.bind(navigator.mozL10n));
-
- if (DEBUG) {
- navigator.mozL10n.ctx.addEventListener('error', console.error);
- navigator.mozL10n.ctx.addEventListener('warning', console.warn);
- }
-
- function getDirection(lang) {
- return (rtlList.indexOf(lang) >= 0) ? 'rtl' : 'ltr';
- }
-
- var readyStates = {
- 'loading': 0,
- 'interactive': 1,
- 'complete': 2
- };
-
- function waitFor(state, callback) {
- state = readyStates[state];
- if (readyStates[document.readyState] >= state) {
- callback();
- return;
- }
-
- document.addEventListener('readystatechange', function l10n_onrsc() {
- if (readyStates[document.readyState] >= state) {
- document.removeEventListener('readystatechange', l10n_onrsc);
- callback();
- }
- });
- }
-
- if (window.document) {
- isPretranslated = (document.documentElement.lang === navigator.language);
-
- // this is a special case for netError bug; see https://bugzil.la/444165
- if (document.documentElement.dataset.noCompleteBug) {
- pretranslate.call(navigator.mozL10n);
- return;
- }
-
-
- if (isPretranslated) {
- waitFor('interactive', function() {
- window.setTimeout(initResources.bind(navigator.mozL10n));
- });
- } else {
- if (document.readyState === 'complete') {
- window.setTimeout(initResources.bind(navigator.mozL10n));
- } else {
- waitFor('interactive', pretranslate.bind(navigator.mozL10n));
- }
- }
-
- }
-
- function pretranslate() {
- /* jshint -W068 */
- if (inlineLocalization.call(this)) {
- waitFor('interactive', (function() {
- window.setTimeout(initResources.bind(this));
- }).bind(this));
- } else {
- initResources.call(this);
- }
- }
-
- function inlineLocalization() {
- var script = document.documentElement
- .querySelector('script[type="application/l10n"]' +
- '[lang="' + navigator.language + '"]');
- if (!script) {
- return false;
- }
-
- var locale = this.ctx.getLocale(navigator.language);
- // the inline localization is happenning very early, when the ctx is not
- // yet ready and when the resources haven't been downloaded yet; add the
- // inlined JSON directly to the current locale
- locale.addAST(JSON.parse(script.innerHTML));
- // localize the visible DOM
- var l10n = {
- ctx: locale,
- language: {
- code: locale.id,
- direction: getDirection(locale.id)
- }
- };
- translateFragment.call(l10n);
- // the visible DOM is now pretranslated
- isPretranslated = true;
- return true;
- }
-
- function initResources() {
- var resLinks = document.head
- .querySelectorAll('link[type="application/l10n"]');
- var iniLinks = [];
- var i;
-
- for (i = 0; i < resLinks.length; i++) {
- var link = resLinks[i];
- var url = link.getAttribute('href');
- var type = url.substr(url.lastIndexOf('.') + 1);
- if (type === 'ini') {
- iniLinks.push(url);
- }
- this.ctx.resLinks.push(url);
- }
-
- var iniLoads = iniLinks.length;
- if (iniLoads === 0) {
- initLocale.call(this);
- return;
- }
-
- function onIniLoaded(err) {
- if (err) {
- this.ctx._emitter.emit('error', err);
- }
- if (--iniLoads === 0) {
- initLocale.call(this);
- }
- }
-
- for (i = 0; i < iniLinks.length; i++) {
- loadINI.call(this, iniLinks[i], onIniLoaded.bind(this));
- }
- }
-
- function initLocale() {
- this.ctx.requestLocales(navigator.language);
- window.addEventListener('languagechange', function l10n_langchange() {
- navigator.mozL10n.language.code = navigator.language;
- });
- }
-
- function onReady() {
- if (!isPretranslated) {
- this.translate();
- }
- isPretranslated = false;
-
- fireLocalizedEvent.call(this);
- }
-
- function fireLocalizedEvent() {
- var event = new CustomEvent('localized', {
- 'bubbles': false,
- 'cancelable': false,
- 'detail': {
- 'language': this.ctx.supportedLocales[0]
- }
- });
- window.dispatchEvent(event);
- }
-
- /* jshint -W104 */
-
- function loadINI(url, callback) {
- var ctx = this.ctx;
- io.load(url, function(err, source) {
- var pos = ctx.resLinks.indexOf(url);
-
- if (err) {
- // remove the ini link from resLinks
- ctx.resLinks.splice(pos, 1);
- return callback(err);
- }
-
- if (!source) {
- ctx.resLinks.splice(pos, 1);
- return callback(new Error('Empty file: ' + url));
- }
-
- var patterns = parseINI(source, url).resources.map(function(x) {
- return x.replace('en-US', '{{locale}}');
- });
- ctx.resLinks.splice.apply(ctx.resLinks, [pos, 1].concat(patterns));
- callback();
- });
- }
-
- function relativePath(baseUrl, url) {
- if (url[0] === '/') {
- return url;
- }
-
- var dirs = baseUrl.split('/')
- .slice(0, -1)
- .concat(url.split('/'))
- .filter(function(path) {
- return path !== '.';
- });
-
- return dirs.join('/');
- }
-
- var iniPatterns = {
- 'section': /^\s*\[(.*)\]\s*$/,
- 'import': /^\s*@import\s+url\((.*)\)\s*$/i,
- 'entry': /[\r\n]+/
- };
-
- function parseINI(source, iniPath) {
- var entries = source.split(iniPatterns.entry);
- var locales = ['en-US'];
- var genericSection = true;
- var uris = [];
- var match;
-
- for (var i = 0; i < entries.length; i++) {
- var line = entries[i];
- // we only care about en-US resources
- if (genericSection && iniPatterns['import'].test(line)) {
- match = iniPatterns['import'].exec(line);
- var uri = relativePath(iniPath, match[1]);
- uris.push(uri);
- continue;
- }
-
- // but we need the list of all locales in the ini, too
- if (iniPatterns.section.test(line)) {
- genericSection = false;
- match = iniPatterns.section.exec(line);
- locales.push(match[1]);
- }
- }
- return {
- locales: locales,
- resources: uris
- };
- }
-
- /* jshint -W104 */
-
- function translateFragment(element) {
- if (!element) {
- element = document.documentElement;
- document.documentElement.lang = this.language.code;
- document.documentElement.dir = this.language.direction;
- }
- translateElement.call(this, element);
-
- var nodes = getTranslatableChildren(element);
- for (var i = 0; i < nodes.length; i++ ) {
- translateElement.call(this, nodes[i]);
- }
- }
-
- function getTranslatableChildren(element) {
- return element ? element.querySelectorAll('*[data-l10n-id]') : [];
- }
-
- function localizeElement(element, id, args) {
- if (!element) {
- return;
- }
-
- if (!id) {
- element.removeAttribute('data-l10n-id');
- element.removeAttribute('data-l10n-args');
- setTextContent(element, '');
- return;
- }
-
- element.setAttribute('data-l10n-id', id);
- if (args && typeof args === 'object') {
- element.setAttribute('data-l10n-args', JSON.stringify(args));
- } else {
- element.removeAttribute('data-l10n-args');
- }
-
- if (this.ctx.isReady) {
- translateElement.call(this, element);
- }
- }
-
- function getL10nAttributes(element) {
- if (!element) {
- return {};
- }
-
- var l10nId = element.getAttribute('data-l10n-id');
- var l10nArgs = element.getAttribute('data-l10n-args');
-
- var args = l10nArgs ? JSON.parse(l10nArgs) : null;
-
- return {id: l10nId, args: args};
- }
-
-
-
- function translateElement(element) {
- var l10n = getL10nAttributes(element);
-
- if (!l10n.id) {
- return;
- }
-
- var entity = this.ctx.getEntity(l10n.id, l10n.args);
-
- if (!entity) {
- return;
- }
-
- if (typeof entity === 'string') {
- setTextContent(element, entity);
- return true;
- }
-
- if (entity.value) {
- setTextContent(element, entity.value);
- }
-
- for (var key in entity.attributes) {
- if (entity.attributes.hasOwnProperty(key)) {
- var attr = entity.attributes[key];
- var pos = key.indexOf('.');
- if (pos !== -1) {
- element[key.substr(0, pos)][key.substr(pos + 1)] = attr;
- } else if (key === 'ariaLabel') {
- element.setAttribute('aria-label', attr);
- } else {
- element[key] = attr;
- }
- }
- }
-
- return true;
- }
-
- function setTextContent(element, text) {
- // standard case: no element children
- if (!element.firstElementChild) {
- element.textContent = text;
- return;
- }
-
- // this element has element children: replace the content of the first
- // (non-blank) child textNode and clear other child textNodes
- var found = false;
- var reNotBlank = /\S/;
- for (var child = element.firstChild; child; child = child.nextSibling) {
- if (child.nodeType === Node.TEXT_NODE &&
- reNotBlank.test(child.nodeValue)) {
- if (found) {
- child.nodeValue = '';
- } else {
- child.nodeValue = text;
- found = true;
- }
- }
- }
- // if no (non-empty) textNode is found, insert a textNode before the
- // element's first child.
- if (!found) {
- element.insertBefore(document.createTextNode(text), element.firstChild);
- }
- }
-
-})(this);
-
diff --git a/src/js/menus.js b/src/js/menus.js
index af12900..ebcba28 100644
--- a/src/js/menus.js
+++ b/src/js/menus.js
@@ -30,7 +30,32 @@ const entryMenu = {
]
};
+const moreMenu = {
+ items: [
+ {
+ name: 'Delete',
+ action() {
+ let files = store.getState().get('files');
+ let active = store.getState().get('activeFile');
+
+ let description;
+ if (active.length) {
+ const count = active.length;
+ description = `Are you sure you want to remove ${count} files?`;
+ } else {
+ const name = files[active].name;
+ description = `Are you sure you want to remove ${name}?`;
+ }
+
+ store.dispatch(hideAll());
+ store.dispatch(show('deleteDialog', {description}));
+ }
+ }
+ ]
+}
+
export default {
fileMenu: Object.assign({}, entryMenu),
- directoryMenu: Object.assign({}, entryMenu)
+ directoryMenu: Object.assign({}, entryMenu),
+ moreMenu
}
diff --git a/src/js/reducers/active-file.js b/src/js/reducers/active-file.js
index d3a4f4b..0c7fc89 100644
--- a/src/js/reducers/active-file.js
+++ b/src/js/reducers/active-file.js
@@ -1,6 +1,6 @@
import { ACTIVE_FILE } from 'actions/types';
-export default function(state = -1, action) {
+export default function(state = null, action) {
if (action.type === ACTIVE_FILE) {
return action.file;
}
diff --git a/src/js/reducers/all.js b/src/js/reducers/all.js
index 41397a1..e6d231c 100644
--- a/src/js/reducers/all.js
+++ b/src/js/reducers/all.js
@@ -7,6 +7,7 @@ import activeFile from './active-file';
import menu from './menu';
import dialog from './dialog';
import settings from './settings';
+import selectView from './select-view';
export default function(state = new Immutable.Map(), action) {
console.log('action', action);
@@ -14,14 +15,16 @@ 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),
+ selectView: selectView(state.get('selectView'), action),
activeFile: activeFile(state.get('activeFile'), action),
navigation: navigation(state.get('navigation'), action),
settings: settings(state.get('settings'), action),
fileMenu: menu(state, action, 'fileMenu'),
directoryMenu: menu(state, action, 'directoryMenu'),
+ moreMenu: menu(state, action, 'moreMenu'),
renameDialog: dialog(state, action, 'renameDialog'),
deleteDialog: dialog(state, action, 'deleteDialog'),
errorDialog: dialog(state, action, 'errorDialog'),
- createDialog: dialog(state, action, 'createDialog')
+ createDialog: dialog(state, action, 'createDialog'),
});
}
diff --git a/src/js/reducers/files.js b/src/js/reducers/files.js
index 64f89e2..dae28bd 100644
--- a/src/js/reducers/files.js
+++ b/src/js/reducers/files.js
@@ -1,14 +1,30 @@
import { LIST_FILES, RENAME_FILE, DELETE_FILE, CREATE_FILE } from 'actions/types';
import { refresh } from 'actions/files-view';
-import { move, sdcard, createFile, createDirectory } from 'api/files';
+import { move, remove, sdcard, createFile, createDirectory } from 'api/files';
import { show } from 'actions/dialog';
import store, { bind } from 'store';
-import { reportError } from 'utils';
+import { reportError, type } from 'utils';
let boundRefresh = bind(refresh());
export default function(state = [], action) {
if (action.type === LIST_FILES) {
+
+ let settings = store.getState().get('settings');
+
+ if (settings.showDirectoriesFirst) {
+ action.files = action.files.sort((a, b) => {
+ if (type(a) === 'Directory') return -1;
+ if (type(a) === 'File') return 1;
+ });
+ }
+
+ if (!settings.showHiddenFiles) {
+ action.files = action.files.filter(file => {
+ return file.name[0] !== '.';
+ })
+ }
+
return action.files;
}
@@ -28,13 +44,26 @@ export default function(state = [], action) {
}
if (action.type === DELETE_FILE) {
- let file = state[action.file];
-
- sdcard().delete((file.path || '') + '/' + file.name);
let copy = state.slice(0);
- copy.splice(action.file, 1);
+
+ 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;
}
return state;
}
+
+function del(state, index) {
+ let file = state[index];
+ return remove((file.path || '') + '/' + file.name).catch(reportError);
+}
diff --git a/src/js/reducers/select-view.js b/src/js/reducers/select-view.js
new file mode 100644
index 0000000..0d719db
--- /dev/null
+++ b/src/js/reducers/select-view.js
@@ -0,0 +1,9 @@
+import { SELECT_VIEW } from 'actions/types';
+
+export default function(state = false, action) {
+ if (action.type === SELECT_VIEW) {
+ return action.active === 'toggle' ? !state : action.active;
+ }
+
+ return state;
+}
diff --git a/src/js/utils.js b/src/js/utils.js
index 1349914..4c7a585 100644
--- a/src/js/utils.js
+++ b/src/js/utils.js
@@ -37,11 +37,9 @@ const sizes = {
'B': -1
}
export function humanSize(size) {
- console.log(size);
for (let key in sizes) {
let value = sizes[key];
- console.log(value);
if (size > value) {
return Math.round(size / value) + key;
}
diff --git a/src/less/components/navigation.less b/src/less/components/navigation.less
index 29d8e5b..5d88f93 100644
--- a/src/less/components/navigation.less
+++ b/src/less/components/navigation.less
@@ -52,39 +52,6 @@ nav {
padding-bottom: 0;
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 {
diff --git a/src/less/icons.less b/src/less/icons.less
index 2d44909..fb69cac 100644
--- a/src/less/icons.less
+++ b/src/less/icons.less
@@ -37,11 +37,11 @@
height: 28px;
}
-.icon-share {
+.icon-select {
.icon;
- background: url(/img/Share.svg) no-repeat;
- width: 25px;
- height: 27px;
+ background: url(/img/Select.svg) no-repeat;
+ width: 32px;
+ height: 34px;
}
.icon-more {
diff --git a/src/less/styles/forms.less b/src/less/styles/forms.less
index 6e5eea5..08230bf 100644
--- a/src/less/styles/forms.less
+++ b/src/less/styles/forms.less
@@ -14,27 +14,35 @@ input {
.light-medium;
}
-input[type="checkbox"] {
- width: 0;
- height: 0;
-}
+label {
+ clear: left;
-input[type="checkbox"]::before {
- content: '';
- display: block;
+ &::after {
+ content: '';
+ display: block;
- border: 1px solid @gray;
+ float: right;
- background: transparent;
+ margin-right: 13px;
- border-radius: 50%;
+ border-radius: 50%;
- width: 10px;
- height: 10px;
+ width: 10px;
+ height: 10px;
- box-sizing: border-box;
+ background: transparent;
- &:checked {
- background: @blue;
+ border: 1px solid @overlay;
}
}
+
+input[type='checkbox'] {
+ clear: right;
+ float: right;
+
+ display: none;
+}
+
+input:checked + label::after {
+ background: @blue;
+}
diff --git a/src/manifest.webapp b/src/manifest.webapp
index bfa7f4f..eb4152c 100644
--- a/src/manifest.webapp
+++ b/src/manifest.webapp
@@ -4,10 +4,10 @@
"description": "Keep an eye on your files with a full-featured file-manager",
"launch_path": "/index.html",
"icons": {
- "16": "/img/icons/icon16x16.png",
- "48": "/img/icons/icon48x48.png",
- "60": "/img/icons/icon60x60.png",
- "128": "/img/icons/icon128x128.png"
+ "16": "/icon/Icon-16.png",
+ "48": "/icon/Icon-48.png",
+ "60": "/icon/Icon-60.png",
+ "128": "/icon/Icon-128.png"
},
"developer": {
"name": "Mahdi Dibaiee",