feat setup: Setup Redux, Immutable.js and React

feat FileList: Implement File List + changedir action
This commit is contained in:
Mahdi Dibaiee
2015-08-31 11:19:22 +04:30
parent 86113d017d
commit ee6f5d6ffb
32 changed files with 8558 additions and 1755 deletions

View File

@ -1,3 +0,0 @@
app_title = Privileged empty app
app_description.innerHTML = This app is empty. Fill it with your own stuff!
message = Hello world

View File

@ -1,3 +0,0 @@
app_title = Aplicación vacía privilegiada
app_description.innerHTML = Esta aplicación está vacía. ¡Lista para que añadas tu código!
message = ¡Hola, mundo!

View File

@ -1,5 +0,0 @@
@import url(en-US.properties)
[es]
@import url(es.properties)

13
src/index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hawk</title>
<meta name="viewport" content="width=device-width">
</head>
<body>
<div id='wrapper'></div>
<script src='main.js'></script>
</body>
</html>

View File

@ -0,0 +1,8 @@
import { CHANGE_DIRECTORY } from 'actions/types';
export default function changedir(dir) {
return {
type: CHANGE_DIRECTORY,
dir
};
}

View File

@ -0,0 +1,8 @@
import { LIST_FILES } from 'actions/types';
export default function listFiles(files) {
return {
type: LIST_FILES,
files
};
}

9
src/js/actions/types.js Normal file
View File

@ -0,0 +1,9 @@
const TYPES = {
CHANGE_DIRECTORY: Symbol(),
LIST_FILES: Symbol(),
SORT: Symbol(),
SEARCH: Symbol(),
REFRESH: Symbol()
};
export default TYPES;

13
src/js/api/files.js Normal file
View File

@ -0,0 +1,13 @@
export async function directory(dir = '/') {
let storage = navigator.getDeviceStorage('sdcard');
let root = await storage.getRoot();
if (dir === '/' || !dir) return root;
return await root.get(dir);
}
export async function children(dir) {
let parent = await directory(dir);
return await parent.getFilesAndDirectories();
}

View File

@ -0,0 +1,38 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import File from './file';
@connect(props)
export default class FileList extends Component {
constructor() {
super();
}
render() {
let { cwd, files } = this.props;
let els = files.map((file, index) => {
return <File key={index} index={index} name={file.name} />;
});
return (
<div><strong>cwd: {cwd}</strong>
{els}
</div>
);
}
}
function props(state) {
return {
cwd: state.get('cwd'),
files: state.get('files')
}
}
async function getFiles(dir) {
let storage = navigator.getDeviceStorage('sdcard');
let root = await storage.get(dir);
return await root.getFilesAndDirectories();
}

20
src/js/components/file.js Normal file
View File

@ -0,0 +1,20 @@
import React, { Component } from 'react';
import store from 'store';
import changedir from 'actions/changedir';
export default class File extends Component {
render() {
return (
<div onClick={this.peekInside.bind(this)}>
<p>{this.props.index}. {this.props.name}</p>
</div>
);
}
peekInside() {
let file = store.getState().get('files')[this.props.index];
console.log(file);
store.dispatch(changedir(file.path.slice(1) + file.name));
}
}

View File

@ -1,5 +1,18 @@
export default React.createClass({
import React, { Component } from 'react'
import FileList from 'components/file-list';
import changedir from 'actions/changedir';
import store from 'store';
window.store = store;
window.changedir = changedir;
export default class Root extends Component {
render() {
return <div></div>;
return (
<div>
Hawk!
<FileList />
</div>
);
}
});
}

View File

@ -1,2 +1,7 @@
import Root from 'components/root'
let x = "I'm just testing";
import React from 'react';
import Root from 'components/root';
import store from 'store';
import { Provider } from 'react-redux';
let wrapper = document.getElementById('wrapper');
React.render(<Provider store={store}>{() => <Root />}</Provider>, wrapper);

10
src/js/reducers/all.js Normal file
View File

@ -0,0 +1,10 @@
import Immutable from 'immutable';
import cwd from './cwd';
import files from './files';
export default function(state = new Immutable.Map(), action) {
return new Immutable.Map({
cwd: cwd(state.get('cwd'), action),
files: files(state.get('files'), action)
});
}

16
src/js/reducers/cwd.js Normal file
View File

@ -0,0 +1,16 @@
import { CHANGE_DIRECTORY } from 'actions/types';
import listFiles from 'actions/list-files';
import { children } from 'api/files';
import store from 'store';
export default function(state = '/', action) {
switch (action.type) {
case CHANGE_DIRECTORY:
children(action.dir).then(files => {
store.dispatch(listFiles(files));
});
return action.dir;
default:
return state;
}
}

10
src/js/reducers/files.js Normal file
View File

@ -0,0 +1,10 @@
import { LIST_FILES } from 'actions/types';
export default function(state = [], action) {
switch (action.type) {
case LIST_FILES:
return action.files;
default:
return state;
}
}

14
src/js/store.js Normal file
View File

@ -0,0 +1,14 @@
import { createStore } from 'redux';
import reducers from 'reducers/all';
import changedir from 'actions/changedir';
import Immutable from 'immutable';
const DEFAULT = new Immutable.Map({
dir: '/',
files: []
});
let store = createStore(reducers, DEFAULT);
store.dispatch(changedir(DEFAULT.dir));
export default store;

0
src/less/main.less Normal file
View File

1
src/less/variables.less Normal file
View File

@ -0,0 +1 @@
@

31
src/manifest.webapp Normal file
View File

@ -0,0 +1,31 @@
{
"version": "0.1.0",
"name": "Hawk",
"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"
},
"developer": {
"name": "Mahdi Dibaiee",
"url": "http://dibaiee.ir"
},
"type": "privileged",
"permissions": {
"device-storage:videos": {"access": "readwrite"},
"device-storage:pictures": {"access": "readwrite"},
"device-storage:music": {"access": "readwrite"},
"device-storage:sdcard": {"access": "readwrite"},
"device-storage:apps": {"access": "readwrite"},
"webapps-manage": {}
},
"installs_allowed_from": [
"*"
],
"locales": {
},
"default_locale": "en"
}