diff --git a/ape/talk.hoon b/ape/talk.hoon
index 61e53b612a..a03c4e8f6f 100644
--- a/ape/talk.hoon
+++ b/ape/talk.hoon
@@ -951,7 +951,6 @@
::
++ bind :: %bind
|= [cha=char pan=(unit (set partner))] ^+ ..sh-work
- ~& bind/[cha pan nik nak]
?~ pan $(pan [~ ?~(active.she passive.she u.active.she)])
=+ ole=(~(get by nik) u.pan)
?: =(ole [~ cha]) ..sh-work
@@ -1102,7 +1101,8 @@
(sh-slug lit)
=+ jub=(rust (tufa buf.say.she) sh-scad)
?~ jub (sh-fact %bel ~)
- =. +> (sh-work u.jub)
+ %. u.jub
+ =< sh-work
=+ buf=buf.say.she
=^ cal say.she (~(transmit sole say.she) [%set ~])
%- sh-fact
@@ -1111,7 +1111,7 @@
[%det cal]
?. ?=([%';' *] buf) ~
:_ ~
- [%txt (weld "----------------| " (tufa buf))]
+ [%txt (runt [14 '-'] `tape`['|' ' ' (tufa buf)])]
==
::
++ sh-sole :: apply edit
@@ -2040,7 +2040,8 @@
^- (quip move +>)
?~ saw [~ +>]
%+ etch-friend [%friend way] |= [man=span cuz=station]
- ~& [%reap-friend-fail man cuz u.saw]
+ =. u.saw [>%reap-friend-fail man cuz< u.saw]
+ %- (slog (flop u.saw))
ra-abet:(ra-quit:ra man cuz)
::
++ quit-friend ::
diff --git a/lib/urb.js b/lib/urb.js
index fcc0cbeb6e..b568ef4a85 100644
--- a/lib/urb.js
+++ b/lib/urb.js
@@ -20,6 +20,7 @@ window.urb.req = function(method,url,params,json,cb) {
if(params.wire) { _data.wire = params.wire; }
if(cb) {
xhr.onload = function() {
+ var err,res
try {
err = null
res = {
@@ -36,7 +37,9 @@ window.urb.req = function(method,url,params,json,cb) {
}
res = null
}
- cb(err,res)
+ finally {
+ cb(err,res)
+ }
}
xhr.onerror = function() {
cb({
@@ -64,7 +67,7 @@ window.urb.qreq = function(method,url,params,json,cb) {
walk = function() {
qobj = {}
qobj.oargs = window.urb.reqq[0]
- qobj.nargs = [].slice.apply(qobj.oargs,[0,4])
+ qobj.nargs = [].slice.call(qobj.oargs,0,4)
qobj.nargs.push(function(){
if(this.oargs[4])
this.oargs[4].apply(window.urb,arguments)
@@ -90,6 +93,7 @@ window.urb.send = function(data,params,cb) { // or send(data, cb)
params.ship = params.ship || this.ship
params.appl = params.appl || this.appl
params.mark = params.mark || $send.mark
+ // params.seqn = params.seqn || $send.seqn
params.wire = params.wire || "/"
params.xyro = (typeof(params.data) === 'undefined') ? null : params.data
@@ -100,17 +104,17 @@ window.urb.send = function(data,params,cb) { // or send(data, cb)
url = ["to",params.appl,params.mark]
url = "/~/"+url.join("/")
- $send.seqn++
+ // $send.seqn++
this.qreq('post',url,params,true,function(err,data) {
- if(err) { $send.seqn--; }
- else if(data && data.data.fail && urb.wall !== false)
+ /* if(err) { $send.seqn--; }
+ else */ if(data && data.data.fail && urb.wall !== false)
document.write("
"+JSON.stringify(params.xyro)+"\n"
+data.data.mess+"
") // XX
if(cb) { cb.apply(this,arguments); }
})
}
-window.urb.send.seqn = 0
+// window.urb.send.seqn = 0
window.urb.send.mark = "json"
@@ -139,6 +143,7 @@ window.urb.poll = function(params) {
$this = this
this.req("get",url,params,true,function(err,res) {
+ $this.poll.dely = params.dely || $this.poll.dely
if(res){
if(res.data.beat)
return $this.poll(params)
@@ -158,27 +163,25 @@ window.urb.poll = function(params) {
default:
throw new Error("Lost event %"+res.data.type)
}
- }
-
- dely = params.dely || $this.poll.dely
-
- if(err)
- dely = dely+Math.ceil(dely*.02)
- else {
- $this.poll.dely = 0
if(params.incs)
params.incs()
else
$this.poll.seqn++
+ $this.poll.dely = 250
+ return $this.poll(params)
}
-
- setTimeout(function() {
- $this.poll(params)
- },dely)
+
+ else if(err){
+ setTimeout(function() {
+ $this.poll(params)
+ }, $this.poll.dely)
+ $this.poll.dely += Math.ceil($this.poll.dely*.2)
+ }
+ else throw "Neither error nor result on poll"
})
}
window.urb.poll.seqn = 1
-window.urb.poll.dely = 0
+window.urb.poll.dely = 250
window.urb.bind = function(path, params, cb, nicecb){ // or bind(path, cb)
if(!params || typeof params === "function")
diff --git a/pub/docs/dev/hoon/tutorial/0-nouns.mdy b/pub/docs/dev/hoon/tutorial/0-nouns.mdy
index 55a9091793..a6ca503647 100644
--- a/pub/docs/dev/hoon/tutorial/0-nouns.mdy
+++ b/pub/docs/dev/hoon/tutorial/0-nouns.mdy
@@ -22,9 +22,9 @@ The main disadvantage of Hoon is that its syntax and semantics
are unfamiliar. The syntax will remind too many of Perl, but
like most human languages (and unlike Perl) it combines a regular
core structure with irregular variations. And Hoon's semantic
-is bounded by the size of the compiler: type inference plus code
-generation are 2000 lines of Hoon. Most peoples' experience is
-that the language is much easier to learn than it looks.
+complexity is bounded by the size of the compiler: type inference plus code
+generation are 2000 lines of Hoon. Most peoples' experience is that the
+language is much easier to learn than it looks.
> The name "Hoon" is from the Wallace Stevens poem, _Tea at the
Palaz of Hoon_. It also means "hooligan" in Australian.
@@ -71,6 +71,19 @@ as the range of a mold function. This mold can also be used to
validate or normalize untrusted, untyped data -- a common problem
in modern programming, because networks.
+> Sending a noun over the network is a good example of why Hoon
+is different. In a normal modern language, you serialize and
+deserialize a data type by extending your type to implement a
+serialization interface. A really good language can process your
+type definition and automatically generate this code. In Hoon,
+we have one function `jam` that converts any noun to an atom,
+and another `cue` that inverts `jam`. To validate, the receiver
+applies its own mold to the cued noun, and we've sent typed data
+over the network without any attack surface (except `jam` and
+`cue`, which fit on a page). No custom serialization code,
+manual or generated, is required. The mold itself is not sent;
+protocol agreement is out of band.
+
Hoon's inference algorithm is dumber than the unification
algorithms (Hindley-Milner) used in most typed functional
languages. Hoon thinks only forward, not backward. Eg, Haskell
@@ -78,26 +91,19 @@ can infer the result type of a function from its argument
(forward), or the argument type from the result (backward).
Hoon can do the first but not the second.
-So Hoon needs more manual typecasts, which you usually want
+So Hoon needs more manual annotations, which you usually want
anyway for prosaic software-engineering reasons. Otherwise its
typesystem solves more or less the same job, including
pattern-matching, genericity / typeclasses, etc.
-> Sending a noun over the network is a good example of why Hoon
-is different. In a normal modern language, you serialize and
-deserialize a data type by extending your type to implement a
-serialization interface. In Hoon, any value is just a noun, so
-we have one function (`jam`) that converts any noun to an atom,
-and another (`cue`) that is its inverse. To validate, the
-receiver runs its own mold on the cued noun, and we've sent typed
-data over the network without any attack surface (except `jam`
-and `cue`, which fit on a page). No custom serialization methods
-are required, and the mold itself is never sent; protocol
-agreement is out of band.
+> A good test of a static higher-order typesystem is whether it can
+infer the product type of a grammar defined as a combinator
+parser. The Hoon parser passes this test; when it typechecks,
+the parser's range nests within the span of the expression mold.
## Let's make some nouns
-Nouns aren't even slightly hard. Let's make a noun:
+Let's make a noun:
```
~tasfyn-partyv:dojo> 42
```
@@ -106,7 +112,7 @@ You'll see the expression you entered, then the result:
> 42
42
```
-Let's try a different value:
+Let's try a different noun. Or is it different?
```
~tasfyn-partyv:dojo> 0x2a
```
@@ -138,11 +144,11 @@ Let's make some cells. Try these on your own urbit:
We observe that cells associate right: `[a b c]` is just another
way of writing `[a [b c]]`.
-> Lisp veterans beware: Hoon `[a b]` is Lisp `(a . b)`, Lisp
-`(a b)` is Hoon `[a b ~]`(`~` represents nil, with a value of
-atom `0`). Lisp and Hoon are both pair-oriented languages down
-below, but Lisp has a layer of sugar that makes it look
-list-oriented. Hoon loves its "improper lists," ie, tuples.
+Lisp masters beware: Hoon `[a b]` is Lisp `(a . b)`, Lisp
+`(a b)` is Hoon `[a b ~]`. `~` means nil, with value zero. Lisp
+and Hoon are both pair-oriented languages down below, but Lisp
+has a layer of sugar that makes it look list-oriented. Hoon
+loves its "improper lists," ie, tuples.
## Looking at spans
@@ -169,15 +175,17 @@ type food chain.
## Looking at spans, part 2
-Good style in Hoon is concrete style. When a Hoon programmer
-defines an abstract semantic value in terms of a noun, we rarely
-put a conceptual layer of abstraction between value and noun. We
-think of the semantic value as an interpretation of the
-concrete noun, and often we just think of the noun.
+Usually, good style in Hoon is concrete style. When a Hoon
+programmer defines an abstract semantic value in terms of a noun,
+we rarely put a conceptual layer of abstraction between value and
+noun. We think of the value as an interpretation of the noun.
+We don't think of the noun as an implementation of the noun.
-With the `?` command, we *do* use an abstract layer, by printing
-our span noun in a custom syntax. But we can also look at the
-span noun directly, with the `??` command.
+But rules are made to be broken. With the `?` command, we *do*
+use an abstract layer, by printing our span noun in that custom
+syntax. But we can also look at the span noun directly, with the
+`??` command. As we'll see, `??` is mainly for newbies, but
+newbies love it.
```
~tasfyn-partyv:dojo> ?? 42
@@ -228,12 +236,12 @@ numbers we've just been using, and make them constants:
%42
```
-> Spans are an exception to the concrete style, because we use
-"manual laziness" to define recursive structures. A recursive
-span contains Hoon code which is evaluated to apply it. In
-practice, it often contains the entire Urbit kernel, so you
-wouldn't want to try to print it in the dojo. If you find
-`??` taking a weirdly long time, this may have happened; just
+> Why `??`? Spans are an exception to concrete style, because they
+use "manual laziness" to define logically recursive structures.
+A recursive span contains Hoon code which is evaluated to apply
+it. In practice, this noun often contains the entire Urbit
+kernel, so you wouldn't want to try to print it in the dojo. If
+you find `??` taking a weirdly long time, this may have happened;
press ^C.
## Our first mold
diff --git a/pub/docs/user/talk.mdy b/pub/docs/user/talk.mdy
index 022a06cfa1..d0f1d7d2d4 100644
--- a/pub/docs/user/talk.mdy
+++ b/pub/docs/user/talk.mdy
@@ -62,7 +62,7 @@ And hit return. Don't worry, no one but you will see this. The
It's boring to post to yourself. Let's join a station:
- ~fintud-macrep: ;join /urbit-meta
+ ~fintud-macrep: ;join ~doznec/urbit-meta
(`/urbit-meta` is a federal station, meaning it's hosted by your
star (for `~fintud-macrep`, `~doznec`). The `/` notation is just
diff --git a/pub/talk/src/css/main.css b/pub/talk/src/css/main.css
index ff5ff9e545..5b4b9859f0 100644
--- a/pub/talk/src/css/main.css
+++ b/pub/talk/src/css/main.css
@@ -591,6 +591,15 @@ a {
font-size: 0.8rem;
text-transform: uppercase;
}
+body:not(.offline) #offline {
+ display: none;
+}
+#offline {
+ transition: color 0.25s ease;
+}
+#offline.error {
+ color: #f00;
+}
@media only screen and (min-width: 1024px) {
#station-container:hover {
max-height: 30rem;
diff --git a/pub/talk/src/css/main.styl b/pub/talk/src/css/main.styl
index fca4bde7fd..0aa6ac43eb 100644
--- a/pub/talk/src/css/main.styl
+++ b/pub/talk/src/css/main.styl
@@ -549,4 +549,17 @@ a
font-size .8rem
text-transform uppercase
+//
+// offline
+//
+
+body:not(.offline) #offline
+ display none
+
+#offline
+ transition: color 0.25s ease
+
+#offline.error
+ color: red
+
@import 'mobile'
diff --git a/pub/talk/src/js/actions/MessageActions.coffee b/pub/talk/src/js/actions/MessageActions.coffee
index 95473cf49c..6843bfcd5f 100644
--- a/pub/talk/src/js/actions/MessageActions.coffee
+++ b/pub/talk/src/js/actions/MessageActions.coffee
@@ -1,33 +1,26 @@
-MessageDispatcher = require '../dispatcher/Dispatcher.coffee'
+Dispatcher = require '../dispatcher/Dispatcher.coffee'
-module.exports =
- loadMessages: (grams,get) ->
- MessageDispatcher.handleServerAction
- type:"messages-load"
- messages:grams.tele
- last:grams.num
- get:get
+_persistence = require '../persistence/MessagePersistence.coffee'
+
+Persistence = _persistence MessageActions: module.exports =
+ loadMessages: (messages,last,get) ->
+ Dispatcher.handleServerAction {messages,last,get,type:"messages-load"}
listenStation: (station,date) ->
if not date then date = window.urb.util.toDate(new Date())
- window.talk.MessagePersistence.listenStation station,date
+ Persistence.listenStation station,date
listeningStation: (station) ->
- MessageDispatcher.handleViewAction
- type:"messages-listen"
- station:station
+ Dispatcher.handleViewAction {station,type:"messages-listen"}
setTyping: (state) ->
- MessageDispatcher.handleViewAction
- type:"messages-typing"
- state:state
+ Dispatcher.handleViewAction {state,type:"messages-typing"}
getMore: (station,start,end) ->
- MessageDispatcher.handleViewAction
- type:"messages-fetch"
- window.talk.MessagePersistence.get station,start,end
+ Dispatcher.handleViewAction type:"messages-fetch"
+ Persistence.get station,start,end
- sendMessage: (message,audience) ->
+ sendMessage: (txt,audience) ->
serial = window.util.uuid32()
# audience.push window.util.mainStationPath window.urb.user
@@ -41,20 +34,17 @@ module.exports =
sender:null
delivery:"pending"
- speech =
- lin:
- say:true
- txt:message
+ speech = lin: {txt, say:true}
- if message[0] is "@"
+ if txt[0] is "@"
speech.lin.txt = speech.lin.txt.slice(1).trim()
speech.lin.say = false
- else if message[0] is "#"
+ else if txt[0] is "#"
speech = eval: speech.lin.txt.slice(1).trim()
- else if window.urb.util.isURL(message)
- speech = url: message
+ else if window.urb.util.isURL(txt)
+ speech = url: txt
speeches =
if not (speech.lin?.txt.length > 64)
@@ -70,7 +60,7 @@ module.exports =
}
for speech in speeches
- _message =
+ message =
ship:window.urb.ship
thought:
serial:window.util.uuid32()
@@ -80,8 +70,6 @@ module.exports =
speech:speech
date: Date.now()
- MessageDispatcher.handleViewAction
- type:"message-send"
- message:_message
- window.talk.MessagePersistence.sendMessage _message.thought
+ Dispatcher.handleViewAction {message,type:"message-send"}
+ Persistence.sendMessage message.thought
diff --git a/pub/talk/src/js/actions/StationActions.coffee b/pub/talk/src/js/actions/StationActions.coffee
index 394c09b2fd..2ea5664881 100644
--- a/pub/talk/src/js/actions/StationActions.coffee
+++ b/pub/talk/src/js/actions/StationActions.coffee
@@ -1,76 +1,31 @@
-StationDispatcher = require '../dispatcher/Dispatcher.coffee'
+Dispatcher = require '../dispatcher/Dispatcher.coffee'
+serverAction = (f)-> ()-> Dispatcher.handleServerAction f.apply this,arguments
+viewAction = (f)-> ()-> Dispatcher.handleViewAction f.apply this,arguments
-module.exports =
- loadConfig: (station,config) ->
- StationDispatcher.handleServerAction
- type: "config-load"
- station:station
- config:config
+_persistence = require '../persistence/StationPersistence.coffee'
+
+Persistence = _persistence StationActions: module.exports =
+ loadGlyphs: serverAction (glyphs) -> {glyphs,type:"glyphs-load"}
+ loadMembers: serverAction (members) -> {members,type:"members-load"}
+ loadStations: serverAction (stations) -> {stations,type:"stations-load"}
+ loadConfig: serverAction (station,config) -> {station,config,type:"config-load"}
- loadGlyphs: (glyphs) ->
- StationDispatcher.handleServerAction
- type: "glyphs-load"
- station:station
- glyphs:glyphs
-
- switchStation: (station) ->
- StationDispatcher.handleViewAction
- type:"station-switch"
- station:station
-
- setAudience: (audience) ->
- StationDispatcher.handleViewAction
- type:"station-set-audience"
- audience:audience
-
- setValidAudience: (valid) ->
- StationDispatcher.handleViewAction
- type:"station-set-valid-audience"
- valid:valid
-
- toggleAudience: (station) ->
- StationDispatcher.handleViewAction
- type:"station-audience-toggle"
- station:station
-
- removeStation: (station) ->
- window.talk.StationPersistence.removeStation station
-
- setSources: (station,sources) ->
- window.talk.StationPersistence.setSources station,window.urb.ship,sources
-
- createStation: (name) ->
- window.talk.StationPersistence.createStation name
-
- listenStation: (station) ->
- window.talk.StationPersistence.listenStation station
-
- listeningStation: (station) ->
- StationDispatcher.handleViewAction
- type:"station-listen"
- station:station
-
- setTyping: (station,state) ->
- StationDispatcher.handleViewAction
- type:"typing-set"
- station:station
- state:state
-
- ping: (_ping) ->
- window.talk.StationPersistence.ping _ping
-
- loadStations: (stations) ->
- StationDispatcher.handleServerAction
- type:"stations-load"
- stations:stations
-
- loadMembers: (members) ->
- StationDispatcher.handleServerAction
- type:"members-load"
- members:members
+ setTyping: viewAction (station,state) -> {station,state,type:"typing-set"}
+ setAudience: viewAction (audience) -> {audience,type:"station-set-audience"}
+ setValidAudience: viewAction (valid) -> {valid,type:"station-set-valid-audience"}
+ toggleAudience: viewAction (station) -> {station,type:"station-audience-toggle"}
+ switchStation: viewAction (station) -> {station,type:"station-switch"}
+ listeningStation: viewAction (station) -> {station,type:"station-listen"}
createStation: (station) ->
- StationDispatcher.handleViewAction
- type: "station-create"
- station: station
- window.talk.StationPersistence.createStation station
+ Dispatcher.handleViewAction {station,type: "station-create"}
+ Persistence.createStation station
+
+ listen: () -> Persistence.listen()
+ ping: (_ping) -> Persistence.ping _ping
+ removeStation: (station) -> Persistence.removeStation station
+ listenStation: (station) -> Persistence.listenStation station
+ createStation: (name) -> Persistence.createStation name
+
+ setSources: (station,sources) ->
+ Persistence.setSources station,window.urb.ship,sources
diff --git a/pub/talk/src/js/components/StationComponent.coffee b/pub/talk/src/js/components/StationComponent.coffee
index e2487dc62c..f6973e0282 100644
--- a/pub/talk/src/js/components/StationComponent.coffee
+++ b/pub/talk/src/js/components/StationComponent.coffee
@@ -1,17 +1,12 @@
recl = React.createClass
-[div,input,textarea,h1,a] = [
- React.DOM.div,
- React.DOM.input,
- React.DOM.textarea,
- React.DOM.h1,
- React.DOM.a
-]
+{div,style,input,textarea,h1,a} = React.DOM
StationStore = require '../stores/StationStore.coffee'
StationActions = require '../actions/StationActions.coffee'
Member = require './MemberComponent.coffee'
module.exports = recl
+ displayName: "Station"
stateFromStore: -> {
audi:StationStore.getAudience()
members:StationStore.getMembers()
@@ -88,7 +83,7 @@ module.exports = recl
else
members = ""
- sourceInput = [(input {className:"join",onKeyUp:@_keyUp,placeholder:"+"}, "")]
+ sourceInput = [(input {className:"join",onKeyUp:@_keyUp,placeholder:"+"})]
sourceCtrl = div {className:"sour-ctrl"},sourceInput
sources = []
@@ -103,21 +98,19 @@ module.exports = recl
else
sources = ""
- head = (div {id:"head"},
- [ (div {id:"who"},[
- (div {className:"sig"},"")
- (div {className:"ship"},"#{window.urb.user}")
- ])
- (div {id:"where"},[
- (div {className:"slat"},"talk")
- (div {className:"path"},"") #window.util.mainStation(window.urb.user))
- (div {className:"caret"},"")
- ])
- ]
+ (div {id:"station",onClick:@_toggleOpen},
+ (div {id:"head"},
+ (div {id:"who"},
+ div {className:"sig"}
+ div {className:"ship"},"#{window.urb.user}"
+ )
+ (div {id:"where"},
+ div {className:"slat"},"talk"
+ div {className:"path"} #, window.util.mainStation(window.urb.user))
+ div {className:"caret"}
+ )
+ div {id:"offline"}, "Warning: no connection to server."
)
-
- parts.push head
- parts.push (div {id:"stations"}, [(h1 {}, "Listening to"),(div {},sources),sourceCtrl])
- parts.push (div {id:"audience"}, (div {},[(h1 {}, "Talking to"),(div {id:"members"},members)]))
-
- div {id:"station",onClick:@_toggleOpen},parts
+ div {id:"stations"}, (h1 {}, "Listening to"),(div {},sources),sourceCtrl
+ div {id:"audience"}, div {}, (h1 {}, "Talking to"),(div {id:"members"},members)
+ )
diff --git a/pub/talk/src/js/components/WritingComponent.coffee b/pub/talk/src/js/components/WritingComponent.coffee
index 640ecee530..fd8bf36bff 100644
--- a/pub/talk/src/js/components/WritingComponent.coffee
+++ b/pub/talk/src/js/components/WritingComponent.coffee
@@ -1,6 +1,8 @@
recl = React.createClass
{div,br,input,textarea} = React.DOM
+husl = require 'husl'
+
MessageActions = require '../actions/MessageActions.coffee'
MessageStore = require '../stores/MessageStore.coffee'
StationActions = require '../actions/StationActions.coffee'
@@ -149,7 +151,13 @@ module.exports = recl
txt = @$writing.text()
e.preventDefault()
if txt.length > 0
- @sendMessage()
+ if window.talk.online
+ @sendMessage()
+ else
+ #@errHue = ((@errHue || 0) + (Math.random() * 300) + 30) % 360
+ #$('#offline').css color: husl.toHex @errHue, 90, 50
+ $('#offline').addClass('error').one 'transitionend',
+ -> $('#offline').removeClass 'error'
return false
@onInput()
@set()
diff --git a/pub/talk/src/js/main.coffee b/pub/talk/src/js/main.coffee
index 984fbecf1c..2ac64c7117 100644
--- a/pub/talk/src/js/main.coffee
+++ b/pub/talk/src/js/main.coffee
@@ -1,11 +1,17 @@
$(() ->
- StationActions = require './actions/StationActions.coffee'
+ StationActions = require './actions/StationActions.coffee' #start poll
rend = React.render
window.talk = {}
- window.talk.MessagePersistence = require './persistence/MessagePersistence.coffee'
- window.talk.StationPersistence = require './persistence/StationPersistence.coffee'
+ window.talk.online = yes
+
+ setInterval (->
+ window.talk.online = window.urb.poll.dely < 500
+ if window.talk.online
+ $('body').removeClass 'offline'
+ else $('body').addClass 'offline'
+ ), 300
require './util.coffee'
require './move.coffee'
@@ -16,8 +22,9 @@ $(() ->
# else
# $('#nav').removeClass 'scrolling'
# setInterval checkScroll, 500
+
- window.talk.StationPersistence.listen()
+ StationActions.listen()
StationComponent = require './components/StationComponent.coffee'
MessagesComponent = require './components/MessagesComponent.coffee'
diff --git a/pub/talk/src/js/main.js b/pub/talk/src/js/main.js
index 943d99c975..3c5d2a4fd0 100644
--- a/pub/talk/src/js/main.js
+++ b/pub/talk/src/js/main.js
@@ -1,206 +1,228 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 64) ? [speech] : ((ref1 = speech.lin, say = ref1.say, txt = ref1.txt, ref1), txt.match(/(.{1,64}$|.{0,64} |.{64}|.+$)/g).map(function(s, i) {
- say || (say = i !== 0);
- return {
- lin: {
- say: say,
- txt: s.slice(-1 !== " ") ? s : s.slice(0, -1)
- }
- };
- }));
- results = [];
- for (j = 0, len = speeches.length; j < len; j++) {
- speech = speeches[j];
- _message = {
- ship: window.urb.ship,
- thought: {
- serial: window.util.uuid32(),
- audience: _audi,
- statement: {
- bouquet: [],
- speech: speech,
- date: Date.now()
- }
- }
- };
- MessageDispatcher.handleViewAction({
- type: "message-send",
- message: _message
+_persistence = require('../persistence/MessagePersistence.coffee');
+
+Persistence = _persistence({
+ MessageActions: module.exports = {
+ loadMessages: function(messages, last, get) {
+ return Dispatcher.handleServerAction({
+ messages: messages,
+ last: last,
+ get: get,
+ type: "messages-load"
});
- results.push(window.talk.MessagePersistence.sendMessage(_message.thought));
+ },
+ listenStation: function(station, date) {
+ if (!date) {
+ date = window.urb.util.toDate(new Date());
+ }
+ return Persistence.listenStation(station, date);
+ },
+ listeningStation: function(station) {
+ return Dispatcher.handleViewAction({
+ station: station,
+ type: "messages-listen"
+ });
+ },
+ setTyping: function(state) {
+ return Dispatcher.handleViewAction({
+ state: state,
+ type: "messages-typing"
+ });
+ },
+ getMore: function(station, start, end) {
+ Dispatcher.handleViewAction({
+ type: "messages-fetch"
+ });
+ return Persistence.get(station, start, end);
+ },
+ sendMessage: function(txt, audience) {
+ var _audi, j, k, len, message, ref, ref1, results, say, serial, speech, speeches, v;
+ serial = window.util.uuid32();
+ audience = _.uniq(audience);
+ _audi = {};
+ for (k in audience) {
+ v = audience[k];
+ _audi[v] = {
+ envelope: {
+ visible: true,
+ sender: null
+ },
+ delivery: "pending"
+ };
+ }
+ speech = {
+ lin: {
+ txt: txt,
+ say: true
+ }
+ };
+ if (txt[0] === "@") {
+ speech.lin.txt = speech.lin.txt.slice(1).trim();
+ speech.lin.say = false;
+ } else if (txt[0] === "#") {
+ speech = {
+ "eval": speech.lin.txt.slice(1).trim()
+ };
+ } else if (window.urb.util.isURL(txt)) {
+ speech = {
+ url: txt
+ };
+ }
+ speeches = !(((ref = speech.lin) != null ? ref.txt.length : void 0) > 64) ? [speech] : ((ref1 = speech.lin, say = ref1.say, txt = ref1.txt, ref1), txt.match(/(.{1,64}$|.{0,64} |.{64}|.+$)/g).map(function(s, i) {
+ say || (say = i !== 0);
+ return {
+ lin: {
+ say: say,
+ txt: s.slice(-1 !== " ") ? s : s.slice(0, -1)
+ }
+ };
+ }));
+ results = [];
+ for (j = 0, len = speeches.length; j < len; j++) {
+ speech = speeches[j];
+ message = {
+ ship: window.urb.ship,
+ thought: {
+ serial: window.util.uuid32(),
+ audience: _audi,
+ statement: {
+ bouquet: [],
+ speech: speech,
+ date: Date.now()
+ }
+ }
+ };
+ Dispatcher.handleViewAction({
+ message: message,
+ type: "message-send"
+ });
+ results.push(Persistence.sendMessage(message.thought));
+ }
+ return results;
}
- return results;
}
+});
+
+
+
+},{"../dispatcher/Dispatcher.coffee":7,"../persistence/MessagePersistence.coffee":19}],2:[function(require,module,exports){
+var Dispatcher, Persistence, _persistence, serverAction, viewAction;
+
+Dispatcher = require('../dispatcher/Dispatcher.coffee');
+
+serverAction = function(f) {
+ return function() {
+ return Dispatcher.handleServerAction(f.apply(this, arguments));
+ };
};
-
-
-},{"../dispatcher/Dispatcher.coffee":7}],2:[function(require,module,exports){
-var StationDispatcher;
-
-StationDispatcher = require('../dispatcher/Dispatcher.coffee');
-
-module.exports = {
- loadConfig: function(station, config) {
- return StationDispatcher.handleServerAction({
- type: "config-load",
- station: station,
- config: config
- });
- },
- loadGlyphs: function(glyphs) {
- return StationDispatcher.handleServerAction({
- type: "glyphs-load",
- station: station,
- glyphs: glyphs
- });
- },
- switchStation: function(station) {
- return StationDispatcher.handleViewAction({
- type: "station-switch",
- station: station
- });
- },
- setAudience: function(audience) {
- return StationDispatcher.handleViewAction({
- type: "station-set-audience",
- audience: audience
- });
- },
- setValidAudience: function(valid) {
- return StationDispatcher.handleViewAction({
- type: "station-set-valid-audience",
- valid: valid
- });
- },
- toggleAudience: function(station) {
- return StationDispatcher.handleViewAction({
- type: "station-audience-toggle",
- station: station
- });
- },
- removeStation: function(station) {
- return window.talk.StationPersistence.removeStation(station);
- },
- setSources: function(station, sources) {
- return window.talk.StationPersistence.setSources(station, window.urb.ship, sources);
- },
- createStation: function(name) {
- return window.talk.StationPersistence.createStation(name);
- },
- listenStation: function(station) {
- return window.talk.StationPersistence.listenStation(station);
- },
- listeningStation: function(station) {
- return StationDispatcher.handleViewAction({
- type: "station-listen",
- station: station
- });
- },
- setTyping: function(station, state) {
- return StationDispatcher.handleViewAction({
- type: "typing-set",
- station: station,
- state: state
- });
- },
- ping: function(_ping) {
- return window.talk.StationPersistence.ping(_ping);
- },
- loadStations: function(stations) {
- return StationDispatcher.handleServerAction({
- type: "stations-load",
- stations: stations
- });
- },
- loadMembers: function(members) {
- return StationDispatcher.handleServerAction({
- type: "members-load",
- members: members
- });
- },
- createStation: function(station) {
- StationDispatcher.handleViewAction({
- type: "station-create",
- station: station
- });
- return window.talk.StationPersistence.createStation(station);
- }
+viewAction = function(f) {
+ return function() {
+ return Dispatcher.handleViewAction(f.apply(this, arguments));
+ };
};
+_persistence = require('../persistence/StationPersistence.coffee');
+
+Persistence = _persistence({
+ StationActions: module.exports = {
+ loadGlyphs: serverAction(function(glyphs) {
+ return {
+ glyphs: glyphs,
+ type: "glyphs-load"
+ };
+ }),
+ loadMembers: serverAction(function(members) {
+ return {
+ members: members,
+ type: "members-load"
+ };
+ }),
+ loadStations: serverAction(function(stations) {
+ return {
+ stations: stations,
+ type: "stations-load"
+ };
+ }),
+ loadConfig: serverAction(function(station, config) {
+ return {
+ station: station,
+ config: config,
+ type: "config-load"
+ };
+ }),
+ setTyping: viewAction(function(station, state) {
+ return {
+ station: station,
+ state: state,
+ type: "typing-set"
+ };
+ }),
+ setAudience: viewAction(function(audience) {
+ return {
+ audience: audience,
+ type: "station-set-audience"
+ };
+ }),
+ setValidAudience: viewAction(function(valid) {
+ return {
+ valid: valid,
+ type: "station-set-valid-audience"
+ };
+ }),
+ toggleAudience: viewAction(function(station) {
+ return {
+ station: station,
+ type: "station-audience-toggle"
+ };
+ }),
+ switchStation: viewAction(function(station) {
+ return {
+ station: station,
+ type: "station-switch"
+ };
+ }),
+ listeningStation: viewAction(function(station) {
+ return {
+ station: station,
+ type: "station-listen"
+ };
+ }),
+ createStation: function(station) {
+ Dispatcher.handleViewAction({
+ station: station,
+ type: "station-create"
+ });
+ return Persistence.createStation(station);
+ },
+ listen: function() {
+ return Persistence.listen();
+ },
+ ping: function(_ping) {
+ return Persistence.ping(_ping);
+ },
+ removeStation: function(station) {
+ return Persistence.removeStation(station);
+ },
+ listenStation: function(station) {
+ return Persistence.listenStation(station);
+ },
+ createStation: function(name) {
+ return Persistence.createStation(name);
+ },
+ setSources: function(station, sources) {
+ return Persistence.setSources(station, window.urb.ship, sources);
+ }
+ }
+});
-},{"../dispatcher/Dispatcher.coffee":7}],3:[function(require,module,exports){
+
+},{"../dispatcher/Dispatcher.coffee":7,"../persistence/StationPersistence.coffee":20}],3:[function(require,module,exports){
var div, input, recl, ref, textarea;
recl = React.createClass;
@@ -532,12 +554,12 @@ module.exports = recl({
-},{"../actions/MessageActions.coffee":1,"../actions/StationActions.coffee":2,"../stores/MessageStore.coffee":20,"../stores/StationStore.coffee":21,"./MemberComponent.coffee":3,"classnames":10,"moment-timezone":15}],5:[function(require,module,exports){
-var Member, StationActions, StationStore, a, div, h1, input, recl, ref, textarea;
+},{"../actions/MessageActions.coffee":1,"../actions/StationActions.coffee":2,"../stores/MessageStore.coffee":21,"../stores/StationStore.coffee":22,"./MemberComponent.coffee":3,"classnames":10,"moment-timezone":16}],5:[function(require,module,exports){
+var Member, StationActions, StationStore, a, div, h1, input, recl, ref, style, textarea;
recl = React.createClass;
-ref = [React.DOM.div, React.DOM.input, React.DOM.textarea, React.DOM.h1, React.DOM.a], div = ref[0], input = ref[1], textarea = ref[2], h1 = ref[3], a = ref[4];
+ref = React.DOM, div = ref.div, style = ref.style, input = ref.input, textarea = ref.textarea, h1 = ref.h1, a = ref.a;
StationStore = require('../stores/StationStore.coffee');
@@ -546,6 +568,7 @@ StationActions = require('../actions/StationActions.coffee');
Member = require('./MemberComponent.coffee');
module.exports = recl({
+ displayName: "Station",
stateFromStore: function() {
return {
audi: StationStore.getAudience(),
@@ -624,7 +647,7 @@ module.exports = recl({
return StationActions.setSources(this.state.station, _sources);
},
render: function() {
- var _remove, _sources, head, members, parts, sourceCtrl, sourceInput, sources;
+ var _remove, _sources, members, parts, sourceCtrl, sourceInput, sources;
parts = [];
members = [];
if (this.state.station && this.state.members) {
@@ -649,7 +672,7 @@ module.exports = recl({
className: "join",
onKeyUp: this._keyUp,
placeholder: "+"
- }, "")
+ })
];
sourceCtrl = div({
className: "sour-ctrl"
@@ -676,56 +699,48 @@ module.exports = recl({
} else {
sources = "";
}
- head = div({
- id: "head"
- }, [
- div({
- id: "who"
- }, [
- div({
- className: "sig"
- }, ""), div({
- className: "ship"
- }, "" + window.urb.user)
- ]), div({
- id: "where"
- }, [
- div({
- className: "slat"
- }, "talk"), div({
- className: "path"
- }, ""), div({
- className: "caret"
- }, "")
- ])
- ]);
- parts.push(head);
- parts.push(div({
- id: "stations"
- }, [h1({}, "Listening to"), div({}, sources), sourceCtrl]));
- parts.push(div({
- id: "audience"
- }, div({}, [
- h1({}, "Talking to"), div({
- id: "members"
- }, members)
- ])));
return div({
id: "station",
onClick: this._toggleOpen
- }, parts);
+ }, div({
+ id: "head"
+ }, div({
+ id: "who"
+ }, div({
+ className: "sig"
+ }), div({
+ className: "ship"
+ }, "" + window.urb.user)), div({
+ id: "where"
+ }, div({
+ className: "slat"
+ }, "talk"), div({
+ className: "path"
+ }), div({
+ className: "caret"
+ })), div({
+ id: "offline"
+ }, "Warning: no connection to server.")), div({
+ id: "stations"
+ }, h1({}, "Listening to"), div({}, sources), sourceCtrl), div({
+ id: "audience"
+ }, div({}, h1({}, "Talking to"), div({
+ id: "members"
+ }, members))));
}
});
-},{"../actions/StationActions.coffee":2,"../stores/StationStore.coffee":21,"./MemberComponent.coffee":3}],6:[function(require,module,exports){
-var Audience, Member, MessageActions, MessageStore, PO, SHIPSHAPE, StationActions, StationStore, br, div, input, recl, ref, textarea;
+},{"../actions/StationActions.coffee":2,"../stores/StationStore.coffee":22,"./MemberComponent.coffee":3}],6:[function(require,module,exports){
+var Audience, Member, MessageActions, MessageStore, PO, SHIPSHAPE, StationActions, StationStore, br, div, husl, input, recl, ref, textarea;
recl = React.createClass;
ref = React.DOM, div = ref.div, br = ref.br, input = ref.input, textarea = ref.textarea;
+husl = require('husl');
+
MessageActions = require('../actions/MessageActions.coffee');
MessageStore = require('../stores/MessageStore.coffee');
@@ -861,7 +876,13 @@ module.exports = recl({
txt = this.$writing.text();
e.preventDefault();
if (txt.length > 0) {
- this.sendMessage();
+ if (window.talk.online) {
+ this.sendMessage();
+ } else {
+ $('#offline').addClass('error').one('transitionend', function() {
+ return $('#offline').removeClass('error');
+ });
+ }
}
return false;
}
@@ -1009,7 +1030,7 @@ module.exports = recl({
-},{"../actions/MessageActions.coffee":1,"../actions/StationActions.coffee":2,"../stores/MessageStore.coffee":20,"../stores/StationStore.coffee":21,"./MemberComponent.coffee":3}],7:[function(require,module,exports){
+},{"../actions/MessageActions.coffee":1,"../actions/StationActions.coffee":2,"../stores/MessageStore.coffee":21,"../stores/StationStore.coffee":22,"./MemberComponent.coffee":3,"husl":14}],7:[function(require,module,exports){
var Dispatcher;
Dispatcher = require('flux').Dispatcher;
@@ -1037,11 +1058,18 @@ $(function() {
StationActions = require('./actions/StationActions.coffee');
rend = React.render;
window.talk = {};
- window.talk.MessagePersistence = require('./persistence/MessagePersistence.coffee');
- window.talk.StationPersistence = require('./persistence/StationPersistence.coffee');
+ window.talk.online = true;
+ setInterval((function() {
+ window.talk.online = window.urb.poll.dely < 500;
+ if (window.talk.online) {
+ return $('body').removeClass('offline');
+ } else {
+ return $('body').addClass('offline');
+ }
+ }), 300);
require('./util.coffee');
require('./move.coffee');
- window.talk.StationPersistence.listen();
+ StationActions.listen();
StationComponent = require('./components/StationComponent.coffee');
MessagesComponent = require('./components/MessagesComponent.coffee');
WritingComponent = require('./components/WritingComponent.coffee');
@@ -1053,7 +1081,7 @@ $(function() {
-},{"./actions/StationActions.coffee":2,"./components/MessagesComponent.coffee":4,"./components/StationComponent.coffee":5,"./components/WritingComponent.coffee":6,"./move.coffee":9,"./persistence/MessagePersistence.coffee":18,"./persistence/StationPersistence.coffee":19,"./util.coffee":22}],9:[function(require,module,exports){
+},{"./actions/StationActions.coffee":2,"./components/MessagesComponent.coffee":4,"./components/StationComponent.coffee":5,"./components/WritingComponent.coffee":6,"./move.coffee":9,"./util.coffee":23}],9:[function(require,module,exports){
var ldy, setSo, so;
so = {};
@@ -1524,6 +1552,390 @@ var invariant = function(condition, format, a, b, c, d, e, f) {
module.exports = invariant;
},{}],14:[function(require,module,exports){
+// Generated by CoffeeScript 1.9.3
+(function() {
+ var L_to_Y, Y_to_L, conv, distanceFromPole, dotProduct, epsilon, fromLinear, getBounds, intersectLineLine, kappa, lengthOfRayUntilIntersect, m, m_inv, maxChromaForLH, maxSafeChromaForL, refU, refV, root, toLinear;
+
+ m = {
+ R: [3.2409699419045214, -1.5373831775700935, -0.49861076029300328],
+ G: [-0.96924363628087983, 1.8759675015077207, 0.041555057407175613],
+ B: [0.055630079696993609, -0.20397695888897657, 1.0569715142428786]
+ };
+
+ m_inv = {
+ X: [0.41239079926595948, 0.35758433938387796, 0.18048078840183429],
+ Y: [0.21263900587151036, 0.71516867876775593, 0.072192315360733715],
+ Z: [0.019330818715591851, 0.11919477979462599, 0.95053215224966058]
+ };
+
+ refU = 0.19783000664283681;
+
+ refV = 0.468319994938791;
+
+ kappa = 903.2962962962963;
+
+ epsilon = 0.0088564516790356308;
+
+ getBounds = function(L) {
+ var bottom, channel, j, k, len1, len2, m1, m2, m3, ref, ref1, ref2, ret, sub1, sub2, t, top1, top2;
+ sub1 = Math.pow(L + 16, 3) / 1560896;
+ sub2 = sub1 > epsilon ? sub1 : L / kappa;
+ ret = [];
+ ref = ['R', 'G', 'B'];
+ for (j = 0, len1 = ref.length; j < len1; j++) {
+ channel = ref[j];
+ ref1 = m[channel], m1 = ref1[0], m2 = ref1[1], m3 = ref1[2];
+ ref2 = [0, 1];
+ for (k = 0, len2 = ref2.length; k < len2; k++) {
+ t = ref2[k];
+ top1 = (284517 * m1 - 94839 * m3) * sub2;
+ top2 = (838422 * m3 + 769860 * m2 + 731718 * m1) * L * sub2 - 769860 * t * L;
+ bottom = (632260 * m3 - 126452 * m2) * sub2 + 126452 * t;
+ ret.push([top1 / bottom, top2 / bottom]);
+ }
+ }
+ return ret;
+ };
+
+ intersectLineLine = function(line1, line2) {
+ return (line1[1] - line2[1]) / (line2[0] - line1[0]);
+ };
+
+ distanceFromPole = function(point) {
+ return Math.sqrt(Math.pow(point[0], 2) + Math.pow(point[1], 2));
+ };
+
+ lengthOfRayUntilIntersect = function(theta, line) {
+ var b1, len, m1;
+ m1 = line[0], b1 = line[1];
+ len = b1 / (Math.sin(theta) - m1 * Math.cos(theta));
+ if (len < 0) {
+ return null;
+ }
+ return len;
+ };
+
+ maxSafeChromaForL = function(L) {
+ var b1, j, len1, lengths, m1, ref, ref1, x;
+ lengths = [];
+ ref = getBounds(L);
+ for (j = 0, len1 = ref.length; j < len1; j++) {
+ ref1 = ref[j], m1 = ref1[0], b1 = ref1[1];
+ x = intersectLineLine([m1, b1], [-1 / m1, 0]);
+ lengths.push(distanceFromPole([x, b1 + x * m1]));
+ }
+ return Math.min.apply(Math, lengths);
+ };
+
+ maxChromaForLH = function(L, H) {
+ var hrad, j, l, len1, lengths, line, ref;
+ hrad = H / 360 * Math.PI * 2;
+ lengths = [];
+ ref = getBounds(L);
+ for (j = 0, len1 = ref.length; j < len1; j++) {
+ line = ref[j];
+ l = lengthOfRayUntilIntersect(hrad, line);
+ if (l !== null) {
+ lengths.push(l);
+ }
+ }
+ return Math.min.apply(Math, lengths);
+ };
+
+ dotProduct = function(a, b) {
+ var i, j, ref, ret;
+ ret = 0;
+ for (i = j = 0, ref = a.length - 1; 0 <= ref ? j <= ref : j >= ref; i = 0 <= ref ? ++j : --j) {
+ ret += a[i] * b[i];
+ }
+ return ret;
+ };
+
+ fromLinear = function(c) {
+ if (c <= 0.0031308) {
+ return 12.92 * c;
+ } else {
+ return 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
+ }
+ };
+
+ toLinear = function(c) {
+ var a;
+ a = 0.055;
+ if (c > 0.04045) {
+ return Math.pow((c + a) / (1 + a), 2.4);
+ } else {
+ return c / 12.92;
+ }
+ };
+
+ conv = {
+ 'xyz': {},
+ 'luv': {},
+ 'lch': {},
+ 'husl': {},
+ 'huslp': {},
+ 'rgb': {},
+ 'hex': {}
+ };
+
+ conv.xyz.rgb = function(tuple) {
+ var B, G, R;
+ R = fromLinear(dotProduct(m.R, tuple));
+ G = fromLinear(dotProduct(m.G, tuple));
+ B = fromLinear(dotProduct(m.B, tuple));
+ return [R, G, B];
+ };
+
+ conv.rgb.xyz = function(tuple) {
+ var B, G, R, X, Y, Z, rgbl;
+ R = tuple[0], G = tuple[1], B = tuple[2];
+ rgbl = [toLinear(R), toLinear(G), toLinear(B)];
+ X = dotProduct(m_inv.X, rgbl);
+ Y = dotProduct(m_inv.Y, rgbl);
+ Z = dotProduct(m_inv.Z, rgbl);
+ return [X, Y, Z];
+ };
+
+ Y_to_L = function(Y) {
+ if (Y <= epsilon) {
+ return Y * kappa;
+ } else {
+ return 116 * Math.pow(Y, 1 / 3) - 16;
+ }
+ };
+
+ L_to_Y = function(L) {
+ if (L <= 8) {
+ return L / kappa;
+ } else {
+ return Math.pow((L + 16) / 116, 3);
+ }
+ };
+
+ conv.xyz.luv = function(tuple) {
+ var L, U, V, X, Y, Z, varU, varV;
+ X = tuple[0], Y = tuple[1], Z = tuple[2];
+ if (Y === 0) {
+ return [0, 0, 0];
+ }
+ L = Y_to_L(Y);
+ varU = (4 * X) / (X + (15 * Y) + (3 * Z));
+ varV = (9 * Y) / (X + (15 * Y) + (3 * Z));
+ U = 13 * L * (varU - refU);
+ V = 13 * L * (varV - refV);
+ return [L, U, V];
+ };
+
+ conv.luv.xyz = function(tuple) {
+ var L, U, V, X, Y, Z, varU, varV;
+ L = tuple[0], U = tuple[1], V = tuple[2];
+ if (L === 0) {
+ return [0, 0, 0];
+ }
+ varU = U / (13 * L) + refU;
+ varV = V / (13 * L) + refV;
+ Y = L_to_Y(L);
+ X = 0 - (9 * Y * varU) / ((varU - 4) * varV - varU * varV);
+ Z = (9 * Y - (15 * varV * Y) - (varV * X)) / (3 * varV);
+ return [X, Y, Z];
+ };
+
+ conv.luv.lch = function(tuple) {
+ var C, H, Hrad, L, U, V;
+ L = tuple[0], U = tuple[1], V = tuple[2];
+ C = Math.sqrt(Math.pow(U, 2) + Math.pow(V, 2));
+ if (C < 0.00000001) {
+ H = 0;
+ } else {
+ Hrad = Math.atan2(V, U);
+ H = Hrad * 360 / 2 / Math.PI;
+ if (H < 0) {
+ H = 360 + H;
+ }
+ }
+ return [L, C, H];
+ };
+
+ conv.lch.luv = function(tuple) {
+ var C, H, Hrad, L, U, V;
+ L = tuple[0], C = tuple[1], H = tuple[2];
+ Hrad = H / 360 * 2 * Math.PI;
+ U = Math.cos(Hrad) * C;
+ V = Math.sin(Hrad) * C;
+ return [L, U, V];
+ };
+
+ conv.husl.lch = function(tuple) {
+ var C, H, L, S, max;
+ H = tuple[0], S = tuple[1], L = tuple[2];
+ if (L > 99.9999999 || L < 0.00000001) {
+ C = 0;
+ } else {
+ max = maxChromaForLH(L, H);
+ C = max / 100 * S;
+ }
+ return [L, C, H];
+ };
+
+ conv.lch.husl = function(tuple) {
+ var C, H, L, S, max;
+ L = tuple[0], C = tuple[1], H = tuple[2];
+ if (L > 99.9999999 || L < 0.00000001) {
+ S = 0;
+ } else {
+ max = maxChromaForLH(L, H);
+ S = C / max * 100;
+ }
+ return [H, S, L];
+ };
+
+ conv.huslp.lch = function(tuple) {
+ var C, H, L, S, max;
+ H = tuple[0], S = tuple[1], L = tuple[2];
+ if (L > 99.9999999 || L < 0.00000001) {
+ C = 0;
+ } else {
+ max = maxSafeChromaForL(L);
+ C = max / 100 * S;
+ }
+ return [L, C, H];
+ };
+
+ conv.lch.huslp = function(tuple) {
+ var C, H, L, S, max;
+ L = tuple[0], C = tuple[1], H = tuple[2];
+ if (L > 99.9999999 || L < 0.00000001) {
+ S = 0;
+ } else {
+ max = maxSafeChromaForL(L);
+ S = C / max * 100;
+ }
+ return [H, S, L];
+ };
+
+ conv.rgb.hex = function(tuple) {
+ var ch, hex, j, len1;
+ hex = "#";
+ for (j = 0, len1 = tuple.length; j < len1; j++) {
+ ch = tuple[j];
+ ch = Math.round(ch * 1e6) / 1e6;
+ if (ch < 0 || ch > 1) {
+ throw new Error("Illegal rgb value: " + ch);
+ }
+ ch = Math.round(ch * 255).toString(16);
+ if (ch.length === 1) {
+ ch = "0" + ch;
+ }
+ hex += ch;
+ }
+ return hex;
+ };
+
+ conv.hex.rgb = function(hex) {
+ var b, g, j, len1, n, r, ref, results;
+ if (hex.charAt(0) === "#") {
+ hex = hex.substring(1, 7);
+ }
+ r = hex.substring(0, 2);
+ g = hex.substring(2, 4);
+ b = hex.substring(4, 6);
+ ref = [r, g, b];
+ results = [];
+ for (j = 0, len1 = ref.length; j < len1; j++) {
+ n = ref[j];
+ results.push(parseInt(n, 16) / 255);
+ }
+ return results;
+ };
+
+ conv.lch.rgb = function(tuple) {
+ return conv.xyz.rgb(conv.luv.xyz(conv.lch.luv(tuple)));
+ };
+
+ conv.rgb.lch = function(tuple) {
+ return conv.luv.lch(conv.xyz.luv(conv.rgb.xyz(tuple)));
+ };
+
+ conv.husl.rgb = function(tuple) {
+ return conv.lch.rgb(conv.husl.lch(tuple));
+ };
+
+ conv.rgb.husl = function(tuple) {
+ return conv.lch.husl(conv.rgb.lch(tuple));
+ };
+
+ conv.huslp.rgb = function(tuple) {
+ return conv.lch.rgb(conv.huslp.lch(tuple));
+ };
+
+ conv.rgb.huslp = function(tuple) {
+ return conv.lch.huslp(conv.rgb.lch(tuple));
+ };
+
+ root = {};
+
+ root.fromRGB = function(R, G, B) {
+ return conv.rgb.husl([R, G, B]);
+ };
+
+ root.fromHex = function(hex) {
+ return conv.rgb.husl(conv.hex.rgb(hex));
+ };
+
+ root.toRGB = function(H, S, L) {
+ return conv.husl.rgb([H, S, L]);
+ };
+
+ root.toHex = function(H, S, L) {
+ return conv.rgb.hex(conv.husl.rgb([H, S, L]));
+ };
+
+ root.p = {};
+
+ root.p.toRGB = function(H, S, L) {
+ return conv.xyz.rgb(conv.luv.xyz(conv.lch.luv(conv.huslp.lch([H, S, L]))));
+ };
+
+ root.p.toHex = function(H, S, L) {
+ return conv.rgb.hex(conv.xyz.rgb(conv.luv.xyz(conv.lch.luv(conv.huslp.lch([H, S, L])))));
+ };
+
+ root.p.fromRGB = function(R, G, B) {
+ return conv.lch.huslp(conv.luv.lch(conv.xyz.luv(conv.rgb.xyz([R, G, B]))));
+ };
+
+ root.p.fromHex = function(hex) {
+ return conv.lch.huslp(conv.luv.lch(conv.xyz.luv(conv.rgb.xyz(conv.hex.rgb(hex)))));
+ };
+
+ root._conv = conv;
+
+ root._getBounds = getBounds;
+
+ root._maxChromaForLH = maxChromaForLH;
+
+ root._maxSafeChromaForL = maxSafeChromaForL;
+
+ if (!((typeof module !== "undefined" && module !== null) || (typeof jQuery !== "undefined" && jQuery !== null) || (typeof requirejs !== "undefined" && requirejs !== null))) {
+ this.HUSL = root;
+ }
+
+ if (typeof module !== "undefined" && module !== null) {
+ module.exports = root;
+ }
+
+ if (typeof jQuery !== "undefined" && jQuery !== null) {
+ jQuery.husl = root;
+ }
+
+ if ((typeof requirejs !== "undefined" && requirejs !== null) && (typeof define !== "undefined" && define !== null)) {
+ define(root);
+ }
+
+}).call(this);
+
+},{}],15:[function(require,module,exports){
module.exports={
"version": "2014j",
"zones": [
@@ -2113,11 +2525,11 @@ module.exports={
"Pacific/Pohnpei|Pacific/Ponape"
]
}
-},{}],15:[function(require,module,exports){
+},{}],16:[function(require,module,exports){
var moment = module.exports = require("./moment-timezone");
moment.tz.load(require('./data/packed/latest.json'));
-},{"./data/packed/latest.json":14,"./moment-timezone":16}],16:[function(require,module,exports){
+},{"./data/packed/latest.json":15,"./moment-timezone":17}],17:[function(require,module,exports){
//! moment-timezone.js
//! version : 0.2.5
//! author : Tim Wood
@@ -2520,7 +2932,7 @@ moment.tz.load(require('./data/packed/latest.json'));
return moment;
}));
-},{"moment":17}],17:[function(require,module,exports){
+},{"moment":18}],18:[function(require,module,exports){
//! moment.js
//! version : 2.10.6
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
@@ -5716,10 +6128,8 @@ moment.tz.load(require('./data/packed/latest.json'));
return _moment;
}));
-},{}],18:[function(require,module,exports){
-var MessageActions, send;
-
-MessageActions = require('../actions/MessageActions.coffee');
+},{}],19:[function(require,module,exports){
+var send;
window.urb.appl = "talk";
@@ -5729,71 +6139,75 @@ send = function(data, cb) {
}, cb);
};
-module.exports = {
- listenStation: function(station, since) {
- var $this;
- console.log('listen station');
- console.log(arguments);
- $this = this;
- return window.urb.bind("/f/" + station + "/" + since, function(err, res) {
- var ref, ref1;
- if (err || !res.data) {
- console.log('/f/ err!');
- console.log(err);
- console.log(res);
- $this.listenStation(station, since);
- return;
- }
- console.log('/f/');
- console.log(res.data);
- if (res.data.ok === true) {
- MessageActions.listeningStation(station);
- }
- if ((ref = res.data) != null ? (ref1 = ref.grams) != null ? ref1.tele : void 0 : void 0) {
- return MessageActions.loadMessages(res.data.grams);
- }
- });
- },
- get: function(station, start, end) {
- end = window.urb.util.numDot(end);
- start = window.urb.util.numDot(start);
- return window.urb.bind("/f/" + station + "/" + end + "/" + start, function(err, res) {
- var ref, ref1;
- if (err || !res.data) {
- console.log('/f/ /e/s err');
- console.log(err);
- return;
- }
- console.log('/f/ /e/s');
- console.log(res);
- if ((ref = res.data) != null ? (ref1 = ref.grams) != null ? ref1.tele : void 0 : void 0) {
- MessageActions.loadMessages(res.data.grams, true);
- return window.urb.drop("/f/" + station + "/" + end + "/" + start, function(err, res) {
- console.log('done');
- return console.log(res);
- });
- }
- });
- },
- sendMessage: function(message, cb) {
- return send({
- publish: [message]
- }, function(err, res) {
- console.log('sent');
+module.exports = function(arg) {
+ var MessageActions;
+ MessageActions = arg.MessageActions;
+ return {
+ listenStation: function(station, since) {
+ var $this;
+ console.log('listen station');
console.log(arguments);
- if (cb) {
- return cb(err, res);
- }
- });
- }
+ $this = this;
+ return window.urb.bind("/f/" + station + "/" + since, function(err, res) {
+ var num, ref, ref1, ref2, ref3, tele;
+ if (err || !res.data) {
+ console.log('/f/ err!');
+ console.log(err);
+ console.log(res);
+ $this.listenStation(station, since);
+ return;
+ }
+ console.log('/f/');
+ console.log(res.data);
+ if (res.data.ok === true) {
+ MessageActions.listeningStation(station);
+ }
+ if ((ref = res.data) != null ? (ref1 = ref.grams) != null ? ref1.tele : void 0 : void 0) {
+ ref3 = (ref2 = res.data) != null ? ref2.grams : void 0, tele = ref3.tele, num = ref3.num;
+ return MessageActions.loadMessages(tele, num);
+ }
+ });
+ },
+ get: function(station, start, end) {
+ end = window.urb.util.numDot(end);
+ start = window.urb.util.numDot(start);
+ return window.urb.bind("/f/" + station + "/" + end + "/" + start, function(err, res) {
+ var num, ref, ref1, ref2, ref3, tele;
+ if (err || !res.data) {
+ console.log('/f/ /e/s err');
+ console.log(err);
+ return;
+ }
+ console.log('/f/ /e/s');
+ console.log(res);
+ if ((ref = res.data) != null ? (ref1 = ref.grams) != null ? ref1.tele : void 0 : void 0) {
+ ref3 = (ref2 = res.data) != null ? ref2.grams : void 0, tele = ref3.tele, num = ref3.num;
+ MessageActions.loadMessages(tele, num, true);
+ return window.urb.drop("/f/" + station + "/" + end + "/" + start, function(err, res) {
+ console.log('done');
+ return console.log(res);
+ });
+ }
+ });
+ },
+ sendMessage: function(message, cb) {
+ return send({
+ publish: [message]
+ }, function(err, res) {
+ console.log('sent');
+ console.log(arguments);
+ if (cb) {
+ return cb(err, res);
+ }
+ });
+ }
+ };
};
-},{"../actions/MessageActions.coffee":1}],19:[function(require,module,exports){
-var StationActions, design, send;
-
-StationActions = require('../actions/StationActions.coffee');
+},{}],20:[function(require,module,exports){
+var design, send;
window.urb.appl = "talk";
@@ -5812,94 +6226,98 @@ design = function(party, config, cb) {
}, cb);
};
-module.exports = {
- createStation: function(name, cb) {
- return design(name, {
- sources: [],
- caption: "",
- cordon: {
+module.exports = function(arg) {
+ var StationActions;
+ StationActions = arg.StationActions;
+ return {
+ createStation: function(name, cb) {
+ return design(name, {
+ sources: [],
+ caption: "",
+ cordon: {
+ posture: "white",
+ list: []
+ }
+ }, cb);
+ },
+ removeStation: function(name, cb) {
+ return design(name, null, cb);
+ },
+ setSources: function(station, ship, sources) {
+ var cordon;
+ cordon = {
posture: "white",
list: []
- }
- }, cb);
- },
- removeStation: function(name, cb) {
- return design(name, null, cb);
- },
- setSources: function(station, ship, sources) {
- var cordon;
- cordon = {
- posture: "white",
- list: []
- };
- return design(station, {
- sources: sources,
- cordon: cordon,
- caption: ""
- }, function(err, res) {
- console.log('talk-command');
- return console.log(arguments);
- });
- },
- members: function() {
- return window.urb.bind("/a/court", function(err, res) {
- var ref, ref1;
- if (err || !res) {
- console.log('/a/ err');
- console.log(err);
- return;
- }
- console.log('/a/');
- console.log(res.data);
- if ((ref = res.data) != null ? (ref1 = ref.group) != null ? ref1.global : void 0 : void 0) {
- return StationActions.loadMembers(res.data.group.global);
- }
- });
- },
- listen: function() {
- return window.urb.bind("/", function(err, res) {
- if (err || !res.data) {
- console.log('/ err');
- console.log(err);
- return;
- }
- console.log('/');
- console.log(res.data);
- if (res.data.house) {
- return StationActions.loadStations(res.data.house);
- }
- });
- },
- listenStation: function(station) {
- return window.urb.bind("/avx/" + station, function(err, res) {
- var ref;
- if (err || !res) {
- console.log('/avx/ err');
- console.log(err);
- return;
- }
- console.log('/avx/');
- console.log(res.data);
- if (res.data.ok === true) {
- StationActions.listeningStation(station);
- }
- if (res.data.group) {
- res.data.group.global[window.util.mainStationPath(window.urb.user)] = res.data.group.local;
- StationActions.loadMembers(res.data.group.global);
- }
- if ((ref = res.data.cabal) != null ? ref.loc : void 0) {
- StationActions.loadConfig(station, res.data.cabal.loc);
- }
- if (res.data.glyph) {
- return StationActions.loadGlyphs(res.data.glyph);
- }
- });
- }
+ };
+ return design(station, {
+ sources: sources,
+ cordon: cordon,
+ caption: ""
+ }, function(err, res) {
+ console.log('talk-command');
+ return console.log(arguments);
+ });
+ },
+ members: function() {
+ return window.urb.bind("/a/court", function(err, res) {
+ var ref, ref1;
+ if (err || !res) {
+ console.log('/a/ err');
+ console.log(err);
+ return;
+ }
+ console.log('/a/');
+ console.log(res.data);
+ if ((ref = res.data) != null ? (ref1 = ref.group) != null ? ref1.global : void 0 : void 0) {
+ return StationActions.loadMembers(res.data.group.global);
+ }
+ });
+ },
+ listen: function() {
+ return window.urb.bind("/", function(err, res) {
+ if (err || !res.data) {
+ console.log('/ err');
+ console.log(err);
+ return;
+ }
+ console.log('/');
+ console.log(res.data);
+ if (res.data.house) {
+ return StationActions.loadStations(res.data.house);
+ }
+ });
+ },
+ listenStation: function(station) {
+ return window.urb.bind("/avx/" + station, function(err, res) {
+ var ref;
+ if (err || !res) {
+ console.log('/avx/ err');
+ console.log(err);
+ return;
+ }
+ console.log('/avx/');
+ console.log(res.data);
+ if (res.data.ok === true) {
+ StationActions.listeningStation(station);
+ }
+ if (res.data.group) {
+ res.data.group.global[window.util.mainStationPath(window.urb.user)] = res.data.group.local;
+ StationActions.loadMembers(res.data.group.global);
+ }
+ if ((ref = res.data.cabal) != null ? ref.loc : void 0) {
+ StationActions.loadConfig(station, res.data.cabal.loc);
+ }
+ if (res.data.glyph) {
+ return StationActions.loadGlyphs(res.data.glyph);
+ }
+ });
+ }
+ };
};
-},{"../actions/StationActions.coffee":2}],20:[function(require,module,exports){
+},{}],21:[function(require,module,exports){
var EventEmitter, MessageDispatcher, MessageStore, _fetching, _last, _listening, _messages, _station, _typing, moment;
moment = require('moment-timezone');
@@ -6046,7 +6464,7 @@ module.exports = MessageStore;
-},{"../dispatcher/Dispatcher.coffee":7,"events":23,"moment-timezone":15}],21:[function(require,module,exports){
+},{"../dispatcher/Dispatcher.coffee":7,"events":24,"moment-timezone":16}],22:[function(require,module,exports){
var EventEmitter, StationDispatcher, StationStore, _audience, _config, _glyphs, _listening, _members, _shpylg, _station, _stations, _typing, _validAudience;
EventEmitter = require('events').EventEmitter;
@@ -6286,7 +6704,7 @@ module.exports = StationStore;
-},{"../dispatcher/Dispatcher.coffee":7,"events":23}],22:[function(require,module,exports){
+},{"../dispatcher/Dispatcher.coffee":7,"events":24}],23:[function(require,module,exports){
if (!window.util) {
window.util = {};
}
@@ -6413,7 +6831,7 @@ _.merge(window.util, {
-},{}],23:[function(require,module,exports){
+},{}],24:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
diff --git a/pub/talk/src/js/module.coffee b/pub/talk/src/js/module.coffee
deleted file mode 100644
index 15f3f72d87..0000000000
--- a/pub/talk/src/js/module.coffee
+++ /dev/null
@@ -1,9 +0,0 @@
-require './util.coffee'
-require './move.coffee'
-
-window.talk =
- Component: require './components/TalkComponent.coffee'
- MessagePersistence: require './persistence/MessagePersistence.coffee'
- StationPersistence: require './persistence/StationPersistence.coffee'
- init: (el) ->
- @StationPersistence.listen()
\ No newline at end of file
diff --git a/pub/talk/src/js/package.json b/pub/talk/src/js/package.json
index 432cda4631..8368e275f7 100644
--- a/pub/talk/src/js/package.json
+++ b/pub/talk/src/js/package.json
@@ -11,6 +11,7 @@
"classnames": "^2.2.0",
"coffeeify": "~0.7.0",
"flux": "~2.0.1",
+ "husl": "^6.0.1",
"lodash": "~2.4.1",
"moment-timezone": "~0.2.4"
}
diff --git a/pub/talk/src/js/persistence/MessagePersistence.coffee b/pub/talk/src/js/persistence/MessagePersistence.coffee
index fe855071cd..8ae4e3a10e 100644
--- a/pub/talk/src/js/persistence/MessagePersistence.coffee
+++ b/pub/talk/src/js/persistence/MessagePersistence.coffee
@@ -1,8 +1,7 @@
-MessageActions = require '../actions/MessageActions.coffee'
-
window.urb.appl = "talk"
send = (data,cb)-> window.urb.send data, {mark:"talk-command"}, cb
-module.exports =
+
+module.exports = ({MessageActions}) ->
listenStation: (station,since) ->
console.log 'listen station'
console.log arguments
@@ -19,7 +18,8 @@ module.exports =
if res.data.ok is true
MessageActions.listeningStation station
if res.data?.grams?.tele
- MessageActions.loadMessages res.data.grams
+ {tele,num} = res.data?.grams
+ MessageActions.loadMessages tele, num
get: (station,start,end) ->
end = window.urb.util.numDot end
@@ -32,7 +32,8 @@ module.exports =
console.log '/f/ /e/s'
console.log res
if res.data?.grams?.tele
- MessageActions.loadMessages res.data.grams,true
+ {tele,num} = res.data?.grams
+ MessageActions.loadMessages tele,num,true
window.urb.drop "/f/#{station}/#{end}/#{start}", (err,res) ->
console.log 'done'
console.log res
diff --git a/pub/talk/src/js/persistence/StationPersistence.coffee b/pub/talk/src/js/persistence/StationPersistence.coffee
index de23b0f133..d866e0ce58 100644
--- a/pub/talk/src/js/persistence/StationPersistence.coffee
+++ b/pub/talk/src/js/persistence/StationPersistence.coffee
@@ -1,9 +1,7 @@
-StationActions = require '../actions/StationActions.coffee'
-
window.urb.appl = "talk"
send = (data,cb)-> window.urb.send data, {mark:"talk-command"}, cb
design = (party,config,cb)-> send {design:{party,config}}, cb
-module.exports =
+module.exports = ({StationActions})->
createStation: (name,cb) ->
design name, {
sources:[]
diff --git a/pub/tree/src/js/components/KidsComponent.coffee b/pub/tree/src/js/components/KidsComponent.coffee
index f6e6d6fc77..ef9c55eec6 100644
--- a/pub/tree/src/js/components/KidsComponent.coffee
+++ b/pub/tree/src/js/components/KidsComponent.coffee
@@ -11,20 +11,34 @@ module.exports = query {kids: {body:'r', meta:'j'}}, recl
if @props.dataType then klass += " #{@props.dataType}"
sorted = true
- _keys = []
+ keyed = {}
for k,v of @props.kids
if @props.sortBy
if @props.sortBy is 'date'
- if not v.meta?.date? then sorted = false
- _k = Number v.meta.date.slice(1).replace /\./g,""
- _keys[_k] = k
+ if not v.meta?.date?
+ sorted = false
+ continue
+ d = v.meta.date.slice(1).split "."
+ if d.length < 3
+ sorted = false
+ continue
+ str = "#{d[0]}-#{d[1]}-#{d[2]}"
+ if d.length > 3
+ str += " #{d[3]}:#{d[4]}:#{d[5]}"
+ _k = Number(new Date(str))
+ keyed[_k] = k
else
if not v.meta?.sort? then sorted = false
- _keys[Number(v.meta?.sort)] = k
+ keyed[Number(v.meta?.sort)] = k
+
+ if sorted isnt true
+ _keys = _.keys(@props.kids).sort()
+ else
+ _keys = _.keys(keyed).sort()
+
if @props.sortBy is 'date' then _keys.reverse()
- if sorted isnt true then _keys = _.keys(@props.kids).sort()
div {className:klass},
- for item in _.values _keys
- elem = @props.kids[item]
+ for item in _keys
+ elem = @props.kids[keyed[item]]
[(div {key:item}, reactify elem.body), (hr {},"")]
diff --git a/pub/tree/src/js/main.js b/pub/tree/src/js/main.js
index c67d0651b6..ee2554b95e 100644
--- a/pub/tree/src/js/main.js
+++ b/pub/tree/src/js/main.js
@@ -676,13 +676,13 @@ module.exports = query({
}, recl({
displayName: "Kids",
render: function() {
- var _k, _keys, elem, item, k, klass, ref1, ref2, ref3, ref4, sorted, v;
+ var _k, _keys, d, elem, item, k, keyed, klass, ref1, ref2, ref3, ref4, sorted, str, v;
klass = "kids";
if (this.props.dataType) {
klass += " " + this.props.dataType;
}
sorted = true;
- _keys = [];
+ keyed = {};
ref1 = this.props.kids;
for (k in ref1) {
v = ref1[k];
@@ -690,32 +690,43 @@ module.exports = query({
if (this.props.sortBy === 'date') {
if (((ref2 = v.meta) != null ? ref2.date : void 0) == null) {
sorted = false;
+ continue;
}
- _k = Number(v.meta.date.slice(1).replace(/\./g, ""));
- _keys[_k] = k;
+ d = v.meta.date.slice(1).split(".");
+ if (d.length < 3) {
+ sorted = false;
+ continue;
+ }
+ str = d[0] + "-" + d[1] + "-" + d[2];
+ if (d.length > 3) {
+ str += " " + d[3] + ":" + d[4] + ":" + d[5];
+ }
+ _k = Number(new Date(str));
+ keyed[_k] = k;
}
} else {
if (((ref3 = v.meta) != null ? ref3.sort : void 0) == null) {
sorted = false;
}
- _keys[Number((ref4 = v.meta) != null ? ref4.sort : void 0)] = k;
+ keyed[Number((ref4 = v.meta) != null ? ref4.sort : void 0)] = k;
}
}
+ if (sorted !== true) {
+ _keys = _.keys(this.props.kids).sort();
+ } else {
+ _keys = _.keys(keyed).sort();
+ }
if (this.props.sortBy === 'date') {
_keys.reverse();
}
- if (sorted !== true) {
- _keys = _.keys(this.props.kids).sort();
- }
return div({
className: klass
}, (function() {
- var i, len, ref5, results;
- ref5 = _.values(_keys);
+ var i, len, results;
results = [];
- for (i = 0, len = ref5.length; i < len; i++) {
- item = ref5[i];
- elem = this.props.kids[item];
+ for (i = 0, len = _keys.length; i < len; i++) {
+ item = _keys[i];
+ elem = this.props.kids[keyed[item]];
results.push([
div({
key: item