redesign about page (#321)

This commit is contained in:
AmirHossein Abdolmotallebi 2024-12-27 04:01:54 +03:30 committed by GitHub
parent a4c0995760
commit c91cbb0dbb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 451 additions and 119 deletions

View File

@ -1,7 +1,6 @@
package com.abdownloadmanager.desktop.pages.about package com.abdownloadmanager.desktop.pages.about
import com.abdownloadmanager.desktop.AppComponent import com.abdownloadmanager.desktop.AppComponent
import com.abdownloadmanager.desktop.ui.Ui
import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow import com.abdownloadmanager.desktop.ui.customwindow.CustomWindow
import com.abdownloadmanager.desktop.ui.customwindow.WindowTitle import com.abdownloadmanager.desktop.ui.customwindow.WindowTitle
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -11,9 +10,10 @@ import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.WindowPosition import androidx.compose.ui.window.WindowPosition
import androidx.compose.ui.window.rememberWindowState import androidx.compose.ui.window.rememberWindowState
import com.abdownloadmanager.desktop.ui.customwindow.WindowIcon
import com.abdownloadmanager.desktop.ui.icon.MyIcons
import com.abdownloadmanager.desktop.ui.theme.LocalUiScale import com.abdownloadmanager.desktop.ui.theme.LocalUiScale
import com.abdownloadmanager.resources.Res import com.abdownloadmanager.resources.Res
import com.abdownloadmanager.resources.*
import ir.amirab.util.compose.resources.myStringResource import ir.amirab.util.compose.resources.myStringResource
import ir.amirab.util.desktop.screen.applyUiScale import ir.amirab.util.desktop.screen.applyUiScale
@ -43,16 +43,18 @@ fun AboutDialog(
CustomWindow( CustomWindow(
resizable = false, resizable = false,
onRequestToggleMaximize = null, onRequestToggleMaximize = null,
alwaysOnTop = false,
onRequestMinimize = null,
state = rememberWindowState( state = rememberWindowState(
position = WindowPosition.Aligned(Alignment.Center), position = WindowPosition.Aligned(Alignment.Center),
size = DpSize(400.dp, 350.dp) size = DpSize(600.dp, 310.dp)
.applyUiScale(LocalUiScale.current) .applyUiScale(LocalUiScale.current)
), ),
onCloseRequest = onClose onCloseRequest = onClose
) { ) {
WindowTitle(myStringResource(Res.string.about)) WindowTitle(myStringResource(Res.string.about))
WindowIcon(MyIcons.info)
AboutPage( AboutPage(
close = onClose,
onRequestShowOpenSourceLibraries = onRequestShowOpenSourceLibraries, onRequestShowOpenSourceLibraries = onRequestShowOpenSourceLibraries,
onRequestShowTranslators = onRequestShowTranslators onRequestShowTranslators = onRequestShowTranslators
) )

View File

@ -2,23 +2,22 @@ package com.abdownloadmanager.desktop.pages.about
import androidx.compose.foundation.* import androidx.compose.foundation.*
import com.abdownloadmanager.utils.compose.LocalTextStyle import com.abdownloadmanager.utils.compose.LocalTextStyle
import com.abdownloadmanager.utils.compose.ProvideTextStyle
import com.abdownloadmanager.desktop.ui.icon.MyIcons import com.abdownloadmanager.desktop.ui.icon.MyIcons
import com.abdownloadmanager.desktop.ui.theme.myColors import com.abdownloadmanager.desktop.ui.theme.myColors
import com.abdownloadmanager.desktop.ui.theme.myTextSizes import com.abdownloadmanager.desktop.ui.theme.myTextSizes
import com.abdownloadmanager.desktop.ui.widget.ActionButton
import com.abdownloadmanager.desktop.ui.widget.Text import com.abdownloadmanager.desktop.ui.widget.Text
import com.abdownloadmanager.desktop.utils.AppInfo import com.abdownloadmanager.desktop.utils.AppInfo
import com.abdownloadmanager.utils.compose.WithContentAlpha import com.abdownloadmanager.utils.compose.WithContentAlpha
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsHoveredAsState import androidx.compose.foundation.interaction.collectIsHoveredAsState
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.getValue import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.remember import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.*
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.input.pointer.PointerIcon import androidx.compose.ui.input.pointer.PointerIcon
import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
@ -26,63 +25,73 @@ import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.abdownloadmanager.desktop.SharedConstants
import com.abdownloadmanager.utils.compose.widget.MyIcon import com.abdownloadmanager.utils.compose.widget.MyIcon
import com.abdownloadmanager.desktop.ui.util.ifThen import com.abdownloadmanager.desktop.ui.util.ifThen
import com.abdownloadmanager.desktop.ui.widget.IconActionButton
import com.abdownloadmanager.desktop.ui.widget.Tooltip
import com.abdownloadmanager.desktop.utils.div
import com.abdownloadmanager.resources.Res import com.abdownloadmanager.resources.Res
import ir.amirab.util.UrlUtils
import ir.amirab.util.compose.IconSource
import ir.amirab.util.compose.StringSource
import ir.amirab.util.compose.asStringSource
import ir.amirab.util.compose.resources.myStringResource import ir.amirab.util.compose.resources.myStringResource
import java.net.URL
@Composable @Composable
fun AboutPage( fun AboutPage(
close: () -> Unit,
onRequestShowOpenSourceLibraries: () -> Unit, onRequestShowOpenSourceLibraries: () -> Unit,
onRequestShowTranslators: () -> Unit, onRequestShowTranslators: () -> Unit,
) { ) {
Column(Modifier.padding(16.dp)) { Box {
BackgroundEffects()
RenderAppInfo( RenderAppInfo(
modifier = Modifier modifier = Modifier,
.weight(1f)
.verticalScroll(rememberScrollState()),
onRequestShowOpenSourceLibraries = onRequestShowOpenSourceLibraries, onRequestShowOpenSourceLibraries = onRequestShowOpenSourceLibraries,
onRequestShowTranslators = onRequestShowTranslators, onRequestShowTranslators = onRequestShowTranslators,
) )
Row(Modifier.fillMaxWidth().wrapContentWidth(Alignment.End)) {
ActionButton(
myStringResource(Res.string.close),
onClick = close
)
}
} }
} }
@Composable @Composable
fun RenderAppInfo( private fun AppIconAndVersion(
modifier: Modifier, modifier: Modifier,
onRequestShowOpenSourceLibraries: () -> Unit,
onRequestShowTranslators: () -> Unit,
) { ) {
Row( Column(
modifier.fillMaxWidth() horizontalAlignment = Alignment.CenterHorizontally,
.padding(horizontal = 8.dp), modifier = modifier.padding(
) { horizontal = 24.dp,
ProvideTextStyle( vertical = 8.dp,
TextStyle(fontSize = myTextSizes.base) )
) {
Column {
Row(
verticalAlignment = Alignment.CenterVertically,
) { ) {
val shape = RoundedCornerShape(16.dp)
Image( Image(
MyIcons.appIcon.rememberPainter(), MyIcons.appIcon.rememberPainter(),
null, null,
Modifier Modifier
.size(48.dp) .shadow(12.dp, shape, spotColor = myColors.primary)
.clip(shape)
.border(
1.dp,
Brush.linearGradient(
listOf(myColors.primary, myColors.secondary)
),
shape
) )
Spacer(Modifier.width(16.dp)) .background(myColors.surface)
Column { .padding(16.dp)
.size(52.dp)
)
Spacer(Modifier.size(16.dp))
Column(
horizontalAlignment = Alignment.Start
) {
Text( Text(
AppInfo.displayName, AppInfo.displayName,
fontSize = myTextSizes.xl, fontSize = myTextSizes.lg,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
) )
Spacer(Modifier.height(2.dp)) Spacer(Modifier.height(2.dp))
@ -91,52 +100,293 @@ fun RenderAppInfo(
myStringResource( myStringResource(
Res.string.version_n, Res.string.version_n,
Res.string.version_n_createArgs( Res.string.version_n_createArgs(
value = AppInfo.version.toString() value = AppInfo.version.toString(),
) )
), fontSize = myTextSizes.base ),
fontSize = myTextSizes.base,
) )
} }
} }
} }
Spacer(Modifier.height(16.dp)) }
WithContentAlpha(1f) {
Text(myStringResource(Res.string.developed_with_love_for_you))
LinkText(myStringResource(Res.string.visit_the_project_website), AppInfo.website)
Spacer(Modifier.height(8.dp)) @Composable
private fun RenderAppInfo(
Text(myStringResource(Res.string.this_is_a_free_and_open_source_software)) modifier: Modifier,
LinkText(myStringResource(Res.string.view_the_source_code), AppInfo.sourceCode) onRequestShowOpenSourceLibraries: () -> Unit,
Spacer(Modifier.height(8.dp)) onRequestShowTranslators: () -> Unit,
Text(myStringResource(Res.string.powered_by_open_source_software)) ) {
Row(
modifier.fillMaxSize(),
) {
Column(
Modifier.width(250.dp),
verticalArrangement = Arrangement.SpaceBetween,
) {
AppIconAndVersion(Modifier.fillMaxWidth())
Spacer(Modifier.weight(1f))
Column(
Modifier
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text( Text(
myStringResource(Res.string.view_the_open_source_licenses), myStringResource(Res.string.developed_with_love_for_you),
style = LocalTextStyle.current.merge(LinkStyle), )
modifier = Modifier.clickable { Spacer(Modifier.height(8.dp))
Spacer(
Modifier
.fillMaxWidth()
.background(myColors.onBackground / 0.05f)
.height(1.dp)
)
Spacer(Modifier.height(8.dp))
val websiteUrl = SharedConstants.projectWebsite
val websiteDisplayName = remember(websiteUrl) {
kotlin.runCatching {
URL(websiteUrl).host
}.getOrNull() ?: websiteUrl
}
LinkText(
text = websiteDisplayName,
link = websiteUrl,
showExternalIndicator = false,
)
Spacer(Modifier.height(16.dp))
}
}
Spacer(
Modifier
.fillMaxHeight()
.width(1.dp)
.background(myColors.onBackground.copy(0.15f))
)
Column(
Modifier.weight(1f)
) {
CreditsSection(
modifier = Modifier.fillMaxWidth().weight(1f),
onRequestShowOpenSourceLibraries = onRequestShowOpenSourceLibraries,
onRequestShowTranslators = onRequestShowTranslators,
)
Spacer(Modifier.height(1.dp).fillMaxWidth().background(myColors.onBackground / 0.15f))
SocialAndLinks(
Modifier
.fillMaxWidth()
.background(myColors.surface / 0.5f)
.padding(top = 12.dp)
.padding(bottom = 16.dp)
.wrapContentWidth(),
horizontalPadding = 8.dp,
)
}
}
}
@Composable
private fun SocialAndLinks(
modifier: Modifier = Modifier,
horizontalPadding: Dp,
) {
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = modifier
.padding(
horizontal = horizontalPadding,
)
) {
SocialSmallButton(
MyIcons.earth,
Res.string.visit_the_project_website.asStringSource(),
onClick = {
UrlUtils.openUrl(SharedConstants.projectWebsite)
}
)
SocialSmallButton(
MyIcons.openSource,
Res.string.view_the_source_code.asStringSource(),
onClick = {
UrlUtils.openUrl(SharedConstants.projectSourceCode)
}
)
SocialSmallButton(
MyIcons.speaker,
Res.string.channel.asStringSource(),
onClick = {
UrlUtils.openUrl(SharedConstants.telegramChannelUrl)
}
)
SocialSmallButton(
MyIcons.group,
Res.string.group.asStringSource(),
onClick = {
UrlUtils.openUrl(SharedConstants.telegramGroupUrl)
}
)
SocialSmallButton(
MyIcons.language,
Res.string.translators_contribute_title.asStringSource(),
onClick = {
UrlUtils.openUrl(SharedConstants.projectTranslations)
}
)
}
}
@Composable
private fun CreditsSection(
modifier: Modifier = Modifier,
onRequestShowOpenSourceLibraries: () -> Unit,
onRequestShowTranslators: () -> Unit,
) {
Column(
modifier
.verticalScroll(rememberScrollState())
.padding(horizontal = 16.dp)
.padding(vertical = 8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
val itemModifier = Modifier.fillMaxWidth()
AboutPageListItemButton(
itemModifier,
icon = MyIcons.hearth,
title = Res.string.this_is_a_free_and_open_source_software.asStringSource(),
description = Res.string.view_the_source_code.asStringSource(),
onClick = {
UrlUtils.openUrl(AppInfo.sourceCode)
}
)
AboutPageListItemButton(
itemModifier,
icon = MyIcons.openSource,
title = Res.string.powered_by_open_source_software.asStringSource(),
description = Res.string.view_the_open_source_licenses.asStringSource(),
onClick = {
onRequestShowOpenSourceLibraries() onRequestShowOpenSourceLibraries()
} }
) )
Spacer(Modifier.height(8.dp)) AboutPageListItemButton(
Text(myStringResource(Res.string.localized_by_translators)) itemModifier,
Text( icon = MyIcons.language,
myStringResource(Res.string.meet_the_translators), title = Res.string.localized_by_translators.asStringSource(),
style = LocalTextStyle.current.merge(LinkStyle), description = Res.string.meet_the_translators.asStringSource(),
modifier = Modifier.clickable { onClick = {
onRequestShowTranslators() onRequestShowTranslators()
} }
) )
} }
} }
@Composable
private fun SocialSmallButton(
icon: IconSource,
title: StringSource,
onClick: () -> Unit,
) {
Tooltip(title) {
IconActionButton(
icon,
contentDescription = title.rememberString(),
onClick = onClick,
)
}
}
@Composable
private fun AboutPageListItemButton(
modifier: Modifier,
icon: IconSource,
title: StringSource,
description: StringSource,
onClick: () -> Unit,
) {
val shape = RoundedCornerShape(6.dp)
Row(
modifier
.clickable(onClick = onClick)
.border(1.dp, myColors.onBackground / 0.15f, shape)
.clip(shape)
.background(myColors.surface / 0.5f)
.padding(
horizontal = 8.dp,
vertical = 8.dp,
),
verticalAlignment = Alignment.CenterVertically,
) {
MyIcon(
icon = icon,
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Spacer(Modifier.width(8.dp))
Column {
Text(
title.rememberString(),
fontSize = myTextSizes.base,
fontWeight = FontWeight.Bold,
)
Spacer(Modifier.height(2.dp))
Text(description.rememberString())
} }
} }
} }
@Composable
private fun BoxScope.BackgroundEffects() {
Box(
Modifier
.align(Alignment.TopCenter)
.offset(x = (-50).dp, y = (-148).dp)
.fillMaxWidth(0.5f)
.height(250.dp)
.blur(
56.dp,
edgeTreatment = BlurredEdgeTreatment.Unbounded
)
.clip(CircleShape)
.background(
myColors.primary / 0.15f
)
)
Box(
Modifier
.align(Alignment.BottomStart)
.size(220.dp)
.offset(x = (-64).dp, y = (+128).dp)
.blur(
56.dp,
edgeTreatment = BlurredEdgeTreatment.Unbounded
)
.clip(CircleShape)
.background(
myColors.secondaryVariant / 0.15f
)
)
Box(
Modifier
.align(Alignment.BottomEnd)
.size(220.dp)
.offset(x = 32.dp, y = (-32).dp)
.blur(
56.dp,
edgeTreatment = BlurredEdgeTreatment.Unbounded
)
.clip(CircleShape)
.background(
myColors.secondary / 0.15f
)
)
}
@Composable @Composable
fun LinkText( fun LinkText(
text: String, text: String,
link: String, link: String,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
maxLines: Int = Int.MAX_VALUE, maxLines: Int = Int.MAX_VALUE,
showExternalIndicator: Boolean = true,
overflow: TextOverflow = TextOverflow.Clip, overflow: TextOverflow = TextOverflow.Clip,
) { ) {
val handler = LocalUriHandler.current val handler = LocalUriHandler.current
@ -164,6 +414,7 @@ fun LinkText(
overflow = overflow, overflow = overflow,
maxLines = maxLines, maxLines = maxLines,
) )
if (showExternalIndicator) {
MyIcon( MyIcon(
MyIcons.externalLink, MyIcons.externalLink,
null, null,
@ -174,6 +425,7 @@ fun LinkText(
) )
} }
} }
}
@Composable @Composable
fun MaybeLinkText( fun MaybeLinkText(

View File

@ -92,4 +92,7 @@ override val back get() = "/icons/back.svg".asIconSource()
override val language: IconSource get() = "/icons/language.svg".asIconSource() override val language: IconSource get() = "/icons/language.svg".asIconSource()
override val externalLink: IconSource get() = "/icons/external_link.svg".asIconSource() override val externalLink: IconSource get() = "/icons/external_link.svg".asIconSource()
override val earth: IconSource get() = "/icons/earth.svg".asIconSource()
override val hearth: IconSource get() = "/icons/hearth.svg".asIconSource()
} }

