Skip to content
This repository has been archived by the owner on Jul 11, 2019. It is now read-only.

use yo-yo #166

Merged
merged 1 commit into from
Mar 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 19 additions & 25 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,16 @@ module.exports = window.App = App
var EventEmitter = require('events').EventEmitter

var catNames = require('cat-names')
var createElement = require('virtual-dom/create-element')
var delegate = require('dom-delegate')
var diff = require('virtual-dom/diff')
var eos = require('end-of-stream')
var githubCurrentUser = require('github-current-user')
var h = require('virtual-dom/h')
var inherits = require('inherits')
var leveldown = require('leveldown') // browser: level-js
var levelup = require('levelup')
var patch = require('virtual-dom/patch')
var subleveldown = require('subleveldown')
var richMessage = require('rich-message')
var Swarm = require('friends-swarm')
var yo = require('yo-yo')

var config = require('./config')
var util = require('./lib/util')
Expand Down Expand Up @@ -191,14 +188,11 @@ function App (el, currentWindow) {

// Initial DOM tree render
var tree = self.render()
var rootNode = createElement(tree)
el.appendChild(rootNode)
el.appendChild(tree)

function render () {
var newTree = self.render()
var patches = diff(tree, newTree)
rootNode = patch(rootNode, patches)
tree = newTree
yo.update(tree, newTree)
}

self.on('render', render)
Expand Down Expand Up @@ -304,24 +298,24 @@ App.prototype.render = function () {
var views = self.views
var data = self.data

return h('div.layout', [
h('.sidebar', [
h('.sidebar-scroll', [
views.channels.render(data.channels),
views.users.render(data.users)
]),
views.status.render(data.username, data.peers)
]),
h('.content', [
views.messages.render(data.activeChannel, data.users),
views.composer.render(data)
])
])
return yo`
<div class="layout">
<div class="sidebar">
<div class="sidebar-scroll">
${views.channels.render(data.channels)}
${views.users.render(data.users)}
</div>
${views.status.render(data.username, data.peers)}
</div>
<div class="content">
${views.messages.render(data.activeChannel, data.users)}
${views.composer.render(data)}
</div>
</div>
`
}

App.prototype.isFocused = function () {
if (this.currentWindow) {
return this.currentWindow.isFocused()
}
if (this.currentWindow) return this.currentWindow.isFocused()
return true
}
44 changes: 30 additions & 14 deletions css/app.styl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

WHITE = rgb(255, 255, 255)

GRAY_HIGHLIGHT = rgb(240, 240, 240)
GRAY_LIGHTEST = rgb(220, 220, 220)
GRAY_LIGHT = rgb(200, 200, 200)
GRAY = rgb(100, 100, 100)
Expand Down Expand Up @@ -122,16 +123,26 @@ button
ellipsis()
color: GRAY_LIGHTEST
text-decoration: none
padding: (SPACING_SIZE / 3) SPACING_SIZE
padding: (SPACING_SIZE / 3) (SPACING_SIZE * 2)
margin: 0
display: block

.addChannel
input
padding: (SPACING_SIZE / 3) SPACING_SIZE
font-size: FONT_SIZE
width: 100%
z-index: 10000
width: 100%
text-align: left

&:hover
color: GRAY_HIGHLIGHT

.add-channel
margin: 0 (-1 * SPACING_SIZE)
button
padding: (SPACING_SIZE / 2) (SPACING_SIZE * 2)
.inputprompt
margin: 0 (SPACING_SIZE * 2)
input
padding: (SPACING_SIZE / 3) SPACING_SIZE
font-size: FONT_SIZE
width: 100%
z-index: 10000

ul
list-style: none
Expand All @@ -142,11 +153,10 @@ button
ellipsis()
margin: 0
padding: 0
margin: 0 (-1 * SPACING_SIZE)

&.active
background-color: RED_LIGHT
margin: 0 (-1 * SPACING_SIZE)
padding: 0 SPACING_SIZE
button
color: WHITE

Expand Down Expand Up @@ -193,12 +203,17 @@ button
padding: SPACING_SIZE
height: TOP_BAR_HEIGHT

.channelName
.channel-name
display: inline-block
color: BLACK
font-size: FONT_SIZE_BIG
font-weight: bold

.num-peers
font-size: FONT_SIZE_SMALL
font-weight: normal
color: GRAY_LIGHT

.button
float: right
margin-top: -3px
Expand All @@ -222,23 +237,24 @@ button
border-radius: BORDER_RADIUS
width: AVATAR_SIZE
height: AVATAR_SIZE
cursor: pointer
.username, .verified, .timestamp
display: inline-block
line-height: 1
.username
font-weight: bold
margin-left: SPACING_SIZE
text-decoration: none
color: inherit
.verified
display: inline-block
background-image: url('../static/verified.svg')
background-size: 10px
width: 10px
height: 10px
margin-left: (SPACING_SIZE / 2)
opacity: 0.8
.timestamp
color: GRAY_LIGHT
font-size: FONT_SIZE_SMALL
margin-left: (SPACING_SIZE * (2 / 3))
.text
margin-left: AVATAR_SIZE + SPACING_SIZE
overflow-wrap: break-word
Expand Down
2 changes: 1 addition & 1 deletion lib/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function command (self, db) {
break
default:
db.aliases.get(command, function (err, alias) {
if (err == null) {
if (err === null) {
self.emit('executeCommand', alias)
} else {
console.log('Unrecognized command: ' + command + ' (in "' + commandStr + '")')
Expand Down
37 changes: 20 additions & 17 deletions lib/elements/channels.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
module.exports = Channels

var h = require('virtual-dom/h')
var InputPrompt = require('./input-prompt.js')
var InputPrompt = require('./input-prompt')
var inherits = require('util').inherits
var BaseElement = require('./base-element')
var yo = require('yo-yo')

function Channels (target) {
var self = this
BaseElement.call(this, target)

self.addChannelPrompt = new InputPrompt({
className: 'addChannel',
className: 'add-channel',
prompt: '+ Join Channel',
placeholder: 'Channel name',
onsubmit: function (channelName) {
Expand All @@ -28,20 +28,23 @@ Channels.prototype.render = function (channels) {

channels = channels.map(function (channel) {
var className = channel.active ? 'active' : ''
return h('li', { className: className }, [
h('button', {
onclick: function () {
self.send('selectChannel', channel.name)
}
}, '#' + channel.name)
])

function onclick () {
self.send('selectChannel', channel.name)
}

return yo`
<li class="${className}">
<button onclick=${onclick}>#${channel.name}</button>
</li>
`
})

return [
h('.heading', 'Channels'),
h('ul', [
channels
]),
self.addChannelPrompt.render()
]
return yo`
<div class="channels">
<div class="heading">Channels</div>
<ul>${channels}</ul>
${self.addChannelPrompt.render()}
</div>
`
}
75 changes: 41 additions & 34 deletions lib/elements/composer.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module.exports = Composer

var h = require('virtual-dom/h')
var inherits = require('util').inherits
var uniq = require('lodash.uniq')
var BaseElement = require('./base-element')
var yo = require('yo-yo')

function Composer (target) {
BaseElement.call(this, target)
Expand All @@ -28,36 +28,47 @@ Composer.prototype.render = function (data) {
data = data || {}
var ownUsername = data.username

return h('textarea.composer', {
onload: self,
rows: 1,
autofocus: true,
onkeydown: function (e) {
if (e.keyCode === TAB_KEY) {
e.preventDefault()

// if there are no matches try matching again
if (!self.autocompleting.length) {
self.resetAutocomplete()
self.autocomplete(self.node.value, ownUsername)
}

self.insertAutocomplete(e.target)
} else if (e.keyCode === ENTER_KEY && !e.shiftKey) {
e.preventDefault()
self.submit(e.target)
}
function onkeydown (e) {
if (e.keyCode === TAB_KEY) {
e.preventDefault()

// reset the completions if the user submits or changes the text to be
// completed
if (e.keyCode !== TAB_KEY) {
// if there are no matches try matching again
if (!self.autocompleting.length) {
self.resetAutocomplete()
self.autocomplete(self.node.value, ownUsername)
}
},
oninput: function (e) {
self.resize(e.target)

self.insertAutocomplete(e.target)
} else if (e.keyCode === ENTER_KEY && !e.shiftKey) {
e.preventDefault()
self.submit(e.target)
}
})

// reset the completions if the user submits or changes the text to be
// completed
if (e.keyCode !== TAB_KEY) {
self.resetAutocomplete()
}
}

function oninput (e) {
self.resize(e.target)
}

self.node = yo`
<textarea
class="composer"
aria-label="Enter a message and press enter"
onload=${self}
rows="1"
onkeydown=${onkeydown}
oninput=${oninput}
autofocus></textarea>
`

this.initAutoExpander()

return self.node
}

Composer.prototype.autocomplete = function (text, ownUsername) {
Expand All @@ -79,7 +90,7 @@ Composer.prototype.submit = function (node) {
} else {
self.send('sendMessage', node.value)
}
node.value = ''
node.innerHTML = ''
self.resize(node)
}

Expand All @@ -97,17 +108,13 @@ Composer.prototype.resetAutocomplete = function () {
}

Composer.prototype.focus = function () {
var self = this
self.node.focus()
this.node.focus()
}

Composer.prototype.hook = function (node) {
Composer.prototype.initAutoExpander = function () {
var self = this
self.node = node

// init for auto expander
setTimeout(function () {
node.setAttribute('aria-label', 'Enter a message and press enter')
var savedValue = self.node.value
self.node.value = ''
self.node.baseScrollHeight = self.node.scrollHeight
Expand Down
Loading