Merge branch 'chat-history' (#1948)

* chat-history:
  chat: added temporary chat-two-update mark with new %messages type
  chat: oust correctness fix and js style fix
  chat-store: factored out functions used in both message and messages
  chat: style fixes
  chat: fixes to cli parser and increased page size in hook
  chat-js: updated to support %messages events
  sur: added rw-security to replace chat-security
  chat: add history functionality. optionally request backlog.

Signed-off-by: Jared Tobin <jared@tlon.io>
This commit is contained in:
Jared Tobin 2019-11-19 10:47:40 +08:00
commit 053c784de6
No known key found for this signature in database
GPG Key ID: B77DC7C964AAD99A
21 changed files with 388 additions and 129 deletions

View File

@ -39,12 +39,14 @@
[%say letter] :: send message [%say letter] :: send message
[%eval cord hoon] :: send #-message [%eval cord hoon] :: send #-message
:: ::
[%create chat-security path (unit glyph)] :: create chat ::
:: create chat
[%create rw-security path (unit glyph) (unit ?)]
[%delete path] :: delete chat [%delete path] :: delete chat
[%invite ?(%r %w %rw) path (set ship)] :: allow [%invite ?(%r %w %rw) path (set ship)] :: allow
[%banish ?(%r %w %rw) path (set ship)] :: disallow [%banish ?(%r %w %rw) path (set ship)] :: disallow
:: ::
[%join target (unit glyph)] :: join target [%join target (unit glyph) (unit ?)] :: join target
[%leave target] :: nuke target [%leave target] :: nuke target
:: ::
[%bind glyph target] :: bind glyph [%bind glyph target] :: bind glyph
@ -178,6 +180,11 @@
:- [prompt:sh-out ~] :- [prompt:sh-out ~]
:: start with fresh sole state :: start with fresh sole state
this(state.cli *sole-share:sole-sur) this(state.cli *sole-share:sole-sur)
::
++ diff-chat-two-update
|= [=wire upd=chat-two-update]
^- (quip move _this)
(read-envelopes (path-to-target path.upd) envelopes.upd)
:: +diff-chat-update: get new mailboxes & messages :: +diff-chat-update: get new mailboxes & messages
:: ::
++ diff-chat-update ++ diff-chat-update
@ -364,13 +371,24 @@
;~ (glue ace) ;~ (glue ace)
(tag %create) (tag %create)
security security
;~(plug path (punt ;~(pfix ace glyph))) ;~ plug
path
(punt ;~(pfix ace glyph))
(punt ;~(pfix ace (fuss 'y' 'n')))
==
== ==
;~((glue ace) (tag %delete) path) ;~((glue ace) (tag %delete) path)
;~((glue ace) (tag %invite) rw path ships) ;~((glue ace) (tag %invite) rw path ships)
;~((glue ace) (tag %banish) rw path ships) ;~((glue ace) (tag %banish) rw path ships)
:: ::
;~((glue ace) (tag %join) ;~(plug targ (punt ;~(pfix ace glyph)))) ;~ (glue ace)
(tag %join)
;~ plug
targ
(punt ;~(pfix ace glyph))
(punt ;~(pfix ace (fuss 'y' 'n')))
==
==
;~((glue ace) (tag %leave) targ) ;~((glue ace) (tag %leave) targ)
:: ::
;~((glue ace) (tag %bind) glyph targ) ;~((glue ace) (tag %bind) glyph targ)
@ -625,7 +643,7 @@
:: +create: new local mailbox :: +create: new local mailbox
:: ::
++ create ++ create
|= [security=chat-security =path gyf=(unit char)] |= [security=rw-security =path gyf=(unit char) allow-history=(unit ?)]
^- (quip move _this) ^- (quip move _this)
::TODO check if already exists ::TODO check if already exists
=/ =target [our-self path] =/ =target [our-self path]
@ -636,18 +654,22 @@
=- [[- moz] this] =- [[- moz] this]
%^ act %do-create %chat-view %^ act %do-create %chat-view
:- %chat-view-action :- %chat-view-action
:^ %create path security :* %create
:: ensure we can read from/write to our own chats path
:: security
:- :: read :: ensure we can read from/write to our own chats
::
:: read
?- security ?- security
?(%channel %journal) ~ ?(%channel %journal) ~
?(%village %mailbox) [our-self ~ ~] ?(%village %mailbox) [our-self ~ ~]
== ==
:: write :: write
?- security ?- security
?(%channel %mailbox) ~ ?(%channel %mailbox) ~
?(%village %journal) [our-self ~ ~] ?(%village %journal) [our-self ~ ~]
==
(fall allow-history %.y)
== ==
:: +delete: delete local chats :: +delete: delete local chats
:: ::
@ -708,7 +730,7 @@
:: +join: sync with remote mailbox :: +join: sync with remote mailbox
:: ::
++ join ++ join
|= [=target gyf=(unit char)] |= [=target gyf=(unit char) ask-history=(unit ?)]
^- (quip move _this) ^- (quip move _this)
=^ moz this =^ moz this
?. ?=(^ gyf) [~ this] ?. ?=(^ gyf) [~ this]
@ -720,7 +742,7 @@
:: gives ugly %chat-hook-reap :: gives ugly %chat-hook-reap
%^ act %do-join %chat-view %^ act %do-join %chat-view
:- %chat-view-action :- %chat-view-action
[%join target] [%join ship.target path.target (fall ask-history %.y)]
:: +leave: unsync & destroy mailbox :: +leave: unsync & destroy mailbox
:: ::
::TODO allow us to "mute" local chats using this ::TODO allow us to "mute" local chats using this

View File

@ -8,16 +8,17 @@
+$ move [bone card] +$ move [bone card]
:: ::
+$ card +$ card
$% [%diff [%chat-update chat-update]] $% [%diff diff]
[%quit ~] [%quit ~]
[%poke wire dock poke] [%poke wire dock poke]
[%pull wire dock ~] [%pull wire dock ~]
[%peer wire dock path] [%peer wire dock path]
== ==
:: ::
+$ state-both +$ versioned-state
$% state-zero $% state-zero
state-one state-one
state-two
== ==
:: ::
+$ state-zero +$ state-zero
@ -33,6 +34,14 @@
invite-created=_| invite-created=_|
== ==
:: ::
+$ state-two
$: %2
synced=(map path ship)
boned=(map wire (list bone))
invite-created=_|
allow-history=(map path ?)
==
::
+$ poke +$ poke
$% [%chat-action chat-action] $% [%chat-action chat-action]
[%permission-action permission-action] [%permission-action permission-action]
@ -40,15 +49,19 @@
[%chat-view-action chat-view-action] [%chat-view-action chat-view-action]
== ==
:: ::
+$ diff
$% [%chat-update chat-update]
[%chat-two-update chat-two-update]
==
-- --
:: ::
|_ [bol=bowl:gall state-one] |_ [bol=bowl:gall state-two]
:: ::
++ this . ++ this .
:: ::
++ prep ++ prep
|= old=(unit state-both) |= old=(unit versioned-state)
^- (quip move _this) |^ ^- (quip move _this)
?~ old ?~ old
:_ this(invite-created %.y) :_ this(invite-created %.y)
:~ (invite-poke [%create /chat]) :~ (invite-poke [%create /chat])
@ -56,19 +69,32 @@
[ost.bol %peer /permissions [our.bol %permission-store] /updates] [ost.bol %peer /permissions [our.bol %permission-store] /updates]
== ==
?- -.u.old ?- -.u.old
%1 [~ this(+<+ u.old)] %2 [~ this(+<+ u.old)]
%1 [~ (migrate-state synced.u.old boned.u.old)]
:: ::
%0 %0
=/ sta *state-one :_ (migrate-state synced.u.old boned.u.old)
=: boned.sta boned.u.old
synced.sta synced.u.old
invite-created %.y
==
:_ this(+<+ sta)
:~ (invite-poke [%create /chat]) :~ (invite-poke [%create /chat])
[ost.bol %peer /invites [our.bol %invite-store] /invitatory/chat] [ost.bol %peer /invites [our.bol %invite-store] /invitatory/chat]
== ==
== ==
::
++ migrate-state
|= [synced=(map path ship) boned=(map wire (list bone))]
^- _this
=/ sta *state-two
=: boned.sta boned
synced.sta synced
allow-history.sta (create-allow-history synced)
invite-created %.y
==
this(+<+ sta)
::
++ create-allow-history
|= synced=(map path ship)
^- (map path ?)
(~(run by synced) |=(* %.n))
--
:: ::
++ poke-json ++ poke-json
|= jon=json |= jon=json
@ -110,7 +136,9 @@
=/ chat-path [%mailbox path.act] =/ chat-path [%mailbox path.act]
?: (~(has by synced) path.act) ?: (~(has by synced) path.act)
[~ this] [~ this]
=. synced (~(put by synced) path.act our.bol) =: synced (~(put by synced) path.act our.bol)
allow-history (~(put by allow-history) path.act allow-history.act)
==
:_ (track-bone chat-path) :_ (track-bone chat-path)
%+ weld %+ weld
[ost.bol %peer chat-path [our.bol %chat-store] chat-path]~ [ost.bol %peer chat-path [our.bol %chat-store] chat-path]~
@ -118,12 +146,13 @@
:: ::
%add-synced %add-synced
?> (team:title our.bol src.bol) ?> (team:title our.bol src.bol)
=/ chat-path [%mailbox (scot %p ship.act) path.act] =/ chat-path=path [%mailbox (scot %p ship.act) path.act]
?: (~(has by synced) [(scot %p ship.act) path.act]) ?: (~(has by synced) [(scot %p ship.act) path.act])
[~ this] [~ this]
=. synced (~(put by synced) [(scot %p ship.act) path.act] ship.act) =. synced (~(put by synced) [(scot %p ship.act) path.act] ship.act)
=/ history=path ?:(ask-history.act /0 /~)
:_ (track-bone chat-path) :_ (track-bone chat-path)
[ost.bol %peer chat-path [ship.act %chat-hook] chat-path]~ [ost.bol %peer chat-path [ship.act %chat-hook] (weld chat-path history)]~
:: ::
%remove %remove
=/ ship (~(get by synced) path.act) =/ ship (~(get by synced) path.act)
@ -157,6 +186,13 @@
++ peer-mailbox ++ peer-mailbox
|= pax=path |= pax=path
^- (quip move _this) ^- (quip move _this)
?> ?=(^ pax)
=/ last (dec (lent pax))
=/ backlog-start=(unit @ud)
%+ rush
(snag last `(list @ta)`pax)
dem:ag
=> .(pax `path`(oust [last 1] `(list @ta)`pax))
?> ?=([* ^] pax) ?> ?=([* ^] pax)
?> (~(has by synced) pax) ?> (~(has by synced) pax)
:: scry permissions to check if read is permitted :: scry permissions to check if read is permitted
@ -164,7 +200,43 @@
=/ box (chat-scry pax) =/ box (chat-scry pax)
?~ box !! ?~ box !!
:_ this :_ this
[ost.bol %diff %chat-update [%create (slav %p i.pax) pax]]~ :- [ost.bol %diff %chat-update [%create (slav %p i.pax) pax]]
?: ?&(?=(^ backlog-start) (~(got by allow-history) pax))
(paginate-messages pax u.box u.backlog-start)
~
::
++ paginate-messages
|= [=path =mailbox start=@ud]
^- (list move)
=/ moves=(list move) ~
=/ end (lent envelopes.mailbox)
?: |((gte start end) =(end 0))
moves
=. envelopes.mailbox (slag start `(list envelope)`envelopes.mailbox)
|- ^- (list move)
?~ envelopes.mailbox
moves
?: (lte end 5.000)
=. moves
%+ snoc moves
%- messages-move
[path start (lent envelopes.mailbox) envelopes.mailbox]
$(envelopes.mailbox ~)
=. moves
%+ snoc moves
%- messages-move
:^ path start
(add start 5.000)
(scag 5.000 `(list envelope)`envelopes.mailbox)
=: start (add start 5.000)
end (sub end 5.000)
==
$(envelopes.mailbox (slag 5.000 `(list envelope)`envelopes.mailbox))
::
++ messages-move
|= [=path start=@ud end=@ud envelopes=(list envelope)]
^- move
[ost.bol %diff %chat-two-update [%messages path start end envelopes]]
:: ::
++ diff-invite-update ++ diff-invite-update
|= [wir=wire diff=invite-update] |= [wir=wire diff=invite-update]
@ -173,8 +245,12 @@
[~ this] [~ this]
:: ::
%accepted %accepted
=/ ask-history
?~ (chat-scry [(scot %p ship.invite.diff) path.invite.diff])
%.y
%.n
:_ this :_ this
[(chat-view-poke [%join ship.invite.diff path.invite.diff])]~ [(chat-view-poke [%join ship.invite.diff path.invite.diff ask-history])]~
== ==
:: ::
++ diff-permission-update ++ diff-permission-update
@ -211,6 +287,24 @@
=/ bne (~(get by sup) [check-ship [%mailbox mail-path]]) =/ bne (~(get by sup) [check-ship [%mailbox mail-path]])
?~(bne ~ [u.bne %quit ~]~) ?~(bne ~ [u.bne %quit ~]~)
:: ::
++ diff-chat-two-update
|= [wir=wire diff=chat-two-update]
^- (quip move _this)
:: local
?: (team:title our.bol src.bol)
:_ this
%+ turn (prey:pubsub:userlib [%mailbox path.diff] bol)
|= [=bone *]
^- move
[bone %diff [%chat-two-update diff]]
:: foreign
:_ this
?> ?=([* ^] path.diff)
=/ shp (~(get by synced) path.diff)
?~ shp ~
?. =(src.bol u.shp) ~
[(chat-poke [%messages path.diff envelopes.diff])]~
::
++ diff-chat-update ++ diff-chat-update
|= [wir=wire diff=chat-update] |= [wir=wire diff=chat-update]
^- (quip move _this) ^- (quip move _this)
@ -222,10 +316,10 @@
|= diff=chat-update |= diff=chat-update
^- (quip move _this) ^- (quip move _this)
?- -.diff ?- -.diff
%keys [~ this] %keys [~ this]
%config [~ this] %config [~ this]
%create [~ this] %create [~ this]
%read [~ this] %read [~ this]
%delete %delete
?. (~(has by synced) path.diff) ?. (~(has by synced) path.diff)
[~ this] [~ this]
@ -263,7 +357,7 @@
?. =(u.shp src.bol) ?. =(u.shp src.bol)
[~ this] [~ this]
:_ this(synced (~(del by synced) path.diff)) :_ this(synced (~(del by synced) path.diff))
:- (chat-poke diff) :- (chat-poke [%delete path.diff])
[ost.bol %pull [%mailbox path.diff] [src.bol %chat-hook] ~]~ [ost.bol %pull [%mailbox path.diff] [src.bol %chat-hook] ~]~
:: ::
%message %message
@ -272,7 +366,7 @@
=/ shp (~(get by synced) path.diff) =/ shp (~(get by synced) path.diff)
?~ shp ~ ?~ shp ~
?. =(src.bol u.shp) ~ ?. =(src.bol u.shp) ~
[(chat-poke diff)]~ [(chat-poke [%message path.diff envelope.diff])]~
== ==
:: ::
++ quit ++ quit
@ -286,9 +380,13 @@
?. (~(has by synced) t.wir) ?. (~(has by synced) t.wir)
:: no-op :: no-op
[~ this] [~ this]
=/ mailbox (chat-scry t.wir)
?~ mailbox [~ this]
~& %chat-hook-resubscribe ~& %chat-hook-resubscribe
=/ pax=path (weld wir /(scot %ud (lent envelopes.u.mailbox)))
~& pax
:_ (track-bone wir) :_ (track-bone wir)
[ost.bol %peer wir [(slav %p i.t.wir) %chat-hook] wir]~ [ost.bol %peer wir [(slav %p i.t.wir) %chat-hook] pax]~
:: ::
++ reap ++ reap
|= [wir=wire saw=(unit tang)] |= [wir=wire saw=(unit tang)]
@ -325,7 +423,7 @@
[ost.bol %poke / [our.bol %invite-store] [%invite-action act]] [ost.bol %poke / [our.bol %invite-store] [%invite-action act]]
:: ::
++ create-permission ++ create-permission
|= [pax=path sec=chat-security] |= [pax=path sec=rw-security]
^- (list move) ^- (list move)
=/ read-perm (weld pax /read) =/ read-perm (weld pax /read)
=/ write-perm (weld pax /write) =/ write-perm (weld pax /write)

View File

@ -21,6 +21,7 @@
$% [%chat-initial inbox] $% [%chat-initial inbox]
[%chat-configs chat-configs] [%chat-configs chat-configs]
[%chat-update chat-update] [%chat-update chat-update]
[%chat-two-update chat-two-update]
== ==
-- --
:: ::
@ -154,10 +155,11 @@
^- (quip move _this) ^- (quip move _this)
?> (team:title our.bol src.bol) ?> (team:title our.bol src.bol)
?- -.action ?- -.action
%create (handle-create action) %create (handle-create action)
%delete (handle-delete action) %delete (handle-delete action)
%message (handle-message action) %message (handle-message action)
%read (handle-read action) %messages (handle-messages action)
%read (handle-read action)
== ==
:: ::
++ handle-create ++ handle-create
@ -187,17 +189,34 @@
=/ mailbox=(unit mailbox) (~(get by inbox) path.act) =/ mailbox=(unit mailbox) (~(get by inbox) path.act)
?~ mailbox ?~ mailbox
[~ this] [~ this]
=* letter letter.envelope.act =. letter.envelope.act (evaluate-letter letter.envelope.act)
=? letter &(?=(%code -.letter) ?=(~ output.letter)) =. u.mailbox (append-envelope u.mailbox envelope.act)
=/ =hoon (ream expression.letter)
letter(output (eval bol hoon))
=: length.config.u.mailbox +(length.config.u.mailbox)
number.envelope.act +(length.config.u.mailbox)
envelopes.u.mailbox (snoc envelopes.u.mailbox envelope.act)
==
:- (send-diff path.act act) :- (send-diff path.act act)
this(inbox (~(put by inbox) path.act u.mailbox)) this(inbox (~(put by inbox) path.act u.mailbox))
:: ::
++ handle-messages
|= act=chat-action
^- (quip move _this)
?> ?=(%messages -.act)
=/ mailbox=(unit mailbox) (~(get by inbox) path.act)
?~ mailbox
[~ this]
=/ evaluated-envelopes=(list envelope) ~
|- ^- (quip move _this)
?~ envelopes.act
:_ this(inbox (~(put by inbox) path.act u.mailbox))
%+ send-two-diff path.act
:* %messages
path.act
(sub length.config.u.mailbox (lent evaluated-envelopes))
length.config.u.mailbox
evaluated-envelopes
==
=. letter.i.envelopes.act (evaluate-letter letter.i.envelopes.act)
=. evaluated-envelopes (snoc evaluated-envelopes i.envelopes.act)
=. u.mailbox (append-envelope u.mailbox i.envelopes.act)
$(envelopes.act t.envelopes.act)
::
++ handle-read ++ handle-read
|= act=chat-action |= act=chat-action
^- (quip move _this) ^- (quip move _this)
@ -209,26 +228,58 @@
:- (send-diff path.act act) :- (send-diff path.act act)
this(inbox (~(put by inbox) path.act u.mailbox)) this(inbox (~(put by inbox) path.act u.mailbox))
:: ::
++ evaluate-letter
|= =letter
^- ^letter
=? letter &(?=(%code -.letter) ?=(~ output.letter))
=/ =hoon (ream expression.letter)
letter(output (eval bol hoon))
letter
::
++ append-envelope
|= [=mailbox =envelope]
^- ^mailbox
=. number.envelope +(length.config.mailbox)
=: length.config.mailbox +(length.config.mailbox)
envelopes.mailbox (snoc envelopes.mailbox envelope)
==
mailbox
::
++ update-subscribers ++ update-subscribers
|= [pax=path act=chat-action] |= [pax=path upd=chat-update]
^- (list move) ^- (list move)
%+ turn (prey:pubsub:userlib pax bol) %+ turn (prey:pubsub:userlib pax bol)
|= [=bone *] |= [=bone *]
[bone %diff %chat-update act] [bone %diff %chat-update upd]
:: ::
++ send-diff ++ send-diff
|= [pax=path act=chat-action] |= [pax=path upd=chat-update]
^- (list move) ^- (list move)
%- zing %- zing
:~ (update-subscribers /all act) :~ (update-subscribers /all upd)
(update-subscribers /updates act) (update-subscribers /updates upd)
(update-subscribers [%mailbox pax] act) (update-subscribers [%mailbox pax] upd)
?. |(=(%read -.act) =(%message -.act)) ?. |(|(=(%read -.upd) =(%message -.upd)) =(%messages -.upd))
~ ~
(update-subscribers /configs act) (update-subscribers /configs upd)
?. |(=(%create -.act) =(%delete -.act)) ?. |(=(%create -.upd) =(%delete -.upd))
~ ~
(update-subscribers /keys act) (update-subscribers /keys upd)
== ==
:: ::
++ send-two-diff
|= [pax=path upd=chat-two-update]
^- (list move)
%- zing
:~ (update-two-subscribers /all upd)
(update-two-subscribers /updates upd)
(update-two-subscribers [%mailbox pax] upd)
==
::
++ update-two-subscribers
|= [pax=path upd=chat-two-update]
^- (list move)
%+ turn (prey:pubsub:userlib pax bol)
|= [=bone *]
[bone %diff %chat-two-update upd]
-- --

View File

@ -129,9 +129,8 @@
%http-response %http-response
%- json-response:app %- json-response:app
%- json-to-octs %- json-to-octs
%+ envelopes-update %- two-update-to-json
envelopes [%messages pax start end envelopes]
[start end pax]
== ==
:: ::
:: inbox page :: inbox page
@ -155,7 +154,6 @@
[~ this] [~ this]
?- -.act ?- -.act
%create %create
:: TODO: add invites
=/ pax [(scot %p our.bol) path.act] =/ pax [(scot %p our.bol) path.act]
=/ group-read=path [%chat (weld pax /read)] =/ group-read=path [%chat (weld pax /read)]
=/ group-write=path [%chat (weld pax /write)] =/ group-write=path [%chat (weld pax /write)]
@ -166,7 +164,7 @@
(group-poke [%add read.act group-read]) (group-poke [%add read.act group-read])
(group-poke [%add write.act group-write]) (group-poke [%add write.act group-write])
(chat-poke [%create our.bol path.act]) (chat-poke [%create our.bol path.act])
(chat-hook-poke [%add-owned pax security.act]) (chat-hook-poke [%add-owned pax security.act allow-history.act])
== ==
(create-security [%chat pax] security.act) (create-security [%chat pax] security.act)
:~ (permission-hook-poke [%add-owned group-read group-read]) :~ (permission-hook-poke [%add-owned group-read group-read])
@ -190,7 +188,7 @@
=/ group-read [%chat (scot %p ship.act) (weld path.act /read)] =/ group-read [%chat (scot %p ship.act) (weld path.act /read)]
=/ group-write [%chat (scot %p ship.act) (weld path.act /write)] =/ group-write [%chat (scot %p ship.act) (weld path.act /write)]
:_ this :_ this
:~ (chat-hook-poke [%add-synced ship.act path.act]) :~ (chat-hook-poke [%add-synced ship.act path.act ask-history.act])
(permission-hook-poke [%add-synced ship.act group-write]) (permission-hook-poke [%add-synced ship.act group-write])
(permission-hook-poke [%add-synced ship.act group-read]) (permission-hook-poke [%add-synced ship.act group-read])
== ==
@ -227,6 +225,21 @@
|= [=bone *] |= [=bone *]
[bone %diff %json configs-json] [bone %diff %json configs-json]
:: ::
++ diff-chat-two-update
|= [wir=wire upd=chat-two-update]
^- (quip move _this)
=/ updates-json (two-update-to-json upd)
=/ configs-json (configs-to-json configs-scry)
:_ this
%+ weld
%+ turn (prey:pubsub:userlib /primary bol)
|= [=bone *]
[bone %diff %json updates-json]
%+ turn (prey:pubsub:userlib /configs bol)
|= [=bone *]
[bone %diff %json configs-json]
::
++ quit ++ quit
|= wir=wire |= wir=wire
^- (quip move _this) ^- (quip move _this)
@ -281,7 +294,7 @@
.^(chat-configs %gx /=chat-store/(scot %da now.bol)/configs/noun) .^(chat-configs %gx /=chat-store/(scot %da now.bol)/configs/noun)
:: ::
++ create-security ++ create-security
|= [pax=path sec=chat-security] |= [pax=path sec=rw-security]
^- (list move) ^- (list move)
=/ read (weld pax /read) =/ read (weld pax /read)
=/ write (weld pax /write) =/ write (weld pax /write)
@ -308,22 +321,6 @@
:: ::
== ==
:: ::
++ envelopes-update
|= [envelopes=(list envelope) start=@ud end=@ud pax=path]
^- json
=, enjs:format
%+ frond %chat-update
%- pairs
:~
:- %messages
%- pairs
:~ [%path (path pax)]
[%start (numb start)]
[%end (numb end)]
[%envelopes [%a (turn envelopes enve)]]
==
==
::
++ truncate-envelopes ++ truncate-envelopes
|= envelopes=(list envelope) |= envelopes=(list envelope)
^- (list envelope) ^- (list envelope)
@ -340,5 +337,4 @@
^- mailbox ^- mailbox
:- config.mail :- config.mail
(truncate-envelopes envelopes.mail) (truncate-envelopes envelopes.mail)
::
-- --

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -118,6 +118,25 @@
[%config (conf config.mailbox)] [%config (conf config.mailbox)]
== ==
:: ::
++ two-update-to-json
|= upd=chat-two-update
=, enjs:format
^- json
%+ frond %chat-update
%- pairs
:~
?: =(%messages -.upd)
?> ?=(%messages -.upd)
:- %messages
%- pairs
:~ [%path (path path.upd)]
[%start (numb start.upd)]
[%end (numb end.upd)]
[%envelopes [%a (turn envelopes.upd enve)]]
==
[*@t *^json]
==
::
++ update-to-json ++ update-to-json
|= upd=chat-update |= upd=chat-update
=, enjs:format =, enjs:format
@ -166,6 +185,7 @@
:~ [%create create] :~ [%create create]
[%delete delete] [%delete delete]
[%message message] [%message message]
[%messages messages]
[%read read] [%read read]
== ==
:: ::
@ -184,6 +204,12 @@
[%envelope envelope] [%envelope envelope]
== ==
:: ::
++ messages
%- ot
:~ [%path pa]
[%envelopes (ar envelope)]
==
::
++ read ++ read
(ot [%path pa] ~) (ot [%path pa] ~)
:: ::
@ -225,6 +251,7 @@
[%security sec] [%security sec]
[%read (as (su ;~(pfix sig fed:ag)))] [%read (as (su ;~(pfix sig fed:ag)))]
[%write (as (su ;~(pfix sig fed:ag)))] [%write (as (su ;~(pfix sig fed:ag)))]
[%allow-history bo]
== ==
:: ::
++ delete ++ delete
@ -234,11 +261,12 @@
%- ot %- ot
:~ [%ship (su ;~(pfix sig fed:ag))] :~ [%ship (su ;~(pfix sig fed:ag))]
[%path pa] [%path pa]
[%ask-history bo]
== ==
:: ::
++ sec ++ sec
=, dejs:format =, dejs:format
^- $-(json chat-security) ^- $-(json rw-security)
(su (perk %channel %village %journal %mailbox ~)) (su (perk %channel %village %journal %mailbox ~))
-- --
-- --

View File

@ -20,16 +20,18 @@
%- ot %- ot
:~ [%path pa] :~ [%path pa]
[%security sec] [%security sec]
[%allow-history bo]
== ==
:: ::
++ add-synced ++ add-synced
%- ot %- ot
:~ [%ship (su ;~(pfix sig fed:ag))] :~ [%ship (su ;~(pfix sig fed:ag))]
[%path pa] [%path pa]
[%ask-history bo]
== ==
:: ::
++ sec ++ sec
^- $-(^json chat-security) ^- $-(^json rw-security)
(su (perk %channel %village %journal %mailbox ~)) (su (perk %channel %village %journal %mailbox ~))
:: ::
-- --

View File

@ -0,0 +1,13 @@
/+ *chat-json
|_ upd=chat-two-update
++ grow
|%
++ json (two-update-to-json upd)
--
::
++ grab
|%
++ noun chat-two-update
--
::
--

View File

@ -1,23 +1,16 @@
/- *rw-security
|% |%
+$ chat-security
$? $channel :: black r, black w
$village :: white r, white w
$journal :: black r, white w
$mailbox :: white r, black w
==
::
+$ chat-hook-action +$ chat-hook-action
$% :: %add-owned: make a chatroom accessible to foreign ships $% :: %add-owned: make a chatroom accessible to foreign ships
:: specified by the chat-security model :: specified by the rw-security model
:: ::
[%add-owned =path security=chat-security] [%add-owned =path security=rw-security allow-history=?]
:: %add-synced: mirror a foreign chatroom to our chat-store :: %add-synced: mirror a foreign chatroom to our chat-store
:: ::
[%add-synced =ship =path] [%add-synced =ship =path ask-history=?]
:: %remove: stop mirroring a foreign chatroom or allowing a local :: %remove: stop mirroring a foreign chatroom or allowing a local
:: chatroom to be mirrored :: chatroom to be mirrored
:: ::
[%remove =path] [%remove =path]
== ==
-- --

View File

@ -30,16 +30,26 @@
:: ::
+$ chat-configs (map path config) +$ chat-configs (map path config)
:: ::
+$ chat-action +$ chat-base
$% [%create =ship =path] :: %create: create a mailbox at ~ship/path $% [%create =ship =path] :: %create: create a mailbox at ~ship/path
[%delete =path] :: %delete: delete a mailbox at path [%delete =path] :: %delete: delete a mailbox at path
[%message =path =envelope] :: %message: append a message to mailbox [%message =path =envelope] :: %message: append a message to mailbox
[%read =path] :: %read: set mailbox to read [%read =path] :: %read: set mailbox to read
== ==
:: ::
+$ chat-action
$% :: %messages: append a list of messages to mailbox
::
[%messages =path envelopes=(list envelope)]
chat-base
==
::
+$ chat-update +$ chat-update
$% [%keys keys=(set path)] $% [%keys keys=(set path)]
[%config =path =config] [%config =path =config]
chat-action chat-base
== ==
::
+$ chat-two-update
[%messages =path start=@ud end=@ud envelopes=(list envelope)]
-- --

View File

@ -1,14 +1,14 @@
/- *rw-security
|% |%
+$ chat-security
$? $channel :: black r, black w
$village :: white r, white w
$journal :: black r, white w
$mailbox :: white r, black w
==
::
+$ chat-view-action +$ chat-view-action
$% [%create =path security=chat-security read=(set ship) write=(set ship)] $% $: %create
=path
security=rw-security
read=(set ship)
write=(set ship)
allow-history=?
==
[%delete =path] [%delete =path]
[%join =ship =path] [%join =ship =path ask-history=?]
== ==
-- --

View File

@ -0,0 +1,8 @@
|%
+$ rw-security
$? $channel :: black r, black w
$village :: white r, white w
$journal :: black r, white w
$mailbox :: white r, black w
==
--

View File

@ -14,6 +14,10 @@ textarea, input, button {
background-color: #fff; background-color: #fff;
} }
input[type=checkbox] {
-webkit-appearance: checkbox;
}
a { a {
color: #000 !important; color: #000 !important;
font-weight: 400 !important; font-weight: 400 !important;

View File

@ -128,10 +128,11 @@ class UrbitApi {
this.action("chat-view", "json", data); this.action("chat-view", "json", data);
} }
chatViewCreate(path, security, read, write) { chatViewCreate(path, security, read, write, allowHistory) {
this.chatViewAction({ this.chatViewAction({
create: { create: {
path, security, read, write path, security, read, write,
'allow-history': allowHistory
} }
}); });
} }
@ -140,8 +141,13 @@ class UrbitApi {
this.chatViewAction({ delete: { path } }); this.chatViewAction({ delete: { path } });
} }
chatViewJoin(ship, path) { chatViewJoin(ship, path, askHistory) {
this.chatViewAction({ join: { ship, path } }); this.chatViewAction({
join: {
ship, path,
'ask-history': askHistory
}
});
} }
inviteAction(data) { inviteAction(data) {

View File

@ -67,7 +67,7 @@ export class ChatScreen extends Component {
updateReadNumber() { updateReadNumber() {
const { props, state } = this; const { props, state } = this;
if (props.read < props.envelopes.length) { if (props.read < props.length) {
props.api.chat.read(state.station); props.api.chat.read(state.station);
} }
} }

View File

@ -47,7 +47,8 @@ export class JoinScreen extends Component {
return; return;
} }
props.api.chatView.join(ship, station); // TODO: askHistory setting
props.api.chatView.join(ship, station, true);
this.props.history.push('/~chat'); this.props.history.push('/~chat');
} }

View File

@ -26,19 +26,21 @@ export class ChatInput extends Component {
// perf testing: // perf testing:
/*let closure = () => { /*let closure = () => {
let x = 0;
for (var i = 0; i < 30; i++) { for (var i = 0; i < 30; i++) {
x++;
props.api.chat.message( props.api.chat.message(
props.station, props.station,
`~${window.ship}`, `~${window.ship}`,
Date.now(), Date.now(),
{ {
text: `${Date.now()}` text: `${x}`
} }
); );
} }
setTimeout(closure, 1000); setTimeout(closure, 1000);
}; };
setTimeout(closure, 2000);*/ this.closure = closure.bind(this);*/
moment.updateLocale('en', { moment.updateLocale('en', {
relativeTime : { relativeTime : {
@ -144,6 +146,7 @@ export class ChatInput extends Component {
Date.now(), Date.now(),
letter letter
); );
// perf: setTimeout(this.closure, 2000);
this.setState({ this.setState({
message: '', message: '',

View File

@ -14,12 +14,14 @@ export class NewScreen extends Component {
invites: '', invites: '',
security: 'village', security: 'village',
idError: false, idError: false,
inviteError: false inviteError: false,
allowHistory: true
}; };
this.idChange = this.idChange.bind(this); this.idChange = this.idChange.bind(this);
this.invChange = this.invChange.bind(this); this.invChange = this.invChange.bind(this);
this.securityChange = this.securityChange.bind(this); this.securityChange = this.securityChange.bind(this);
this.allowHistoryChange = this.allowHistoryChange.bind(this);
} }
componentDidUpdate(prevProps, prevState) { componentDidUpdate(prevProps, prevState) {
@ -47,6 +49,10 @@ export class NewScreen extends Component {
this.setState({security: event.target.value}); this.setState({security: event.target.value});
} }
allowHistoryChange(event) {
this.setState({allowHistory: !!event.target.checked});
}
onClickCreate() { onClickCreate() {
const { props, state } = this; const { props, state } = this;
if (!state.idName) { if (!state.idName) {
@ -114,14 +120,15 @@ export class NewScreen extends Component {
readAud = aud.slice(); // white list readAud = aud.slice(); // white list
writeAud = []; // black list writeAud = []; // black list
} }
this.setState({ this.setState({
error: false, error: false,
success: true, success: true,
invites: '' invites: ''
}, () => { }, () => {
props.setSpinner(true); props.setSpinner(true);
props.api.chatView.create(station, state.security, readAud, writeAud); props.api.chatView.create(
station, state.security, readAud, writeAud, state.allowHistory
);
aud.forEach((ship) => { aud.forEach((ship) => {
if (ship !== `~${window.ship}`) { if (ship !== `~${window.ship}`) {
props.api.invite.invite(station, ship); props.api.invite.invite(station, ship);
@ -194,6 +201,18 @@ export class NewScreen extends Component {
<option value="journal">Journal</option> <option value="journal">Journal</option>
<option value="mailbox">Mailbox</option> <option value="mailbox">Mailbox</option>
</select> </select>
<p className="body-medium mt3 db">Chat History</p>
<div className="db mt2">
<input
type="checkbox"
checked={this.state.allowHistory}
onChange={this.allowHistoryChange.bind(this)}
className="dib mr2"
/>
<p className="body-small db mt2 mb3 dib">
Allow participants to download the chat history upon joining.
</p>
</div>
<button <button
onClick={this.onClickCreate.bind(this)} onClick={this.onClickCreate.bind(this)}
className={createClasses} className={createClasses}

View File

@ -44,7 +44,8 @@ export class Root extends Component {
messagePreviews[stat] = envelopes[envelopes.length - 1]; messagePreviews[stat] = envelopes[envelopes.length - 1];
} }
unreads[stat] = envelopes.length > state.inbox[stat].config.read; unreads[stat] =
state.inbox[stat].config.length > state.inbox[stat].config.read;
}); });
let invites = '/chat' in state.invites ? let invites = '/chat' in state.invites ?
@ -113,7 +114,7 @@ export class Root extends Component {
`/${props.match.params.ship}/${props.match.params.station}`; `/${props.match.params.ship}/${props.match.params.station}`;
let mailbox = state.inbox[station] || { let mailbox = state.inbox[station] || {
config: { config: {
read: -1, read: 0,
length: 0 length: 0
}, },
envelopes: [] envelopes: []
@ -127,6 +128,7 @@ export class Root extends Component {
api={api} api={api}
subscription={subscription} subscription={subscription}
read={mailbox.config.read} read={mailbox.config.read}
length={mailbox.config.length}
envelopes={mailbox.envelopes} envelopes={mailbox.envelopes}
inbox={state.inbox} inbox={state.inbox}
group={write} group={write}

View File

@ -18,15 +18,18 @@ export class ChatUpdateReducer {
let data = _.get(json, 'message', false); let data = _.get(json, 'message', false);
if (data) { if (data) {
state.inbox[data.path].envelopes.push(data.envelope); state.inbox[data.path].envelopes.push(data.envelope);
state.inbox[data.path].config.length
= state.inbox[data.path].config.length + 1;
} }
} }
messages(json, state) { messages(json, state) {
let data = _.get(json, 'messages', false); let data = _.get(json, 'messages', false);
if (data) { if (data) {
console.log(data);
state.inbox[data.path].envelopes = state.inbox[data.path].envelopes =
data.envelopes.concat(state.inbox[data.path].envelopes); data.envelopes.concat(state.inbox[data.path].envelopes);
state.inbox[data.path].config.length =
state.inbox[data.path].config.length + data.envelopes.length;
} }
} }
@ -34,7 +37,7 @@ export class ChatUpdateReducer {
let data = _.get(json, 'read', false); let data = _.get(json, 'read', false);
if (data) { if (data) {
state.inbox[data.path].config.read = state.inbox[data.path].config.read =
state.inbox[data.path].envelopes.length; state.inbox[data.path].config.length;
} }
} }
@ -44,8 +47,8 @@ export class ChatUpdateReducer {
state.inbox[`/~${data.ship}${data.path}`] = { state.inbox[`/~${data.ship}${data.path}`] = {
envelopes: [], envelopes: [],
config: { config: {
read:0, read: 0,
length: 0, length: 0
} }
}; };
} }