message splitting

This commit is contained in:
Anton Dyudin 2015-10-27 16:43:08 -07:00
parent c43e311674
commit e7ab4f7c7d
6 changed files with 205 additions and 139 deletions

View File

@ -27,6 +27,13 @@
^- (unit (list ,_[(wonk *fel) (need *wit)]))
(zl (turn (~(tap by a)) (head-rush fel)))
::
++ ke :: callbacks
|* [gar=* sef=_|.(fist)]
|= jon=json
^- (unit ,_gar)
=- ~! gar ~! (need -) -
((sef) jon)
::
++ as :: array as set
:: |*(a=fist (cu sa (ar a))) :: XX types
|* a=fist
@ -69,20 +76,31 @@
%+ sear (soft passport)
;~((glue fas) sym urs:ab) :: XX [a-z0-9_]{1,15}
::
++ speeech ?(speech [%eval p=@t] [%mor p=(list speeech)])
++ eval
|= a=(trel ,@da bouquet ?(speech [%eval p=@t])) ^- statement
?. ?=(%eval -.r.a) a
=+ pax=[&1:% &2:% (scot %da p.a) |3:%]
=- a(r [%fat tank/- %exp p.r.a])
p:(mule |.([(sell (slap !>(..zuse) (rain pax p.r.a)))]~))
|= a=(trel ,@da bouquet speeech) ^- statement
%= a r ^- speech
|-
?: ?=(%mor -.r.a)
[%mor (turn p.r.a |=(b=speeech ^$(r.a b)))]
?. ?=(%eval -.r.a) r.a
=- [%fat tank/- %exp p.r.a]
=+ pax=[&1:% &2:% (scot %da p.a) |3:%]
p:(mule |.([(sell (slap !>(..zuse) (rain pax p.r.a)))]~))
==
::
++ stam
^- $+(json (unit statement))
%+ cu eval
=- (ot date/di bouquet/(as (ar so)) speech/(of -) ~)
(ot date/di bouquet/(as (ar so)) speech/spec ~)
::
++ spec
%+ ke *speeech |.
%- of
:~ lin/(ot say/bo txt/so ~)
url/(su aurf:urlp)
eval/so
mor/(ar spec)
:: exp/(cu |=(a=cord [a ~]) so)
:: inv/(ot ship/(su fed:ag) party/(su urs:ab) ~)
==

View File

@ -95,6 +95,7 @@
%tax (joba txt/(jape (rend-work-duty p.a)))
%app (jobe txt/[%s q.a] src/[%s p.a] ~)
%fat (jobe tor/(tors p.a) taf/$(a q.a) ~)
%mor a/(turn p.a spec)
:: %inv (jobe ship/(jope p.a) party/[%s q.a] ~)
==
::

View File

@ -56,17 +56,30 @@ module.exports =
else if window.urb.util.isURL(message)
speech = url: message
_message =
ship:window.urb.ship
thought:
serial:serial
audience:_audi
statement:
bouquet:[]
speech:speech
date: Date.now()
MessageDispatcher.handleViewAction
type:"message-send"
message:_message
window.talk.MessagePersistence.sendMessage _message.thought
speeches =
if speech.lin?.txt.length < 64
[speech]
else
{say,txt} = speech.lin
txt.match(/(.{0,64} |.{64}|.+$)/g).map (s)->
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()
MessageDispatcher.handleViewAction
type:"message-send"
message:_message
window.talk.MessagePersistence.sendMessage _message.thought

View File

@ -29,6 +29,15 @@ Message = recl
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 = if @props.pending isnt "received" then "pending" else ""
delivery = _.uniq _.pluck @props.thought.audience, "delivery"
@ -50,14 +59,8 @@ Message = recl
type = ['private','public']
type = type[Number(aude.indexOf(window.util.mainStationPath(window.urb.user)) is -1)]
mess = 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)
else "Unknown speech type:" + (" %"+x for x of speech).join ''
mess = @renderSpeech speech
klass += switch
when speech.app? then " say"

View File

