Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: menu #572

Merged
merged 16 commits into from
Dec 29, 2017
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