diff --git a/pub/bootstrap/hymn.hook b/pub/bootstrap/hymn.hook index d61143a2e..78d5be8a1 100644 --- a/pub/bootstrap/hymn.hook +++ b/pub/bootstrap/hymn.hook @@ -18,8 +18,8 @@ ;head ;title: Bootstrap Test - ~2016.1 ;meta(name "viewport", content "width=device-width, initial-scale=1"); - ;link(rel "stylesheet", href "/home/lib/fonts.css"); - ;link(rel "stylesheet", href "/home/lib/bootstrap.css"); + ;link(rel "stylesheet", href "/home/lib/css/fonts.css"); + ;link(rel "stylesheet", href "/home/lib/css/bootstrap.css"); ;script(src "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.js"); == ;body diff --git a/pub/module/main.js b/pub/module/main.js new file mode 100644 index 000000000..f6433dca1 --- /dev/null +++ b/pub/module/main.js @@ -0,0 +1,6 @@ +main = { + mount: function() { console.log('mount.') }, + unmount: function() { console.log('unmount.') } +} + +window.tree.modules.talk = main \ No newline at end of file diff --git a/pub/module/mod.md b/pub/module/mod.md new file mode 100644 index 000000000..38ec42b4d --- /dev/null +++ b/pub/module/mod.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pub/talk/hymn.hook b/pub/talk/hymn.hook index 16184e286..4d074f95f 100644 --- a/pub/talk/hymn.hook +++ b/pub/talk/hymn.hook @@ -31,10 +31,10 @@ "lodash.js/2.4.1/lodash.min.js" "react/0.13.1/react.js" == - ;script(type "text/javascript", src "{?:(aut "/~~" "")}/~/at/home/lib/urb.js"); + ;script(type "text/javascript", src "{?:(aut "/~~" "")}/~/at/home/lib/js/urb.js"); ;meta(name "viewport", content "width=device-width, height=device-height, ". "initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"); - ;link(type "text/css", rel "stylesheet", href "/home/pub/talk/src/css/main.css"); + ;link(type "text/css", rel "stylesheet", href "/home/pub/talk/main.css"); ;title: Talk == ;body @@ -45,6 +45,6 @@ ;div#scrolling: BOTTOM == ;script: window.talk = {(pojo (joba 'mainStation' s/man))} - ;script(type "text/javascript", src "/home/pub/talk/src/js/main.js"); + ;script(type "text/javascript", src "/home/pub/talk/main.js"); == == diff --git a/pub/talk/src/css/main.css b/pub/talk/main.css similarity index 100% rename from pub/talk/src/css/main.css rename to pub/talk/main.css diff --git a/pub/talk/src/js/main.js b/pub/talk/main.js similarity index 100% rename from pub/talk/src/js/main.js rename to pub/talk/main.js diff --git a/pub/talk/src/css/fonts.styl b/pub/talk/src/css/fonts.styl deleted file mode 100644 index abfedf60e..000000000 --- a/pub/talk/src/css/fonts.styl +++ /dev/null @@ -1,84 +0,0 @@ -@font-face { - font-family: "bau"; - src: url("//storage.googleapis.com/urbit-extra/bau.woff"); - font-weight: 400; - font-style: normal; -} -@font-face { - font-family: "bau"; - src: url("//storage.googleapis.com/urbit-extra/bau-italic.woff"); - font-weight: 400; - font-style: italic; -} -@font-face { - font-family: "bau"; - src: url("//storage.googleapis.com/urbit-extra/bau-medium.woff"); - font-weight: 500; - font-style: normal; -} -@font-face { - font-family: "bau"; - src: url("//storage.googleapis.com/urbit-extra/bau-mediumitalic.woff"); - font-weight: 500; - font-style: italic; -} -@font-face { - font-family: "bau"; - src: url("//storage.googleapis.com/urbit-extra/bau-bold.woff"); - font-weight: 600; - font-style: normal; -} -@font-face { - font-family: "bau"; - src: url("//storage.googleapis.com/urbit-extra/bau-bolditalic.woff"); - font-weight: 600; - font-style: italic; -} -@font-face { - font-family: "bau"; - src: url("//storage.googleapis.com/urbit-extra/bau-super.woff"); - font-weight: 600; - font-style: normal; -} -@font-face { - font-family: "bau"; - src: url("//storage.googleapis.com/urbit-extra/bau-superitalic.woff"); - font-weight: 600; - font-style: italic; -} -@font-face { - font-family: "scp"; - src: url("//storage.googleapis.com/urbit-extra/scp-extralight.woff"); - font-weight: 200; - font-style: normal; -} -@font-face { - font-family: "scp"; - src: url("//storage.googleapis.com/urbit-extra/scp-light.woff"); - font-weight: 300; - font-style: normal; -} -@font-face { - font-family: "scp"; - src: url("//storage.googleapis.com/urbit-extra/scp-regular.woff"); - font-weight: 400; - font-style: normal; -} -@font-face { - font-family: "scp"; - src: url("//storage.googleapis.com/urbit-extra/scp-medium.woff"); - font-weight: 500; - font-style: normal; -} -@font-face { - font-family: "scp"; - src: url("//storage.googleapis.com/urbit-extra/scp-bold.woff"); - font-weight: 600; - font-style: normal; -} -@font-face { - font-family: "scp"; - src: url("//storage.googleapis.com/urbit-extra/scp-black.woff"); - font-weight: 700; - font-style: normal; -} \ No newline at end of file diff --git a/pub/talk/src/css/main.styl b/pub/talk/src/css/main.styl deleted file mode 100644 index 0aa6ac43e..000000000 --- a/pub/talk/src/css/main.styl +++ /dev/null @@ -1,565 +0,0 @@ -// -// fonts first -// - -@import 'fonts' - -html -body - height 100% - font-family "bau" - -.type - font-family "scp" - -input - font-size 1rem - -webkit-appearance none - border-radius 0 - font-family "bau" - -#length -.time - letter-spacing 0 - -.time - font-weight 200 - letter-spacing .1rem - color #555 - -#length -.audi -.time -.station -#audience .iden - font-size .8rem - line-height 1rem - -#length - letter-spacing .1rem - -#writing-container:focus #length - display inline - -// input.join -// .iden -// .audi -// #station -// font-size .7rem - -.ship - text-transform uppercase - letter-spacing .05rem - -html -body - font-size 18px - -// -// containers -// - -body - background-color #fefefe - padding 0 - margin 0 - -.hidden - display none - -#c - position absolute - top 0rem - left 50% - width 58rem - margin-left -29rem - margin-bottom 6rem - -#station-container - position fixed - width 58rem - max-height 4rem - background-color rgba(255,255,255,.95) - color #555 - overflow hidden - z-index 10 - border-bottom 1px solid #ddd - -webkit-transition max-height .2s - -#station #station-container - padding-top 1rem - min-width 30rem - text-align right - -#writing-container - margin-top 2rem - margin-bottom 1rem - -#messages-container - vertical-align top - margin-top 5rem - -// -// components -// - -.caret -.circle - display inline-block - -.caret - width 0 - height 0 - border-top 6px solid transparent - border-right 6px solid transparent - border-bottom 6px solid transparent - border-left 6px solid #000 - margin-top 2px - -.circle - width 6px - height 6px - border 3px solid black - border-radius 6px - margin-top 2px - -// -// station -// - -#station-container #where .caret - -webkit-transform rotate(0deg) - -webkit-transform-origin 0 50% - -webkit-transition -webkit-transform .2s - -#station-container #where .caret - margin-top 9px - border-top 9px solid transparent - border-right 9px solid transparent - border-bottom 9px solid transparent - border-left 9px solid white - -webkit-transition border-left-color .2s - -#head - width 100% - height 4rem - color #333 - border-bottom 1px solid #ddd - -#station-container h1 - display none - color #555 - font-weight 400 - font-size 1rem - letter-spacing .06rem - display inline-block - line-height 1.2rem - -#station-container h1:after - content "—" - margin-left .6rem - -#station-container .audi -#station-container .iden > div - background-color transparent - -#who - width 16rem - -#stations - width 15rem - padding-bottom 1rem - border-left 16rem solid transparent - -#station-container #head .ship - font-size .9rem - font-weight 400 - -#station-container:hover #where - color white - -webkit-transition color .2s - -#station-container:hover #where - color rgb(240,73,65) - -webkit-transition color .2s - -#station-container:hover #where .caret - border-left-color rgb(240,73,65) - -webkit-transition border-left-color .2s - -#stations -#audience -#head > div -#where > div - display inline-block - vertical-align top - -#where > div - margin-right 1rem - text-transform capitalize - letter-spacing .05rem - font-size 1.6rem - -#where .slat - font-weight 500 - -#where .slat:after - margin-left 1rem - content "—" - -#head > div - height 2rem - line-height 2rem - margin-top 1rem - -#where .caret - border-left-color white - -#who > div - vertical-align middle - -#members - margin-bottom 1rem - -#members > div - display block - max-width 24rem - overflow hidden - white-space nowrap - -#members > div:hover - white-space normal - -#members > div div - display inline-block - vertical-align bottom - -#members .audi - margin-right .3rem - margin-top 0 - -#members .iden - min-width 10rem - -.station div - display inline-block - -.station .path - text-transform uppercase - -.station .remove - opacity 0 - cursor pointer - width .6rem - margin-left .6rem - line-height 1rem - font-size 1.2rem - font-weight 500 - color #ff0000 - vertical-align top - -.station:hover .remove - opacity 1 - -// add source -.sour-ctrl input - color #555 - background-color transparent - border none - font-size .8rem - line-height 1.2rem - letter-spacing .05rem - margin-top .6rem - font-weight 300 - text-align left - outline none - cursor pointer - text-transform uppercase - border-bottom 2px solid transparent - -.sour-ctrl input:focus - border-bottom 2px solid #fff - -.sour-ctrl input::-webkit-input-placeholder - font-weight 400 - font-size 1.2rem - margin-left .6rem - color #555 - -.sour-ctrl input:focus::-webkit-input-placeholder - color transparent - -// -// messages -// - -.message - padding-top .3rem - margin-bottom .6rem - -#messages .message .time -#messages .message .audi - opacity 0 - margin-left 2rem - -#messages .message:hover .time -#messages .message:hover .audi - opacity 1 - -#messages .message .attr - position absolute - overflow hidden - max-height 1.6rem - white-space nowrap - -// #writing-container -// #messages .message.first -// border-top 1px solid #ededed - -#writing-container - padding-top .3rem - -#messages .message.first - -#messages .message.same .audi - margin-top 0 - -#messages .message.same .type - opacity 0 - -#messages .message.same .iden - display none - -#messages .message:hover .type - color rgb(240,73,65) - -#messages .message.attr - max-height 2rem - -webkit-transition max-height 2s, color .1s linear - -#messages .message:hover .attr - max-height 6rem - padding-bottom 1rem - z-index 3 - -webkit-transition max-height .2s, color .1s linear - -#messages .message:hover .attr > div - max-width 48rem - -#messages .message .ship -#messages .message .audi > div - cursor pointer - -#messages .message.new - border-top 1px solid #e5e5e5 - -.member - width 12rem - margin .3rem .6rem .3rem 0 - -#messages - height auto - -.message.pending - color #ccc - -.message.say .mess - font-style italic - -.message.exp .mess - font-family monospace - -a - text-decoration underline - color inherit - -.sig -.type - margin-left 1rem - float left - width 1rem - -.type - height 2rem - -.sig - font-size 2rem - margin-left .7rem - margin-right .3rem - -.sig:before - content "~" - -.type.private:before - content attr(data-glyph) - font-size 1rem - line-height 1.1rem - -.type.public:before - content attr(data-glyph) - font-size .8rem - line-height 1.2rem - -.mess -.iden -#station .member div -#writing - display inline-block - -.mess -#writing -#length - vertical-align top - -.attr > div - line-height 1.4rem - max-width 16rem - -.attr - text-align left - display inline-block - max-height 1.2rem - margin-right .3rem - min-width 16rem - background-color white - -.attr .iden - line-hieght 1.4rem - -.audi -.station .path - white-space nowrap - overflow hidden - text-transform uppercase - letter-spacing .05rem - -.audi - margin-top 1rem - background-color #fff - -.audi > div - margin-right .3rem - max-width 16rem - display block - -.iden > div - max-width 11rem - display inline-block - font-size .9rem - -.iden > div -.audi > div - background-color white - overflow hidden - white-space nowrap - text-overflow ellipsis - -webkit-transition max-width .2s - -.audi > div:last-child - margin-right 0 - -.iden > div:hover -.audi > div:hover - position relative - -webkit-transition max-width .2s - -.mess - letter-spacing .03rem - word-wrap break-word - margin-left 16.3rem - -.mess -#writing -.iden > div:hover -.audi > div:hover - max-width 42rem - -.iden > div:hover - padding-right 3rem - -.mess -#writing - font-size 1.2rem - -// -// writing -// - -#writing - min-height 1.6rem - min-width 1.3rem - max-width 32rem - line-height 2rem - outline none - padding .3rem .1rem - margin-top -.3rem - border-bottom 3px solid #555 - -.writing - padding-top .3rem - -.writing #length - display inline - margin-left 1rem - margin-top 1.2rem - -.writing .attr - line-height 1.6rem - vertical-align top - margin-left 2rem - min-width 14rem - -.writing .iden - display block - width 100% - -.writing .iden .ship - margin-right .3rem - -#audi - display inline-block - margin-right -.2rem - margin-bottom .3rem - outline none - overflow hidden - max-width 12rem - min-width 1rem - padding .3rem .1rem .1rem 0 - border-bottom 2px solid #555 - -.valid-false - color #ff2f2f !important - -// -// scrolling -// - -#scrolling - display none - -.scrolling #scrolling - position fixed - bottom 3rem - left 2rem - height 1rem - padding 1rem - height 2rem - background-color #f9f9f9 - font-weight 500 - font-size .8rem - text-transform uppercase - -// -// offline -// - -body:not(.offline) #offline - display none - -#offline - transition: color 0.25s ease - -#offline.error - color: red - -@import 'mobile' diff --git a/pub/talk/src/css/mobile.styl b/pub/talk/src/css/mobile.styl deleted file mode 100644 index bb63d3239..000000000 --- a/pub/talk/src/css/mobile.styl +++ /dev/null @@ -1,91 +0,0 @@ -/* computers --------*/ -@media only screen and (min-width: 1024px) - #station-container:hover - max-height 30rem - height auto - -webkit-transition max-height .2s - - #station-container:hover #where .caret - transform rotate(90deg) - transform-origin 0 50% - -webkit-transform rotate(90deg) - -webkit-transition -webkit-transform .2s - -/* laptops / small screens ----------- */ -@media only screen and (max-width: 1170px) - #station-container.open - max-height 30rem - height auto - -webkit-transition max-height .2s - - #station-container.open #where .caret - transform rotate(90deg) - transform-origin 0 50% - -webkit-transform rotate(90deg) - -webkit-transition -webkit-transform .2s - - #c - #station-container - width 96% - left 0 - margin-left 2% - margin-right 2% - - .mess - #writing - max-width 60% - line-height 1.6rem - - .attr - #stations - #where - width 20% - min-width 20% - - #audience - #who - width 60% - - #writing - padding .1rem - - #station-container.m-down - #station-container.m-up - position absolute - - #station-container.m-down.m-fixed - position fixed - top 0 - -/* tablets + phones ----------- */ -// @media only screen and (min-width: 320px) and (max-width: 1024px) - -/* phones portrait and landscape ----------- */ -@media only screen and (min-device-width: 320px) and (max-device-width: 480px) - .mess - #writing - max-width 70% - line-height 1.2rem - - #stations - #audience - width 96% - - #stations - #audience - .sour-ctrl input - text-align left - - #station - cursor pointer - - #station-container.open - max-height 30rem - height auto - -webkit-transition max-height .2s - - #station-container.open #where .caret - transform rotate(90deg) - transform-origin 0 50% - -webkit-transform rotate(90deg) - -webkit-transition -webkit-transform .2s diff --git a/pub/talk/src/js/.main.js b/pub/talk/src/js/.main.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/pub/talk/src/js/actions/MessageActions.coffee b/pub/talk/src/js/actions/MessageActions.coffee deleted file mode 100644 index 6843bfcd5..000000000 --- a/pub/talk/src/js/actions/MessageActions.coffee +++ /dev/null @@ -1,75 +0,0 @@ -Dispatcher = require '../dispatcher/Dispatcher.coffee' - -_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()) - Persistence.listenStation station,date - - listeningStation: (station) -> - Dispatcher.handleViewAction {station,type:"messages-listen"} - - setTyping: (state) -> - Dispatcher.handleViewAction {state,type:"messages-typing"} - - getMore: (station,start,end) -> - Dispatcher.handleViewAction type:"messages-fetch" - Persistence.get station,start,end - - sendMessage: (txt,audience) -> - serial = window.util.uuid32() - - # audience.push window.util.mainStationPath window.urb.user - audience = _.uniq audience - - _audi = {} - for k,v of audience - _audi[v] = - envelope: - visible:true - sender:null - delivery:"pending" - - speech = lin: {txt, say:true} - - if txt[0] is "@" - speech.lin.txt = speech.lin.txt.slice(1).trim() - speech.lin.say = false - - else if txt[0] is "#" - speech = eval: speech.lin.txt.slice(1).trim() - - else if window.urb.util.isURL(txt) - speech = url: txt - - speeches = - if not (speech.lin?.txt.length > 64) - [speech] - else - {say,txt} = speech.lin - txt.match(/(.{1,64}$|.{0,64} |.{64}|.+$)/g).map (s,i)-> - say ||= i isnt 0 - lin: {say, txt: - if s.slice -1 isnt " " - s - else s.slice 0,-1 - } - - for speech in speeches - message = - ship:window.urb.ship - thought: - serial:window.util.uuid32() - audience:_audi - statement: - bouquet:[] - speech:speech - date: Date.now() - - 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 deleted file mode 100644 index 2ea566488..000000000 --- a/pub/talk/src/js/actions/StationActions.coffee +++ /dev/null @@ -1,31 +0,0 @@ -Dispatcher = require '../dispatcher/Dispatcher.coffee' -serverAction = (f)-> ()-> Dispatcher.handleServerAction f.apply this,arguments -viewAction = (f)-> ()-> Dispatcher.handleViewAction f.apply this,arguments - -_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"} - - 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) -> - Dispatcher.handleViewAction {station,type: "station-create"} - Persistence.createStation station - - listen: () -> Persistence.listen() - ping: (_ping) -> Persistence.ping _ping - removeStation: (station) -> Persistence.removeStation station - listenStation: (station) -> Persistence.listenStation station - createStation: (name) -> Persistence.createStation name - - setSources: (station,sources) -> - Persistence.setSources station,window.urb.ship,sources diff --git a/pub/talk/src/js/components/MemberComponent.coffee b/pub/talk/src/js/components/MemberComponent.coffee deleted file mode 100644 index 46be2a3a1..000000000 --- a/pub/talk/src/js/components/MemberComponent.coffee +++ /dev/null @@ -1,12 +0,0 @@ -recl = React.createClass -{div,input,textarea} = React.DOM - -module.exports = recl - render: -> - if @props.ship[0] is "~" then @props.ship = @props.ship.slice(1) - k = "ship" - k+= " #{@props.presence}" if @props.presence - div {className:"iden"}, [ - # div {}, @props.glyph || "*" - div {className:k}, @props.ship - ] diff --git a/pub/talk/src/js/components/MessagesComponent.coffee b/pub/talk/src/js/components/MessagesComponent.coffee deleted file mode 100644 index c337106b2..000000000 --- a/pub/talk/src/js/components/MessagesComponent.coffee +++ /dev/null @@ -1,213 +0,0 @@ -moment = require 'moment-timezone' -clas = require 'classnames' - -recl = React.createClass -{div,pre,br,span,input,textarea,a} = React.DOM - -MessageActions = require '../actions/MessageActions.coffee' -MessageStore = require '../stores/MessageStore.coffee' -StationActions = require '../actions/StationActions.coffee' -StationStore = require '../stores/StationStore.coffee' -Member = require './MemberComponent.coffee' - -Message = recl - displayName: "Message" - lz: (n) -> if n<10 then "0#{n}" else "#{n}" - - convTime: (time) -> - d = new Date time - h = @lz d.getHours() - m = @lz d.getMinutes() - s = @lz d.getSeconds() - "~#{h}.#{m}.#{s}" - - _handleAudi: (e) -> - audi = _.map $(e.target).closest('.audi').find('div'), (div) -> return "~"+$(div).text() - @props._handleAudi audi - - _handlePm: (e) -> - return if not @props._handlePm - user = $(e.target).closest('.iden').text() - return if user.toLowerCase() is 'system' - @props._handlePm user - - renderSpeech: (speech)-> switch - when (con = speech.lin) or (con = speech.app) or - (con = speech.exp) or (con = speech.tax) - con.txt - when (con = speech.url) - (a {href:con.txt,target:"_blank"}, con.txt) - when (con = speech.mor) then con.map @renderSpeech - else "Unknown speech type:" + (" %"+x for x of speech).join '' - - render: -> - # pendingClass = clas pending: @props.pending isnt "received" - delivery = _.uniq _.pluck @props.thought.audience, "delivery" - speech = @props.thought.statement.speech - attachments = [] - while speech.fat? - attachments.push pre {}, speech.fat.tor.tank.join("\n") - speech = speech.fat.taf # XX - if !speech? then return; - - name = if @props.name then @props.name else "" - aude = _.keys @props.thought.audience - audi = window.util.clipAudi(aude).map (_audi) -> (div {}, _audi.slice(1)) - - mainStation = window.util.mainStationPath(window.urb.user) - type = if mainStation in aude then 'private' else 'public' - - className = clas {message:true}, - (if @props.sameAs then "same" else "first"), - (if delivery.indexOf("received") isnt -1 then "received" else "pending"), - {say: speech.lin?.say is false, url: speech.url, 'new': @props.unseen}, - switch - when speech.app? then "say" - when speech.exp? then "exp" - - div {className}, [ - (div {className:"attr"}, [ - div {className:"type #{type}", "data-glyph": @props.glyph || "*"} - (div {onClick:@_handlePm}, - (React.createElement Member,{ship:@props.ship,glyph:@props.glyph})) - div {onClick:@_handleAudi,className:"audi"}, audi - div {className:"time"}, @convTime @props.thought.statement.date - ]) - - div {className:"mess"}, - (@renderSpeech speech) - if attachments.length - div {className:"fat"}, attachments - ] - -module.exports = recl - displayName: "Messages" - pageSize: 50 - paddingTop: 100 - - stateFromStore: -> { - messages:MessageStore.getAll() - last:MessageStore.getLast() - fetching:MessageStore.getFetching() - listening:MessageStore.getListening() - station:window.talk.mainStation - stations:StationStore.getStations() - configs:StationStore.getConfigs() - typing:MessageStore.getTyping() - glyphs:StationStore.getGlyphMap() - } - - getInitialState: -> @stateFromStore() - - _blur: -> - @focussed = false - @lastSeen = @last - - _focus: -> - @focussed = true - @lastSeen = null - $('.message.new').removeClass 'new' - document.title = document.title.replace /\ \([0-9]*\)/, "" - - checkMore: -> - if $(window).scrollTop() < @paddingTop && - @state.fetching is false && - this.state.last && - this.state.last > 0 - end = @state.last-@pageSize - end = 0 if end < 0 - @lastLength = @length - MessageActions.getMore @state.station,(@state.last+1),end - - setAudience: -> - return if not @last - if _.keys(@last.thought.audience).length > 0 and @state.typing is false and - _.difference(_.keys(@last.thought.audience),@state.audi).length is 0 - StationActions.setAudience _.keys(@last.thought.audience) - - sortedMessages: (messages) -> - _.sortBy messages, (_message) -> - _message.pending = _message.thought.audience[station] - _message.key - #_message.thought.statement.date - - componentDidMount: -> - MessageStore.addChangeListener @_onChangeStore - StationStore.addChangeListener @_onChangeStore - if @state.station and - @state.listening.indexOf(@state.station) is -1 - MessageActions.listenStation @state.station - checkMore = @checkMore - $(window).on 'scroll', checkMore - @focussed = true - $(window).on 'blur', @_blur - $(window).on 'focus', @_focus - window.util.setScroll() - - componentDidUpdate: -> - $window = $(window) - if @lastLength - st = $window.height() - $window.scrollTop st - @lastLength = null - else - if not window.util.isScrolling() - window.util.setScroll() - else - console.log 'scrolling' - - if @focussed is false and @last isnt @lastSeen - _messages = @sortedMessages @state.messages - d = _messages.length-_messages.indexOf(@lastSeen)-1 - t = document.title - if document.title.match(/\([0-9]*\)/) - document.title = document.title.replace /\([0-9]*\)/, "(#{d})" - else - document.title = document.title + " (#{d})" - - componentWillUnmount: -> - MessageStore.removeChangeListener @_onChangeStore - StationStore.removeChangeListener @_onChangeStore - - _onChangeStore: -> @setState @stateFromStore() - - _handlePm: (user) -> - audi = [window.util.mainStationPath(user)] - if user is window.urb.user then audi.pop() - StationActions.setAudience audi - - _handleAudi: (audi) -> StationActions.setAudience audi - - render: -> - station = @state.station - _station = "~"+window.urb.ship+"/"+station - sources = _.clone @state.configs[@state.station]?.sources ? [] - sources.push _station - _messages = @sortedMessages @state.messages - - @last = _messages[_messages.length-1] - if @last?.ship && @last.ship is window.urb.user then @lastSeen = @last - @length = _messages.length - - setTimeout => - @checkMore() if length < @pageSize - , 1 - - lastIndex = if @lastSeen then _messages.indexOf(@lastSeen)+1 else null - lastSaid = null - - div {id: "messages"}, _messages.map (_message,k) => - nowSaid = [_message.ship,_message.thought.audience] - glyph = window.util.getGlyph @state.glyphs, _.keys _message.thought.audience - {station} = @state - mess = { - glyph, station, @_handlePm, @_handleAudi, - unseen: lastIndex and lastIndex is k - sameAs: _.isEqual lastSaid, nowSaid - } - lastSaid = nowSaid - - if _message.thought.statement.speech?.app - mess.ship = "system" - - React.createElement Message, (_.extend {}, _message, mess) diff --git a/pub/talk/src/js/components/StationComponent.coffee b/pub/talk/src/js/components/StationComponent.coffee deleted file mode 100644 index 7cd76078b..000000000 --- a/pub/talk/src/js/components/StationComponent.coffee +++ /dev/null @@ -1,119 +0,0 @@ -recl = React.createClass -{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() - station:window.talk.mainStation - stations:StationStore.getStations() - configs:StationStore.getConfigs() - typing:StationStore.getTyping() - listening:StationStore.getListening() - } - - getInitialState: -> @stateFromStore() - - componentDidMount: -> - @$el = $(@getDOMNode()) - @$input = @$el.find('input') - - StationStore.addChangeListener @_onChangeStore - if @state.listening.indexOf(@state.station) is -1 - StationActions.listenStation @state.station - - componentWillUnmount: -> - StationStore.removeChangeListener @_onChangeStore - - - _onChangeStore: -> - @setState @stateFromStore() - - _toggleOpen: (e) -> - if $(e.target).closest('.sour-ctrl').length > 0 - return - $("#station-container").toggleClass 'open' - - validateSource: (s) -> - if @state.configs[@state.station].sources.indexOf(s) isnt -1 - return false - if s.length < 5 - return false - if s[0] isnt "~" - return false - if s.indexOf("/") is -1 - return false - return true - - _keyUp: (e) -> - $('.sour-ctrl .join').removeClass 'valid-false' - if e.keyCode is 13 - v = @$input.val().toLowerCase() - if v[0] isnt "~" then v = "~#{v}" - if @validateSource v - _sources = _.clone @state.configs[@state.station].sources - _sources.push v - StationActions.setSources @state.station,_sources - @$input.val('') - @$input.blur() - else - $('.sour-ctrl .join').addClass 'valid-false' - - _remove: (e) -> - e.stopPropagation() - e.preventDefault() - _station = $(e.target).attr "data-station" - _sources = _.clone @state.configs[@state.station].sources - _sources.splice _sources.indexOf(_station),1 - StationActions.setSources @state.station,_sources - - render: -> - if window.urb.user isnt window.urb.ship #foreign - return div {id:"station"} - - parts = [] - members = [] - - if @state.station and @state.members - members = _.map @state.members, (stations,member) -> - audi = _.map stations,(presence,station) -> (div {className:"audi"}, station.slice(1)) - (div {}, [(React.createElement Member, {ship:member}),audi]) - else - members = "" - - sourceInput = [(input {className:"join",onKeyUp:@_keyUp,placeholder:"+"})] - sourceCtrl = div {className:"sour-ctrl"},sourceInput - - sources = [] - if @state.station and @state.configs[@state.station] - _remove = @_remove - _sources = _.clone @state.configs[@state.station].sources - sources = _.map _sources,(source) => - (div {className:"station"}, [ - (div {className:"path"}, source.slice(1)) - (div {className:"remove",onClick:_remove,"data-station":source},"×"), - ]) - else - sources = "" - - (div {id:"station",onClick:@_toggleOpen}, - (div {id:"head"}, - (div {id:"who"}, - div {className:"sig"} - div {className:"ship"},"#{window.urb.user}" - ) - (div {id:"where"}, - div {className:"slat"},"talk" - div {className:"path"} #, window.util.mainStation(window.urb.user)) - div {className:"caret"} - ) - div {id:"offline"}, "Warning: no connection to server." - ) - 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/StationsComponent.coffee b/pub/talk/src/js/components/StationsComponent.coffee deleted file mode 100644 index 0309ffc32..000000000 --- a/pub/talk/src/js/components/StationsComponent.coffee +++ /dev/null @@ -1,61 +0,0 @@ -recl = React.createClass -{div,input} = React.DOM - -StationStore = require '../stores/StationStore.coffee' -StationActions = require '../actions/StationActions.coffee' - -module.exports = recl - stateFromStore: -> { - stations: StationStore.getStations() - station: "~zod/court" - } - - getInitialState: -> @stateFromStore() - - componentDidMount: -> - @$el = $ @getDOMNode() - @$add = $ '#stations .add' - @$input = @$el.find 'input' - StationStore.addChangeListener @_onChangeStore - - componentWillUnmount: -> - StationStore.removeChangeListener @_onChangeStore - - _onChangeStore: -> @setState @stateFromStore() - - _click: (e) -> - s = $(e.target).closest('.station').find('.name').text() - window.location.hash = "/#{s.toLowerCase()}" - - _keyUp: (e) -> - if e.keyCode is 13 - v = @$input.val().toLowerCase() - if @state.stations.indexOf(v) is -1 - StationActions.createStation v - @$input.val('') - @$input.blur() - - _remove: (e) -> - _station = $(e.target).parent().find('.name').text() - _stations = _.without @state.stations,_station - StationActions.removeStation _station,_stations - e.stopPropagation() - e.preventDefault() - - render: -> - station = @state.station - _click = @_click - _remove = @_remove - stations = @state.stations.map (_station) -> - k = "station" - parts = [(div {className:"name"}, _station.name)] - if _station.name isnt window.util.mainStation() - parts.push (div {className:"remove",onClick:_remove,dataStation:_station.name},"×") - div {className:k,onClick:_click},parts - - div {id:"stations"}, [ - div {className:"stations"},stations - div {className:"join-ctrl"}, [ - input {className:"join",onKeyUp:@_keyUp,placeholder:"+"}, "" - ] - ] \ No newline at end of file diff --git a/pub/talk/src/js/components/TalkComponent.coffee b/pub/talk/src/js/components/TalkComponent.coffee deleted file mode 100644 index ae816c81e..000000000 --- a/pub/talk/src/js/components/TalkComponent.coffee +++ /dev/null @@ -1,15 +0,0 @@ -recl = React.createClass -recf = React.createFactory -{div} = React.DOM - -StationComponent = recf require './StationComponent.coffee' -MessagesComponent = recf require './MessagesComponent.coffee' -WritingComponent = recf require './WritingComponent.coffee' - -module.exports = recl - render: -> - (div {}, [ - (div {id:"station-container"}, (StationComponent {})) - (div {id:"messages-container"}, (MessagesComponent {})) - (div {id:"writing-container"}, (WritingComponent {})) - ]) \ No newline at end of file diff --git a/pub/talk/src/js/components/WritingComponent.coffee b/pub/talk/src/js/components/WritingComponent.coffee deleted file mode 100644 index 795df136f..000000000 --- a/pub/talk/src/js/components/WritingComponent.coffee +++ /dev/null @@ -1,284 +0,0 @@ -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' -StationStore = require '../stores/StationStore.coffee' -Member = require './MemberComponent.coffee' - -SHIPSHAPE = /// -^~?( #preamble - [a-z]{3} # galaxy - | [a-z]{6}(-[a-z]{6}){0,3} # star - moon - | [a-z]{6}(-[a-z]{6}){3} # comet - (--[a-z]{6}(-[a-z]{6}){3})+ # -)$ #postamble -/// -PO = ''' -dozmarbinwansamlitsighidfidlissogdirwacsabwissib -rigsoldopmodfoglidhopdardorlorhodfolrintogsilmir -holpaslacrovlivdalsatlibtabhanticpidtorbolfosdot -losdilforpilramtirwintadbicdifrocwidbisdasmidlop -rilnardapmolsanlocnovsitnidtipsicropwitnatpanmin -ritpodmottamtolsavposnapnopsomfinfonbanporworsip -ronnorbotwicsocwatdolmagpicdavbidbaltimtasmallig -sivtagpadsaldivdactansidfabtarmonranniswolmispal -lasdismaprabtobrollatlonnodnavfignomnibpagsopral -bilhaddocridmocpacravripfaltodtiltinhapmicfanpat -taclabmogsimsonpinlomrictapfirhasbosbatpochactid -havsaplindibhosdabbitbarracparloddosbortochilmac -tomdigfilfasmithobharmighinradmashalraglagfadtop -mophabnilnosmilfopfamdatnoldinhatnacrisfotribhoc -nimlarfitwalrapsarnalmoslandondanladdovrivbacpol -laptalpitnambonrostonfodponsovnocsorlavmatmipfap - -zodnecbudwessevpersutletfulpensytdurwepserwylsun -rypsyxdyrnuphebpeglupdepdysputlughecryttyvsydnex -lunmeplutseppesdelsulpedtemledtulmetwenbynhexfeb -pyldulhetmevruttylwydtepbesdexsefwycburderneppur -rysrebdennutsubpetrulsynregtydsupsemwynrecmegnet -secmulnymtevwebsummutnyxrextebfushepbenmuswyxsym -selrucdecwexsyrwetdylmynmesdetbetbeltuxtugmyrpel -syptermebsetdutdegtexsurfeltudnuxruxrenwytnubmed -lytdusnebrumtynseglyxpunresredfunrevrefmectedrus -bexlebduxrynnumpyxrygryxfeptyrtustyclegnemfermer -tenlusnussyltecmexpubrymtucfyllepdebbermughuttun -bylsudpemdevlurdefbusbeprunmelpexdytbyttyplevmyl -wedducfurfexnulluclennerlexrupnedlecrydlydfenwel -nydhusrelrudneshesfetdesretdunlernyrsebhulryllud -remlysfynwerrycsugnysnyllyndyndemluxfedsedbecmun -lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes -''' - -Audience = recl - displayName: "Audience" - onKeyDown: (e) -> - if e.keyCode is 13 - e.preventDefault() - setTimeout () -> - $('#writing').focus() - ,0 - return false - render: -> - div { - id:"audi" - className:"audi valid-#{@props.valid}" - contentEditable:true - @onKeyDown - onBlur:@props.onBlur - }, @props.audi.join(" ") - -module.exports = recl - displayName: "Writing" - set: -> - if window.localStorage and @$writing then window.localStorage.setItem 'writing', @$writing.text() - - get: -> - if window.localStorage then window.localStorage.getItem 'writing' - - stateFromStore: -> - s = - audi:StationStore.getAudience() - ludi:MessageStore.getLastAudience() - config:StationStore.getConfigs() - members:StationStore.getMembers() - typing:StationStore.getTyping() - valid:StationStore.getValidAudience() - s.audi = _.without s.audi, window.util.mainStationPath window.urb.user - s.ludi = _.without s.ludi, window.util.mainStationPath window.urb.user - s - - getInitialState: -> _.extend @stateFromStore(), length:0, lengthy: false - - typing: (state) -> - if @state.typing[@state.station] isnt state - StationActions.setTyping @state.station,state - - onBlur: -> - @$writing.text @$writing.text() - MessageActions.setTyping false - @typing false - - onFocus: -> - MessageActions.setTyping true - @typing true - @cursorAtEnd - - addCC: (audi) -> - if window.urb.user isnt window.urb.ship #foreign - return audi - listening = @state.config[window.util.mainStation(window.urb.user)]?.sources ? [] - cc = false - for s in audi - if listening.indexOf(s) is -1 - cc = true - if listening.length is 0 then cc = true - if cc is true - audi.push window.util.mainStationPath(window.urb.user) - audi - - sendMessage: -> - if @_validateAudi() is false - $('#audi').focus() - return - if @state.audi.length is 0 and $('#audi').text().trim().length > 0 - audi = if @_setAudi() then @_setAudi() else @state.ludi - else - audi = @state.audi - audi = @addCC audi - txt = @$writing.text().trim().replace(/\xa0/g,' ') - MessageActions.sendMessage txt,audi - @$writing.text('') - @setState length:0 - @set() - @typing false - - onKeyUp: (e) -> - if not window.urb.util.isURL @$writing.text() - @setState lengthy: (@$writing.text().length > 62) - # r = window.getSelection().getRangeAt(0).cloneRange() - # @$writing.text @$writing.text() - # setTimeout => - # s = window.getSelection() - # s.removeAllRanges() - # s.addRange r - # console.log r - # ,0 - - onKeyDown: (e) -> - if e.keyCode is 13 - txt = @$writing.text() - e.preventDefault() - if txt.length > 0 - if window.talk.online - @sendMessage() - else - #@errHue = ((@errHue || 0) + (Math.random() * 300) + 30) % 360 - #$('#offline').css color: husl.toHex @errHue, 90, 50 - $('#offline').addClass('error').one 'transitionend', - -> $('#offline').removeClass 'error' - return false - @onInput() - @set() - - onInput: (e) -> - text = @$writing.text() - length = text.length - # geturl = new RegExp [ - # '(^|[ \t\r\n])((ftp|http|https|gopher|mailto|' - # 'news|nntp|telnet|wais|file|prospero|aim|webcal' - # '):(([A-Za-z0-9$_.+!*(),;/?:@&~=-])|%[A-Fa-f0-9]{2}){2,}' - # '(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*(),;/?:@&~=%-]*))?' - # '([A-Za-z0-9$_+!*();/?:~-]))' - # ].join() , "g" - # urls = text.match(geturl) - # if urls isnt null and urls.length > 0 - # for url in urls - # length -= url.length - # length += 10 - @setState {length} - - _validateAudiPart: (a) -> - a = a.trim() - # if a[0] isnt "~" - # return false - if a.indexOf("/") isnt -1 - _a = a.split("/") - if _a[1].length is 0 - return false - ship = _a[0] - else - ship = a - - return (SHIPSHAPE.test ship) and - _.all (ship.match /[a-z]{3}/g), (a)-> -1 isnt PO.indexOf a - - _validateAudi: -> - v = $('#audi').text() - v = v.trim() - if v.length is 0 - return true - if v.length < 5 # zod/a is shortest - return false - _.all (v.split /\ +/), @_validateAudiPart - - _setAudi: -> - valid = @_validateAudi() - StationActions.setValidAudience valid - if valid is true - stan = $('#audi').text() || window.util.mainStationPath window.urb.user - stan = (stan.split /\ +/).map (v)-> - if v[0] is "~" then v else "~"+v - StationActions.setAudience stan - stan - else - false - - getTime: -> - d = new Date() - seconds = d.getSeconds() - if seconds < 10 - seconds = "0" + seconds - "~"+d.getHours() + "." + d.getMinutes() + "." + seconds - - cursorAtEnd: -> - range = document.createRange() - range.selectNodeContents @$writing[0] - range.collapse(false) - selection = window.getSelection() - selection.removeAllRanges() - selection.addRange(range) - - componentDidMount: -> - window.util.sendMessage = @sendMessage - StationStore.addChangeListener @_onChangeStore - MessageStore.addChangeListener @_onChangeStore - @$el = $ @getDOMNode() - @$writing = $('#writing') - @$writing.focus() - if @get() - @$writing.text @get() - @onInput() - @interval = setInterval => - @$el.find('.time').text @getTime() - , 1000 - - componentWillUnmount: -> - StationStore.removeChangeListener @_onChangeStore - clearInterval @interval - - _onChangeStore: -> @setState @stateFromStore() - - render: -> - # if window.urb.user isnt window.urb.ship #foreign - # return div {className:"writing"} - - user = "~"+window.urb.user - iden = StationStore.getMember(user) - ship = if iden then iden.ship else user - name = if iden then iden.name else "" - - audi = if @state.audi.length is 0 then @state.ludi else @state.audi - audi = window.util.clipAudi audi - for k,v of audi - audi[k] = v.slice(1) - - k = "writing" - - div {className:k}, [ - (div {className:"attr"}, [ - (React.createElement Member, iden) - (React.createElement Audience, {audi,valid:@state.valid, onBlur:@_setAudi}) - (div {className:"time"}, @getTime()) - ]) - (div { - id:"writing" - contentEditable:true - onPaste: @onInput - @onInput, @onFocus, @onBlur, @onKeyDown, @onKeyUp - }, "") - (div {id:"length"}, "#{@state.length}/64 (#{Math.ceil @state.length / 64})") - ] diff --git a/pub/talk/src/js/dep/director.js b/pub/talk/src/js/dep/director.js deleted file mode 100644 index c956af400..000000000 --- a/pub/talk/src/js/dep/director.js +++ /dev/null @@ -1,7 +0,0 @@ - - -// -// Generated on Tue Dec 16 2014 12:13:47 GMT+0100 (CET) by Charlie Robbins, Paolo Fragomeni & the Contributors (Using Codesurgeon). -// Version 1.2.6 -// -(function(a){function k(a,b,c,d){var e=0,f=0,g=0,c=(c||"(").toString(),d=(d||")").toString(),h;for(h=0;hi.indexOf(d,e)||~i.indexOf(c,e)&&!~i.indexOf(d,e)||!~i.indexOf(c,e)&&~i.indexOf(d,e)){f=i.indexOf(c,e),g=i.indexOf(d,e);if(~f&&!~g||!~f&&~g){var j=a.slice(0,(h||1)+1).join(b);a=[j].concat(a.slice((h||1)+1))}e=(g>f?g:f)+1,h=0}else e=0}return a}function j(a,b){var c,d=0,e="";while(c=a.substr(d).match(/[^\w\d\- %@&]*\*[^\w\d\- %@&]*/))d=c.index+c[0].length,c[0]=c[0].replace(/^\*/,"([_.()!\\ %@&a-zA-Z0-9-]+)"),e+=a.substr(0,c.index)+c[0];a=e+=a.substr(d);var f=a.match(/:([^\/]+)/ig),g,h;if(f){h=f.length;for(var j=0;j7))this.history===!0?setTimeout(function(){window.onpopstate=d},500):window.onhashchange=d,this.mode="modern";else{var f=document.createElement("iframe");f.id="state-frame",f.style.display="none",document.body.appendChild(f),this.writeFrame(""),"onpropertychange"in document&&"attachEvent"in document&&document.attachEvent("onpropertychange",function(){event.propertyName==="location"&&c.check()}),window.setInterval(function(){c.check()},50),this.onHashChanged=d,this.mode="legacy"}e.listeners.push(a);return this.mode},destroy:function(a){if(!!e&&!!e.listeners){var b=e.listeners;for(var c=b.length-1;c>=0;c--)b[c]===a&&b.splice(c,1)}},setHash:function(a){this.mode==="legacy"&&this.writeFrame(a),this.history===!0?(window.history.pushState({},document.title,a),this.fire()):b.hash=a[0]==="/"?a:"/"+a;return this},writeFrame:function(a){var b=document.getElementById("state-frame"),c=b.contentDocument||b.contentWindow.document;c.open(),c.write("