mirror of
https://github.com/urbit/shrub.git
synced 2024-12-23 19:05:48 +03:00
Merge branch 'master' into release/next-vere
This commit is contained in:
commit
effdd30d54
@ -30,7 +30,7 @@ If applicable, add screenshots to help explain your problem.
|
|||||||
**System (please supply the following information, if relevant):**
|
**System (please supply the following information, if relevant):**
|
||||||
- OS: [e.g. macOS, linux64, FreeBSD]
|
- OS: [e.g. macOS, linux64, FreeBSD]
|
||||||
- Vere and Urbit OS versions
|
- Vere and Urbit OS versions
|
||||||
- Your ship's `%base` hash (use `.^(@uv %cz /=base=)` to check)
|
- Your ship's `%base` hash (use `+trouble` to check)
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
4
.github/ISSUE_TEMPLATE/os1-bug-report.md
vendored
4
.github/ISSUE_TEMPLATE/os1-bug-report.md
vendored
@ -27,13 +27,13 @@ If applicable, add screenshots to help explain your problem. If possible, please
|
|||||||
**Desktop (please complete the following information):**
|
**Desktop (please complete the following information):**
|
||||||
- OS: [e.g. MacOS 10.15.3]
|
- OS: [e.g. MacOS 10.15.3]
|
||||||
- Browser [e.g. chrome, safari]
|
- Browser [e.g. chrome, safari]
|
||||||
- Base hash of your urbit ship. Run ` .^(@uv %cz /=base=)` in Dojo to see this.
|
- Base hash of your urbit ship. Run `+trouble` in Dojo to see this.
|
||||||
|
|
||||||
**Smartphone (please complete the following information):**
|
**Smartphone (please complete the following information):**
|
||||||
- Device: [e.g. iPhone6]
|
- Device: [e.g. iPhone6]
|
||||||
- OS: [e.g. iOS8.1]
|
- OS: [e.g. iOS8.1]
|
||||||
- Browser [e.g. stock browser, safari]
|
- Browser [e.g. stock browser, safari]
|
||||||
- Base hash of your urbit ship. Run ` .^(@uv %cz /=base=)` in Dojo to see this.
|
- Base hash of your urbit ship. Run `+trouble` in Dojo to see this.
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:ecf3f8593815742e409008421f318b664124e672b1eecd131e4a1e49864a1c2a
|
oid sha256:d7088528dbfd54a913921ade093251d678c4ccebfd0ad85ef2022520266b3954
|
||||||
size 6175676
|
size 16451173
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
+$ glyph char
|
+$ glyph char
|
||||||
++ glyphs "!@#$%^&()-=_+[]\{}'\\:\",.<>?"
|
++ glyphs "!@#$%^&()-=_+[]\{}'\\:\",.<>?"
|
||||||
::
|
::
|
||||||
+$ nu-security ?(%channel %village %village-with-group)
|
+$ nu-security ?(%channel %village)
|
||||||
::
|
::
|
||||||
+$ command
|
+$ command
|
||||||
$% [%target (set target)] :: set messaging target
|
$% [%target (set target)] :: set messaging target
|
||||||
@ -81,7 +81,7 @@
|
|||||||
::
|
::
|
||||||
::
|
::
|
||||||
:: create chat
|
:: create chat
|
||||||
[%create nu-security path (unit glyph) (unit ?)]
|
[%create nu-security path (unit resource) (unit glyph) (unit ?)]
|
||||||
[%delete path] :: delete chat
|
[%delete path] :: delete chat
|
||||||
[%invite [? path] (set ship)] :: allow
|
[%invite [? path] (set ship)] :: allow
|
||||||
[%banish [? path] (set ship)] :: disallow
|
[%banish [? path] (set ship)] :: disallow
|
||||||
@ -293,8 +293,6 @@
|
|||||||
::
|
::
|
||||||
++ target-to-path
|
++ target-to-path
|
||||||
|= target
|
|= target
|
||||||
%+ weld
|
|
||||||
?:(in-group ~ /~)
|
|
||||||
[(scot %p ship) path]
|
[(scot %p ship) path]
|
||||||
:: +path-to-target: deduces a target from a mailbox path
|
:: +path-to-target: deduces a target from a mailbox path
|
||||||
::
|
::
|
||||||
@ -464,6 +462,7 @@
|
|||||||
security
|
security
|
||||||
;~ plug
|
;~ plug
|
||||||
path
|
path
|
||||||
|
(punt ;~(pfix ace group))
|
||||||
(punt ;~(pfix ace glyph))
|
(punt ;~(pfix ace glyph))
|
||||||
(punt ;~(pfix ace (fuss 'y' 'n')))
|
(punt ;~(pfix ace (fuss 'y' 'n')))
|
||||||
==
|
==
|
||||||
@ -535,16 +534,15 @@
|
|||||||
:: ;~(pfix ace ;~(plug i.opt $(opt t.opt)))
|
:: ;~(pfix ace ;~(plug i.opt $(opt t.opt)))
|
||||||
:: --
|
:: --
|
||||||
::
|
::
|
||||||
|
++ group ;~((glue net) ship sym)
|
||||||
++ tag |*(a=@tas (cold a (jest a))) ::TODO into stdlib
|
++ tag |*(a=@tas (cold a (jest a))) ::TODO into stdlib
|
||||||
++ ship ;~(pfix sig fed:ag)
|
++ ship ;~(pfix sig fed:ag)
|
||||||
++ path ;~(pfix net ;~(plug urs:ab (easy ~))) ::NOTE short only, tmp
|
++ path ;~(pfix net ;~(plug urs:ab (easy ~))) ::NOTE short only, tmp
|
||||||
:: +mang: un/managed indicator prefix
|
:: +mang: un/managed indicator prefix
|
||||||
::
|
::
|
||||||
++ mang
|
:: deprecated, as sig prefix is no longer used
|
||||||
;~ pose
|
::
|
||||||
(cold %| (jest '~/'))
|
++ mang (cold %& (easy ~))
|
||||||
(cold %& (easy ~))
|
|
||||||
==
|
|
||||||
:: +tarl: local target, as /path
|
:: +tarl: local target, as /path
|
||||||
::
|
::
|
||||||
++ tarl (stag our-self path)
|
++ tarl (stag our-self path)
|
||||||
@ -585,7 +583,7 @@
|
|||||||
:: +security: security mode
|
:: +security: security mode
|
||||||
::
|
::
|
||||||
++ security
|
++ security
|
||||||
(perk %channel %village-with-group %village ~)
|
(perk %channel %village ~)
|
||||||
::
|
::
|
||||||
:: +glyph: shorthand character
|
:: +glyph: shorthand character
|
||||||
::
|
::
|
||||||
@ -741,15 +739,21 @@
|
|||||||
:: +create: new local mailbox
|
:: +create: new local mailbox
|
||||||
::
|
::
|
||||||
++ create
|
++ create
|
||||||
|= [security=nu-security =path gyf=(unit char) allow-history=(unit ?)]
|
|= $: security=nu-security
|
||||||
|
=path
|
||||||
|
ugroup=(unit resource)
|
||||||
|
gyf=(unit char)
|
||||||
|
allow-history=(unit ?)
|
||||||
|
==
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
=/ with-group=? ?=(%village-with-group security)
|
=/ with-group=? ?=(^ ugroup)
|
||||||
=/ =target [with-group our-self path]
|
=/ =target [with-group our-self path]
|
||||||
=/ real-path=^path (target-to-path target)
|
=/ real-path=^path (target-to-path target)
|
||||||
|
=/ group-path=^path ?~(ugroup ship+real-path (en-path:resource u.ugroup))
|
||||||
=/ =policy
|
=/ =policy
|
||||||
?- security
|
?- security
|
||||||
%channel *open:policy
|
%channel *open:policy
|
||||||
?(%village %village-with-group) *invite:policy
|
%village *invite:policy
|
||||||
==
|
==
|
||||||
?^ (scry-for (unit mailbox:store) %chat-store [%mailbox real-path])
|
?^ (scry-for (unit mailbox:store) %chat-store [%mailbox real-path])
|
||||||
=- [[- ~] state]
|
=- [[- ~] state]
|
||||||
@ -767,7 +771,7 @@
|
|||||||
(rsh 3 1 (spat path))
|
(rsh 3 1 (spat path))
|
||||||
''
|
''
|
||||||
real-path :: chat
|
real-path :: chat
|
||||||
real-path :: group
|
group-path :: group
|
||||||
policy
|
policy
|
||||||
~
|
~
|
||||||
(fall allow-history %.y)
|
(fall allow-history %.y)
|
||||||
|
@ -18,17 +18,19 @@
|
|||||||
state-1
|
state-1
|
||||||
state-2
|
state-2
|
||||||
state-3
|
state-3
|
||||||
|
state-4
|
||||||
|
state-5
|
||||||
|
state-6
|
||||||
|
state-7
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
+$ state-3
|
+$ state-7 [%7 state-base]
|
||||||
$: %3
|
+$ state-6 [%6 state-base]
|
||||||
state-base
|
+$ state-5 [%5 state-base]
|
||||||
==
|
+$ state-4 [%4 state-base]
|
||||||
|
+$ state-3 [%3 state-base]
|
||||||
|
+$ state-2 [%2 state-base]
|
||||||
::
|
::
|
||||||
+$ state-2
|
|
||||||
$: %2
|
|
||||||
state-base
|
|
||||||
==
|
|
||||||
+$ state-1
|
+$ state-1
|
||||||
$: %1
|
$: %1
|
||||||
loaded-cards=*
|
loaded-cards=*
|
||||||
@ -52,7 +54,7 @@
|
|||||||
$% [%chat-update update:store]
|
$% [%chat-update update:store]
|
||||||
==
|
==
|
||||||
--
|
--
|
||||||
=| state-3
|
=| state-7
|
||||||
=* state -
|
=* state -
|
||||||
::
|
::
|
||||||
%- agent:dbug
|
%- agent:dbug
|
||||||
@ -81,8 +83,20 @@
|
|||||||
=/ old !<(versioned-state old-vase)
|
=/ old !<(versioned-state old-vase)
|
||||||
=| cards=(list card)
|
=| cards=(list card)
|
||||||
|-
|
|-
|
||||||
?: ?=(%3 -.old)
|
?: ?=(%7 -.old)
|
||||||
[cards this(state old)]
|
[cards this(state old)]
|
||||||
|
?: ?=(%6 -.old)
|
||||||
|
=. cards
|
||||||
|
%+ weld cards
|
||||||
|
^- (list card)
|
||||||
|
[%pass /s %agent [our.bol %chat-hook] %poke %noun !>(%fix-out-of-sync)]~
|
||||||
|
$(-.old %7)
|
||||||
|
?: ?=(?(%3 %4 %5) -.old)
|
||||||
|
=. cards
|
||||||
|
%+ weld cards
|
||||||
|
^- (list card)
|
||||||
|
[%pass /pokeme %agent [our.bol %chat-hook] %poke %noun !>(%fix-dm)]~
|
||||||
|
$(-.old %6)
|
||||||
?: ?=(%2 -.old)
|
?: ?=(%2 -.old)
|
||||||
=. cards
|
=. cards
|
||||||
%+ weld cards
|
%+ weld cards
|
||||||
@ -319,9 +333,9 @@
|
|||||||
^- (quip card _this)
|
^- (quip card _this)
|
||||||
=^ cards state
|
=^ cards state
|
||||||
?+ mark (on-poke:def mark vase)
|
?+ mark (on-poke:def mark vase)
|
||||||
%json (poke-json:cc !<(json vase))
|
%json (poke-json:cc !<(json vase))
|
||||||
%chat-action (poke-chat-action:cc !<(action:store vase))
|
%chat-action (poke-chat-action:cc !<(action:store vase))
|
||||||
%noun [~ state]
|
%noun (poke-noun:cc !<(?(%fix-dm %fix-out-of-sync) vase))
|
||||||
::
|
::
|
||||||
%chat-hook-action
|
%chat-hook-action
|
||||||
(poke-chat-hook-action:cc !<(action:hook vase))
|
(poke-chat-hook-action:cc !<(action:hook vase))
|
||||||
@ -383,6 +397,81 @@
|
|||||||
|_ bol=bowl:gall
|
|_ bol=bowl:gall
|
||||||
++ grp ~(. grpl bol)
|
++ grp ~(. grpl bol)
|
||||||
::
|
::
|
||||||
|
++ poke-noun
|
||||||
|
|= a=?(%fix-dm %fix-out-of-sync)
|
||||||
|
^- (quip card _state)
|
||||||
|
|^
|
||||||
|
:_ state
|
||||||
|
?- a
|
||||||
|
%fix-dm (fix-dm %fix-dm)
|
||||||
|
%fix-out-of-sync (fix-out-of-sync %fix-out-of-sync)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ fix-out-of-sync
|
||||||
|
|= b=%fix-out-of-sync
|
||||||
|
^- (list card)
|
||||||
|
%- zing
|
||||||
|
%+ turn ~(tap by synced)
|
||||||
|
|= [=path host=ship]
|
||||||
|
^- (list card)
|
||||||
|
?: =(host our.bol) ~
|
||||||
|
?> ?=([@ @ ~] path)
|
||||||
|
=/ =ship (slav %p i.path)
|
||||||
|
:~ =- [%pass / %agent [our.bol %chat-hook] %poke %chat-hook-action -]
|
||||||
|
!> ^- action:hook
|
||||||
|
[%remove path]
|
||||||
|
::
|
||||||
|
=- [%pass / %agent [our.bol %chat-hook] %poke %chat-hook-action -]
|
||||||
|
!> ^- action:hook
|
||||||
|
[%add-synced ship path %.y]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ fix-dm
|
||||||
|
|= b=%fix-dm
|
||||||
|
^- (list card)
|
||||||
|
%- zing
|
||||||
|
%+ turn
|
||||||
|
~(tap by synced)
|
||||||
|
|= [=path host=ship]
|
||||||
|
^- (list card)
|
||||||
|
?> ?=([@ @ *] path)
|
||||||
|
=/ =ship (slav %p i.path)
|
||||||
|
?: =(ship our.bol)
|
||||||
|
:: local dm, no need to do cleanup
|
||||||
|
~
|
||||||
|
?: ?=(^ (groups-of-chat path))
|
||||||
|
:: correctly initialized, no need to do cleanup
|
||||||
|
::
|
||||||
|
~
|
||||||
|
?. =((end 3 4 i.t.path) 'dm--')
|
||||||
|
~
|
||||||
|
:- =- [%pass /fixdm %agent [our.bol %chat-view] %poke %chat-view-action -]
|
||||||
|
!> ^- action:view
|
||||||
|
[%delete path]
|
||||||
|
=/ new-dm /(scot %p our.bol)/(crip (weld "dm--" (trip (scot %p ship))))
|
||||||
|
=/ mailbox=(unit mailbox:store) (chat-scry path)
|
||||||
|
?~ mailbox
|
||||||
|
~
|
||||||
|
:~ =- [%pass /fixdm %agent [our.bol %chat-view] %poke %chat-view-action -]
|
||||||
|
!> ^- action:view
|
||||||
|
:* %create
|
||||||
|
%- crip
|
||||||
|
(zing [(trip (scot %p our.bol)) " <-> " (trip (scot %p ship)) ~])
|
||||||
|
''
|
||||||
|
new-dm
|
||||||
|
ship+new-dm
|
||||||
|
[%invite (silt ~[ship])]
|
||||||
|
(silt ~[ship])
|
||||||
|
%.y
|
||||||
|
%.n
|
||||||
|
==
|
||||||
|
::
|
||||||
|
=- [%pass /fixdm %agent [our.bol %chat-store] %poke %chat-action -]
|
||||||
|
!> ^- action:store
|
||||||
|
[%messages new-dm envelopes.u.mailbox]
|
||||||
|
==
|
||||||
|
--
|
||||||
|
::
|
||||||
++ poke-json
|
++ poke-json
|
||||||
|= jon=json
|
|= jon=json
|
||||||
^- (quip card _state)
|
^- (quip card _state)
|
||||||
|
@ -269,7 +269,7 @@
|
|||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ on-leave on-leave:def
|
++ on-leave on-leave:def
|
||||||
++ on-peek
|
++ on-peek
|
||||||
|= =path
|
|= =path
|
||||||
^- (unit (unit cage))
|
^- (unit (unit cage))
|
||||||
|^
|
|^
|
||||||
@ -287,10 +287,9 @@
|
|||||||
*@uv
|
*@uv
|
||||||
=/ parent (scot %p ship.u.ota)
|
=/ parent (scot %p ship.u.ota)
|
||||||
=+ .^(=cass:clay %cs /[parent]/[desk.u.ota]/1/late/foo)
|
=+ .^(=cass:clay %cs /[parent]/[desk.u.ota]/1/late/foo)
|
||||||
%^ end 3 3
|
%^ end 0 25
|
||||||
.^(@uv %cz /[parent]/[desk.u.ota]/(scot %ud ud.cass))
|
.^(@uv %cz /[parent]/[desk.u.ota]/(scot %ud ud.cass))
|
||||||
--
|
--
|
||||||
|
|
||||||
++ on-agent on-agent:def
|
++ on-agent on-agent:def
|
||||||
++ on-fail on-fail:def
|
++ on-fail on-fail:def
|
||||||
--
|
--
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/- glob
|
/- glob
|
||||||
/+ default-agent, verb, dbug
|
/+ default-agent, verb, dbug
|
||||||
|%
|
|%
|
||||||
++ hash 0v5.knd3c.vvtvt.h0gg0.8qcau.8iii4
|
++ hash 0v3.cus8h.vc64c.rfb3t.22oji.b529a
|
||||||
+$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))]
|
+$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))]
|
||||||
+$ all-states
|
+$ all-states
|
||||||
$% state-0
|
$% state-0
|
||||||
@ -58,7 +58,6 @@
|
|||||||
++ on-load
|
++ on-load
|
||||||
|= old-state=vase
|
|= old-state=vase
|
||||||
^- (quip card _this)
|
^- (quip card _this)
|
||||||
~& > %initting
|
|
||||||
=+ !<(old=all-states old-state)
|
=+ !<(old=all-states old-state)
|
||||||
?> ?=(%0 -.old)
|
?> ?=(%0 -.old)
|
||||||
?~ glob.old
|
?~ glob.old
|
||||||
|
572
pkg/arvo/app/graph-store.hoon
Normal file
572
pkg/arvo/app/graph-store.hoon
Normal file
@ -0,0 +1,572 @@
|
|||||||
|
/+ store=graph-store, sigs=signatures, res=resource, default-agent, dbug
|
||||||
|
~% %graph-store-top ..is ~
|
||||||
|
|%
|
||||||
|
+$ card card:agent:gall
|
||||||
|
+$ versioned-state
|
||||||
|
$% state-0
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ state-0 [%0 network:store]
|
||||||
|
++ orm orm:store
|
||||||
|
++ orm-log orm-log:store
|
||||||
|
--
|
||||||
|
::
|
||||||
|
=| state-0
|
||||||
|
=* state -
|
||||||
|
::
|
||||||
|
%- agent:dbug
|
||||||
|
^- agent:gall
|
||||||
|
~% %graph-store-agent ..card ~
|
||||||
|
|_ =bowl:gall
|
||||||
|
+* this .
|
||||||
|
def ~(. (default-agent this %|) bowl)
|
||||||
|
::
|
||||||
|
++ on-init [~ this]
|
||||||
|
++ on-save !>(state)
|
||||||
|
++ on-load
|
||||||
|
|= old=vase
|
||||||
|
^- (quip card _this)
|
||||||
|
[~ this(state !<(state-0 old))]
|
||||||
|
::
|
||||||
|
++ on-watch
|
||||||
|
~/ %graph-store-watch
|
||||||
|
|= =path
|
||||||
|
^- (quip card _this)
|
||||||
|
|^
|
||||||
|
?> (team:title our.bowl src.bowl)
|
||||||
|
=/ cards=(list card)
|
||||||
|
?+ path (on-watch:def path)
|
||||||
|
[%updates ~] ~
|
||||||
|
[%keys ~] (give [%keys ~(key by graphs)])
|
||||||
|
[%tags ~] (give [%tags ~(key by tag-queries)])
|
||||||
|
==
|
||||||
|
[cards this]
|
||||||
|
::
|
||||||
|
++ give
|
||||||
|
|= =update-0:store
|
||||||
|
^- (list card)
|
||||||
|
[%give %fact ~ [%graph-update !>([%0 now.bowl update-0])]]~
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ on-poke
|
||||||
|
~/ %graph-store-poke
|
||||||
|
|= [=mark =vase]
|
||||||
|
^- (quip card _this)
|
||||||
|
|^
|
||||||
|
?> (team:title our.bowl src.bowl)
|
||||||
|
=^ cards state
|
||||||
|
?+ mark (on-poke:def mark vase)
|
||||||
|
%graph-update (graph-update !<(update:store vase))
|
||||||
|
==
|
||||||
|
[cards this]
|
||||||
|
::
|
||||||
|
++ graph-update
|
||||||
|
|= =update:store
|
||||||
|
^- (quip card _state)
|
||||||
|
|^
|
||||||
|
?> ?=(%0 -.update)
|
||||||
|
?- -.q.update
|
||||||
|
%add-graph (add-graph +.q.update)
|
||||||
|
%remove-graph (remove-graph +.q.update)
|
||||||
|
%add-nodes (add-nodes p.update +.q.update)
|
||||||
|
%remove-nodes (remove-nodes p.update +.q.update)
|
||||||
|
%add-signatures (add-signatures p.update +.q.update)
|
||||||
|
%remove-signatures (remove-signatures p.update +.q.update)
|
||||||
|
%add-tag (add-tag +.q.update)
|
||||||
|
%remove-tag (remove-tag +.q.update)
|
||||||
|
%archive-graph (archive-graph +.q.update)
|
||||||
|
%unarchive-graph (unarchive-graph +.q.update)
|
||||||
|
%run-updates (run-updates +.q.update)
|
||||||
|
%keys ~|('cannot send %keys as poke' !!)
|
||||||
|
%tags ~|('cannot send %tags as poke' !!)
|
||||||
|
%tag-queries ~|('cannot send %tag-queries as poke' !!)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ add-graph
|
||||||
|
|= [=resource:store =graph:store mark=(unit mark:store)]
|
||||||
|
^- (quip card _state)
|
||||||
|
?< (~(has by archive) resource)
|
||||||
|
?< (~(has by graphs) resource)
|
||||||
|
?> (validate-graph graph mark)
|
||||||
|
:_ %_ state
|
||||||
|
graphs (~(put by graphs) resource [graph mark])
|
||||||
|
update-logs (~(put by update-logs) resource (gas:orm-log ~ ~))
|
||||||
|
validators
|
||||||
|
?~ mark validators
|
||||||
|
(~(put in validators) u.mark)
|
||||||
|
==
|
||||||
|
%- zing
|
||||||
|
:~ (give [/updates /keys ~] [%add-graph resource graph mark])
|
||||||
|
?~ mark ~
|
||||||
|
?: (~(has in validators) u.mark) ~
|
||||||
|
=/ wire (weld /graph (en-path:res resource))
|
||||||
|
=/ =rave:clay [%sing %b [%da now.bowl] /[u.mark]]
|
||||||
|
[%pass wire %arvo %c %warp our.bowl [%home `rave]]~
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ remove-graph
|
||||||
|
|= =resource:store
|
||||||
|
^- (quip card _state)
|
||||||
|
?< (~(has by archive) resource)
|
||||||
|
?> (~(has by graphs) resource)
|
||||||
|
:- (give [/updates /keys ~] [%remove-graph resource])
|
||||||
|
%_ state
|
||||||
|
graphs (~(del by graphs) resource)
|
||||||
|
update-logs (~(del by update-logs) resource)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ add-nodes
|
||||||
|
|= $: =time
|
||||||
|
=resource:store
|
||||||
|
nodes=(map index:store node:store)
|
||||||
|
==
|
||||||
|
^- (quip card _state)
|
||||||
|
|^
|
||||||
|
=/ [=graph:store mark=(unit mark:store)]
|
||||||
|
(~(got by graphs) resource)
|
||||||
|
=/ =update-log:store (~(got by update-logs) resource)
|
||||||
|
=. update-log
|
||||||
|
(put:orm-log update-log time [%0 time [%add-nodes resource nodes]])
|
||||||
|
::
|
||||||
|
:- (give [/updates]~ [%add-nodes resource nodes])
|
||||||
|
%_ state
|
||||||
|
update-logs (~(put by update-logs) resource update-log)
|
||||||
|
graphs
|
||||||
|
%+ ~(put by graphs)
|
||||||
|
resource
|
||||||
|
:_ mark
|
||||||
|
(add-node-list resource graph mark (sort-nodes nodes))
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ sort-nodes
|
||||||
|
|= nodes=(map index:store node:store)
|
||||||
|
^- (list [index:store node:store])
|
||||||
|
%+ sort ~(tap by nodes)
|
||||||
|
|= [p=[=index:store *] q=[=index:store *]]
|
||||||
|
^- ?
|
||||||
|
(lth (lent index.p) (lent index.q))
|
||||||
|
::
|
||||||
|
++ add-node-list
|
||||||
|
|= $: =resource:store
|
||||||
|
=graph:store
|
||||||
|
mark=(unit mark:store)
|
||||||
|
node-list=(list [index:store node:store])
|
||||||
|
==
|
||||||
|
^- graph:store
|
||||||
|
?~ node-list graph
|
||||||
|
=* index -.i.node-list
|
||||||
|
=* node +.i.node-list
|
||||||
|
%_ $
|
||||||
|
node-list t.node-list
|
||||||
|
graph (add-node-at-index graph index node mark)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ add-node-at-index
|
||||||
|
=| parent-hash=(unit hash:store)
|
||||||
|
|= $: =graph:store
|
||||||
|
=index:store
|
||||||
|
=node:store
|
||||||
|
mark=(unit mark:store)
|
||||||
|
==
|
||||||
|
^- graph:store
|
||||||
|
?< ?=(~ index)
|
||||||
|
~| "validation of node failed using mark {<mark>}"
|
||||||
|
?> (validate-graph (gas:orm ~ [i.index node]~) mark)
|
||||||
|
=* atom i.index
|
||||||
|
%^ put:orm
|
||||||
|
graph
|
||||||
|
atom
|
||||||
|
:: add child
|
||||||
|
::
|
||||||
|
?~ t.index
|
||||||
|
=* p post.node
|
||||||
|
=/ =validated-portion:store
|
||||||
|
[parent-hash author.p time-sent.p contents.p]
|
||||||
|
=/ =hash:store `@ux`(sham validated-portion)
|
||||||
|
?~ hash.p node(signatures.post *signatures:store)
|
||||||
|
~| "signatures do not match the calculated hash"
|
||||||
|
?> (are-signatures-valid:sigs signatures.p hash now.bowl)
|
||||||
|
~| "hash of post does not match calculated hash"
|
||||||
|
?> =(hash u.hash.p)
|
||||||
|
node
|
||||||
|
:: recurse children
|
||||||
|
::
|
||||||
|
=/ parent=node:store
|
||||||
|
~| "index does not exist to add a node to!"
|
||||||
|
(need (get:orm graph atom))
|
||||||
|
%_ parent
|
||||||
|
children
|
||||||
|
^- internal-graph:store
|
||||||
|
:- %graph
|
||||||
|
%_ $
|
||||||
|
index t.index
|
||||||
|
parent-hash hash.post.parent
|
||||||
|
graph
|
||||||
|
?: ?=(%graph -.children.parent)
|
||||||
|
p.children.parent
|
||||||
|
(gas:orm ~ ~)
|
||||||
|
==
|
||||||
|
==
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ remove-nodes
|
||||||
|
|= [=time =resource:store indices=(set index:store)]
|
||||||
|
^- (quip card _state)
|
||||||
|
|^
|
||||||
|
=/ [=graph:store mark=(unit mark:store)]
|
||||||
|
(~(got by graphs) resource)
|
||||||
|
=/ =update-log:store (~(got by update-logs) resource)
|
||||||
|
=. update-log
|
||||||
|
(put:orm-log update-log time [%0 time [%remove-nodes resource indices]])
|
||||||
|
::
|
||||||
|
:- (give [/updates]~ [%remove-nodes resource indices])
|
||||||
|
%_ state
|
||||||
|
update-logs (~(put by update-logs) resource update-log)
|
||||||
|
graphs
|
||||||
|
%+ ~(put by graphs)
|
||||||
|
resource
|
||||||
|
[(remove-indices resource graph ~(tap in indices)) mark]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ remove-indices
|
||||||
|
|= [=resource:store =graph:store indices=(list index:store)]
|
||||||
|
^- graph:store
|
||||||
|
?~ indices graph
|
||||||
|
%_ $
|
||||||
|
indices t.indices
|
||||||
|
graph (remove-index graph i.indices)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ remove-index
|
||||||
|
|= [=graph:store =index:store]
|
||||||
|
^- graph:store
|
||||||
|
?~ index graph
|
||||||
|
=* atom i.index
|
||||||
|
:: last index in list
|
||||||
|
::
|
||||||
|
?~ t.index
|
||||||
|
+:`[* graph:store]`(del:orm graph atom)
|
||||||
|
=/ =node:store
|
||||||
|
~| "parent index does not exist to remove a node from!"
|
||||||
|
(need (get:orm graph atom))
|
||||||
|
~| "child index does not exist to remove a node from!"
|
||||||
|
?> ?=(%graph -.children.node)
|
||||||
|
%^ put:orm
|
||||||
|
graph
|
||||||
|
atom
|
||||||
|
node(p.children $(graph p.children.node, index t.index))
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ add-signatures
|
||||||
|
|= [=time =uid:store =signatures:store]
|
||||||
|
^- (quip card _state)
|
||||||
|
|^
|
||||||
|
=* resource resource.uid
|
||||||
|
=/ [=graph:store mark=(unit mark:store)]
|
||||||
|
(~(got by graphs) resource)
|
||||||
|
=/ =update-log:store (~(got by update-logs) resource)
|
||||||
|
=. update-log
|
||||||
|
(put:orm-log update-log time [%0 time [%add-signatures uid signatures]])
|
||||||
|
::
|
||||||
|
:- (give [/updates]~ [%add-signatures uid signatures])
|
||||||
|
%_ state
|
||||||
|
update-logs (~(put by update-logs) resource update-log)
|
||||||
|
graphs
|
||||||
|
%+ ~(put by graphs) resource
|
||||||
|
[(add-at-index graph index.uid signatures) mark]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ add-at-index
|
||||||
|
|= [=graph:store =index:store =signatures:store]
|
||||||
|
^- graph:store
|
||||||
|
?~ index graph
|
||||||
|
=* atom i.index
|
||||||
|
=/ =node:store
|
||||||
|
~| "node does not exist to add signatures to!"
|
||||||
|
(need (get:orm graph atom))
|
||||||
|
:: last index in list
|
||||||
|
::
|
||||||
|
%^ put:orm
|
||||||
|
graph
|
||||||
|
atom
|
||||||
|
?~ t.index
|
||||||
|
~| "cannot add signatures to a node missing a hash"
|
||||||
|
?> ?=(^ hash.post.node)
|
||||||
|
~| "signatures did not match public keys!"
|
||||||
|
?> (are-signatures-valid:sigs signatures u.hash.post.node now.bowl)
|
||||||
|
node(signatures.post (~(uni in signatures) signatures.post.node))
|
||||||
|
~| "child graph does not exist to add signatures to!"
|
||||||
|
?> ?=(%graph -.children.node)
|
||||||
|
node(p.children $(graph p.children.node, index t.index))
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ remove-signatures
|
||||||
|
|= [=time =uid:store =signatures:store]
|
||||||
|
^- (quip card _state)
|
||||||
|
|^
|
||||||
|
=* resource resource.uid
|
||||||
|
=/ [=graph:store mark=(unit mark:store)]
|
||||||
|
(~(got by graphs) resource)
|
||||||
|
=/ =update-log:store (~(got by update-logs) resource)
|
||||||
|
=. update-log
|
||||||
|
%^ put:orm-log update-log
|
||||||
|
time
|
||||||
|
[%0 time [%remove-signatures uid signatures]]
|
||||||
|
::
|
||||||
|
:- (give [/updates]~ [%remove-signatures uid signatures])
|
||||||
|
%_ state
|
||||||
|
update-logs (~(put by update-logs) resource update-log)
|
||||||
|
graphs
|
||||||
|
%+ ~(put by graphs) resource
|
||||||
|
[(remove-at-index graph index.uid signatures) mark]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ remove-at-index
|
||||||
|
|= [=graph:store =index:store =signatures:store]
|
||||||
|
^- graph:store
|
||||||
|
?~ index graph
|
||||||
|
=* atom i.index
|
||||||
|
=/ =node:store
|
||||||
|
~| "node does not exist to add signatures to!"
|
||||||
|
(need (get:orm graph atom))
|
||||||
|
:: last index in list
|
||||||
|
::
|
||||||
|
%^ put:orm
|
||||||
|
graph
|
||||||
|
atom
|
||||||
|
?~ t.index
|
||||||
|
node(signatures.post (~(dif in signatures) signatures.post.node))
|
||||||
|
~| "child graph does not exist to add signatures to!"
|
||||||
|
?> ?=(%graph -.children.node)
|
||||||
|
node(p.children $(graph p.children.node, index t.index))
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ add-tag
|
||||||
|
|= [=term =resource:store]
|
||||||
|
^- (quip card _state)
|
||||||
|
?> (~(has by graphs) resource)
|
||||||
|
:- (give [/updates /tags ~] [%add-tag term resource])
|
||||||
|
%_ state
|
||||||
|
tag-queries (~(put ju tag-queries) term resource)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ remove-tag
|
||||||
|
|= [=term =resource:store]
|
||||||
|
^- (quip card _state)
|
||||||
|
?> (~(has by graphs) resource)
|
||||||
|
:- (give [/updates /tags ~] [%remove-tag term resource])
|
||||||
|
%_ state
|
||||||
|
tag-queries (~(del ju tag-queries) term resource)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ archive-graph
|
||||||
|
|= =resource:store
|
||||||
|
^- (quip card _state)
|
||||||
|
?< (~(has by archive) resource)
|
||||||
|
?> (~(has by graphs) resource)
|
||||||
|
:- (give [/updates /keys /tags ~] [%archive-graph resource])
|
||||||
|
%_ state
|
||||||
|
archive (~(put by archive) resource (~(got by graphs) resource))
|
||||||
|
graphs (~(del by graphs) resource)
|
||||||
|
update-logs (~(del by update-logs) resource)
|
||||||
|
tag-queries
|
||||||
|
%- ~(run by tag-queries)
|
||||||
|
|= =resources:store
|
||||||
|
(~(del in resources) resource)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ unarchive-graph
|
||||||
|
|= =resource:store
|
||||||
|
^- (quip card _state)
|
||||||
|
?> (~(has by archive) resource)
|
||||||
|
?< (~(has by graphs) resource)
|
||||||
|
:- (give [/updates /keys ~] [%unarchive-graph resource])
|
||||||
|
%_ state
|
||||||
|
archive (~(del by archive) resource)
|
||||||
|
graphs (~(put by graphs) resource (~(got by archive) resource))
|
||||||
|
update-logs (~(put by update-logs) resource (gas:orm-log ~ ~))
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ run-updates
|
||||||
|
|= [=resource:store =update-log:store]
|
||||||
|
^- (quip card _state)
|
||||||
|
?< (~(has by archive) resource)
|
||||||
|
?> (~(has by graphs) resource)
|
||||||
|
:_ state
|
||||||
|
%+ turn (tap:orm-log update-log)
|
||||||
|
|= [=time update=logged-update:store]
|
||||||
|
^- card
|
||||||
|
?> ?=(%0 -.update)
|
||||||
|
:* %pass
|
||||||
|
/run-updates/(scot %da time)
|
||||||
|
%agent
|
||||||
|
[our.bowl %graph-store]
|
||||||
|
%poke
|
||||||
|
:- %graph-update
|
||||||
|
!>
|
||||||
|
^- update:store
|
||||||
|
?- -.q.update
|
||||||
|
%add-nodes update(resource.q resource)
|
||||||
|
%remove-nodes update(resource.q resource)
|
||||||
|
%add-signatures update(resource.uid.q resource)
|
||||||
|
%remove-signatures update(resource.uid.q resource)
|
||||||
|
==
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ validate-graph
|
||||||
|
|= [=graph:store mark=(unit mark:store)]
|
||||||
|
^- ?
|
||||||
|
?~ mark %.y
|
||||||
|
?~ graph %.y
|
||||||
|
=/ =dais:clay
|
||||||
|
.^ =dais:clay
|
||||||
|
%cb
|
||||||
|
/(scot %p our.bowl)/[q.byk.bowl]/(scot %da now.bowl)/[u.mark]
|
||||||
|
==
|
||||||
|
%+ roll (tap:orm graph)
|
||||||
|
|= [[=atom =node:store] out=?]
|
||||||
|
?& out
|
||||||
|
=(%& -:(mule |.((vale:dais [atom post.node]))))
|
||||||
|
?- -.children.node
|
||||||
|
%empty %.y
|
||||||
|
%graph ^$(graph p.children.node)
|
||||||
|
==
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ give
|
||||||
|
|= [paths=(list path) update=update-0:store]
|
||||||
|
^- (list card)
|
||||||
|
[%give %fact paths [%graph-update !>([%0 now.bowl update])]]~
|
||||||
|
--
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ on-peek
|
||||||
|
~/ %graph-store-peek
|
||||||
|
|= =path
|
||||||
|
^- (unit (unit cage))
|
||||||
|
|^
|
||||||
|
?> (team:title our.bowl src.bowl)
|
||||||
|
?+ path (on-peek:def path)
|
||||||
|
[%x %keys ~] ``noun+!>(~(key by graphs))
|
||||||
|
[%x %tags ~] ``noun+!>(~(key by tag-queries))
|
||||||
|
[%x %tag-queries ~] ``noun+!>(tag-queries)
|
||||||
|
[%x %graph @ @ ~]
|
||||||
|
=/ =ship (slav %p i.t.t.path)
|
||||||
|
=/ =term i.t.t.t.path
|
||||||
|
=/ result=(unit marked-graph:store)
|
||||||
|
(~(get by graphs) [ship term])
|
||||||
|
?~ result [~ ~]
|
||||||
|
``noun+!>(u.result)
|
||||||
|
::
|
||||||
|
[%x %graph-subset @ @ @ @ ~]
|
||||||
|
=/ =ship (slav %p i.t.t.path)
|
||||||
|
=/ =term i.t.t.t.path
|
||||||
|
=/ start=(unit atom) (rush i.t.t.t.t.path dem:ag)
|
||||||
|
=/ end=(unit atom) (rush i.t.t.t.t.t.path dem:ag)
|
||||||
|
=/ graph=(unit marked-graph:store)
|
||||||
|
(~(get by graphs) [ship term])
|
||||||
|
?~ graph [~ ~]
|
||||||
|
``noun+!>(`graph:store`(subset:orm p.u.graph start end))
|
||||||
|
::
|
||||||
|
[%x %node @ @ @ *]
|
||||||
|
=/ =ship (slav %p i.t.t.path)
|
||||||
|
=/ =term i.t.t.t.path
|
||||||
|
=/ =index:store
|
||||||
|
(turn t.t.t.t.path |=(=cord (slav %ud cord)))
|
||||||
|
=/ node=(unit node:store) (get-node ship term index)
|
||||||
|
?~ node [~ ~]
|
||||||
|
``noun+!>(u.node)
|
||||||
|
::
|
||||||
|
[%x %post @ @ @ *]
|
||||||
|
=/ =ship (slav %p i.t.t.path)
|
||||||
|
=/ =term i.t.t.t.path
|
||||||
|
=/ =index:store
|
||||||
|
(turn t.t.t.t.path |=(=cord (slav %ud cord)))
|
||||||
|
=/ node=(unit node:store) (get-node ship term index)
|
||||||
|
?~ node [~ ~]
|
||||||
|
``noun+!>(post.u.node)
|
||||||
|
::
|
||||||
|
[%x %node-children @ @ @ *]
|
||||||
|
=/ =ship (slav %p i.t.t.path)
|
||||||
|
=/ =term i.t.t.t.path
|
||||||
|
=/ =index:store
|
||||||
|
(turn t.t.t.t.path |=(=cord (slav %ud cord)))
|
||||||
|
=/ node=(unit node:store) (get-node ship term index)
|
||||||
|
?~ node [~ ~]
|
||||||
|
?- -.children.u.node
|
||||||
|
%empty [~ ~]
|
||||||
|
%graph ``noun+!>(p.children.u.node)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
[%x %node-children-subset @ @ @ @ @ *]
|
||||||
|
=/ =ship (slav %p i.t.t.path)
|
||||||
|
=/ =term i.t.t.t.path
|
||||||
|
=/ start=(unit atom) (rush i.t.t.t.t.path dem:ag)
|
||||||
|
=/ end=(unit atom) (rush i.t.t.t.t.t.path dem:ag)
|
||||||
|
=/ =index:store
|
||||||
|
(turn t.t.t.t.t.t.path |=(=cord (slav %ud cord)))
|
||||||
|
=/ node=(unit node:store) (get-node ship term index)
|
||||||
|
?~ node [~ ~]
|
||||||
|
?- -.children.u.node
|
||||||
|
%empty [~ ~]
|
||||||
|
%graph ``noun+!>(`graph:store`(subset:orm p.children.u.node start end))
|
||||||
|
==
|
||||||
|
::
|
||||||
|
[%x %update-log @ @ ~]
|
||||||
|
=/ =ship (slav %p i.t.t.path)
|
||||||
|
=/ =term i.t.t.t.path
|
||||||
|
=/ update-log=(unit update-log:store) (~(get by update-logs) [ship term])
|
||||||
|
?~ update-log [~ ~]
|
||||||
|
``noun+!>(u.update-log)
|
||||||
|
::
|
||||||
|
[%x %peek-update-log @ @ ~]
|
||||||
|
=/ =ship (slav %p i.t.t.path)
|
||||||
|
=/ =term i.t.t.t.path
|
||||||
|
=/ update-log=(unit update-log:store) (~(get by update-logs) [ship term])
|
||||||
|
?~ update-log [~ ~]
|
||||||
|
=/ result=(unit [time update:store])
|
||||||
|
(peek:orm-log:store u.update-log)
|
||||||
|
?~ result [~ ~]
|
||||||
|
``noun+!>([~ -.u.result])
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ get-node
|
||||||
|
|= [=ship =term =index:store]
|
||||||
|
^- (unit node:store)
|
||||||
|
=/ parent-graph=(unit marked-graph:store)
|
||||||
|
(~(get by graphs) [ship term])
|
||||||
|
?~ parent-graph ~
|
||||||
|
=/ node=(unit node:store) ~
|
||||||
|
=/ =graph:store p.u.parent-graph
|
||||||
|
|-
|
||||||
|
?~ index
|
||||||
|
node
|
||||||
|
?~ t.index
|
||||||
|
(get:orm graph i.index)
|
||||||
|
=. node (get:orm graph i.index)
|
||||||
|
?~ node ~
|
||||||
|
?- -.children.u.node
|
||||||
|
%empty ~
|
||||||
|
%graph $(graph p.children.u.node, index t.index)
|
||||||
|
==
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ on-arvo
|
||||||
|
|= [=wire =sign-arvo]
|
||||||
|
^- (quip card _this)
|
||||||
|
?+ -.sign-arvo (on-arvo:def wire sign-arvo)
|
||||||
|
%c
|
||||||
|
:_ this
|
||||||
|
?> ?=([%graph @ *] wire)
|
||||||
|
=/ =resource:store (de-path:res t.wire)
|
||||||
|
=/ gra=(unit marked-graph:store) (~(get by graphs) resource)
|
||||||
|
?~ gra ~
|
||||||
|
?~ q.u.gra ~
|
||||||
|
=/ =rave:clay [%next %b [%da now.bowl] /[u.q.u.gra]]
|
||||||
|
[%pass wire %arvo %c %warp our.bowl [%home `rave]]~
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ on-agent on-agent:def
|
||||||
|
++ on-leave on-leave:def
|
||||||
|
++ on-fail on-fail:def
|
||||||
|
--
|
@ -2,22 +2,16 @@
|
|||||||
/+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln
|
/+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln
|
||||||
|%
|
|%
|
||||||
+$ state
|
+$ state
|
||||||
$: %8
|
$: %9
|
||||||
drum=state:drum
|
|
||||||
helm=state:helm
|
|
||||||
kiln=state:kiln
|
|
||||||
==
|
|
||||||
+$ state-7
|
|
||||||
$: %7
|
|
||||||
drum=state:drum
|
drum=state:drum
|
||||||
helm=state:helm
|
helm=state:helm
|
||||||
kiln=state:kiln
|
kiln=state:kiln
|
||||||
==
|
==
|
||||||
+$ any-state
|
+$ any-state
|
||||||
$% state
|
$% state
|
||||||
state-7
|
|
||||||
[ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)]
|
[ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)]
|
||||||
[%7 drum=state:drum helm=state:helm kiln=state:kiln]
|
[%7 drum=state:drum helm=state:helm kiln=state:kiln]
|
||||||
|
[%8 drum=state:drum helm=state:helm kiln=state:kiln]
|
||||||
==
|
==
|
||||||
+$ any-state-tuple
|
+$ any-state-tuple
|
||||||
$: drum=any-state:drum
|
$: drum=any-state:drum
|
||||||
|
@ -85,15 +85,16 @@
|
|||||||
old [%2 +.old]
|
old [%2 +.old]
|
||||||
::
|
::
|
||||||
cards
|
cards
|
||||||
%+ turn
|
%+ murn
|
||||||
~(tap in ~(key by group-indices.old))
|
~(tap in ~(key by group-indices.old))
|
||||||
|= =group-path
|
|= =group-path
|
||||||
^- card
|
^- (unit card)
|
||||||
=/ rid=resource
|
=/ rid=(unit resource)
|
||||||
(de-path:resource group-path)
|
(de-path-soft:resource group-path)
|
||||||
?: =(our.bowl entity.rid)
|
?~ rid ~
|
||||||
(poke-md-hook %add-owned group-path)
|
?: =(our.bowl entity.u.rid)
|
||||||
(poke-md-hook %add-synced entity.rid group-path)
|
`(poke-md-hook %add-owned group-path)
|
||||||
|
`(poke-md-hook %add-synced entity.u.rid group-path)
|
||||||
==
|
==
|
||||||
=/ new-state=state-one
|
=/ new-state=state-one
|
||||||
%* . *state-one
|
%* . *state-one
|
||||||
@ -254,6 +255,11 @@
|
|||||||
=/ =group-path (stab (slav %t i.t.t.path))
|
=/ =group-path (stab (slav %t i.t.t.path))
|
||||||
=/ =md-resource [`@tas`i.t.t.t.path (stab (slav %t i.t.t.t.t.path))]
|
=/ =md-resource [`@tas`i.t.t.t.path (stab (slav %t i.t.t.t.t.path))]
|
||||||
``noun+!>((~(get by associations) [group-path md-resource]))
|
``noun+!>((~(get by associations) [group-path md-resource]))
|
||||||
|
::
|
||||||
|
[%x %resource @ *]
|
||||||
|
=/ app=@tas i.t.t.path
|
||||||
|
=/ app-path=^path t.t.t.path
|
||||||
|
``noun+!>((~(get by resource-indices) app app-path))
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ on-agent on-agent:def
|
++ on-agent on-agent:def
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
[%3 state-three]
|
[%3 state-three]
|
||||||
[%4 state-three]
|
[%4 state-three]
|
||||||
[%5 state-three]
|
[%5 state-three]
|
||||||
|
[%6 state-three]
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
+$ metadata-delta
|
+$ metadata-delta
|
||||||
@ -69,7 +70,7 @@
|
|||||||
==
|
==
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
=| [%5 state-three]
|
=| [%6 state-three]
|
||||||
=* state -
|
=* state -
|
||||||
%- agent:dbug
|
%- agent:dbug
|
||||||
%+ verb |
|
%+ verb |
|
||||||
@ -86,7 +87,6 @@
|
|||||||
:_ this
|
:_ this
|
||||||
:~ [%pass /view-bind %arvo %e %connect [~ /'publish-view'] %publish]
|
:~ [%pass /view-bind %arvo %e %connect [~ /'publish-view'] %publish]
|
||||||
[%pass /read/paths %arvo %c %warp our.bol q.byk.bol `rav]
|
[%pass /read/paths %arvo %c %warp our.bol q.byk.bol `rav]
|
||||||
[%pass /permissions %agent [our.bol %permission-store] %watch /updates]
|
|
||||||
(invite-poke:main [%create /publish])
|
(invite-poke:main [%create /publish])
|
||||||
:* %pass /invites %agent [our.bol %invite-store] %watch
|
:* %pass /invites %agent [our.bol %invite-store] %watch
|
||||||
/invitatory/publish
|
/invitatory/publish
|
||||||
@ -218,6 +218,26 @@
|
|||||||
==
|
==
|
||||||
::
|
::
|
||||||
%5
|
%5
|
||||||
|
%= $
|
||||||
|
-.p.old-state %6
|
||||||
|
cards
|
||||||
|
%+ weld cards
|
||||||
|
%+ roll ~(tap by books.p.old-state)
|
||||||
|
|= [[[who=@p book=@tas] nb=notebook] out=(list card)]
|
||||||
|
^- (list card)
|
||||||
|
?. =(who our.bol)
|
||||||
|
out
|
||||||
|
=/ rid (de-path:resource writers.nb)
|
||||||
|
=/ grp=(unit group) (scry-group:grup:main rid)
|
||||||
|
?~ grp out
|
||||||
|
?: hidden.u.grp
|
||||||
|
out
|
||||||
|
=/ =tag [%publish (cat 3 'writers-' book)]
|
||||||
|
:_ out
|
||||||
|
(group-proxy-poke entity.rid %add-tag rid tag members.u.grp)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
%6
|
||||||
[cards this(state p.old-state)]
|
[cards this(state p.old-state)]
|
||||||
==
|
==
|
||||||
++ convert-notebook-3-4
|
++ convert-notebook-3-4
|
||||||
@ -995,6 +1015,22 @@
|
|||||||
[~ state]
|
[~ state]
|
||||||
:_ state
|
:_ state
|
||||||
%- zing
|
%- zing
|
||||||
|
:- ^- (list card)
|
||||||
|
%+ roll ~(tap by books)
|
||||||
|
|= [[[who=@p book=@tas] nb=notebook] out=(list card)]
|
||||||
|
^- (list card)
|
||||||
|
?. =(who our.bol)
|
||||||
|
out
|
||||||
|
?. =(writers.nb path)
|
||||||
|
out
|
||||||
|
=/ rid (de-path:resource writers.nb)
|
||||||
|
=/ grp=(unit group) (scry-group:grup rid)
|
||||||
|
?~ grp out
|
||||||
|
?: hidden.u.grp
|
||||||
|
out
|
||||||
|
=/ =tag [%publish (cat 3 'writers-' book)]
|
||||||
|
:_ out
|
||||||
|
(group-proxy-poke entity.rid %add-tag rid tag members.u.grp)
|
||||||
%+ turn ~(tap in ships)
|
%+ turn ~(tap in ships)
|
||||||
|= who=@p
|
|= who=@p
|
||||||
?. (allowed who %read u.book)
|
?. (allowed who %read u.book)
|
||||||
@ -1226,12 +1262,19 @@
|
|||||||
^- [(list card) write=path read=path]
|
^- [(list card) write=path read=path]
|
||||||
?> ?=(^ group-path.group)
|
?> ?=(^ group-path.group)
|
||||||
=/ scry-path
|
=/ scry-path
|
||||||
;:(welp /(scot %p our.bol)/group-store/(scot %da now.bol) [%groups group-path.group] /noun)
|
;: welp
|
||||||
=/ grp .^((unit ^group) %gx scry-path)
|
/(scot %p our.bol)/group-store/(scot %da now.bol)
|
||||||
|
[%groups group-path.group]
|
||||||
|
/noun
|
||||||
|
==
|
||||||
|
=/ rid=resource (de-path:resource group-path.group)
|
||||||
|
=/ grp=(unit ^group) (scry-group:grup rid)
|
||||||
?: use-preexisting.group
|
?: use-preexisting.group
|
||||||
?~ grp !!
|
?~ grp !!
|
||||||
?. (is-managed group-path.group) !!
|
?. (is-managed group-path.group) !!
|
||||||
`[group-path.group group-path.group]
|
=/ =tag [%publish (cat 3 'writers-' book)]
|
||||||
|
:_ [group-path.group group-path.group]
|
||||||
|
[(group-proxy-poke entity.rid %add-tag rid tag members.u.grp)]~
|
||||||
::
|
::
|
||||||
=/ =policy
|
=/ =policy
|
||||||
*open:policy
|
*open:policy
|
||||||
@ -1684,10 +1727,9 @@
|
|||||||
?> ?=(^ subscribers.u.book)
|
?> ?=(^ subscribers.u.book)
|
||||||
=/ cards=(list card)
|
=/ cards=(list card)
|
||||||
~[(delete-dir pax)]
|
~[(delete-dir pax)]
|
||||||
|
|
||||||
=/ rid=resource
|
=/ rid=resource
|
||||||
(de-path:resource writers.u.book)
|
(de-path:resource writers.u.book)
|
||||||
=? cards (is-managed:grup rid)
|
=? cards !(is-managed:grup rid)
|
||||||
[(group-poke %remove-group rid ~) cards]
|
[(group-poke %remove-group rid ~) cards]
|
||||||
[cards state]
|
[cards state]
|
||||||
:: %del-note:
|
:: %del-note:
|
||||||
@ -1791,6 +1833,10 @@
|
|||||||
?> (team:title our.bol src.bol)
|
?> (team:title our.bol src.bol)
|
||||||
=/ join-wire=wire
|
=/ join-wire=wire
|
||||||
/join-group/[(scot %p who.act)]/[book.act]
|
/join-group/[(scot %p who.act)]/[book.act]
|
||||||
|
=/ meta=(unit (set path))
|
||||||
|
(metadata-resource-scry %publish /(scot %p who.act)/[book.act])
|
||||||
|
?^ meta
|
||||||
|
(subscribe-notebook who.act book.act)
|
||||||
=/ rid=resource
|
=/ rid=resource
|
||||||
[who.act book.act]
|
[who.act book.act]
|
||||||
=/ =cage
|
=/ =cage
|
||||||
@ -1811,12 +1857,16 @@
|
|||||||
(de-path:resource writers.book)
|
(de-path:resource writers.book)
|
||||||
=/ =group
|
=/ =group
|
||||||
(need (scry-group:grup rid))
|
(need (scry-group:grup rid))
|
||||||
:_ state(books (~(del by books) who.act book.act))
|
=/ cards=(list card)
|
||||||
:~ `card`[%pass wir %agent [who.act %publish] %leave ~]
|
:~ [%pass wir %agent [who.act %publish] %leave ~]
|
||||||
`card`[%give %fact [/primary]~ %publish-primary-delta !>(del)]
|
[%give %fact [/primary]~ %publish-primary-delta !>(del)]
|
||||||
(group-proxy-poke who.act %remove-members rid (sy our.bol ~))
|
==
|
||||||
(group-poke %remove-group rid ~)
|
=? cards hidden.group
|
||||||
==
|
%+ weld cards
|
||||||
|
:~ (group-proxy-poke who.act %remove-members rid (sy our.bol ~))
|
||||||
|
(group-poke %remove-group rid ~)
|
||||||
|
==
|
||||||
|
[cards state(books (~(del by books) who.act book.act))]
|
||||||
:: %read
|
:: %read
|
||||||
::
|
::
|
||||||
%read
|
%read
|
||||||
@ -1952,6 +2002,19 @@
|
|||||||
/noun
|
/noun
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
|
++ metadata-resource-scry
|
||||||
|
|= [app=@tas app-path=path]
|
||||||
|
^- (unit (set path))
|
||||||
|
?. .^(? %gu (scot %p our.bol) %metadata-store (scot %da now.bol) ~) ~
|
||||||
|
.^ (unit (set path))
|
||||||
|
%gx
|
||||||
|
;: weld
|
||||||
|
/(scot %p our.bol)/metadata-store/(scot %da now.bol)/resource/[app]
|
||||||
|
app-path
|
||||||
|
/noun
|
||||||
|
==
|
||||||
|
==
|
||||||
|
::
|
||||||
++ emit-metadata
|
++ emit-metadata
|
||||||
|= del=metadata-delta
|
|= del=metadata-delta
|
||||||
^- (list card)
|
^- (list card)
|
||||||
@ -2044,9 +2107,11 @@
|
|||||||
(emit-updates-and-state host.del book.del data.del del sty)
|
(emit-updates-and-state host.del book.del data.del del sty)
|
||||||
=/ rid=resource
|
=/ rid=resource
|
||||||
(de-path:resource writers.data.del)
|
(de-path:resource writers.data.del)
|
||||||
|
=? cards !=(our.bol entity.rid)
|
||||||
|
:_ cards
|
||||||
|
(group-pull-hook-poke [%add host.del rid])
|
||||||
:_ state
|
:_ state
|
||||||
:* (group-pull-hook-poke [%add host.del rid])
|
:* (metadata-hook-poke [%add-synced host.del writers.data.del])
|
||||||
(metadata-hook-poke [%add-synced host.del writers.data.del])
|
|
||||||
cards
|
cards
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
|
10
pkg/arvo/gen/graph-store/add-graph.hoon
Normal file
10
pkg/arvo/gen/graph-store/add-graph.hoon
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
:: graph-store|add-graph: add new graph
|
||||||
|
::
|
||||||
|
/+ *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[=resource mark=(unit mark) ~] ~]
|
||||||
|
==
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
[%0 now [%add-graph resource (gas:orm ~ ~) mark]]
|
20
pkg/arvo/gen/graph-store/add-post.hoon
Normal file
20
pkg/arvo/gen/graph-store/add-post.hoon
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
:: graph-store|add-post: add post to a graph
|
||||||
|
::
|
||||||
|
/- *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[[our=ship name=term] contents=(list content) ~] ~]
|
||||||
|
==
|
||||||
|
=/ =post *post
|
||||||
|
=: author.post our
|
||||||
|
index.post [now]~
|
||||||
|
time-sent.post now
|
||||||
|
contents.post contents
|
||||||
|
==
|
||||||
|
::
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
:+ %0 now
|
||||||
|
:+ %add-nodes [our name]
|
||||||
|
%- ~(gas by *(map index node))
|
||||||
|
~[[[now]~ [post [%empty ~]]]]
|
10
pkg/arvo/gen/graph-store/add-signatures.hoon
Normal file
10
pkg/arvo/gen/graph-store/add-signatures.hoon
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
:: graph-store|add-signatures: add signatures to a node at a particular uid
|
||||||
|
::
|
||||||
|
/- *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[[=resource =index] =signatures ~] ~]
|
||||||
|
==
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
[%0 now [%add-signatures [resource index] signatures]]
|
10
pkg/arvo/gen/graph-store/add-tag.hoon
Normal file
10
pkg/arvo/gen/graph-store/add-tag.hoon
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
:: graph-store|add-tag: tag a particular graph
|
||||||
|
::
|
||||||
|
/- *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[=term =resource ~] ~]
|
||||||
|
==
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
[%0 now [%add-tag term resource]]
|
10
pkg/arvo/gen/graph-store/archive-graph.hoon
Normal file
10
pkg/arvo/gen/graph-store/archive-graph.hoon
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
:: graph-store|archive-graph: archive graph
|
||||||
|
::
|
||||||
|
/- *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[=resource ~] ~]
|
||||||
|
==
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
[%0 now [%archive-graph resource]]
|
10
pkg/arvo/gen/graph-store/remove-graph.hoon
Normal file
10
pkg/arvo/gen/graph-store/remove-graph.hoon
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
:: graph-store|remove-graph: remove graph
|
||||||
|
::
|
||||||
|
/- *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[=resource ~] ~]
|
||||||
|
==
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
[%0 now [%remove-graph resource]]
|
10
pkg/arvo/gen/graph-store/remove-nodes.hoon
Normal file
10
pkg/arvo/gen/graph-store/remove-nodes.hoon
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
:: graph-store|remove-nodes: remove nodes from a graph at indices
|
||||||
|
::
|
||||||
|
/- *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[=resource indices=(set index) ~] ~]
|
||||||
|
==
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
[%0 now [%remove-nodes resource indices]]
|
11
pkg/arvo/gen/graph-store/remove-signatures.hoon
Normal file
11
pkg/arvo/gen/graph-store/remove-signatures.hoon
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
:: graph-store|remove-signatures: remove signatures from a node at a
|
||||||
|
:: particular uid
|
||||||
|
::
|
||||||
|
/- *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[[=resource =index] =signatures ~] ~]
|
||||||
|
==
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
[%0 now [%remove-signatures [resource index] signatures]]
|
10
pkg/arvo/gen/graph-store/remove-tag.hoon
Normal file
10
pkg/arvo/gen/graph-store/remove-tag.hoon
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
:: graph-store|remove-tag: remove a tag from a particular graph
|
||||||
|
::
|
||||||
|
/- *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[=term =resource ~] ~]
|
||||||
|
==
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
[%0 now [%remove-tag term resource]]
|
10
pkg/arvo/gen/graph-store/unarchive-graph.hoon
Normal file
10
pkg/arvo/gen/graph-store/unarchive-graph.hoon
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
:: graph-store|unarchive-graph: unarchive graph
|
||||||
|
::
|
||||||
|
/- *graph-store
|
||||||
|
:- %say
|
||||||
|
|= $: [now=@da eny=@uvJ =beak]
|
||||||
|
[[=resource ~] ~]
|
||||||
|
==
|
||||||
|
:- %graph-update
|
||||||
|
^- update
|
||||||
|
[%0 now [%unarchive-graph resource]]
|
@ -36,7 +36,7 @@
|
|||||||
public-key
|
public-key
|
||||||
=/ cub (pit:nu:crub:crypto 512 (shaz (jam mon life eny)))
|
=/ cub (pit:nu:crub:crypto 512 (shaz (jam mon life eny)))
|
||||||
=/ =seed:able:jael
|
=/ =seed:able:jael
|
||||||
[mon 1 sec:ex:cub ~]
|
[mon life sec:ex:cub ~]
|
||||||
%- %- slog
|
%- %- slog
|
||||||
:~ leaf+"moon: {(scow %p mon)}"
|
:~ leaf+"moon: {(scow %p mon)}"
|
||||||
leaf+(scow %uw (jam seed))
|
leaf+(scow %uw (jam seed))
|
||||||
|
@ -8,7 +8,11 @@
|
|||||||
::
|
::
|
||||||
:- %say
|
:- %say
|
||||||
|= $: [now=@da eny=@uvJ bec=beak]
|
|= $: [now=@da eny=@uvJ bec=beak]
|
||||||
[arg=?(~ [her=@p sud=@tas ~]) ~]
|
[arg=?(~ [%disable ~] [her=@p sud=@tas ~]) ~]
|
||||||
==
|
==
|
||||||
|
?~ arg
|
||||||
|
:- %kiln-ota-info ~
|
||||||
:- %kiln-ota
|
:- %kiln-ota
|
||||||
?~(arg ~ `[her sud]:arg)
|
?: ?=([%disable ~] arg)
|
||||||
|
~
|
||||||
|
`[her sud]:arg
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
[%tang >timers< ~]
|
[%tang >timers< ~]
|
||||||
.^ (list [date=@da =duct])
|
.^ (list [date=@da =duct])
|
||||||
%bx
|
%bx
|
||||||
(en-beam:format [p.bec %$ r.bec] /debug/timers)
|
(en-beam:format [p.bec %$ r.bec] /timers/debug)
|
||||||
==
|
==
|
||||||
|
411
pkg/arvo/lib/graph-store.hoon
Normal file
411
pkg/arvo/lib/graph-store.hoon
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
/- sur=graph-store, pos=post
|
||||||
|
/+ res=resource
|
||||||
|
=< [sur .]
|
||||||
|
=< [pos .]
|
||||||
|
=, sur
|
||||||
|
=, pos
|
||||||
|
|%
|
||||||
|
:: NOTE: move these functions to zuse
|
||||||
|
++ nu :: parse number as hex
|
||||||
|
|= jon/json
|
||||||
|
?> ?=({$s *} jon)
|
||||||
|
(rash p.jon hex)
|
||||||
|
::
|
||||||
|
++ re :: recursive reparsers
|
||||||
|
|* {gar/* sef/_|.(fist:dejs-soft:format)}
|
||||||
|
|= jon/json
|
||||||
|
^- (unit _gar)
|
||||||
|
=- ~! gar ~! (need -) -
|
||||||
|
((sef) jon)
|
||||||
|
::
|
||||||
|
++ dank :: tank
|
||||||
|
^- $-(json (unit tank))
|
||||||
|
=, ^? dejs-soft:format
|
||||||
|
%+ re *tank |. ~+
|
||||||
|
%- of :~
|
||||||
|
leaf+sa
|
||||||
|
palm+(ot style+(ot mid+sa cap+sa open+sa close+sa ~) lines+(ar dank) ~)
|
||||||
|
rose+(ot style+(ot mid+sa open+sa close+sa ~) lines+(ar dank) ~)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ orm ((ordered-map atom node) gth)
|
||||||
|
++ orm-log ((ordered-map time logged-update) gth)
|
||||||
|
::
|
||||||
|
++ enjs
|
||||||
|
=, enjs:format
|
||||||
|
|%
|
||||||
|
++ update
|
||||||
|
|= upd=^update
|
||||||
|
^- json
|
||||||
|
?> ?=(%0 -.upd)
|
||||||
|
|^ (frond %graph-update (pairs ~[(encode q.upd)]))
|
||||||
|
::
|
||||||
|
++ encode
|
||||||
|
|= upd=update-0
|
||||||
|
^- [cord json]
|
||||||
|
?- -.upd
|
||||||
|
%add-graph
|
||||||
|
:- %add-graph
|
||||||
|
%- pairs
|
||||||
|
:~ [%resource (enjs:res resource.upd)]
|
||||||
|
[%graph (graph graph.upd)]
|
||||||
|
[%mark ?~(mark.upd ~ s+u.mark.upd)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
%remove-graph
|
||||||
|
[%remove-graph (enjs:res resource.upd)]
|
||||||
|
::
|
||||||
|
%add-nodes
|
||||||
|
:- %add-nodes
|
||||||
|
%- pairs
|
||||||
|
:~ [%resource (enjs:res resource.upd)]
|
||||||
|
[%nodes (nodes nodes.upd)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
%remove-nodes
|
||||||
|
:- %remove-nodes
|
||||||
|
%- pairs
|
||||||
|
:~ [%resource (enjs:res resource.upd)]
|
||||||
|
[%indices (indices indices.upd)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
%add-signatures
|
||||||
|
:- %add-signatures
|
||||||
|
%- pairs
|
||||||
|
:~ [%uid (uid uid.upd)]
|
||||||
|
[%signatures (signatures signatures.upd)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
%remove-signatures
|
||||||
|
:- %remove-signatures
|
||||||
|
%- pairs
|
||||||
|
:~ [%uid (uid uid.upd)]
|
||||||
|
[%signatures (signatures signatures.upd)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
%add-tag
|
||||||
|
:- %add-tag
|
||||||
|
%- pairs
|
||||||
|
:~ [%term s+term.upd]
|
||||||
|
[%resource (enjs:res resource.upd)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
%remove-tag
|
||||||
|
:- %remove-tag
|
||||||
|
%- pairs
|
||||||
|
:~ [%term s+term.upd]
|
||||||
|
[%resource (enjs:res resource.upd)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
%archive-graph
|
||||||
|
[%archive-graph (enjs:res resource.upd)]
|
||||||
|
::
|
||||||
|
%unarchive-graph
|
||||||
|
[%unarchive-graph (enjs:res resource.upd)]
|
||||||
|
::
|
||||||
|
%keys
|
||||||
|
[%keys [%a (turn ~(tap in resources.upd) enjs:res)]]
|
||||||
|
::
|
||||||
|
%tags
|
||||||
|
[%tags [%a (turn ~(tap in tags.upd) |=(=term s+term))]]
|
||||||
|
::
|
||||||
|
%run-updates
|
||||||
|
[%run-updates ~]
|
||||||
|
::
|
||||||
|
%tag-queries
|
||||||
|
:- %tag-queries
|
||||||
|
%- pairs
|
||||||
|
%+ turn ~(tap by tag-queries.upd)
|
||||||
|
|= [=term =resources]
|
||||||
|
^- [cord json]
|
||||||
|
[term [%a (turn ~(tap in resources) enjs:res)]]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ graph
|
||||||
|
|= g=^graph
|
||||||
|
^- json
|
||||||
|
:- %a
|
||||||
|
%+ turn (tap:orm g)
|
||||||
|
|= [a=atom n=^node]
|
||||||
|
^- json
|
||||||
|
:- %a
|
||||||
|
:~ (index [a]~)
|
||||||
|
(node n)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ index
|
||||||
|
|= i=^index
|
||||||
|
^- json
|
||||||
|
=/ j=^tape ""
|
||||||
|
|-
|
||||||
|
?~ i [%s (crip j)]
|
||||||
|
=/ k=json (numb i.i)
|
||||||
|
?> ?=(%n -.k)
|
||||||
|
%_ $
|
||||||
|
i t.i
|
||||||
|
j (weld j (weld "/" (trip +.k)))
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ node
|
||||||
|
|= n=^node
|
||||||
|
^- json
|
||||||
|
%- pairs
|
||||||
|
:~ [%post (post post.n)]
|
||||||
|
:- %children
|
||||||
|
?- -.children.n
|
||||||
|
%empty ~
|
||||||
|
%graph (graph +.children.n)
|
||||||
|
==
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ post
|
||||||
|
|= p=^post
|
||||||
|
^- json
|
||||||
|
%- pairs
|
||||||
|
:~ [%author (ship author.p)]
|
||||||
|
[%index (index index.p)]
|
||||||
|
[%time-sent (time time-sent.p)]
|
||||||
|
[%contents [%a (turn contents.p content)]]
|
||||||
|
[%hash ?~(hash.p ~ s+(scot %ux u.hash.p))]
|
||||||
|
[%signatures (signatures signatures.p)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ content
|
||||||
|
|= c=^content
|
||||||
|
^- json
|
||||||
|
?- -.c
|
||||||
|
%text (frond %text s+text.c)
|
||||||
|
%url (frond %url s+url.c)
|
||||||
|
%reference (frond %reference (uid uid.c))
|
||||||
|
%code
|
||||||
|
%+ frond %code
|
||||||
|
%- pairs
|
||||||
|
:- [%expression s+expression.c]
|
||||||
|
:_ ~
|
||||||
|
:- %output
|
||||||
|
:: virtualize output rendering, +tank:enjs:format might crash
|
||||||
|
::
|
||||||
|
=/ result=(each (list json) tang)
|
||||||
|
(mule |.((turn output.c tank)))
|
||||||
|
?- -.result
|
||||||
|
%& a+p.result
|
||||||
|
%| a+[a+[%s '[[output rendering error]]']~]~
|
||||||
|
==
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ nodes
|
||||||
|
|= m=(map ^index ^node)
|
||||||
|
^- json
|
||||||
|
:- %a
|
||||||
|
%+ turn ~(tap by m)
|
||||||
|
|= [n=^index o=^node]
|
||||||
|
^- json
|
||||||
|
:- %a
|
||||||
|
:~ (index n)
|
||||||
|
(node o)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ indices
|
||||||
|
|= i=(set ^index)
|
||||||
|
^- json
|
||||||
|
[%a (turn ~(tap in i) index)]
|
||||||
|
::
|
||||||
|
++ uid
|
||||||
|
|= u=^uid
|
||||||
|
^- json
|
||||||
|
%- pairs
|
||||||
|
:~ [%resource (enjs:res resource.u)]
|
||||||
|
[%index (index index.u)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ signatures
|
||||||
|
|= s=^signatures
|
||||||
|
^- json
|
||||||
|
[%a (turn ~(tap in s) signature)]
|
||||||
|
::
|
||||||
|
++ signature
|
||||||
|
|= s=^signature
|
||||||
|
^- json
|
||||||
|
%- pairs
|
||||||
|
:~ [%signature s+(scot %ux p.s)]
|
||||||
|
[%ship (ship q.s)]
|
||||||
|
[%life (numb r.s)]
|
||||||
|
==
|
||||||
|
--
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ dejs
|
||||||
|
=, dejs:format
|
||||||
|
|%
|
||||||
|
++ update
|
||||||
|
|= jon=json
|
||||||
|
^- ^update
|
||||||
|
:- %0
|
||||||
|
:- *time
|
||||||
|
^- update-0
|
||||||
|
=< (decode jon)
|
||||||
|
|%
|
||||||
|
++ decode
|
||||||
|
%- of
|
||||||
|
:~ [%add-graph add-graph]
|
||||||
|
[%remove-graph remove-graph]
|
||||||
|
[%add-nodes add-nodes]
|
||||||
|
[%remove-nodes remove-nodes]
|
||||||
|
[%add-signatures add-signatures]
|
||||||
|
[%remove-signatures remove-signatures]
|
||||||
|
[%add-tag add-tag]
|
||||||
|
[%remove-tag remove-tag]
|
||||||
|
[%archive-graph archive-graph]
|
||||||
|
[%unarchive-graph unarchive-graph]
|
||||||
|
[%keys keys]
|
||||||
|
[%tags tags]
|
||||||
|
[%tag-queries tag-queries]
|
||||||
|
[%run-updates run-updates]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ add-graph
|
||||||
|
%- ot
|
||||||
|
:~ [%resource dejs:res]
|
||||||
|
[%graph graph]
|
||||||
|
[%mark (mu so)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ graph
|
||||||
|
|= a=json
|
||||||
|
^- ^graph
|
||||||
|
=/ or-mp ((ordered-map atom ^node) gth)
|
||||||
|
%+ gas:or-mp ~
|
||||||
|
%+ turn ~(tap by ((om node) a))
|
||||||
|
|* [b=cord c=*]
|
||||||
|
^- [atom ^node]
|
||||||
|
=> .(+< [b c]=+<)
|
||||||
|
[(rash b dem) c]
|
||||||
|
::
|
||||||
|
++ remove-graph (ot [%resource dejs:res]~)
|
||||||
|
++ archive-graph (ot [%resource dejs:res]~)
|
||||||
|
++ unarchive-graph (ot [%resource dejs:res]~)
|
||||||
|
::
|
||||||
|
++ add-nodes
|
||||||
|
%- ot
|
||||||
|
:~ [%resource dejs:res]
|
||||||
|
[%nodes nodes]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ nodes (op ;~(pfix net (more net dem)) node)
|
||||||
|
::
|
||||||
|
++ node
|
||||||
|
%- ot
|
||||||
|
:~ [%post post]
|
||||||
|
:: TODO: support adding nodes with children by supporting the
|
||||||
|
:: graph key
|
||||||
|
[%children (of [%empty ul]~)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ post
|
||||||
|
%- ot
|
||||||
|
:~ [%author (su ;~(pfix sig fed:ag))]
|
||||||
|
[%index index]
|
||||||
|
[%time-sent di]
|
||||||
|
[%contents (ar content)]
|
||||||
|
[%hash (mu nu)]
|
||||||
|
[%signatures (as signature)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ content
|
||||||
|
%- of
|
||||||
|
:~ [%text so]
|
||||||
|
[%url so]
|
||||||
|
[%reference uid]
|
||||||
|
[%code eval]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ eval
|
||||||
|
|= a=^json
|
||||||
|
^- [cord (list tank)]
|
||||||
|
=, ^? dejs-soft:format
|
||||||
|
=+ exp=((ot expression+so ~) a)
|
||||||
|
%- need
|
||||||
|
?~ exp [~ '' ~]
|
||||||
|
:+ ~ u.exp
|
||||||
|
:: NOTE: when sending, if output is an empty list,
|
||||||
|
:: graph-store will evaluate
|
||||||
|
(fall ((ot output+(ar dank) ~) a) ~)
|
||||||
|
::
|
||||||
|
++ remove-nodes
|
||||||
|
%- ot
|
||||||
|
:~ [%resource dejs:res]
|
||||||
|
[%indices (as index)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ add-signatures
|
||||||
|
%- ot
|
||||||
|
:~ [%uid uid]
|
||||||
|
[%signatures (as signature)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ remove-signatures
|
||||||
|
%- ot
|
||||||
|
:~ [%uid uid]
|
||||||
|
[%signatures (as signature)]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ signature
|
||||||
|
%- ot
|
||||||
|
:~ [%hash nu]
|
||||||
|
[%ship (su ;~(pfix sig fed:ag))]
|
||||||
|
[%life ni]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ uid
|
||||||
|
%- ot
|
||||||
|
:~ [%resource dejs:res]
|
||||||
|
[%index index]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ index (su ;~(pfix net (more net dem)))
|
||||||
|
::
|
||||||
|
++ add-tag
|
||||||
|
%- ot
|
||||||
|
:~ [%term so]
|
||||||
|
[%resource dejs:res]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ remove-tag
|
||||||
|
%- ot
|
||||||
|
:~ [%term so]
|
||||||
|
[%resource dejs:res]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ keys
|
||||||
|
|= =json
|
||||||
|
*resources
|
||||||
|
::
|
||||||
|
++ tags
|
||||||
|
|= =json
|
||||||
|
*(set term)
|
||||||
|
::
|
||||||
|
++ tag-queries
|
||||||
|
|= =json
|
||||||
|
*^tag-queries
|
||||||
|
::
|
||||||
|
++ run-updates
|
||||||
|
|= a=json
|
||||||
|
^- [resource update-log]
|
||||||
|
[*resource *update-log]
|
||||||
|
--
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ create
|
||||||
|
|_ [our=ship now=time]
|
||||||
|
++ post
|
||||||
|
|= [=index contents=(list content)]
|
||||||
|
^- ^post
|
||||||
|
:* our
|
||||||
|
index
|
||||||
|
now
|
||||||
|
contents
|
||||||
|
~
|
||||||
|
*signatures
|
||||||
|
==
|
||||||
|
--
|
||||||
|
--
|
24
pkg/arvo/lib/graph.hoon
Normal file
24
pkg/arvo/lib/graph.hoon
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/- *resource
|
||||||
|
/+ store=graph-store
|
||||||
|
|_ =bowl:gall
|
||||||
|
++ scry-for
|
||||||
|
|* [=mold =path]
|
||||||
|
.^ mold
|
||||||
|
%gx
|
||||||
|
(scot %p our.bowl)
|
||||||
|
%graph-store
|
||||||
|
(scot %da now.bowl)
|
||||||
|
(snoc `^path`path %noun)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
++ get-graph
|
||||||
|
|= res=resource
|
||||||
|
^- marked-graph:store
|
||||||
|
%+ scry-for marked-graph:store
|
||||||
|
/graph/(scot %p entity.res)/[name.res]
|
||||||
|
::
|
||||||
|
++ peek-log
|
||||||
|
|= res=resource
|
||||||
|
^- (unit time)
|
||||||
|
(scry-for (unit time) /peek-update-log/(scot %p entity.res)/[name.res])
|
||||||
|
--
|
@ -104,6 +104,7 @@
|
|||||||
%s3-store
|
%s3-store
|
||||||
%file-server
|
%file-server
|
||||||
%glob
|
%glob
|
||||||
|
%graph-store
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ deft-fish :: default connects
|
++ deft-fish :: default connects
|
||||||
@ -206,7 +207,7 @@
|
|||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ on-load
|
++ on-load
|
||||||
|= [hood-version=?(%1 %2 %3 %4 %5 %6 %7 %8) old=any-state]
|
|= [hood-version=?(%1 %2 %3 %4 %5 %6 %7 %8 %9) old=any-state]
|
||||||
=< se-abet =< se-view
|
=< se-abet =< se-view
|
||||||
=. sat old
|
=. sat old
|
||||||
=. dev (~(gut by bin) ost *source)
|
=. dev (~(gut by bin) ost *source)
|
||||||
@ -233,6 +234,8 @@
|
|||||||
=? ..on-load (lte hood-version %8)
|
=? ..on-load (lte hood-version %8)
|
||||||
=> (se-born | %home %group-push-hook)
|
=> (se-born | %home %group-push-hook)
|
||||||
(se-born | %home %group-pull-hook)
|
(se-born | %home %group-pull-hook)
|
||||||
|
=? ..on-load (lte hood-version %9)
|
||||||
|
(se-born | %home %graph-store)
|
||||||
..on-load
|
..on-load
|
||||||
::
|
::
|
||||||
++ reap-phat :: ack connect
|
++ reap-phat :: ack connect
|
||||||
|
@ -208,7 +208,7 @@
|
|||||||
::
|
::
|
||||||
++ get-germ
|
++ get-germ
|
||||||
|= =desk
|
|= =desk
|
||||||
=+ .^(=cass:clay %cw /(scot %p our)/home/(scot %da now))
|
=+ .^(=cass:clay %cw /(scot %p our)/[desk]/(scot %da now))
|
||||||
?- ud.cass
|
?- ud.cass
|
||||||
%0 %init
|
%0 %init
|
||||||
%1 %that
|
%1 %that
|
||||||
@ -341,13 +341,22 @@
|
|||||||
abet:(spam (render "already syncing" [sud her syd]:hos) ~)
|
abet:(spam (render "already syncing" [sud her syd]:hos) ~)
|
||||||
abet:abet:start-sync:(auto hos)
|
abet:abet:start-sync:(auto hos)
|
||||||
::
|
::
|
||||||
|
++ ota-info
|
||||||
|
?~ ota
|
||||||
|
"OTAs disabled"
|
||||||
|
"OTAs enabled from {<desk.u.ota>} on {<ship.u.ota>}"
|
||||||
|
::
|
||||||
|
++ poke-ota-info
|
||||||
|
|= *
|
||||||
|
=< abet %- spam
|
||||||
|
:~ [%leaf ota-info]
|
||||||
|
[%leaf "use |ota %disable or |ota ~sponsor %kids to reset it"]
|
||||||
|
==
|
||||||
|
::
|
||||||
++ poke-syncs :: print sync config
|
++ poke-syncs :: print sync config
|
||||||
|= ~
|
|= ~
|
||||||
=< abet %- spam
|
=< abet %- spam
|
||||||
:- :- %leaf
|
:- [%leaf ota-info]
|
||||||
?~ ota
|
|
||||||
"OTAs disabled"
|
|
||||||
"OTAs from {<desk.u.ota>} on {<ship.u.ota>}"
|
|
||||||
?: =(0 ~(wyt by syn))
|
?: =(0 ~(wyt by syn))
|
||||||
[%leaf "no other syncs configured"]~
|
[%leaf "no other syncs configured"]~
|
||||||
%+ turn ~(tap in ~(key by syn))
|
%+ turn ~(tap in ~(key by syn))
|
||||||
@ -416,6 +425,7 @@
|
|||||||
%kiln-merge =;(f (f !<(_+<.f vase)) poke-merge)
|
%kiln-merge =;(f (f !<(_+<.f vase)) poke-merge)
|
||||||
%kiln-mount =;(f (f !<(_+<.f vase)) poke-mount)
|
%kiln-mount =;(f (f !<(_+<.f vase)) poke-mount)
|
||||||
%kiln-ota =;(f (f !<(_+<.f vase)) poke:update)
|
%kiln-ota =;(f (f !<(_+<.f vase)) poke:update)
|
||||||
|
%kiln-ota-info =;(f (f !<(_+<.f vase)) poke-ota-info)
|
||||||
%kiln-permission =;(f (f !<(_+<.f vase)) poke-permission)
|
%kiln-permission =;(f (f !<(_+<.f vase)) poke-permission)
|
||||||
%kiln-rm =;(f (f !<(_+<.f vase)) poke-rm)
|
%kiln-rm =;(f (f !<(_+<.f vase)) poke-rm)
|
||||||
%kiln-schedule =;(f (f !<(_+<.f vase)) poke-schedule)
|
%kiln-schedule =;(f (f !<(_+<.f vase)) poke-schedule)
|
||||||
|
@ -59,7 +59,6 @@
|
|||||||
|~ [term tang]
|
|~ [term tang]
|
||||||
*[(list card) _^|(..on-init)]
|
*[(list card) _^|(..on-init)]
|
||||||
:: +resource-for-update: get affected resource from an update
|
:: +resource-for-update: get affected resource from an update
|
||||||
|
|
||||||
++ resource-for-update
|
++ resource-for-update
|
||||||
|~ vase
|
|~ vase
|
||||||
*(unit resource)
|
*(unit resource)
|
||||||
|
43
pkg/arvo/lib/signatures.hoon
Normal file
43
pkg/arvo/lib/signatures.hoon
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/- post
|
||||||
|
^?
|
||||||
|
=< [post .]
|
||||||
|
=, post
|
||||||
|
|%
|
||||||
|
++ sign
|
||||||
|
|= [our=ship now=time =hash]
|
||||||
|
^- signature
|
||||||
|
=/ =life .^(life %j /=life/(scot %da now)/(scot %p our))
|
||||||
|
=/ =ring .^(ring %j /=vein/(scot %da now)/(scot %ud life))
|
||||||
|
:+ `@ux`(sign:as:(nol:nu:crub:crypto ring) hash)
|
||||||
|
our
|
||||||
|
life
|
||||||
|
::
|
||||||
|
++ is-signature-valid
|
||||||
|
|= [=signature =hash now=time]
|
||||||
|
^- ?
|
||||||
|
=/ deed=(unit [a=life b=pass c=(unit @ux)])
|
||||||
|
.^ (unit [life pass (unit @ux)])
|
||||||
|
%j
|
||||||
|
/=deed/(scot %da now)/(scot %p q.signature)/(scot %ud p.signature)
|
||||||
|
==
|
||||||
|
:: we do not have a public key from ship
|
||||||
|
::
|
||||||
|
?~ deed %.y
|
||||||
|
:: we do not have a public key from ship at this life
|
||||||
|
::
|
||||||
|
?. =(a.u.deed r.signature) %.y
|
||||||
|
:: verify signature from ship at life
|
||||||
|
::
|
||||||
|
=(`hash (tear:as:crub:crypto b.u.deed p.signature))
|
||||||
|
::
|
||||||
|
++ are-signatures-valid
|
||||||
|
|= [=signatures =hash now=time]
|
||||||
|
^- ?
|
||||||
|
=/ signature-list ~(tap in signatures)
|
||||||
|
|-
|
||||||
|
?~ signature-list
|
||||||
|
%.y
|
||||||
|
?: (is-signature-valid i.signature-list hash now)
|
||||||
|
$(signature-list t.signature-list)
|
||||||
|
%.n
|
||||||
|
--
|
13
pkg/arvo/mar/graph/update.hoon
Normal file
13
pkg/arvo/mar/graph/update.hoon
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/+ *graph-store
|
||||||
|
|_ upd=update
|
||||||
|
++ grow
|
||||||
|
|%
|
||||||
|
++ json (update:enjs upd)
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ grab
|
||||||
|
|%
|
||||||
|
++ noun update
|
||||||
|
++ json update:dejs
|
||||||
|
--
|
||||||
|
--
|
17
pkg/arvo/mar/graph/validator/chat.hoon
Normal file
17
pkg/arvo/mar/graph/validator/chat.hoon
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/- *post
|
||||||
|
|_ i=indexed-post
|
||||||
|
++ grow
|
||||||
|
|%
|
||||||
|
++ noun i
|
||||||
|
--
|
||||||
|
++ grab
|
||||||
|
|%
|
||||||
|
++ noun
|
||||||
|
|= p=*
|
||||||
|
=/ ip ;;(indexed-post p)
|
||||||
|
?> ?=([@ ~] index.p.ip)
|
||||||
|
ip
|
||||||
|
--
|
||||||
|
::
|
||||||
|
++ grad %noun
|
||||||
|
--
|
61
pkg/arvo/sur/graph-store.hoon
Normal file
61
pkg/arvo/sur/graph-store.hoon
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/- *post
|
||||||
|
|%
|
||||||
|
+$ graph ((mop atom node) gth)
|
||||||
|
+$ marked-graph [p=graph q=(unit mark)]
|
||||||
|
::
|
||||||
|
+$ node [=post children=internal-graph]
|
||||||
|
+$ graphs (map resource marked-graph)
|
||||||
|
::
|
||||||
|
+$ tag-queries (jug term resource)
|
||||||
|
::
|
||||||
|
+$ update-log ((mop time logged-update) gth)
|
||||||
|
+$ update-logs (map resource update-log)
|
||||||
|
::
|
||||||
|
+$ internal-graph
|
||||||
|
$~ [%empty ~]
|
||||||
|
$% [%graph p=graph]
|
||||||
|
[%empty ~]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ network
|
||||||
|
$: =graphs
|
||||||
|
=tag-queries
|
||||||
|
=update-logs
|
||||||
|
archive=graphs
|
||||||
|
validators=(set mark)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ update
|
||||||
|
$% [%0 p=time q=update-0]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ logged-update
|
||||||
|
$% [%0 p=time q=logged-update-0]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ logged-update-0
|
||||||
|
$% [%add-nodes =resource nodes=(map index node)]
|
||||||
|
[%remove-nodes =resource indices=(set index)]
|
||||||
|
[%add-signatures =uid =signatures]
|
||||||
|
[%remove-signatures =uid =signatures]
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ update-0
|
||||||
|
$% logged-update-0
|
||||||
|
[%add-graph =resource =graph mark=(unit mark)]
|
||||||
|
[%remove-graph =resource]
|
||||||
|
::
|
||||||
|
[%add-tag =term =resource]
|
||||||
|
[%remove-tag =term =resource]
|
||||||
|
::
|
||||||
|
[%archive-graph =resource]
|
||||||
|
[%unarchive-graph =resource]
|
||||||
|
[%run-updates =resource =update-log]
|
||||||
|
::
|
||||||
|
:: NOTE: cannot be sent as pokes
|
||||||
|
::
|
||||||
|
[%keys =resources]
|
||||||
|
[%tags tags=(set term)]
|
||||||
|
[%tag-queries =tag-queries]
|
||||||
|
==
|
||||||
|
--
|
37
pkg/arvo/sur/post.hoon
Normal file
37
pkg/arvo/sur/post.hoon
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/- *resource
|
||||||
|
|%
|
||||||
|
+$ index (list atom)
|
||||||
|
+$ uid [=resource =index]
|
||||||
|
::
|
||||||
|
:: +sham (half sha-256) hash of +validated-portion
|
||||||
|
+$ hash @ux
|
||||||
|
::
|
||||||
|
+$ signature [p=@ux q=ship r=life]
|
||||||
|
+$ signatures (set signature)
|
||||||
|
+$ post
|
||||||
|
$: author=ship
|
||||||
|
=index
|
||||||
|
time-sent=time
|
||||||
|
contents=(list content)
|
||||||
|
hash=(unit hash)
|
||||||
|
=signatures
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ indexed-post [a=atom p=post]
|
||||||
|
::
|
||||||
|
+$ validated-portion
|
||||||
|
$: parent-hash=(unit hash)
|
||||||
|
author=ship
|
||||||
|
time-sent=time
|
||||||
|
contents=(list content)
|
||||||
|
==
|
||||||
|
::
|
||||||
|
+$ content
|
||||||
|
$% [%text text=cord]
|
||||||
|
[%url url=cord]
|
||||||
|
[%code expression=cord output=(list tank)]
|
||||||
|
[%reference =uid]
|
||||||
|
:: TODO: maybe use a cask?
|
||||||
|
::[%cage =cage]
|
||||||
|
==
|
||||||
|
--
|
@ -8,5 +8,4 @@
|
|||||||
+$ update
|
+$ update
|
||||||
$% [%tracking tracking=(map resource ship)]
|
$% [%tracking tracking=(map resource ship)]
|
||||||
==
|
==
|
||||||
::
|
|
||||||
--
|
--
|
||||||
|
@ -7762,11 +7762,13 @@
|
|||||||
++ teal
|
++ teal
|
||||||
|= mod/spec
|
|= mod/spec
|
||||||
^- spec
|
^- spec
|
||||||
|
?: ?=(%& -.tik) mod
|
||||||
[%over [%& 3]~ mod]
|
[%over [%& 3]~ mod]
|
||||||
::
|
::
|
||||||
++ tele
|
++ tele
|
||||||
|= syn/skin
|
|= syn/skin
|
||||||
^- skin
|
^- skin
|
||||||
|
?: ?=(%& -.tik) syn
|
||||||
[%over [%& 3]~ syn]
|
[%over [%& 3]~ syn]
|
||||||
::
|
::
|
||||||
++ gray
|
++ gray
|
||||||
|
@ -1121,17 +1121,32 @@
|
|||||||
?> =(rcvr-life.shut-packet our-life.channel)
|
?> =(rcvr-life.shut-packet our-life.channel)
|
||||||
:: non-galaxy: update route with heard lane or forwarded lane
|
:: non-galaxy: update route with heard lane or forwarded lane
|
||||||
::
|
::
|
||||||
=? route.peer-state
|
=? route.peer-state !=(%czar (clan:title her.channel))
|
||||||
?: =(%czar (clan:title her.channel))
|
:: if new packet is direct, use that. otherwise, if the new new
|
||||||
%.n
|
:: and old lanes are indirect, use the new one. if the new lane
|
||||||
=/ is-old-direct=? ?=([~ %& *] route.peer-state)
|
:: is indirect but the old lane is direct, then if the lanes are
|
||||||
=/ is-new-direct=? ?=(~ origin.packet)
|
:: identical, don't mark it indirect; if they're not identical,
|
||||||
:: old direct takes precedence over new indirect
|
:: use the new lane and mark it indirect.
|
||||||
::
|
|
||||||
|(is-new-direct !is-old-direct)
|
|
||||||
::
|
::
|
||||||
?~ origin.packet
|
:: if you mark lane as indirect because you got an indirect
|
||||||
|
:: packet even though you already had a direct identical lane,
|
||||||
|
:: then delayed forwarded packets will come later and reset to
|
||||||
|
:: indirect, so you're unlikely to get a stable direct route
|
||||||
|
:: (unless the forwarder goes offline for a while).
|
||||||
|
::
|
||||||
|
:: conversely, if you don't accept indirect routes with different
|
||||||
|
:: lanes, then if your lane is stale and they're trying to talk
|
||||||
|
:: to you, your acks will go to the stale lane, and you'll never
|
||||||
|
:: time it out unless you reach out to them. this manifests as
|
||||||
|
:: needing to |hi or dotpost to get a response when the other
|
||||||
|
:: ship has changed lanes.
|
||||||
|
::
|
||||||
|
?: ?=(~ origin.packet)
|
||||||
`[direct=%.y lane]
|
`[direct=%.y lane]
|
||||||
|
?: ?=([~ %& *] route.peer-state)
|
||||||
|
?: =(lane.u.route.peer-state u.origin.packet)
|
||||||
|
route.peer-state
|
||||||
|
`[direct=%.n u.origin.packet]
|
||||||
`[direct=%.n u.origin.packet]
|
`[direct=%.n u.origin.packet]
|
||||||
:: perform peer-specific handling of packet
|
:: perform peer-specific handling of packet
|
||||||
::
|
::
|
||||||
|
@ -109,6 +109,10 @@
|
|||||||
mut/(list (trel path lobe cage)) :: mutations
|
mut/(list (trel path lobe cage)) :: mutations
|
||||||
== ::
|
== ::
|
||||||
::
|
::
|
||||||
|
:: Over-the-wire backfill request
|
||||||
|
::
|
||||||
|
+$ fill [=desk =lobe]
|
||||||
|
::
|
||||||
:: Ford cache
|
:: Ford cache
|
||||||
::
|
::
|
||||||
+$ ford-cache
|
+$ ford-cache
|
||||||
@ -214,18 +218,29 @@
|
|||||||
:: requests, and a possible nako if we've received data from the other ship and
|
:: requests, and a possible nako if we've received data from the other ship and
|
||||||
:: are in the process of validating it.
|
:: are in the process of validating it.
|
||||||
::
|
::
|
||||||
++ rind :: request manager
|
+$ rind :: request manager
|
||||||
$: nix/@ud :: request index
|
$: nix=@ud :: request index
|
||||||
bom/(map @ud {p/duct q/rave}) :: outstanding
|
bom=(map @ud update-state) :: outstanding
|
||||||
fod/(map duct @ud) :: current requests
|
fod=(map duct @ud) :: current requests
|
||||||
haw/(map mood (unit cage)) :: simple cache
|
haw=(map mood (unit cage)) :: simple cache
|
||||||
== ::
|
== ::
|
||||||
|
::
|
||||||
|
:: Active downloads
|
||||||
|
::
|
||||||
|
+$ update-state
|
||||||
|
$: =duct
|
||||||
|
=rave
|
||||||
|
have=(map lobe blob)
|
||||||
|
need=(list lobe)
|
||||||
|
nako=(qeu (unit nako))
|
||||||
|
busy=_|
|
||||||
|
==
|
||||||
::
|
::
|
||||||
:: Result of a subscription
|
:: Result of a subscription
|
||||||
::
|
::
|
||||||
++ sub-result
|
++ sub-result
|
||||||
$% [%blab =mood data=(each cage lobe)]
|
$% [%blab =mood data=(each cage lobe)]
|
||||||
[%bleb ins=@ud range=(unit (pair aeon aeon))]
|
[%bleb ver=@ud ins=@ud range=(unit (pair aeon aeon))]
|
||||||
[%balk cage=(unit (each cage lobe)) =mood]
|
[%balk cage=(unit (each cage lobe)) =mood]
|
||||||
[%blas moods=(set mood)]
|
[%blas moods=(set mood)]
|
||||||
[%blub ~]
|
[%blub ~]
|
||||||
@ -246,7 +261,7 @@
|
|||||||
:: Generally used when we store a request in our state somewhere.
|
:: Generally used when we store a request in our state somewhere.
|
||||||
::
|
::
|
||||||
++ cach (unit (unit (each cage lobe))) :: cached result
|
++ cach (unit (unit (each cage lobe))) :: cached result
|
||||||
+$ wove [for=(unit ship) =rove] :: stored source + req
|
+$ wove [for=(unit [=ship ver=@ud]) =rove] :: stored source + req
|
||||||
++ rove :: stored request
|
++ rove :: stored request
|
||||||
$% [%sing =mood] :: single request
|
$% [%sing =mood] :: single request
|
||||||
[%next =mood aeon=(unit aeon) =cach] :: next version of one
|
[%next =mood aeon=(unit aeon) =cach] :: next version of one
|
||||||
@ -1134,13 +1149,13 @@
|
|||||||
:: Give next step in a subscription.
|
:: Give next step in a subscription.
|
||||||
::
|
::
|
||||||
++ bleb
|
++ bleb
|
||||||
|= {hen/duct ins/@ud hip/(unit (pair aeon aeon))}
|
|= [hen=duct ver=@ud ins=@ud hip=(unit (pair aeon aeon))]
|
||||||
^+ +>
|
^+ +>
|
||||||
%^ blab hen [%w [%ud ins] ~]
|
%^ blab hen [%w [%ud ins] ~]
|
||||||
:- %&
|
:- %&
|
||||||
?~ hip
|
?~ hip
|
||||||
[%null [%atom %n ~] ~]
|
[%null [%atom %n ~] ~]
|
||||||
[%nako !>((make-nako:ze u.hip))]
|
[%nako !>((make-nako:ze ver u.hip))]
|
||||||
::
|
::
|
||||||
:: Tell subscriber that subscription is done.
|
:: Tell subscriber that subscription is done.
|
||||||
::
|
::
|
||||||
@ -1183,7 +1198,7 @@
|
|||||||
=/ =desk p.riff
|
=/ =desk p.riff
|
||||||
=/ =wire /warp-index/(scot %p ship)/(scot %tas desk)/(scot %ud index)
|
=/ =wire /warp-index/(scot %p ship)/(scot %tas desk)/(scot %ud index)
|
||||||
=/ =path [%question desk (scot %ud index) ~]
|
=/ =path [%question desk (scot %ud index) ~]
|
||||||
(emit duct %pass wire %a %plea ship %c path riff)
|
(emit duct %pass wire %a %plea ship %c path [[%1 ~] riff])
|
||||||
::
|
::
|
||||||
:: Create a request that cannot be filled immediately.
|
:: Create a request that cannot be filled immediately.
|
||||||
::
|
::
|
||||||
@ -1210,7 +1225,7 @@
|
|||||||
(send-over-ames hen her inx syd `rave)
|
(send-over-ames hen her inx syd `rave)
|
||||||
%= +>+.$
|
%= +>+.$
|
||||||
nix.u.ref +(nix.u.ref)
|
nix.u.ref +(nix.u.ref)
|
||||||
bom.u.ref (~(put by bom.u.ref) inx [hen rave])
|
bom.u.ref (~(put by bom.u.ref) inx [hen rave ~ ~ ~ |])
|
||||||
fod.u.ref (~(put by fod.u.ref) hen inx)
|
fod.u.ref (~(put by fod.u.ref) hen inx)
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
@ -2003,6 +2018,7 @@
|
|||||||
:: bob's.
|
:: bob's.
|
||||||
::
|
::
|
||||||
?: ?=(%init germ)
|
?: ?=(%init germ)
|
||||||
|
?> ?=(~ bob-yaki)
|
||||||
&+`[conflicts=~ new=|+ali-yaki lat=~]
|
&+`[conflicts=~ new=|+ali-yaki lat=~]
|
||||||
::
|
::
|
||||||
=/ bob-yaki (need bob-yaki)
|
=/ bob-yaki (need bob-yaki)
|
||||||
@ -2589,7 +2605,7 @@
|
|||||||
:: and then waiting if the subscription range extends into the future.
|
:: and then waiting if the subscription range extends into the future.
|
||||||
::
|
::
|
||||||
++ start-request
|
++ start-request
|
||||||
|= [for=(unit ship) rav=rave]
|
|= [for=(unit [ship @ud]) rav=rave]
|
||||||
^+ ..start-request
|
^+ ..start-request
|
||||||
=^ [new-sub=(unit rove) sub-results=(list sub-result)] fod.dom
|
=^ [new-sub=(unit rove) sub-results=(list sub-result)] fod.dom
|
||||||
(try-fill-sub for (rave-to-rove rav))
|
(try-fill-sub for (rave-to-rove rav))
|
||||||
@ -2612,9 +2628,9 @@
|
|||||||
?> ?=(^ ref)
|
?> ?=(^ ref)
|
||||||
=+ ruv=(~(get by bom.u.ref) inx)
|
=+ ruv=(~(get by bom.u.ref) inx)
|
||||||
?~ ruv +>.$
|
?~ ruv +>.$
|
||||||
=/ rav=rave q.u.ruv
|
=/ rav=rave rave.u.ruv
|
||||||
?: ?=(%many -.rav)
|
?: ?=(%many -.rav)
|
||||||
(take-foreign-update inx rut)
|
abet:(apex:(foreign-update inx) rut)
|
||||||
?~ rut
|
?~ rut
|
||||||
:: nothing here, so cache that
|
:: nothing here, so cache that
|
||||||
::
|
::
|
||||||
@ -2689,36 +2705,138 @@
|
|||||||
!>(;;(@uvI q.page))
|
!>(;;(@uvI q.page))
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
:: A full foreign update. Validate and apply to our local cache of
|
:: Respond to backfill request
|
||||||
:: their state.
|
|
||||||
::
|
::
|
||||||
++ take-foreign-update
|
:: Maybe should verify the requester is allowed to access this blob?
|
||||||
|= [inx=@ud rut=(unit rand)]
|
::
|
||||||
^+ ..take-foreign-update
|
++ give-backfill
|
||||||
|
|= =lobe
|
||||||
|
^+ ..give-backfill
|
||||||
|
(emit hen %give %boon (~(got by lat.ran) lobe))
|
||||||
|
::
|
||||||
|
:: Ingest foreign update, requesting missing blobs if necessary
|
||||||
|
::
|
||||||
|
++ foreign-update
|
||||||
|
|= inx=@ud
|
||||||
?> ?=(^ ref)
|
?> ?=(^ ref)
|
||||||
=/ ruv (~(get by bom.u.ref) inx)
|
=/ [sat=update-state lost=?]
|
||||||
?~ ruv
|
=/ ruv (~(get by bom.u.ref) inx)
|
||||||
~& [%clay-foreign-update-lost her syd inx]
|
?~ ruv
|
||||||
..take-foreign-update
|
~& [%clay-foreign-update-lost her syd inx]
|
||||||
=. hen p.u.ruv
|
[*update-state &]
|
||||||
=/ =rave q.u.ruv
|
[u.ruv |]
|
||||||
?> ?=(%many -.rave)
|
=/ done=? |
|
||||||
|^
|
=. hen duct.sat
|
||||||
?~ rut
|
|%
|
||||||
done
|
++ abet
|
||||||
=. lim ?.(?=(%da -.to.moat.rave) lim p.to.moat.rave)
|
^+ ..foreign-update
|
||||||
?> ?=(%nako p.r.u.rut)
|
?: lost
|
||||||
=/ nako ;;(nako q.r.u.rut)
|
..foreign-update
|
||||||
=. ..take-foreign-update
|
?: done
|
||||||
=< ?>(?=(^ ref) .)
|
=: bom.u.ref (~(del by bom.u.ref) inx)
|
||||||
(apply-foreign-update nako)
|
fod.u.ref (~(del by fod.u.ref) hen)
|
||||||
done
|
==
|
||||||
|
=<(?>(?=(^ ref) .) wake)
|
||||||
|
=. bom.u.ref (~(put by bom.u.ref) inx sat)
|
||||||
|
..foreign-update
|
||||||
::
|
::
|
||||||
++ done
|
++ apex
|
||||||
=: bom.u.ref (~(del by bom.u.ref) inx)
|
|= rut=(unit rand)
|
||||||
bom.u.ref (~(del by bom.u.ref) hen)
|
^+ ..abet
|
||||||
==
|
?: lost ..abet
|
||||||
=<(?>(?=(^ ref) .) wake)
|
?~ rut
|
||||||
|
=. nako.sat (~(put to nako.sat) ~)
|
||||||
|
work
|
||||||
|
?> ?=(%nako p.r.u.rut)
|
||||||
|
=/ nako ;;(nako q.r.u.rut)
|
||||||
|
=/ missing (missing-blobs nako)
|
||||||
|
=. need.sat `(list lobe)`(welp need.sat ~(tap in missing))
|
||||||
|
=. nako.sat (~(put to nako.sat) ~ nako)
|
||||||
|
work
|
||||||
|
::
|
||||||
|
++ missing-blobs
|
||||||
|
|= =nako
|
||||||
|
^- (set lobe)
|
||||||
|
=/ yakis ~(tap in lar.nako)
|
||||||
|
|- ^- (set lobe)
|
||||||
|
=* yaki-loop $
|
||||||
|
?~ yakis
|
||||||
|
~
|
||||||
|
=/ lobes=(list [=path =lobe]) ~(tap by q.i.yakis)
|
||||||
|
|- ^- (set lobe)
|
||||||
|
=* blob-loop $
|
||||||
|
?~ lobes
|
||||||
|
yaki-loop(yakis t.yakis)
|
||||||
|
?: (~(has by lat.ran) lobe.i.lobes)
|
||||||
|
blob-loop(lobes t.lobes)
|
||||||
|
(~(put in blob-loop(lobes t.lobes)) lobe.i.lobes)
|
||||||
|
::
|
||||||
|
:: Receive backfill response
|
||||||
|
::
|
||||||
|
++ take-backfill
|
||||||
|
|= =blob
|
||||||
|
^+ ..abet
|
||||||
|
?: lost ..abet
|
||||||
|
=? need.sat
|
||||||
|
?& ?=(%delta -.blob)
|
||||||
|
!(~(has by lat.ran) q.q.blob)
|
||||||
|
!(~(has by have.sat) q.q.blob)
|
||||||
|
==
|
||||||
|
[q.q.blob need.sat]
|
||||||
|
:: We can't put a blob in lat.ran if its parent isn't already
|
||||||
|
:: there. Unions are in reverse order so we don't overwrite
|
||||||
|
:: existing blobs.
|
||||||
|
::
|
||||||
|
=. ..abet
|
||||||
|
?: &(?=(%delta -.blob) !(~(has by lat.ran) q.q.blob))
|
||||||
|
..abet(have.sat (~(uni by (malt [p.blob `^blob`blob] ~)) have.sat))
|
||||||
|
..abet(lat.ran (~(uni by (malt [p.blob blob] ~)) lat.ran))
|
||||||
|
work(busy.sat |)
|
||||||
|
::
|
||||||
|
:: Fetch next blob
|
||||||
|
::
|
||||||
|
++ work
|
||||||
|
^+ ..abet
|
||||||
|
?: busy.sat
|
||||||
|
..abet
|
||||||
|
|- ^+ ..abet
|
||||||
|
?: =(~ need.sat)
|
||||||
|
:: NB: if you change to release nakos as we get enough blobs
|
||||||
|
:: for them instead of all at the end, you *must* store the
|
||||||
|
:: `lim` that should be applied after the nako is complete and
|
||||||
|
:: not use the one in the rave, since that will apply to the
|
||||||
|
:: end of subscription.
|
||||||
|
::
|
||||||
|
=. lat.ran (~(uni by have.sat) lat.ran)
|
||||||
|
|- ^+ ..abet
|
||||||
|
?: =(~ nako.sat)
|
||||||
|
..abet
|
||||||
|
=^ next=(unit nako) nako.sat ~(get to nako.sat)
|
||||||
|
?~ next
|
||||||
|
..abet(done &)
|
||||||
|
=. ..abet (apply-foreign-update u.next)
|
||||||
|
=. ..foreign-update =<(?>(?=(^ ref) .) wake)
|
||||||
|
$
|
||||||
|
?> ?=(^ need.sat)
|
||||||
|
:: This is what removes an item from `need`. This happens every
|
||||||
|
:: time we take a backfill response, but it could happen more than
|
||||||
|
:: once if we somehow got this data in the meantime (maybe from
|
||||||
|
:: another desk updating concurrently, or a previous update on this
|
||||||
|
:: same desk).
|
||||||
|
::
|
||||||
|
?: ?| (~(has by lat.ran) i.need.sat)
|
||||||
|
(~(has by have.sat) i.need.sat)
|
||||||
|
==
|
||||||
|
$(need.sat t.need.sat)
|
||||||
|
:: Otherwise, fetch the next blob
|
||||||
|
::
|
||||||
|
=/ =fill [syd i.need.sat]
|
||||||
|
=/ =wire /back-index/(scot %p her)/[syd]/(scot %ud inx)
|
||||||
|
=/ =path [%backfill syd (scot %ud inx) ~]
|
||||||
|
=. ..foreign-update
|
||||||
|
=< ?>(?=(^ ref) .)
|
||||||
|
(emit hen %pass wire %a %plea her %c path fill)
|
||||||
|
..abet(busy.sat &)
|
||||||
::
|
::
|
||||||
:: When we get a %w foreign update, store this in our state.
|
:: When we get a %w foreign update, store this in our state.
|
||||||
::
|
::
|
||||||
@ -2728,7 +2846,7 @@
|
|||||||
::
|
::
|
||||||
++ apply-foreign-update
|
++ apply-foreign-update
|
||||||
|= =nako
|
|= =nako
|
||||||
^+ ..take-foreign-update
|
^+ ..abet
|
||||||
:: hit: updated commit-hashes by @ud case
|
:: hit: updated commit-hashes by @ud case
|
||||||
:: nut: new commit-hash/commit pairs
|
:: nut: new commit-hash/commit pairs
|
||||||
:: hut: updated commits by hash
|
:: hut: updated commits by hash
|
||||||
@ -2765,12 +2883,19 @@
|
|||||||
$(aeon +(aeon))
|
$(aeon +(aeon))
|
||||||
:: produce updated state
|
:: produce updated state
|
||||||
::
|
::
|
||||||
|
=/ =rave rave:(~(got by bom.u.ref) inx)
|
||||||
|
?> ?=(%many -.rave)
|
||||||
=: let.dom (max let.nako let.dom)
|
=: let.dom (max let.nako let.dom)
|
||||||
hit.dom hit
|
hit.dom hit
|
||||||
hut.ran hut
|
hut.ran hut
|
||||||
lat.ran lat
|
lat.ran lat
|
||||||
|
:: Is this correct? Seeems like it should only go to `to` if
|
||||||
|
:: we've gotten all the way to the end. Leaving this
|
||||||
|
:: behavior unchanged for now, but I believe it's wrong.
|
||||||
|
::
|
||||||
|
lim ?.(?=(%da -.to.moat.rave) lim p.to.moat.rave)
|
||||||
==
|
==
|
||||||
..take-foreign-update
|
..abet
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
:: fire function if request is in future
|
:: fire function if request is in future
|
||||||
@ -2862,8 +2987,9 @@
|
|||||||
:: Try to fill a subscription
|
:: Try to fill a subscription
|
||||||
::
|
::
|
||||||
++ try-fill-sub
|
++ try-fill-sub
|
||||||
|= [for=(unit ship) rov=rove]
|
|= [far=(unit [=ship ver=@ud]) rov=rove]
|
||||||
^- [[new-sub=(unit rove) (list sub-result)] ford-cache]
|
^- [[new-sub=(unit rove) (list sub-result)] ford-cache]
|
||||||
|
=/ for=(unit ship) ?~(far ~ `ship.u.far)
|
||||||
?- -.rov
|
?- -.rov
|
||||||
%sing
|
%sing
|
||||||
=/ cache-value=(unit (unit cage))
|
=/ cache-value=(unit (unit cage))
|
||||||
@ -3075,6 +3201,7 @@
|
|||||||
::
|
::
|
||||||
[`rov ~]
|
[`rov ~]
|
||||||
=/ to-aeon (case-to-aeon to.moat.rov)
|
=/ to-aeon (case-to-aeon to.moat.rov)
|
||||||
|
=/ ver ?~(far %1 ver.u.far)
|
||||||
?~ to-aeon
|
?~ to-aeon
|
||||||
:: we're in the middle of the range, so produce what we can,
|
:: we're in the middle of the range, so produce what we can,
|
||||||
:: but don't end the subscription
|
:: but don't end the subscription
|
||||||
@ -3092,7 +3219,7 @@
|
|||||||
~
|
~
|
||||||
:: else changes, so produce them
|
:: else changes, so produce them
|
||||||
::
|
::
|
||||||
[%bleb let.dom ?:(track.rov ~ `[u.from-aeon let.dom])]~
|
[%bleb ver let.dom ?:(track.rov ~ `[u.from-aeon let.dom])]~
|
||||||
:: we're past the end of the range, so end subscription
|
:: we're past the end of the range, so end subscription
|
||||||
::
|
::
|
||||||
:- ~
|
:- ~
|
||||||
@ -3103,7 +3230,7 @@
|
|||||||
=/ bleb=(list sub-result)
|
=/ bleb=(list sub-result)
|
||||||
?: =(lobes.rov new-lobes)
|
?: =(lobes.rov new-lobes)
|
||||||
~
|
~
|
||||||
[%bleb +(u.from-aeon) ?:(track.rov ~ `[u.from-aeon u.to-aeon])]~
|
[%bleb ver +(u.from-aeon) ?:(track.rov ~ `[u.from-aeon u.to-aeon])]~
|
||||||
:: end subscription
|
:: end subscription
|
||||||
::
|
::
|
||||||
=/ blub=(list sub-result)
|
=/ blub=(list sub-result)
|
||||||
@ -3111,17 +3238,6 @@
|
|||||||
(weld bleb blub)
|
(weld bleb blub)
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
++ drop-me
|
|
||||||
^+ .
|
|
||||||
~| %clay-drop-me-not-implemented
|
|
||||||
!!
|
|
||||||
:: ?~ mer
|
|
||||||
:: .
|
|
||||||
:: %- emit(mer ~) ^- move :*
|
|
||||||
:: hen.u.mer %give %mere %| %user-interrupt
|
|
||||||
:: >sor.u.mer< >our< >cas.u.mer< >gem.u.mer< ~
|
|
||||||
:: ==
|
|
||||||
::
|
|
||||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
::
|
::
|
||||||
:: This core has no additional state, and the distinction exists purely for
|
:: This core has no additional state, and the distinction exists purely for
|
||||||
@ -3209,7 +3325,7 @@
|
|||||||
:: Creates a nako of all the changes between a and b.
|
:: Creates a nako of all the changes between a and b.
|
||||||
::
|
::
|
||||||
++ make-nako
|
++ make-nako
|
||||||
|= {a/aeon b/aeon}
|
|= [ver=@ud a=aeon b=aeon]
|
||||||
^- nako
|
^- nako
|
||||||
:+ ?> (lte b let.dom)
|
:+ ?> (lte b let.dom)
|
||||||
|-
|
|-
|
||||||
@ -3219,7 +3335,7 @@
|
|||||||
b
|
b
|
||||||
?: =(0 b)
|
?: =(0 b)
|
||||||
[~ ~]
|
[~ ~]
|
||||||
(data-twixt-takos (~(get by hit.dom) a) (aeon-to-tako b))
|
(data-twixt-takos =(0 ver) (~(get by hit.dom) a) (aeon-to-tako b))
|
||||||
::
|
::
|
||||||
:: Traverse parentage and find all ancestor hashes
|
:: Traverse parentage and find all ancestor hashes
|
||||||
::
|
::
|
||||||
@ -3245,16 +3361,21 @@
|
|||||||
:: ones we found before `a`. Then convert the takos to yakis and also get
|
:: ones we found before `a`. Then convert the takos to yakis and also get
|
||||||
:: all the data in all the yakis.
|
:: all the data in all the yakis.
|
||||||
::
|
::
|
||||||
|
:: What happens if you run an %init merge on a desk that already
|
||||||
|
:: had a commit?
|
||||||
|
::
|
||||||
++ data-twixt-takos
|
++ data-twixt-takos
|
||||||
|= {a/(unit tako) b/tako}
|
|= [plops=? a=(unit tako) b=tako]
|
||||||
^- {(set yaki) (set plop)}
|
^- [(set yaki) (set plop)]
|
||||||
=+ old=?~(a ~ (reachable-takos u.a))
|
=+ old=?~(a ~ (reachable-takos u.a))
|
||||||
=/ yal/(set tako)
|
=/ yal=(set tako)
|
||||||
%- silt
|
%- silt
|
||||||
%+ skip
|
%+ skip
|
||||||
~(tap in (reachable-takos b))
|
~(tap in (reachable-takos b))
|
||||||
|=(tak/tako (~(has in old) tak))
|
|=(tak=tako (~(has in old) tak))
|
||||||
:- (silt (turn ~(tap in yal) tako-to-yaki))
|
:- (silt (turn ~(tap in yal) tako-to-yaki))
|
||||||
|
?. plops
|
||||||
|
~
|
||||||
(silt (turn ~(tap in (new-lobes (new-lobes ~ old) yal)) lobe-to-blob))
|
(silt (turn ~(tap in (new-lobes (new-lobes ~ old) yal)) lobe-to-blob))
|
||||||
::
|
::
|
||||||
:: Get all the lobes that are referenced in `a` except those that are
|
:: Get all the lobes that are referenced in `a` except those that are
|
||||||
@ -3728,7 +3849,7 @@
|
|||||||
::
|
::
|
||||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||||
=| :: instrument state
|
=| :: instrument state
|
||||||
$: ver=%3 :: vane version
|
$: ver=%4 :: vane version
|
||||||
ruf=raft :: revision tree
|
ruf=raft :: revision tree
|
||||||
== ::
|
== ::
|
||||||
|= [our=ship now=@da eny=@uvJ ski=sley] :: current invocation
|
|= [our=ship now=@da eny=@uvJ ski=sley] :: current invocation
|
||||||
@ -3939,7 +4060,14 @@
|
|||||||
=^ for req
|
=^ for req
|
||||||
?: ?=(%warp -.req)
|
?: ?=(%warp -.req)
|
||||||
[~ req]
|
[~ req]
|
||||||
:- ?:(=(our who.req) ~ `who.req)
|
:: ?: =(our who.req)
|
||||||
|
:: [~ [%warp wer.req rif.req]]
|
||||||
|
=^ ver rif.req
|
||||||
|
?@ -.rif.req
|
||||||
|
[%0 rif.req]
|
||||||
|
[-<.rif.req +.rif.req]
|
||||||
|
?> ?=(@ -.rif.req)
|
||||||
|
:- ?:(=(our who.req) ~ `[who.req ver])
|
||||||
[%warp wer.req rif.req]
|
[%warp wer.req rif.req]
|
||||||
::
|
::
|
||||||
?> ?=(%warp -.req)
|
?> ?=(%warp -.req)
|
||||||
@ -3957,8 +4085,14 @@
|
|||||||
=* pax path.plea.req
|
=* pax path.plea.req
|
||||||
=* res payload.plea.req
|
=* res payload.plea.req
|
||||||
::
|
::
|
||||||
?> ?=({%question *} pax)
|
?: ?=([%backfill *] pax)
|
||||||
=+ ryf=;;(riff res)
|
=+ ;;(=fill res)
|
||||||
|
=^ mos ruf
|
||||||
|
=/ den ((de our now ski hen ruf) our desk.fill)
|
||||||
|
abet:(give-backfill:den +.fill)
|
||||||
|
[[[hen %give %done ~] mos] ..^$]
|
||||||
|
?> ?=([%question *] pax)
|
||||||
|
=+ ryf=;;(riff-any res)
|
||||||
:_ ..^$
|
:_ ..^$
|
||||||
:~ [hen %give %done ~]
|
:~ [hen %give %done ~]
|
||||||
=/ =wire
|
=/ =wire
|
||||||
@ -3971,11 +4105,58 @@
|
|||||||
!:
|
!:
|
||||||
|^
|
|^
|
||||||
|= old=any-state
|
|= old=any-state
|
||||||
~! [old=old new=*state-3]
|
~! [old=old new=*state-4]
|
||||||
=? old ?=(%2 -.old) (load-2-to-3 old)
|
=? old ?=(%2 -.old) (load-2-to-3 old)
|
||||||
?> ?=(%3 -.old)
|
=? old ?=(%3 -.old) (load-3-to-4 old)
|
||||||
|
?> ?=(%4 -.old)
|
||||||
..^^$(ruf +.old)
|
..^^$(ruf +.old)
|
||||||
::
|
::
|
||||||
|
++ load-3-to-4
|
||||||
|
|= =state-3
|
||||||
|
^- state-4
|
||||||
|
|^
|
||||||
|
=- state-3(- %4, hoy hoy.-, rom (room-3-to-4 rom.state-3))
|
||||||
|
^- hoy=(map ship rung)
|
||||||
|
%- ~(run by hoy.state-3)
|
||||||
|
|= =rung-3
|
||||||
|
^- rung
|
||||||
|
%- ~(run by rus.rung-3)
|
||||||
|
|= =rede-3
|
||||||
|
^- rede
|
||||||
|
=- rede-3(ref ref.-, qyx (cult-3-to-4 qyx.rede-3))
|
||||||
|
^- ref=(unit rind)
|
||||||
|
?~ ref.rede-3
|
||||||
|
~
|
||||||
|
=- `u.ref.rede-3(bom bom.-)
|
||||||
|
^- bom=(map @ud update-state)
|
||||||
|
%- ~(run by bom.u.ref.rede-3)
|
||||||
|
|= [=duct =rave]
|
||||||
|
^- update-state
|
||||||
|
[duct rave ~ ~ ~ |]
|
||||||
|
::
|
||||||
|
++ room-3-to-4
|
||||||
|
|= =room-3
|
||||||
|
^- room
|
||||||
|
=- room-3(dos dos.-)
|
||||||
|
^- dos=(map desk dojo)
|
||||||
|
%- ~(run by dos.room-3)
|
||||||
|
|= =dojo-3
|
||||||
|
^- dojo
|
||||||
|
dojo-3(qyx (cult-3-to-4 qyx.dojo-3))
|
||||||
|
::
|
||||||
|
++ cult-3-to-4
|
||||||
|
|= =cult-3
|
||||||
|
^- cult
|
||||||
|
%- malt
|
||||||
|
%+ turn ~(tap by cult-3)
|
||||||
|
|= [=wove-3 ducts=(set duct)]
|
||||||
|
^- [wove (set duct)]
|
||||||
|
:_ ducts :_ rove.wove-3
|
||||||
|
?~ for.wove-3
|
||||||
|
~
|
||||||
|
`[u.for.wove-3 %0]
|
||||||
|
--
|
||||||
|
::
|
||||||
++ load-2-to-3
|
++ load-2-to-3
|
||||||
|= =state-2
|
|= =state-2
|
||||||
^- state-3
|
^- state-3
|
||||||
@ -4005,11 +4186,11 @@
|
|||||||
:- %ford-fusion
|
:- %ford-fusion
|
||||||
[leaf+"queued merge canceled due to upgrade to ford fusion" ~]
|
[leaf+"queued merge canceled due to upgrade to ford fusion" ~]
|
||||||
`[duct %slip %b %drip !>([%mere %| err])]
|
`[duct %slip %b %drip !>([%mere %| err])]
|
||||||
^- rom=room
|
^- rom=room-3
|
||||||
:- hun.rom.state-2
|
:- hun.rom.state-2
|
||||||
%- ~(urn by dos.rom.state-2)
|
%- ~(urn by dos.rom.state-2)
|
||||||
|= [=desk =dojo-2]
|
|= [=desk =dojo-2]
|
||||||
^- dojo
|
^- dojo-3
|
||||||
=- dojo-2(dom -)
|
=- dojo-2(dom -)
|
||||||
^- dome
|
^- dome
|
||||||
=/ fer=(unit reef-cache)
|
=/ fer=(unit reef-cache)
|
||||||
@ -4019,23 +4200,22 @@
|
|||||||
(~(got by hut.ran.state-2) (~(got by hit.dom.dojo-2) let.dom.dojo-2))
|
(~(got by hut.ran.state-2) (~(got by hit.dom.dojo-2) let.dom.dojo-2))
|
||||||
`(build-reef desk q.yaki)
|
`(build-reef desk q.yaki)
|
||||||
[ank let hit lab mim fod=*ford-cache fer=fer]:[dom.dojo-2 .]
|
[ank let hit lab mim fod=*ford-cache fer=fer]:[dom.dojo-2 .]
|
||||||
^- hoy=(map ship rung)
|
^- hoy=(map ship rung-3)
|
||||||
%- ~(run by hoy.state-2)
|
%- ~(run by hoy.state-2)
|
||||||
|= =rung-2
|
|= =rung-2
|
||||||
^- rung
|
^- rung-3
|
||||||
%- ~(run by rus.rung-2)
|
%- ~(run by rus.rung-2)
|
||||||
|= =rede-2
|
|= =rede-2
|
||||||
^- rede
|
^- rede-3
|
||||||
=- rede-2(ref ref.-, dom dom.-)
|
=- rede-2(ref ref.-, dom dom.-)
|
||||||
:- ^- dom=dome
|
:- ^- dom=dome
|
||||||
[ank let hit lab mim fod=*ford-cache fer=~]:[dom.rede-2 .]
|
[ank let hit lab mim fod=*ford-cache fer=~]:[dom.rede-2 .]
|
||||||
^- ref=(unit rind)
|
^- ref=(unit rind-3)
|
||||||
?~ ref.rede-2
|
?~ ref.rede-2
|
||||||
~
|
~
|
||||||
:: TODO: somehow call +wake later to notify subscribers
|
|
||||||
:- ~
|
:- ~
|
||||||
^- rind
|
^- rind-3
|
||||||
=/ rin=rind [nix bom fod haw]:u.ref.rede-2
|
=/ rin=rind-3 [nix bom fod haw]:u.ref.rede-2
|
||||||
=. rin
|
=. rin
|
||||||
=/ pur=(list [inx=@ud =rand *]) ~(tap by pur.u.ref.rede-2)
|
=/ pur=(list [inx=@ud =rand *]) ~(tap by pur.u.ref.rede-2)
|
||||||
|- ^+ rin
|
|- ^+ rin
|
||||||
@ -4138,8 +4318,46 @@
|
|||||||
--
|
--
|
||||||
--
|
--
|
||||||
::
|
::
|
||||||
+$ any-state $%(state-3 state-2)
|
+$ any-state $%(state-4 state-3 state-2)
|
||||||
+$ state-3 [%3 raft]
|
+$ state-4 [%4 raft]
|
||||||
|
+$ state-3
|
||||||
|
$: %3
|
||||||
|
rom=room-3
|
||||||
|
hoy=(map ship rung-3)
|
||||||
|
ran=rang
|
||||||
|
mon=(map term beam)
|
||||||
|
hez=(unit duct)
|
||||||
|
cez=(map @ta crew)
|
||||||
|
pud=(unit [=desk =yoki])
|
||||||
|
pun=(list move)
|
||||||
|
==
|
||||||
|
+$ rung-3 rus=(map desk rede-3)
|
||||||
|
+$ rede-3
|
||||||
|
$: lim/@da
|
||||||
|
ref/(unit rind-3)
|
||||||
|
qyx/cult-3
|
||||||
|
dom/dome
|
||||||
|
per/regs
|
||||||
|
pew/regs
|
||||||
|
==
|
||||||
|
+$ rind-3
|
||||||
|
$: nix/@ud
|
||||||
|
bom/(map @ud {p/duct q/rave})
|
||||||
|
fod/(map duct @ud)
|
||||||
|
haw/(map mood (unit cage))
|
||||||
|
==
|
||||||
|
+$ room-3
|
||||||
|
$: hun/duct
|
||||||
|
dos/(map desk dojo-3)
|
||||||
|
==
|
||||||
|
++ dojo-3
|
||||||
|
$: qyx/cult-3
|
||||||
|
dom/dome
|
||||||
|
per/regs
|
||||||
|
pew/regs
|
||||||
|
==
|
||||||
|
+$ cult-3 (jug wove-3 duct)
|
||||||
|
+$ wove-3 [for=(unit ship) =rove]
|
||||||
+$ state-2
|
+$ state-2
|
||||||
$: %2
|
$: %2
|
||||||
rom=room-2 :: domestic
|
rom=room-2 :: domestic
|
||||||
@ -4156,7 +4374,7 @@
|
|||||||
dos/(map desk dojo-2) :: native desk
|
dos/(map desk dojo-2) :: native desk
|
||||||
== ::
|
== ::
|
||||||
+$ dojo-2
|
+$ dojo-2
|
||||||
$: qyx/cult :: subscribers
|
$: qyx/cult-3 :: subscribers
|
||||||
dom/dome-2 :: desk state
|
dom/dome-2 :: desk state
|
||||||
per/regs :: read perms per path
|
per/regs :: read perms per path
|
||||||
pew/regs :: write perms per path
|
pew/regs :: write perms per path
|
||||||
@ -4172,7 +4390,7 @@
|
|||||||
+$ rede-2
|
+$ rede-2
|
||||||
$: lim/@da :: complete to
|
$: lim/@da :: complete to
|
||||||
ref/(unit rind-2) :: outgoing requests
|
ref/(unit rind-2) :: outgoing requests
|
||||||
qyx/cult :: subscribers
|
qyx/cult-3 :: subscribers
|
||||||
dom/dome-2 :: revision state
|
dom/dome-2 :: revision state
|
||||||
per/regs :: read perms per path
|
per/regs :: read perms per path
|
||||||
pew/regs :: write perms per path
|
pew/regs :: write perms per path
|
||||||
@ -4303,6 +4521,35 @@
|
|||||||
[mos ..^$]
|
[mos ..^$]
|
||||||
==
|
==
|
||||||
::
|
::
|
||||||
|
?: ?=([%back-index @ @ @ ~] tea)
|
||||||
|
?+ +<.q.hin ~| %clay-backfill-index-strange !!
|
||||||
|
%done
|
||||||
|
?~ error.q.hin
|
||||||
|
[~ ..^$]
|
||||||
|
:: TODO better error handling
|
||||||
|
::
|
||||||
|
~& %clay-take-backfill-index-error^our^tea^tag.u.error.q.hin
|
||||||
|
%- (slog tang.u.error.q.hin)
|
||||||
|
[~ ..^$]
|
||||||
|
::
|
||||||
|
%lost
|
||||||
|
~| %clay-take-backfill-lost^our
|
||||||
|
:: TODO better error handling
|
||||||
|
!!
|
||||||
|
::
|
||||||
|
%boon
|
||||||
|
=+ ;; =blob payload.q.hin
|
||||||
|
::
|
||||||
|
=/ her=ship (slav %p i.t.tea)
|
||||||
|
=/ =desk (slav %tas i.t.t.tea)
|
||||||
|
=/ index=@ud (slav %ud i.t.t.t.tea)
|
||||||
|
::
|
||||||
|
=^ mos ruf
|
||||||
|
=/ den ((de our now ski hen ruf) her desk)
|
||||||
|
abet:abet:(take-backfill:(foreign-update:den index) blob)
|
||||||
|
[mos ..^$]
|
||||||
|
==
|
||||||
|
::
|
||||||
?: ?=([%sinks ~] tea)
|
?: ?=([%sinks ~] tea)
|
||||||
?> ?=(%public-keys +<.q.hin)
|
?> ?=(%public-keys +<.q.hin)
|
||||||
?. ?=(%breach -.public-keys-result.q.hin)
|
?. ?=(%breach -.public-keys-result.q.hin)
|
||||||
@ -4396,7 +4643,9 @@
|
|||||||
:+ desk %|
|
:+ desk %|
|
||||||
:~ ankh+&+ank.dom.dojo
|
:~ ankh+&+ank.dom.dojo
|
||||||
mime+&+mim.dom.dojo
|
mime+&+mim.dom.dojo
|
||||||
ford+&+fod.dom.dojo
|
ford-vases+&+vases.fod.dom.dojo
|
||||||
|
ford-marks+&+marks.fod.dom.dojo
|
||||||
|
ford-casts+&+casts.fod.dom.dojo
|
||||||
==
|
==
|
||||||
:~ domestic+|+domestic
|
:~ domestic+|+domestic
|
||||||
foreign+&+hoy.ruf
|
foreign+&+hoy.ruf
|
||||||
|
@ -861,7 +861,7 @@
|
|||||||
$>(%trim vane-task) :: trim state
|
$>(%trim vane-task) :: trim state
|
||||||
$>(%vega vane-task) :: report upgrade
|
$>(%vega vane-task) :: report upgrade
|
||||||
{$warp wer/ship rif/riff} :: internal file req
|
{$warp wer/ship rif/riff} :: internal file req
|
||||||
{$werp who/ship wer/ship rif/riff} :: external file req
|
{$werp who/ship wer/ship rif/riff-any} :: external file req
|
||||||
$>(%plea vane-task) :: ames request
|
$>(%plea vane-task) :: ames request
|
||||||
== ::
|
== ::
|
||||||
-- ::able
|
-- ::able
|
||||||
@ -967,7 +967,10 @@
|
|||||||
who/(pair (set ship) (map @ta crew)) ::
|
who/(pair (set ship) (map @ta crew)) ::
|
||||||
== ::
|
== ::
|
||||||
++ regs (map path rule) :: rules for paths
|
++ regs (map path rule) :: rules for paths
|
||||||
++ riff {p/desk q/(unit rave)} :: request+desist
|
+$ riff [p=desk q=(unit rave)] :: request+desist
|
||||||
|
+$ riff-any
|
||||||
|
$^ [[%1 ~] riff]
|
||||||
|
riff
|
||||||
++ rite :: new permissions
|
++ rite :: new permissions
|
||||||
$% {$r red/(unit rule)} :: for read
|
$% {$r red/(unit rule)} :: for read
|
||||||
{$w wit/(unit rule)} :: for write
|
{$w wit/(unit rule)} :: for write
|
||||||
|
@ -11,14 +11,14 @@
|
|||||||
;< ~ bind:m (spawn az ~marbud)
|
;< ~ bind:m (spawn az ~marbud)
|
||||||
;< ~ bind:m (real-ship az ~bud)
|
;< ~ bind:m (real-ship az ~bud)
|
||||||
;< ~ bind:m (real-ship az ~marbud)
|
;< ~ bind:m (real-ship az ~marbud)
|
||||||
;< file=@t bind:m (touch-file ~bud %base %foo)
|
;< file=@t bind:m (touch-file ~bud %kids %foo)
|
||||||
;< ~ bind:m (check-file-touched ~marbud %home file)
|
;< ~ bind:m (check-file-touched ~marbud %home file)
|
||||||
;< ~ bind:m (breach-and-hear az ~bud ~marbud)
|
;< ~ bind:m (breach-and-hear az ~bud ~marbud)
|
||||||
;< ~ bind:m (real-ship az ~bud)
|
;< ~ bind:m (real-ship az ~bud)
|
||||||
;< ~ bind:m (breach-and-hear az ~marbud ~bud)
|
;< ~ bind:m (breach-and-hear az ~marbud ~bud)
|
||||||
;< ~ bind:m (real-ship az ~marbud)
|
;< ~ bind:m (real-ship az ~marbud)
|
||||||
;< file=@t bind:m (touch-file ~bud %base %bar)
|
;< file=@t bind:m (touch-file ~bud %kids %bar)
|
||||||
;< file=@t bind:m (touch-file ~bud %base %baz)
|
;< file=@t bind:m (touch-file ~bud %kids %baz)
|
||||||
;< ~ bind:m (check-file-touched ~marbud %home file)
|
;< ~ bind:m (check-file-touched ~marbud %home file)
|
||||||
;< ~ bind:m end-azimuth
|
;< ~ bind:m end-azimuth
|
||||||
(pure:m *vase)
|
(pure:m *vase)
|
||||||
|
@ -13,13 +13,13 @@
|
|||||||
;< ~ bind:m (spawn az ~marbud)
|
;< ~ bind:m (spawn az ~marbud)
|
||||||
;< ~ bind:m (real-ship az ~bud)
|
;< ~ bind:m (real-ship az ~bud)
|
||||||
;< ~ bind:m (real-ship az ~marbud)
|
;< ~ bind:m (real-ship az ~marbud)
|
||||||
;< file=@t bind:m (touch-file ~bud %base %foo)
|
;< file=@t bind:m (touch-file ~bud %kids %foo)
|
||||||
;< ~ bind:m (check-file-touched ~marbud %home file)
|
;< ~ bind:m (check-file-touched ~marbud %home file)
|
||||||
;< ~ bind:m (breach az ~bud)
|
;< ~ bind:m (breach az ~bud)
|
||||||
;< ~ bind:m (real-ship az ~bud)
|
;< ~ bind:m (real-ship az ~bud)
|
||||||
;< ~ bind:m (dojo ~bud "|merge %base ~marbud %kids, =gem %this")
|
;< ~ bind:m (dojo ~bud "|merge %home ~marbud %kids, =gem %this")
|
||||||
;< file=@t bind:m (touch-file ~bud %base %bar)
|
;< file=@t bind:m (touch-file ~bud %kids %bar)
|
||||||
;< file=@t bind:m (touch-file ~bud %base %baz)
|
;< file=@t bind:m (touch-file ~bud %kids %baz)
|
||||||
;< ~ bind:m (check-file-touched ~marbud %home file)
|
;< ~ bind:m (check-file-touched ~marbud %home file)
|
||||||
;< ~ bind:m end-azimuth
|
;< ~ bind:m end-azimuth
|
||||||
(pure:m *vase)
|
(pure:m *vase)
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
;< ~ bind:m (real-ship az ~marbud)
|
;< ~ bind:m (real-ship az ~marbud)
|
||||||
;< file=@t bind:m (touch-file ~bud %kids %foo)
|
;< file=@t bind:m (touch-file ~bud %kids %foo)
|
||||||
;< ~ bind:m (check-file-touched ~marbud %home file)
|
;< ~ bind:m (check-file-touched ~marbud %home file)
|
||||||
|
:: Merge so that when we unify history with the %this merge later, we
|
||||||
|
:: don't get a spurious conflict in %home
|
||||||
|
::
|
||||||
|
;< ~ bind:m (dojo ~marbud "|merge %kids our %home")
|
||||||
;< ~ bind:m (breach-and-hear az ~bud ~marbud)
|
;< ~ bind:m (breach-and-hear az ~bud ~marbud)
|
||||||
;< ~ bind:m (real-ship az ~bud)
|
;< ~ bind:m (real-ship az ~bud)
|
||||||
;< ~ bind:m (dojo ~bud "|merge %kids ~marbud %kids, =gem %this")
|
;< ~ bind:m (dojo ~bud "|merge %kids ~marbud %kids, =gem %this")
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
;< ~ bind:m start-simple
|
;< ~ bind:m start-simple
|
||||||
;< ~ bind:m (raw-ship ~bud ~)
|
;< ~ bind:m (raw-ship ~bud ~)
|
||||||
;< ~ bind:m (raw-ship ~marbud ~)
|
;< ~ bind:m (raw-ship ~marbud ~)
|
||||||
;< file=@t bind:m (touch-file ~bud %base %foo)
|
;< file=@t bind:m (touch-file ~bud %home %foo)
|
||||||
|
;< ~ bind:m (dojo ~bud "|merge %kids our %home")
|
||||||
;< ~ bind:m (check-file-touched ~marbud %home file)
|
;< ~ bind:m (check-file-touched ~marbud %home file)
|
||||||
;< ~ bind:m end-simple
|
;< ~ bind:m end-simple
|
||||||
(pure:m *vase)
|
(pure:m *vase)
|
||||||
|
@ -29,15 +29,15 @@
|
|||||||
%^ cat 3 (get-val /mar/js/hoon)
|
%^ cat 3 (get-val /mar/js/hoon)
|
||||||
' ~& > new-val=new-val .'
|
' ~& > new-val=new-val .'
|
||||||
=/ js-contents
|
=/ js-contents
|
||||||
%^ cat 3 (get-val /app/publish/js/index/js)
|
%^ cat 3 (get-val /app/landscape/js/channel/js)
|
||||||
'extra'
|
'extra'
|
||||||
=/ files
|
=/ files
|
||||||
:~ [/sys/zuse/hoon zuse-contents]
|
:~ [/sys/zuse/hoon zuse-contents]
|
||||||
[/mar/js/hoon mar-contents]
|
[/mar/js/hoon mar-contents]
|
||||||
[/app/publish/js/index/js js-contents]
|
[/app/landscape/js/channel/js js-contents]
|
||||||
==
|
==
|
||||||
;< ~ bind:m (send-events (insert-files:util her desk files))
|
;< ~ bind:m (send-events (insert-files:util her desk files))
|
||||||
(pure:m /app/publish/js/index/js js-contents)
|
(pure:m /app/landscape/js/channel/js js-contents)
|
||||||
::
|
::
|
||||||
++ aqua-path
|
++ aqua-path
|
||||||
|= =path
|
|= =path
|
||||||
|
226
pkg/interface/package-lock.json
generated
226
pkg/interface/package-lock.json
generated
@ -1393,6 +1393,42 @@
|
|||||||
"tslib": "^1.11.1"
|
"tslib": "^1.11.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@reach/disclosure": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reach/disclosure/-/disclosure-0.10.5.tgz",
|
||||||
|
"integrity": "sha512-DCae28vcL7wXJNt8hySI2uaowEJ6KPDJ9U14xQMkMs0/lH7Tz8PoAO3llf7csEXk/4kzjnDpkyobDiEV3pz05g==",
|
||||||
|
"requires": {
|
||||||
|
"@reach/auto-id": "0.10.5",
|
||||||
|
"@reach/utils": "0.10.5",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@reach/auto-id": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reach/auto-id/-/auto-id-0.10.5.tgz",
|
||||||
|
"integrity": "sha512-we4/bwjFxJ3F+2eaddQ1HltbKvJ7AB8clkN719El7Zugpn/vOjfPMOVUiBqTmPGLUvkYrq4tpuFwLvk2HyOVHg==",
|
||||||
|
"requires": {
|
||||||
|
"@reach/utils": "0.10.5",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@reach/utils": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reach/utils/-/utils-0.10.5.tgz",
|
||||||
|
"integrity": "sha512-5E/xxQnUbmpI/LrufBAOXjunl96DnqX6B4zC2MO2KH/dRzLug5gM5VuOwV26egsp0jvsSPxojwciOhS43px3qw==",
|
||||||
|
"requires": {
|
||||||
|
"@types/warning": "^3.0.0",
|
||||||
|
"tslib": "^2.0.0",
|
||||||
|
"warning": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@reach/menu-button": {
|
"@reach/menu-button": {
|
||||||
"version": "0.10.1",
|
"version": "0.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/@reach/menu-button/-/menu-button-0.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/@reach/menu-button/-/menu-button-0.10.1.tgz",
|
||||||
@ -1443,6 +1479,53 @@
|
|||||||
"tslib": "^1.11.1"
|
"tslib": "^1.11.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@reach/tabs": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reach/tabs/-/tabs-0.10.5.tgz",
|
||||||
|
"integrity": "sha512-oQJxQ9FwFsXo2HxEzJxFU/wP31bPVh4VU54NlhHW9f49uofyYkIKBbAhdF0Zb3TnaFp4cGKPHX39pXBYGPDkAQ==",
|
||||||
|
"requires": {
|
||||||
|
"@reach/auto-id": "0.10.5",
|
||||||
|
"@reach/descendants": "0.10.5",
|
||||||
|
"@reach/utils": "0.10.5",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@reach/auto-id": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reach/auto-id/-/auto-id-0.10.5.tgz",
|
||||||
|
"integrity": "sha512-we4/bwjFxJ3F+2eaddQ1HltbKvJ7AB8clkN719El7Zugpn/vOjfPMOVUiBqTmPGLUvkYrq4tpuFwLvk2HyOVHg==",
|
||||||
|
"requires": {
|
||||||
|
"@reach/utils": "0.10.5",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@reach/descendants": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reach/descendants/-/descendants-0.10.5.tgz",
|
||||||
|
"integrity": "sha512-8HhN4DwS/HsPQ+Ym/Ft/XJ1spXBYdE8hqpnbYR9UcU7Nx3oDbTIdhjA6JXXt23t5avYIx2jRa8YHCtVKSHuiwA==",
|
||||||
|
"requires": {
|
||||||
|
"@reach/utils": "0.10.5",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@reach/utils": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@reach/utils/-/utils-0.10.5.tgz",
|
||||||
|
"integrity": "sha512-5E/xxQnUbmpI/LrufBAOXjunl96DnqX6B4zC2MO2KH/dRzLug5gM5VuOwV26egsp0jvsSPxojwciOhS43px3qw==",
|
||||||
|
"requires": {
|
||||||
|
"@types/warning": "^3.0.0",
|
||||||
|
"tslib": "^2.0.0",
|
||||||
|
"warning": "^4.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@reach/utils": {
|
"@reach/utils": {
|
||||||
"version": "0.10.1",
|
"version": "0.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/@reach/utils/-/utils-0.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/@reach/utils/-/utils-0.10.1.tgz",
|
||||||
@ -1555,15 +1638,15 @@
|
|||||||
"@styled-system/css": "^5.1.5"
|
"@styled-system/css": "^5.1.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@tlon/indigo-light": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tlon/indigo-light/-/indigo-light-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-3OPSdf9cejP/TSzWXuBaYbzLtAfBzQnc75SlPLkoPfwpxnv1Bvy9hiWngLY0WnKRR6lMOldnkYQCCuNWeDibYQ=="
|
||||||
|
},
|
||||||
"@tlon/indigo-react": {
|
"@tlon/indigo-react": {
|
||||||
"version": "1.1.12",
|
"version": "1.1.15",
|
||||||
"resolved": "https://registry.npmjs.org/@tlon/indigo-react/-/indigo-react-1.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/@tlon/indigo-react/-/indigo-react-1.1.15.tgz",
|
||||||
"integrity": "sha512-XBJjHwaslEwZA2r09qnoh84BeVLnd/jwZRkhq71KNABnRD+QRtg/dYNvtswueML4Km89Vx9QBtCIEIeujzrblw==",
|
"integrity": "sha512-Ao+1hAJjN5y1gDyT7GIUgXORPXTIpZKVVtrS++ZGYBemYMSq3oJFMIZertsSZbDHuh/TsVPenJrMUZBpV60law=="
|
||||||
"requires": {
|
|
||||||
"@reach/menu-button": "^0.10.0",
|
|
||||||
"@styled-system/css": "^5.1.5",
|
|
||||||
"@types/styled-system__css": "^5.0.5"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"@types/anymatch": {
|
"@types/anymatch": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
@ -1667,14 +1750,6 @@
|
|||||||
"integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
|
"integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/styled-system__css": {
|
|
||||||
"version": "5.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/styled-system__css/-/styled-system__css-5.0.8.tgz",
|
|
||||||
"integrity": "sha512-skv+daDje8vWQ8wnqVV0GCzgWVKx4gI9lJpAxWE77s52Ne6k/SCPP8HGE4BFbWDvK+qi5O3p89BGWVOQ1VHjMg==",
|
|
||||||
"requires": {
|
|
||||||
"csstype": "^2.6.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@types/tapable": {
|
"@types/tapable": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.5.tgz",
|
||||||
@ -3328,7 +3403,8 @@
|
|||||||
"csstype": {
|
"csstype": {
|
||||||
"version": "2.6.10",
|
"version": "2.6.10",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.10.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.10.tgz",
|
||||||
"integrity": "sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w=="
|
"integrity": "sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"cyclist": {
|
"cyclist": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -5949,6 +6025,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
|
||||||
"integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg=="
|
"integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg=="
|
||||||
},
|
},
|
||||||
|
"markdown-to-jsx": {
|
||||||
|
"version": "6.11.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-6.11.4.tgz",
|
||||||
|
"integrity": "sha512-3lRCD5Sh+tfA52iGgfs/XZiw33f7fFX9Bn55aNnVNUd2GzLDkOWyKYYD8Yju2B1Vn+feiEdgJs8T6Tg0xNokPw==",
|
||||||
|
"requires": {
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
|
"unquote": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"md5.js": {
|
"md5.js": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||||
@ -5985,6 +6070,11 @@
|
|||||||
"p-is-promise": "^2.0.0"
|
"p-is-promise": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"memoize-one": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA=="
|
||||||
|
},
|
||||||
"memory-fs": {
|
"memory-fs": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
||||||
@ -7491,6 +7581,15 @@
|
|||||||
"tiny-warning": "^1.0.0"
|
"tiny-warning": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-window": {
|
||||||
|
"version": "1.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.5.tgz",
|
||||||
|
"integrity": "sha512-HeTwlNa37AFa8MDZFZOKcNEkuF2YflA0hpGPiTT9vR7OawEt+GZbfM6wqkBahD3D3pUjIabQYzsnY/BSJbgq6Q==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.0.0",
|
||||||
|
"memoize-one": ">=3.1.1 <6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
@ -9257,6 +9356,11 @@
|
|||||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
|
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"unquote": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ="
|
||||||
|
},
|
||||||
"unset-value": {
|
"unset-value": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-0.1.2.tgz",
|
||||||
@ -9565,7 +9669,8 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@ -9586,12 +9691,14 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -9606,17 +9713,20 @@
|
|||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@ -9733,7 +9843,8 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@ -9745,6 +9856,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -9759,6 +9871,7 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@ -9766,12 +9879,14 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@ -9790,6 +9905,7 @@
|
|||||||
"version": "0.5.3",
|
"version": "0.5.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "^1.2.5"
|
"minimist": "^1.2.5"
|
||||||
}
|
}
|
||||||
@ -9851,7 +9967,8 @@
|
|||||||
"npm-normalize-package-bin": {
|
"npm-normalize-package-bin": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"npm-packlist": {
|
"npm-packlist": {
|
||||||
"version": "1.4.8",
|
"version": "1.4.8",
|
||||||
@ -9879,7 +9996,8 @@
|
|||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@ -9891,6 +10009,7 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@ -9968,7 +10087,8 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@ -10004,6 +10124,7 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@ -10023,6 +10144,7 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -10066,12 +10188,14 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -10552,7 +10676,8 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@ -10573,12 +10698,14 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@ -10593,17 +10720,20 @@
|
|||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@ -10720,7 +10850,8 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@ -10732,6 +10863,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -10746,6 +10878,7 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@ -10753,12 +10886,14 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@ -10777,6 +10912,7 @@
|
|||||||
"version": "0.5.3",
|
"version": "0.5.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "^1.2.5"
|
"minimist": "^1.2.5"
|
||||||
}
|
}
|
||||||
@ -10838,7 +10974,8 @@
|
|||||||
"npm-normalize-package-bin": {
|
"npm-normalize-package-bin": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"npm-packlist": {
|
"npm-packlist": {
|
||||||
"version": "1.4.8",
|
"version": "1.4.8",
|
||||||
@ -10866,7 +11003,8 @@
|
|||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@ -10878,6 +11016,7 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@ -10955,7 +11094,8 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@ -10991,6 +11131,7 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@ -11010,6 +11151,7 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@ -11053,12 +11195,14 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -5,13 +5,17 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.10.5",
|
"@babel/runtime": "^7.10.5",
|
||||||
|
"@reach/disclosure": "^0.10.5",
|
||||||
"@reach/menu-button": "^0.10.1",
|
"@reach/menu-button": "^0.10.1",
|
||||||
"@tlon/indigo-react": "^1.1.10",
|
"@reach/tabs": "^0.10.5",
|
||||||
|
"@tlon/indigo-light": "^1.0.3",
|
||||||
|
"@tlon/indigo-react": "^1.1.15",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"codemirror": "^5.51.0",
|
"codemirror": "^5.51.0",
|
||||||
"css-loader": "^3.5.3",
|
"css-loader": "^3.5.3",
|
||||||
"formik": "^2.1.4",
|
"formik": "^2.1.4",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
|
"markdown-to-jsx": "^6.11.4",
|
||||||
"moment": "^2.20.1",
|
"moment": "^2.20.1",
|
||||||
"mousetrap": "^1.6.5",
|
"mousetrap": "^1.6.5",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
@ -20,6 +24,7 @@
|
|||||||
"react-dom": "^16.8.6",
|
"react-dom": "^16.8.6",
|
||||||
"react-markdown": "^4.3.1",
|
"react-markdown": "^4.3.1",
|
||||||
"react-router-dom": "^5.0.0",
|
"react-router-dom": "^5.0.0",
|
||||||
|
"react-window": "^1.8.5",
|
||||||
"remark-disable-tokenizers": "^1.0.24",
|
"remark-disable-tokenizers": "^1.0.24",
|
||||||
"style-loader": "^1.2.1",
|
"style-loader": "^1.2.1",
|
||||||
"styled-components": "^5.1.0",
|
"styled-components": "^5.1.0",
|
||||||
|
@ -6,7 +6,8 @@ import styled, { ThemeProvider, createGlobalStyle } from 'styled-components';
|
|||||||
|
|
||||||
import './css/indigo-static.css';
|
import './css/indigo-static.css';
|
||||||
import './css/fonts.css';
|
import './css/fonts.css';
|
||||||
import { light, dark, inverted, paperDark } from '@tlon/indigo-react';
|
import light from './themes/light';
|
||||||
|
import dark from './themes/old-dark';
|
||||||
|
|
||||||
import LaunchApp from './apps/launch/app';
|
import LaunchApp from './apps/launch/app';
|
||||||
import ChatApp from './apps/chat/app';
|
import ChatApp from './apps/chat/app';
|
||||||
@ -16,7 +17,7 @@ import LinksApp from './apps/links/app';
|
|||||||
import PublishApp from './apps/publish/app';
|
import PublishApp from './apps/publish/app';
|
||||||
|
|
||||||
import StatusBar from './components/StatusBar';
|
import StatusBar from './components/StatusBar';
|
||||||
import NotFound from './components/404';
|
import ErrorComponent from './components/Error';
|
||||||
|
|
||||||
import GlobalStore from './store/store';
|
import GlobalStore from './store/store';
|
||||||
import GlobalSubscription from './subscription/global';
|
import GlobalSubscription from './subscription/global';
|
||||||
@ -85,7 +86,7 @@ class App extends React.Component {
|
|||||||
const associations = this.state.associations ? this.state.associations : { contacts: {} };
|
const associations = this.state.associations ? this.state.associations : { contacts: {} };
|
||||||
const selectedGroups = this.state.selectedGroups ? this.state.selectedGroups : [];
|
const selectedGroups = this.state.selectedGroups ? this.state.selectedGroups : [];
|
||||||
const { state } = this;
|
const { state } = this;
|
||||||
const theme = state.dark ? paperDark : light;
|
const theme = state.dark ? dark : light;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
@ -161,7 +162,11 @@ class App extends React.Component {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Route component={NotFound} />
|
<Route
|
||||||
|
render={(props) => (
|
||||||
|
<ErrorComponent {...props} code={404} description="Not Found" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Content>
|
</Content>
|
||||||
</Router>
|
</Router>
|
||||||
|
@ -94,6 +94,7 @@ interface ChatScreenState {
|
|||||||
scrollLocked: boolean;
|
scrollLocked: boolean;
|
||||||
read: number;
|
read: number;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
messages: Map<string, string>;
|
||||||
lastScrollHeight: number | null;
|
lastScrollHeight: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +119,7 @@ export class ChatScreen extends Component<ChatScreenProps, ChatScreenState> {
|
|||||||
scrollLocked: false,
|
scrollLocked: false,
|
||||||
read: props.read,
|
read: props.read,
|
||||||
active: true,
|
active: true,
|
||||||
|
messages: new Map(),
|
||||||
// only for FF
|
// only for FF
|
||||||
lastScrollHeight: null,
|
lastScrollHeight: null,
|
||||||
};
|
};
|
||||||
@ -594,8 +596,12 @@ export class ChatScreen extends Component<ChatScreenProps, ChatScreenState> {
|
|||||||
envelopes={props.envelopes}
|
envelopes={props.envelopes}
|
||||||
contacts={props.contacts}
|
contacts={props.contacts}
|
||||||
onEnter={() => this.setState({ scrollLocked: false })}
|
onEnter={() => this.setState({ scrollLocked: false })}
|
||||||
|
onUnmount={(msg: string) => this.setState({
|
||||||
|
messages: this.state.messages.set(props.station, msg)
|
||||||
|
})}
|
||||||
s3={props.s3}
|
s3={props.s3}
|
||||||
placeholder="Message..."
|
placeholder="Message..."
|
||||||
|
message={this.state.messages.get(props.station) || ""}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -40,7 +40,7 @@ export class ChatInput extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
message: '',
|
message: props.message,
|
||||||
patpSearch: null
|
patpSearch: null
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,24 +57,6 @@ export class ChatInput extends Component {
|
|||||||
|
|
||||||
this.editor = null;
|
this.editor = null;
|
||||||
|
|
||||||
// perf testing:
|
|
||||||
/* let closure = () => {
|
|
||||||
let x = 0;
|
|
||||||
for (var i = 0; i < 30; i++) {
|
|
||||||
x++;
|
|
||||||
props.api.chat.message(
|
|
||||||
props.station,
|
|
||||||
`~${window.ship}`,
|
|
||||||
Date.now(),
|
|
||||||
{
|
|
||||||
text: `${x}`
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
setTimeout(closure, 1000);
|
|
||||||
};
|
|
||||||
this.closure = closure.bind(this);*/
|
|
||||||
|
|
||||||
moment.updateLocale('en', {
|
moment.updateLocale('en', {
|
||||||
relativeTime : {
|
relativeTime : {
|
||||||
past: function(input) {
|
past: function(input) {
|
||||||
@ -99,6 +81,10 @@ export class ChatInput extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.props.onUnmount(this.state.message);
|
||||||
|
}
|
||||||
|
|
||||||
nextAutocompleteSuggestion(backward = false) {
|
nextAutocompleteSuggestion(backward = false) {
|
||||||
const { patpSuggestions } = this.state;
|
const { patpSuggestions } = this.state;
|
||||||
let idx = patpSuggestions.findIndex(s => s === this.state.selectedSuggestion);
|
let idx = patpSuggestions.findIndex(s => s === this.state.selectedSuggestion);
|
||||||
@ -150,6 +136,9 @@ export class ChatInput extends Component {
|
|||||||
if(patpSearch !== null) {
|
if(patpSearch !== null) {
|
||||||
this.patpAutocomplete(value, false);
|
this.patpAutocomplete(value, false);
|
||||||
}
|
}
|
||||||
|
this.setState({
|
||||||
|
message: value
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getLetterType(letter) {
|
getLetterType(letter) {
|
||||||
@ -209,29 +198,60 @@ export class ChatInput extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let message = [];
|
let message = [];
|
||||||
editorMessage.split(' ').map((each) => {
|
let isInCodeBlock = false;
|
||||||
if (this.isUrl(each)) {
|
let endOfCodeBlock = false;
|
||||||
if (message.length > 0) {
|
editorMessage.split(/\r?\n/).forEach((line) => {
|
||||||
message = message.join(' ');
|
// A line of backticks enters and exits a codeblock
|
||||||
message = this.getLetterType(message);
|
if (line.startsWith('```')) {
|
||||||
props.api.chat.message(
|
// But we need to check if we've ended a codeblock
|
||||||
props.station,
|
endOfCodeBlock = isInCodeBlock;
|
||||||
`~${window.ship}`,
|
isInCodeBlock = (!isInCodeBlock);
|
||||||
Date.now(),
|
|
||||||
message
|
|
||||||
);
|
|
||||||
message = [];
|
|
||||||
}
|
|
||||||
const URL = this.getLetterType(each);
|
|
||||||
props.api.chat.message(
|
|
||||||
props.station,
|
|
||||||
`~${window.ship}`,
|
|
||||||
Date.now(),
|
|
||||||
URL
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return message.push(each);
|
endOfCodeBlock = false;
|
||||||
}
|
}
|
||||||
|
if (isInCodeBlock) {
|
||||||
|
message.push(`\n${line}`);
|
||||||
|
} else if (endOfCodeBlock) {
|
||||||
|
message.push(`\n${line}\n`);
|
||||||
|
} else {
|
||||||
|
line.split(/\s/).forEach((str) => {
|
||||||
|
if (
|
||||||
|
(str.startsWith('`') && str !== '`')
|
||||||
|
|| (str === '`' && !isInCodeBlock)
|
||||||
|
) {
|
||||||
|
isInCodeBlock = true;
|
||||||
|
} else if (
|
||||||
|
(str.endsWith('`') && str !== '`')
|
||||||
|
|| (str === '`' && isInCodeBlock)
|
||||||
|
) {
|
||||||
|
isInCodeBlock = false;
|
||||||
|
}
|
||||||
|
if (this.isUrl(str) && !isInCodeBlock) {
|
||||||
|
if (message.length > 0) {
|
||||||
|
message = message.join(' ');
|
||||||
|
message = this.getLetterType(message);
|
||||||
|
props.api.chat.message(
|
||||||
|
props.station,
|
||||||
|
`~${window.ship}`,
|
||||||
|
Date.now(),
|
||||||
|
message
|
||||||
|
);
|
||||||
|
message = [];
|
||||||
|
}
|
||||||
|
const URL = this.getLetterType(str);
|
||||||
|
props.api.chat.message(
|
||||||
|
props.station,
|
||||||
|
`~${window.ship}`,
|
||||||
|
Date.now(),
|
||||||
|
URL
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message.push(str);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (message.length > 0) {
|
if (message.length > 0) {
|
||||||
@ -246,8 +266,24 @@ export class ChatInput extends Component {
|
|||||||
message = [];
|
message = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// perf:
|
// perf testing:
|
||||||
// setTimeout(this.closure, 2000);
|
/*let closure = () => {
|
||||||
|
let x = 0;
|
||||||
|
for (var i = 0; i < 30; i++) {
|
||||||
|
x++;
|
||||||
|
props.api.chat.message(
|
||||||
|
props.station,
|
||||||
|
`~${window.ship}`,
|
||||||
|
Date.now(),
|
||||||
|
{
|
||||||
|
text: `${x}`
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
setTimeout(closure, 1000);
|
||||||
|
};
|
||||||
|
this.closure = closure.bind(this);
|
||||||
|
setTimeout(this.closure, 2000);*/
|
||||||
|
|
||||||
this.editor.setValue('');
|
this.editor.setValue('');
|
||||||
}
|
}
|
||||||
@ -364,6 +400,7 @@ export class ChatInput extends Component {
|
|||||||
style={{ flexGrow: 1, maxHeight: '224px', width: 'calc(100% - 72px)' }}
|
style={{ flexGrow: 1, maxHeight: '224px', width: 'calc(100% - 72px)' }}
|
||||||
>
|
>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
|
value={this.props.message}
|
||||||
options={options}
|
options={options}
|
||||||
editorDidMount={(editor) => {
|
editorDidMount={(editor) => {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
|
28
pkg/interface/src/apps/chat/components/lib/content/code.js
Normal file
28
pkg/interface/src/apps/chat/components/lib/content/code.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
|
||||||
|
export default class CodeContent extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { props } = this;
|
||||||
|
const content = props.content;
|
||||||
|
|
||||||
|
const outputElement =
|
||||||
|
(Boolean(content.code.output) &&
|
||||||
|
content.code.output.length && content.code.output.length > 0) ?
|
||||||
|
(
|
||||||
|
<pre className={`f7 clamp-attachment pa1 mt0 mb0 b--gray4 b--gray1-d bl br bb`}>
|
||||||
|
{content.code.output[0].join('\n')}
|
||||||
|
</pre>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mv2">
|
||||||
|
<pre className={`f7 clamp-attachment pa1 mt0 mb0 bg-light-gray b--gray4 b--gray1-d ba`}>
|
||||||
|
{content.code.expression}
|
||||||
|
</pre>
|
||||||
|
{outputElement}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
65
pkg/interface/src/apps/chat/components/lib/content/text.js
Normal file
65
pkg/interface/src/apps/chat/components/lib/content/text.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import ReactMarkdown from 'react-markdown';
|
||||||
|
import RemarkDisableTokenizers from 'remark-disable-tokenizers';
|
||||||
|
import urbitOb from 'urbit-ob';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
const DISABLED_BLOCK_TOKENS = [
|
||||||
|
'indentedCode',
|
||||||
|
'blockquote',
|
||||||
|
'atxHeading',
|
||||||
|
'thematicBreak',
|
||||||
|
'list',
|
||||||
|
'setextHeading',
|
||||||
|
'html',
|
||||||
|
'definition',
|
||||||
|
'table'
|
||||||
|
];
|
||||||
|
|
||||||
|
const DISABLED_INLINE_TOKENS = [
|
||||||
|
'autoLink',
|
||||||
|
'url',
|
||||||
|
'email',
|
||||||
|
'link',
|
||||||
|
'reference'
|
||||||
|
];
|
||||||
|
|
||||||
|
const MessageMarkdown = React.memo(props => (
|
||||||
|
<ReactMarkdown
|
||||||
|
{...props}
|
||||||
|
plugins={[[
|
||||||
|
RemarkDisableTokenizers,
|
||||||
|
{ block: DISABLED_BLOCK_TOKENS, inline: DISABLED_INLINE_TOKENS }
|
||||||
|
]]} />
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
export default class TextContent extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { props } = this;
|
||||||
|
const content = props.content;
|
||||||
|
|
||||||
|
const group = content.text.match(
|
||||||
|
/([~][/])?(~[a-z]{3,6})(-[a-z]{6})?([/])(([a-z])+([/-])?)+/
|
||||||
|
);
|
||||||
|
if ((group !== null) // matched possible chatroom
|
||||||
|
&& (group[2].length > 2) // possible ship?
|
||||||
|
&& (urbitOb.isValidPatp(group[2]) // valid patp?
|
||||||
|
&& (group[0] === content.text))) { // entire message is room name?
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
className="bb b--black b--white-d f7 mono lh-copy v-top"
|
||||||
|
to={'/~groups/join/' + group.input}>
|
||||||
|
{content.text}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<section className="chat-md-message">
|
||||||
|
<MessageMarkdown source={content.text} />
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
101
pkg/interface/src/apps/chat/components/lib/content/url.js
Normal file
101
pkg/interface/src/apps/chat/components/lib/content/url.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
|
||||||
|
const IMAGE_REGEX =
|
||||||
|
/(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF|GIF|webp|WEBP|webm|WEBM|svg|SVG)$/;
|
||||||
|
|
||||||
|
const YOUTUBE_REGEX =
|
||||||
|
new RegExp(
|
||||||
|
String(/(?:https?:\/\/(?:[a-z]+.)?)/.source) // protocol
|
||||||
|
+ /(?:youtu\.?be(?:\.com)?\/)(?:embed\/)?/.source // short and long-links
|
||||||
|
+ /(?:(?:(?:(?:watch\?)?(?:time_continue=(?:[0-9]+))?.+v=)?([a-zA-Z0-9_-]+))(?:\?t\=(?:[0-9a-zA-Z]+))?)/.source // id
|
||||||
|
);
|
||||||
|
|
||||||
|
export default class UrlContent extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
unfold: false,
|
||||||
|
copied: false
|
||||||
|
};
|
||||||
|
this.unfoldEmbed = this.unfoldEmbed.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
unfoldEmbed(id) {
|
||||||
|
let unfoldState = this.state.unfold;
|
||||||
|
unfoldState = !unfoldState;
|
||||||
|
this.setState({ unfold: unfoldState });
|
||||||
|
const iframe = this.refs.iframe;
|
||||||
|
iframe.setAttribute('src', iframe.getAttribute('data-src'));
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { props } = this;
|
||||||
|
const content = props.content;
|
||||||
|
const imgMatch = IMAGE_REGEX.exec(props.content.url);
|
||||||
|
const ytMatch = YOUTUBE_REGEX.exec(props.content.url);
|
||||||
|
|
||||||
|
let contents = content.url;
|
||||||
|
if (imgMatch) {
|
||||||
|
contents = (
|
||||||
|
<img
|
||||||
|
className="o-80-d"
|
||||||
|
src={content.url}
|
||||||
|
style={{
|
||||||
|
width: '50%',
|
||||||
|
maxWidth: '250px'
|
||||||
|
}}
|
||||||
|
></img>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<a className={`f7 lh-copy v-top word-break-all`}
|
||||||
|
href={content.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{contents}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
} else if (ytMatch) {
|
||||||
|
contents = (
|
||||||
|
<div className={'embed-container mb2 w-100 w-75-l w-50-xl ' +
|
||||||
|
((this.state.unfold === true)
|
||||||
|
? 'db' : 'dn')}
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
ref="iframe"
|
||||||
|
width="560"
|
||||||
|
height="315"
|
||||||
|
data-src={`https://www.youtube.com/embed/${ytMatch[1]}`}
|
||||||
|
frameBorder="0" allow="picture-in-picture, fullscreen"
|
||||||
|
>
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<a href={content.url}
|
||||||
|
className={`f7 lh-copy v-top bb b--white-d word-break-all`}
|
||||||
|
href={content.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">{content.url}</a>
|
||||||
|
<a className="ml2 f7 pointer lh-copy v-top"
|
||||||
|
onClick={e => this.unfoldEmbed()}>
|
||||||
|
[embed]
|
||||||
|
</a>
|
||||||
|
{contents}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<a className={`f7 lh-copy v-top bb b--white-d b--black word-break-all`}
|
||||||
|
href={content.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{contents}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
import TextContent from './content/text';
|
||||||
|
import CodeContent from './content/code';
|
||||||
|
import UrlContent from './content/url';
|
||||||
|
|
||||||
|
|
||||||
|
export default class MessageContent extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { props } = this;
|
||||||
|
|
||||||
|
const content = props.letter;
|
||||||
|
|
||||||
|
if ('code' in content) {
|
||||||
|
return <CodeContent content={content} />;
|
||||||
|
} else if ('url' in content) {
|
||||||
|
return <UrlContent content={content} />;
|
||||||
|
} else if ('me' in content) {
|
||||||
|
return (
|
||||||
|
<p className='f7 i lh-copy v-top'>
|
||||||
|
{content.me}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ('text' in content) {
|
||||||
|
return <TextContent content={content} />;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,275 +1,127 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { OverlaySigil } from './overlay-sigil';
|
import { OverlaySigil } from './overlay-sigil';
|
||||||
|
import MessageContent from './message-content';
|
||||||
import { uxToHex, cite, writeText } from '../../../../lib/util';
|
import { uxToHex, cite, writeText } from '../../../../lib/util';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
import RemarkDisableTokenizers from 'remark-disable-tokenizers';
|
|
||||||
import urbitOb from 'urbit-ob';
|
|
||||||
|
|
||||||
const DISABLED_BLOCK_TOKENS = [
|
|
||||||
'indentedCode',
|
|
||||||
'blockquote',
|
|
||||||
'atxHeading',
|
|
||||||
'thematicBreak',
|
|
||||||
'list',
|
|
||||||
'setextHeading',
|
|
||||||
'html',
|
|
||||||
'definition',
|
|
||||||
'table'
|
|
||||||
];
|
|
||||||
|
|
||||||
const DISABLED_INLINE_TOKENS = [
|
|
||||||
'autoLink',
|
|
||||||
'url',
|
|
||||||
'email',
|
|
||||||
'link',
|
|
||||||
'reference'
|
|
||||||
];
|
|
||||||
|
|
||||||
const MessageMarkdown = React.memo(
|
|
||||||
props => (<ReactMarkdown
|
|
||||||
{...props}
|
|
||||||
plugins={[[RemarkDisableTokenizers, { block: DISABLED_BLOCK_TOKENS, inline: DISABLED_INLINE_TOKENS }]]}
|
|
||||||
/>));
|
|
||||||
|
|
||||||
export class Message extends Component {
|
export class Message extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
unfold: false,
|
|
||||||
copied: false
|
copied: false
|
||||||
};
|
};
|
||||||
this.unFoldEmbed = this.unFoldEmbed.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unFoldEmbed(id) {
|
|
||||||
let unfoldState = this.state.unfold;
|
|
||||||
unfoldState = !unfoldState;
|
|
||||||
this.setState({ unfold: unfoldState });
|
|
||||||
const iframe = this.refs.iframe;
|
|
||||||
iframe.setAttribute('src', iframe.getAttribute('data-src'));
|
|
||||||
}
|
|
||||||
|
|
||||||
renderContent() {
|
|
||||||
const { props } = this;
|
|
||||||
const letter = props.msg.letter;
|
|
||||||
|
|
||||||
if ('code' in letter) {
|
|
||||||
const outputElement =
|
|
||||||
(Boolean(letter.code.output) &&
|
|
||||||
letter.code.output.length && letter.code.output.length > 0) ?
|
|
||||||
(
|
|
||||||
<pre className="f7 clamp-attachment pa1 mt0 mb0 b--gray4 b--gray1-d bl br bb">
|
|
||||||
{letter.code.output[0].join('\n')}
|
|
||||||
</pre>
|
|
||||||
) : null;
|
|
||||||
return (
|
|
||||||
<div className="mv2">
|
|
||||||
<pre className="f7 clamp-attachment pa1 mt0 mb0 bg-light-gray b--gray4 b--gray1-d ba">
|
|
||||||
{letter.code.expression}
|
|
||||||
</pre>
|
|
||||||
{outputElement}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else if ('url' in letter) {
|
|
||||||
const imgMatch =
|
|
||||||
/(jpg|img|png|gif|tiff|jpeg|JPG|IMG|PNG|TIFF|GIF|webp|WEBP|svg|SVG)$/
|
|
||||||
.exec(letter.url);
|
|
||||||
const youTubeRegex = new RegExp(String(/(?:https?:\/\/(?:[a-z]+.)?)/.source) // protocol
|
|
||||||
+ /(?:youtu\.?be(?:\.com)?\/)(?:embed\/)?/.source // short and long-links
|
|
||||||
+ /(?:(?:(?:(?:watch\?)?(?:time_continue=(?:[0-9]+))?.+v=)?([a-zA-Z0-9_-]+))(?:\?t\=(?:[0-9a-zA-Z]+))?)/.source // id
|
|
||||||
);
|
|
||||||
const ytMatch =
|
|
||||||
youTubeRegex.exec(letter.url);
|
|
||||||
let contents = letter.url;
|
|
||||||
if (imgMatch) {
|
|
||||||
contents = (
|
|
||||||
<img
|
|
||||||
className="o-80-d"
|
|
||||||
src={letter.url}
|
|
||||||
style={{
|
|
||||||
height: 'min(250px, 20vh)',
|
|
||||||
maxWidth: 'calc(100% - 36px - 1.5rem)',
|
|
||||||
objectFit: 'contain'
|
|
||||||
}}
|
|
||||||
></img>
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<a className="f7 lh-copy v-top word-break-all"
|
|
||||||
href={letter.url}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{contents}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
} else if (ytMatch) {
|
|
||||||
contents = (
|
|
||||||
<div className={'embed-container mb2 w-100 w-75-l w-50-xl ' +
|
|
||||||
((this.state.unfold === true)
|
|
||||||
? 'db' : 'dn')}
|
|
||||||
>
|
|
||||||
<iframe
|
|
||||||
ref="iframe"
|
|
||||||
width="560"
|
|
||||||
height="315"
|
|
||||||
data-src={`https://www.youtube.com/embed/${ytMatch[1]}`}
|
|
||||||
frameBorder="0" allow="picture-in-picture, fullscreen"
|
|
||||||
>
|
|
||||||
</iframe>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<a href={letter.url}
|
|
||||||
className="f7 lh-copy v-top bb b--white-d word-break-all"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{letter.url}
|
|
||||||
</a>
|
|
||||||
<a className="ml2 f7 pointer lh-copy v-top"
|
|
||||||
onClick={e => this.unFoldEmbed()}
|
|
||||||
>
|
|
||||||
[embed]
|
|
||||||
</a>
|
|
||||||
{contents}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<a className="f7 lh-copy v-top bb b--white-d b--black word-break-all"
|
|
||||||
href={letter.url}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{contents}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if ('me' in letter) {
|
|
||||||
return (
|
|
||||||
<p className='f7 i lh-copy v-top'>
|
|
||||||
{letter.me}
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const group = letter.text.match(
|
|
||||||
/([~][/])?(~[a-z]{3,6})(-[a-z]{6})?([/])(([a-z])+([/-])?)+/
|
|
||||||
);
|
|
||||||
if ((group !== null) // matched possible chatroom
|
|
||||||
&& (group[2].length > 2) // possible ship?
|
|
||||||
&& (urbitOb.isValidPatp(group[2]) // valid patp?
|
|
||||||
&& (group[0] === letter.text))) { // entire message is room name?
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
className="bb b--black b--white-d f7 mono lh-copy v-top"
|
|
||||||
to={'/~groups/join/' + group.input}
|
|
||||||
>
|
|
||||||
{letter.text}
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<section className="chat-md-message">
|
|
||||||
<MessageMarkdown
|
|
||||||
source={letter.text}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { props, state } = this;
|
const { props, state } = this;
|
||||||
|
|
||||||
const pending = props.msg.pending ? ' o-40' : '';
|
const pending = props.msg.pending ? ' o-40' : '';
|
||||||
const datestamp = '~' + moment.unix(props.msg.when / 1000).format('YYYY.M.D');
|
const containerClass =
|
||||||
|
props.renderSigil ?
|
||||||
|
`w-100 f7 pl3 pt4 pr3 cf flex lh-copy ` + pending :
|
||||||
|
'w-100 pr3 cf hide-child flex' + pending;
|
||||||
|
|
||||||
|
const timestamp =
|
||||||
|
moment.unix(props.msg.when / 1000).format(
|
||||||
|
props.renderSigil ? 'hh:mm a' : 'hh:mm'
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={this.containerRef}
|
||||||
|
className={containerClass}
|
||||||
|
style={{
|
||||||
|
minHeight: 'min-content'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
props.renderSigil ? (
|
||||||
|
this.renderWithSigil(timestamp)
|
||||||
|
) : (
|
||||||
|
this.renderWithoutSigil(timestamp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderWithSigil(timestamp) {
|
||||||
|
const { props, state } = this;
|
||||||
const paddingTop = props.paddingTop ? { 'paddingTop': '6px' } : '';
|
const paddingTop = props.paddingTop ? { 'paddingTop': '6px' } : '';
|
||||||
|
const datestamp =
|
||||||
|
'~' + moment.unix(props.msg.when / 1000).format('YYYY.M.D');
|
||||||
|
|
||||||
if (props.renderSigil) {
|
const contact = props.msg.author in props.contacts
|
||||||
const timestamp = moment.unix(props.msg.when / 1000).format('hh:mm a');
|
? props.contacts[props.msg.author] : false;
|
||||||
|
let name = `~${props.msg.author}`;
|
||||||
const contact = props.msg.author in props.contacts
|
let color = '#000000';
|
||||||
? props.contacts[props.msg.author] : false;
|
let sigilClass = 'mix-blend-diff';
|
||||||
let name = `~${props.msg.author}`;
|
if (contact) {
|
||||||
let color = '#000000';
|
name = (contact.nickname.length > 0)
|
||||||
let sigilClass = 'mix-blend-diff';
|
? contact.nickname : `~${props.msg.author}`;
|
||||||
if (contact) {
|
color = `#${uxToHex(contact.color)}`;
|
||||||
name = (contact.nickname.length > 0)
|
sigilClass = '';
|
||||||
? contact.nickname : `~${props.msg.author}`;
|
|
||||||
color = `#${uxToHex(contact.color)}`;
|
|
||||||
sigilClass = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (`~${props.msg.author}` === name) {
|
|
||||||
name = cite(props.msg.author);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={this.containerRef}
|
|
||||||
className={
|
|
||||||
'w-100 f7 pl3 pt4 pr3 cf flex lh-copy ' + ' ' + pending
|
|
||||||
}
|
|
||||||
style={{
|
|
||||||
minHeight: 'min-content'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<OverlaySigil
|
|
||||||
ship={props.msg.author}
|
|
||||||
contact={contact}
|
|
||||||
color={color}
|
|
||||||
sigilClass={sigilClass}
|
|
||||||
association={props.association}
|
|
||||||
group={props.group}
|
|
||||||
className="fl pr3 v-top bg-white bg-gray0-d"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className="fr clamp-message white-d"
|
|
||||||
style={{ flexGrow: 1, marginTop: -8 }}
|
|
||||||
>
|
|
||||||
<div className="hide-child" style={paddingTop}>
|
|
||||||
<p className="v-mid f9 gray2 dib mr3 c-default">
|
|
||||||
<span
|
|
||||||
className={'pointer ' + (contact.nickname || state.copied ? null : 'mono')}
|
|
||||||
onClick={() => {
|
|
||||||
writeText(props.msg.author);
|
|
||||||
this.setState({ copied: true });
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({ copied: false });
|
|
||||||
}, 800);
|
|
||||||
}}
|
|
||||||
title={`~${props.msg.author}`}
|
|
||||||
>
|
|
||||||
{state.copied && 'Copied' || name}
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
<p className="v-mid mono f9 gray2 dib">{timestamp}</p>
|
|
||||||
<p className="v-mid mono f9 ml2 gray2 dib child dn-s">{datestamp}</p>
|
|
||||||
</div>
|
|
||||||
{this.renderContent()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const timestamp = moment.unix(props.msg.when / 1000).format('hh:mm');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={'w-100 pr3 cf hide-child flex' + pending}
|
|
||||||
style={{
|
|
||||||
minHeight: 'min-content'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<p className="child pt2 pl2 pr1 mono f9 gray2 dib">{timestamp}</p>
|
|
||||||
<div className="fr f7 clamp-message white-d pr3 lh-copy" style={{ flexGrow: 1 }}>
|
|
||||||
{this.renderContent()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (`~${props.msg.author}` === name) {
|
||||||
|
name = cite(props.msg.author);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex w-100">
|
||||||
|
<OverlaySigil
|
||||||
|
ship={props.msg.author}
|
||||||
|
contact={contact}
|
||||||
|
color={color}
|
||||||
|
sigilClass={sigilClass}
|
||||||
|
association={props.association}
|
||||||
|
group={props.group}
|
||||||
|
className="fl pr3 v-top bg-white bg-gray0-d"
|
||||||
|
/>
|
||||||
|
<div className="fr clamp-message white-d"
|
||||||
|
style={{ flexGrow: 1, marginTop: -8 }}>
|
||||||
|
<div className="hide-child" style={paddingTop}>
|
||||||
|
<p className={`v-mid f9 gray2 dib mr3 c-default`}>
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
'mw5 dib truncate pointer ' +
|
||||||
|
(contact.nickname || state.copied ? '' : 'mono')
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
writeText(props.msg.author);
|
||||||
|
this.setState({ copied: true });
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState({ copied: false });
|
||||||
|
}, 800);
|
||||||
|
}}
|
||||||
|
title={`~${props.msg.author}`}
|
||||||
|
>
|
||||||
|
{state.copied && 'Copied' || name}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className={`v-mid mono f9 gray2 dib`}>{timestamp}</p>
|
||||||
|
<p className={`v-mid mono f9 ml2 gray2 dib child dn-s`}>
|
||||||
|
{datestamp}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<MessageContent letter={props.msg.letter} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderWithoutSigil(timestamp) {
|
||||||
|
const { props } = this;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex w-100">
|
||||||
|
<p className="child pt2 pl2 pr1 mono f9 gray2 dib">{timestamp}</p>
|
||||||
|
<div className="fr f7 clamp-message white-d pr3 lh-copy"
|
||||||
|
style={{ flexGrow: 1 }}>
|
||||||
|
<MessageContent letter={props.msg.letter} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ export class ProfileOverlay extends Component {
|
|||||||
if (!(top || bottom)) {
|
if (!(top || bottom)) {
|
||||||
bottom = `-${Math.round(OVERLAY_HEIGHT / 2)}px`;
|
bottom = `-${Math.round(OVERLAY_HEIGHT / 2)}px`;
|
||||||
}
|
}
|
||||||
const containerStyle = { top, bottom, left: '100%' };
|
const containerStyle = { top, bottom, left: '100%', maxWidth: '160px' };
|
||||||
|
|
||||||
const isOwn = window.ship === ship;
|
const isOwn = window.ship === ship;
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ export class ProfileOverlay extends Component {
|
|||||||
</div>
|
</div>
|
||||||
<div className="pv3 pl3 pr2">
|
<div className="pv3 pl3 pr2">
|
||||||
{contact && contact.nickname && (
|
{contact && contact.nickname && (
|
||||||
<div className="b white-d">{contact.nickname}</div>
|
<div className="b white-d truncate">{contact.nickname}</div>
|
||||||
)}
|
)}
|
||||||
<div className="mono gray2">{cite(`~${ship}`)}</div>
|
<div className="mono gray2">{cite(`~${ship}`)}</div>
|
||||||
{!isOwn && (
|
{!isOwn && (
|
||||||
|
@ -6,6 +6,7 @@ import { Spinner } from '../../../components/Spinner';
|
|||||||
import { ChatTabBar } from './lib/chat-tabbar';
|
import { ChatTabBar } from './lib/chat-tabbar';
|
||||||
import { InviteSearch } from '../../../components/InviteSearch';
|
import { InviteSearch } from '../../../components/InviteSearch';
|
||||||
import SidebarSwitcher from '../../../components/SidebarSwitch';
|
import SidebarSwitcher from '../../../components/SidebarSwitch';
|
||||||
|
import Toggle from '../../../components/toggle';
|
||||||
|
|
||||||
export class SettingsScreen extends Component {
|
export class SettingsScreen extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -195,18 +196,12 @@ export class SettingsScreen extends Component {
|
|||||||
} else {
|
} else {
|
||||||
let inclusiveToggle = <div />;
|
let inclusiveToggle = <div />;
|
||||||
if (state.targetGroup) {
|
if (state.targetGroup) {
|
||||||
// TODO toggle component into /lib
|
|
||||||
const inclusiveClasses = state.inclusive
|
|
||||||
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
|
||||||
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
|
||||||
inclusiveToggle = (
|
inclusiveToggle = (
|
||||||
<div className="mt4">
|
<div className="mt4">
|
||||||
<input
|
<Toggle
|
||||||
type="checkbox"
|
boolean={state.inclusive}
|
||||||
style={{ WebkitAppearance: 'none', width: 28 }}
|
change={this.changeInclusive}
|
||||||
className={inclusiveClasses}
|
/>
|
||||||
onChange={this.changeInclusive}
|
|
||||||
/>
|
|
||||||
<span className="dib f9 white-d inter ml3">
|
<span className="dib f9 white-d inter ml3">
|
||||||
Add all members to group
|
Add all members to group
|
||||||
</span>
|
</span>
|
||||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|||||||
|
|
||||||
import Welcome from './lib/welcome';
|
import Welcome from './lib/welcome';
|
||||||
import { alphabetiseAssociations } from '../../../lib/util';
|
import { alphabetiseAssociations } from '../../../lib/util';
|
||||||
import { SidebarInvite } from './lib/sidebar-invite';
|
import SidebarInvite from '../../../components/SidebarInvite';
|
||||||
import { GroupItem } from './lib/group-item';
|
import { GroupItem } from './lib/group-item';
|
||||||
|
|
||||||
export class Sidebar extends Component {
|
export class Sidebar extends Component {
|
||||||
@ -51,10 +51,10 @@ export class Sidebar extends Component {
|
|||||||
.map((uid) => {
|
.map((uid) => {
|
||||||
return (
|
return (
|
||||||
<SidebarInvite
|
<SidebarInvite
|
||||||
uid={uid}
|
|
||||||
key={uid}
|
key={uid}
|
||||||
invite={props.invites[uid]}
|
invite={props.invites[uid]}
|
||||||
api={props.api}
|
onAccept={() => props.api.invite.accept('/chat', uid)}
|
||||||
|
onDecline={() => props.api.invite.decline('/chat', uid)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import ErrorBoundary from '../../../components/ErrorBoundary';
|
||||||
|
|
||||||
export class Skeleton extends Component {
|
export class Skeleton extends Component {
|
||||||
render() {
|
render() {
|
||||||
@ -61,7 +62,9 @@ export class Skeleton extends Component {
|
|||||||
width: 'calc(100% - 300px)'
|
width: 'calc(100% - 300px)'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{this.props.children}
|
<ErrorBoundary>
|
||||||
|
{this.props.children}
|
||||||
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,7 +6,6 @@ import urbitOb from 'urbit-ob';
|
|||||||
export class JoinScreen extends Component {
|
export class JoinScreen extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
group: '',
|
group: '',
|
||||||
error: false,
|
error: false,
|
||||||
@ -21,12 +20,11 @@ export class JoinScreen extends Component {
|
|||||||
this.componentDidUpdate();
|
this.componentDidUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate() {
|
||||||
const { props, state } = this;
|
const { props, state } = this;
|
||||||
// autojoin by URL, waits for group information
|
// autojoin by URL, waits for group information
|
||||||
if ((props.ship && props.name) &&
|
if ((props.ship && props.name) &&
|
||||||
(prevProps && (prevProps.groups !== props.groups))) {
|
(props.contacts && (Object.keys(props.contacts).length > 0) && !state.group)) {
|
||||||
console.log('autojoining');
|
|
||||||
const incomingGroup = `${props.ship}/${props.name}`;
|
const incomingGroup = `${props.ship}/${props.name}`;
|
||||||
// push to group if already exists
|
// push to group if already exists
|
||||||
if (`/ship/${incomingGroup}` in props.groups) {
|
if (`/ship/${incomingGroup}` in props.groups) {
|
||||||
@ -48,10 +46,8 @@ export class JoinScreen extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onClickJoin() {
|
onClickJoin() {
|
||||||
const { props, state } = this;
|
const { props, state } = this;
|
||||||
console.log('i am joining');
|
|
||||||
|
|
||||||
const { group } = state;
|
const { group } = state;
|
||||||
const [ship, name] = group.split('/');
|
const [ship, name] = group.split('/');
|
||||||
@ -101,14 +97,12 @@ export class JoinScreen extends Component {
|
|||||||
<p className="f8 lh-copy mt3 db">Enter a <span className="mono">~ship/group-name</span></p>
|
<p className="f8 lh-copy mt3 db">Enter a <span className="mono">~ship/group-name</span></p>
|
||||||
<p className="f9 gray2 mb4">Group names use lowercase, hyphens, and slashes.</p>
|
<p className="f9 gray2 mb4">Group names use lowercase, hyphens, and slashes.</p>
|
||||||
<textarea
|
<textarea
|
||||||
ref={ (e) => {
|
|
||||||
this.textarea = e;
|
|
||||||
} }
|
|
||||||
className={'f7 mono ba bg-gray0-d white-d pa3 mb2 db ' +
|
className={'f7 mono ba bg-gray0-d white-d pa3 mb2 db ' +
|
||||||
'focus-b--black focus-b--white-d b--gray3 b--gray2-d nowrap '}
|
'focus-b--black focus-b--white-d b--gray3 b--gray2-d nowrap overflow-y-hidden'}
|
||||||
placeholder="~zod/group-name"
|
placeholder="~zod/group-name"
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
rows={1}
|
rows={1}
|
||||||
|
cols={32}
|
||||||
onKeyPress={(e) => {
|
onKeyPress={(e) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -116,7 +110,7 @@ export class JoinScreen extends Component {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
resize: 'none'
|
resize: 'none',
|
||||||
}}
|
}}
|
||||||
onChange={this.groupChange}
|
onChange={this.groupChange}
|
||||||
value={this.state.group}
|
value={this.state.group}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import { FixedSizeList as List } from 'react-window';
|
||||||
|
|
||||||
import { ContactItem } from './contact-item';
|
import { ContactItem } from './contact-item';
|
||||||
import { ShareSheet } from './share-sheet';
|
import { ShareSheet } from './share-sheet';
|
||||||
import { Sigil } from '../../../../lib/sigil';
|
import { Sigil } from '../../../../lib/sigil';
|
||||||
@ -23,6 +25,7 @@ interface ContactSidebarProps {
|
|||||||
}
|
}
|
||||||
interface ContactSidebarState {
|
interface ContactSidebarState {
|
||||||
awaiting: boolean;
|
awaiting: boolean;
|
||||||
|
memberboxHeight: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -31,9 +34,20 @@ export class ContactSidebar extends Component<ContactSidebarProps, ContactSideba
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
awaiting: false
|
awaiting: false,
|
||||||
|
memberboxHeight: 0
|
||||||
};
|
};
|
||||||
|
this.memberbox = this.memberbox.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memberbox(element) {
|
||||||
|
if (element) {
|
||||||
|
this.setState({
|
||||||
|
memberboxHeight: element.getBoundingClientRect().height
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { props } = this;
|
const { props } = this;
|
||||||
|
|
||||||
@ -145,17 +159,17 @@ export class ContactSidebar extends Component<ContactSidebarProps, ContactSideba
|
|||||||
const detailHref = `/~groups/detail${props.path}`;
|
const detailHref = `/~groups/detail${props.path}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'bn br-m br-l br-xl b--gray4 b--gray1-d lh-copy h-100 ' +
|
<div ref={this.memberbox} className={'bn br-m br-l br-xl b--gray4 b--gray1-d lh-copy h-100 ' +
|
||||||
'flex-basis-100-s flex-basis-30-ns mw5-m mw5-l mw5-xl relative ' +
|
'flex-basis-100-s flex-basis-30-ns mw5-m mw5-l mw5-xl relative ' +
|
||||||
'overflow-hidden flex-shrink-0 ' + responsiveClasses}
|
'overflow-hidden flex-shrink-0 ' + responsiveClasses}
|
||||||
>
|
>
|
||||||
<div className="pt3 pb5 pl3 f8 db dn-m dn-l dn-xl">
|
<div className="pt3 pb5 pl3 f8 db dn-m dn-l dn-xl">
|
||||||
<Link to="/~groups/">{'⟵ All Groups'}</Link>
|
<Link to="/~groups/">{'⟵ All Groups'}</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-auto h-100">
|
<div className="overflow-auto h-100 flex flex-column">
|
||||||
<Link
|
<Link
|
||||||
to={'/~groups/add' + props.path}
|
to={'/~groups/add' + props.path}
|
||||||
className={((props.path.includes(window.ship))
|
className={((role === "admin" || role === "moderator")
|
||||||
? 'dib'
|
? 'dib'
|
||||||
: 'dn')}
|
: 'dn')}
|
||||||
>
|
>
|
||||||
@ -166,8 +180,20 @@ export class ContactSidebar extends Component<ContactSidebarProps, ContactSideba
|
|||||||
>Channels</Link>
|
>Channels</Link>
|
||||||
{shareSheet}
|
{shareSheet}
|
||||||
<h2 className="f9 pt4 pr4 pb2 pl4 gray2 c-default">Members</h2>
|
<h2 className="f9 pt4 pr4 pb2 pl4 gray2 c-default">Members</h2>
|
||||||
{contactItems}
|
<List
|
||||||
{groupItems}
|
height={this.state.memberboxHeight}
|
||||||
|
className="flex-auto"
|
||||||
|
itemCount={contactItems.length + groupItems.length}
|
||||||
|
itemSize={44}
|
||||||
|
width="100%"
|
||||||
|
>
|
||||||
|
{({ index, style }) => (<div style={style}>{
|
||||||
|
index <= (contactItems.length - 1) // If the index is within the length of contact items,
|
||||||
|
? contactItems[index] // show a contact item
|
||||||
|
: groupItems[index - contactItems.length] // Otherwise show a group item
|
||||||
|
}</div>)}
|
||||||
|
</List>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<Spinner awaiting={this.state.awaiting} text="Removing from group..." classes="pa2 ba absolute right-1 bottom-1 b--gray1-d" />
|
<Spinner awaiting={this.state.awaiting} text="Removing from group..." classes="pa2 ba absolute right-1 bottom-1 b--gray1-d" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Spinner } from '../../../../components/Spinner';
|
import { Spinner } from '../../../../components/Spinner';
|
||||||
|
import { Toggle } from '../../../../components/toggle';
|
||||||
import { GroupView } from '../../../../components/Group';
|
import { GroupView } from '../../../../components/Group';
|
||||||
import { deSig, uxToHex, writeText } from '../../../../lib/util';
|
import { deSig, uxToHex, writeText } from '../../../../lib/util';
|
||||||
|
import { roleForShip, resourceFromPath } from '../../../../lib/group';
|
||||||
|
|
||||||
export class GroupDetail extends Component {
|
export class GroupDetail extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -15,6 +17,7 @@ export class GroupDetail extends Component {
|
|||||||
};
|
};
|
||||||
this.changeTitle = this.changeTitle.bind(this);
|
this.changeTitle = this.changeTitle.bind(this);
|
||||||
this.changeDescription = this.changeDescription.bind(this);
|
this.changeDescription = this.changeDescription.bind(this);
|
||||||
|
this.changePolicy = this.changePolicy.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -47,6 +50,17 @@ export class GroupDetail extends Component {
|
|||||||
this.setState({ description: event.target.value });
|
this.setState({ description: event.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changePolicy() {
|
||||||
|
this.setState({ awaiting: true }, () => {
|
||||||
|
this.props.api.groups.changePolicy(resourceFromPath(this.props.path),
|
||||||
|
Boolean(this.props.group?.policy?.open)
|
||||||
|
? { replace: { invite: { pending: [] } } }
|
||||||
|
: { replace: { open: { banned: [], banRanks: [] } } }
|
||||||
|
).then(() => this.setState({ awaiting: false }));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderDetail() {
|
renderDetail() {
|
||||||
const { props } = this;
|
const { props } = this;
|
||||||
|
|
||||||
@ -175,7 +189,8 @@ export class GroupDetail extends Component {
|
|||||||
|
|
||||||
const { group, association } = props;
|
const { group, association } = props;
|
||||||
|
|
||||||
const groupOwner = (deSig(props.match.params.ship) === window.ship);
|
const ourRole = roleForShip(group, window.ship);
|
||||||
|
const groupOwner = (ourRole === 'admin');
|
||||||
|
|
||||||
const deleteButtonClasses = (groupOwner) ? 'b--red2 red2 pointer bg-gray0-d' : 'b--gray3 gray3 bg-gray0-d c-default';
|
const deleteButtonClasses = (groupOwner) ? 'b--red2 red2 pointer bg-gray0-d' : 'b--gray3 gray3 bg-gray0-d c-default';
|
||||||
|
|
||||||
@ -280,7 +295,17 @@ export class GroupDetail extends Component {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p className="f9 mt3 lh-copy">Delete Group</p>
|
<div className="relative w-100 mt6" style={{ maxWidth: '29rem' }}>
|
||||||
|
<Toggle
|
||||||
|
boolean={(Boolean(group?.policy?.invite))}
|
||||||
|
change={this.changePolicy}
|
||||||
|
/>
|
||||||
|
<span className="dib f9 white-d inter ml3">Private Group</span>
|
||||||
|
<p className="f9 gray2 pt1" style={{ paddingLeft: 40 }}>
|
||||||
|
If private, members must be invited
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p className="f9 mt6 lh-copy">Delete Group</p>
|
||||||
<p className="f9 gray2 mb2">
|
<p className="f9 gray2 mb2">
|
||||||
Permanently delete this group. All current members will no longer see this group.
|
Permanently delete this group. All current members will no longer see this group.
|
||||||
</p>
|
</p>
|
||||||
|
@ -3,7 +3,7 @@ import React, { Component } from 'react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { GroupItem } from './group-item';
|
import { GroupItem } from './group-item';
|
||||||
import { Sigil } from '../../../../lib/sigil';
|
import { Sigil } from '../../../../lib/sigil';
|
||||||
import { SidebarInvite } from './sidebar-invite';
|
import SidebarInvite from '../../../../components/SidebarInvite';
|
||||||
import { Welcome } from './welcome';
|
import { Welcome } from './welcome';
|
||||||
|
|
||||||
import { cite } from '../../../../lib/util';
|
import { cite } from '../../../../lib/util';
|
||||||
@ -48,10 +48,18 @@ export class GroupSidebar extends Component {
|
|||||||
return (
|
return (
|
||||||
<SidebarInvite
|
<SidebarInvite
|
||||||
key={uid}
|
key={uid}
|
||||||
api={props.api}
|
|
||||||
invite={invite}
|
invite={invite}
|
||||||
uid={uid}
|
onAccept={() => {
|
||||||
history={props.history}
|
const [,,ship, name] = invite.path.split('/');
|
||||||
|
const resource = { ship, name };
|
||||||
|
api.contacts.join(resource).then(() => {
|
||||||
|
api.invite.accept('/contacts', uid);
|
||||||
|
});
|
||||||
|
props.history.push(`/~groups${invite.path}`);
|
||||||
|
}}
|
||||||
|
onDecline={() => {
|
||||||
|
api.invite.decline('/contacts', uid);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
|
|
||||||
export class SidebarInvite extends Component {
|
|
||||||
onAccept() {
|
|
||||||
const { props } = this;
|
|
||||||
const [,,ship, name] = props.invite.path.split('/');
|
|
||||||
const resource = { ship, name };
|
|
||||||
props.api.contacts.join(resource).then(() => {
|
|
||||||
props.api.invite.accept('/contacts', props.uid);
|
|
||||||
});
|
|
||||||
props.history.push(`/~groups${props.invite.path}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDecline() {
|
|
||||||
this.props.api.invite.decline('/contacts', this.props.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { props } = this;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='pa3'>
|
|
||||||
<div className='w-100 v-mid'>
|
|
||||||
<p className="dib f8 mono white-d">
|
|
||||||
You have been invited to join {props.invite.path}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<a className="dib pointer pa2 f9 bg-green2 white mt4" onClick={this.onAccept.bind(this)}>Accept Invite</a>
|
|
||||||
<a className="dib pointer ml4 pa2 f9 bg-black white mt4" onClick={this.onDecline.bind(this)}>Decline</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,6 +3,7 @@ import React, { Component } from 'react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { InviteSearch, Invites } from '../../../components/InviteSearch';
|
import { InviteSearch, Invites } from '../../../components/InviteSearch';
|
||||||
import { Spinner } from '../../../components/Spinner';
|
import { Spinner } from '../../../components/Spinner';
|
||||||
|
import { Toggle } from '../../../components/toggle';
|
||||||
import { RouteComponentProps } from 'react-router-dom';
|
import { RouteComponentProps } from 'react-router-dom';
|
||||||
import { Groups, GroupPolicy, Resource } from '../../../types/group-update';
|
import { Groups, GroupPolicy, Resource } from '../../../types/group-update';
|
||||||
import { Contacts, Rolodex } from '../../../types/contact-update';
|
import { Contacts, Rolodex } from '../../../types/contact-update';
|
||||||
@ -129,9 +130,6 @@ export class NewScreen extends Component<NewScreenProps, NewScreenState> {
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const privacySwitchClasses = this.state.privacy
|
|
||||||
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
|
||||||
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='h-100 w-100 mw6 pa3 pt4 overflow-x-hidden bg-gray0-d white-d flex flex-column'>
|
<div className='h-100 w-100 mw6 pa3 pt4 overflow-x-hidden bg-gray0-d white-d flex flex-column'>
|
||||||
@ -174,11 +172,9 @@ export class NewScreen extends Component<NewScreenProps, NewScreenState> {
|
|||||||
onChange={this.descriptionChange}
|
onChange={this.descriptionChange}
|
||||||
/>
|
/>
|
||||||
<div className='mv7'>
|
<div className='mv7'>
|
||||||
<input
|
<Toggle
|
||||||
type='checkbox'
|
boolean={this.state.privacy}
|
||||||
style={{ WebkitAppearance: 'none', width: 28 }}
|
change={this.groupPrivacyChange}
|
||||||
onChange={this.groupPrivacyChange}
|
|
||||||
className={privacySwitchClasses}
|
|
||||||
/>
|
/>
|
||||||
<span className='dib f9 white-d inter ml3'>Private Group</span>
|
<span className='dib f9 white-d inter ml3'>Private Group</span>
|
||||||
<p className='f9 gray2 pt1' style={{ paddingLeft: 40 }}>
|
<p className='f9 gray2 pt1' style={{ paddingLeft: 40 }}>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { GroupSidebar } from './lib/group-sidebar';
|
import { GroupSidebar } from './lib/group-sidebar';
|
||||||
|
import ErrorBoundary from '../../../components/ErrorBoundary';
|
||||||
|
|
||||||
export class Skeleton extends Component {
|
export class Skeleton extends Component {
|
||||||
render() {
|
render() {
|
||||||
@ -25,7 +26,9 @@ export class Skeleton extends Component {
|
|||||||
className={'h-100 w-100 relative ' + rightPanelClasses}
|
className={'h-100 w-100 relative ' + rightPanelClasses}
|
||||||
style={{ flexGrow: 1 }}
|
style={{ flexGrow: 1 }}
|
||||||
>
|
>
|
||||||
{props.children}
|
<ErrorBoundary>
|
||||||
|
{props.children}
|
||||||
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { GroupItem } from './group-item';
|
import { GroupItem } from './group-item';
|
||||||
import { SidebarInvite } from './sidebar-invite';
|
import SidebarInvite from '../../../../components/SidebarInvite';
|
||||||
import { Welcome } from './welcome';
|
import { Welcome } from './welcome';
|
||||||
import { alphabetiseAssociations } from '../../../../lib/util';
|
import { alphabetiseAssociations } from '../../../../lib/util';
|
||||||
|
|
||||||
@ -17,9 +17,9 @@ export class ChannelsSidebar extends Component {
|
|||||||
return (
|
return (
|
||||||
<SidebarInvite
|
<SidebarInvite
|
||||||
key={uid}
|
key={uid}
|
||||||
uid={uid}
|
|
||||||
invite={props.invites[uid]}
|
invite={props.invites[uid]}
|
||||||
api={props.api}
|
onAccept={() => props.api.invite.accept('/link', uid)}
|
||||||
|
onDecline={() => props.api.invite.decline('/link', uid)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
export class SidebarInvite extends Component {
|
|
||||||
onAccept() {
|
|
||||||
this.props.api.invite.accept('/link', this.props.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDecline() {
|
|
||||||
this.props.api.invite.decline('/link', this.props.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { props } = this;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='w-100 bg-transparent pa4 bb b--gray4 b--gray1-d'>
|
|
||||||
<div className='w-100 v-mid'>
|
|
||||||
<p className="dib f8 mono gray4-d">
|
|
||||||
{props.invite.text}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<a
|
|
||||||
className="dib pointer pa2 f9 bg-green2 white mt4"
|
|
||||||
onClick={this.onAccept.bind(this)}
|
|
||||||
>
|
|
||||||
Accept Invite
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="dib pointer ml4 pa2 f9 bg-black bg-gray0-d white mt4"
|
|
||||||
onClick={this.onDecline.bind(this)}
|
|
||||||
>
|
|
||||||
Decline
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { ChannelsSidebar } from './lib/channel-sidebar';
|
import { ChannelsSidebar } from './lib/channel-sidebar';
|
||||||
|
import ErrorBoundary from '../../../components/ErrorBoundary';
|
||||||
|
|
||||||
export class Skeleton extends Component {
|
export class Skeleton extends Component {
|
||||||
render() {
|
render() {
|
||||||
@ -40,7 +41,9 @@ export class Skeleton extends Component {
|
|||||||
flexGrow: 1
|
flexGrow: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{this.props.children}
|
<ErrorBoundary>
|
||||||
|
{props.children}
|
||||||
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -65,7 +65,7 @@ export default class PublishApp extends React.Component {
|
|||||||
this.unreadTotal = unreadTotal;
|
this.unreadTotal = unreadTotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { api, groups, sidebarShown } = props;
|
const { api, groups, sidebarShown, invites } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
@ -77,7 +77,7 @@ export default class PublishApp extends React.Component {
|
|||||||
active={'sidebar'}
|
active={'sidebar'}
|
||||||
rightPanelHide={true}
|
rightPanelHide={true}
|
||||||
sidebarShown={true}
|
sidebarShown={true}
|
||||||
invites={props.invites}
|
invites={invites}
|
||||||
notebooks={notebooks}
|
notebooks={notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
@ -108,7 +108,7 @@ export default class PublishApp extends React.Component {
|
|||||||
active={'rightPanel'}
|
active={'rightPanel'}
|
||||||
rightPanelHide={false}
|
rightPanelHide={false}
|
||||||
sidebarShown={sidebarShown}
|
sidebarShown={sidebarShown}
|
||||||
invites={props.invites}
|
invites={invites}
|
||||||
notebooks={notebooks}
|
notebooks={notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
@ -139,7 +139,7 @@ export default class PublishApp extends React.Component {
|
|||||||
active={'rightPanel'}
|
active={'rightPanel'}
|
||||||
rightPanelHide={false}
|
rightPanelHide={false}
|
||||||
sidebarShown={sidebarShown}
|
sidebarShown={sidebarShown}
|
||||||
invites={props.invites}
|
invites={invites}
|
||||||
notebooks={notebooks}
|
notebooks={notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
@ -185,7 +185,7 @@ export default class PublishApp extends React.Component {
|
|||||||
active={'rightPanel'}
|
active={'rightPanel'}
|
||||||
rightPanelHide={false}
|
rightPanelHide={false}
|
||||||
sidebarShown={sidebarShown}
|
sidebarShown={sidebarShown}
|
||||||
invites={props.invites}
|
invites={invites}
|
||||||
notebooks={notebooks}
|
notebooks={notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
@ -211,7 +211,7 @@ export default class PublishApp extends React.Component {
|
|||||||
active={'rightPanel'}
|
active={'rightPanel'}
|
||||||
rightPanelHide={false}
|
rightPanelHide={false}
|
||||||
sidebarShown={sidebarShown}
|
sidebarShown={sidebarShown}
|
||||||
invites={props.invites}
|
invites={invites}
|
||||||
notebooks={notebooks}
|
notebooks={notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
contacts={contacts}
|
contacts={contacts}
|
||||||
@ -263,7 +263,7 @@ export default class PublishApp extends React.Component {
|
|||||||
active={'rightPanel'}
|
active={'rightPanel'}
|
||||||
rightPanelHide={false}
|
rightPanelHide={false}
|
||||||
sidebarShown={sidebarShown}
|
sidebarShown={sidebarShown}
|
||||||
invites={props.invites}
|
invites={invites}
|
||||||
notebooks={notebooks}
|
notebooks={notebooks}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
@ -290,7 +290,7 @@ export default class PublishApp extends React.Component {
|
|||||||
active={'rightPanel'}
|
active={'rightPanel'}
|
||||||
rightPanelHide={false}
|
rightPanelHide={false}
|
||||||
sidebarShown={sidebarShown}
|
sidebarShown={sidebarShown}
|
||||||
invites={props.invites}
|
invites={invites}
|
||||||
notebooks={notebooks}
|
notebooks={notebooks}
|
||||||
associations={associations}
|
associations={associations}
|
||||||
selectedGroups={selectedGroups}
|
selectedGroups={selectedGroups}
|
||||||
|
@ -25,6 +25,29 @@ export class NewPost extends Component {
|
|||||||
|
|
||||||
postSubmit() {
|
postSubmit() {
|
||||||
const { state } = this;
|
const { state } = this;
|
||||||
|
|
||||||
|
// perf testing:
|
||||||
|
/*let closure = () => {
|
||||||
|
let x = 0;
|
||||||
|
for (var i = 0; i < 5; i++) {
|
||||||
|
x++;
|
||||||
|
let rand = Math.floor(Math.random() * 1000);
|
||||||
|
const newNote = {
|
||||||
|
'new-note': {
|
||||||
|
who: this.props.ship.slice(1),
|
||||||
|
book: this.props.book,
|
||||||
|
note: stringToSymbol(this.state.title + '-' + Date.now() + '-' + rand),
|
||||||
|
title: 'asdf-' + rand + '-' + Date.now(),
|
||||||
|
body: 'asdf-' + Date.now()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.props.api.publishAction(newNote);
|
||||||
|
}
|
||||||
|
setTimeout(closure, 3000);
|
||||||
|
};
|
||||||
|
setTimeout(closure, 2000);*/
|
||||||
|
|
||||||
if (state.submit && !state.disabled) {
|
if (state.submit && !state.disabled) {
|
||||||
const newNote = {
|
const newNote = {
|
||||||
'new-note': {
|
'new-note': {
|
||||||
|
@ -165,8 +165,7 @@ export class NewScreen extends Component {
|
|||||||
</p>
|
</p>
|
||||||
<Link className="green2 absolute right-0 bottom-0 f9" to="/~groups/new">Create Group</Link>
|
<Link className="green2 absolute right-0 bottom-0 f9" to="/~groups/new">Create Group</Link>
|
||||||
<p className="f9 gray2 db mv1 pb4">
|
<p className="f9 gray2 db mv1 pb4">
|
||||||
Selected ships will be invited to read your notebook. Selected
|
Selected ships or group will be invited to read your notebook. Additional writers can be added from the 'subscribers' panel.
|
||||||
groups will be invited to read and write notes.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<InviteSearch
|
<InviteSearch
|
||||||
|
@ -5,6 +5,7 @@ import { NotebookPosts } from './notebook-posts';
|
|||||||
import { Subscribers } from './subscribers';
|
import { Subscribers } from './subscribers';
|
||||||
import { Settings } from './settings';
|
import { Settings } from './settings';
|
||||||
import { cite } from '../../../../lib/util';
|
import { cite } from '../../../../lib/util';
|
||||||
|
import { roleForShip } from '../../../../lib/group';
|
||||||
|
|
||||||
export class Notebook extends Component {
|
export class Notebook extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -176,11 +177,15 @@ export class Notebook extends Component {
|
|||||||
Unsubscribe
|
Unsubscribe
|
||||||
</button>;
|
</button>;
|
||||||
|
|
||||||
const subsComponent = (this.props.ship.slice(1) !== window.ship)
|
|
||||||
? null
|
const group = props.groups[notebook?.['writers-group-path']];
|
||||||
: <Link to={subs} className={tabStyles.subscribers}>
|
const role = group ? roleForShip(group, window.ship) : undefined;
|
||||||
|
|
||||||
|
const subsComponent = (this.props.ship.slice(1) === window.ship) || (role === 'admin')
|
||||||
|
? (<Link to={subs} className={tabStyles.subscribers}>
|
||||||
Subscribers
|
Subscribers
|
||||||
</Link>;
|
</Link>)
|
||||||
|
: null
|
||||||
|
|
||||||
const settingsComponent = (this.props.ship.slice(1) !== window.ship)
|
const settingsComponent = (this.props.ship.slice(1) !== window.ship)
|
||||||
? null
|
? null
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { writeText } from '../../../../lib/util';
|
|
||||||
import { Spinner } from '../../../../components/Spinner';
|
import { Spinner } from '../../../../components/Spinner';
|
||||||
import { InviteSearch } from '../../../../components/InviteSearch';
|
import { InviteSearch } from '../../../../components/InviteSearch';
|
||||||
|
import Toggle from '../../../../components/toggle';
|
||||||
|
|
||||||
export class Settings extends Component {
|
export class Settings extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -133,22 +133,16 @@ export class Settings extends Component {
|
|||||||
// don't give the option to make inclusive if we don't own the target
|
// don't give the option to make inclusive if we don't own the target
|
||||||
// group
|
// group
|
||||||
const targetOwned = (state.targetGroup)
|
const targetOwned = (state.targetGroup)
|
||||||
? state.targetGroup.slice(0, window.ship.length+3) === `/~${window.ship}/`
|
? Boolean(state.targetGroup.includes(`/~${window.ship}/`))
|
||||||
: false;
|
: false;
|
||||||
let inclusiveToggle = <div />;
|
let inclusiveToggle = <div />;
|
||||||
if (targetOwned) {
|
if (targetOwned) {
|
||||||
// TODO toggle component into /lib
|
|
||||||
const inclusiveClasses = state.inclusive
|
|
||||||
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
|
||||||
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
|
||||||
inclusiveToggle = (
|
inclusiveToggle = (
|
||||||
<div className="mt4">
|
<div className="mt4">
|
||||||
<input
|
<Toggle
|
||||||
type="checkbox"
|
boolean={state.inclusive}
|
||||||
style={{ WebkitAppearance: 'none', width: 28 }}
|
change={this.changeInclusive}
|
||||||
className={inclusiveClasses}
|
/>
|
||||||
onChange={this.changeInclusive}
|
|
||||||
/>
|
|
||||||
<span className="dib f9 white-d inter ml3">
|
<span className="dib f9 white-d inter ml3">
|
||||||
Add all members to group
|
Add all members to group
|
||||||
</span>
|
</span>
|
||||||
@ -201,10 +195,6 @@ export class Settings extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const commentsSwitchClasses = (this.state.comments)
|
|
||||||
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
|
||||||
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
|
||||||
|
|
||||||
if (this.props.host.slice(1) === window.ship) {
|
if (this.props.host.slice(1) === window.ship) {
|
||||||
return (
|
return (
|
||||||
<div className="flex-column">
|
<div className="flex-column">
|
||||||
@ -274,11 +264,9 @@ export class Settings extends Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mv6">
|
<div className="mv6">
|
||||||
<input
|
<Toggle
|
||||||
type="checkbox"
|
boolean={this.state.comments}
|
||||||
style={{ WebkitAppearance: 'none', width: 28 }}
|
change={this.changeComments}
|
||||||
className={commentsSwitchClasses}
|
|
||||||
onChange={this.changeComments}
|
|
||||||
/>
|
/>
|
||||||
<span className="dib f9 white-d inter ml3">Comments</span>
|
<span className="dib f9 white-d inter ml3">Comments</span>
|
||||||
<p className="f9 gray2 pt1" style={{ paddingLeft: 40 }}>
|
<p className="f9 gray2 pt1" style={{ paddingLeft: 40 }}>
|
||||||
@ -293,7 +281,7 @@ export class Settings extends Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return copyShortcode;
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
|
|
||||||
export class SidebarInvite extends Component {
|
|
||||||
onAccept() {
|
|
||||||
this.props.api.invite.accept('/publish', this.props.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDecline() {
|
|
||||||
this.props.api.invite.decline('/publish', this.props.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { props } = this;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='pa3 bb b--gray4 b--gray1-d'>
|
|
||||||
<div className='w-100 v-mid'>
|
|
||||||
<p className="dib f9 mono gray4-d">
|
|
||||||
{props.invite.text}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<a
|
|
||||||
className="dib pointer pa2 f9 bg-green2 white mt4"
|
|
||||||
onClick={this.onAccept.bind(this)}
|
|
||||||
>
|
|
||||||
Accept Invite
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="dib pointer ml4 pa2 f9 bg-black bg-gray0-d white mt4"
|
|
||||||
onClick={this.onDecline.bind(this)}
|
|
||||||
>
|
|
||||||
Decline
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { SidebarInvite } from './sidebar-invite';
|
import SidebarInvite from '../../../../components/SidebarInvite';
|
||||||
import { Welcome } from './welcome';
|
import { Welcome } from './welcome';
|
||||||
import { GroupItem } from './group-item';
|
import { GroupItem } from './group-item';
|
||||||
import { alphabetiseAssociations } from '../../../../lib/util';
|
import { alphabetiseAssociations } from '../../../../lib/util';
|
||||||
@ -19,13 +19,13 @@ export class Sidebar extends Component {
|
|||||||
const sidebarInvites = !(props.invites && props.invites['/publish'])
|
const sidebarInvites = !(props.invites && props.invites['/publish'])
|
||||||
? null
|
? null
|
||||||
: Object.keys(props.invites['/publish'])
|
: Object.keys(props.invites['/publish'])
|
||||||
.map((uid, i) => {
|
.map((uid) => {
|
||||||
return (
|
return (
|
||||||
<SidebarInvite
|
<SidebarInvite
|
||||||
uid={uid}
|
key={uid}
|
||||||
invite={props.invites['/publish'][uid]}
|
invite={props.invites['/publish'][uid]}
|
||||||
api={this.props.api}
|
onAccept={() => props.api.invite.accept('/publish', uid)}
|
||||||
key={i}
|
onDecline={() => props.api.invite.decline('/publish', uid)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { GroupView } from '../../../../components/Group';
|
import { GroupView } from '../../../../components/Group';
|
||||||
|
import { resourceFromPath } from '../../../../lib/group';
|
||||||
|
|
||||||
export class Subscribers extends Component {
|
export class Subscribers extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -7,6 +8,7 @@ export class Subscribers extends Component {
|
|||||||
this.redirect = this.redirect.bind(this);
|
this.redirect = this.redirect.bind(this);
|
||||||
this.addUser = this.addUser.bind(this);
|
this.addUser = this.addUser.bind(this);
|
||||||
this.removeUser = this.removeUser.bind(this);
|
this.removeUser = this.removeUser.bind(this);
|
||||||
|
this.addAll = this.addAll.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
addUser(who, path) {
|
addUser(who, path) {
|
||||||
@ -21,6 +23,18 @@ export class Subscribers extends Component {
|
|||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addAll() {
|
||||||
|
const path = this.props.notebook['writers-group-path'];
|
||||||
|
const group = path ? this.props.groups[path] : null;
|
||||||
|
const resource = resourceFromPath(path);
|
||||||
|
this.props.api.groups.addTag(
|
||||||
|
resource,
|
||||||
|
{ app: 'publish', tag: `writers-${this.props.book}` },
|
||||||
|
[...group.members].map(m => `~${m}`)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const path = this.props.notebook['writers-group-path'];
|
const path = this.props.notebook['writers-group-path'];
|
||||||
const group = path ? this.props.groups[path] : null;
|
const group = path ? this.props.groups[path] : null;
|
||||||
@ -45,17 +59,25 @@ export class Subscribers extends Component {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GroupView
|
<div>
|
||||||
permissions
|
<button
|
||||||
resourcePath={path}
|
onClick={this.addAll}
|
||||||
group={group}
|
className={'dib f9 black gray4-d bg-gray0-d ba pa2 mb4 b--black b--gray1-d pointer'}
|
||||||
tags={tags}
|
>
|
||||||
appTags={appTags}
|
Add all members as writers
|
||||||
contacts={props.contacts}
|
</button>
|
||||||
groups={props.groups}
|
<GroupView
|
||||||
associations={props.associations}
|
permissions
|
||||||
api={this.props.api}
|
resourcePath={path}
|
||||||
/>
|
group={group}
|
||||||
|
tags={tags}
|
||||||
|
appTags={appTags}
|
||||||
|
contacts={this.props.contacts}
|
||||||
|
groups={this.props.groups}
|
||||||
|
associations={this.props.associations}
|
||||||
|
api={this.props.api}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Sidebar } from './lib/sidebar';
|
import { Sidebar } from './lib/sidebar';
|
||||||
|
import ErrorBoundary from '../../../components/ErrorBoundary';
|
||||||
|
|
||||||
export class Skeleton extends Component {
|
export class Skeleton extends Component {
|
||||||
render() {
|
render() {
|
||||||
@ -36,7 +37,9 @@ export class Skeleton extends Component {
|
|||||||
flexGrow: 1
|
flexGrow: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
<ErrorBoundary>
|
||||||
|
{props.children}
|
||||||
|
</ErrorBoundary>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
const NotFound = () => <div
|
|
||||||
className="fixed inter tc"
|
|
||||||
style={{
|
|
||||||
top: '50vh',
|
|
||||||
left: '50%',
|
|
||||||
transform: 'translate(-50%, -25vh)',
|
|
||||||
fontFeatureSettings: '\'zero\' 1' }}>
|
|
||||||
<h1 className="fw2 f2">404</h1>
|
|
||||||
<p className="tc">Not found.<br /><br />
|
|
||||||
If this is unexpected, email <code>support@tlon.io</code> or <a className="bb" href="https://github.com/urbit/urbit/issues/new/choose">submit an issue</a>.</p>
|
|
||||||
</div>;
|
|
||||||
|
|
||||||
export default NotFound;
|
|
40
pkg/interface/src/components/Error.tsx
Normal file
40
pkg/interface/src/components/Error.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
type ErrorProps = RouteComponentProps & {
|
||||||
|
code?: number | string,
|
||||||
|
description?: string,
|
||||||
|
error?: Error
|
||||||
|
};
|
||||||
|
|
||||||
|
class ErrorComponent extends Component<ErrorProps> {
|
||||||
|
render () {
|
||||||
|
const { code, error, history, description } = this.props;
|
||||||
|
return (
|
||||||
|
<div className="pa4 inter tc flex flex-column items-center justify-center w-100 h-100">
|
||||||
|
<h1 className="mb4 fw2 f2" style={{
|
||||||
|
fontFeatureSettings: '\'zero\' 1',
|
||||||
|
}}>
|
||||||
|
{code ? code : 'Error'}
|
||||||
|
</h1>
|
||||||
|
{description ? <p className="tc mb4">{description}</p> : null}
|
||||||
|
{error ? (
|
||||||
|
<div className="mb4">
|
||||||
|
<p className="mb4"><code>“{error.message}”</code></p>
|
||||||
|
<details>
|
||||||
|
<summary>Stack trace</summary>
|
||||||
|
<pre className="tl">{error.stack}</pre>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<p className="tc mb4">If this is unexpected, email <code>support@tlon.io</code> or <a className="bb" href="https://github.com/urbit/urbit/issues/new/choose">submit an issue</a>.</p>
|
||||||
|
{history.length > 1
|
||||||
|
? <button className="bg-light-green green2 pa2 pointer" onClick={() => history.go(-1) }>Go back</button>
|
||||||
|
: <button className="bg-light-green green2 pa2 pointer" onClick={() => history.push('/') }>Go home</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(ErrorComponent);
|
35
pkg/interface/src/components/ErrorBoundary.tsx
Normal file
35
pkg/interface/src/components/ErrorBoundary.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||||
|
import ErrorComponent from './Error';
|
||||||
|
|
||||||
|
class ErrorBoundary extends Component<
|
||||||
|
RouteComponentProps,
|
||||||
|
{ error?: Error }
|
||||||
|
> {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { error: undefined };
|
||||||
|
const { history } = this.props;
|
||||||
|
history.listen((location, action) => {
|
||||||
|
if (this.state.error) {
|
||||||
|
this.setState({
|
||||||
|
error: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidCatch(error) {
|
||||||
|
this.setState({ error });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.error) {
|
||||||
|
return (<ErrorComponent error={this.state.error} />)
|
||||||
|
}
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(ErrorBoundary);
|
@ -1,5 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import _, { capitalize } from 'lodash';
|
import _, { capitalize } from 'lodash';
|
||||||
|
import { FixedSizeList as List } from 'react-window';
|
||||||
|
|
||||||
import { Dropdown } from '../apps/publish/components/lib/dropdown';
|
import { Dropdown } from '../apps/publish/components/lib/dropdown';
|
||||||
import { cite, deSig } from '../lib/util';
|
import { cite, deSig } from '../lib/util';
|
||||||
import { roleForShip, resourceFromPath } from '../lib/group';
|
import { roleForShip, resourceFromPath } from '../lib/group';
|
||||||
@ -143,7 +145,7 @@ export class GroupView extends Component<
|
|||||||
|
|
||||||
isAdmin(): boolean {
|
isAdmin(): boolean {
|
||||||
const us = `~${window.ship}`;
|
const us = `~${window.ship}`;
|
||||||
const role = roleForShip(this.props.group, us);
|
const role = roleForShip(this.props.group, window.ship);
|
||||||
const resource = resourceFromPath(this.props.resourcePath);
|
const resource = resourceFromPath(this.props.resourcePath);
|
||||||
return resource.ship == us || role === 'admin';
|
return resource.ship == us || role === 'admin';
|
||||||
}
|
}
|
||||||
@ -156,10 +158,15 @@ export class GroupView extends Component<
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
const role = roleForShip(group, ship);
|
const role = roleForShip(group, ship);
|
||||||
|
const myRole = roleForShip(group, window.ship);
|
||||||
if (role === 'admin' || resource.ship === ship) {
|
if (role === 'admin' || resource.ship === ship) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
if ('open' in group.policy) {
|
if (
|
||||||
|
'open' in group.policy // If blacklist, not whitelist
|
||||||
|
&& (this.isAdmin()) // And we can ban people (TODO: add || role === 'moderator')
|
||||||
|
&& ship !== window.ship // We can't ban ourselves
|
||||||
|
) {
|
||||||
options.unshift({ text: 'Ban', onSelect: () => this.banUser(ship) });
|
options.unshift({ text: 'Ban', onSelect: () => this.banUser(ship) });
|
||||||
}
|
}
|
||||||
if (this.isAdmin() && !role) {
|
if (this.isAdmin() && !role) {
|
||||||
@ -199,52 +206,45 @@ export class GroupView extends Component<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMembers() {
|
memberElements() {
|
||||||
const { group, permissions } = this.props;
|
const { group, permissions } = this.props;
|
||||||
const { members } = group;
|
const { members } = group;
|
||||||
const isAdmin = this.isAdmin();
|
const isAdmin = this.isAdmin();
|
||||||
return (
|
return Array.from(members).map((ship) => {
|
||||||
<div className='flex flex-column'>
|
const role = roleForShip(group, deSig(ship));
|
||||||
<div className='f9 gray2 mt6 mb3'>Members</div>
|
const onRoleRemove =
|
||||||
{Array.from(members).map((ship) => {
|
role && isAdmin
|
||||||
const role = roleForShip(group, deSig(ship));
|
? () => {
|
||||||
const onRoleRemove =
|
this.removeTag(ship, { tag: role });
|
||||||
role && isAdmin
|
}
|
||||||
? () => {
|
: undefined;
|
||||||
this.removeTag(ship, { tag: role });
|
const [present, missing] = this.getAppTags(ship);
|
||||||
}
|
const options = this.optionsForShip(ship, missing);
|
||||||
: undefined;
|
|
||||||
const [present, missing] = this.getAppTags(ship);
|
|
||||||
const options = this.optionsForShip(ship, missing);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={ship} className='flex flex-column pv3'>
|
<GroupMember ship={ship} options={options}>
|
||||||
<GroupMember ship={ship} options={options}>
|
{((permissions && role) || present.length > 0) && (
|
||||||
{((permissions && role) || present.length > 0) && (
|
<div className='flex mt1'>
|
||||||
<div className='flex mt1'>
|
{role && (
|
||||||
{role && (
|
<Tag
|
||||||
<Tag
|
onRemove={onRoleRemove}
|
||||||
onRemove={onRoleRemove}
|
description={capitalize(role)}
|
||||||
description={capitalize(role)}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
{present.map((tag, idx) => (
|
||||||
{present.map((tag, idx) => (
|
<Tag
|
||||||
<Tag
|
key={idx}
|
||||||
key={idx}
|
onRemove={this.doIfAdmin(() =>
|
||||||
onRemove={this.doIfAdmin(() =>
|
this.removeTag(ship, tag)
|
||||||
this.removeTag(ship, tag)
|
)}
|
||||||
)}
|
description={tag.desc}
|
||||||
description={tag.desc}
|
/>
|
||||||
/>
|
))}
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</GroupMember>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
)}
|
||||||
})}
|
</GroupMember>
|
||||||
</div>
|
);
|
||||||
);
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
setInvites(invites: Invites) {
|
setInvites(invites: Invites) {
|
||||||
@ -321,6 +321,7 @@ export class GroupView extends Component<
|
|||||||
render() {
|
render() {
|
||||||
const { group, resourcePath, className } = this.props;
|
const { group, resourcePath, className } = this.props;
|
||||||
const resource = resourceFromPath(resourcePath);
|
const resource = resourceFromPath(resourcePath);
|
||||||
|
const memberElements = this.memberElements();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
@ -332,7 +333,17 @@ export class GroupView extends Component<
|
|||||||
</div>
|
</div>
|
||||||
{'invite' in group.policy && this.renderInvites(group.policy)}
|
{'invite' in group.policy && this.renderInvites(group.policy)}
|
||||||
{'open' in group.policy && this.renderBanned(group.policy)}
|
{'open' in group.policy && this.renderBanned(group.policy)}
|
||||||
{this.renderMembers()}
|
<div className='flex flex-column'>
|
||||||
|
<div className='f9 gray2 mt6 mb3'>Members</div>
|
||||||
|
<List
|
||||||
|
height={500}
|
||||||
|
itemCount={memberElements.length}
|
||||||
|
itemSize={44}
|
||||||
|
width="100%"
|
||||||
|
>
|
||||||
|
{({ index, style }) => <div key={index} style={style} className='flex flex-column pv3'>{memberElements[index]}</div>}
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
awaiting={this.state.awaiting}
|
awaiting={this.state.awaiting}
|
||||||
|
@ -1,33 +1,26 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import { Invite } from '../types/invite-update';
|
||||||
|
|
||||||
export class SidebarInvite extends Component {
|
export class SidebarInvite extends Component<{invite: Invite, onAccept: Function, onDecline: Function}, {}> {
|
||||||
onAccept() {
|
|
||||||
this.props.api.invite.accept('/chat', this.props.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDecline() {
|
|
||||||
this.props.api.invite.decline('/chat', this.props.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { props } = this;
|
const { props } = this;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='w-100 bg-transparent pa4 bb b--gray4 b--gray1-d'>
|
<div className='w-100 bg-white bg-gray0-d pa4 bb b--gray4 b--gray1-d z-5' style={{position: 'sticky', top: 0}}>
|
||||||
<div className='w-100 v-mid'>
|
<div className='w-100 v-mid'>
|
||||||
<p className="dib f8 mono gray4-d">
|
<p className="dib f8 mono gray4-d">
|
||||||
{props.invite.path}
|
{props.invite.text ? props.invite.text : props.invite.path}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
className="dib pointer pa2 f9 bg-green2 white mt4"
|
className="dib pointer pa2 f9 bg-green2 white mt4"
|
||||||
onClick={this.onAccept.bind(this)}
|
onClick={this.props.onAccept.bind(this)}
|
||||||
>
|
>
|
||||||
Accept Invite
|
Accept Invite
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
className="dib pointer ml4 pa2 f9 bg-black bg-gray0-d white mt4"
|
className="dib pointer ml4 pa2 f9 bg-black bg-gray0-d white mt4"
|
||||||
onClick={this.onDecline.bind(this)}
|
onClick={this.props.onDecline.bind(this)}
|
||||||
>
|
>
|
||||||
Decline
|
Decline
|
||||||
</a>
|
</a>
|
||||||
@ -36,3 +29,4 @@ export class SidebarInvite extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default SidebarInvite;
|
20
pkg/interface/src/components/toggle.js
Normal file
20
pkg/interface/src/components/toggle.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
export class Toggle extends Component {
|
||||||
|
render() {
|
||||||
|
const switchClasses = (this.props.boolean)
|
||||||
|
? 'relative checked bg-green2 br3 h1 toggle v-mid z-0'
|
||||||
|
: 'relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
style={{ WebkitAppearance: 'none', width: 28 }}
|
||||||
|
className={switchClasses}
|
||||||
|
onChange={this.props.change}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Toggle;
|
@ -6,6 +6,7 @@ import {
|
|||||||
Group,
|
Group,
|
||||||
Tags,
|
Tags,
|
||||||
GroupPolicy,
|
GroupPolicy,
|
||||||
|
GroupPolicyDiff,
|
||||||
OpenPolicyDiff,
|
OpenPolicyDiff,
|
||||||
OpenPolicy,
|
OpenPolicy,
|
||||||
InvitePolicyDiff,
|
InvitePolicyDiff,
|
||||||
@ -24,7 +25,6 @@ function decodeGroup(group: Enc<Group>): Group {
|
|||||||
tags: decodeTags(group.tags),
|
tags: decodeTags(group.tags),
|
||||||
policy: decodePolicy(group.policy),
|
policy: decodePolicy(group.policy),
|
||||||
};
|
};
|
||||||
console.log(res);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,6 +179,8 @@ export default class GroupReducer<S extends GroupState> {
|
|||||||
this.openChangePolicy(diff.open, policy);
|
this.openChangePolicy(diff.open, policy);
|
||||||
} else if ('invite' in policy && 'invite' in diff) {
|
} else if ('invite' in policy && 'invite' in diff) {
|
||||||
this.inviteChangePolicy(diff.invite, policy);
|
this.inviteChangePolicy(diff.invite, policy);
|
||||||
|
} else if ('replace' in diff) {
|
||||||
|
state.groups[resourcePath].policy = diff.replace;
|
||||||
} else {
|
} else {
|
||||||
console.log('bad policy diff');
|
console.log('bad policy diff');
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,6 @@ export default class InviteReducer<S extends InviteState> {
|
|||||||
accepted(json: InviteUpdate, state: S) {
|
accepted(json: InviteUpdate, state: S) {
|
||||||
const data = _.get(json, 'accepted', false);
|
const data = _.get(json, 'accepted', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
console.log(data);
|
|
||||||
delete state.invites[data.path][data.uid];
|
delete state.invites[data.path][data.uid];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,10 @@ export default class MetadataReducer<S extends MetadataState> {
|
|||||||
reduce(json: Cage, state: S) {
|
reduce(json: Cage, state: S) {
|
||||||
let data = json['metadata-update']
|
let data = json['metadata-update']
|
||||||
if (data) {
|
if (data) {
|
||||||
console.log('data: ', data);
|
|
||||||
this.associations(data, state);
|
this.associations(data, state);
|
||||||
this.add(data, state);
|
this.add(data, state);
|
||||||
this.update(data, state);
|
this.update(data, state);
|
||||||
this.remove(data, state);
|
this.remove(data, state);
|
||||||
console.log('state: ', state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,4 +48,3 @@ export default class PublishStore extends BaseStore {
|
|||||||
this.responseReducer.reduce(data, this.state);
|
this.responseReducer.reduce(data, this.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
169
pkg/interface/src/themes/light.ts
Normal file
169
pkg/interface/src/themes/light.ts
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
import baseStyled, { ThemedStyledInterface } from "styled-components";
|
||||||
|
|
||||||
|
const base = {
|
||||||
|
white: "rgba(255,255,255,1)",
|
||||||
|
black: "rgba(0,0,0,1)",
|
||||||
|
red: "rgba(255,65,54,1)",
|
||||||
|
yellow: "rgba(255,199,0,1)",
|
||||||
|
green: "rgba(0,159,101,1)",
|
||||||
|
blue: "rgba(0,142,255,1)",
|
||||||
|
};
|
||||||
|
|
||||||
|
const scales = {
|
||||||
|
white10: "rgba(255,255,255,0.1)",
|
||||||
|
white20: "rgba(255,255,255,0.2)",
|
||||||
|
white30: "rgba(255,255,255,0.3)",
|
||||||
|
white40: "rgba(255,255,255,0.4)",
|
||||||
|
white50: "rgba(255,255,255,0.5)",
|
||||||
|
white60: "rgba(255,255,255,0.6)",
|
||||||
|
white70: "rgba(255,255,255,0.7)",
|
||||||
|
white80: "rgba(255,255,255,0.8)",
|
||||||
|
white90: "rgba(255,255,255,0.9)",
|
||||||
|
white100: "rgba(255,255,255,1)",
|
||||||
|
black10: "rgba(0,0,0,0.1)",
|
||||||
|
black20: "rgba(0,0,0,0.2)",
|
||||||
|
black30: "rgba(0,0,0,0.3)",
|
||||||
|
black40: "rgba(0,0,0,0.4)",
|
||||||
|
black50: "rgba(0,0,0,0.5)",
|
||||||
|
black60: "rgba(0,0,0,0.6)",
|
||||||
|
black70: "rgba(0,0,0,0.7)",
|
||||||
|
black80: "rgba(0,0,0,0.8)",
|
||||||
|
black90: "rgba(0,0,0,0.9)",
|
||||||
|
black100: "rgba(0,0,0,1)",
|
||||||
|
red10: "rgba(255,65,54,0.1)",
|
||||||
|
red20: "rgba(255,65,54,0.2)",
|
||||||
|
red30: "rgba(255,65,54,0.3)",
|
||||||
|
red40: "rgba(255,65,54,0.4)",
|
||||||
|
red50: "rgba(255,65,54,0.5)",
|
||||||
|
red60: "rgba(255,65,54,0.6)",
|
||||||
|
red70: "rgba(255,65,54,0.7)",
|
||||||
|
red80: "rgba(255,65,54,0.8)",
|
||||||
|
red90: "rgba(255,65,54,0.9)",
|
||||||
|
red100: "rgba(255,65,54,1)",
|
||||||
|
yellow10: "rgba(255,199,0,0.1)",
|
||||||
|
yellow20: "rgba(255,199,0,0.2)",
|
||||||
|
yellow30: "rgba(255,199,0,0.3)",
|
||||||
|
yellow40: "rgba(255,199,0,0.4)",
|
||||||
|
yellow50: "rgba(255,199,0,0.5)",
|
||||||
|
yellow60: "rgba(255,199,0,0.6)",
|
||||||
|
yellow70: "rgba(255,199,0,0.7)",
|
||||||
|
yellow80: "rgba(255,199,0,0.8)",
|
||||||
|
yellow90: "rgba(255,199,0,0.9)",
|
||||||
|
yellow100: "rgba(255,199,0,1)",
|
||||||
|
green10: "rgba(0,159,101,0.1)",
|
||||||
|
green20: "rgba(0,159,101,0.2)",
|
||||||
|
green30: "rgba(0,159,101,0.3)",
|
||||||
|
green40: "rgba(0,159,101,0.4)",
|
||||||
|
green50: "rgba(0,159,101,0.5)",
|
||||||
|
green60: "rgba(0,159,101,0.6)",
|
||||||
|
green70: "rgba(0,159,101,0.7)",
|
||||||
|
green80: "rgba(0,159,101,0.8)",
|
||||||
|
green90: "rgba(0,159,101,0.9)",
|
||||||
|
green100: "rgba(0,159,101,1)",
|
||||||
|
blue10: "rgba(0,142,255,0.1)",
|
||||||
|
blue20: "rgba(0,142,255,0.2)",
|
||||||
|
blue30: "rgba(0,142,255,0.3)",
|
||||||
|
blue40: "rgba(0,142,255,0.4)",
|
||||||
|
blue50: "rgba(0,142,255,0.5)",
|
||||||
|
blue60: "rgba(0,142,255,0.6)",
|
||||||
|
blue70: "rgba(0,142,255,0.7)",
|
||||||
|
blue80: "rgba(0,142,255,0.8)",
|
||||||
|
blue90: "rgba(0,142,255,0.9)",
|
||||||
|
blue100: "rgba(0,142,255,1)",
|
||||||
|
};
|
||||||
|
|
||||||
|
const theme = {
|
||||||
|
colors: {
|
||||||
|
white: base.white,
|
||||||
|
black: base.black,
|
||||||
|
|
||||||
|
gray: scales.black60,
|
||||||
|
lightGray: scales.black30,
|
||||||
|
washedGray: scales.black10,
|
||||||
|
|
||||||
|
red: base.red,
|
||||||
|
lightRed: scales.red30,
|
||||||
|
washedRed: scales.red10,
|
||||||
|
|
||||||
|
yellow: base.yellow,
|
||||||
|
lightYellow: scales.yellow30,
|
||||||
|
washedYellow: scales.yellow10,
|
||||||
|
|
||||||
|
green: base.green,
|
||||||
|
lightGreen: scales.green30,
|
||||||
|
washedGreen: scales.green10,
|
||||||
|
|
||||||
|
blue: base.blue,
|
||||||
|
lightBlue: scales.blue30,
|
||||||
|
washedBlue: scales.blue10,
|
||||||
|
|
||||||
|
none: "rgba(0,0,0,0)",
|
||||||
|
scales: scales,
|
||||||
|
},
|
||||||
|
fonts: {
|
||||||
|
sans: `"Inter", "Inter UI", -apple-system, BlinkMacSystemFont, 'San Francisco', 'Helvetica Neue', Arial, sans-serif`,
|
||||||
|
mono: `"Source Code Pro", "Roboto mono", "Courier New", monospace`,
|
||||||
|
},
|
||||||
|
// font-size
|
||||||
|
fontSizes: [
|
||||||
|
12, // 0
|
||||||
|
16, // 1
|
||||||
|
24, // 2
|
||||||
|
32, // 3
|
||||||
|
48, // 4
|
||||||
|
64, // 5
|
||||||
|
],
|
||||||
|
// font-weight
|
||||||
|
fontWeights: {
|
||||||
|
thin: 300,
|
||||||
|
regular: 400,
|
||||||
|
bold: 600,
|
||||||
|
},
|
||||||
|
// line-height
|
||||||
|
lineHeights: {
|
||||||
|
min: 1.2,
|
||||||
|
short: 1.333333,
|
||||||
|
regular: 1.5,
|
||||||
|
tall: 1.666666,
|
||||||
|
},
|
||||||
|
// border, border-top, border-right, border-bottom, border-left
|
||||||
|
borders: ["none", "1px solid"],
|
||||||
|
// margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, grid-gap, grid-column-gap, grid-row-gap
|
||||||
|
space: [
|
||||||
|
0, // 0
|
||||||
|
4, // 1
|
||||||
|
8, // 2
|
||||||
|
16, // 3
|
||||||
|
24, // 4
|
||||||
|
32, // 5
|
||||||
|
48, // 6
|
||||||
|
64, // 7
|
||||||
|
96, // 8
|
||||||
|
],
|
||||||
|
// border-radius
|
||||||
|
radii: [
|
||||||
|
0, // 0
|
||||||
|
2, // 1
|
||||||
|
4, // 2
|
||||||
|
8, // 3
|
||||||
|
16, // 4
|
||||||
|
],
|
||||||
|
// width, height, min-width, max-width, min-height, max-height
|
||||||
|
sizes: [
|
||||||
|
0, // 0
|
||||||
|
4, // 1
|
||||||
|
8, // 2
|
||||||
|
16, // 3
|
||||||
|
24, // 4
|
||||||
|
32, // 5
|
||||||
|
48, // 6
|
||||||
|
64, // 7
|
||||||
|
96, // 8
|
||||||
|
],
|
||||||
|
// z-index
|
||||||
|
zIndices: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||||
|
breakpoints: ["768px", "1024px", "1440px", "2200px"],
|
||||||
|
};
|
||||||
|
export type Theme = typeof theme;
|
||||||
|
export const styled = baseStyled as ThemedStyledInterface<Theme>;
|
||||||
|
export default theme;
|
184
pkg/interface/src/themes/old-dark.ts
Normal file
184
pkg/interface/src/themes/old-dark.ts
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import baseStyled, { ThemedStyledInterface } from "styled-components";
|
||||||
|
|
||||||
|
const base = {
|
||||||
|
white: "rgba(255,255,255,1)",
|
||||||
|
black: "rgba(0,0,0,1)",
|
||||||
|
red: "rgba(255,65,54,1)",
|
||||||
|
yellow: "rgba(255,199,0,1)",
|
||||||
|
green: "rgba(0,159,101,1)",
|
||||||
|
blue: "rgba(0,142,255,1)",
|
||||||
|
};
|
||||||
|
|
||||||
|
const scales = {
|
||||||
|
white05: "rgba(255,255,255,0.05)",
|
||||||
|
white10: "rgba(255,255,255,0.1)",
|
||||||
|
white20: "rgba(255,255,255,0.2)",
|
||||||
|
white30: "rgba(255,255,255,0.3)",
|
||||||
|
white40: "rgba(255,255,255,0.4)",
|
||||||
|
white50: "rgba(255,255,255,0.5)",
|
||||||
|
white60: "rgba(255,255,255,0.6)",
|
||||||
|
white70: "rgba(255,255,255,0.7)",
|
||||||
|
white80: "rgba(255,255,255,0.8)",
|
||||||
|
white90: "rgba(255,255,255,0.9)",
|
||||||
|
white100: "rgba(255,255,255,1)",
|
||||||
|
black05: "rgba(0,0,0,0.05)",
|
||||||
|
black10: "rgba(0,0,0,0.1)",
|
||||||
|
black20: "rgba(0,0,0,0.2)",
|
||||||
|
black30: "rgba(0,0,0,0.3)",
|
||||||
|
black40: "rgba(0,0,0,0.4)",
|
||||||
|
black50: "rgba(0,0,0,0.5)",
|
||||||
|
black60: "rgba(0,0,0,0.6)",
|
||||||
|
black70: "rgba(0,0,0,0.7)",
|
||||||
|
black80: "rgba(0,0,0,0.8)",
|
||||||
|
black90: "rgba(0,0,0,0.9)",
|
||||||
|
black100: "rgba(0,0,0,1)",
|
||||||
|
red05: "rgba(255,65,54,0.05)",
|
||||||
|
red10: "rgba(255,65,54,0.1)",
|
||||||
|
red20: "rgba(255,65,54,0.2)",
|
||||||
|
red30: "rgba(255,65,54,0.3)",
|
||||||
|
red40: "rgba(255,65,54,0.4)",
|
||||||
|
red50: "rgba(255,65,54,0.5)",
|
||||||
|
red60: "rgba(255,65,54,0.6)",
|
||||||
|
red70: "rgba(255,65,54,0.7)",
|
||||||
|
red80: "rgba(255,65,54,0.8)",
|
||||||
|
red90: "rgba(255,65,54,0.9)",
|
||||||
|
red100: "rgba(255,65,54,1)",
|
||||||
|
yellow05: "rgba(255,199,0,0.05)",
|
||||||
|
yellow10: "rgba(255,199,0,0.1)",
|
||||||
|
yellow20: "rgba(255,199,0,0.2)",
|
||||||
|
yellow30: "rgba(255,199,0,0.3)",
|
||||||
|
yellow40: "rgba(255,199,0,0.4)",
|
||||||
|
yellow50: "rgba(255,199,0,0.5)",
|
||||||
|
yellow60: "rgba(255,199,0,0.6)",
|
||||||
|
yellow70: "rgba(255,199,0,0.7)",
|
||||||
|
yellow80: "rgba(255,199,0,0.8)",
|
||||||
|
yellow90: "rgba(255,199,0,0.9)",
|
||||||
|
yellow100: "rgba(255,199,0,1)",
|
||||||
|
green05: "rgba(0,159,101,0.05)",
|
||||||
|
green10: "rgba(0,159,101,0.1)",
|
||||||
|
green20: "rgba(0,159,101,0.2)",
|
||||||
|
green30: "rgba(0,159,101,0.3)",
|
||||||
|
green40: "rgba(0,159,101,0.4)",
|
||||||
|
green50: "rgba(0,159,101,0.5)",
|
||||||
|
green60: "rgba(0,159,101,0.6)",
|
||||||
|
green70: "rgba(0,159,101,0.7)",
|
||||||
|
green80: "rgba(0,159,101,0.8)",
|
||||||
|
green90: "rgba(0,159,101,0.9)",
|
||||||
|
green100: "rgba(0,159,101,1)",
|
||||||
|
blue05: "rgba(0,142,255,0.05)",
|
||||||
|
blue10: "rgba(0,142,255,0.1)",
|
||||||
|
blue20: "rgba(0,142,255,0.2)",
|
||||||
|
blue30: "rgba(0,142,255,0.3)",
|
||||||
|
blue40: "rgba(0,142,255,0.4)",
|
||||||
|
blue50: "rgba(0,142,255,0.5)",
|
||||||
|
blue60: "rgba(0,142,255,0.6)",
|
||||||
|
blue70: "rgba(0,142,255,0.7)",
|
||||||
|
blue80: "rgba(0,142,255,0.8)",
|
||||||
|
blue90: "rgba(0,142,255,0.9)",
|
||||||
|
blue100: "rgba(0,142,255,1)",
|
||||||
|
};
|
||||||
|
|
||||||
|
const util = {
|
||||||
|
cyan: "#00FFFF",
|
||||||
|
magenta: "#FF00FF",
|
||||||
|
yellow: "#FFFF00",
|
||||||
|
black: "#000000",
|
||||||
|
gray0: "#333333"
|
||||||
|
};
|
||||||
|
|
||||||
|
const theme = {
|
||||||
|
colors: {
|
||||||
|
white: util.gray0,
|
||||||
|
black: base.white,
|
||||||
|
|
||||||
|
gray: scales.white60,
|
||||||
|
lightGray: scales.white30,
|
||||||
|
washedGray: scales.white05,
|
||||||
|
|
||||||
|
red: base.red,
|
||||||
|
lightRed: scales.red30,
|
||||||
|
washedRed: scales.red05,
|
||||||
|
|
||||||
|
yellow: base.yellow,
|
||||||
|
lightYellow: scales.yellow30,
|
||||||
|
washedYellow: scales.yellow10,
|
||||||
|
|
||||||
|
green: base.green,
|
||||||
|
lightGreen: scales.green30,
|
||||||
|
washedGreen: scales.green10,
|
||||||
|
|
||||||
|
blue: base.blue,
|
||||||
|
lightBlue: scales.blue30,
|
||||||
|
washedBlue: scales.blue10,
|
||||||
|
|
||||||
|
none: "rgba(0,0,0,0)",
|
||||||
|
|
||||||
|
scales: scales,
|
||||||
|
util: util,
|
||||||
|
},
|
||||||
|
fonts: {
|
||||||
|
sans: `"Inter", "Inter UI", -apple-system, BlinkMacSystemFont, 'San Francisco', 'Helvetica Neue', Arial, sans-serif`,
|
||||||
|
mono: `"Source Code Pro", "Roboto mono", "Courier New", monospace`,
|
||||||
|
},
|
||||||
|
// font-size
|
||||||
|
fontSizes: [
|
||||||
|
12, // 0
|
||||||
|
16, // 1
|
||||||
|
24, // 2
|
||||||
|
32, // 3
|
||||||
|
48, // 4
|
||||||
|
64, // 5
|
||||||
|
],
|
||||||
|
// font-weight
|
||||||
|
fontWeights: {
|
||||||
|
thin: 300,
|
||||||
|
regular: 400,
|
||||||
|
bold: 600,
|
||||||
|
},
|
||||||
|
// line-height
|
||||||
|
lineHeights: {
|
||||||
|
min: 1.2,
|
||||||
|
short: 1.333333,
|
||||||
|
regular: 1.5,
|
||||||
|
tall: 1.666666,
|
||||||
|
},
|
||||||
|
// border, border-top, border-right, border-bottom, border-left
|
||||||
|
borders: ["none", "1px solid"],
|
||||||
|
// margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, grid-gap, grid-column-gap, grid-row-gap
|
||||||
|
space: [
|
||||||
|
0, // 0
|
||||||
|
4, // 1
|
||||||
|
8, // 2
|
||||||
|
16, // 3
|
||||||
|
24, // 4
|
||||||
|
32, // 5
|
||||||
|
48, // 6
|
||||||
|
64, // 7
|
||||||
|
96, // 8
|
||||||
|
],
|
||||||
|
// border-radius
|
||||||
|
radii: [
|
||||||
|
0, // 0
|
||||||
|
2, // 1
|
||||||
|
4, // 2
|
||||||
|
8, // 3
|
||||||
|
],
|
||||||
|
// width, height, min-width, max-width, min-height, max-height
|
||||||
|
sizes: [
|
||||||
|
0, // 0
|
||||||
|
4, // 1
|
||||||
|
8, // 2
|
||||||
|
16, // 3
|
||||||
|
24, // 4
|
||||||
|
32, // 5
|
||||||
|
48, // 6
|
||||||
|
64, // 7
|
||||||
|
96, // 8
|
||||||
|
],
|
||||||
|
// z-index
|
||||||
|
zIndices: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||||
|
breakpoints: ["768px", "1024px", "1440px", "2200px"],
|
||||||
|
};
|
||||||
|
export type Theme = typeof theme;
|
||||||
|
export const styled = baseStyled as ThemedStyledInterface<Theme>;
|
||||||
|
export default theme;
|
Loading…
Reference in New Issue
Block a user