@ -70,6 +70,7 @@ Audience = recl
}, @props.audi.join(" ")
module.exports = recl
displayName: "Writing"
set: ->
if window.localStorage and @$writing then window.localStorage.setItem 'writing', @$writing.text()
@ -124,7 +125,8 @@ module.exports = recl
else
audi = @state.audi
audi = @addCC audi
MessageActions.sendMessage @$writing.text().trim(),audi
txt = @$writing.text().trim().replace(/\xa0/g,' ')
MessageActions.sendMessage txt,audi
@$writing.text('')
@setState length:0
@set()
@ -141,13 +143,12 @@ module.exports = recl
# s.addRange r
# console.log r
# ,0
onKeyDown: (e) ->
if e.keyCode is 13
txt = @$writing.text()
e.preventDefault()
if ( (txt.length > 0 and txt.length < 63) or
window.urb.util.isURL @$writing.text() )
if txt.length > 0
@sendMessage()
return false
@onInput()
@ -266,5 +267,5 @@ module.exports = recl
onPaste: @onInput
@onInput, @onFocus, @onBlur, @onKeyDown, @onKeyUp
}, "")
(div {id:"length",className:("valid-false" if @state.lengthy)}, "#{@state.length}/62")
(div {id:"length"}, "#{@state.length}/64 (#{Math.ceil @state.length / 64})")
]

View File

