Skip to content

Commit

Permalink
refactor: menu (#572)
Browse files Browse the repository at this point in the history
* menu
* remove icons and some styling
* updates
* settings on menubar itself
* remove some classes
* idea for menu structure
* keep idea going
* add key to options menu
* organise css and start light theme
* style and refactoring
* set default pane as 'info'
* move close to settings
* fix loading screen loader
* tweaks
* remove useless css
* remove heartbeat from corner and remove useless css
  • Loading branch information
hacdias authored Dec 29, 2017
1 parent 57b5afc commit 55262f1
Show file tree
Hide file tree
Showing 41 changed files with 741 additions and 769 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ import Footer from '../components/view/footer'

export default function MyPane {
return (
<Pane class='left-pane peers'>
<Pane class='peers'>
<Header title='The title of your pane' />

<div className='main'>
Expand All @@ -117,16 +117,16 @@ Now, to incorporate your pane into Station iself so it is visible, you have to i
The components are classes exported with CamelCase names. The corresponding files have the associated class name with hyphen-separated-words. So, e.g., `simple-stat.js` exports a class named `SimpleStat`.

+ [**Button**](./src/js/components/view/button.js) is a simple button with text.
+ [**File**](./src/js/components/view/file.js) is used within a file list to describe a file with a button to copy its link.
+ [**CheckboxBlock**](./src/js/components/view/checkbox-block.js) is like an `InfoBlock`, but with a checkbox attached to it.
+ [**FileBlock**](./src/js/components/view/file-block.js) is used within a file list to describe a file with a button to copy its link.
+ [**Footer**](./src/js/components/view/footer.js) is the footer of a pane.
+ [**Header**](./src/js/components/view/header.js) is the header of a pane.
+ [**Heartbeat**](./src/js/components/view/heartbeat.js) displays an heartbeat-like animation with the IPFS logo.
+ [**IconButton**](./src/js/components/view/icon-button.js) is a button with an icon inside.
+ [**IconDropdownList**](./src/js/components/view/icon-dropdown-list.js) is a dropdown list with an icon.
+ [**Icon**](./src/js/components/view/icon.js) shows an icon.
+ [**InfoBlock**](./src/js/components/view/info-block.js) shows a block of information (used on node info pane).
+ [**Loader**](./src/js/components/view/loader.js) is a loader.
+ [**Peer**](./src/js/components/view/peer.js) shows a peer information.
+ [**MenuOption**](./src/js/components/view/menu-option.js) is a menu option to show within a menu bar.

## Contribute

Expand Down
15 changes: 2 additions & 13 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,6 @@ export default {
ice: logo('ice'),
black: logo('black')
},
// Will be replaced by a BrowserWindow instance.
settingsWindow: {
index: `file://${__dirname}/views/settings.html`,
title: 'IPFS Station Settings',
show: false,
icon: logo('ice'),
backgroundColor: '#252525',
resizable: false,
width: 450,
height: 450
},
// Will be replaced by a Menubar instance.
menubar: {
index: `file://${__dirname}/views/menubar.html`,
Expand All @@ -112,9 +101,9 @@ export default {
window: {
resizable: false,
skipTaskbar: true,
width: 850,
width: 600,
height: 400,
backgroundColor: '#000000',
backgroundColor: (settingsStore.get('lightTheme') ? '#FFFFFF' : '#000000'),
webPreferences: {
nodeIntegration: true,
webSecurity: false
Expand Down
47 changes: 11 additions & 36 deletions src/controls/main/settings.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,5 @@
import {join} from 'path'
import {shell, ipcMain, BrowserWindow} from 'electron'

function setupWindow (opts) {
const options = opts.settingsWindow
const window = new BrowserWindow(options)

window.setMenu(null)
window.loadURL(options.index)
window.on('close', (event) => {
event.preventDefault()
window.hide()
})

// Replace the window settings by the actual
// instance of BrowserWindow
opts.settingsWindow = window
}

function open (opts) {
const {settingsWindow, settingsStore} = opts

return () => {
settingsWindow.webContents.send('settings', settingsStore.toObject())
settingsWindow.show()
settingsWindow.focus()
}
}
import {shell, ipcMain} from 'electron'

function openNodeConfig (opts) {
const {settingsStore} = opts
Expand All @@ -39,19 +13,20 @@ function openNodeConfig (opts) {
function updateSettings (opts) {
const {settingsStore} = opts

return (event, settings) => {
for (const key in settings) {
if (settings.hasOwnProperty(key)) {
settingsStore.set(key, settings[key])
}
}
return (event, key, value) => {
settingsStore.set(key, value)
}
}

export default function (opts) {
setupWindow(opts)
const {send, settingsStore} = opts

const handler = () => {
send('settings', settingsStore.toObject())
}

ipcMain.on('open-settings', open(opts))
ipcMain.on('update-settings', updateSettings(opts))
ipcMain.on('request-settings', handler)
settingsStore.on('change', handler)
ipcMain.on('update-setting', updateSettings(opts))
ipcMain.on('open-node-settings', openNodeConfig(opts))
}
9 changes: 0 additions & 9 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,6 @@ app.makeSingleInstance(() => {
)
})

// Make sure Settings Window is closed when quitting the application.
app.on('before-quit', (event) => {
const {settingsWindow} = config

if (settingsWindow instanceof BrowserWindow) {
settingsWindow.destroy()
}
})

// Local Variables

let poller = null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,41 @@
import React from 'react'
import PropTypes from 'prop-types'

export default function CheckboxItem (props) {
/**
* Is a Checkbox Block.
*
* @param {Object} props
*
* @prop {Bool} value - the current value (checked or not)
* @prop {Any} info - the description
* @prop {String} title - the option's title
* @prop {Function} onChange - the on change handler
*
* @return {ReactElement}
*/
export default function CheckboxBlock (props) {
const _onClick = () => {
props.onChange(!props.value)
}

return (
<div onClick={_onClick} className='info-block checkbox'>
<div>
<div>
<input type='checkbox' id={props.id} checked={props.value} />
<span className='checkbox' />
</div>
<div>
<p className='label'>{props.title}</p>
<p className='info'>{props.info}</p>
</div>
<div>
<input type='checkbox' onChange={_onClick} checked={props.value} />
<span className='checkbox' />
</div>
</div>
</div>
)
}

CheckboxItem.propTypes = {
CheckboxBlock.propTypes = {
value: PropTypes.bool.isRequired,
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
info: PropTypes.any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Button from './button'
import Icon from './icon'

/**
* Is a File.
* Is a File Block.
*
* @param {Object} props
*
Expand All @@ -18,7 +18,7 @@ import Icon from './icon'
*
* @return {ReactElement}
*/
export default function File (props) {
export default function FileBlock (props) {
const extension = fileExtension(props.name)
let icon = 'file'
if (fileTypes[extension]) {
Expand All @@ -45,7 +45,7 @@ export default function File (props) {
)
}

File.propTypes = {
FileBlock.propTypes = {
name: PropTypes.string.isRequired,
date: PropTypes.string.isRequired,
hash: PropTypes.string.isRequired
Expand Down
8 changes: 8 additions & 0 deletions src/js/components/view/icon.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ import PropTypes from 'prop-types'
* @return {ReactElement}
*/
export default function Icon (props) {
if (props.name === 'ipfs') {
return (
<span className='icon'>
<img src='../img/ipfs-logo-black.png' />
</span>
)
}

return (
<span className={`icon ti-${props.name}`} />
)
Expand Down
28 changes: 7 additions & 21 deletions src/js/components/view/info-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,19 @@ import Button from '../view/button'
* @prop {Bool} [button=true] - sets 'onClick' to be triggered when clicking a button.
* Otherwise it triggeres when clicking the whole block.
* @prop {String} [buttonMessage=Copy] - sets the button message.
* @prop {Bool} [pre=false] - tells if the information should be wrapped inside a 'pre' block.
*
* @return {ReactElement}
*/
export default function InfoBlock (props) {
let info = null

if (props.pre) {
if (Array.isArray(props.info)) {
info = []
props.info.forEach((element, index) => {
info.push((<pre key={index}>{element}</pre>))
})
} else {
info = (<pre>{props.info}</pre>)
}
if (Array.isArray(props.info)) {
info = []
props.info.forEach((element, index) => {
info.push((<p key={index} className='info'>{element}</p>))
})
} else {
if (Array.isArray(props.info)) {
info = []
props.info.forEach((element, index) => {
info.push((<p key={index} className='info'>{element}</p>))
})
} else {
info = (<p className='info'>{props.info}</p>)
}
info = (<p className='info'>{props.info}</p>)
}

let button = null
Expand Down Expand Up @@ -72,12 +60,10 @@ InfoBlock.propTypes = {
title: PropTypes.string.isRequired,
onClick: PropTypes.func,
button: PropTypes.bool,
buttonMessage: PropTypes.string,
pre: PropTypes.bool
buttonMessage: PropTypes.string
}

InfoBlock.defaultProps = {
pre: false,
button: true,
buttonMessage: 'Copy',
onClick: null
Expand Down
29 changes: 29 additions & 0 deletions src/js/components/view/key-combo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react'
import PropTypes from 'prop-types'

import Key from './key'

/**
* Is a Key Combination
*
* @param {Object} props
*
* @prop {Array} keys - must be an array of strings.
*
* @return {ReactElement}
*/
export default function KeyCombo (props) {
const keys = []

props.keys.forEach((key, index) => {
keys.push(<Key key={`${index}k`}>{key}</Key>)
keys.push(<span key={`${index}s`}> + </span>)
})

keys.pop()
return keys
}

KeyCombo.propTypes = {
keys: PropTypes.array.isRequired
}
23 changes: 23 additions & 0 deletions src/js/components/view/key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react'
import PropTypes from 'prop-types'

/**
* Is a Key.
*
* @param {Object} props
*
* @prop {Node} children - must be a string or a node.
*
* @return {ReactElement}
*/
export default function Key (props) {
return (
<span className='key'>
{props.children}
</span>
)
}

Key.propTypes = {
children: PropTypes.node.isRequired
}
24 changes: 0 additions & 24 deletions src/js/components/view/loader.js

This file was deleted.

35 changes: 35 additions & 0 deletions src/js/components/view/menu-option.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react'
import PropTypes from 'prop-types'

import Icon from './icon'

/**
* Is a menu option.
*
* @param {Object} props
*
* @prop {Bool} [active]
* @prop {Function} onClick
* @prop {String} icon
* @prop {String} title
*
* @return {ReactElement}
*/
export default function MenuOption (props) {
let className = 'menu-option'
if (props.active) className += ' active'

return (
<button onClick={props.onClick} className={className}>
<Icon name={props.icon} />
<p>{props.title}</p>
</button>
)
}

MenuOption.propTypes = {
active: PropTypes.bool,
onClick: PropTypes.func.isRequired,
icon: PropTypes.string.isRequired,
title: PropTypes.string.isRequired
}
Loading

0 comments on commit 55262f1

Please sign in to comment.