From ea39b7ee37c6b4c0bbd03ec33de2f01764c74716 Mon Sep 17 00:00:00 2001 From: Anton Dyudin Date: Mon, 2 Nov 2015 14:57:41 -0800 Subject: [PATCH 1/9] clean up more indentation, command print order --- ape/talk.hoon | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ape/talk.hoon b/ape/talk.hoon index b978ee1033..29b80a2265 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 @@ -2029,7 +2029,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 :: From cd345e58694c110e28dc3a1bb87d8155cae573bb Mon Sep 17 00:00:00 2001 From: Anton Dyudin Date: Mon, 2 Nov 2015 15:31:48 -0800 Subject: [PATCH 2/9] exponential backoff tweaks --- lib/urb.js | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) 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") From 572c271bfb94975414ebb03d469aa9f6e2981181 Mon Sep 17 00:00:00 2001 From: Wilder Ramsey Date: Mon, 2 Nov 2015 16:58:45 -0800 Subject: [PATCH 3/9] Update talk.mdy --- pub/docs/user/talk.mdy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pub/docs/user/talk.mdy b/pub/docs/user/talk.mdy index 16759a0165..1c486e612f 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 From eeb546139db0be7410db85621b665ae0c5b669cc Mon Sep 17 00:00:00 2001 From: Anton Dyudin Date: Tue, 3 Nov 2015 10:55:08 -0800 Subject: [PATCH 4/9] offline "banner" --- pub/talk/src/css/main.css | 3 + pub/talk/src/css/main.styl | 7 ++ .../src/js/components/StationComponent.coffee | 43 +++++------- pub/talk/src/js/main.js | 69 ++++++++----------- 4 files changed, 58 insertions(+), 64 deletions(-) diff --git a/pub/talk/src/css/main.css b/pub/talk/src/css/main.css index ff5ff9e545..7690f1b080 100644 --- a/pub/talk/src/css/main.css +++ b/pub/talk/src/css/main.css @@ -591,6 +591,9 @@ a { font-size: 0.8rem; text-transform: uppercase; } +body:not(.offline) #offline { + display: none; +} @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..49fe153674 100644 --- a/pub/talk/src/css/main.styl +++ b/pub/talk/src/css/main.styl @@ -549,4 +549,11 @@ a font-size .8rem text-transform uppercase +// +// offline +// + +body:not(.offline) #offline + display none + @import 'mobile' diff --git a/pub/talk/src/js/components/StationComponent.coffee b/pub/talk/src/js/components/StationComponent.coffee index e2487dc62c..44753bc550 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 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/main.js b/pub/talk/src/js/main.js index 9d933b93d1..77dcdd2608 100644 --- a/pub/talk/src/js/main.js +++ b/pub/talk/src/js/main.js @@ -532,11 +532,11 @@ 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; +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'); @@ -545,6 +545,7 @@ StationActions = require('../actions/StationActions.coffee'); Member = require('./MemberComponent.coffee'); module.exports = recl({ + displayName: "Station", stateFromStore: function() { return { audi: StationStore.getAudience(), @@ -623,7 +624,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) { @@ -648,7 +649,7 @@ module.exports = recl({ className: "join", onKeyUp: this._keyUp, placeholder: "+" - }, "") + }) ]; sourceCtrl = div({ className: "sour-ctrl" @@ -675,44 +676,34 @@ 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 server.")), div({ + id: "stations" + }, h1({}, "Listening to"), div({}, sources), sourceCtrl), div({ + id: "audience" + }, div({}, h1({}, "Talking to"), div({ + id: "members" + }, members)))); } }); From c50ca15a57d16ec153847534a5af13370810f735 Mon Sep 17 00:00:00 2001 From: Anton Dyudin Date: Tue, 3 Nov 2015 11:27:39 -0800 Subject: [PATCH 5/9] tightened persistence<->actions dependency cycles --- pub/talk/src/js/actions/MessageActions.coffee | 52 +- pub/talk/src/js/actions/StationActions.coffee | 99 +-- pub/talk/src/js/main.coffee | 5 +- pub/talk/src/js/main.js | 705 +++++++++--------- pub/talk/src/js/module.coffee | 9 - .../js/persistence/MessagePersistence.coffee | 11 +- .../js/persistence/StationPersistence.coffee | 4 +- 7 files changed, 422 insertions(+), 463 deletions(-) delete mode 100644 pub/talk/src/js/module.coffee 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/main.coffee b/pub/talk/src/js/main.coffee index 984fbecf1c..89618c8927 100644 --- a/pub/talk/src/js/main.coffee +++ b/pub/talk/src/js/main.coffee @@ -1,11 +1,10 @@ $(() -> - 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' require './util.coffee' require './move.coffee' @@ -17,7 +16,7 @@ $(() -> # $('#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 77dcdd2608..819bfefff2 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":18}],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":19}],3:[function(require,module,exports){ var div, input, recl, ref, textarea; recl = React.createClass; @@ -1028,10 +1050,9 @@ $(function() { rend = React.render; window.talk = {}; window.talk.MessagePersistence = require('./persistence/MessagePersistence.coffee'); - window.talk.StationPersistence = require('./persistence/StationPersistence.coffee'); 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'); @@ -1043,7 +1064,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,"./persistence/MessagePersistence.coffee":18,"./util.coffee":22}],9:[function(require,module,exports){ var ldy, setSo, so; so = {}; @@ -5707,9 +5728,7 @@ moment.tz.load(require('./data/packed/latest.json')); })); },{}],18:[function(require,module,exports){ -var MessageActions, send; - -MessageActions = require('../actions/MessageActions.coffee'); +var send; window.urb.appl = "talk"; @@ -5719,71 +5738,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'); +},{}],19:[function(require,module,exports){ +var design, send; window.urb.appl = "talk"; @@ -5802,94 +5825,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){ +},{}],20:[function(require,module,exports){ var EventEmitter, MessageDispatcher, MessageStore, _fetching, _last, _listening, _messages, _station, _typing, moment; moment = require('moment-timezone'); 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/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:[] From 7c78c40d4f025a3c5625e49dc9eb335fd4f9c488 Mon Sep 17 00:00:00 2001 From: Anton Dyudin Date: Tue, 3 Nov 2015 12:12:32 -0800 Subject: [PATCH 6/9] check whether offline --- .../src/js/components/WritingComponent.coffee | 9 +- pub/talk/src/js/main.coffee | 10 +- pub/talk/src/js/main.js | 437 +++++++++++++++++- pub/talk/src/js/package.json | 1 + 4 files changed, 437 insertions(+), 20 deletions(-) diff --git a/pub/talk/src/js/components/WritingComponent.coffee b/pub/talk/src/js/components/WritingComponent.coffee index 640ecee530..2bdd4b15c4 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,12 @@ 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 + # XX insert actual css here return false @onInput() @set() diff --git a/pub/talk/src/js/main.coffee b/pub/talk/src/js/main.coffee index 89618c8927..2ac64c7117 100644 --- a/pub/talk/src/js/main.coffee +++ b/pub/talk/src/js/main.coffee @@ -4,7 +4,14 @@ $(() -> rend = React.render window.talk = {} - window.talk.MessagePersistence = require './persistence/MessagePersistence.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' @@ -15,6 +22,7 @@ $(() -> # else # $('#nav').removeClass 'scrolling' # setInterval checkScroll, 500 + StationActions.listen() diff --git a/pub/talk/src/js/main.js b/pub/talk/src/js/main.js index 819bfefff2..6f818a3fab 100644 --- a/pub/talk/src/js/main.js +++ b/pub/talk/src/js/main.js @@ -109,7 +109,7 @@ Persistence = _persistence({ -},{"../dispatcher/Dispatcher.coffee":7,"../persistence/MessagePersistence.coffee":18}],2:[function(require,module,exports){ +},{"../dispatcher/Dispatcher.coffee":7,"../persistence/MessagePersistence.coffee":19}],2:[function(require,module,exports){ var Dispatcher, Persistence, _persistence, serverAction, viewAction; Dispatcher = require('../dispatcher/Dispatcher.coffee'); @@ -222,7 +222,7 @@ Persistence = _persistence({ -},{"../dispatcher/Dispatcher.coffee":7,"../persistence/StationPersistence.coffee":19}],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; @@ -553,7 +553,7 @@ 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){ +},{"../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; @@ -731,13 +731,15 @@ module.exports = recl({ -},{"../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'); @@ -873,7 +875,14 @@ module.exports = recl({ txt = this.$writing.text(); e.preventDefault(); if (txt.length > 0) { - this.sendMessage(); + if (window.talk.online) { + this.sendMessage(); + } else { + this.errHue = ((this.errHue || 0) + (Math.random() * 300) + 30) % 360; + $('#offline').css({ + color: husl.toHex(this.errHue, 90, 50) + }); + } } return false; } @@ -1021,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; @@ -1049,7 +1058,15 @@ $(function() { StationActions = require('./actions/StationActions.coffee'); rend = React.render; window.talk = {}; - window.talk.MessagePersistence = require('./persistence/MessagePersistence.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'); StationActions.listen(); @@ -1064,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,"./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 = {}; @@ -1535,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": [ @@ -2124,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 @@ -2531,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 @@ -5727,7 +6128,7 @@ moment.tz.load(require('./data/packed/latest.json')); return _moment; })); -},{}],18:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ var send; window.urb.appl = "talk"; @@ -5805,7 +6206,7 @@ module.exports = function(arg) { -},{}],19:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ var design, send; window.urb.appl = "talk"; @@ -5916,7 +6317,7 @@ module.exports = function(arg) { -},{}],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'); @@ -6063,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; @@ -6303,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 = {}; } @@ -6415,7 +6816,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/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" } From 1674f4e0dac6fcf635f950ea158cf629ddf26c07 Mon Sep 17 00:00:00 2001 From: Anton Dyudin Date: Tue, 3 Nov 2015 12:55:28 -0800 Subject: [PATCH 7/9] grammar, css; this branch closes #339 --- pub/talk/src/css/main.css | 6 ++++++ pub/talk/src/css/main.styl | 6 ++++++ pub/talk/src/js/components/StationComponent.coffee | 2 +- pub/talk/src/js/components/WritingComponent.coffee | 7 ++++--- pub/talk/src/js/main.js | 7 +++---- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/pub/talk/src/css/main.css b/pub/talk/src/css/main.css index 7690f1b080..5b4b9859f0 100644 --- a/pub/talk/src/css/main.css +++ b/pub/talk/src/css/main.css @@ -594,6 +594,12 @@ a { 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 49fe153674..0aa6ac43eb 100644 --- a/pub/talk/src/css/main.styl +++ b/pub/talk/src/css/main.styl @@ -556,4 +556,10 @@ a 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/components/StationComponent.coffee b/pub/talk/src/js/components/StationComponent.coffee index 44753bc550..f6973e0282 100644 --- a/pub/talk/src/js/components/StationComponent.coffee +++ b/pub/talk/src/js/components/StationComponent.coffee @@ -109,7 +109,7 @@ module.exports = recl div {className:"path"} #, window.util.mainStation(window.urb.user)) div {className:"caret"} ) - div {id:"offline"}, "Warning: no connection server." + 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) diff --git a/pub/talk/src/js/components/WritingComponent.coffee b/pub/talk/src/js/components/WritingComponent.coffee index 2bdd4b15c4..fd8bf36bff 100644 --- a/pub/talk/src/js/components/WritingComponent.coffee +++ b/pub/talk/src/js/components/WritingComponent.coffee @@ -154,9 +154,10 @@ module.exports = recl if window.talk.online @sendMessage() else - @errHue = ((@errHue || 0) + (Math.random() * 300) + 30) % 360 - $('#offline').css color: husl.toHex @errHue, 90, 50 - # XX insert actual css here + #@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.js b/pub/talk/src/js/main.js index 6f818a3fab..230723836a 100644 --- a/pub/talk/src/js/main.js +++ b/pub/talk/src/js/main.js @@ -719,7 +719,7 @@ module.exports = recl({ className: "caret" })), div({ id: "offline" - }, "Warning: no connection server.")), div({ + }, "Warning: no connection to server.")), div({ id: "stations" }, h1({}, "Listening to"), div({}, sources), sourceCtrl), div({ id: "audience" @@ -878,9 +878,8 @@ module.exports = recl({ if (window.talk.online) { this.sendMessage(); } else { - this.errHue = ((this.errHue || 0) + (Math.random() * 300) + 30) % 360; - $('#offline').css({ - color: husl.toHex(this.errHue, 90, 50) + $('#offline').addClass('error').one('transitionend', function() { + return $('#offline').removeClass('error'); }); } } From 953e2ec334ef8618630103feec312aebf790257d Mon Sep 17 00:00:00 2001 From: "C. Guy Yarvin" Date: Wed, 4 Nov 2015 10:33:16 -0800 Subject: [PATCH 8/9] More small edits. --- pub/docs/dev/hoon/tutorial/0-nouns.mdy | 80 ++++++++++++++------------ 1 file changed, 44 insertions(+), 36 deletions(-) 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 From 3149dce765784a587ede420bf74291b191dd8c80 Mon Sep 17 00:00:00 2001 From: Galen Wolfe-Pauly Date: Tue, 3 Nov 2015 16:26:20 -0800 Subject: [PATCH 9/9] date sort kids --- .../src/js/components/KidsComponent.coffee | 30 +++++++++++---- pub/tree/src/js/main.js | 37 ++++++++++++------- 2 files changed, 46 insertions(+), 21 deletions(-) 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