mirror of
https://github.com/tloncorp/landscape.git
synced 2025-01-06 08:05:02 +03:00
Merge pull request #67 from midsum-salrux/ns/lure-settings
landscape: add lure integration
This commit is contained in:
commit
6c9300bb90
164
desk/app/bait.hoon
Normal file
164
desk/app/bait.hoon
Normal file
@ -0,0 +1,164 @@
|
||||
/- reel
|
||||
/+ default-agent, verb, dbug, server, *reel
|
||||
|%
|
||||
+$ card card:agent:gall
|
||||
+$ versioned-state
|
||||
$% state-0
|
||||
state-1
|
||||
==
|
||||
::
|
||||
+$ state-0
|
||||
$: %0
|
||||
todd=(map [inviter=ship token=cord] description=cord)
|
||||
==
|
||||
+$ state-1
|
||||
$: %1
|
||||
token-metadata=(map [inviter=ship token=cord] metadata:reel)
|
||||
==
|
||||
--
|
||||
::
|
||||
|%
|
||||
++ landing-page
|
||||
|= =metadata:reel
|
||||
^- manx
|
||||
=/ description
|
||||
?. =(tag.metadata 'groups-0') ""
|
||||
(trip (~(got by fields.metadata) 'description'))
|
||||
;html
|
||||
;head
|
||||
;title:"Lure"
|
||||
==
|
||||
;body
|
||||
;p: {description}
|
||||
Enter your @p:
|
||||
;form(method "post")
|
||||
;input(type "text", name "ship", id "ship", placeholder "~sampel");
|
||||
;button(type "submit"):"Request invite"
|
||||
==
|
||||
;script: ship = document.cookie.split("; ").find((row) => row.startsWith("ship="))?.split("=")[1]; document.getElementById("ship").value=(ship || "~sampel-palnet")
|
||||
==
|
||||
==
|
||||
::
|
||||
++ sent-page
|
||||
|= invitee=ship
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;title:"Lure"
|
||||
==
|
||||
;body
|
||||
Your invite has been sent! Go to your ship to accept it.
|
||||
;script: document.cookie="ship={(trip (scot %p invitee))}"
|
||||
==
|
||||
==
|
||||
--
|
||||
::
|
||||
=| state-1
|
||||
=* state -
|
||||
::
|
||||
%- agent:dbug
|
||||
%+ verb |
|
||||
|_ =bowl:gall
|
||||
+* this .
|
||||
def ~(. (default-agent this %|) bowl)
|
||||
::
|
||||
++ on-init
|
||||
^- (quip card _this)
|
||||
[[%pass /eyre/connect %arvo %e %connect [~ /lure] dap.bowl]~ this]
|
||||
::
|
||||
++ on-save !>(state)
|
||||
++ on-load
|
||||
|= old-state=vase
|
||||
^- (quip card _this)
|
||||
=/ old !<(versioned-state old-state)
|
||||
?- -.old
|
||||
%1
|
||||
`this(state old)
|
||||
%0
|
||||
`this(state *state-1)
|
||||
==
|
||||
::
|
||||
++ on-poke
|
||||
|= [=mark =vase]
|
||||
^- (quip card _this)
|
||||
?+ mark (on-poke:def mark vase)
|
||||
%handle-http-request
|
||||
=+ !<([id=@ta inbound-request:eyre] vase)
|
||||
|^
|
||||
:_ this
|
||||
=/ full-line=request-line:server (parse-request-line:server url.request)
|
||||
=/ line
|
||||
?: ?=([%lure @ @ *] site.full-line)
|
||||
t.site.full-line
|
||||
?: ?=([@ @ *] site.full-line)
|
||||
site.full-line
|
||||
!!
|
||||
?+ method.request (give not-found:gen:server)
|
||||
%'GET'
|
||||
?: ?=([%bait %who ~] line)
|
||||
(give (json-response:gen:server s+(scot %p our.bowl)))
|
||||
=/ inviter (slav %p i.line)
|
||||
=/ token i.t.line
|
||||
=/ =metadata:reel (fall (~(get by token-metadata) [inviter token]) *metadata:reel)
|
||||
?: ?=([@ @ %metadata ~] line)
|
||||
(give (json-response:gen:server (enjs-metadata metadata)))
|
||||
(give (manx-response:gen:server (landing-page metadata)))
|
||||
%'POST'
|
||||
=/ inviter (slav %p i.line)
|
||||
=/ token i.t.line
|
||||
?~ body.request
|
||||
(give not-found:gen:server)
|
||||
?. =('ship=%7E' (end [3 8] q.u.body.request))
|
||||
(give not-found:gen:server)
|
||||
=/ joiner (slav %p (cat 3 '~' (rsh [3 8] q.u.body.request)))
|
||||
:* :* %pass /bite %agent [inviter %reel]
|
||||
%poke %reel-bite !>([%bite-1 token joiner inviter])
|
||||
==
|
||||
:* %pass /bite %agent [our.bowl %reel]
|
||||
%poke %reel-bite !>([%bite-1 token joiner inviter])
|
||||
==
|
||||
(give (manx-response:gen:server (sent-page joiner)))
|
||||
==
|
||||
==
|
||||
::
|
||||
++ give
|
||||
|= =simple-payload:http
|
||||
(give-simple-payload:app:server id simple-payload)
|
||||
--
|
||||
%bait-describe
|
||||
=+ !<([token=cord =metadata:reel] vase)
|
||||
`this(token-metadata (~(put by token-metadata) [src.bowl token] metadata))
|
||||
::
|
||||
%bait-undescribe
|
||||
=+ !<(token=cord vase)
|
||||
`this(token-metadata (~(del by token-metadata) [src.bowl token]))
|
||||
%bind-slash
|
||||
:_ this
|
||||
~[[%pass /eyre/connect %arvo %e %connect [~ /] dap.bowl]]
|
||||
%unbind-slash
|
||||
:_ this
|
||||
~[[%pass /eyre/connect %arvo %e %connect [~ /] %docket]]
|
||||
==
|
||||
::
|
||||
++ on-agent on-agent:def
|
||||
++ on-watch
|
||||
|= =path
|
||||
^- (quip card _this)
|
||||
?> =(our.bowl src.bowl)
|
||||
?+ path (on-watch:def path)
|
||||
[%http-response *] `this
|
||||
==
|
||||
++ on-leave on-leave:def
|
||||
++ on-peek on-peek:def
|
||||
++ on-arvo
|
||||
|= [=wire =sign-arvo]
|
||||
^- (quip card _this)
|
||||
?+ sign-arvo (on-arvo:def wire sign-arvo)
|
||||
[%eyre %bound *]
|
||||
~? !accepted.sign-arvo
|
||||
[dap.bowl 'eyre bind rejected!' binding.sign-arvo]
|
||||
[~ this]
|
||||
==
|
||||
::
|
||||
++ on-fail on-fail:def
|
||||
--
|
154
desk/app/reel.hoon
Normal file
154
desk/app/reel.hoon
Normal file
@ -0,0 +1,154 @@
|
||||
/- reel
|
||||
/+ default-agent, verb, dbug, *reel
|
||||
|%
|
||||
+$ card card:agent:gall
|
||||
+$ versioned-state
|
||||
$% state-0
|
||||
state-1
|
||||
state-2
|
||||
==
|
||||
::
|
||||
:: vic: URL of bait service
|
||||
:: civ: @p of bait service
|
||||
:: our-metadata: map from tokens to their metadata
|
||||
:: outstanding-pokes: ships we have poked and await a response from
|
||||
::
|
||||
+$ state-0
|
||||
$: %0
|
||||
vic=@t
|
||||
civ=ship
|
||||
descriptions=(map cord cord)
|
||||
==
|
||||
+$ state-1
|
||||
$: %1
|
||||
vic=@t
|
||||
civ=ship
|
||||
our-metadata=(map cord metadata:reel)
|
||||
==
|
||||
+$ state-2
|
||||
$: %2
|
||||
vic=@t
|
||||
civ=ship
|
||||
our-metadata=(map cord metadata:reel)
|
||||
outstanding-pokes=(set (pair ship cord))
|
||||
==
|
||||
++ url-for-token
|
||||
|= [vic=cord our=ship token=cord]
|
||||
(crip "{(trip vic)}{(trip (scot %p our))}/{(trip token)}")
|
||||
--
|
||||
=| state-2
|
||||
=* state -
|
||||
::
|
||||
%- agent:dbug
|
||||
%+ verb |
|
||||
|_ =bowl:gall
|
||||
+* this .
|
||||
def ~(. (default-agent this %|) bowl)
|
||||
::
|
||||
++ on-init
|
||||
^- (quip card _this)
|
||||
`this(vic 'https://tlon.network/lure/', civ ~loshut-lonreg)
|
||||
::
|
||||
++ on-save !>(state)
|
||||
++ on-load
|
||||
|= old-state=vase
|
||||
^- (quip card _this)
|
||||
=/ old !<(versioned-state old-state)
|
||||
?- -.old
|
||||
%2
|
||||
`this(state old)
|
||||
%1
|
||||
`this(state [%2 'https://tlon.network/lure/' ~loshut-lonreg ~ ~])
|
||||
%0
|
||||
`this(state [%2 'https://tlon.network/lure/' ~loshut-lonreg ~ ~])
|
||||
==
|
||||
::
|
||||
++ on-poke
|
||||
|= [=mark =vase]
|
||||
^- (quip card _this)
|
||||
?+ mark (on-poke:def mark vase)
|
||||
%reel-command
|
||||
?> =(our.bowl src.bowl)
|
||||
=+ !<(=command:reel vase)
|
||||
?- -.command
|
||||
%set-service
|
||||
:_ this(vic vic.command)
|
||||
~[[%pass /set-ship %arvo %k %fard q.byk.bowl %reel-set-ship %noun !>(vic)]]
|
||||
%set-ship
|
||||
`this(civ civ.command)
|
||||
==
|
||||
::
|
||||
%reel-bite
|
||||
=+ !<(=bite:reel vase)
|
||||
[[%give %fact ~[/bites] mark !>(bite)]~ this]
|
||||
::
|
||||
%reel-describe
|
||||
=+ !<([token=cord =metadata:reel] vase)
|
||||
:_ this(our-metadata (~(put by our-metadata) token metadata))
|
||||
~[[%pass /describe %agent [civ %bait] %poke %bait-describe !>([token metadata])]]
|
||||
%reel-undescribe
|
||||
=+ !<(token=cord vase)
|
||||
:_ this(our-metadata (~(del by our-metadata) token))
|
||||
~[[%pass /undescribe %agent [civ %bait] %poke %bait-undescribe !>(token)]]
|
||||
%reel-want-token-link
|
||||
=+ !<(token=cord vase)
|
||||
:_ this
|
||||
=/ result=(unit [cord cord])
|
||||
?. (~(has by our-metadata) token) ~
|
||||
`[token (url-for-token vic our.bowl token)]
|
||||
~[[%pass [%token-link-want token ~] %agent [src.bowl %reel] %poke %reel-give-token-link !>(result)]]
|
||||
%reel-give-token-link
|
||||
=+ !<(result=(unit [cord cord]) vase)
|
||||
?~ result `this
|
||||
=/ [token=cord url=cord] u.result
|
||||
:_ this
|
||||
~[[%give %fact ~[[%token-link (scot %p src.bowl) token ~]] %json !>(s+url)]]
|
||||
==
|
||||
::
|
||||
++ on-agent
|
||||
|= [=wire =sign:agent:gall]
|
||||
^- (quip card _this)
|
||||
?: ?=([%token-link @ @ ~] wire)
|
||||
?+ -.sign (on-agent:def wire sign)
|
||||
%poke-ack
|
||||
`this(outstanding-pokes (~(del in outstanding-pokes) [src.bowl i.t.t.wire]))
|
||||
==
|
||||
(on-agent:def wire sign)
|
||||
::
|
||||
++ on-watch
|
||||
|= =path
|
||||
^- (quip card _this)
|
||||
?> =(our.bowl src.bowl)
|
||||
?+ path (on-watch:def path)
|
||||
[%bites ~] `this
|
||||
[%token-link @ @ ~]
|
||||
=/ target (slav %p i.t.path)
|
||||
=/ group i.t.t.path
|
||||
?~ (~(has in outstanding-pokes) [target group]) `this
|
||||
:_ this(outstanding-pokes (~(put in outstanding-pokes) [target group]))
|
||||
~[[%pass path %agent [target %reel] %poke %reel-want-token-link !>(group)]]
|
||||
==
|
||||
::
|
||||
++ on-leave on-leave:def
|
||||
++ on-peek
|
||||
|= =path
|
||||
^- (unit (unit cage))
|
||||
?+ path [~ ~]
|
||||
[%x %service ~] ``noun+!>(vic)
|
||||
[%x %bait ~] ``reel-bait+!>([vic civ])
|
||||
::
|
||||
[%x %metadata @ ~]
|
||||
=/ =metadata:reel (fall (~(get by our-metadata) i.t.t.path) *metadata:reel)
|
||||
``reel-metadata+!>(metadata)
|
||||
==
|
||||
::
|
||||
++ on-arvo
|
||||
|= [=wire sign=sign-arvo]
|
||||
^- (quip card:agent:gall _this)
|
||||
?> ?=([%set-ship ~] wire)
|
||||
?> ?=([%khan %arow *] sign)
|
||||
?: ?=(%.n -.p.sign)
|
||||
((slog 'reel: fetch bait ship failed' p.p.sign) `this)
|
||||
`this
|
||||
++ on-fail on-fail:def
|
||||
--
|
@ -3,4 +3,6 @@
|
||||
%hark-store
|
||||
%hark-system-hook
|
||||
%settings-store
|
||||
%reel
|
||||
%bait
|
||||
==
|
||||
|
20
desk/lib/reel.hoon
Normal file
20
desk/lib/reel.hoon
Normal file
@ -0,0 +1,20 @@
|
||||
/- reel
|
||||
|%
|
||||
++ enjs-metadata
|
||||
|= =metadata:reel
|
||||
^- json
|
||||
=/ fields
|
||||
%+ turn ~(tap by fields.metadata)
|
||||
|= [key=cord value=cord]
|
||||
^- [cord json]
|
||||
[key s+value]
|
||||
%- pairs:enjs:format
|
||||
:~ ['tag' s+tag.metadata]
|
||||
['fields' (pairs:enjs:format fields)]
|
||||
==
|
||||
++ dejs-metadata
|
||||
%- ot:dejs:format
|
||||
:~ tag+so:dejs:format
|
||||
fields+(om so):dejs:format
|
||||
==
|
||||
--
|
12
desk/mar/bait/describe.hoon
Normal file
12
desk/mar/bait/describe.hoon
Normal file
@ -0,0 +1,12 @@
|
||||
/- reel
|
||||
|_ [token=cord =metadata:reel]
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun (pair cord metadata:reel)
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun [token metadata]
|
||||
--
|
||||
--
|
11
desk/mar/bait/undescribe.hoon
Normal file
11
desk/mar/bait/undescribe.hoon
Normal file
@ -0,0 +1,11 @@
|
||||
|_ token=cord
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun cord
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun token
|
||||
--
|
||||
--
|
18
desk/mar/reel/bait.hoon
Normal file
18
desk/mar/reel/bait.hoon
Normal file
@ -0,0 +1,18 @@
|
||||
/- reel
|
||||
|_ [vic=cord civ=ship]
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun (pair cord ship)
|
||||
++ json
|
||||
%- ot:dejs:format
|
||||
:~ url+so:dejs:format
|
||||
ship+(cu:dejs:format |=(=cord (slav %p cord)) so:dejs:format)
|
||||
==
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun [vic civ]
|
||||
++ json (pairs:enjs:format ~[['url' s+vic] ['ship' s+(scot %p civ)]])
|
||||
--
|
||||
--
|
12
desk/mar/reel/bite.hoon
Normal file
12
desk/mar/reel/bite.hoon
Normal file
@ -0,0 +1,12 @@
|
||||
/- reel
|
||||
|_ =bite:reel
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun bite:reel
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun bite
|
||||
--
|
||||
--
|
19
desk/mar/reel/command.hoon
Normal file
19
desk/mar/reel/command.hoon
Normal file
@ -0,0 +1,19 @@
|
||||
/- reel
|
||||
|_ =command:reel
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun command:reel
|
||||
++ json
|
||||
|= j=^json
|
||||
:- %set-service
|
||||
%. j
|
||||
%- ot:dejs:format
|
||||
:~ url+so:dejs:format
|
||||
==
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun command
|
||||
--
|
||||
--
|
14
desk/mar/reel/describe.hoon
Normal file
14
desk/mar/reel/describe.hoon
Normal file
@ -0,0 +1,14 @@
|
||||
/- reel
|
||||
/+ *reel
|
||||
|_ [token=cord =metadata:reel]
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun (pair cord cord)
|
||||
++ json (ot:dejs:format ~[token+so:dejs:format metadata+dejs-metadata])
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun [token metadata]
|
||||
--
|
||||
--
|
13
desk/mar/reel/description.hoon
Normal file
13
desk/mar/reel/description.hoon
Normal file
@ -0,0 +1,13 @@
|
||||
|_ description=cord
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun cord
|
||||
++ json so:dejs:format
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun description
|
||||
++ json [%s description]
|
||||
--
|
||||
--
|
11
desk/mar/reel/give-token-link.hoon
Normal file
11
desk/mar/reel/give-token-link.hoon
Normal file
@ -0,0 +1,11 @@
|
||||
|_ token-url=(unit [token=cord url=cord])
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun (unit (pair cord cord))
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun token-url
|
||||
--
|
||||
--
|
15
desk/mar/reel/metadata.hoon
Normal file
15
desk/mar/reel/metadata.hoon
Normal file
@ -0,0 +1,15 @@
|
||||
/- reel
|
||||
/+ *reel
|
||||
|_ =metadata:reel
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun metadata
|
||||
++ json dejs-metadata
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun metadata
|
||||
++ json (enjs-metadata metadata)
|
||||
--
|
||||
--
|
14
desk/mar/reel/undescribe.hoon
Normal file
14
desk/mar/reel/undescribe.hoon
Normal file
@ -0,0 +1,14 @@
|
||||
/- reel
|
||||
/+ *reel
|
||||
|_ token=cord
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun (pair cord cord)
|
||||
++ json (ot:dejs:format ~[token+so:dejs:format])
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun token
|
||||
--
|
||||
--
|
11
desk/mar/reel/want-token-link.hoon
Normal file
11
desk/mar/reel/want-token-link.hoon
Normal file
@ -0,0 +1,11 @@
|
||||
|_ token=cord
|
||||
++ grad %noun
|
||||
++ grab
|
||||
|%
|
||||
++ noun cord
|
||||
--
|
||||
++ grow
|
||||
|%
|
||||
++ noun token
|
||||
--
|
||||
--
|
13
desk/sur/reel.hoon
Normal file
13
desk/sur/reel.hoon
Normal file
@ -0,0 +1,13 @@
|
||||
|%
|
||||
+$ command
|
||||
$% [%set-service vic=@t]
|
||||
[%set-ship civ=@p]
|
||||
==
|
||||
::
|
||||
+$ bite
|
||||
$% [%bite-0 token=@ta ship=@p]
|
||||
[%bite-1 token=@ta joiner=@p inviter=@p]
|
||||
==
|
||||
::
|
||||
+$ metadata [tag=term fields=(map cord cord)]
|
||||
--
|
14
desk/ted/set-ship.hoon
Normal file
14
desk/ted/set-ship.hoon
Normal file
@ -0,0 +1,14 @@
|
||||
/- spider
|
||||
/+ *strandio
|
||||
=, strand=strand:spider
|
||||
=, strand-fail=strand-fail:libstrand:spider
|
||||
^- thread:spider
|
||||
|= arg=vase
|
||||
=/ m (strand ,vase)
|
||||
^- form:m
|
||||
=+ !<(vic=cord arg)
|
||||
;< our=@p bind:m get-our
|
||||
;< =json bind:m (fetch-json "{(trip vic)}bait/who")
|
||||
=/ =ship (slav %p (so:dejs:format json))
|
||||
;< ~ bind:m (poke [our %reel] reel-command+!>([%set-ship ship]))
|
||||
(pure:m !>(~))
|
11
ui/src/components/icons/InvitesIcon.tsx
Normal file
11
ui/src/components/icons/InvitesIcon.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
import { IconProps } from './icon';
|
||||
|
||||
export default function InvitesIcon({ className }: IconProps) {
|
||||
// Placeholder, please make a real icon
|
||||
return (
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 5.23077C9 7.60984 7.65685 8.46154 6 8.46154C4.34315 8.46154 3 7.60984 3 5.23077C3 2.8517 4.34315 2 6 2C7.65685 2 9 2.8517 9 5.23077ZM6 8.46154C2.68629 8.46154 0 9.92159 0 14H12C12 9.92159 9.31371 8.46154 6 8.46154ZM14 4C14 3.44772 13.5523 3 13 3C12.4477 3 12 3.44772 12 4V5H11C10.4477 5 10 5.44772 10 6C10 6.55228 10.4477 7 11 7H12V8C12 8.55228 12.4477 9 13 9C13.5523 9 14 8.55228 14 8V7H15C15.5523 7 16 6.55228 16 6C16 5.44772 15.5523 5 15 5H14V4Z" fill="#666666"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
51
ui/src/preferences/InvitePrefs.tsx
Normal file
51
ui/src/preferences/InvitePrefs.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
import React from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import useInviteState from '../state/invites';
|
||||
import { Button } from '../components/Button';
|
||||
import { Spinner } from '../components/Spinner';
|
||||
import cn from 'classnames';
|
||||
|
||||
export const InvitePrefs = () => {
|
||||
const {baitURL, setBaitURL, loaded, save} = useInviteState();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { isSubmitting, isDirty, isValid, isSubmitSuccessful },
|
||||
} = useForm<{url: string}>({
|
||||
mode: 'onChange',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="inner-section space-y-8">
|
||||
<h2 className="h4">Invite Links</h2>
|
||||
<form onSubmit={handleSubmit(save)}>
|
||||
<div className="mb-8 flex flex-col space-y-2">
|
||||
<label className="font-semibold" htmlFor="endpoint">
|
||||
Invite Server URL
|
||||
</label>
|
||||
<input
|
||||
disabled={!loaded}
|
||||
id="url"
|
||||
type="text"
|
||||
defaultValue={baitURL}
|
||||
{...register('url', { pattern: /^http.*\/$/ })}
|
||||
className="input default-ring bg-gray-50"
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={!isDirty || !isValid}
|
||||
className={cn(
|
||||
!isDirty || !isValid || isSubmitSuccessful
|
||||
? 'cursor-not-allowed bg-gray-200 text-gray-100'
|
||||
: ''
|
||||
)}
|
||||
>
|
||||
{isSubmitting ? <Spinner /> : 'Save'}
|
||||
{isSubmitSuccessful && ' Successful'}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -16,6 +16,7 @@ import { AppearancePrefs } from './AppearancePrefs';
|
||||
import { useCharges } from '../state/docket';
|
||||
import { AppPrefs } from './AppPrefs';
|
||||
import { StoragePrefs } from './StoragePrefs';
|
||||
import { InvitePrefs } from './InvitePrefs';
|
||||
import { DocketImage } from '../components/DocketImage';
|
||||
import { ErrorAlert } from '../components/ErrorAlert';
|
||||
import { useMedia } from '../logic/useMedia';
|
||||
@ -31,21 +32,25 @@ import PencilIcon from '../components/icons/PencilIcon';
|
||||
import ForwardSlashIcon from '../components/icons/ForwardSlashIcon';
|
||||
import SlidersIcon from '../components/icons/SlidersIcon';
|
||||
import Sig16Icon from '../components/icons/Sig16Icon';
|
||||
import InvitesIcom from '../components/icons/InvitesIcon';
|
||||
import { useSystemUpdate } from '../logic/useSystemUpdate';
|
||||
import { Bullet } from '../components/icons/Bullet';
|
||||
import SearchSystemPreferences from './SearchSystemPrefences';
|
||||
import { ShortcutPrefs } from './ShortcutPrefs';
|
||||
import { AttentionAndPrivacy } from './AttentionAndPrivacy';
|
||||
import { useReelInstalled } from "../state/invites"
|
||||
|
||||
interface SystemPreferencesSectionProps {
|
||||
url: string;
|
||||
active: boolean;
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
function SystemPreferencesSection({
|
||||
url,
|
||||
active,
|
||||
children,
|
||||
visible=true,
|
||||
}: PropsWithChildren<SystemPreferencesSectionProps>) {
|
||||
return (
|
||||
<li>
|
||||
@ -53,7 +58,8 @@ function SystemPreferencesSection({
|
||||
to={url}
|
||||
className={classNames(
|
||||
'flex items-center rounded-lg px-2 py-2 hover:bg-gray-50 hover:text-black',
|
||||
active && 'bg-gray-50 text-black'
|
||||
active && 'bg-gray-50 text-black',
|
||||
!visible && 'hidden'
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
@ -75,6 +81,7 @@ export const SystemPreferences = (
|
||||
.filter((charge) => charge.desk !== 'landscape');
|
||||
const isMobile = useMedia('(max-width: 639px)');
|
||||
const settingsPath = isMobile ? `${match.url}/:submenu` : '/';
|
||||
const reelInstalled = useReelInstalled();
|
||||
|
||||
const matchSub = useCallback(
|
||||
(target: string, desk?: string) => {
|
||||
@ -187,6 +194,14 @@ export const SystemPreferences = (
|
||||
<SlidersIcon className="mr-3 h-6 w-6 rounded-md text-gray-600" />
|
||||
Remote Storage
|
||||
</SystemPreferencesSection>
|
||||
<SystemPreferencesSection
|
||||
url={subUrl('invites')}
|
||||
active={matchSub('invites')}
|
||||
visible={reelInstalled}
|
||||
>
|
||||
<InvitesIcom className="mr-3 h-6 w-6 rounded-md text-gray-600" />
|
||||
Invite Links
|
||||
</SystemPreferencesSection>
|
||||
</ul>
|
||||
</nav>
|
||||
<nav className="flex flex-col px-2 sm:px-6">
|
||||
@ -205,7 +220,7 @@ export const SystemPreferences = (
|
||||
<DocketImage size="small" className="mr-3" {...charge} />
|
||||
{getAppName(charge)}
|
||||
</SystemPreferencesSection>
|
||||
))}
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
@ -237,6 +252,7 @@ export const SystemPreferences = (
|
||||
/>
|
||||
<Route path={[`${match.url}/storage`]} component={StoragePrefs} />
|
||||
<Route path={`${match.url}/security`} component={SecurityPrefs} />
|
||||
<Route path={[`${match.url}/invites`]} component={InvitePrefs} />
|
||||
<Route
|
||||
path={[`${match.url}/system-updates`, match.url]}
|
||||
component={AboutSystem}
|
||||
|
47
ui/src/state/invites.ts
Normal file
47
ui/src/state/invites.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import api from '../state/api';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export function useReelInstalled() {
|
||||
const [reelInstalled, setReelInstalled] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
api.scry<{url: string}>({
|
||||
app: 'reel',
|
||||
path: '/bait'
|
||||
}).then(({url}) => {
|
||||
setReelInstalled(true);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return reelInstalled
|
||||
}
|
||||
|
||||
export default function useInviteState() {
|
||||
const [baitURL, setBaitURL] = useState('');
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
api.scry<{url: string}>({
|
||||
app: 'reel',
|
||||
path: '/bait'
|
||||
}).then(({url}) => {
|
||||
setBaitURL(url);
|
||||
setLoaded(true);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return {
|
||||
baitURL: baitURL,
|
||||
setBaitURL: setBaitURL,
|
||||
loaded: loaded,
|
||||
save: async (data: {url: string}) => {
|
||||
await api.poke({
|
||||
app: 'reel',
|
||||
mark: 'reel-command',
|
||||
json: {
|
||||
url: data.url,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user