@ -37,7 +37,7 @@ module.exports = {
return window.talk.MessagePersistence.get(station, start, end);
},
sendMessage: function(message, audience) {
var _audi, _message, k, serial, speech, v;
var _audi, _message, i, k, len, ref, ref1, results, say, serial, speech, speeches, txt, v;
serial = window.util.uuid32();
audience = _.uniq(audience);
_audi = {};
@ -69,23 +69,36 @@ module.exports = {
url: message
};
}
_message = {
ship: window.urb.ship,
thought: {
serial: serial,
audience: _audi,
statement: {
bouquet: [],
speech: speech,
date: Date.now()
speeches = ((ref = speech.lin) != null ? ref.txt.length : void 0) < 64 ? [speech] : ((ref1 = speech.lin, say = ref1.say, txt = ref1.txt, ref1), txt.match(/(.{0,64} |.{64}|.+$)/g).map(function(s) {
return {
lin: {
say: say,
txt: s.slice(-1 !== " ") ? s : s.slice(0, -1)
}
}
};
MessageDispatcher.handleViewAction({
type: "message-send",
message: _message
});
return window.talk.MessagePersistence.sendMessage(_message.thought);
};
}));
results = [];
for (i = 0, len = speeches.length; i < len; i++) {
speech = speeches[i];
_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
});
results.push(window.talk.MessagePersistence.sendMessage(_message.thought));
}
return results;
}
};
@ -261,8 +274,31 @@ Message = recl({
}
return this.props._handlePm(user);
},
renderSpeech: function(speech) {
var con, x;
switch (false) {
case !((con = speech.lin) || (con = speech.app) || (con = speech.exp) || (con = speech.tax)):
return con.txt;
case !(con = speech.url):
return a({
href: con.txt,
target: "_blank"
}, con.txt);
case !(con = speech.mor):
return con.map(this.renderSpeech);
default:
return "Unknown speech type:" + ((function() {
var results;
results = [];
for (x in speech) {
results.push(" %" + x);
}
return results;
})()).join('');
}
},
render: function() {
var attachments, aude, audi, con, delivery, klass, mess, name, ref1, speech, type, x;
var attachments, aude, audi, delivery, klass, mess, name, ref1, speech, type;
delivery = _.uniq(_.pluck(this.props.thought.audience, "delivery"));
klass = delivery.indexOf("received") !== -1 ? " received" : " pending";
speech = this.props.thought.statement.speech;
@ -295,26 +331,7 @@ Message = recl({
});
type = ['private', 'public'];
type = type[Number(aude.indexOf(window.util.mainStationPath(window.urb.user)) === -1)];
mess = (function() {
switch (false) {
case !((con = speech.lin) || (con = speech.app) || (con = speech.exp) || (con = speech.tax)):
return con.txt;
case !(con = speech.url):
return a({
href: con.txt,
target: "_blank"
}, con.txt);
default:
return "Unknown speech type:" + ((function() {
var results;
results = [];
for (x in speech) {
results.push(" %" + x);
}
return results;
})()).join('');
}
})();
mess = this.renderSpeech(speech);
klass += (function() {
switch (false) {
case speech.app == null:
@ -696,7 +713,7 @@ module.exports = recl({
},{"../actions/StationActions.coffee":2,"../stores/StationStore.coffee":20,"./MemberComponent.coffee":3}],6:[function(require,module,exports){
var Member, MessageActions, MessageStore, StationActions, StationStore, br, div, input, recl, ref, textarea;
var Audience, Member, MessageActions, MessageStore, PO, SHIPSHAPE, StationActions, StationStore, br, div, input, recl, ref, textarea;
recl = React.createClass;
@ -712,7 +729,34 @@ StationStore = require('../stores/StationStore.coffee');
Member = require('./MemberComponent.coffee');
SHIPSHAPE = /^~?([a-z]{3}|[a-z]{6}(-[a-z]{6}){0,3}|[a-z]{6}(-[a-z]{6}){3}(--[a-z]{6}(-[a-z]{6}){3})+)$/;
PO = 'dozmarbinwansamlitsighidfidlissogdirwacsabwissib\nrigsoldopmodfoglidhopdardorlorhodfolrintogsilmir\nholpaslacrovlivdalsatlibtabhanticpidtorbolfosdot\nlosdilforpilramtirwintadbicdifrocwidbisdasmidlop\nrilnardapmolsanlocnovsitnidtipsicropwitnatpanmin\nritpodmottamtolsavposnapnopsomfinfonbanporworsip\nronnorbotwicsocwatdolmagpicdavbidbaltimtasmallig\nsivtagpadsaldivdactansidfabtarmonranniswolmispal\nlasdismaprabtobrollatlonnodnavfignomnibpagsopral\nbilhaddocridmocpacravripfaltodtiltinhapmicfanpat\ntaclabmogsimsonpinlomrictapfirhasbosbatpochactid\nhavsaplindibhosdabbitbarracparloddosbortochilmac\ntomdigfilfasmithobharmighinradmashalraglagfadtop\nmophabnilnosmilfopfamdatnoldinhatnacrisfotribhoc\nnimlarfitwalrapsarnalmoslandondanladdovrivbacpol\nlaptalpitnambonrostonfodponsovnocsorlavmatmipfap\n\nzodnecbudwessevpersutletfulpensytdurwepserwylsun\nrypsyxdyrnuphebpeglupdepdysputlughecryttyvsydnex\nlunmeplutseppesdelsulpedtemledtulmetwenbynhexfeb\npyldulhetmevruttylwydtepbesdexsefwycburderneppur\nrysrebdennutsubpetrulsynregtydsupsemwynrecmegnet\nsecmulnymtevwebsummutnyxrextebfushepbenmuswyxsym\nselrucdecwexsyrwetdylmynmesdetbetbeltuxtugmyrpel\nsyptermebsetdutdegtexsurfeltudnuxruxrenwytnubmed\nlytdusnebrumtynseglyxpunresredfunrevrefmectedrus\nbexlebduxrynnumpyxrygryxfeptyrtustyclegnemfermer\ntenlusnussyltecmexpubrymtucfyllepdebbermughuttun\nbylsudpemdevlurdefbusbeprunmelpexdytbyttyplevmyl\nwedducfurfexnulluclennerlexrupnedlecrydlydfenwel\nnydhusrelrudneshesfetdesretdunlernyrsebhulryllud\nremlysfynwerrycsugnysnyllyndyndemluxfedsedbecmun\nlyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes';
Audience = recl({
displayName: "Audience",
onKeyDown: function(e) {
if (e.keyCode === 13) {
e.preventDefault();
setTimeout(function() {
return $('#writing').focus();
}, 0);
return false;
}
},
render: function() {
return div({
id: "audi",
className: "audi valid-" + this.props.valid,
contentEditable: true,
onKeyDown: this.onKeyDown,
onBlur: this.props.onBlur
}, this.props.audi.join(" "));
}
});
module.exports = recl({
displayName: "Writing",
set: function() {
if (window.localStorage && this.$writing) {
return window.localStorage.setItem('writing', this.$writing.text());
@ -738,21 +782,25 @@ module.exports = recl({
return s;
},
getInitialState: function() {
return this.stateFromStore();
return _.extend(this.stateFromStore(), {
length: 0,
lengthy: false
});
},
typing: function(state) {
if (this.state.typing[this.state.station] !== state) {
return StationActions.setTyping(this.state.station, state);
}
},
_blur: function() {
onBlur: function() {
this.$writing.text(this.$writing.text());
MessageActions.setTyping(false);
return this.typing(false);
},
_focus: function() {
onFocus: function() {
MessageActions.setTyping(true);
return this.typing(true);
this.typing(true);
return this.cursorAtEnd;
},
addCC: function(audi) {
var cc, i, len, listening, s;
@ -773,7 +821,7 @@ module.exports = recl({
return audi;
},
sendMessage: function() {
var audi;
var audi, txt;
if (this._validateAudi() === false) {
$('#audi').focus();
return;
@ -784,50 +832,46 @@ module.exports = recl({
audi = this.state.audi;
}
audi = this.addCC(audi);
MessageActions.sendMessage(this.$writing.text().trim(), audi);
this.$length.text("0/62");
txt = this.$writing.text().trim().replace(/\xa0/g, ' ');
MessageActions.sendMessage(txt, audi);
this.$writing.text('');
this.setState({
length: 0
});
this.set();
return this.typing(false);
},
_audiKeyDown: function(e) {
if (e.keyCode === 13) {
e.preventDefault();
setTimeout(function() {
return $('#writing').focus();
}, 0);
return false;
}
},
_writingKeyUp: function(e) {
onKeyUp: function(e) {
if (!window.urb.util.isURL(this.$writing.text())) {
return this.$length.toggleClass('valid-false', this.$writing.text().length > 62);
return this.setState({
lengthy: this.$writing.text().length > 62
});
}
},
_writingKeyDown: function(e) {
onKeyDown: function(e) {
var txt;
if (e.keyCode === 13) {
txt = this.$writing.text();
e.preventDefault();
if ((txt.length > 0 && txt.length < 63) || window.urb.util.isURL(this.$writing.text())) {
if (txt.length > 0) {
this.sendMessage();
}
return false;
}
this._input();
this.onInput();
return this.set();
},
_input: function(e) {
onInput: function(e) {
var length, text;
text = this.$writing.text();
length = text.length;
return this.$length.text(length + "/62");
},
_setFocus: function() {
return this.$writing.focus();
return this.setState({
length: length
});
},
_validateAudiPart: function(a) {
var _a, ship;
a = a.trim();
if (a.indexOf("/") !== -1) {
_a = a.split("/");
if (_a[1].length === 0) {
@ -837,13 +881,12 @@ module.exports = recl({
} else {
ship = a;
}
if (ship.length < 3) {
return false;
}
return true;
return (SHIPSHAPE.test(ship)) && _.all(ship.match(/[a-z]{3}/g), function(a) {
return -1 !== PO.indexOf(a);
});
},
_validateAudi: function() {
var a, i, len, v, valid;
var v;
v = $('#audi').text();
v = v.trim();
if (v.length === 0) {
@ -852,32 +895,23 @@ module.exports = recl({
if (v.length < 5) {
return false;
}
v = v.split(" ");
for (i = 0, len = v.length; i < len; i++) {
a = v[i];
a = a.trim();
valid = this._validateAudiPart(a);
}
return valid;
return _.all(v.split(/\ +/), this._validateAudiPart);
},
_setAudi: function() {
var _v, k, v, valid;
var stan, valid;
valid = this._validateAudi();
StationActions.setValidAudience(valid);
if (valid === true) {
v = $('#audi').text();
if (v.length === 0) {
v = window.util.mainStationPath(window.urb.user);
}
v = v.split(" ");
for (k in v) {
_v = v[k];
if (_v[0] !== "~") {
v[k] = "~" + _v;
stan = $('#audi').text() || window.util.mainStationPath(window.urb.user);
stan = (stan.split(/\ +/)).map(function(v) {
if (v[0] === "~") {
return v;
} else {
return "~" + v;
}
}
StationActions.setAudience(v);
return v;
});
StationActions.setAudience(stan);
return stan;
} else {
return false;
}
@ -905,12 +939,11 @@ module.exports = recl({
StationStore.addChangeListener(this._onChangeStore);
MessageStore.addChangeListener(this._onChangeStore);
this.$el = $(this.getDOMNode());
this.$length = $('#length');
this.$writing = $('#writing');
this.$writing.focus();
if (this.get()) {
this.$writing.text(this.get());
this._input();
this.onInput();
}
return this.interval = setInterval((function(_this) {
return function() {
@ -944,28 +977,25 @@ module.exports = recl({
div({
className: "attr"
}, [
React.createElement(Member, iden), div({
id: "audi",
className: "audi valid-" + this.state.valid,
contentEditable: true,
onKeyDown: this._audiKeyDown,
React.createElement(Member, iden), React.createElement(Audience, {
audi: audi,
valid: this.state.valid,
onBlur: this._setAudi
}, audi.join(" ")), div({
}), div({
className: "time"
}, this.getTime())
]), div({
id: "writing",
contentEditable: true,
onFocus: this._focus,
onBlur: this._blur,
onInput: this._input,
onPaste: this._input,
onKeyDown: this._writingKeyDown,
onKeyUp: this._writingKeyUp,
onFocus: this.cursorAtEnd
onPaste: this.onInput,
onInput: this.onInput,
onFocus: this.onFocus,
onBlur: this.onBlur,
onKeyDown: this.onKeyDown,
onKeyUp: this.onKeyUp
}, ""), div({
id: "length"
}, "0/62")
}, this.state.length + "/64 (" + (Math.ceil(this.state.length / 64)) + ")")
]);
}
});