Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99daeb014c
|
||
|
|
f5a4014e41
|
@@ -15,19 +15,36 @@ describe('ReponsMastodon', () => {
|
||||
expect(container).toBeEmptyDOMElement()
|
||||
})
|
||||
|
||||
it('affiche un lien direct vers le fil bokante', () => {
|
||||
it('affiche un lien direct vers le fil BOKANTE', () => {
|
||||
render(<ReponsMastodon bokanteStatusId='112233' />)
|
||||
const lien = screen.getByRole('link', {name: 'Mastodon'})
|
||||
const lien = screen.getByRole('link', {name: 'BOKANTE (Mastodon)'})
|
||||
expect(lien).toHaveAttribute('href', 'https://bokante.o-k-i.net/@pawol_nu/112233')
|
||||
})
|
||||
|
||||
it('redirige vers authorize_interaction avec le domaine extrait d\'un identifiant complet', async () => {
|
||||
it('redirige vers BOKANTE par défaut quand on continue', async () => {
|
||||
window.open = vi.fn()
|
||||
const user = userEvent.setup()
|
||||
render(<ReponsMastodon bokanteStatusId='112233' />)
|
||||
|
||||
await user.click(screen.getByRole('button', {name: /répondre via mastodon/i}))
|
||||
await user.type(screen.getByLabelText(/@vous@votre-instance/i), '@quelqun@mastodon.social')
|
||||
await user.click(screen.getByRole('button', {name: /répondre sur mastodon/i}))
|
||||
await user.click(screen.getByRole('button', {name: /continuer/i}))
|
||||
|
||||
expect(window.open).toHaveBeenCalledWith(
|
||||
'https://bokante.o-k-i.net/authorize_interaction?uri=' + encodeURIComponent('https://bokante.o-k-i.net/@pawol_nu/112233'),
|
||||
'_blank',
|
||||
'noopener,noreferrer'
|
||||
)
|
||||
})
|
||||
|
||||
it('permet de choisir une autre instance dans le select', async () => {
|
||||
window.open = vi.fn()
|
||||
const user = userEvent.setup()
|
||||
render(<ReponsMastodon bokanteStatusId='112233' />)
|
||||
|
||||
await user.click(screen.getByRole('button', {name: /répondre sur mastodon/i}))
|
||||
await user.click(screen.getByLabelText(/instance mastodon/i))
|
||||
await user.click(screen.getByRole('option', {name: /autre instance/i}))
|
||||
await user.type(screen.getByLabelText(/@vous@votre-instance/i), 'mastodon.social')
|
||||
await user.click(screen.getByRole('button', {name: /continuer/i}))
|
||||
|
||||
expect(window.open).toHaveBeenCalledWith(
|
||||
@@ -37,17 +54,19 @@ describe('ReponsMastodon', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('accepte aussi juste un nom d\'instance sans @', async () => {
|
||||
it('accepte un identifiant complet pour une autre instance', async () => {
|
||||
window.open = vi.fn()
|
||||
const user = userEvent.setup()
|
||||
render(<ReponsMastodon bokanteStatusId='112233' />)
|
||||
|
||||
await user.click(screen.getByRole('button', {name: /répondre via mastodon/i}))
|
||||
await user.type(screen.getByLabelText(/@vous@votre-instance/i), 'mastodon.social')
|
||||
await user.click(screen.getByRole('button', {name: /répondre sur mastodon/i}))
|
||||
await user.click(screen.getByLabelText(/instance mastodon/i))
|
||||
await user.click(screen.getByRole('option', {name: /autre instance/i}))
|
||||
await user.type(screen.getByLabelText(/@vous@votre-instance/i), '@quelqun@mastodon.social')
|
||||
await user.click(screen.getByRole('button', {name: /continuer/i}))
|
||||
|
||||
expect(window.open).toHaveBeenCalledWith(
|
||||
expect.stringContaining('https://mastodon.social/authorize_interaction'),
|
||||
'https://mastodon.social/authorize_interaction?uri=' + encodeURIComponent('https://bokante.o-k-i.net/@pawol_nu/112233'),
|
||||
'_blank',
|
||||
'noopener,noreferrer'
|
||||
)
|
||||
|
||||
@@ -10,11 +10,24 @@ import DialogContent from '@mui/material/DialogContent'
|
||||
import DialogActions from '@mui/material/DialogActions'
|
||||
import TextField from '@mui/material/TextField'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Link from 'next/link'
|
||||
import FormControl from '@mui/material/FormControl'
|
||||
import InputLabel from '@mui/material/InputLabel'
|
||||
import Select from '@mui/material/Select'
|
||||
import MenuItem from '@mui/material/MenuItem'
|
||||
import Link from '@mui/material/Link'
|
||||
import {Mastodon} from '@icons-pack/react-simple-icons'
|
||||
|
||||
const BOKANTE_URL = process.env.NEXT_PUBLIC_BOKANTE_URL || 'https://bokante.o-k-i.net'
|
||||
const BOKANTE_ACCOUNT = process.env.NEXT_PUBLIC_BOKANTE_ACCOUNT || 'pawol_nu'
|
||||
|
||||
const INSTANCES_SUGGEREES = [
|
||||
{domain: 'bokante.o-k-i.net', label: 'BOKANTE - notre instance'},
|
||||
{domain: 'mastodon.social', label: 'mastodon.social'},
|
||||
{domain: 'piaille.fr', label: 'piaille.fr'},
|
||||
]
|
||||
|
||||
const AUTRE_INSTANCE = 'autre'
|
||||
|
||||
function extraireInstance(saisie) {
|
||||
const valeur = saisie.trim().replace(/^@/, '').replace(/^https?:\/\//, '').replace(/\/$/, '')
|
||||
return valeur.includes('@') ? valeur.split('@').pop() : valeur
|
||||
@@ -22,7 +35,8 @@ function extraireInstance(saisie) {
|
||||
|
||||
export default function ReponsMastodon({bokanteStatusId}) {
|
||||
const [ouvert, setOuvert] = useState(false)
|
||||
const [saisie, setSaisie] = useState('')
|
||||
const [instance, setInstance] = useState(INSTANCES_SUGGEREES[0].domain)
|
||||
const [autreInstance, setAutreInstance] = useState('')
|
||||
|
||||
if (!bokanteStatusId) {
|
||||
return null
|
||||
@@ -31,43 +45,92 @@ export default function ReponsMastodon({bokanteStatusId}) {
|
||||
const tootUrl = `${BOKANTE_URL}/@${BOKANTE_ACCOUNT}/${bokanteStatusId}`
|
||||
|
||||
const repondre = () => {
|
||||
const instance = extraireInstance(saisie)
|
||||
if (!instance) {
|
||||
const domaine = instance === AUTRE_INSTANCE ? extraireInstance(autreInstance) : instance
|
||||
if (!domaine) {
|
||||
return
|
||||
}
|
||||
|
||||
window.open(`https://${instance}/authorize_interaction?uri=${encodeURIComponent(tootUrl)}`, '_blank', 'noopener,noreferrer')
|
||||
window.open(`https://${domaine}/authorize_interaction?uri=${encodeURIComponent(tootUrl)}`, '_blank', 'noopener,noreferrer')
|
||||
setOuvert(false)
|
||||
setAutreInstance('')
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{maxWidth: 700, margin: '1em auto 0', textAlign: 'center'}}>
|
||||
<Typography variant='body2' sx={{mb: 1}}>
|
||||
Rejoignez la discussion sur{' '}
|
||||
<Link href={tootUrl} target='_blank' rel='noopener noreferrer'>Mastodon</Link>
|
||||
Rejoignez la discussion sur le Fediverse via{' '}
|
||||
<Link
|
||||
href={tootUrl}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
underline='hover'
|
||||
sx={{
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: 0.5,
|
||||
px: 1,
|
||||
py: 0.25,
|
||||
borderRadius: 1,
|
||||
bgcolor: 'action.hover',
|
||||
color: 'primary.main',
|
||||
fontWeight: 500,
|
||||
textDecoration: 'none',
|
||||
'&:hover': {
|
||||
bgcolor: 'action.selected'
|
||||
}
|
||||
}}
|
||||
>
|
||||
BOKANTE (Mastodon)
|
||||
</Link>
|
||||
</Typography>
|
||||
<Button variant='outlined' size='small' onClick={() => setOuvert(true)}>
|
||||
Répondre via Mastodon
|
||||
<Button
|
||||
variant='outlined'
|
||||
size='small'
|
||||
startIcon={<Mastodon size={16} color='#6364FF' title='' />}
|
||||
onClick={() => setOuvert(true)}
|
||||
>
|
||||
Répondre sur Mastodon
|
||||
</Button>
|
||||
<Dialog open={ouvert} onClose={() => setOuvert(false)}>
|
||||
<DialogTitle>Répondre depuis votre compte Mastodon</DialogTitle>
|
||||
<DialogTitle>Répondre depuis Mastodon</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant='body2' sx={{mb: 2}}>
|
||||
Indiquez votre identifiant (@vous@votre-instance) ou juste le nom de votre
|
||||
instance, vous serez redirigé·e vers votre compte pour répondre.
|
||||
Choisissez l’instance Mastodon sur laquelle vous avez un compte.
|
||||
BOKANTE est l’instance de OKI : vous pouvez aussi utiliser
|
||||
n’importe quelle autre instance du Fediverse.
|
||||
</Typography>
|
||||
<TextField
|
||||
autoFocus
|
||||
fullWidth
|
||||
label='@vous@votre-instance'
|
||||
value={saisie}
|
||||
onChange={event => setSaisie(event.target.value)}
|
||||
onKeyDown={event => {
|
||||
if (event.key === 'Enter') {
|
||||
repondre()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<FormControl fullWidth sx={{mb: 2}}>
|
||||
<InputLabel id='instance-mastodon-label'>Instance Mastodon</InputLabel>
|
||||
<Select
|
||||
labelId='instance-mastodon-label'
|
||||
id='instance-mastodon'
|
||||
value={instance}
|
||||
label='Instance Mastodon'
|
||||
onChange={event => setInstance(event.target.value)}
|
||||
>
|
||||
{INSTANCES_SUGGEREES.map(({domain, label}) => (
|
||||
<MenuItem key={domain} value={domain}>
|
||||
{label}
|
||||
</MenuItem>
|
||||
))}
|
||||
<MenuItem value={AUTRE_INSTANCE}>Autre instance…</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
{instance === AUTRE_INSTANCE && (
|
||||
<TextField
|
||||
autoFocus
|
||||
fullWidth
|
||||
label='@vous@votre-instance'
|
||||
helperText='Indiquez votre identifiant (@vous@votre-instance) ou juste le nom de votre instance, vous serez redirigé·e vers votre compte pour répondre.'
|
||||
value={autreInstance}
|
||||
onChange={event => setAutreInstance(event.target.value)}
|
||||
onKeyDown={event => {
|
||||
if (event.key === 'Enter') {
|
||||
repondre()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setOuvert(false)}>Annuler</Button>
|
||||
|
||||
Reference in New Issue
Block a user