Merge pull request #2369 from urbit/unmanaged-chats-rc

Unmanaged Chats Work Properly and Support Metadata Syncing
This commit is contained in:
Logan 2020-02-28 11:52:54 -08:00 committed by GitHub
commit 1cfd176434
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 71 additions and 39 deletions

View File

@ -208,8 +208,8 @@
%- zing %- zing
:~ (create-chat app-path.act security.act allow-history.act) :~ (create-chat app-path.act security.act allow-history.act)
(create-managed-group group-path.act security.act members.act) (create-managed-group group-path.act security.act members.act)
(create-metadata title.act description.act group-path.act app-path.act)
(create-security group-path.act security.act) (create-security group-path.act security.act)
(create-metadata group-path.act app-path.act)
~[(permission-hook-poke [%add-owned group-path.act group-path.act])] ~[(permission-hook-poke [%add-owned group-path.act group-path.act])]
== ==
:: ::
@ -224,6 +224,7 @@
:: ::
?: (is-managed group-path) ~ ?: (is-managed group-path) ~
:~ (permission-hook-poke [%remove group-path]) :~ (permission-hook-poke [%remove group-path])
(permission-poke [%delete group-path])
(group-poke [%unbundle group-path]) (group-poke [%unbundle group-path])
(metadata-hook-poke [%remove group-path]) (metadata-hook-poke [%remove group-path])
== ==
@ -249,26 +250,24 @@
++ create-managed-group ++ create-managed-group
|= [=path security=rw-security ships=(set ship)] |= [=path security=rw-security ships=(set ship)]
^- (list card) ^- (list card)
?> ?=(^ path)
?^ (group-scry path) ~ ?^ (group-scry path) ~
:: do not create a managed group if this is a sig path or a blacklist :: do not create a managed group if this is a sig path or a blacklist
:: ::
?: =(security %channel) ?: =(security %channel)
~[(group-poke [%bundle path])] ~[(group-poke [%bundle path])]
?: =(i.path '~') ?: (is-managed path)
:~ (group-poke [%bundle path]) ~[(contact-view-poke [%create path ships])]
(group-poke [%add ships path]) :~ (group-poke [%bundle path])
== (group-poke [%add ships path])
~[(contact-view-poke [%create path ships])] ==
:: ::
++ create-metadata ++ create-metadata
|= [group-path=path app-path=path] |= [title=@t description=@t group-path=path app-path=path]
^- (list card) ^- (list card)
~& group-path+group-path
~& app-path+app-path
~& is-managed+(is-managed app-path)
=/ =metadata =/ =metadata
%* . *metadata %* . *metadata
title title
description description
date-created now.bol date-created now.bol
creator creator
%+ slav %p %+ slav %p
@ -373,6 +372,11 @@
^- card ^- card
[%pass / %agent [our.bol %group-store] %poke %group-action !>(act)] [%pass / %agent [our.bol %group-store] %poke %group-action !>(act)]
:: ::
++ permission-poke
|= act=permission-action
^- card
[%pass / %agent [our.bol %permission-store] %poke %permission-action !>(act)]
::
++ chat-hook-poke ++ chat-hook-poke
|= act=chat-hook-action |= act=chat-hook-action
^- card ^- card

File diff suppressed because one or more lines are too long

View File

@ -132,7 +132,7 @@
|= pax=^path |= pax=^path
^- associations ^- associations
=. pax ;:(weld /=metadata-store/(scot %da now.bowl)/group pax /noun) =. pax ;:(weld /=metadata-store/(scot %da now.bowl)/group pax /noun)
(need .^((unit associations) %gx pax)) .^(associations %gx pax)
-- --
:: ::
++ fact-metadata-update ++ fact-metadata-update

View File

@ -171,6 +171,7 @@
:: ::
++ metadata-for-app ++ metadata-for-app
|= =app-name |= =app-name
^- ^associations
%- ~(gas by *^associations) %- ~(gas by *^associations)
%+ turn ~(tap in (~(gut by app-indices) app-name ~)) %+ turn ~(tap in (~(gut by app-indices) app-name ~))
|= [=group-path =app-path] |= [=group-path =app-path]
@ -179,6 +180,7 @@
:: ::
++ metadata-for-group ++ metadata-for-group
|= =group-path |= =group-path
^- ^associations
%- ~(gas by *^associations) %- ~(gas by *^associations)
%+ turn ~(tap in (~(got by group-indices) group-path)) %+ turn ~(tap in (~(got by group-indices) group-path))
|= =resource |= =resource

View File

@ -117,7 +117,6 @@
(snoc (recreate-permissions perm-paths associate) (watch-group group)) (snoc (recreate-permissions perm-paths associate) (watch-group group))
:: ::
=/ grp (group-scry group) =/ grp (group-scry group)
~& associate+grp
=. u.perms (~(uni in u.perms) perm-paths) =. u.perms (~(uni in u.perms) perm-paths)
:_ state(relation (~(put by relation) group u.perms)) :_ state(relation (~(put by relation) group u.perms))
%+ weld %+ weld

View File

@ -224,7 +224,9 @@
:: ::
++ create ++ create
%- ot %- ot
:~ [%app-path pa] :~ [%title so]
[%description so]
[%app-path pa]
[%group-path pa] [%group-path pa]
[%security sec] [%security sec]
[%members (as (su ;~(pfix sig fed:ag)))] [%members (as (su ;~(pfix sig fed:ag)))]

View File

@ -2,6 +2,8 @@
|% |%
+$ chat-view-action +$ chat-view-action
$% $: %create $% $: %create
title=@t
description=@t
app-path=path app-path=path
group-path=path group-path=path
security=rw-security security=rw-security

