Merge branch 'kidsort-fixed', remote-tracking branches 'wilderr/master', 'anton/talk-offline' and 'curtis/trivial' into pending

kidsort-fixed is a fixed version of galen/kidsort.

fixes #516
This commit is contained in:
Philip C Monk 2015-11-04 13:46:13 -05:00
18 changed files with 1042 additions and 623 deletions

View File

@ -951,7 +951,6 @@
:: ::
++ bind :: %bind ++ bind :: %bind
|= [cha=char pan=(unit (set partner))] ^+ ..sh-work |= [cha=char pan=(unit (set partner))] ^+ ..sh-work
~& bind/[cha pan nik nak]
?~ pan $(pan [~ ?~(active.she passive.she u.active.she)]) ?~ pan $(pan [~ ?~(active.she passive.she u.active.she)])
=+ ole=(~(get by nik) u.pan) =+ ole=(~(get by nik) u.pan)
?: =(ole [~ cha]) ..sh-work ?: =(ole [~ cha]) ..sh-work
@ -1102,7 +1101,8 @@
(sh-slug lit) (sh-slug lit)
=+ jub=(rust (tufa buf.say.she) sh-scad) =+ jub=(rust (tufa buf.say.she) sh-scad)
?~ jub (sh-fact %bel ~) ?~ jub (sh-fact %bel ~)
=. +> (sh-work u.jub) %. u.jub
=< sh-work
=+ buf=buf.say.she =+ buf=buf.say.she
=^ cal say.she (~(transmit sole say.she) [%set ~]) =^ cal say.she (~(transmit sole say.she) [%set ~])
%- sh-fact %- sh-fact
@ -1111,7 +1111,7 @@
[%det cal] [%det cal]
?. ?=([%';' *] buf) ~ ?. ?=([%';' *] buf) ~
:_ ~ :_ ~
[%txt (weld "----------------| " (tufa buf))] [%txt (runt [14 '-'] `tape`['|' ' ' (tufa buf)])]
== ==
:: ::
++ sh-sole :: apply edit ++ sh-sole :: apply edit
@ -2040,7 +2040,8 @@
^- (quip move +>) ^- (quip move +>)
?~ saw [~ +>] ?~ saw [~ +>]
%+ etch-friend [%friend way] |= [man=span cuz=station] %+ 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) ra-abet:(ra-quit:ra man cuz)
:: ::
++ quit-friend :: ++ quit-friend ::

View File