View File

@ -15,7 +15,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Popup import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.rememberComponentRectPositionProvider import androidx.compose.ui.window.rememberComponentRectPositionProvider
import com.abdownloadmanager.desktop.pages.settings.configurable.Configurable
import com.abdownloadmanager.desktop.ui.icon.MyIcons import com.abdownloadmanager.desktop.ui.icon.MyIcons
import com.abdownloadmanager.desktop.ui.theme.myColors import com.abdownloadmanager.desktop.ui.theme.myColors
import com.abdownloadmanager.desktop.ui.theme.myTextSizes import com.abdownloadmanager.desktop.ui.theme.myTextSizes
@ -51,32 +50,10 @@ fun Help(
tint = myColors.onSurface, tint = myColors.onSurface,
) )
if (showHelpContent) { if (showHelpContent) {
Popup( TooltipPopup(
popupPositionProvider = rememberComponentRectPositionProvider( onRequestCloseShowHelpContent = onRequestCloseShowHelpContent,
anchor = Alignment.TopCenter, content = content,
alignment = Alignment.TopCenter,
),
onDismissRequest = onRequestCloseShowHelpContent
) {
val shape = RoundedCornerShape(6.dp)
Box(
Modifier
.padding(vertical = 4.dp)
.widthIn(max = 240.dp)
.shadow(24.dp)
.clip(shape)
.border(1.dp, myColors.surface, shape)
.background(myColors.menuGradientBackground)
.padding(8.dp)
) {
WithContentColor(myColors.onSurface) {
Text(
content,
fontSize = myTextSizes.base,
) )
} }
} }
} }
}
}
}

