diff --git a/css/style.css b/css/style.css index a2cc2c4..644074d 100644 --- a/css/style.css +++ b/css/style.css @@ -1,3 +1,10 @@ +@font-face { + font-family: 'sawasdeeregular'; + src: url('../fonts/sawasdee-webfont.woff2') format('woff2'); + font-weight: normal; + font-style: normal; +} + * { box-sizing: border-box; } @@ -5,7 +12,7 @@ html, body { padding: 0; margin: 0; - font-family: 'Droid Sans', 'Ubuntu Sans', sans-serif; + font-family: 'sawasdeeregular'; background-size: contain; background-position: center; background-color: rgb(34, 107, 160); @@ -15,23 +22,40 @@ html, body { overflow-x: hidden; } + +/* Common */ + .alert.alert-default { border-radius: 4px; border: 1px solid #ddd; } +.app-icon { + background-position: center center; + background-size: contain; + background-repeat: no-repeat; + transition: background-image 250ms ease-in-out; +} + +.full-width { + width: 100%; +} + /* Launcher View */ .launcher { display: flex; - width: 100%; - height: 100%; flex-direction: column; background: url('../img/background.png'); background-repeat: no-repeat; background-size: cover; background-position: center center; transition: background-image 250ms ease-in-out; + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: 0; } .launcher .main { @@ -44,7 +68,7 @@ html, body { justify-content: center; align-items: center; display: flex; - width: 50px; + width: 60px; } .launcher .nav a.goback { @@ -52,6 +76,7 @@ html, body { color: white; font-size: 60px; text-shadow: 1px 1px #444; + font-family: sans-serif; } .launcher .nav a.goback:hover { @@ -75,7 +100,7 @@ html, body { .launcher ul.apps-list { margin: 0; - padding: 0; + padding: 0 20%; display: flex; flex-direction: row; list-style: none; @@ -87,7 +112,7 @@ html, body { } .launcher .nav ~ ul.apps-list { - margin-left: -50px; + margin-left: -60px; } .launcher li.app-item { @@ -123,8 +148,9 @@ html, body { } .launcher li.app-item > .app-icon { - width: 70%; - height: auto; + width: 90px; + height: 90px; + margin: auto; } .launcher li.app-item > .app-label { @@ -147,21 +173,47 @@ html, body { flex-direction: column; } +.edit .title { + margin-top: 5px; +} + .edit .menu-bar { padding: 5px 10px; + display: flex; + flex-direction: row; } .edit .menu-bar button { margin-right: 3px; } +.edit .left { + flex: 1; + display: flex; +} + +.edit .main { + flex: 3; + display: flex; +} + +.edit .right { + flex: 1; + display: flex; +} + .edit .workspace { display: flex; flex-direction: row; padding: 10px; - flex: 3; + flex: 1; } +.edit .workspace .main { + flex-direction: column; +} + + .edit .left-menu { display: flex; flex-direction: column; @@ -169,6 +221,15 @@ html, body { overflow-y: auto; } +.edit .workspace .left .apps-menu { + display: flex; + flex-direction: column; +} + +.edit .workspace .right { + flex-direction: column; +} + .edit .item-form { display: flex; flex-direction: row; @@ -179,6 +240,11 @@ html, body { width: 100%; } +.edit .apps-list { + overflow: auto; + margin-top: 5px; +} + .edit .apps-list .icon-theme-selector > select { width: 100%; } @@ -187,25 +253,25 @@ html, body { list-style: none; padding: 0; height: 100%; - margin: 10px 0 0 0; - padding: 0 10px 0 0; -} - -.edit .apps-list li.desktop-app { - + display: block; + margin-right: 5px; } .edit .desktop-app > .app-icon { - height: 35px; - width: 35px; + height: 20px; + width: 20px; display: inline-block; vertical-align: middle; margin-right: 10px; } +.edit .desktop-app.list-group-item { + padding: 5px 10px; +} + .edit .profile-tree { - flex: 3; padding: 0 5px; + width: 100%; } .edit .profile-tree ul { @@ -224,11 +290,13 @@ html, body { .edit .profile-tree .tree-item .app-icon { height: 25px; + width: 25px; margin-right: 5px; + display: inline-block; + vertical-align: middle; } .edit .app-item-edit { - flex: 1; padding: 0 5px; } diff --git a/default-profile.json b/default-profile.json index f9779d0..4bf6228 100644 --- a/default-profile.json +++ b/default-profile.json @@ -19,7 +19,7 @@ "_key": "item_1444480285022_2" }, { - "label": "Level 2-2", + "label": "Level 2-3", "icon": "chromium-browser", "items": [ { @@ -36,7 +36,15 @@ "label": "Atom", "icon": "atom", "exec": "/usr/share/atom/atom %U", - "_key": "item_1444480288996_7" + "_key": "item_1444480288996_7", + "items": [] + }, + { + "label": "Firefox Developer Edition Web Browser", + "icon": "firefox", + "exec": "firefox %u", + "_key": "item_1444761351301_2", + "selected": true } ], "_key": "item_1444480285022_5" @@ -49,4 +57,4 @@ } ], "_key": "item_1444480285021_0" -} +} \ No newline at end of file diff --git a/fonts/sawasdee-webfont.woff2 b/fonts/sawasdee-webfont.woff2 new file mode 100644 index 0000000..9903526 Binary files /dev/null and b/fonts/sawasdee-webfont.woff2 differ diff --git a/index.html b/index.html index 32aad08..a5e7757 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,6 @@ Lanceur - Pitaya - @@ -20,12 +19,11 @@ if(isDev) { // Auto transform JSX require('node-jsx').install({extension: '.js'}); - // Launch application - require('./js/app.js'); - } else { - require('./js-compiled/app.js'); } + // Launch app + require('./'+(isDev ? 'src' : 'dist')+'/app.js'); + diff --git a/main.js b/main.js index edd65bb..ee5310c 100644 --- a/main.js +++ b/main.js @@ -1,7 +1,8 @@ var app = require('app'); // Module to control application life. var BrowserWindow = require('browser-window'); // Module to create native browser window. +var Menu = require('menu'); var isDev = process.env.NODE_ENV === 'development'; -var constants = require('./'+(isDev ? 'js': 'js-compiled')+'/util/const'); +var constants = require('./'+(isDev ? 'src': 'dist')+'/util/const'); var mainWindow = null; @@ -13,7 +14,7 @@ app.on('window-all-closed', function() { app.on('ready', function() { // Create the browser window. var electronScreen = require('screen'); - var size = electronScreen.getPrimaryDisplay().workAreaSize; + var size = electronScreen.getPrimaryDisplay().size; var asDesktop = process.env.PITAYA_AS_DESKTOP == 1; @@ -23,11 +24,12 @@ app.on('ready', function() { frame: !asDesktop, width: asDesktop ? size.width : undefined, height: asDesktop ? size.height : undefined, + 'auto-hide-menu-bar': true, x: asDesktop ? 0 : undefined, y: asDesktop ? 0 : undefined, }); - if(process.env.NODE_ENV === 'development') { + if(isDev) { mainWindow.openDevTools(); } diff --git a/package.json b/package.json index 3db5826..99c47d7 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,9 @@ "scripts": { "test": "./node_modules/.bin/nodeunit test", "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", + "compile": "./node_modules/.bin/jsx -x js src dist", + "clean": "rm -rf dist/* build/*", + "package": "./node_modules/.bin/electron-packager ./ pitaya --prune --ignore=res/ --platform=linux --arch=ia32,x64 --version=0.33.6 --out=build --overwrite --app-version 0.0.0", "build": "npm run clean && npm run compile && npm run package" }, "dependencies": { diff --git a/js/app.js b/src/app.js similarity index 100% rename from js/app.js rename to src/app.js diff --git a/js/components/common/app-icon.js b/src/components/common/app-icon.js similarity index 82% rename from js/components/common/app-icon.js rename to src/components/common/app-icon.js index 53c4388..f67770e 100644 --- a/js/components/common/app-icon.js +++ b/src/components/common/app-icon.js @@ -41,8 +41,12 @@ module.exports = React.createClass({ var icon = this.state.icon; + var style = { + backgroundImage: 'url('+icon+')' + }; + return ( - +
); }, @@ -60,6 +64,13 @@ module.exports = React.createClass({ } return iconPath; }) + .then(function(iconPath) { + return Util.System.exists(iconPath) + .then(function(exists) { + return exists ? iconPath : DEFAULT_ICON; + }) + ; + }) .then(function(iconPath) { self.setState({ icon: iconPath }); }) diff --git a/js/components/edit/desktop-app-item.js b/src/components/edit/desktop-app-item.js similarity index 100% rename from js/components/edit/desktop-app-item.js rename to src/components/edit/desktop-app-item.js diff --git a/js/components/edit/desktop-app-list.js b/src/components/edit/desktop-app-list.js similarity index 100% rename from js/components/edit/desktop-app-list.js rename to src/components/edit/desktop-app-list.js diff --git a/js/components/edit/edit-view.js b/src/components/edit/edit-view.js similarity index 53% rename from js/components/edit/edit-view.js rename to src/components/edit/edit-view.js index eb29ffc..551d300 100644 --- a/js/components/edit/edit-view.js +++ b/src/components/edit/edit-view.js @@ -21,19 +21,38 @@ var EditView = React.createClass({ return (
+
- +
+ +
+
+
+ +
+
+
-
- - +
+
+ Thème + + Applications + +
+
+
+ Arbre de profil + +
+
+ Édition +
- -
); @@ -58,6 +77,16 @@ var EditView = React.createClass({ handleItemChange: function(item, key, value) { this.props.dispatch(actions.edit.updateProfileItem(item, key, value)); + }, + + handleAddNewNode: function() { + var newItem = { + label: 'Nouveau noeud', + icon: '', + exec: '', + background: '' + }; + this.props.dispatch(actions.edit.addProfileItem(newItem, this.props.profile)); } }); diff --git a/js/components/edit/icon-theme-selector.js b/src/components/edit/icon-theme-selector.js similarity index 100% rename from js/components/edit/icon-theme-selector.js rename to src/components/edit/icon-theme-selector.js diff --git a/js/components/edit/item-form.js b/src/components/edit/item-form.js similarity index 77% rename from js/components/edit/item-form.js rename to src/components/edit/item-form.js index 58933a9..874b38e 100644 --- a/js/components/edit/item-form.js +++ b/src/components/edit/item-form.js @@ -17,7 +17,8 @@ var ItemForm = React.createClass({ this.setState({ label: props.item.label, icon: props.item.icon, - exec: props.item.exec + exec: props.item.exec, + background: props.item.background }); } @@ -31,25 +32,27 @@ var ItemForm = React.createClass({
-
-
-
+
+ +
); diff --git a/js/components/edit/profile-menu.js b/src/components/edit/profile-menu.js similarity index 90% rename from js/components/edit/profile-menu.js rename to src/components/edit/profile-menu.js index e98e15a..00e3de7 100644 --- a/js/components/edit/profile-menu.js +++ b/src/components/edit/profile-menu.js @@ -10,8 +10,8 @@ var ProfileMenu = React.createClass({ return (
- - + +
); diff --git a/js/components/edit/profile-tree.js b/src/components/edit/profile-tree.js similarity index 100% rename from js/components/edit/profile-tree.js rename to src/components/edit/profile-tree.js diff --git a/js/components/edit/tree-item.js b/src/components/edit/tree-item.js similarity index 100% rename from js/components/edit/tree-item.js rename to src/components/edit/tree-item.js diff --git a/js/components/launcher/app-item.js b/src/components/launcher/app-item.js similarity index 100% rename from js/components/launcher/app-item.js rename to src/components/launcher/app-item.js diff --git a/js/components/launcher/app-list.js b/src/components/launcher/app-list.js similarity index 100% rename from js/components/launcher/app-list.js rename to src/components/launcher/app-list.js diff --git a/js/components/launcher/category-header.js b/src/components/launcher/category-header.js similarity index 100% rename from js/components/launcher/category-header.js rename to src/components/launcher/category-header.js diff --git a/js/components/launcher/launcher-view.js b/src/components/launcher/launcher-view.js similarity index 100% rename from js/components/launcher/launcher-view.js rename to src/components/launcher/launcher-view.js diff --git a/js/components/launcher/nav.js b/src/components/launcher/nav.js similarity index 100% rename from js/components/launcher/nav.js rename to src/components/launcher/nav.js diff --git a/js/components/mixins/animate.js b/src/components/mixins/animate.js similarity index 100% rename from js/components/mixins/animate.js rename to src/components/mixins/animate.js diff --git a/js/components/mixins/lazy-load.js b/src/components/mixins/lazy-load.js similarity index 100% rename from js/components/mixins/lazy-load.js rename to src/components/mixins/lazy-load.js diff --git a/js/store/actions/common.js b/src/store/actions/common.js similarity index 100% rename from js/store/actions/common.js rename to src/store/actions/common.js diff --git a/js/store/actions/edit.js b/src/store/actions/edit.js similarity index 91% rename from js/store/actions/edit.js rename to src/store/actions/edit.js index 3bc664e..5f41925 100644 --- a/js/store/actions/edit.js +++ b/src/store/actions/edit.js @@ -1,5 +1,6 @@ var Util = require('../../util'); var path = require('path'); +var _ = require('lodash'); // Action types var LOAD_DESKTOP_APPS = exports.LOAD_PROFILE = 'LOAD_DESKTOP_APPS'; @@ -45,7 +46,14 @@ exports.saveProfile = function(destPath, profile) { dispatch({ type: SAVE_PROFILE, profile: profile, path: destPath }); - return Util.System.saveJSON(destPath, profile) + var cleanedProfile = _.cloneDeep(profile); + + Util.Tree.walk(cleanedProfile, function(item) { + delete item.selected; + delete item._key; + }); + + return Util.System.saveJSON(destPath, cleanedProfile) .then(function() { dispatch({ type: SAVE_PROFILE_SUCCESS, profile: profile, path: destPath }); }) diff --git a/js/store/actions/index.js b/src/store/actions/index.js similarity index 100% rename from js/store/actions/index.js rename to src/store/actions/index.js diff --git a/js/store/actions/launcher.js b/src/store/actions/launcher.js similarity index 100% rename from js/store/actions/launcher.js rename to src/store/actions/launcher.js diff --git a/js/store/index.js b/src/store/index.js similarity index 100% rename from js/store/index.js rename to src/store/index.js diff --git a/js/store/middlewares/logger.js b/src/store/middlewares/logger.js similarity index 100% rename from js/store/middlewares/logger.js rename to src/store/middlewares/logger.js diff --git a/js/store/reducers/desktop-apps.js b/src/store/reducers/desktop-apps.js similarity index 100% rename from js/store/reducers/desktop-apps.js rename to src/store/reducers/desktop-apps.js diff --git a/js/store/reducers/index.js b/src/store/reducers/index.js similarity index 100% rename from js/store/reducers/index.js rename to src/store/reducers/index.js diff --git a/js/store/reducers/profile.js b/src/store/reducers/profile.js similarity index 77% rename from js/store/reducers/profile.js rename to src/store/reducers/profile.js index af735f1..454a82d 100644 --- a/js/store/reducers/profile.js +++ b/src/store/reducers/profile.js @@ -4,33 +4,40 @@ var tree = require('../../util/tree'); module.exports = function(oldProfile, action) { + var newProfile = oldProfile || { items: [] }; + switch(action.type) { case actions.common.LOAD_PROFILE_SUCCESS: - var newProfile = _.cloneDeep(action.profile); - tree.walk(newProfile, ensureItemKey); - return newProfile; + newProfile = _.cloneDeep(action.profile); + break; case actions.edit.MOVE_PROFILE_ITEM: - return moveProfileItem(oldProfile, action.movedItem, action.targetItem); + newProfile = moveProfileItem(oldProfile, action.movedItem, action.targetItem); + break; case actions.edit.REMOVE_PROFILE_ITEM: - return removeProfileItem(oldProfile, action.removedItem); + newProfile = removeProfileItem(oldProfile, action.removedItem); + break; case actions.edit.ADD_PROFILE_ITEM: - return addProfileItem(oldProfile, action.newItem, action.targetItem); + newProfile = addProfileItem(oldProfile, action.newItem, action.targetItem); + break; case actions.edit.UPDATE_PROFILE_ITEM: - return updateProfileItem(oldProfile, action.item, action.key, action.value); + newProfile = updateProfileItem(oldProfile, action.item, action.key, action.value); + break; case actions.edit.SELECT_PROFILE_ITEM: - return selectProfileItem(oldProfile, action.item); - - default: - return oldProfile || null; + newProfile = selectProfileItem(oldProfile, action.item); + break; } + if(newProfile) tree.walk(newProfile, ensureItemKey); + + return newProfile; + }; function selectProfileItem(oldProfile, item) { diff --git a/js/store/reducers/theme.js b/src/store/reducers/theme.js similarity index 100% rename from js/store/reducers/theme.js rename to src/store/reducers/theme.js diff --git a/js/util/cache.js b/src/util/cache.js similarity index 100% rename from js/util/cache.js rename to src/util/cache.js diff --git a/js/util/const.js b/src/util/const.js similarity index 100% rename from js/util/const.js rename to src/util/const.js diff --git a/js/util/debug.js b/src/util/debug.js similarity index 100% rename from js/util/debug.js rename to src/util/debug.js diff --git a/js/util/desktop-apps.js b/src/util/desktop-apps.js similarity index 91% rename from js/util/desktop-apps.js rename to src/util/desktop-apps.js index 1b0f0f6..3645c9c 100644 --- a/js/util/desktop-apps.js +++ b/src/util/desktop-apps.js @@ -2,6 +2,7 @@ var path = require('path'); var System = require('./system'); var debug = require('./debug')('desktop-apps'); var Cache = require('./cache'); +var promises = require('./promises'); // Constants var ICON_REALPATH_REGEX = /\..+$/; @@ -19,11 +20,9 @@ exports.loadAllDesktopFiles = function(rootDirs) { return exports.findAllDesktopFiles(rootDirs) .then(function(filePaths) { - var promises = filePaths.map(function(path) { - return exports.loadDesktopFile(path); - }); - - return Promise.all(promises) + return promises.seq(filePaths, function(path) { + return exports.loadDesktopFile(path); + }) .then(function(contents) { return contents.map(function(content, i) { return { content: content, path: filePaths[i] }; @@ -48,11 +47,9 @@ exports.findAllDesktopFiles = function(baseDirs) { baseDirs = [baseDirs]; } - var promises = baseDirs.map(function(baseDir) { - return System.findFiles('**/*.desktop', {cwd: baseDir, realpath: true}); - }); - - return Promise.all(promises) + return promises.seq(baseDirs, function(baseDir) { + return System.findFiles('**/*.desktop', {cwd: baseDir, realpath: true}); + }) .then(function(apps) { return uniq(flatten(apps)); }) @@ -104,10 +101,9 @@ exports.findIcon = function(iconName, themeName, size, themeIgnore) { return exports.findIconThemes() .then(function(themes) { themeIgnore = themeIgnore || []; - var promises = themes.map(function(theme) { - return exports.findIcon(iconName, theme, size, themeIgnore); - }); - return Promise.all(promises) + return promises.seq(themes, function(theme) { + return exports.findIcon(iconName, theme, size, themeIgnore); + }) .then(exports._selectBestIcon) ; }) @@ -160,11 +156,9 @@ exports.findParentsThemeIcon = function(iconName, themeName, size, themeIgnore) debug('Found parents %j', parents); - var promises = parents.map(function(themeName) { - return exports.findIcon(iconName, themeName, size, themeIgnore); - }); - - return Promise.all(promises) + return promises.seq(parents, function(themeName) { + return exports.findIcon(iconName, themeName, size, themeIgnore); + }) .then(exports._selectBestIcon) ; @@ -278,7 +272,6 @@ exports._selectBestIcon = function(iconPaths) { return iconSelection.scalable || iconSelection.bitmap; }; - // Array helpers function clean(arr) { diff --git a/js/util/index.js b/src/util/index.js similarity index 58% rename from js/util/index.js rename to src/util/index.js index 49a2fea..9070008 100644 --- a/js/util/index.js +++ b/src/util/index.js @@ -2,3 +2,6 @@ exports.System = require('./system'); exports.DesktopApps = require('./desktop-apps'); exports.Cache = require('./cache'); exports.Debug = require('./debug'); +exports.Tree = require('./tree'); +exports.Const = require('./const'); +exports.Promises = require('./promises'); diff --git a/src/util/promises.js b/src/util/promises.js new file mode 100644 index 0000000..07ded5c --- /dev/null +++ b/src/util/promises.js @@ -0,0 +1,31 @@ + + +exports.seq = function(items, generator) { + + var results = []; + var p = Promise.resolve(); + + for(var i = 0, len = items.length; i < len; ++i) { + p = p.then(generateNextHandler(items[i], i === 0)) + } + + return p.then(function(lastResult) { + results.push(lastResult); + return results; + }); + + // Internal helper + function generateNextHandler(item, ignoreResult) { + return function(prevResult) { + if(!ignoreResult) results.push(prevResult); + return generator(item, prevResult); + }; + } + +}; + +exports.delay = function(delay) { + return new Promise(function(resolve) { + setTimeout(resolve, delay); + }); +}; diff --git a/js/util/system.js b/src/util/system.js similarity index 100% rename from js/util/system.js rename to src/util/system.js diff --git a/js/util/tree.js b/src/util/tree.js similarity index 100% rename from js/util/tree.js rename to src/util/tree.js