@ -20,6 +20,7 @@ window.urb.req = function(method,url,params,json,cb) {
if(params.wire) { _data.wire = params.wire; } if(params.wire) { _data.wire = params.wire; }
if(cb) { if(cb) {
xhr.onload = function() { xhr.onload = function() {
var err,res
try { try {
err = null err = null
res = { res = {
@ -36,7 +37,9 @@ window.urb.req = function(method,url,params,json,cb) {
} }
res = null res = null
} }
cb(err,res) finally {
cb(err,res)
}
} }
xhr.onerror = function() { xhr.onerror = function() {
cb({ cb({
@ -64,7 +67,7 @@ window.urb.qreq = function(method,url,params,json,cb) {
walk = function() { walk = function() {
qobj = {} qobj = {}
qobj.oargs = window.urb.reqq[0] 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(){ qobj.nargs.push(function(){
if(this.oargs[4]) if(this.oargs[4])
this.oargs[4].apply(window.urb,arguments) 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.ship = params.ship || this.ship
params.appl = params.appl || this.appl params.appl = params.appl || this.appl
params.mark = params.mark || $send.mark params.mark = params.mark || $send.mark
// params.seqn = params.seqn || $send.seqn
params.wire = params.wire || "/" params.wire = params.wire || "/"
params.xyro = (typeof(params.data) === 'undefined') ? null : params.data 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 = ["to",params.appl,params.mark]
url = "/~/"+url.join("/") url = "/~/"+url.join("/")
$send.seqn++ // $send.seqn++
this.qreq('post',url,params,true,function(err,data) { this.qreq('post',url,params,true,function(err,data) {
if(err) { $send.seqn--; } /* if(err) { $send.seqn--; }
else if(data && data.data.fail && urb.wall !== false) else */ if(data && data.data.fail && urb.wall !== false)
document.write("<pre>"+JSON.stringify(params.xyro)+"\n" document.write("<pre>"+JSON.stringify(params.xyro)+"\n"
+data.data.mess+"</pre>") // XX +data.data.mess+"</pre>") // XX
if(cb) { cb.apply(this,arguments); } if(cb) { cb.apply(this,arguments); }
}) })
} }
window.urb.send.seqn = 0 // window.urb.send.seqn = 0
window.urb.send.mark = "json" window.urb.send.mark = "json"
@ -139,6 +143,7 @@ window.urb.poll = function(params) {
$this = this $this = this
this.req("get",url,params,true,function(err,res) { this.req("get",url,params,true,function(err,res) {
$this.poll.dely = params.dely || $this.poll.dely
if(res){ if(res){
if(res.data.beat) if(res.data.beat)
return $this.poll(params) return $this.poll(params)
@ -158,27 +163,25 @@ window.urb.poll = function(params) {
default: default:
throw new Error("Lost event %"+res.data.type) 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) if(params.incs)
params.incs() params.incs()
else else
$this.poll.seqn++ $this.poll.seqn++
$this.poll.dely = 250
return $this.poll(params)
} }
setTimeout(function() { else if(err){
$this.poll(params) setTimeout(function() {
},dely) $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.seqn = 1
window.urb.poll.dely = 0 window.urb.poll.dely = 250
window.urb.bind = function(path, params, cb, nicecb){ // or bind(path, cb) window.urb.bind = function(path, params, cb, nicecb){ // or bind(path, cb)
if(!params || typeof params === "function") if(!params || typeof params === "function")

View File

@ -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 are unfamiliar. The syntax will remind too many of Perl, but
like most human languages (and unlike Perl) it combines a regular like most human languages (and unlike Perl) it combines a regular
core structure with irregular variations. And Hoon's semantic core structure with irregular variations. And Hoon's semantic
is bounded by the size of the compiler: type inference plus code complexity is bounded by the size of the compiler: type inference plus code
generation are 2000 lines of Hoon. Most peoples' experience is generation are 2000 lines of Hoon. Most peoples' experience is that the
that the language is much easier to learn than it looks. language is much easier to learn than it looks.
> The name "Hoon" is from the Wallace Stevens poem, _Tea at the > The name "Hoon" is from the Wallace Stevens poem, _Tea at the
Palaz of Hoon_. It also means "hooligan" in Australian. 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 validate or normalize untrusted, untyped data -- a common problem
in modern programming, because networks. 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 Hoon's inference algorithm is dumber than the unification
algorithms (Hindley-Milner) used in most typed functional algorithms (Hindley-Milner) used in most typed functional
languages. Hoon thinks only forward, not backward. Eg, Haskell 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). (forward), or the argument type from the result (backward).
Hoon can do the first but not the second. 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 anyway for prosaic software-engineering reasons. Otherwise its
typesystem solves more or less the same job, including typesystem solves more or less the same job, including
pattern-matching, genericity / typeclasses, etc. pattern-matching, genericity / typeclasses, etc.
> Sending a noun over the network is a good example of why Hoon > A good test of a static higher-order typesystem is whether it can
is different. In a normal modern language, you serialize and infer the product type of a grammar defined as a combinator
deserialize a data type by extending your type to implement a parser. The Hoon parser passes this test; when it typechecks,
serialization interface. In Hoon, any value is just a noun, so the parser's range nests within the span of the expression mold.
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.
## Let's make some nouns ## 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 ~tasfyn-partyv:dojo> 42
``` ```
@ -106,7 +112,7 @@ You'll see the expression you entered, then the result:
> 42 > 42
42 42
``` ```
Let's try a different value: Let's try a different noun. Or is it different?
``` ```
~tasfyn-partyv:dojo> 0x2a ~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 We observe that cells associate right: `[a b c]` is just another
way of writing `[a [b c]]`. way of writing `[a [b c]]`.
> Lisp veterans beware: Hoon `[a b]` is Lisp `(a . b)`, Lisp Lisp masters beware: Hoon `[a b]` is Lisp `(a . b)`, Lisp
`(a b)` is Hoon `[a b ~]`(`~` represents nil, with a value of `(a b)` is Hoon `[a b ~]`. `~` means nil, with value zero. Lisp
atom `0`). Lisp and Hoon are both pair-oriented languages down and Hoon are both pair-oriented languages down below, but Lisp
below, but Lisp has a layer of sugar that makes it look has a layer of sugar that makes it look list-oriented. Hoon
list-oriented. Hoon loves its "improper lists," ie, tuples. loves its "improper lists," ie, tuples.
## Looking at spans ## Looking at spans
@ -169,15 +175,17 @@ type food chain.
## Looking at spans, part 2 ## Looking at spans, part 2
Good style in Hoon is concrete style. When a Hoon programmer Usually, good style in Hoon is concrete style. When a Hoon
defines an abstract semantic value in terms of a noun, we rarely programmer defines an abstract semantic value in terms of a noun,
put a conceptual layer of abstraction between value and noun. We we rarely put a conceptual layer of abstraction between value and
think of the semantic value as an interpretation of the noun. We think of the value as an interpretation of the noun.
concrete noun, and often we just think 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 But rules are made to be broken. With the `?` command, we *do*
our span noun in a custom syntax. But we can also look at the use an abstract layer, by printing our span noun in that custom
span noun directly, with the `??` command. 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 ~tasfyn-partyv:dojo> ?? 42
@ -228,12 +236,12 @@ numbers we've just been using, and make them constants:
%42 %42
``` ```
> Spans are an exception to the concrete style, because we use > Why `??`? Spans are an exception to concrete style, because they
"manual laziness" to define recursive structures. A recursive use "manual laziness" to define logically recursive structures.
span contains Hoon code which is evaluated to apply it. In A recursive span contains Hoon code which is evaluated to apply
practice, it often contains the entire Urbit kernel, so you it. In practice, this noun often contains the entire Urbit
wouldn't want to try to print it in the dojo. If you find kernel, so you wouldn't want to try to print it in the dojo. If
`??` taking a weirdly long time, this may have happened; just you find `??` taking a weirdly long time, this may have happened;
press ^C. press ^C.
## Our first mold ## Our first mold

View File

@ -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: 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 (`/urbit-meta` is a federal station, meaning it's hosted by your
star (for `~fintud-macrep`, `~doznec`). The `/` notation is just star (for `~fintud-macrep`, `~doznec`). The `/` notation is just

View File

@ -591,6 +591,15 @@ a {
font-size: 0.8rem; font-size: 0.8rem;
text-transform: uppercase; 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) { @media only screen and (min-width: 1024px) {
#station-container:hover { #station-container:hover {
max-height: 30rem; max-height: 30rem;

View File

@ -549,4 +549,17 @@ a
font-size .8rem font-size .8rem
text-transform uppercase text-transform uppercase
//
// offline
//
body:not(.offline) #offline
display none
#offline
transition: color 0.25s ease
#offline.error
color: red
@import 'mobile' @import 'mobile'

View File

@ -1,33 +1,26 @@
MessageDispatcher = require '../dispatcher/Dispatcher.coffee' Dispatcher = require '../dispatcher/Dispatcher.coffee'
module.exports = _persistence = require '../persistence/MessagePersistence.coffee'
loadMessages: (grams,get) ->
MessageDispatcher.handleServerAction Persistence = _persistence MessageActions: module.exports =
type:"messages-load" loadMessages: (messages,last,get) ->
messages:grams.tele Dispatcher.handleServerAction {messages,last,get,type:"messages-load"}
last:grams.num
get:get
listenStation: (station,date) -> listenStation: (station,date) ->
if not date then date = window.urb.util.toDate(new Date()) if not date then date = window.urb.util.toDate(new Date())
window.talk.MessagePersistence.listenStation station,date Persistence.listenStation station,date
listeningStation: (station) -> listeningStation: (station) ->
MessageDispatcher.handleViewAction Dispatcher.handleViewAction {station,type:"messages-listen"}
type:"messages-listen"
station:station
setTyping: (state) -> setTyping: (state) ->
MessageDispatcher.handleViewAction Dispatcher.handleViewAction {state,type:"messages-typing"}
type:"messages-typing"
state:state
getMore: (station,start,end) -> getMore: (station,start,end) ->
MessageDispatcher.handleViewAction Dispatcher.handleViewAction type:"messages-fetch"
type:"messages-fetch" Persistence.get station,start,end
window.talk.MessagePersistence.get station,start,end
sendMessage: (message,audience) -> sendMessage: (txt,audience) ->
serial = window.util.uuid32() serial = window.util.uuid32()
# audience.push window.util.mainStationPath window.urb.user # audience.push window.util.mainStationPath window.urb.user
@ -41,20 +34,17 @@ module.exports =
sender:null sender:null
delivery:"pending" delivery:"pending"
speech = speech = lin: {txt, say:true}
lin:
say:true
txt:message
if message[0] is "@" if txt[0] is "@"
speech.lin.txt = speech.lin.txt.slice(1).trim() speech.lin.txt = speech.lin.txt.slice(1).trim()
speech.lin.say = false speech.lin.say = false
else if message[0] is "#" else if txt[0] is "#"
speech = eval: speech.lin.txt.slice(1).trim() speech = eval: speech.lin.txt.slice(1).trim()
else if window.urb.util.isURL(message) else if window.urb.util.isURL(txt)
speech = url: message speech = url: txt
speeches = speeches =
if not (speech.lin?.txt.length > 64) if not (speech.lin?.txt.length > 64)
@ -70,7 +60,7 @@ module.exports =
} }
for speech in speeches for speech in speeches
_message = message =
ship:window.urb.ship ship:window.urb.ship
thought: thought:
serial:window.util.uuid32() serial:window.util.uuid32()
@ -80,8 +70,6 @@ module.exports =
speech:speech speech:speech
date: Date.now() date: Date.now()
MessageDispatcher.handleViewAction Dispatcher.handleViewAction {message,type:"message-send"}
type:"message-send" Persistence.sendMessage message.thought
message:_message
window.talk.MessagePersistence.sendMessage _message.thought

View File

@ -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 = _persistence = require '../persistence/StationPersistence.coffee'
loadConfig: (station,config) ->
StationDispatcher.handleServerAction
type: "config-load"
station:station
config:config
loadGlyphs: (glyphs) -> Persistence = _persistence StationActions: module.exports =
StationDispatcher.handleServerAction loadGlyphs: serverAction (glyphs) -> {glyphs,type:"glyphs-load"}
type: "glyphs-load" loadMembers: serverAction (members) -> {members,type:"members-load"}
station:station loadStations: serverAction (stations) -> {stations,type:"stations-load"}
glyphs:glyphs loadConfig: serverAction (station,config) -> {station,config,type:"config-load"}
switchStation: (station) -> setTyping: viewAction (station,state) -> {station,state,type:"typing-set"}
StationDispatcher.handleViewAction setAudience: viewAction (audience) -> {audience,type:"station-set-audience"}
type:"station-switch" setValidAudience: viewAction (valid) -> {valid,type:"station-set-valid-audience"}
station:station toggleAudience: viewAction (station) -> {station,type:"station-audience-toggle"}
switchStation: viewAction (station) -> {station,type:"station-switch"}
setAudience: (audience) -> listeningStation: viewAction (station) -> {station,type:"station-listen"}
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
createStation: (station) -> createStation: (station) ->
StationDispatcher.handleViewAction Dispatcher.handleViewAction {station,type: "station-create"}
type: "station-create" Persistence.createStation station
station: station
window.talk.StationPersistence.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

View File

@ -1,17 +1,12 @@
recl = React.createClass recl = React.createClass
[div,input,textarea,h1,a] = [ {div,style,input,textarea,h1,a} = React.DOM
React.DOM.div,
React.DOM.input,
React.DOM.textarea,
React.DOM.h1,
React.DOM.a
]
StationStore = require '../stores/StationStore.coffee' StationStore = require '../stores/StationStore.coffee'
StationActions = require '../actions/StationActions.coffee' StationActions = require '../actions/StationActions.coffee'
Member = require './MemberComponent.coffee' Member = require './MemberComponent.coffee'
module.exports = recl module.exports = recl
displayName: "Station"
stateFromStore: -> { stateFromStore: -> {
audi:StationStore.getAudience() audi:StationStore.getAudience()
members:StationStore.getMembers() members:StationStore.getMembers()
@ -88,7 +83,7 @@ module.exports = recl
else else
members = "" members = ""
sourceInput = [(input {className:"join",onKeyUp:@_keyUp,placeholder:"+"}, "")] sourceInput = [(input {className:"join",onKeyUp:@_keyUp,placeholder:"+"})]
sourceCtrl = div {className:"sour-ctrl"},sourceInput sourceCtrl = div {className:"sour-ctrl"},sourceInput
sources = [] sources = []
@ -103,21 +98,19 @@ module.exports = recl
else else
sources = "" sources = ""
head = (div {id:"head"}, (div {id:"station",onClick:@_toggleOpen},
[ (div {id:"who"},[ (div {id:"head"},
(div {className:"sig"},"") (div {id:"who"},
(div {className:"ship"},"#{window.urb.user}") div {className:"sig"}
]) div {className:"ship"},"#{window.urb.user}"
(div {id:"where"},[ )
(div {className:"slat"},"talk") (div {id:"where"},
(div {className:"path"},"") #window.util.mainStation(window.urb.user)) div {className:"slat"},"talk"
(div {className:"caret"},"") div {className:"path"} #, window.util.mainStation(window.urb.user))
]) div {className:"caret"}
] )
div {id:"offline"}, "Warning: no connection to server."
) )
div {id:"stations"}, (h1 {}, "Listening to"),(div {},sources),sourceCtrl
parts.push head div {id:"audience"}, div {}, (h1 {}, "Talking to"),(div {id:"members"},members)
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

View File

@ -1,6 +1,8 @@
recl = React.createClass recl = React.createClass
{div,br,input,textarea} = React.DOM {div,br,input,textarea} = React.DOM
husl = require 'husl'
MessageActions = require '../actions/MessageActions.coffee' MessageActions = require '../actions/MessageActions.coffee'
MessageStore = require '../stores/MessageStore.coffee' MessageStore = require '../stores/MessageStore.coffee'
StationActions = require '../actions/StationActions.coffee' StationActions = require '../actions/StationActions.coffee'
@ -149,7 +151,13 @@ module.exports = recl
txt = @$writing.text() txt = @$writing.text()
e.preventDefault() e.preventDefault()
if txt.length > 0 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 return false
@onInput() @onInput()
@set() @set()

View File

@ -1,11 +1,17 @@
$(() -> $(() ->
StationActions = require './actions/StationActions.coffee' StationActions = require './actions/StationActions.coffee' #start poll
rend = React.render rend = React.render
window.talk = {} window.talk = {}
window.talk.MessagePersistence = require './persistence/MessagePersistence.coffee' window.talk.online = yes
window.talk.StationPersistence = require './persistence/StationPersistence.coffee'
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 './util.coffee'
require './move.coffee' require './move.coffee'
@ -17,7 +23,8 @@ $(() ->
# $('#nav').removeClass 'scrolling' # $('#nav').removeClass 'scrolling'
# setInterval checkScroll, 500 # setInterval checkScroll, 500
window.talk.StationPersistence.listen()
StationActions.listen()
StationComponent = require './components/StationComponent.coffee' StationComponent = require './components/StationComponent.coffee'
MessagesComponent = require './components/MessagesComponent.coffee' MessagesComponent = require './components/MessagesComponent.coffee'

File diff suppressed because it is too large Load Diff

View File

@ -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()

View File

@ -11,6 +11,7 @@
"classnames": "^2.2.0", "classnames": "^2.2.0",
"coffeeify": "~0.7.0", "coffeeify": "~0.7.0",
"flux": "~2.0.1", "flux": "~2.0.1",
"husl": "^6.0.1",
"lodash": "~2.4.1", "lodash": "~2.4.1",
"moment-timezone": "~0.2.4" "moment-timezone": "~0.2.4"
} }

View File

@ -1,8 +1,7 @@
MessageActions = require '../actions/MessageActions.coffee'
window.urb.appl = "talk" window.urb.appl = "talk"
send = (data,cb)-> window.urb.send data, {mark:"talk-command"}, cb send = (data,cb)-> window.urb.send data, {mark:"talk-command"}, cb
module.exports =
module.exports = ({MessageActions}) ->
listenStation: (station,since) -> listenStation: (station,since) ->
console.log 'listen station' console.log 'listen station'
console.log arguments console.log arguments
@ -19,7 +18,8 @@ module.exports =
if res.data.ok is true if res.data.ok is true
MessageActions.listeningStation station MessageActions.listeningStation station
if res.data?.grams?.tele if res.data?.grams?.tele
MessageActions.loadMessages res.data.grams {tele,num} = res.data?.grams
MessageActions.loadMessages tele, num
get: (station,start,end) -> get: (station,start,end) ->
end = window.urb.util.numDot end end = window.urb.util.numDot end
@ -32,7 +32,8 @@ module.exports =
console.log '/f/ /e/s' console.log '/f/ /e/s'
console.log res console.log res
if res.data?.grams?.tele 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) -> window.urb.drop "/f/#{station}/#{end}/#{start}", (err,res) ->
console.log 'done' console.log 'done'
console.log res console.log res

View File

@ -1,9 +1,7 @@
StationActions = require '../actions/StationActions.coffee'
window.urb.appl = "talk" window.urb.appl = "talk"
send = (data,cb)-> window.urb.send data, {mark:"talk-command"}, cb send = (data,cb)-> window.urb.send data, {mark:"talk-command"}, cb
design = (party,config,cb)-> send {design:{party,config}}, cb design = (party,config,cb)-> send {design:{party,config}}, cb
module.exports = module.exports = ({StationActions})->
createStation: (name,cb) -> createStation: (name,cb) ->
design name, { design name, {
sources:[] sources:[]

View File

@ -11,20 +11,34 @@ module.exports = query {kids: {body:'r', meta:'j'}}, recl
if @props.dataType then klass += " #{@props.dataType}" if @props.dataType then klass += " #{@props.dataType}"
sorted = true sorted = true
_keys = [] keyed = {}
for k,v of @props.kids for k,v of @props.kids
if @props.sortBy if @props.sortBy
if @props.sortBy is 'date' if @props.sortBy is 'date'
if not v.meta?.date? then sorted = false if not v.meta?.date?
_k = Number v.meta.date.slice(1).replace /\./g,"" sorted = false
_keys[_k] = k 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 else
if not v.meta?.sort? then sorted = false 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 @props.sortBy is 'date' then _keys.reverse()
if sorted isnt true then _keys = _.keys(@props.kids).sort()
div {className:klass}, div {className:klass},
for item in _.values _keys for item in _keys
elem = @props.kids[item] elem = @props.kids[keyed[item]]
[(div {key:item}, reactify elem.body), (hr {},"")] [(div {key:item}, reactify elem.body), (hr {},"")]

View File

@ -676,13 +676,13 @@ module.exports = query({
}, recl({ }, recl({
displayName: "Kids", displayName: "Kids",
render: function() { 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"; klass = "kids";
if (this.props.dataType) { if (this.props.dataType) {
klass += " " + this.props.dataType; klass += " " + this.props.dataType;
} }
sorted = true; sorted = true;
_keys = []; keyed = {};
ref1 = this.props.kids; ref1 = this.props.kids;
for (k in ref1) { for (k in ref1) {
v = ref1[k]; v = ref1[k];
@ -690,32 +690,43 @@ module.exports = query({
if (this.props.sortBy === 'date') { if (this.props.sortBy === 'date') {
if (((ref2 = v.meta) != null ? ref2.date : void 0) == null) { if (((ref2 = v.meta) != null ? ref2.date : void 0) == null) {
sorted = false; sorted = false;
continue;
} }
_k = Number(v.meta.date.slice(1).replace(/\./g, "")); d = v.meta.date.slice(1).split(".");
_keys[_k] = k; 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 { } else {
if (((ref3 = v.meta) != null ? ref3.sort : void 0) == null) { if (((ref3 = v.meta) != null ? ref3.sort : void 0) == null) {
sorted = false; 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') { if (this.props.sortBy === 'date') {
_keys.reverse(); _keys.reverse();
} }
if (sorted !== true) {
_keys = _.keys(this.props.kids).sort();
}
return div({ return div({
className: klass className: klass
}, (function() { }, (function() {
var i, len, ref5, results; var i, len, results;
ref5 = _.values(_keys);
results = []; results = [];
for (i = 0, len = ref5.length; i < len; i++) { for (i = 0, len = _keys.length; i < len; i++) {
item = ref5[i]; item = _keys[i];
elem = this.props.kids[item]; elem = this.props.kids[keyed[item]];
results.push([ results.push([
div({ div({
key: item key: item