View File

@ -0,0 +1,91 @@
package com.abdownloadmanager.desktop.ui.widget
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.hoverable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsHoveredAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.rememberComponentRectPositionProvider
import com.abdownloadmanager.desktop.ui.theme.myColors
import com.abdownloadmanager.desktop.ui.theme.myTextSizes
import com.abdownloadmanager.utils.compose.WithContentColor
import ir.amirab.util.compose.StringSource
import kotlinx.coroutines.delay
@Composable
fun Tooltip(
tooltip: StringSource,
delayUntilShow: Long = 500,
content: @Composable () -> Unit,
) {
val interactionSource = remember { MutableInteractionSource() }
val isHovered by interactionSource.collectIsHoveredAsState()
var showHint by remember { mutableStateOf(false) }
LaunchedEffect(isHovered) {
if (isHovered) {
delay(delayUntilShow)
showHint = true
} else {
showHint = false
}
}
Column(
modifier = Modifier
.hoverable(interactionSource)
) {
if (showHint) {
TooltipPopup(
onRequestCloseShowHelpContent = {
showHint = false
},
content = tooltip.rememberString(),
)
}
content()
}
}
@Composable
fun TooltipPopup(
onRequestCloseShowHelpContent: () -> Unit,
content: String,
) {
Popup(
popupPositionProvider = rememberComponentRectPositionProvider(
anchor = Alignment.TopCenter,
alignment = Alignment.TopCenter,
),
onDismissRequest = onRequestCloseShowHelpContent
) {
val shape = RoundedCornerShape(6.dp)
Box(
Modifier
.padding(vertical = 4.dp)
.widthIn(max = 240.dp)
.shadow(24.dp)
.clip(shape)
.border(1.dp, myColors.surface, shape)
.background(myColors.menuGradientBackground)
.padding(8.dp)
) {
WithContentColor(myColors.onSurface) {
Text(
content,
fontSize = myTextSizes.base,
)
}
}
}
}

