mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-20 15:31:30 +00:00
Add prev and next buttons to carousel
This commit is contained in:
parent
1902d4755c
commit
db4ff94084
@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.conversation.v2
|
|||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@ -9,25 +10,30 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
import androidx.compose.foundation.layout.FlowRow
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.aspectRatio
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.PagerState
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.Card
|
|
||||||
import androidx.compose.material.Divider
|
import androidx.compose.material.Divider
|
||||||
|
import androidx.compose.material.Icon
|
||||||
|
import androidx.compose.material.IconButton
|
||||||
import androidx.compose.material.LocalTextStyle
|
import androidx.compose.material.LocalTextStyle
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.ComposeView
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@ -40,6 +46,7 @@ import androidx.lifecycle.ViewModel
|
|||||||
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
|
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
|
||||||
import com.bumptech.glide.integration.compose.GlideImage
|
import com.bumptech.glide.integration.compose.GlideImage
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||||
import org.session.libsession.utilities.Util
|
import org.session.libsession.utilities.Util
|
||||||
@ -76,7 +83,6 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var storage: Storage
|
lateinit var storage: Storage
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Extras
|
// Extras
|
||||||
const val MESSAGE_TIMESTAMP = "message_timestamp"
|
const val MESSAGE_TIMESTAMP = "message_timestamp"
|
||||||
@ -103,11 +109,14 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
val duration = slide.takeIf { it.hasAudio() }
|
val duration = slide.takeIf { it.hasAudio() }
|
||||||
?.let { it.asAttachment() as? DatabaseAttachment }
|
?.let { it.asAttachment() as? DatabaseAttachment }
|
||||||
?.let { attachment ->
|
?.let { attachment ->
|
||||||
attachmentDb.getAttachmentAudioExtras(attachment.attachmentId)?.let { audioExtras ->
|
attachmentDb.getAttachmentAudioExtras(attachment.attachmentId)
|
||||||
|
?.let { audioExtras ->
|
||||||
audioExtras.durationMs.takeIf { it > 0 }?.let {
|
audioExtras.durationMs.takeIf { it > 0 }?.let {
|
||||||
String.format("%01d:%02d",
|
String.format(
|
||||||
|
"%01d:%02d",
|
||||||
TimeUnit.MILLISECONDS.toMinutes(it),
|
TimeUnit.MILLISECONDS.toMinutes(it),
|
||||||
TimeUnit.MILLISECONDS.toSeconds(it) % 60)
|
TimeUnit.MILLISECONDS.toSeconds(it) % 60
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,16 +126,28 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
fileName.orNull()?.let { TitledText("File Id:", it) },
|
fileName.orNull()?.let { TitledText("File Id:", it) },
|
||||||
TitledText("File Type:", asAttachment().contentType),
|
TitledText("File Type:", asAttachment().contentType),
|
||||||
TitledText("File Size:", Util.getPrettyFileSize(fileSize)),
|
TitledText("File Size:", Util.getPrettyFileSize(fileSize)),
|
||||||
if (slide.hasImage()) { TitledText("Resolution:", slide.asAttachment().run { "${width}x$height" } ) } else null,
|
if (slide.hasImage()) {
|
||||||
|
TitledText(
|
||||||
|
"Resolution:",
|
||||||
|
slide.asAttachment().run { "${width}x$height" })
|
||||||
|
} else null,
|
||||||
duration?.let { TitledText("Duration:", it) },
|
duration?.let { TitledText("Duration:", it) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Attachment(slide, details)
|
Attachment(slide, details)
|
||||||
},
|
},
|
||||||
sent = dateSent.let(::Date).toString().let { TitledText("Sent:", it) },
|
sent = dateSent.let(::Date).toString().let { TitledText("Sent:", it) },
|
||||||
received = dateReceived.let(::Date).toString().let { TitledText("Received:", it) },
|
received = dateReceived.let(::Date).toString()
|
||||||
|
.let { TitledText("Received:", it) },
|
||||||
error = error?.let { TitledText("Error:", it) },
|
error = error?.let { TitledText("Error:", it) },
|
||||||
senderInfo = individualRecipient.run { name?.let { TitledText(it, address.serialize()) } },
|
senderInfo = individualRecipient.run {
|
||||||
|
name?.let {
|
||||||
|
TitledText(
|
||||||
|
it,
|
||||||
|
address.serialize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
sender = individualRecipient
|
sender = individualRecipient
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -141,12 +162,14 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
|
|
||||||
timestamp = intent.getLongExtra(MESSAGE_TIMESTAMP, -1L)
|
timestamp = intent.getLongExtra(MESSAGE_TIMESTAMP, -1L)
|
||||||
|
|
||||||
messageRecord = DatabaseComponent.get(this).mmsSmsDatabase().getMessageForTimestamp(timestamp) ?: run {
|
messageRecord =
|
||||||
|
DatabaseComponent.get(this).mmsSmsDatabase().getMessageForTimestamp(timestamp) ?: run {
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val error = DatabaseComponent.get(this).lokiMessageDatabase().getErrorMessage(messageRecord!!.getId())
|
val error = DatabaseComponent.get(this).lokiMessageDatabase()
|
||||||
|
.getErrorMessage(messageRecord!!.getId())
|
||||||
|
|
||||||
viewModel.setMessageRecord(messageRecord, error)
|
viewModel.setMessageRecord(messageRecord, error)
|
||||||
|
|
||||||
@ -226,16 +249,29 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||||
sent?.let { titledText(it) }
|
sent?.let { titledText(it) }
|
||||||
received?.let { titledText(it) }
|
received?.let { titledText(it) }
|
||||||
error?.let { titledText(it, valueStyle = LocalTextStyle.current.copy(color = colorDestructive)) }
|
error?.let {
|
||||||
|
titledText(
|
||||||
|
it,
|
||||||
|
valueStyle = LocalTextStyle.current.copy(color = colorDestructive)
|
||||||
|
)
|
||||||
|
}
|
||||||
senderInfo?.let {
|
senderInfo?.let {
|
||||||
titledView("From:") {
|
titledView("From:") {
|
||||||
Row {
|
Row {
|
||||||
sender?.let {
|
sender?.let {
|
||||||
Box(modifier = Modifier
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
.width(60.dp)
|
.width(60.dp)
|
||||||
.align(Alignment.CenterVertically)) {
|
.align(Alignment.CenterVertically)
|
||||||
|
) {
|
||||||
AndroidView(
|
AndroidView(
|
||||||
factory = { ProfilePictureView(it).apply { update(sender) } },
|
factory = {
|
||||||
|
ProfilePictureView(it).apply {
|
||||||
|
update(
|
||||||
|
sender
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(46.dp)
|
.width(46.dp)
|
||||||
.height(46.dp)
|
.height(46.dp)
|
||||||
@ -243,7 +279,10 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column {
|
Column {
|
||||||
titledText(it, valueStyle = LocalTextStyle.current.copy(fontFamily = FontFamily.Monospace))
|
titledText(
|
||||||
|
it,
|
||||||
|
valueStyle = LocalTextStyle.current.copy(fontFamily = FontFamily.Monospace)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,13 +291,26 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
}
|
}
|
||||||
Cell {
|
Cell {
|
||||||
Column {
|
Column {
|
||||||
ItemButton("Reply", R.drawable.ic_message_details__reply, onClick = onReply)
|
ItemButton(
|
||||||
|
"Reply",
|
||||||
|
R.drawable.ic_message_details__reply,
|
||||||
|
onClick = onReply
|
||||||
|
)
|
||||||
Divider()
|
Divider()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
ItemButton("Resend", R.drawable.ic_message_details__refresh, onClick = onResend)
|
ItemButton(
|
||||||
|
"Resend",
|
||||||
|
R.drawable.ic_message_details__refresh,
|
||||||
|
onClick = onResend
|
||||||
|
)
|
||||||
Divider()
|
Divider()
|
||||||
}
|
}
|
||||||
ItemButton("Delete", R.drawable.ic_message_details__trash, colors = destructiveButtonColors(), onClick = onDelete)
|
ItemButton(
|
||||||
|
"Delete",
|
||||||
|
R.drawable.ic_message_details__trash,
|
||||||
|
colors = destructiveButtonColors(),
|
||||||
|
onClick = onDelete
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,18 +329,18 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
@OptIn(
|
@OptIn(
|
||||||
ExperimentalFoundationApi::class,
|
ExperimentalFoundationApi::class,
|
||||||
ExperimentalGlideComposeApi::class,
|
ExperimentalGlideComposeApi::class,
|
||||||
ExperimentalLayoutApi::class,
|
|
||||||
)
|
)
|
||||||
@Composable
|
@Composable
|
||||||
fun ImageAttachments(attachments: List<Attachment>) {
|
fun ImageAttachments(attachments: List<Attachment>) {
|
||||||
val imageAttachments = attachments.filter { it.slide.hasImage() }
|
val imageAttachments = attachments.filter { it.slide.hasImage() }
|
||||||
val pagerState = rememberPagerState {
|
val pagerState = rememberPagerState { imageAttachments.size }
|
||||||
imageAttachments.size
|
|
||||||
}
|
|
||||||
|
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||||
|
Row {
|
||||||
|
if (imageAttachments.size >= 2) PrevButton(pagerState, modifier = Modifier.align(Alignment.CenterVertically))
|
||||||
|
else Spacer(modifier = Modifier.width(32.dp))
|
||||||
|
Box(modifier = Modifier.weight(1f)) {
|
||||||
CellNoMargin {
|
CellNoMargin {
|
||||||
Box {
|
|
||||||
HorizontalPager(state = pagerState) { i ->
|
HorizontalPager(state = pagerState) { i ->
|
||||||
imageAttachments[i].slide.apply {
|
imageAttachments[i].slide.apply {
|
||||||
GlideImage(
|
GlideImage(
|
||||||
@ -299,6 +351,7 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (imageAttachments.size >= 2) {
|
if (imageAttachments.size >= 2) {
|
||||||
SessionHorizontalPagerIndicator(
|
SessionHorizontalPagerIndicator(
|
||||||
modifier = Modifier.align(Alignment.BottomCenter),
|
modifier = Modifier.align(Alignment.BottomCenter),
|
||||||
@ -307,7 +360,54 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (imageAttachments.size >= 2) NextButton(pagerState, modifier = Modifier.align(Alignment.CenterVertically))
|
||||||
|
else Spacer(modifier = Modifier.width(32.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileDetails(attachments, pagerState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun PrevButton(pagerState: PagerState, modifier: Modifier = Modifier) {
|
||||||
|
CarouselButton(pagerState, modifier = modifier, enabled = pagerState.canScrollBackward, id = R.drawable.ic_prev, delta = -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun NextButton(pagerState: PagerState, modifier: Modifier = Modifier) {
|
||||||
|
CarouselButton(pagerState, modifier = modifier, enabled = pagerState.canScrollForward, id = R.drawable.ic_next, delta = 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun CarouselButton(
|
||||||
|
pagerState: PagerState,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
enabled: Boolean,
|
||||||
|
@DrawableRes id: Int,
|
||||||
|
delta: Int
|
||||||
|
) {
|
||||||
|
val animationScope = rememberCoroutineScope()
|
||||||
|
pagerState.apply {
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(40.dp)
|
||||||
|
.then(modifier),
|
||||||
|
enabled = enabled,
|
||||||
|
onClick = { animationScope.launch { animateScrollToPage(currentPage + delta) } }) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = id),
|
||||||
|
contentDescription = "",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class)
|
||||||
|
@Composable
|
||||||
|
fun FileDetails(attachments: List<Attachment>, pagerState: PagerState) {
|
||||||
attachments[pagerState.currentPage].fileDetails.takeIf { it.isNotEmpty() }?.let {
|
attachments[pagerState.currentPage].fileDetails.takeIf { it.isNotEmpty() }?.let {
|
||||||
CellWithPaddingAndMargin {
|
CellWithPaddingAndMargin {
|
||||||
FlowRow(
|
FlowRow(
|
||||||
@ -319,15 +419,22 @@ class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Divider() {
|
fun Divider() {
|
||||||
Divider(modifier = Modifier.padding(horizontal = 16.dp), thickness = 1.dp, color = LocalExtraColors.current.divider)
|
Divider(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
thickness = 1.dp,
|
||||||
|
color = LocalExtraColors.current.divider
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun titledText(titledText: TitledText, modifier: Modifier = Modifier, valueStyle: TextStyle = LocalTextStyle.current) {
|
fun titledText(
|
||||||
|
titledText: TitledText,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
valueStyle: TextStyle = LocalTextStyle.current
|
||||||
|
) {
|
||||||
Column(modifier = modifier, verticalArrangement = Arrangement.spacedBy(4.dp)) {
|
Column(modifier = modifier, verticalArrangement = Arrangement.spacedBy(4.dp)) {
|
||||||
Title(titledText.title)
|
Title(titledText.title)
|
||||||
Text(titledText.value, style = valueStyle)
|
Text(titledText.value, style = valueStyle)
|
||||||
|
@ -57,11 +57,11 @@ fun ItemButton(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Cell(content: @Composable () -> Unit) {
|
fun Cell(content: @Composable () -> Unit) {
|
||||||
CellWithPaddingAndMargin(0.dp) { content() }
|
CellWithPaddingAndMargin(padding = 0.dp) { content() }
|
||||||
}
|
}
|
||||||
@Composable
|
@Composable
|
||||||
fun CellNoMargin(content: @Composable () -> Unit) {
|
fun CellNoMargin(content: @Composable () -> Unit) {
|
||||||
CellWithPaddingAndMargin(0.dp, 0.dp) { content() }
|
CellWithPaddingAndMargin(padding = 0.dp, margin = 0.dp) { content() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
8
app/src/main/res/drawable/ic_next.xml
Normal file
8
app/src/main/res/drawable/ic_next.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<vector android:autoMirrored="true" android:height="17dp"
|
||||||
|
android:viewportHeight="17" android:viewportWidth="13"
|
||||||
|
android:width="13dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<group>
|
||||||
|
<clip-path android:pathData="M13,16.004l-13,-0l-0,-16l13,-0z"/>
|
||||||
|
<path android:fillColor="#ffffff" android:pathData="M0.646,1.736L10.112,7.933L0.444,14.268C0.323,14.343 0.222,14.438 0.144,14.547C0.067,14.657 0.015,14.779 -0.007,14.906C-0.029,15.033 -0.022,15.163 0.014,15.287C0.05,15.412 0.115,15.529 0.203,15.632C0.292,15.734 0.404,15.82 0.532,15.885C0.66,15.95 0.801,15.991 0.948,16.008C1.095,16.024 1.244,16.015 1.386,15.981C1.529,15.946 1.662,15.887 1.778,15.808L12.353,8.88C12.466,8.805 12.562,8.711 12.635,8.605C12.687,8.563 12.734,8.518 12.778,8.47C12.955,8.266 13.031,8.009 12.99,7.756C12.949,7.503 12.794,7.274 12.559,7.12L1.984,0.193C1.868,0.117 1.736,0.061 1.595,0.029C1.454,-0.003 1.307,-0.011 1.163,0.006C1.018,0.024 0.88,0.066 0.754,0.13C0.628,0.194 0.519,0.279 0.431,0.381C0.343,0.482 0.278,0.597 0.241,0.72C0.204,0.843 0.195,0.971 0.215,1.097C0.235,1.223 0.284,1.344 0.358,1.454C0.432,1.563 0.53,1.659 0.646,1.736Z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
8
app/src/main/res/drawable/ic_prev.xml
Normal file
8
app/src/main/res/drawable/ic_prev.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<vector android:autoMirrored="true" android:height="17dp"
|
||||||
|
android:viewportHeight="17" android:viewportWidth="12"
|
||||||
|
android:width="12dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<group>
|
||||||
|
<clip-path android:pathData="M0,0.004h12v16h-12z"/>
|
||||||
|
<path android:fillColor="#ffffff" android:pathData="M11.403,14.272L2.666,8.075L11.59,1.74C11.701,1.665 11.795,1.57 11.867,1.46C11.938,1.351 11.986,1.229 12.006,1.102C12.027,0.975 12.02,0.845 11.987,0.721C11.954,0.596 11.894,0.479 11.812,0.376C11.73,0.274 11.627,0.187 11.509,0.123C11.391,0.058 11.26,0.016 11.125,0C10.989,-0.016 10.852,-0.007 10.72,0.027C10.589,0.062 10.466,0.12 10.359,0.2L0.597,7.127C0.493,7.203 0.405,7.297 0.337,7.403C0.289,7.444 0.245,7.49 0.205,7.538C0.042,7.742 -0.029,7.999 0.009,8.252C0.047,8.505 0.19,8.734 0.407,8.887L10.168,15.815C10.275,15.891 10.398,15.947 10.528,15.979C10.658,16.011 10.793,16.019 10.927,16.001C11.06,15.984 11.188,15.942 11.304,15.878C11.42,15.814 11.521,15.728 11.602,15.627C11.684,15.526 11.743,15.411 11.777,15.288C11.811,15.165 11.82,15.037 11.801,14.911C11.783,14.785 11.738,14.664 11.67,14.554C11.601,14.445 11.511,14.349 11.403,14.272Z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
Loading…
x
Reference in New Issue
Block a user