Style sidebar sharing options

This commit is contained in:
viktorstrate
2021-06-04 16:12:43 +02:00
parent 309e338b4d
commit fc009ead1c
6 changed files with 241 additions and 221 deletions

View File

@@ -1,25 +1,11 @@
import React, { useEffect, useState } from 'react'
import React, { useEffect } from 'react'
import { useMutation, useQuery, gql, useLazyQuery } from '@apollo/client'
import {
Table,
Button,
Dropdown,
Checkbox,
Input,
Icon,
} from 'semantic-ui-react'
import copy from 'copy-to-clipboard'
import styled from 'styled-components'
import { useTranslation } from 'react-i18next'
import { sidbarGetAlbumShares_album_shares } from './__generated__/sidbarGetAlbumShares'
import {
sidebareDeleteShare,
sidebareDeleteShareVariables,
} from './__generated__/sidebareDeleteShare'
import {
sidebarProtectShare,
sidebarProtectShareVariables,
} from './__generated__/sidebarProtectShare'
import { sidbarGetPhotoShares_media_shares } from './__generated__/sidbarGetPhotoShares'
import {
sidebarPhotoAddShare,
@@ -40,6 +26,12 @@ import {
import { authToken } from '../../helpers/authentication'
import { SidebarSection, SidebarSectionTitle } from './SidebarComponents'
import { ReactComponent as LinkIcon } from './icons/shareLinkIcon.svg'
import { ReactComponent as CopyIcon } from './icons/shareCopyIcon.svg'
import { ReactComponent as DeleteIcon } from './icons/shareDeleteIcon.svg'
import { ReactComponent as MoreIcon } from './icons/shareMoreIcon.svg'
import { ReactComponent as AddIcon } from './icons/shareAddIcon.svg'
const SHARE_PHOTO_QUERY = gql`
query sidebarGetPhotoShares($id: ID!) {
media(id: $id) {
@@ -82,14 +74,14 @@ const ADD_ALBUM_SHARE_MUTATION = gql`
}
`
const PROTECT_SHARE_MUTATION = gql`
mutation sidebarProtectShare($token: String!, $password: String) {
protectShareToken(token: $token, password: $password) {
token
hasPassword
}
}
`
// const PROTECT_SHARE_MUTATION = gql`
// mutation sidebarProtectShare($token: String!, $password: String) {
// protectShareToken(token: $token, password: $password) {
// token
// hasPassword
// }
// }
// `
const DELETE_SHARE_MUTATION = gql`
mutation sidebareDeleteShare($token: String!) {
@@ -99,162 +91,150 @@ const DELETE_SHARE_MUTATION = gql`
}
`
type ShareItemMoreDropdownProps = {
id: string
isPhoto: boolean
share: sidbarGetAlbumShares_album_shares
}
// type ShareItemMoreDropdownProps = {
// id: string
// query: DocumentNode
// share: sidbarGetAlbumShares_album_shares
// }
const ShareItemMoreDropdown = ({
id,
share,
isPhoto,
}: ShareItemMoreDropdownProps) => {
const { t } = useTranslation()
const query = isPhoto ? SHARE_PHOTO_QUERY : SHARE_ALBUM_QUERY
// const ShareItemMoreDropdown = ({
// id,
// share,
// query,
// }: ShareItemMoreDropdownProps) => {
// const { t } = useTranslation()
const [deleteShare, { loading: deleteShareLoading }] = useMutation<
sidebareDeleteShare,
sidebareDeleteShareVariables
>(DELETE_SHARE_MUTATION, {
refetchQueries: [{ query: query, variables: { id } }],
})
// const [addingPassword, setAddingPassword] = useState(false)
// const showPasswordInput = addingPassword || share.hasPassword
const [addingPassword, setAddingPassword] = useState(false)
const showPasswordInput = addingPassword || share.hasPassword
// const [passwordInputValue, setPasswordInputValue] = useState(
// share.hasPassword ? '**********' : ''
// )
// const [passwordHidden, setPasswordHidden] = useState(share.hasPassword)
const [passwordInputValue, setPasswordInputValue] = useState(
share.hasPassword ? '**********' : ''
)
const [passwordHidden, setPasswordHidden] = useState(share.hasPassword)
// const hidePassword = (hide: boolean) => {
// setPasswordHidden(hide)
// if (hide) {
// setPasswordInputValue('**********')
// }
// }
const hidePassword = (hide: boolean) => {
setPasswordHidden(hide)
if (hide) {
setPasswordInputValue('**********')
}
}
// const [setPassword, { loading: setPasswordLoading }] = useMutation<
// sidebarProtectShare,
// sidebarProtectShareVariables
// >(PROTECT_SHARE_MUTATION, {
// refetchQueries: [{ query: query, variables: { id } }],
// onCompleted: data => {
// hidePassword(data.protectShareToken.hasPassword)
// },
// // refetchQueries: [{ query: query, variables: { id } }],
// variables: {
// token: share.token,
// },
// })
const [setPassword, { loading: setPasswordLoading }] = useMutation<
sidebarProtectShare,
sidebarProtectShareVariables
>(PROTECT_SHARE_MUTATION, {
refetchQueries: [{ query: query, variables: { id } }],
onCompleted: data => {
hidePassword(data.protectShareToken.hasPassword)
},
// refetchQueries: [{ query: query, variables: { id } }],
variables: {
token: share.token,
},
})
// let addPasswordInput = null
// if (showPasswordInput) {
// const setPasswordEvent = (event: React.KeyboardEvent<HTMLInputElement>) => {
// if (!passwordHidden && passwordInputValue != '' && event.key == 'Enter') {
// event.preventDefault()
// setPassword({
// variables: {
// token: share.token,
// password: (event.target as HTMLInputElement).value,
// },
// })
// }
// }
let addPasswordInput = null
if (showPasswordInput) {
const setPasswordEvent = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (!passwordHidden && passwordInputValue != '' && event.key == 'Enter') {
event.preventDefault()
setPassword({
variables: {
token: share.token,
password: (event.target as HTMLInputElement).value,
},
})
}
}
// addPasswordInput = (
// <Input
// disabled={setPasswordLoading}
// loading={setPasswordLoading}
// style={{ marginTop: 8, marginRight: 0, display: 'block' }}
// onClick={(e: MouseEvent) => e.stopPropagation()}
// value={passwordInputValue}
// type={passwordHidden ? 'password' : 'text'}
// onKeyUp={setPasswordEvent}
// onChange={event => {
// hidePassword(false)
// setPasswordInputValue(event.target.value)
// }}
// placeholder="Password"
// icon={
// <Icon
// name={passwordHidden ? 'lock' : 'arrow right'}
// link={!passwordHidden}
// onClick={setPasswordEvent}
// />
// }
// />
// )
// }
addPasswordInput = (
<Input
disabled={setPasswordLoading}
loading={setPasswordLoading}
style={{ marginTop: 8, marginRight: 0, display: 'block' }}
onClick={(e: MouseEvent) => e.stopPropagation()}
value={passwordInputValue}
type={passwordHidden ? 'password' : 'text'}
onKeyUp={setPasswordEvent}
onChange={event => {
hidePassword(false)
setPasswordInputValue(event.target.value)
}}
placeholder="Password"
icon={
<Icon
name={passwordHidden ? 'lock' : 'arrow right'}
link={!passwordHidden}
onClick={setPasswordEvent}
/>
}
/>
)
}
// const checkboxClick = () => {
// const enable = !showPasswordInput
// setAddingPassword(enable)
// if (!enable) {
// setPassword({
// variables: {
// token: share.token,
// password: null,
// },
// })
// setPasswordInputValue('')
// }
// }
const checkboxClick = () => {
const enable = !showPasswordInput
setAddingPassword(enable)
if (!enable) {
setPassword({
variables: {
token: share.token,
password: null,
},
})
setPasswordInputValue('')
}
}
// // const [dropdownOpen, setDropdownOpen] = useState(false)
// const [dropdownOpen, setDropdownOpen] = useState(false)
return (
<Dropdown
// onBlur={event => {
// console.log('Blur')
// }}
// onClick={() => setDropdownOpen(state => !state)}
// onClose={() => setDropdownOpen(false)}
// open={dropdownOpen}
button
text={t('general.action.more', 'More')}
closeOnChange={false}
closeOnBlur={false}
>
<Dropdown.Menu>
<Dropdown.Item
onKeyDown={(e: KeyboardEvent) => e.stopPropagation()}
onClick={e => {
e.stopPropagation()
checkboxClick()
}}
>
<Checkbox
label={t('login_page.field.password', 'Password')}
onClick={e => e.stopPropagation()}
checked={showPasswordInput}
onChange={() => {
checkboxClick()
}}
/>
{addPasswordInput}
</Dropdown.Item>
<Dropdown.Item
text={t('general.action.delete', 'Delete')}
icon="delete"
disabled={deleteShareLoading}
onClick={() => {
deleteShare({
variables: {
token: share.token,
},
})
}}
/>
</Dropdown.Menu>
</Dropdown>
)
}
const ShareButtonGroup = styled(Button.Group)`
flex-wrap: wrap;
`
// return (
// <Dropdown
// // onBlur={event => {
// // console.log('Blur')
// // }}
// // onClick={() => setDropdownOpen(state => !state)}
// // onClose={() => setDropdownOpen(false)}
// // open={dropdownOpen}
// button
// text={t('general.action.more', 'More')}
// closeOnChange={false}
// closeOnBlur={false}
// >
// <Dropdown.Menu>
// <Dropdown.Item
// onKeyDown={(e: KeyboardEvent) => e.stopPropagation()}
// onClick={e => {
// e.stopPropagation()
// checkboxClick()
// }}
// >
// <Checkbox
// label={t('login_page.field.password', 'Password')}
// onClick={e => e.stopPropagation()}
// checked={showPasswordInput}
// onChange={() => {
// checkboxClick()
// }}
// />
// {addPasswordInput}
// </Dropdown.Item>
// {/* <Dropdown.Item
// text={t('general.action.delete', 'Delete')}
// icon="delete"
// disabled={deleteShareLoading}
// onClick={() => {
// deleteShare({
// variables: {
// token: share.token,
// },
// })
// }}
// /> */}
// </Dropdown.Menu>
// </Dropdown>
// )
// }
type SidebarShareAlbumProps = {
id: string
@@ -369,37 +349,67 @@ const SidebarShare = ({
}: SidebarShareProps) => {
const { t } = useTranslation()
const query = isPhoto ? SHARE_PHOTO_QUERY : SHARE_ALBUM_QUERY
const [deleteShare] = useMutation<
sidebareDeleteShare,
sidebareDeleteShareVariables
>(DELETE_SHARE_MUTATION, {
refetchQueries: [{ query: query, variables: { id } }],
})
if (shares === undefined) {
return null
}
const optionsRows = shares.map(share => (
<Table.Row key={share.token}>
<Table.Cell>
<b>{t('sidebar.sharing.public_link', 'Public Link')}</b> {share.token}
</Table.Cell>
<Table.Cell>
<ShareButtonGroup>
<Button
icon="chain"
content={t('sidebar.sharing.copy_link', 'Copy Link')}
onClick={() => {
copy(`${location.origin}/share/${share.token}`)
}}
/>
<ShareItemMoreDropdown share={share} id={id} isPhoto={isPhoto} />
</ShareButtonGroup>
</Table.Cell>
</Table.Row>
<tr key={share.token} className="border-gray-100 border-b border-t">
<td className="pl-4 w-full py-2">
<span className="text-[#585858] mr-2">
<LinkIcon className="inline-block mr-2" />
<span className="text-xs uppercase font-bold">
{t('sidebar.sharing.public_link', 'Public Link') + ' '}
</span>
</span>
<span className="text-sm">{share.token}</span>
</td>
<td className="pr-4 py-2 whitespace-nowrap text-[#5C6A7F] flex">
<button
className="align-middle p-1 ml-1"
title={t('sidebar.sharing.copy_link', 'Copy Link')}
onClick={() => {
copy(`${location.origin}/share/${share.token}`)
}}
>
<CopyIcon />
</button>
<button
onClick={() => {
deleteShare({ variables: { token: share.token } })
}}
className="align-middle p-1 ml-1"
title={t('sidebar.sharing.delete', 'Delete')}
>
<DeleteIcon />
</button>
<button
className="align-middle p-1 ml-1"
title={t('sidebar.sharing.more', 'More')}
>
<MoreIcon />
</button>
{/* <ShareItemMoreDropdown share={share} id={id} isPhoto={isPhoto} /> */}
</td>
</tr>
))
if (optionsRows.length == 0) {
optionsRows.push(
<Table.Row key="no-shares">
<Table.Cell colSpan="2">
<tr key="no-shares">
<td colSpan={2}>
{t('sidebar.sharing.no_shares_found', 'No shares found')}
</Table.Cell>
</Table.Row>
</td>
</tr>
)
}
@@ -409,37 +419,27 @@ const SidebarShare = ({
{t('sidebar.sharing.title', 'Sharing options')}
</SidebarSectionTitle>
<div>
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell colSpan="2">
{t('sidebar.sharing.table_header', 'Public shares')}
</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>{optionsRows}</Table.Body>
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan="2">
<Button
content={t('sidebar.sharing.add_share', 'Add shares')}
icon="add"
floated="right"
positive
loading={loading}
disabled={loading}
onClick={() => {
shareItem({
variables: {
id,
},
})
}}
/>
</Table.HeaderCell>
</Table.Row>
</Table.Footer>
</Table>
<table className="border-collapse">
{optionsRows}
<tr className="text-left border-gray-100 border-b border-t">
<td colSpan={2} className="pl-4 py-2">
<button
className="text-[#4ABF3C] font-bold uppercase text-xs"
disabled={loading}
onClick={() => {
shareItem({
variables: {
id,
},
})
}}
>
<AddIcon className="inline-block mr-2" />
<span>{t('sidebar.sharing.add_share', 'Add shares')}</span>
</button>
</td>
</tr>
</table>
</div>
</SidebarSection>
)

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M5.66666667,1 L5.66666667,10.3333333 M1,5.66666667 L10.3333333,5.66666667" fill="none" stroke="currentColor" stroke-width="1.5"></path>
</svg>

After

Width:  |  Height:  |  Size: 337 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path stroke="none" d="M12.0909091,4.45454545 C13.1452709,4.45454545 14,5.30927457 14,6.36363636 L14,6.36363636 L14,12.0909091 C14,13.1452709 13.1452709,14 12.0909091,14 L12.0909091,14 L6.36363636,14 C5.30927457,14 4.45454545,13.1452709 4.45454545,12.0909091 L4.45454545,12.0909091 L4.45454545,6.36363636 C4.45454545,5.30927457 5.30927457,4.45454545 6.36363636,4.45454545 L6.36363636,4.45454545 Z M12.0909091,5.72727273 L6.36363636,5.72727273 C6.01218243,5.72727273 5.72727273,6.01218243 5.72727273,6.36363636 L5.72727273,6.36363636 L5.72727273,12.0909091 C5.72727273,12.442363 6.01218243,12.7272727 6.36363636,12.7272727 L6.36363636,12.7272727 L12.0909091,12.7272727 C12.442363,12.7272727 12.7272727,12.442363 12.7272727,12.0909091 L12.7272727,12.0909091 L12.7272727,6.36363636 C12.7272727,6.01218243 12.442363,5.72727273 12.0909091,5.72727273 L12.0909091,5.72727273 Z M7.63636364,0 C8.65306965,0 9.48414783,0.79476725 9.54221374,1.79691732 L9.54545455,1.90909091 L9.54545455,2.54545455 C9.54545455,2.89690848 9.26054484,3.18181818 8.90909091,3.18181818 C8.58274083,3.18181818 8.31376817,2.93615624 8.27700856,2.61966799 L8.27272727,2.54545455 L8.27272727,1.90909091 C8.27272727,1.58274083 8.02706533,1.31376817 7.71057708,1.27700856 L7.63636364,1.27272727 L1.90909091,1.27272727 C1.58274083,1.27272727 1.31376817,1.51838921 1.27700856,1.83487747 L1.27272727,1.90909091 L1.27272727,7.63636364 C1.27272727,7.96271372 1.51838921,8.23168637 1.83487747,8.26844599 L1.90909091,8.27272727 L2.54545455,8.27272727 C2.89690848,8.27272727 3.18181818,8.55763698 3.18181818,8.90909091 C3.18181818,9.23544099 2.93615624,9.50441365 2.61966799,9.54117326 L2.54545455,9.54545455 L1.90909091,9.54545455 C0.892384892,9.54545455 0.0613067131,8.7506873 0.0032408049,7.74853723 L0,7.63636364 L0,1.90909091 C0,0.892384892 0.79476725,0.0613067131 1.79691732,0.0032408049 L1.90909091,0 L7.63636364,0 Z" fill="currentColor" fill-rule="nonzero"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="13px" height="14px" viewBox="0 0 13 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path stroke="none" d="M7.63636364,0 C8.65306965,0 9.48414783,0.79476725 9.54221374,1.79691732 L9.54545455,1.90909091 L9.545,2.545 L12.0909091,2.54545455 C12.442363,2.54545455 12.7272727,2.83036425 12.7272727,3.18181818 C12.7272727,3.50816826 12.4816108,3.77714092 12.1651225,3.81390053 L12.0909091,3.81818182 L11.454,3.818 L11.4545455,12.0909091 C11.4545455,13.1076151 10.6597782,13.9386933 9.65762814,13.9967592 L9.54545455,14 L3.18181818,14 C2.16511217,14 1.33403399,13.2052327 1.27596808,12.2030827 L1.27272727,12.0909091 L1.272,3.818 L0.636363636,3.81818182 C0.284909705,3.81818182 2.27373675e-13,3.53327211 2.27373675e-13,3.18181818 C2.27373675e-13,2.8554681 0.245661939,2.58649544 0.562150193,2.54973583 L0.636363636,2.54545455 L3.181,2.545 L3.18181818,1.90909091 C3.18181818,0.892384892 3.97658543,0.0613067131 4.9787355,0.0032408049 L5.09090909,0 L7.63636364,0 Z M10.181,3.818 L2.545,3.818 L2.54545455,12.0909091 C2.54545455,12.4172592 2.79111648,12.6862318 3.10760474,12.7229914 L3.18181818,12.7272727 L9.54545455,12.7272727 C9.87180462,12.7272727 10.1407773,12.4816108 10.1775369,12.1651225 L10.1818182,12.0909091 L10.181,3.818 Z M5.09090909,5.72727273 C5.41725917,5.72727273 5.68623183,5.97293467 5.72299144,6.28942292 L5.72727273,6.36363636 L5.72727273,10.1818182 C5.72727273,10.5332721 5.44236302,10.8181818 5.09090909,10.8181818 C4.76455901,10.8181818 4.49558635,10.5725199 4.45882674,10.2560316 L4.45454545,10.1818182 L4.45454545,6.36363636 C4.45454545,6.01218243 4.73945516,5.72727273 5.09090909,5.72727273 Z M7.63636364,5.72727273 C7.96271372,5.72727273 8.23168637,5.97293467 8.26844599,6.28942292 L8.27272727,6.36363636 L8.27272727,10.1818182 C8.27272727,10.5332721 7.98781757,10.8181818 7.63636364,10.8181818 C7.31001356,10.8181818 7.0410409,10.5725199 7.00428128,10.2560316 L7,10.1818182 L7,6.36363636 C7,6.01218243 7.2849097,5.72727273 7.63636364,5.72727273 Z M7.63636364,1.27272727 L5.09090909,1.27272727 C4.76455901,1.27272727 4.49558635,1.51838921 4.45882674,1.83487747 L4.45454545,1.90909091 L4.454,2.545 L8.272,2.545 L8.27272727,1.90909091 C8.27272727,1.58274083 8.02706533,1.31376817 7.71057708,1.27700856 L7.63636364,1.27272727 Z" fill="currentColor" fill-rule="nonzero"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="12px" viewBox="0 0 12 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path stroke="none" stroke-width="1" fill="none" d="M5.01241676,3.99743718 L5.2123926,4.0051107 C6.08060614,4.06729045 6.87900923,4.50349496 7.40038252,5.20051071 C7.56578589,5.42163587 7.52061445,5.73497915 7.29948929,5.90038252 C7.07836413,6.06578589 6.76502085,6.02061445 6.59961748,5.79948929 C6.25203528,5.33481212 5.71976656,5.04400912 5.14095753,5.00255596 C4.62002941,4.96524811 4.10763194,5.1332244 3.71124008,5.46642286 L3.58355339,5.58355339 L2.0896441,7.0773559 C1.33169968,7.86211367 1.34253936,9.10952545 2.11400695,9.88099305 C2.84487099,10.6118571 4.00289823,10.6600523 4.78475751,10.0238225 L4.91144661,9.91144661 L5.76644661,9.05644661 C5.96170876,8.86118446 6.27829124,8.86118446 6.47355339,9.05644661 C6.64711974,9.23001296 6.66640489,9.49943736 6.53140884,9.6943055 L6.47355339,9.76355339 L5.6123559,10.6246441 C4.43521924,11.7615607 2.56410157,11.7453012 1.40690017,10.5880998 C0.295986831,9.47718649 0.236565536,7.70832791 1.24484904,6.52165836 L1.37644661,6.37644661 L2.87638252,4.87651071 C3.44442608,4.30826116 4.21444071,3.99361146 5.01241676,3.99743718 Z M10.5930998,1.41190017 C11.7040132,2.52281351 11.7634345,4.29167209 10.755151,5.47834164 L10.6235534,5.62355339 L9.12361748,7.12348929 C8.50823696,7.73909297 7.65582094,8.05706905 6.7876074,7.9948893 C5.91939386,7.93270955 5.12099077,7.49650504 4.59961748,6.79948929 C4.43421411,6.57836413 4.47938555,6.26502085 4.70051071,6.09961748 C4.92163587,5.93421411 5.23497915,5.97938555 5.40038252,6.20051071 C5.74796472,6.66518788 6.28023344,6.95599088 6.85904247,6.99744404 C7.37997059,7.03475189 7.89236806,6.8667756 8.28875992,6.53357714 L8.41644661,6.41644661 L9.9103559,4.9226441 C10.6683003,4.13788633 10.6574606,2.89047455 9.88599305,2.11900695 C9.15512901,1.38814291 7.99710177,1.3399477 7.21436478,1.97705267 L7.08752112,2.08958265 L6.22752112,2.94458265 C6.03169053,3.13927469 5.71510939,3.13835172 5.52041735,2.94252112 C5.34735776,2.76844949 5.32885818,2.49897001 5.46442178,2.30449627 L5.52247888,2.23541735 L6.3876441,1.3753559 C7.56478076,0.238439269 9.43589843,0.254698775 10.5930998,1.41190017 Z" fill="currentColor" fill-rule="nonzero"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="10px" height="2px" viewBox="0 0 10 2" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path stroke="none" stroke-width="1" fill="none" d="M0.646446609,0.646446609 C1.13807119,0.5 1.26307119,0.555964406 1.35355339,0.646446609 C1.44403559,0.736928813 1.5,0.861928813 1.5,1 C1.5,1.13807119 1.44403559,1.26307119 1.35355339,1.35355339 C1.26307119,1.44403559 1.13807119,1.5 1,1.5 C0.861928813,1.5 0.736928813,1.44403559 0.646446609,1.35355339 C0.555964406,1.26307119 0.5,1.13807119 0.5,1 C0.5,0.861928813 0.555964406,0.736928813 0.646446609,0.646446609 Z M4.64644661,0.646446609 C5.13807119,0.5 5.26307119,0.555964406 5.35355339,0.646446609 C5.44403559,0.736928813 5.5,0.861928813 5.5,1 C5.5,1.13807119 5.44403559,1.26307119 5.35355339,1.35355339 C5.26307119,1.44403559 5.13807119,1.5 5,1.5 C4.86192881,1.5 4.73692881,1.44403559 4.64644661,1.35355339 C4.55596441,1.26307119 4.5,1.13807119 4.5,1 C4.5,0.861928813 4.55596441,0.736928813 4.64644661,0.646446609 Z M8.64644661,0.646446609 C9.13807119,0.5 9.26307119,0.555964406 9.35355339,0.646446609 C9.44403559,0.736928813 9.5,0.861928813 9.5,1 C9.5,1.13807119 9.44403559,1.26307119 9.35355339,1.35355339 C9.26307119,1.44403559 9.13807119,1.5 9,1.5 C8.86192881,1.5 8.73692881,1.44403559 8.64644661,1.35355339 C8.55596441,1.26307119 8.5,1.13807119 8.5,1 C8.5,0.861928813 8.55596441,0.736928813 8.64644661,0.646446609 Z" stroke="currentColor"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB