diff --git a/desk/lib/summarize.hoon b/desk/lib/summarize.hoon
index 782e7545..90773fb0 100644
--- a/desk/lib/summarize.hoon
+++ b/desk/lib/summarize.hoon
@@ -1,6 +1,6 @@
:: summarize: utilities for summarizing groups/chat state in various ways
::
-/- chat, groups
+/- c=channels, ct=chat, chat=chat-2, groups
::
|_ [our=@p now=@da]
:: +range: period of time to summarize over
@@ -14,6 +14,48 @@
[(scot %p our) term (scot %da now) spur]
::
++ summarize-activity
+ ?: .^(? %gu (scry-path %channels /$))
+ summarize-activity-new-groups
+ summarize-activity-old-groups
+::
+++ summarize-activity-new-groups
+ ^- $: sent=@ud
+ received=@ud
+ most-sent-group=@t
+ ==
+ =- :+ s r
+ =/ g=flag:groups
+ =< -
+ ::TODO crashes if no groups
+ %+ snag 0
+ %+ sort ~(tap by g)
+ |=([[* a=@ud] [* b=@ud]] (gth a b))
+ =< title.meta
+ .^ group:groups
+ %gx
+ (scry-path %groups /groups/(scot %p p.g)/[q.g]/group)
+ ==
+ %+ roll
+ %~ tap by
+ .^ channels:c
+ %gx
+ (scry-path %channels /channels/channels)
+ ==
+ |= [[n=nest:c channel:c] g=(map flag:groups @ud) s=@ud r=@ud]
+ ?. ?=(%chat kind.n) [g s r]
+ =+ .^ paged-posts:c
+ %gx
+ %+ scry-path %channels
+ /chat/(scot %p ship.n)/[name.n]/posts/newer/(scot %ud (sub now range))/(scot %ud limit)/outline/channel-posts
+ ==
+ :- %+ ~(put by g) group.perm
+ (add (~(gut by g) group.perm 0) (wyt:on-posts:c posts))
+ %+ roll (tap:on-posts:c posts)
+ |= [[id-post:c p=(unit post:c)] s=_s r=_r]
+ ?~ p [s r]
+ ?:(=(our author.u.p) [+(s) r] [s +(r)])
+::
+++ summarize-activity-old-groups
^- $: sent=@ud
received=@ud
most-sent-group=@t
@@ -31,7 +73,7 @@
(scry-path %groups /groups/(scot %p p.g)/[q.g]/group)
==
%+ roll
- %~ tap in
+ %~ tap by
.^ (map flag:chat chat:chat)
%gx
(scry-path %chat /chats/chats)
@@ -50,6 +92,54 @@
?:(=(our author) [+(s) r] [s +(r)])
::
++ summarize-inactivity
+ ?: .^(? %gu (scry-path %channels /$))
+ summarize-inactivity-new-groups
+ summarize-inactivity-old-groups
+::
+++ summarize-inactivity-new-groups
+ ^- $: unread-dms=@ud :: unread dm count
+ unread-etc=@ud :: unread chats count
+ top-group=@t :: most active group
+ top-channel=@t :: most active channel
+ ==
+ =+ .^(=unreads:ct %gx (scry-path %chat /unreads/chat-unreads))
+ :: accumulate unread counts
+ ::
+ =/ dum=@ud
+ %- ~(rep by unreads)
+ |= [[w=whom:ct unread:unreads:ct] n=@ud]
+ (add n count)
+ :- dum
+ :: gather all chat channels & their groups & unread counts
+ ::
+ =/ [duc=@ud faz=(list [g=flag:groups n=nest:c u=@ud])]
+ %+ roll
+ %~ tap by
+ .^(channels:c %gx (scry-path %channels /channels/channels))
+ =+ .^(=unreads:c %gx (scry-path %channels /unreads/channel-unreads))
+ |= [[n=nest:c channel:c] duc=@ud faz=(list [flag:groups nest:c @ud])]
+ ?. ?=(%chat kind.n) [duc faz] :: ignore non-chat channels for now
+ =/ =unread:c (~(gut by unreads) n *unread:c)
+ :- (add duc count.unread)
+ [[group.perm n count.unread] faz]
+ :- duc
+ =. faz (sort faz |=([[* * a=@ud] [* * b=@ud]] (gth a b)))
+ :: get display titles of most active channel and its group
+ ::
+ ::NOTE in rare cases, we might not know of the existence of the associated
+ :: group. simply skip past it and try the next one...
+ =+ .^(=groups:groups %gx (scry-path %groups /groups/groups))
+ |-
+ ?~ faz ['???' '???'] ::TODO better copy
+ ~| i.faz
+ ?. (~(has by groups) g.i.faz)
+ $(faz t.faz)
+ =/ =group:^groups (~(got by groups) g.i.faz)
+ ?~ chat=(~(get by channels.group) n.i.faz)
+ $(faz t.faz)
+ [title.meta.group title.meta.u.chat]
+::
+++ summarize-inactivity-old-groups
^- $: unread-dms=@ud :: unread dm count
unread-etc=@ud :: unread chats count
top-group=@t :: most active group
@@ -71,7 +161,7 @@
::
=/ faz=(list [g=flag:chat c=flag:chat n=@ud])
%+ turn
- %~ tap in
+ %~ tap by
.^ (map flag:chat chat:chat)
%gx
(scry-path %chat /chats/chats)
diff --git a/desk/sur/channels.hoon b/desk/sur/channels.hoon
new file mode 100644
index 00000000..2db94219
--- /dev/null
+++ b/desk/sur/channels.hoon
@@ -0,0 +1,461 @@
+:: channels: message stream structures
+::
+:: four shapes that cross client-subscriber-publisher boundaries:
+:: - actions client-to-subscriber change requests (user actions)
+:: - commands subscriber-to-publisher change requests
+:: - updates publisher-to-subscriber change notifications
+:: - responses subscriber-to-client change notifications
+::
+:: --action--> --command-->
+:: client subscriber publisher
+:: <--response-- <--update--
+::
+:: local actions _may_ become responses,
+:: remote actions become commands,
+:: commands _may_ become updates,
+:: updates _may_ become responses.
+::
+/- g=groups, c=cite
+/+ mp=mop-extensions
+|%
++| %ancients
+::
+++ mar
+ |%
+ ++ act `mark`%channel-action
+ ++ cmd `mark`%channel-command
+ ++ upd `mark`%channel-update
+ ++ log `mark`%channel-logs
+ ++ not `mark`%channel-posts
+ --
+::
++| %primitives
+::
++$ v-channels (map nest v-channel)
+++ v-channel
+ |^ ,[global local]
+ :: $global: should be identical between ships
+ ::
+ +$ global
+ $: posts=v-posts
+ order=(rev order=arranged-posts)
+ view=(rev =view)
+ sort=(rev =sort)
+ perm=(rev =perm)
+ ==
+ :: $window: sparse set of time ranges
+ ::
+ ::TODO populate this
+ +$ window (list [from=time to=time])
+ :: .window: time range for requested posts that we haven't received
+ :: .diffs: diffs for posts in the window, to apply on receipt
+ ::
+ +$ future
+ [=window diffs=(jug id-post u-post)]
+ :: $local: local-only information
+ ::
+ +$ local
+ $: =net
+ =log
+ =remark
+ =window
+ =future
+ ==
+ --
+:: $v-post: a channel post
+::
++$ v-post [v-seal (rev essay)]
++$ id-post time
++$ v-posts ((mop id-post (unit v-post)) lte)
+++ on-v-posts ((on id-post (unit v-post)) lte)
+++ mo-v-posts ((mp id-post (unit v-post)) lte)
+:: $v-reply: a post comment
+::
++$ v-reply [v-reply-seal memo]
++$ id-reply time
++$ v-replies ((mop id-reply (unit v-reply)) lte)
+++ on-v-replies ((on id-reply (unit v-reply)) lte)
+++ mo-v-replies ((mp time (unit v-reply)) lte)
+:: $v-seal: host-side data for a post
+::
++$ v-seal $+ channel-seal
+ $: id=id-post
+ replies=v-replies
+ reacts=v-reacts
+ ==
+:: $v-reply-seal: host-side data for a reply
+::
++$ v-reply-seal
+ $: id=id-reply
+ reacts=v-reacts
+ ==
+:: $essay: top-level post, with metadata
+::
++$ essay [memo =kind-data]
+:: $reply-meta: metadata for all replies
++$ reply-meta
+ $: reply-count=@ud
+ last-repliers=(set ship)
+ last-reply=(unit time)
+ ==
+:: $kind-data: metadata for a channel type's "post"
+::
++$ kind-data
+ $% [%diary title=@t image=@t]
+ [%heap title=(unit @t)]
+ [%chat kind=$@(~ [%notice ~])]
+ ==
+:: $memo: post data proper
+::
+:: content: the body of the comment
+:: author: the ship that wrote the comment
+:: sent: the client-side time the comment was made
+::
++$ memo
+ $: content=story
+ author=ship
+ sent=time
+ ==
+:: $story: post body content
+::
++$ story (list verse)
+:: $verse: a chunk of post content
+::
+:: blocks stand on their own. inlines come in groups and get wrapped
+:: into a paragraph
+::
++$ verse
+ $% [%block p=block]
+ [%inline p=(list inline)]
+ ==
+:: $listing: recursive type for infinitely nested
or
++$ listing
+ $% [%list p=?(%ordered %unordered %tasklist) q=(list listing) r=(list inline)]
+ [%item p=(list inline)]
+ ==
+:: $block: post content that sits outside of the normal text
+::
+:: %image: a visual, we record dimensions for better rendering
+:: %cite: an Urbit reference
+:: %header: a traditional HTML heading, h1-h6
+:: %listing: a traditional HTML list, ul and ol
+:: %code: a block of code
+::
++$ block $+ channel-block
+ $% [%image src=cord height=@ud width=@ud alt=cord]
+ [%cite =cite:c]
+ [%header p=?(%h1 %h2 %h3 %h4 %h5 %h6) q=(list inline)]
+ [%listing p=listing]
+ [%rule ~]
+ [%code code=cord lang=cord]
+ ==
+:: $inline: post content that flows within a paragraph
+::
+:: @t: plain text
+:: %italics: italic text
+:: %bold: bold text
+:: %strike: strikethrough text
+:: %inline-code: code formatting for small snippets
+:: %blockquote: blockquote surrounded content
+:: %block: link/reference to blocks
+:: %code: code formatting for large snippets
+:: %tag: tag gets special signifier
+:: %link: link to a URL with a face
+:: %break: line break
+::
++$ inline $+ channel-inline
+ $@ @t
+ $% [%italics p=(list inline)]
+ [%bold p=(list inline)]
+ [%strike p=(list inline)]
+ [%blockquote p=(list inline)]
+ [%inline-code p=cord]
+ [%code p=cord]
+ [%ship p=ship]
+ [%block p=@ud q=cord]
+ [%tag p=cord]
+ [%link p=cord q=cord]
+ [%task p=?(%.y %.n) q=(list inline)]
+ [%break ~]
+ ==
+::
++$ kind ?(%diary %heap %chat)
+:: $nest: identifier for a channel
++$ nest [=kind =ship name=term]
+:: $view: the persisted display format for a channel
++$ view $~(%list ?(%grid %list))
+:: $sort: the persisted sort type for a channel
++$ sort $~(%time ?(%alpha %time %arranged))
+:: $arranged-posts: an array of postIds
++$ arranged-posts (unit (list time))
+:: $hidden-posts: a set of ids for posts that are hidden
++$ hidden-posts (set id-post)
+:: $post-toggle: hide or show a particular post by id
++$ post-toggle
+ $% [%hide =id-post]
+ [%show =id-post]
+ ==
+:: $react: either an emoji identifier like :diff or a URL for custom
++$ react @ta
++$ v-reacts (map ship (rev (unit react)))
+:: $scan: search results
++$ scan (list reference)
++$ reference
+ $% [%post =post]
+ [%reply =id-post =reply]
+ ==
+:: $said: used for references
++$ said (pair nest reference)
+:: $plan: index into channel state
+:: p: Post being referred to
+:: q: Reply being referred to, if any
+::
++$ plan
+ (pair time (unit time))
+::
+:: $net: subscriber-only state
+::
++$ net [p=ship load=_|]
+::
+:: $unreads: a map of channel unread information, for clients
+:: $unread: unread data for a specific channel, for clients
+:: recency: time of most recent message
+:: count: how many posts are unread
+:: unread-id: the id of the first unread top-level post
+:: threads: for each unread thread, the id of the first unread reply
+::
++$ unreads (map nest unread)
++$ unread
+ $: recency=time
+ count=@ud
+ unread-id=(unit id-post)
+ threads=(map id-post id-reply)
+ ==
+:: $remark: markers representing unread state
+:: last-read: time at which the user last read this channel
+:: watching: unused, intended for disabling unread accumulation
+:: unread-threads: threads that contain unread messages
+::
++$ remark [recency=time last-read=time watching=_| unread-threads=(set id-post)]
+::
+:: $perm: represents the permissions for a channel and gives a
+:: pointer back to the group it belongs to.
+::
++$ perm
+ $: writers=(set sect:g)
+ group=flag:g
+ ==
+::
+:: $log: a time ordered history of modifications to a channel
+::
++$ log ((mop time u-channel) lte)
+++ log-on ((on time u-channel) lte)
+::
+:: $create-channel: represents a request to create a channel
+::
+:: $create-channel is consumed by the channel agent first and then
+:: passed to the groups agent to register the channel with the group.
+::
+:: Write permission is stored with the specific agent in the channel,
+:: read permission is stored with the group's data.
+::
++$ create-channel
+ $: =kind
+ name=term
+ group=flag:g
+ title=cord
+ description=cord
+ readers=(set sect:g)
+ writers=(set sect:g)
+ ==
+:: $outline: abridged $post
+:: .replies: number of comments
+::
++$ outline
+ [replies=@ud replyers=(set ship) essay]
+::
+++ outlines
+ =< outlines
+ |%
+ +$ outlines ((mop time outline) lte)
+ ++ on ((^on time outline) lte)
+ --
+++ rev
+ |$ [data]
+ [rev=@ud data]
+::
+++ apply-rev
+ |* [old=(rev) new=(rev)]
+ ^+ [changed=& old]
+ ?: (lth rev.old rev.new)
+ &+new
+ |+old
+::
+++ next-rev
+ |* [old=(rev) new=*]
+ ^+ [changed=& old]
+ ?: =(+.old new)
+ |+old
+ &+old(rev +(rev.old), + new)
+::
++| %actions
+::
+:: some actions happen to be the same as commands, but this can freely
+:: change
+::
+::NOTE we might want to add a action-id=uuid to this eventually, threading
+:: that through all the way, so that an $r-channels may indicate what
+:: originally caused it
++$ a-channels
+ $% [%create =create-channel]
+ [%pin pins=(list nest)]
+ [%channel =nest =a-channel]
+ [%toggle-post toggle=post-toggle]
+ ==
++$ a-channel
+ $% [%join group=flag:g]
+ [%leave ~]
+ a-remark
+ c-channel
+ ==
+::
++$ a-remark
+ $~ [%read ~]
+ $% [%read ~]
+ [%read-at =time]
+ [%watch ~]
+ [%unwatch ~]
+ ==
+::
++$ a-post c-post
++$ a-reply c-reply
+::
++| %commands
+::
++$ c-channels
+ $% [%create =create-channel]
+ [%channel =nest =c-channel]
+ ==
++$ c-channel
+ $% [%post =c-post]
+ [%view =view]
+ [%sort =sort]
+ [%order order=arranged-posts]
+ [%add-writers sects=(set sect:g)]
+ [%del-writers sects=(set sect:g)]
+ ==
+::
++$ c-post
+ $% [%add =essay]
+ [%edit id=id-post =essay]
+ [%del id=id-post]
+ [%reply id=id-post =c-reply]
+ c-react
+ ==
+::
++$ c-reply
+ $% [%add =memo]
+ [%del id=id-reply]
+ c-react
+ ==
+::
++$ c-react
+ $% [%add-react id=@da p=ship q=react]
+ [%del-react id=@da p=ship]
+ ==
+::
++| %updates
+::
++$ update [=time =u-channel]
++$ u-channels [=nest =u-channel]
++$ u-channel
+ $% [%create =perm]
+ [%order (rev order=arranged-posts)]
+ [%view (rev =view)]
+ [%sort (rev =sort)]
+ [%perm (rev =perm)]
+ [%post id=id-post =u-post]
+ ==
+::
++$ u-post
+ $% [%set post=(unit v-post)]
+ [%reacts reacts=v-reacts]
+ [%essay (rev =essay)]
+ [%reply id=id-reply =u-reply]
+ ==
+::
++$ u-reply
+ $% [%set reply=(unit v-reply)]
+ [%reacts reacts=v-reacts]
+ ==
+::
++$ u-checkpoint global:v-channel
+::
++| %responses
+::
++$ r-channels [=nest =r-channel]
++$ r-channel
+ $% [%posts =posts]
+ [%post id=id-post =r-post]
+ [%order order=arranged-posts]
+ [%view =view]
+ [%sort =sort]
+ [%perm =perm]
+ ::
+ [%create =perm]
+ [%join group=flag:g]
+ [%leave ~]
+ a-remark
+ ==
+::
++$ r-post
+ $% [%set post=(unit post)]
+ [%reply id=id-reply =reply-meta =r-reply]
+ [%reacts =reacts]
+ [%essay =essay]
+ ==
+::
++$ r-reply
+ $% [%set reply=(unit reply)]
+ [%reacts =reacts]
+ ==
+:: versions of backend types with their revision numbers stripped,
+:: because the frontend shouldn't care to learn those.
+::
++$ channels (map nest channel)
+++ channel
+ |^ ,[global local]
+ +$ global
+ $: =posts
+ order=arranged-posts
+ =view
+ =sort
+ =perm
+ ==
+ ::
+ +$ local
+ $: =net
+ =remark
+ ==
+ --
++$ paged-posts
+ $: =posts
+ newer=(unit time)
+ older=(unit time)
+ total=@ud
+ ==
++$ posts ((mop id-post (unit post)) lte)
++$ post [seal essay]
++$ seal
+ $: id=id-post
+ =reacts
+ =replies
+ =reply-meta
+ ==
++$ reacts (map ship react)
++$ reply [reply-seal memo]
++$ replies ((mop id-reply reply) lte)
++$ reply-seal [id=id-reply parent-id=id-post =reacts]
+++ on-posts ((on id-post (unit post)) lte)
+++ on-replies ((on id-reply reply) lte)
+--
diff --git a/desk/sur/chat-2.hoon b/desk/sur/chat-2.hoon
new file mode 100644
index 00000000..09225a1e
--- /dev/null
+++ b/desk/sur/chat-2.hoon
@@ -0,0 +1,356 @@
+/- g=groups
+/- meta
+/- metadata-store
+/- cite
+/- e=epic
+|%
+:: +mar: mark name
+++ okay `epic:e`0
+++ mar
+ |%
+ ++ act `mark`(rap 3 %chat-action '-' (scot %ud okay) ~)
+ ++ upd `mark`(rap 3 %chat-update '-' (scot %ud okay) ~)
+ ++ log `mark`(rap 3 %chat-logs '-' (scot %ud okay) ~)
+ --
+::
+:: $scan: search results
++$ scan (list (pair time writ))
+:: $writ: a chat message
++$ writ [seal memo]
+:: $id: an identifier for chat messages
++$ id (pair ship time)
+:: $feel: either an emoji identifier like :wave: or a URL for custom
++$ feel @ta
++$ said (pair flag writ)
+::
+:: $seal: the id of a chat and its meta-responses
+::
+:: id: the id of the message
+:: feels: reactions to a message
+:: replied: set of replies to a message
+::
++$ seal
+ $: =id
+ feels=(map ship feel)
+ replied=(set id)
+ ==
+::
+:: $whom: a polymorphic identifier for chats
+::
++$ whom
+ $% [%flag p=flag]
+ [%ship p=ship]
+ [%club p=id:club]
+ ==
+::
+:: $briefs: a map of chat/club/dm unread information
+::
+:: brief: the last time a message was read, how many messages since,
+:: and the id of the last read message
+::
+++ briefs
+ =< briefs
+ |%
+ +$ briefs
+ (map whom brief)
+ +$ brief
+ [last=time count=@ud read-id=(unit id)]
+ +$ update
+ (pair whom brief)
+ --
+::
++$ remark-action
+ (pair whom remark-diff)
+::
++$ remark-diff
+ $% [%read ~]
+ [%read-at p=time]
+ [?(%watch %unwatch) ~]
+ ==
+::
+:: $flag: an identifier for a $chat channel
+::
++$ flag (pair ship term)
+::
+:: $diff: represents an update to state
+::
+:: %writs: a chat message update
+:: %add-sects: add sects to writer permissions
+:: %del-sects: delete sects from writers
+:: %create: create a new chat
+::
++$ diff
+ $% [%writs p=diff:writs]
+ ::
+ [%add-sects p=(set sect:g)]
+ [%del-sects p=(set sect:g)]
+ ::
+ [%create p=perm q=pact]
+ ==
+:: $index: a map of chat message id to server received message time
+::
++$ index (map id time)
+::
+:: $pact: a double indexed map of chat messages, id -> time -> message
+::
++$ pact
+ $: wit=writs
+ dex=index
+ ==
+::
+:: $club: a direct line of communication between multiple parties
+::
+:: uses gossip to ensure all parties keep in sync
+::
+++ club
+ =< club
+ |%
+ :: $id: an identification signifier for a $club
+ ::
+ +$ id @uvH
+ :: $net: status of club
+ ::
+ +$ net ?(%archive %invited %done)
+ +$ club [=heard =remark =pact =crew]
+ ::
+ :: $crew: a container for the metadata for the club
+ ::
+ :: team: members that have accepted an invite
+ :: hive: pending members that have been invited
+ :: met: metadata representing club
+ :: net: status
+ :: pin: should the $club be pinned to the top
+ ::
+ +$ crew
+ $: team=(set ship)
+ hive=(set ship)
+ met=data:meta
+ =net
+ pin=_|
+ ==
+ :: $rsvp: a $club invitation response
+ ::
+ +$ rsvp [=id =ship ok=?]
+ :: $create: a request to create a $club with a starting set of ships
+ ::
+ +$ create
+ [=id hive=(set ship)]
+ :: $invite: the contents to send in an invitation to someone
+ ::
+ +$ invite [=id team=(set ship) hive=(set ship) met=data:meta]
+ :: $uid: unique identifier for each club action
+ ::
+ +$ uid @uv
+ :: $heard: the set of action uid's we've already heard
+ ::
+ +$ heard (set uid)
+ ::
+ +$ diff (pair uid delta)
+ ::
+ +$ delta
+ $% [%writ =diff:writs]
+ [%meta meta=data:meta]
+ [%team =ship ok=?]
+ [%hive by=ship for=ship add=?]
+ [%init team=(set ship) hive=(set ship) met=data:meta]
+ ==
+ ::
+ +$ action (pair id diff)
+ --
+::
+:: $writs: a set of time ordered chat messages
+::
+++ writs
+ =< writs
+ |%
+ +$ writs
+ ((mop time writ) lte)
+ ++ on
+ ((^on time writ) lte)
+ +$ diff
+ (pair id delta)
+ +$ delta
+ $% [%add p=memo]
+ [%del ~]
+ [%add-feel p=ship q=feel]
+ [%del-feel p=ship]
+ ==
+ --
+::
+:: $dm: a direct line of communication between two ships
+::
+:: net: status of dm
+:: id: a message identifier
+:: action: an update to the dm
+:: rsvp: a response to a dm invitation
+::
+++ dm
+ =< dm
+ |%
+ +$ dm
+ $: =pact
+ =remark
+ =net
+ pin=_|
+ ==
+ +$ net ?(%inviting %invited %archive %done)
+ +$ id (pair ship time)
+ +$ diff diff:writs
+ +$ action (pair ship diff)
+ +$ rsvp [=ship ok=?]
+ --
+::
+:: $log: a time ordered map of all modifications to chats
+::
++$ log
+ ((mop time diff) lte)
+++ log-on
+ ((on time diff) lte)
++$ remark
+ [last-read=time watching=_| ~]
+::
+:: $chat: a group based channel for communicating
+::
++$ chat
+ [=net =remark =log =perm =pact]
+::
+:: $notice: the contents of an automated message
+::
+:: pfix: text preceding ship name
+:: sfix: text following ship name
+::
++$ notice [pfix=@t sfix=@t]
+::
+:: $content: the contents of a message whether handwritten or automated
+::
++$ content
+ $% [%story p=story]
+ [%notice p=notice]
+ ==
+::
+:: $draft: the contents of an unsent message at a particular $whom
+::
++$ draft
+ (pair whom story)
+::
+:: $story: handwritten contents of a message
+::
+:: blocks precede inline content
+::
++$ story
+ (pair (list block) (list inline))
+::
+:: $block: content which stands on it's own outside of inline content
+::
++$ block
+ $% [%image src=cord height=@ud width=@ud alt=cord]
+ [%cite =cite]
+ ==
+::
+:: $inline: a representation of text with or without formatting
+::
+:: @t: plain text
+:: %italics: italic text
+:: %bold: bold text
+:: %strike: strikethrough text
+:: %blockquote: blockquote surrounded content
+:: %inline-code: code formatting for small snippets
+:: %ship: a mention of a ship
+:: %block: link/reference to blocks
+:: %code: code formatting for large snippets
+:: %tag: tag gets special signifier
+:: %link: link to a URL with a face
+:: %break: line break
+::
++$ inline
+ $@ @t
+ $% [%italics p=(list inline)]
+ [%bold p=(list inline)]
+ [%strike p=(list inline)]
+ [%blockquote p=(list inline)]
+ [%inline-code p=cord]
+ [%ship p=ship]
+ [%block p=@ud q=cord]
+ [%code p=cord]
+ [%tag p=cord]
+ [%link p=cord q=cord]
+ [%break ~]
+ ==
+::
+:: $memo: a chat message with metadata
+::
+:: replying: what message we're replying to
+:: author: writer of the message
+:: sent: time (from sender) when the message was sent
+:: content: body of the message
+::
++$ memo
+ $: replying=(unit id)
+ author=ship
+ sent=time
+ =content
+ ==
+::
+:: $net: an indicator of whether I'm a host or subscriber
+::
+:: %load: iniating chat join
+:: %pub: am publisher/host with fresh log
+:: %sub: subscribed to the ship
+::
++$ net
+ $% [%sub host=ship load=_| =saga:e]
+ [%pub ~]
+ ==
+::
+:: $action: the complete set of data required to edit a chat
+::
++$ action
+ (pair flag update)
+::
+:: $update: a representation in time of a modification of a chat
+::
++$ update
+ (pair time diff)
+::
+:: $logs: a time ordered map of all modifications to groups
+::
++$ logs
+ ((mop time diff) lte)
+::
+:: $perm: represents the permissions for a channel and gives a pointer
+:: back to the group it belongs to.
+::
++$ perm
+ $: writers=(set sect:g)
+ group=flag:g
+ ==
+:: $join: a group + channel flag to join a channel, group required for perms
+::
++$ join
+ $: group=flag:g
+ chan=flag:g
+ ==
+:: $leave: a flag to pass for a channel leave
+::
++$ leave flag:g
+::
+:: $create: represents a request to create a channel
+::
+:: The name will be used as part of the flag which represents the
+:: channel. $create is consumed by the chat agent first
+:: and then passed to the groups agent to register the channel with
+:: the group.
+::
+:: Write permission is stored with the specific agent in the channel,
+:: read permission is stored with the group's data.
+::
++$ create
+ $: group=flag:g
+ name=term
+ title=cord
+ description=cord
+ readers=(set sect:g)
+ writers=(set sect:g)
+ ==
+++ met metadata-store
+--
diff --git a/desk/sur/chat.hoon b/desk/sur/chat.hoon
index d2e8963f..9aa1d147 100644
--- a/desk/sur/chat.hoon
+++ b/desk/sur/chat.hoon
@@ -1,107 +1,144 @@
-/- g=groups, uno=chat-1, zer=chat-0
+/- g=groups, d=channels, dos=chat-2, uno=chat-1, zer=chat-0
/- meta
-/- cite
-/- e=epic
|%
++ old
|%
++ zero zer
- ++ one uno
- --
-:: +mar: mark name
-++ okay `epic:e`0
-++ mar
- |%
- ++ act `mark`(rap 3 %chat-action '-' (scot %ud okay) ~)
- ++ upd `mark`(rap 3 %chat-update '-' (scot %ud okay) ~)
- ++ log `mark`(rap 3 %chat-logs '-' (scot %ud okay) ~)
+ ++ one uno
+ ++ two dos
--
::
-:: $scan: search results
-+$ scan (list (pair time writ))
-:: $writ: a chat message
-+$ writ [seal memo]
:: $id: an identifier for chat messages
+$ id (pair ship time)
-:: $feel: either an emoji identifier like :wave: or a URL for custom
-+$ feel @ta
-+$ said (pair flag writ)
+:: $writ: a chat message
++$ writ [seal essay]
+:: $reply: a chat reply
++$ reply [reply-seal memo:d]
+:: $react: either an emoji identifier like :wave: or a URL for custom
++$ react @ta
+:: $scan: search results
++$ scan (list reference)
+:: $blocked: a set of ships that the user has blocked
++$ blocked (set ship)
++$ blocked-by (set ship)
++$ hidden-messages (set id)
++$ message-toggle
+ $% [%hide =id]
+ [%show =id]
+ ==
++$ reference
+ $% [%writ =writ]
+ [%reply =id =reply]
+ ==
::
:: $seal: the id of a chat and its meta-responses
::
-:: id: the id of the message
-:: feels: reactions to a message
-:: replied: set of replies to a message
+:: id: the id of the message
+:: time: the time the message was received
+:: replies: set of replies to a message
+:: reacts: reactions to a message
::
+$ seal
$: =id
- feels=(map ship feel)
- replied=(set id)
+ time=id-post:d
+ =reacts
+ =replies
+ meta=reply-meta
+ ==
++$ reply-meta
+ $: reply-count=@ud
+ last-repliers=(set ship)
+ last-reply=(unit time)
==
::
-:: $whom: a polymorphic identifier for chats
-::
-+$ whom
- $% [%flag p=flag]
- [%ship p=ship]
- [%club p=id:club]
- ==
+:: $reply-seal: chat reply metadata
++$ reply-seal
+ $: =id
+ parent-id=id
+ time=id-post:d
+ =reacts
+ ==
::
-:: $briefs: a map of chat/club/dm unread information
+:: $essay: a chat message with metadata
++$ essay [memo:d %chat =kind]
+:: $kind: whether or not the chat is a system message
++$ kind $@(~ [%notice ~])
+:: $reacts: a set of reactions to a chat message
++$ reacts (map ship react)
::
-:: brief: the last time a message was read, how many messages since,
-:: and the id of the last read message
+:: $pact: a double indexed map of chat messages, id -> time -> message
::
-++ briefs
- =< briefs
- |%
- +$ briefs
- (map whom brief)
- +$ brief
- [last=time count=@ud read-id=(unit id)]
- +$ update
- (pair whom brief)
- --
++$ pact
+ $: wit=writs
+ dex=index
+ ==
::
-+$ remark-action
- (pair whom remark-diff)
+:: $paged-writs: a set of time ordered chat messages, with page cursors
::
-+$ remark-diff
- $% [%read ~]
- [%read-at p=time]
- [?(%watch %unwatch) ~]
++$ paged-writs
+ $: =writs
+ newer=(unit id)
+ older=(unit id)
+ total=@ud
==
::
-:: $flag: an identifier for a $chat channel
+:: $writs: a set of time ordered chat messages
::
-+$ flag (pair ship term)
+++ writs
+ =< writs
+ |%
+ +$ writs
+ ((mop time writ) lte)
+ ++ on
+ ((^on time writ) lte)
+ +$ diff
+ (pair id delta)
+ +$ delta
+ :: time and meta are units because we won't have it when we send,
+ :: but we need it upon receipt
+ $% [%add =memo:d =kind time=(unit time)]
+ [%del ~]
+ [%reply =id meta=(unit reply-meta) =delta:replies]
+ [%add-react =ship =react]
+ [%del-react =ship]
+ ==
+ +$ response [=id response=response-delta]
+ +$ response-delta
+ $% [%add =memo:d =time]
+ [%del ~]
+ [%reply =id meta=(unit reply-meta) delta=response-delta:replies]
+ [%add-react =ship =react]
+ [%del-react =ship]
+ ==
+ --
::
-:: $diff: represents an update to state
+:: $replies: a set of time ordered chat replies
::
-:: %writs: a chat message update
-:: %add-sects: add sects to writer permissions
-:: %del-sects: delete sects from writers
-:: %create: create a new chat
+++ replies
+ =< replies
+ |%
+ +$ replies
+ ((mop time reply) lte)
+ ++ on
+ ((^on time reply) lte)
+ +$ delta
+ $% [%add =memo:d time=(unit time)]
+ [%del ~]
+ [%add-react =ship =react]
+ [%del-react =ship]
+ ==
+ +$ response-delta
+ $% [%add =memo:d =time]
+ [%del ~]
+ [%add-react =ship =react]
+ [%del-react =ship]
+ ==
+ --
::
-+$ diff
- $% [%writs p=diff:writs]
- ::
- [%add-sects p=(set sect:g)]
- [%del-sects p=(set sect:g)]
- ::
- [%create p=perm q=pact]
- ==
:: $index: a map of chat message id to server received message time
::
+$ index (map id time)
::
-:: $pact: a double indexed map of chat messages, id -> time -> message
-::
-+$ pact
- $: wit=writs
- dex=index
- ==
-::
:: $club: a direct line of communication between multiple parties
::
:: uses gossip to ensure all parties keep in sync
@@ -151,7 +188,7 @@
::
+$ diff (pair uid delta)
::
- +$ delta
+ +$ delta
$% [%writ =diff:writs]
[%meta meta=data:meta]
[%team =ship ok=?]
@@ -162,25 +199,6 @@
+$ action (pair id diff)
--
::
-:: $writs: a set of time ordered chat messages
-::
-++ writs
- =< writs
- |%
- +$ writs
- ((mop time writ) lte)
- ++ on
- ((^on time writ) lte)
- +$ diff
- (pair id delta)
- +$ delta
- $% [%add p=memo]
- [%del ~]
- [%add-feel p=ship q=feel]
- [%del-feel p=ship]
- ==
- --
-::
:: $dm: a direct line of communication between two ships
::
:: net: status of dm
@@ -197,163 +215,49 @@
=net
pin=_|
==
- +$ net ?(%inviting %invited %archive %done)
- +$ id (pair ship time)
- +$ diff diff:writs
- +$ action (pair ship diff)
- +$ rsvp [=ship ok=?]
+ +$ net ?(%inviting %invited %archive %done)
+ +$ id (pair ship time)
+ +$ diff diff:writs
+ +$ action (pair ship diff)
+ +$ rsvp [=ship ok=?]
--
::
-:: $log: a time ordered map of all modifications to chats
-::
-+$ log
- ((mop time diff) lte)
-++ log-on
- ((on time diff) lte)
-+$ remark
- [last-read=time watching=_| ~]
-::
-:: $chat: a group based channel for communicating
-::
-+$ chat
- [=net =remark =log =perm =pact]
-::
-:: $notice: the contents of an automated message
-::
-:: pfix: text preceding ship name
-:: sfix: text following ship name
-::
-+$ notice [pfix=@t sfix=@t]
-::
-:: $content: the contents of a message whether handwritten or automated
-::
-+$ content
- $% [%story p=story]
- [%notice p=notice]
- ==
-::
-:: $draft: the contents of an unsent message at a particular $whom
-::
-+$ draft
- (pair whom story)
-::
-:: $story: handwritten contents of a message
-::
-:: blocks precede inline content
-::
-+$ story
- (pair (list block) (list inline))
-::
-:: $block: content which stands on it's own outside of inline content
-::
-+$ block
- $% [%image src=cord height=@ud width=@ud alt=cord]
- [%cite =cite]
- ==
-::
-:: $inline: a representation of text with or without formatting
-::
-:: @t: plain text
-:: %italics: italic text
-:: %bold: bold text
-:: %strike: strikethrough text
-:: %blockquote: blockquote surrounded content
-:: %inline-code: code formatting for small snippets
-:: %ship: a mention of a ship
-:: %block: link/reference to blocks
-:: %code: code formatting for large snippets
-:: %tag: tag gets special signifier
-:: %link: link to a URL with a face
-:: %break: line break
-::
-+$ inline
- $@ @t
- $% [%italics p=(list inline)]
- [%bold p=(list inline)]
- [%strike p=(list inline)]
- [%blockquote p=(list inline)]
- [%inline-code p=cord]
- [%ship p=ship]
- [%block p=@ud q=cord]
- [%code p=cord]
- [%tag p=cord]
- [%link p=cord q=cord]
- [%break ~]
- ==
-::
-:: $memo: a chat message with metadata
-::
-:: replying: what message we're replying to
-:: author: writer of the message
-:: sent: time (from sender) when the message was sent
-:: content: body of the message
-::
-+$ memo
- $: replying=(unit id)
- author=ship
- sent=time
- =content
- ==
-::
-:: $net: an indicator of whether I'm a host or subscriber
-::
-:: %load: iniating chat join
-:: %pub: am publisher/host with fresh log
-:: %sub: subscribed to the ship
+:: $whom: a polymorphic identifier for chats
::
-+$ net
- $% [%sub host=ship load=_| =saga:e]
- [%pub ~]
++$ whom
+ $% [%ship p=ship]
+ [%club p=id:club]
==
::
-:: $action: the complete set of data required to edit a chat
-::
-+$ action
- (pair flag update)
-::
-:: $update: a representation in time of a modification of a chat
-::
-+$ update
- (pair time diff)
-::
-:: $logs: a time ordered map of all modifications to groups
+:: $unreads: a map of club/dm unread information
::
-+$ logs
- ((mop time diff) lte)
-::
-:: $perm: represents the permissions for a channel and gives a pointer
-:: back to the group it belongs to.
-::
-+$ perm
- $: writers=(set sect:g)
- group=flag:g
- ==
-:: $join: a group + channel flag to join a channel, group required for perms
+:: unread: the last time a message was read, how many messages since,
+:: and the id of the last read message
::
-+$ join
- $: group=flag:g
- chan=flag:g
- ==
-:: $leave: a flag to pass for a channel leave
+++ unreads
+ =< unreads
+ |%
+ +$ unreads
+ (map whom unread)
+ +$ unread
+ $: recency=time
+ count=@ud
+ unread-id=(unit id)
+ threads=(map id id)
+ ==
+ +$ update
+ (pair whom unread)
+ --
::
-+$ leave flag:g
++$ remark
+ [recency=time last-read=time watching=_| unread-threads=(set id)]
::
-:: $create: represents a request to create a channel
-::
-:: The name will be used as part of the flag which represents the
-:: channel. $create is consumed by the chat agent first
-:: and then passed to the groups agent to register the channel with
-:: the group.
-::
-:: Write permission is stored with the specific agent in the channel,
-:: read permission is stored with the group's data.
++$ remark-action
+ (pair whom remark-diff)
::
-+$ create
- $: group=flag:g
- name=term
- title=cord
- description=cord
- readers=(set sect:g)
- writers=(set sect:g)
++$ remark-diff
+ $% [%read ~]
+ [%read-at p=time]
+ [?(%watch %unwatch) ~]
==
--