View File

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.5001 12.572L12.0001 20L4.50006 12.572C4.00536 12.0906 3.6157 11.512 3.3556 10.8726C3.09551 10.2333 2.97062 9.54694 2.98879 8.85693C3.00697 8.16691 3.16782 7.48813 3.46121 6.86333C3.75461 6.23853 4.17419 5.68125 4.69354 5.22657C5.21289 4.7719 5.82076 4.42968 6.47887 4.22147C7.13697 4.01327 7.83106 3.94358 8.51743 4.0168C9.20379 4.09001 9.86756 4.30455 10.4669 4.6469C11.0663 4.98925 11.5883 5.45199 12.0001 6.00599C12.4136 5.45602 12.9362 4.99731 13.5352 4.6586C14.1341 4.31988 14.7966 4.10844 15.481 4.03751C16.1654 3.96658 16.8571 4.03769 17.5128 4.24639C18.1685 4.45508 18.7741 4.79687 19.2916 5.25036C19.8091 5.70385 20.2275 6.25928 20.5205 6.88189C20.8135 7.50449 20.9748 8.18088 20.9944 8.8687C21.0139 9.55653 20.8913 10.241 20.6342 10.8792C20.3771 11.5175 19.991 12.0958 19.5001 12.578"
stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1006 B

View File

@ -79,4 +79,7 @@ interface IMyIcons {
val network: IconSource val network: IconSource
val language: IconSource val language: IconSource
val externalLink: IconSource val externalLink: IconSource
val earth: IconSource
val hearth: IconSource
} }