diff --git a/Makefile b/Makefile index deceb32..542b2f0 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ install: npm install app: install build - ./node_modules/.bin/electron-packager . + ./node_modules/.bin/electron-packager . qian --overwrite --icon=icon.icns clean: rm -rf node_modules diff --git a/README.md b/README.md index 06bfd07..3efb7f8 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,25 @@ In addition, if a feature seems interesting to implement, let's talk about it in - `make` (a combo of `make build` and `make run`) - `make app` to create a runnable app on OSX +## Shortcuts + +- `Tab` : toggle the focus on the searchbar +- `Cmd + Alt + Enter` : Open the current folder in finder +- `Cmd + Enter` : Open the current folder in a terminal + +> those shortcuts works only if the search bar does not have the focus + +- `Cmd + Left` : Go on the pred view (if it exists) +- `Cmd + Right` : Go on the next view (if it exists) +- `Cmd + Up` : Go to the parent (if it exists) + +## About the search bar + +Using `Tab` you can toggle the search-bar activation. When you write +text into this bar, the content of the folder will be filtered using +a fuzzy-filtering. If you write `/`, Qian will open the first element +of the result of the filtering. + ## Credits @@ -47,8 +66,10 @@ In addition, if a feature seems interesting to implement, let's talk about it in - [@xvw](https://github.com/xvw): everything else... (I think :P) ### Tools + +- [Dotgrid](http://wiki.xxiivv.com/#dotgrid) (for the logo) - [Elm](http://elm-lang.org/) (to have a nice language) - [Electron](https://electron.atom.io/) (to have a window !) - [Font Awesome](http://fontawesome.io/) (for the icon in the UI) -- [NoRedInk](http://package.elm-lang.org/packages/NoRedInk/elm-simple-fuzzy/latest) +- [NoRedInk Simple Fuzzy](http://package.elm-lang.org/packages/NoRedInk/elm-simple-fuzzy/latest) (for the Fuzzy Searching) diff --git a/icon.icns b/icon.icns new file mode 100644 index 0000000..286e589 Binary files /dev/null and b/icon.icns differ diff --git a/icon.ico b/icon.ico new file mode 100644 index 0000000..20223f7 Binary files /dev/null and b/icon.ico differ diff --git a/main.js b/main.js index 6794965..5285368 100644 --- a/main.js +++ b/main.js @@ -14,7 +14,8 @@ function createWindow() { backgroundColor: "#000", frame: true, resizable: true, - autoHideMenuBar: true + autoHideMenuBar: true, + icon: __dirname + '/icon.ico' }) mainWindow.loadURL(`file://${ __dirname }/static/index.html`) //mainWindow.webContents.openDevTools() diff --git a/package-lock.json b/package-lock.json index 0c8d7ec..66062f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "qian", - "version": "1.0.0", + "version": "1.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 44a0671..5f1d966 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "qian", - "version": "1.0.0", + "version": "1.2.0", "description": "A small experience", "main": "main.js", "scripts": { diff --git a/src/Action.elm b/src/Action.elm index 5d55992..9cb079e 100644 --- a/src/Action.elm +++ b/src/Action.elm @@ -13,6 +13,8 @@ module Action , goToSettings , goToTree , changeDefaultTerminal + , navigateHistoryFromMenu + , toParentFromMenu ) {-| Provide all "action" of the application @@ -175,6 +177,18 @@ changeDir model newPath = changeHistory model (\history -> History.push history newPath) +{-| Go to the parent from Electron +-} +toParentFromMenu : Model -> ( Model, Cmd Message ) +toParentFromMenu model = + case File.parent model.history.present of + Nothing -> + ( model, Cmd.none ) + + Just parent -> + changeDir model parent + + {-| Navigate in the history (pred/next) -} navigateHistory : Model -> History File.Path -> ( Model, Cmd Message ) @@ -187,6 +201,25 @@ navigateHistory model newHistory = ( newModel, Port.getTree (Model.now newModel) ) +{-| Navigate in the history from Electron +-} +navigateHistoryFromMenu : Model -> Bool -> ( Model, Cmd Message ) +navigateHistoryFromMenu model isPast = + let + f = + if isPast then + History.backward + else + History.forward + in + case f model.history of + Just x -> + navigateHistory model x + + Nothing -> + ( model, Cmd.none ) + + {-| Change the current tree -} changeTree : Model -> File.Tree -> ( Model, Cmd Message ) diff --git a/src/Main.elm b/src/Main.elm index bb7d4f0..5f220ef 100644 --- a/src/Main.elm +++ b/src/Main.elm @@ -18,6 +18,8 @@ subscriptions model = Sub.batch [ Port.retreiveTree ChangeTree , Port.treeMutation TreeMutation + , Port.historyNavigation NavigateHistoryFromMenu + , Port.jumpToParent ToParentFromMenu ] @@ -62,6 +64,12 @@ update message model = GoToTree -> Action.goToTree model + NavigateHistoryFromMenu isPast -> + Action.navigateHistoryFromMenu model isPast + + ToParentFromMenu _ -> + Action.toParentFromMenu model + ChangeDefaultTerminal -> Action.changeDefaultTerminal model diff --git a/src/Message.elm b/src/Message.elm index b76e649..628288d 100644 --- a/src/Message.elm +++ b/src/Message.elm @@ -20,4 +20,6 @@ type Message | RecordConfigTerminal String -- Track the configuration changement | GoToSettings -- Go to the user settings | GoToTree -- Return to the treeView + | NavigateHistoryFromMenu Bool -- Navigation from Electron + | ToParentFromMenu Bool -- Go to parent from Electron | ChangeDefaultTerminal -- Change the default terminal diff --git a/src/Port.elm b/src/Port.elm index 164234a..cbf13cf 100644 --- a/src/Port.elm +++ b/src/Port.elm @@ -9,6 +9,8 @@ port module Port , openInFinder , openInTerminal , changeTerminal + , historyNavigation + , jumpToParent ) {-| JavaScript interopt @@ -41,6 +43,16 @@ port getTree : File.Path -> Cmd msg port retreiveTree : (File.Tree -> msg) -> Sub msg +{-| Perform a modification on the history from Electron +-} +port historyNavigation : (Bool -> msg) -> Sub msg + + +{-| Jump to the parent from Electron +-} +port jumpToParent : (Bool -> msg) -> Sub msg + + {-| Watch the TreeMutation -} port treeMutation : (Bool -> msg) -> Sub msg diff --git a/static/index.html b/static/index.html index a9eedc6..0a865e9 100644 --- a/static/index.html +++ b/static/index.html @@ -4,7 +4,7 @@ - Qian 1 + qian diff --git a/static/js/index.js b/static/js/index.js index bb1a249..fde870c 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -9,6 +9,9 @@ import * as childProcess from 'child_process' const { shell, remote } = electron const { app } = remote +const Menu = remote.Menu; +const MenuItem = remote.MenuItem; + // A default configuration (actually, it is supported // only a Terminal :) ) @@ -43,12 +46,14 @@ function rewriteConfiguration(config) { fs.writeFileSync(qianFile, JSON.stringify(config)) } +const configObj = getConfigObject(defaultConfig) +const homePath = path.resolve(app.getPath('home')); // Define the flag to be passed to the Elm Program const flags = { - current: path.resolve("."), - config: getConfigObject(defaultConfig), - home: path.resolve(app.getPath('home')), + current: homePath, + config: configObj, + home: homePath, root: '/' } @@ -56,13 +61,83 @@ const flags = { const container = document.getElementById('app'); const elmApp = elm.Main.embed(container, flags); +// Application + + +function openInTerminal(app, dir) { + childProcess.spawn('open', ['-a', app, dir]) +} + // Ports to Elm Application let watcher // the file Watcher +let currentTree = homePath; + +const template = + [ + { + label: 'qian', + submenu: [{role: 'about'}, {role: 'quit'}] + }, + { + label: 'Shortcuts', + submenu: [ + { + label: 'Pred', + accelerator: 'CmdOrCtrl+Left', + click: function(item, focusedWindow) { + if (focusedWindow) { + elmApp.ports.historyNavigation.send(true) + } + } + }, + { + label: 'Next', + accelerator: 'CmdOrCtrl+Right', + click: function(item, focusedWindow) { + if (focusedWindow) { + elmApp.ports.historyNavigation.send(false) + } + } + }, + { + label: 'Parent', + accelerator: 'CmdOrCtrl+Up', + click: function(item, focusedWindow) { + if (focusedWindow) { + elmApp.ports.jumpToParent.send(true) + } + } + }, + { + label: 'Open in finder', + accelerator: 'CmdOrCtrl+Alt+enter', + click: function(item, focusedWindow) { + if (focusedWindow) { + shell.showItemInFolder(currentTree) + } + } + }, + { + label: 'Open in Terminal', + accelerator: 'CmdOrCtrl+enter', + click: function(item, focusedWindow) { + if (focusedWindow) { + openInTerminal(configObj.terminal, currentTree) + } + } + } + ] + } + ]; + +const menu = Menu.buildFromTemplate(template) +Menu.setApplicationMenu(menu) // Watch and get treeFile elmApp.ports.getTree.subscribe((pwd) => { const dir = path.resolve(pwd) + currentTree = dir; const tree = fs.readdirSync(dir).map((entry) => { const completePath = path.join(dir, entry) return { @@ -97,7 +172,7 @@ elmApp.ports.openInFinder.subscribe((pwd) => { elmApp.ports.openInTerminal.subscribe((input) => { const dir = path.resolve(input.path) - childProcess.spawn('open', ['-a', input.app, dir]) + openInTerminal(input.app, dir) }); elmApp.ports.changeTerminal.subscribe((config) => {