View File

@ -128,9 +128,14 @@ class UrbitApi {
return this.action("chat-view", "json", data); return this.action("chat-view", "json", data);
} }
chatViewCreate(appPath, groupPath, security, members, allowHistory) { chatViewCreate(
return this.chatViewAction({ title, description, appPath, groupPath,
security, members, allowHistory
) {
return this.chatViewAction({
create: { create: {
title,
description,
'app-path': appPath, 'app-path': appPath,
'group-path': groupPath, 'group-path': groupPath,
security, security,

View File

@ -64,14 +64,14 @@ export class JoinScreen extends Component {
} }
let station = text.split('/'); let station = text.split('/');
let sig = state.station.includes("/~/"); let sig = state.station.includes("~/");
let ship = !!sig ? station[2] : station[1]; let ship = !!sig ? station[1] : station[0];
station = station.join('/'); station = station.join('/');
if ( if (
station.length < 2 || (!sig && station.split('/').length < 2) ||
(!!sig && station.length < 3) || (!!sig && station.split('/').length < 3) ||
!urbitOb.isValidPatp(ship) !urbitOb.isValidPatp(ship)
) { ) {
this.setState({ this.setState({
@ -80,7 +80,7 @@ export class JoinScreen extends Component {
return; return;
} }
props.api.chatView.join(ship, station, true); props.api.chatView.join(ship, `/${station}`, true);
} }
stationChange(event) { stationChange(event) {
@ -115,7 +115,7 @@ export class JoinScreen extends Component {
</div> </div>
<h2 className="mb3 f8">Join Existing Chat</h2> <h2 className="mb3 f8">Join Existing Chat</h2>
<div className="w-100"> <div className="w-100">
<p className="f8 lh-copy mt3 db">Enter a <span className="mono">~ship/chat-name</span></p> <p className="f8 lh-copy mt3 db">Enter a <span className="mono">~ship/chat-name</span> or <span className="mono">~/~ship/chat-name</span></p>
<p className="f9 gray2 mb4">Chat names use lowercase, hyphens, and slashes.</p> <p className="f9 gray2 mb4">Chat names use lowercase, hyphens, and slashes.</p>
<textarea <textarea
ref={ e => { this.textarea = e; } } ref={ e => { this.textarea = e; } }

View File

@ -10,6 +10,8 @@ export class NewScreen extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
title: '',
description: '',
idName: '', idName: '',
groups: [], groups: [],
ships: [], ships: [],
@ -20,7 +22,8 @@ export class NewScreen extends Component {
createGroup: true createGroup: true
}; };
this.idChange = this.idChange.bind(this); this.titleChange = this.titleChange.bind(this);
this.descriptionChange = this.descriptionChange.bind(this);
this.securityChange = this.securityChange.bind(this); this.securityChange = this.securityChange.bind(this);
this.allowHistoryChange = this.allowHistoryChange.bind(this); this.allowHistoryChange = this.allowHistoryChange.bind(this);
this.setInvite = this.setInvite.bind(this); this.setInvite = this.setInvite.bind(this);
@ -38,9 +41,18 @@ export class NewScreen extends Component {
} }
} }
idChange(event) { titleChange(event) {
let asciiSafe = event.target.value.toLowerCase()
.replace(/[^a-z0-9~_.-]/g, "-");
this.setState({ this.setState({
idName: event.target.value idName: asciiSafe,
title: event.target.value
});
}
descriptionChange(event) {
this.setState({
description: event.target.value
}); });
} }
@ -82,13 +94,7 @@ export class NewScreen extends Component {
onClickCreate() { onClickCreate() {
const { props, state } = this; const { props, state } = this;
let validChar = /^[a-z0-9~_.-]*$/; if (!state.title) {
let invalid = (
(!state.idName) || (!validChar.test(state.idName))
);
if (invalid) {
this.setState({ this.setState({
idError: true, idError: true,
inviteError: false inviteError: false
@ -147,6 +153,8 @@ export class NewScreen extends Component {
groupPath = state.groups[0]; groupPath = state.groups[0];
} }
let submit = props.api.chatView.create( let submit = props.api.chatView.create(
state.title,
state.description,
appPath, appPath,
groupPath, groupPath,
state.security, state.security,
@ -220,19 +228,29 @@ export class NewScreen extends Component {
<h2 className="mb3 f8">New Chat</h2> <h2 className="mb3 f8">New Chat</h2>
<div className="w-100"> <div className="w-100">
<p className="f8 mt3 lh-copy db">Name</p> <p className="f8 mt3 lh-copy db">Name</p>
<p className="f9 gray2 db mb2 pt1">
Lowercase alphanumeric characters, dashes, and slashes only
</p>
<textarea <textarea
className={idClasses} className={idClasses}
placeholder="secret-chat" placeholder="Secret Chat"
rows={1} rows={1}
style={{ style={{
resize: "none" resize: "none"
}} }}
onChange={this.idChange} onChange={this.titleChange}
/>
{idErrElem}
<p className="f8 mt3 lh-copy db">
Description
<span className="gray3"> (Optional)</span>
</p>
<textarea
className={idClasses}
placeholder="The coolest chat"
rows={1}
style={{
resize: "none"
}}
onChange={this.descriptionChange}
/> />
{idErrElem}
<p className="f8 mt4 lh-copy db"> <p className="f8 mt4 lh-copy db">
Invite Invite
<span className="gray3"> (Optional)</span> <span className="gray3"> (Optional)</span>