-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Invite a collaborator now without sending an email. Instead, you'll r…
…eceive a link that you can share manually. This change was made to prevent abuse by individuals who used the email feature for spamming.
- Loading branch information
Rustem Mussabekov
committed
Sep 16, 2024
1 parent
e8382da
commit 7f3da7e
Showing
17 changed files
with
129 additions
and
159 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file modified
BIN
-26 Bytes
(100%)
...eproj/project.xcworkspace/xcuserdata/exentrich.xcuserdatad/UserInterfaceState.xcuserstate
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 80 additions & 90 deletions
170
src/co/collections/sharing/collaborators/invite/view.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,98 @@ | ||
import React from 'react' | ||
import React, { useState, useCallback } from 'react' | ||
import t from '~t' | ||
import links from '~config/links' | ||
|
||
import { Alert } from '~co/overlay/dialog' | ||
import { Layout, Title, Label, Text, Radio, Buttons } from '~co/common/form' | ||
import { Prompt, Error } from '~co/overlay/dialog' | ||
import { Layout, Title, Label, Radio, Buttons } from '~co/common/form' | ||
import Button from '~co/common/button' | ||
import Icon from '~co/common/icon' | ||
|
||
export default class CollectionSharingInviteView extends React.PureComponent { | ||
state = { | ||
emails: '', | ||
role: 'member' | ||
} | ||
export default function CollectionSharingInviteView({ access, onInvite }) { | ||
const [role, setRole] = useState('member') | ||
const [loading, setLoading] = useState(false) | ||
|
||
componentDidUpdate(prev) { | ||
if (prev.status != this.props.status) | ||
switch(this.props.status) { | ||
case 'error': | ||
Alert(t.s('sendInvites')+' '+t.s('server').toLowerCase(), { variant: 'error' }) | ||
break | ||
|
||
case 'done': | ||
this.setState({ emails: '' }) | ||
Alert(t.s('invitesSendTo')+' '+this.props.sendTo.join(', ')) | ||
break | ||
} | ||
} | ||
const onRoleChange = useCallback(e=>{ | ||
setRole(e.currentTarget.value) | ||
}, [setRole]) | ||
|
||
handleEmailsChange = (e)=> | ||
this.setState({ emails: e.target.value }) | ||
|
||
handleChangeRole = (e)=> | ||
this.setState({ role: e.currentTarget.value }) | ||
|
||
onSubmit = e=>{ | ||
const onSubmit = useCallback(e=>{ | ||
e.preventDefault() | ||
setLoading(true) | ||
|
||
if (!this.state.emails) | ||
return | ||
|
||
this.props.onInvite(this.state.emails.split(/,|\s/), this.state.role) | ||
} | ||
onInvite( | ||
role, | ||
async(link)=>{ | ||
const copy = await Prompt( | ||
t.s('invite'), | ||
link, | ||
{ | ||
description: ` | ||
Share this link with the person you want to invite to the collection. | ||
Anyone with this link and a Raindrop.io account can join and ${role == 'member' ? 'edit' : 'view'} the collection. | ||
Please note, this link can only be used once and will expire in a week. | ||
`, | ||
ok: t.s('copyLinkToClipboard') | ||
} | ||
) | ||
|
||
render() { | ||
const { emails, role } = this.state | ||
const { status, access } = this.props | ||
|
||
const loading = status == 'loading' | ||
if (copy) { | ||
await navigator.permissions.query({name: 'clipboard-write'}) | ||
await await navigator.clipboard.writeText(link) | ||
} | ||
setLoading(false) | ||
}, | ||
(error)=>{ | ||
Error(error, { | ||
message: t.s('sendInvites')+' '+t.s('server').toLowerCase() | ||
}) | ||
setLoading(false) | ||
} | ||
) | ||
}, [onInvite, role, setLoading]) | ||
|
||
if (!access || access.level < 3) | ||
return null | ||
if (!access || access.level < 3) | ||
return null | ||
|
||
return ( | ||
<form onSubmit={this.onSubmit}> | ||
<Layout type='grid'> | ||
<Title>{t.s('invite')}</Title> | ||
<Label>Email</Label> | ||
<Text | ||
type='email' | ||
multiple={true} | ||
placeholder={t.s('enterEmails')} | ||
return ( | ||
<form onSubmit={onSubmit}> | ||
<Layout type='grid'> | ||
<Title>{t.s('invite')}</Title> | ||
|
||
<Label>{t.s('withAccessLevel')}</Label> | ||
<div> | ||
<Radio | ||
checked={role=='member'} | ||
value='member' | ||
disabled={loading} | ||
value={emails} | ||
required | ||
autoFocus | ||
onChange={this.handleEmailsChange} /> | ||
onChange={onRoleChange}> | ||
{t.s('role_members')+' '+t.s('und')+' '+t.s('invite').toLowerCase()} | ||
</Radio> | ||
|
||
<Label>{t.s('withAccessLevel')}</Label> | ||
<div> | ||
<Radio | ||
checked={role=='member'} | ||
value='member' | ||
disabled={loading} | ||
onChange={this.handleChangeRole}> | ||
{t.s('role_members')+' '+t.s('und')+' '+t.s('invite').toLowerCase()} | ||
</Radio> | ||
|
||
<Radio | ||
checked={role=='viewer'} | ||
value='viewer' | ||
disabled={loading} | ||
onChange={this.handleChangeRole}> | ||
{t.s('role_viewer')} | ||
</Radio> | ||
</div> | ||
<Radio | ||
checked={role=='viewer'} | ||
value='viewer' | ||
disabled={loading} | ||
onChange={onRoleChange}> | ||
{t.s('role_viewer')} | ||
</Radio> | ||
</div> | ||
|
||
<Buttons variant='between'> | ||
<Button | ||
as='input' | ||
type='submit' | ||
variant='primary' | ||
disabled={loading} | ||
value={t.s('sendInvites')+(loading ? '…' : '')} /> | ||
<Buttons variant='between'> | ||
<Button | ||
as='input' | ||
type='submit' | ||
variant='primary' | ||
disabled={loading} | ||
value={t.s('invite')+(loading ? '…' : '')} /> | ||
|
||
<Button | ||
href={links.help.collaboration} | ||
target='_blank'> | ||
<Icon name='help' /> | ||
{t.s('howToUse')} | ||
</Button> | ||
</Buttons> | ||
</Layout> | ||
</form> | ||
) | ||
} | ||
<Button | ||
href={links.help.collaboration} | ||
target='_blank'> | ||
<Icon name='help' /> | ||
{t.s('howToUse')} | ||
</Button> | ||
</Buttons> | ||
</Layout> | ||
</form> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
.prompt { | ||
width: 10rem //400px | ||
} | ||
|
||
.description { | ||
color: var(--primary-text-color) | ||
} |
Oops, something went wrong.