Merge branch 'feature/electron' into develop
This commit is contained in:
commit
7db3d9eb69
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ dist
|
||||
build
|
||||
nwjs
|
||||
my-profile.json
|
||||
js-compiled
|
||||
|
118
Gruntfile.js
118
Gruntfile.js
@ -1,118 +0,0 @@
|
||||
/* jshint node: true */
|
||||
var _ = require('lodash');
|
||||
var path = require('path');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
var NW_VERSION = '0.12.3';
|
||||
var BUILD_DIR = 'build';
|
||||
var BUILD_TARGETS = {
|
||||
linux_ia32: true,
|
||||
linux_x64: true,
|
||||
win: false,
|
||||
osx: false
|
||||
};
|
||||
var PKG = grunt.file.readJSON('package.json');
|
||||
var PKG_OVERWRITE = {
|
||||
window: {
|
||||
toolbar: false,
|
||||
kiosk: true
|
||||
}
|
||||
};
|
||||
|
||||
// Create build tasks options
|
||||
var buildOptions = _.merge({
|
||||
runtimeVersion: NW_VERSION
|
||||
}, BUILD_TARGETS);
|
||||
|
||||
// Define copy:build tasks files
|
||||
var appFiles = [];
|
||||
|
||||
_.forEach(BUILD_TARGETS, function(isEnabled, target) {
|
||||
|
||||
if(!isEnabled) return;
|
||||
|
||||
var arch = 'ia32';
|
||||
var platform = target;
|
||||
if(platform.indexOf('linux') !== -1) {
|
||||
arch = platform.split('_')[1];
|
||||
platform = 'linux';
|
||||
}
|
||||
var dirName = PKG.name + '-' + PKG.version + '-' + platform + '-' + arch;
|
||||
var destPath = path.join(BUILD_DIR, dirName + '/');
|
||||
|
||||
// Retreive NPM dependencies
|
||||
var npmDeps = _.keys(PKG.dependencies).map(function(moduleName) {
|
||||
return path.join('node_modules', moduleName, '**');
|
||||
});
|
||||
appFiles.push({ src: npmDeps, dest: destPath });
|
||||
|
||||
// Add main files, licence, & config
|
||||
appFiles.push({
|
||||
src: [
|
||||
'index.html',
|
||||
'package.json',
|
||||
'default-profile.json',
|
||||
'LICENCE',
|
||||
'css/**',
|
||||
'js/**',
|
||||
'img/**'
|
||||
],
|
||||
dest: destPath
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Configure tasks
|
||||
grunt.initConfig({
|
||||
|
||||
pkg: PKG,
|
||||
|
||||
download: {
|
||||
options: {
|
||||
runtimeVersion: NW_VERSION
|
||||
}
|
||||
},
|
||||
|
||||
run: {
|
||||
options: {
|
||||
nwArgs: ['.'].concat(process.argv.slice(3)),
|
||||
runtimeVersion: NW_VERSION
|
||||
}
|
||||
},
|
||||
|
||||
build: {
|
||||
options: buildOptions
|
||||
},
|
||||
|
||||
clean: {
|
||||
build: [BUILD_DIR]
|
||||
},
|
||||
|
||||
copy: {
|
||||
build: {
|
||||
files: appFiles,
|
||||
options: {
|
||||
noProcess: ['**','!package.json'],
|
||||
process: function() {
|
||||
var pkg = _.merge(PKG, PKG_OVERWRITE);
|
||||
return JSON.stringify(pkg, null, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
grunt.registerTask('pitaya:run', ['download', 'run']);
|
||||
grunt.registerTask(
|
||||
'pitaya:build',
|
||||
['download', 'build', 'copy:build']
|
||||
);
|
||||
grunt.registerTask('default', ['pitaya:run']);
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-nw');
|
||||
|
||||
};
|
28
README.md
28
README.md
@ -9,33 +9,25 @@ Lanceur d'application pour GNU/Linux
|
||||
- [NodeJS](https://nodejs.org/) - Dernière version stable, testé sur la 0.12.*
|
||||
- [NPM](https://www.npmjs.com/) - Normalement automatiquement installé avec NodeJS.
|
||||
|
||||
### Initialisation du projet
|
||||
### Initialisation du projet & lancement de Pitaya
|
||||
|
||||
```
|
||||
git clone https://forge.cadoles.com/wpetit/pitaya.git
|
||||
cd pitaya
|
||||
git checkout develop
|
||||
npm install
|
||||
DEBUG=pitaya* npm start
|
||||
DEBUG=pitaya* NODE_ENV=development npm start
|
||||
```
|
||||
|
||||
## Options
|
||||
## Variables d'environnement
|
||||
|
||||
```
|
||||
--profile=<chemin_profile> Chemin vers le fichier de profil à charger dans l'application.
|
||||
--edit Ouvrir l'application en mode édition.
|
||||
```
|
||||
Vous pouvez configurer le comportement de Pitaya en passant des variables d'environnement:
|
||||
|
||||
### Passer des options en développement
|
||||
|
||||
```
|
||||
npm start -- [options...]
|
||||
```
|
||||
|
||||
Exemple:
|
||||
```
|
||||
npm start -- --profile=my-profile.json
|
||||
```
|
||||
| Variable | Description | Valeurs possibles | Valeur par défaut |
|
||||
|-------------------|------------------------------------|-------------------|------------------------|
|
||||
| PITAYA_MODE | Mode d'exécution de Pitaya | launcher, edit | launcher |
|
||||
| PITAYA_PROFILE | Chemin du fichier profil à charger | -- | ./default-profile.json |
|
||||
| PITAYA_AS_DESKTOP | Afficher Pitaya en mode "Bureau" | 1, 0 | 0 |
|
||||
|
||||
## Comment construire l'application depuis les sources
|
||||
|
||||
@ -43,7 +35,7 @@ npm start -- --profile=my-profile.json
|
||||
npm run build
|
||||
```
|
||||
|
||||
Un dossier `pitaya-<version>-<target>-<arch>` sera créé dans le répertoire `./build`. Celui ci contient tous les fichiers nécessaires à l'application.
|
||||
Un dossier `pitaya-<target>-<arch>` sera créé dans le répertoire `./build`. Celui ci contient tous les fichiers nécessaires à l'application.
|
||||
|
||||
|
||||
## Comment contribuer
|
||||
|
@ -27,21 +27,42 @@ html, body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
background: url('../img/background.png') no-repeat;
|
||||
background: url('../img/background.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
transition: background-image 250ms ease-in-out;
|
||||
}
|
||||
|
||||
.launcher .main {
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.launcher .nav {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.launcher .nav a.goback {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
font-size: 60px;
|
||||
text-shadow: 1px 1px #444;
|
||||
}
|
||||
|
||||
.launcher .nav a.goback:hover {
|
||||
-webkit-animation: 500ms pulse-large infinite;
|
||||
}
|
||||
|
||||
.launcher .category-header {
|
||||
padding: 40px 50px 0;
|
||||
padding: 25px 40px 0;
|
||||
font-size: 50px;
|
||||
}
|
||||
|
||||
.launcher .category-header a.goback {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.launcher .category-header a.goback:hover {
|
||||
-webkit-animation: 500ms pulse-large infinite;
|
||||
color: #fff;
|
||||
text-shadow: 1px 1px #444;
|
||||
}
|
||||
|
||||
.launcher .category-header > .category-label {
|
||||
@ -65,6 +86,10 @@ html, body {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.launcher .nav ~ ul.apps-list {
|
||||
margin-left: -50px;
|
||||
}
|
||||
|
||||
.launcher li.app-item {
|
||||
margin: 5px;
|
||||
border-radius: 5px;
|
||||
@ -221,7 +246,7 @@ html, body {
|
||||
|
||||
@-webkit-keyframes pulse-large {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.5); }
|
||||
50% { transform: scale(1.3); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
{
|
||||
"label": "Level 1",
|
||||
"icon": "chromium-browser",
|
||||
"background": "./img/background2.jpg",
|
||||
"items": [
|
||||
{
|
||||
"label": "Level 2-1",
|
||||
@ -11,9 +12,11 @@
|
||||
{
|
||||
"label": "Chromium Browser 1",
|
||||
"icon": "chromium-browser",
|
||||
"exec": "/usr/bin/chromium-browser"
|
||||
"exec": "/usr/bin/chromium-browser",
|
||||
"_key": "item_1444480285022_3"
|
||||
}
|
||||
]
|
||||
],
|
||||
"_key": "item_1444480285022_2"
|
||||
},
|
||||
{
|
||||
"label": "Level 2-2",
|
||||
@ -26,13 +29,24 @@
|
||||
{
|
||||
"label": "Chromium Browser 2",
|
||||
"icon": "chromium-browser",
|
||||
"exec": "/usr/bin/chromium-browser"
|
||||
"exec": "/usr/bin/chromium-browser",
|
||||
"_key": "item_1444480285022_6"
|
||||
},
|
||||
{
|
||||
"label": "Atom",
|
||||
"icon": "atom",
|
||||
"exec": "/usr/share/atom/atom %U",
|
||||
"_key": "item_1444480288996_7"
|
||||
}
|
||||
]
|
||||
],
|
||||
"_key": "item_1444480285022_5"
|
||||
}
|
||||
]
|
||||
],
|
||||
"_key": "item_1444480285022_4"
|
||||
}
|
||||
]
|
||||
],
|
||||
"_key": "item_1444480285022_1"
|
||||
}
|
||||
]
|
||||
],
|
||||
"_key": "item_1444480285021_0"
|
||||
}
|
||||
|
BIN
img/background2.jpg
Normal file
BIN
img/background2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 903 KiB |
13
index.html
13
index.html
@ -15,11 +15,16 @@
|
||||
global.document = global.window.document;
|
||||
global.navigator = global.window.navigator;
|
||||
|
||||
// Auto transform JSX
|
||||
require('node-jsx').install();
|
||||
var isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
// Launch application
|
||||
require('./js/app.jsx');
|
||||
if(isDev) {
|
||||
// Auto transform JSX
|
||||
require('node-jsx').install({extension: '.js'});
|
||||
// Launch application
|
||||
require('./js/app.js');
|
||||
} else {
|
||||
require('./js-compiled/app.js');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
var React = require('react');
|
||||
var LauncherView = require('./components/launcher/launcher-view.jsx');
|
||||
var EditView = require('./components/edit/edit-view.jsx');
|
||||
var LauncherView = require('./components/launcher/launcher-view.js');
|
||||
var EditView = require('./components/edit/edit-view.js');
|
||||
var Provider = require('react-redux').Provider;
|
||||
var connect = require('react-redux').connect;
|
||||
var store = require('./store');
|
||||
@ -10,7 +10,7 @@ var App = React.createClass({
|
||||
|
||||
render: function() {
|
||||
|
||||
var editMode = this.props.processOpts.edit || false;
|
||||
var editMode = process.env.PITAYA_MODE === 'edit';
|
||||
|
||||
var view = editMode ? <EditView /> : <LauncherView />;
|
||||
|
@ -1,6 +1,6 @@
|
||||
var React = require('react');
|
||||
var Util = require('../../util');
|
||||
var AppIcon = require('../common/app-icon.jsx');
|
||||
var AppIcon = require('../common/app-icon.js');
|
||||
var DragSource = require('react-dnd').DragSource;
|
||||
|
||||
var DesktopAppItem = React.createClass({
|
@ -1,6 +1,6 @@
|
||||
var React = require('react');
|
||||
var Util = require('../../util');
|
||||
var DesktopAppItem = require('./desktop-app-item.jsx');
|
||||
var DesktopAppItem = require('./desktop-app-item.js');
|
||||
var path = require('path');
|
||||
var debug = require('../../util/debug')('pitaya:desktop-app-list');
|
||||
|
@ -1,10 +1,10 @@
|
||||
var React = require('react');
|
||||
var connect = require('react-redux').connect;
|
||||
var ProfileTree = require('./profile-tree.jsx');
|
||||
var DesktopAppList = require('./desktop-app-list.jsx');
|
||||
var ItemForm = require('./item-form.jsx');
|
||||
var IconThemeSelector = require('./icon-theme-selector.jsx');
|
||||
var ProfileMenu = require('./profile-menu.jsx');
|
||||
var ProfileTree = require('./profile-tree.js');
|
||||
var DesktopAppList = require('./desktop-app-list.js');
|
||||
var ItemForm = require('./item-form.js');
|
||||
var IconThemeSelector = require('./icon-theme-selector.js');
|
||||
var ProfileMenu = require('./profile-menu.js');
|
||||
var tree = require('../../util/tree');
|
||||
|
||||
var actions = require('../../store/actions');
|
85
js/components/edit/profile-menu.js
Normal file
85
js/components/edit/profile-menu.js
Normal file
@ -0,0 +1,85 @@
|
||||
/* jhsint node:true, jsx: true */
|
||||
var React = require('react');
|
||||
var connect = require('react-redux').connect;
|
||||
var actions = require('../../store/actions');
|
||||
var dialog = require('remote').require('dialog');
|
||||
|
||||
var ProfileMenu = React.createClass({
|
||||
|
||||
render: function() {
|
||||
|
||||
return (
|
||||
<div className="profile-menu">
|
||||
<button className="btn btn-default" onClick={this.handleOpenClick}>Ouvrir</button>
|
||||
<button className="btn btn-primary" onClick={this.handleSaveClick}>Enregistrer</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
handleOpenClick: function() {
|
||||
var dispatch = this.props.dispatch;
|
||||
this.showOpenProfileDialog()
|
||||
.then(function(profilePath) {
|
||||
if(profilePath) dispatch(actions.common.loadProfile(profilePath));
|
||||
})
|
||||
;
|
||||
},
|
||||
|
||||
handleSaveClick: function() {
|
||||
|
||||
var dispatch = this.props.dispatch;
|
||||
var profile = this.props.profile;
|
||||
var profilePath = this.props.profilePath;
|
||||
|
||||
this.showSaveProfileDialog(profilePath)
|
||||
.then(function(profilePath) {
|
||||
if(profilePath) dispatch(actions.edit.saveProfile(profilePath, profile));
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
showOpenProfileDialog: function() {
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
dialog.showOpenDialog(
|
||||
{
|
||||
title: 'Éditer un profil',
|
||||
filters: [ {name: 'Profils Pitaya', extensions: ['json'] } ],
|
||||
properties: ['openFile']
|
||||
},
|
||||
function(files) {
|
||||
return resolve(files ? files[0] : null);
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
showSaveProfileDialog: function(defaultPath) {
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
dialog.showSaveDialog(
|
||||
{
|
||||
defaultPath: defaultPath,
|
||||
title: 'Enregistrer un profil',
|
||||
filters: [ {name: 'Profils Pitaya', extensions: ['json'] } ]
|
||||
},
|
||||
function(file) {
|
||||
return resolve(file);
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function select(state) {
|
||||
return {
|
||||
profile: state.profile,
|
||||
profilePath: state.profilePath
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = connect(select)(ProfileMenu);
|
@ -1,79 +0,0 @@
|
||||
var React = require('react');
|
||||
var connect = require('react-redux').connect;
|
||||
var actions = require('../../store/actions');
|
||||
|
||||
var ProfileMenu = React.createClass({
|
||||
|
||||
render: function() {
|
||||
|
||||
return (
|
||||
<div className="profile-menu">
|
||||
<input ref="fileInput" style={{display: 'none'}} filter=".json" type="file" />
|
||||
<button className="btn btn-default" onClick={this.handleOpenClick}>Ouvrir</button>
|
||||
<button className="btn btn-primary" onClick={this.handleSaveClick}>Enregistrer</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
handleOpenClick: function() {
|
||||
var dispatch = this.props.dispatch;
|
||||
this.showFileDialog()
|
||||
.then(function(profilePath) {
|
||||
dispatch(actions.common.loadProfile(profilePath));
|
||||
})
|
||||
;
|
||||
},
|
||||
|
||||
handleSaveClick: function() {
|
||||
|
||||
var dispatch = this.props.dispatch;
|
||||
var profile = this.props.profile;
|
||||
var profilePath = this.props.profilePath;
|
||||
|
||||
var promise = profilePath ? Promise.resolve(profilePath) : this.showFileDialog(true);
|
||||
|
||||
promise.then(function(profilePath) {
|
||||
dispatch(actions.edit.saveProfile(profilePath, profile));
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
showFileDialog: function(saveAs) {
|
||||
|
||||
var fileInput = this.refs.fileInput.getDOMNode();
|
||||
|
||||
// Toggle 'save as' feature
|
||||
if(saveAs) {
|
||||
fileInput.nwsaveas = true;
|
||||
} else {
|
||||
fileInput.removeAttribute('nwsaveas');
|
||||
}
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
|
||||
fileInput.addEventListener('change', handleChange, false);
|
||||
fileInput.click();
|
||||
|
||||
function handleChange(evt) {
|
||||
fileInput.removeEventListener('change', handleChange);
|
||||
var value = this.value;
|
||||
this.value = null;
|
||||
resolve(value);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function select(state) {
|
||||
return {
|
||||
profile: state.profile,
|
||||
profilePath: state.profilePath
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = connect(select)(ProfileMenu);
|
@ -1,7 +1,7 @@
|
||||
var React = require('react');
|
||||
var connect = require('react-redux').connect;
|
||||
var actions = require('../../store/actions');
|
||||
var TreeItem = require('./tree-item.jsx');
|
||||
var TreeItem = require('./tree-item.js');
|
||||
|
||||
var TreeNode = React.createClass({
|
||||
|
||||
@ -17,6 +17,7 @@ var TreeNode = React.createClass({
|
||||
selectedItem={this.props.selectedItem}
|
||||
onItemClicked={this.props.onItemClicked}
|
||||
onItemMoved={this.props.onItemMoved}
|
||||
onItemRemoved={this.props.onItemRemoved}
|
||||
theme={this.props.theme} />
|
||||
</li>
|
||||
);
|
||||
@ -66,6 +67,7 @@ var ProfileTree = React.createClass({
|
||||
selectedItem={this.props.selectedItem}
|
||||
onItemClicked={this.onItemSelected}
|
||||
onItemMoved={this.onItemMoved}
|
||||
onItemRemoved={this.onItemRemoved}
|
||||
theme={this.props.theme} />
|
||||
);
|
||||
},
|
||||
@ -76,6 +78,10 @@ var ProfileTree = React.createClass({
|
||||
|
||||
onItemSelected: function(selectedItem) {
|
||||
this.props.dispatch(actions.edit.selectProfileItem(selectedItem));
|
||||
},
|
||||
|
||||
onItemRemoved: function(selectedItem) {
|
||||
this.props.dispatch(actions.edit.removeProfileItem(selectedItem));
|
||||
}
|
||||
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
var React = require('react/addons');
|
||||
var classNames = require('classnames');
|
||||
var AppIcon = require('../common/app-icon.jsx');
|
||||
var AppIcon = require('../common/app-icon.js');
|
||||
var DragSource = require('react-dnd').DragSource;
|
||||
var DropTarget = require('react-dnd').DropTarget;
|
||||
var _ = require('lodash');
|
||||
@ -30,6 +30,9 @@ var TreeItem = React.createClass({
|
||||
<div className={classes} style={style} onClick={this.handleClick}>
|
||||
{appIcon}
|
||||
<span className="app-label">{data.label}</span>
|
||||
<button type="button" className="close pull-right" onClick={this.handleRemoveClick}>
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
));
|
||||
|
||||
@ -38,6 +41,11 @@ var TreeItem = React.createClass({
|
||||
handleClick: function(evt) {
|
||||
evt.preventDefault();
|
||||
this.props.onItemClicked(this.props.data);
|
||||
},
|
||||
|
||||
handleRemoveClick: function(evt) {
|
||||
evt.preventDefault();
|
||||
this.props.onItemRemoved(this.props.data);
|
||||
}
|
||||
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
var React = require('react');
|
||||
var AppIcon = require('../common/app-icon.jsx');
|
||||
var AppIcon = require('../common/app-icon.js');
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
@ -1,5 +1,5 @@
|
||||
var React = require('react');
|
||||
var AppItem = require('./app-item.jsx');
|
||||
var AppItem = require('./app-item.js');
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
19
js/components/launcher/category-header.js
Normal file
19
js/components/launcher/category-header.js
Normal file
@ -0,0 +1,19 @@
|
||||
var React = require('react');
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
item: React.PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
|
||||
return (
|
||||
<div className="category-header">
|
||||
<span className="category-label">{this.props.item.label}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
});
|
@ -1,12 +1,14 @@
|
||||
var React = require('react');
|
||||
var CategoryHeader = require('./category-header.jsx');
|
||||
var AppList = require('./app-list.jsx');
|
||||
var CategoryHeader = require('./category-header.js');
|
||||
var AppList = require('./app-list.js');
|
||||
var Nav = require('./nav.js');
|
||||
var AnimateMixin = require('../mixins/animate');
|
||||
var actions = require('../../store/actions');
|
||||
var connect = require('react-redux').connect;
|
||||
var debug = require('../../util/debug')('launcher-view');
|
||||
var path = require('path');
|
||||
|
||||
var DEFAULT_PROFILE = './default-profile.json';
|
||||
var DEFAULT_PROFILE = path.join(__dirname, '..', '..', '..', 'default-profile.json');
|
||||
|
||||
var LauncherView = React.createClass({
|
||||
|
||||
@ -20,7 +22,7 @@ var LauncherView = React.createClass({
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
var profilePath = this.props.processOpts.profile || DEFAULT_PROFILE;
|
||||
var profilePath = process.env.PITAYA_PROFILE || DEFAULT_PROFILE;
|
||||
this.props.dispatch(actions.common.loadProfile(profilePath));
|
||||
},
|
||||
|
||||
@ -38,19 +40,34 @@ var LauncherView = React.createClass({
|
||||
|
||||
var header = currentItemPath !== '' ?
|
||||
( <CategoryHeader
|
||||
item={currentItem} /> ) :
|
||||
null
|
||||
;
|
||||
|
||||
var nav = currentItemPath !== '' ?
|
||||
( <Nav
|
||||
onBackClick={this.onBackClick}
|
||||
item={currentItem}
|
||||
itemPath={currentItemPath} /> ) :
|
||||
null
|
||||
;
|
||||
|
||||
var style = {};
|
||||
|
||||
if(currentItem && currentItem.background) {
|
||||
style.backgroundImage = 'url('+currentItem.background+')';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="launcher">
|
||||
<div className="launcher" style={style}>
|
||||
{header}
|
||||
<AppList ref="appList"
|
||||
items={items}
|
||||
parentPath={currentItemPath}
|
||||
onItemClick={this.onItemClick} />
|
||||
<div className="main">
|
||||
{nav}
|
||||
<AppList ref="appList"
|
||||
items={items}
|
||||
parentPath={currentItemPath}
|
||||
onItemClick={this.onItemClick} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* jshint node: true jsx: true */
|
||||
var React = require('react');
|
||||
|
||||
module.exports = React.createClass({
|
||||
@ -14,9 +15,8 @@ module.exports = React.createClass({
|
||||
render: function() {
|
||||
|
||||
return (
|
||||
<div className="category-header">
|
||||
<div className="nav">
|
||||
<a href="#" onClick={this._onBackClick} className="goback" >◄</a>
|
||||
<span className="category-label">{this.props.item.label}</span>
|
||||
</div>
|
||||
);
|
||||
|
@ -12,6 +12,7 @@ var SAVE_PROFILE_FAILED = exports.SAVE_PROFILE_FAILED = 'SAVE_PROFILE_FAILED';
|
||||
|
||||
var MOVE_PROFILE_ITEM = exports.MOVE_PROFILE_ITEM = 'MOVE_PROFILE_ITEM';
|
||||
var ADD_PROFILE_ITEM = exports.ADD_PROFILE_ITEM = 'ADD_PROFILE_ITEM';
|
||||
var REMOVE_PROFILE_ITEM = exports.REMOVE_PROFILE_ITEM = 'REMOVE_PROFILE_ITEM';
|
||||
var USE_ICON_THEME = exports.USE_ICON_THEME = 'USE_ICON_THEME';
|
||||
var SELECT_PROFILE_ITEM = exports.SELECT_PROFILE_ITEM = 'SELECT_PROFILE_ITEM';
|
||||
var UPDATE_PROFILE_ITEM = exports.UPDATE_PROFILE_ITEM = 'UPDATE_PROFILE_ITEM';
|
||||
@ -71,6 +72,13 @@ exports.moveProfileItem = function(movedItem, targetItem) {
|
||||
};
|
||||
};
|
||||
|
||||
exports.removeProfileItem = function(removedItem) {
|
||||
return {
|
||||
type: REMOVE_PROFILE_ITEM,
|
||||
removedItem: removedItem
|
||||
};
|
||||
};
|
||||
|
||||
exports.addProfileItem = function(newItem, targetItem) {
|
||||
return {
|
||||
type: ADD_PROFILE_ITEM,
|
||||
|
@ -1,6 +1,5 @@
|
||||
var redux = require('redux');
|
||||
var thunkMiddleware = require('redux-thunk');
|
||||
var loggerMiddleware = require('redux-logger');
|
||||
var reducers = require('./reducers');
|
||||
var loggerMiddleware = require('./middlewares/logger');
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
exports.desktopApps = require('./desktop-apps');
|
||||
exports.profile = require('./profile');
|
||||
exports.processOpts = require('./process-opts');
|
||||
exports.theme = require('./theme');
|
||||
|
@ -1,8 +0,0 @@
|
||||
var minimist = require('minimist');
|
||||
var gui = global.window.require('nw.gui');
|
||||
|
||||
var opts = minimist(gui.App.argv);
|
||||
|
||||
module.exports = function(state, action) {
|
||||
return opts;
|
||||
};
|
@ -14,6 +14,9 @@ module.exports = function(oldProfile, action) {
|
||||
case actions.edit.MOVE_PROFILE_ITEM:
|
||||
return moveProfileItem(oldProfile, action.movedItem, action.targetItem);
|
||||
|
||||
case actions.edit.REMOVE_PROFILE_ITEM:
|
||||
return removeProfileItem(oldProfile, action.removedItem);
|
||||
|
||||
case actions.edit.ADD_PROFILE_ITEM:
|
||||
return addProfileItem(oldProfile, action.newItem, action.targetItem);
|
||||
|
||||
@ -48,6 +51,18 @@ function updateProfileItem(oldProfile, targetItem, key, value) {
|
||||
return newProfile;
|
||||
}
|
||||
|
||||
function removeProfileItem(oldProfile, removedItem) {
|
||||
|
||||
var newProfile = _.cloneDeep(oldProfile);
|
||||
var parent = tree.find(newProfile, removedItem).parent;
|
||||
|
||||
parent.items = _.reject(parent.items, function(item) {
|
||||
return _.isEqual(item, removedItem);
|
||||
});
|
||||
|
||||
return newProfile;
|
||||
|
||||
}
|
||||
|
||||
function moveProfileItem(oldProfile, movedItem, targetItem) {
|
||||
|
||||
|
2
js/util/const.js
Normal file
2
js/util/const.js
Normal file
@ -0,0 +1,2 @@
|
||||
exports.EDIT_MODE = 'edit';
|
||||
exports.LAUNCHER_MODE = 'launcher';
|
@ -3,15 +3,5 @@ var util = require('util');
|
||||
|
||||
module.exports = function createLogger(namespace) {
|
||||
var logger = debug('pitaya:'+namespace);
|
||||
var isNWContext = 'window' in global;
|
||||
var console = isNWContext ? global.window.console : global.console;
|
||||
logger.log = function() {
|
||||
if(isNWContext) {
|
||||
console.log.apply(console, arguments);
|
||||
} else {
|
||||
var str = util.format.apply(util, arguments);
|
||||
console.log(str);
|
||||
}
|
||||
};
|
||||
return logger;
|
||||
};
|
||||
|
@ -249,7 +249,9 @@ exports.findPixmapsIcon = function(iconName) {
|
||||
exports.findIconThemes = function() {
|
||||
return System.findFiles('*/', {cwd: ICON_THEMES_ROOTDIR, realpath: true})
|
||||
.then(function(files) {
|
||||
return files.map(path.basename.bind(path));
|
||||
return files.map(function(f) {
|
||||
return path.basename(f);
|
||||
});
|
||||
})
|
||||
;
|
||||
};
|
||||
|
41
main.js
Normal file
41
main.js
Normal file
@ -0,0 +1,41 @@
|
||||
var app = require('app'); // Module to control application life.
|
||||
var BrowserWindow = require('browser-window'); // Module to create native browser window.
|
||||
var isDev = process.env.NODE_ENV === 'development';
|
||||
var constants = require('./'+(isDev ? 'js': 'js-compiled')+'/util/const');
|
||||
|
||||
var mainWindow = null;
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', function() {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
app.on('ready', function() {
|
||||
// Create the browser window.
|
||||
var electronScreen = require('screen');
|
||||
var size = electronScreen.getPrimaryDisplay().workAreaSize;
|
||||
|
||||
var asDesktop = process.env.PITAYA_AS_DESKTOP == 1;
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
type: asDesktop ? 'desktop' : undefined,
|
||||
'skip-taskbar': asDesktop,
|
||||
frame: !asDesktop,
|
||||
width: asDesktop ? size.width : undefined,
|
||||
height: asDesktop ? size.height : undefined,
|
||||
x: asDesktop ? 0 : undefined,
|
||||
y: asDesktop ? 0 : undefined,
|
||||
});
|
||||
|
||||
if(process.env.NODE_ENV === 'development') {
|
||||
mainWindow.openDevTools();
|
||||
}
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadUrl('file://' + __dirname + '/index.html');
|
||||
|
||||
mainWindow.on('closed', function() {
|
||||
mainWindow = null;
|
||||
});
|
||||
|
||||
});
|
28
package.json
28
package.json
@ -2,25 +2,21 @@
|
||||
"name": "pitaya",
|
||||
"version": "0.0.0",
|
||||
"private": "true",
|
||||
"main": "index.html",
|
||||
"main": "main.js",
|
||||
"devDependencies": {
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-cli": "^0.1.13",
|
||||
"grunt-contrib-clean": "^0.6.0",
|
||||
"grunt-contrib-copy": "^0.7.0",
|
||||
"grunt-nw": "git+https://github.com/snap-project/grunt-nw#develop",
|
||||
"lodash": "^3.0.1",
|
||||
"nodeunit": "^0.9.1"
|
||||
"electron-packager": "^5.1.0",
|
||||
"electron-prebuilt": "^0.33.6",
|
||||
"nodeunit": "^0.9.1",
|
||||
"react-tools": "^0.13.3",
|
||||
"node-jsx": "^0.13.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "./node_modules/.bin/nodeunit test",
|
||||
"start": "./node_modules/.bin/grunt pitaya:run",
|
||||
"build": "./node_modules/.bin/grunt pitaya:build"
|
||||
},
|
||||
"chromium-args": "--ignore-certificate-errors",
|
||||
"window": {
|
||||
"toolbar": true,
|
||||
"kiosk": false
|
||||
"start": "./node_modules/.bin/electron .",
|
||||
"compile": "./node_modules/.bin/jsx -x js js js-compiled",
|
||||
"clean": "rm -rf js-compiled/* build/*",
|
||||
"package": "./node_modules/.bin/electron-packager ./ pitaya --prune --ignore=js/ --platform=linux --arch=ia32 --version=0.33.6 --out=build --overwrite --app-version 0.0.0",
|
||||
"build": "npm run clean && npm run compile && npm run package"
|
||||
},
|
||||
"dependencies": {
|
||||
"bootstrap": "^3.3.5",
|
||||
@ -29,8 +25,6 @@
|
||||
"glob": "^5.0.14",
|
||||
"ini": "^1.3.4",
|
||||
"lodash": "^3.10.1",
|
||||
"minimist": "^1.1.3",
|
||||
"node-jsx": "^0.13.3",
|
||||
"react": "^0.13.3",
|
||||
"react-dnd": "^1.1.5",
|
||||
"react-redux": "^2.0.0",
|
||||
|
Loading…
Reference in New Issue
Block a user