feat(Airdrop): Added welcome page and basic view to create airdrop
- Added basic navigation. - Added welcome page. - Added temporal basic create airdrop page. Closes #9796
This commit is contained in:
parent
3feddd892b
commit
b8b6f36bd9
|
@ -14,6 +14,7 @@ StatusDropdown {
|
|||
|
||||
property var assetsModel
|
||||
property var collectiblesModel
|
||||
property bool isENSTab: true
|
||||
|
||||
property var usedTokens: []
|
||||
property var usedEnsNames: []
|
||||
|
@ -74,6 +75,8 @@ StatusDropdown {
|
|||
readonly property var holdingTypes: [
|
||||
HoldingTypes.Type.Asset, HoldingTypes.Type.Collectible, HoldingTypes.Type.Ens
|
||||
]
|
||||
readonly property var tabsModel: [qsTr("Assets"), qsTr("Collectibles"), qsTr("ENS")]
|
||||
readonly property var tabsModelNoEns: [qsTr("Assets"), qsTr("Collectibles")]
|
||||
readonly property bool assetsReady: root.assetAmount > 0 && root.assetKey
|
||||
readonly property bool collectiblesReady: root.collectibleAmount > 0 && root.collectibleKey
|
||||
readonly property bool ensReady: d.ensDomainNameValid
|
||||
|
@ -179,13 +182,15 @@ StatusDropdown {
|
|||
]
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
d.currentHoldingType = d.holdingTypes[currentIndex]
|
||||
d.setInitialFlow()
|
||||
if(currentIndex >= 0) {
|
||||
d.currentHoldingType = d.holdingTypes[currentIndex]
|
||||
d.setInitialFlow()
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: tabLabelsRepeater
|
||||
model: [qsTr("Assets"), qsTr("Collectibles"), qsTr("ENS")]
|
||||
model: root.isENSTab ? d.tabsModel : d.tabsModelNoEns
|
||||
|
||||
StatusSwitchTabButton {
|
||||
text: modelData
|
||||
|
@ -204,14 +209,14 @@ StatusDropdown {
|
|||
State {
|
||||
name: HoldingsDropdown.FlowType.Selected
|
||||
PropertyChanges {target: loader; sourceComponent: (d.currentHoldingType === HoldingTypes.Type.Asset) ? assetLayout :
|
||||
((d.currentHoldingType === HoldingTypes.Type.Collectible) ? collectibleLayout : ensLayout) }
|
||||
((d.currentHoldingType === HoldingTypes.Type.Collectible) ? collectibleLayout : ensLayout) }
|
||||
PropertyChanges {target: root; height: undefined} // use implicit height
|
||||
},
|
||||
State {
|
||||
name: HoldingsDropdown.FlowType.List_Deep1
|
||||
PropertyChanges {target: loader; sourceComponent: listLayout}
|
||||
PropertyChanges {target: root; height: d.extendedContentHeight}
|
||||
PropertyChanges {target: d; extendedDeepNavigation: false}
|
||||
PropertyChanges {target: d; extendedDeepNavigation: false}
|
||||
},
|
||||
State {
|
||||
name: HoldingsDropdown.FlowType.List_Deep2
|
||||
|
@ -352,8 +357,8 @@ StatusDropdown {
|
|||
onRemoveClicked: root.removeClicked()
|
||||
|
||||
Component.onCompleted: {
|
||||
if (d.collectibleAmountText.length === 0 && root.collectibleAmount)
|
||||
collectiblePanel.setAmount(root.collectibleAmount)
|
||||
if (d.collectibleAmountText.length === 0 && root.collectibleAmount)
|
||||
collectiblePanel.setAmount(root.collectibleAmount)
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
import AppLayouts.Chat.layouts 1.0
|
||||
import AppLayouts.Chat.views.communities 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
SettingsPageLayout {
|
||||
id: root
|
||||
|
||||
// Token models:
|
||||
required property var assetsModel
|
||||
required property var collectiblesModel
|
||||
|
||||
property int viewWidth: 560 // by design
|
||||
|
||||
signal airdropClicked(var airdropTokens, string address)
|
||||
|
||||
// TODO: Update with stackmanager when #8736 is integrated
|
||||
function navigateBack() {
|
||||
stackManager.pop(StackView.Immediate)
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property string welcomeViewState: "WELCOME"
|
||||
readonly property string newAirdropViewState: "NEW_AIRDROP"
|
||||
|
||||
readonly property string welcomePageTitle: qsTr("Airdrops")
|
||||
readonly property string newAirdropViewPageTitle: qsTr("New airdrop")
|
||||
}
|
||||
|
||||
content: StackView {
|
||||
anchors.fill: parent
|
||||
initialItem: welcomeView
|
||||
|
||||
Component.onCompleted: stackManager.pushInitialState(d.welcomeViewState)
|
||||
}
|
||||
|
||||
state: stackManager.currentState
|
||||
states: [
|
||||
State {
|
||||
name: d.welcomeViewState
|
||||
PropertyChanges {target: root; title: d.welcomePageTitle}
|
||||
PropertyChanges {target: root; previousPageName: ""}
|
||||
PropertyChanges {target: root; headerButtonVisible: true}
|
||||
PropertyChanges {target: root; headerButtonText: qsTr("New Airdrop")}
|
||||
PropertyChanges {target: root; headerWidth: root.viewWidth}
|
||||
},
|
||||
State {
|
||||
name: d.newAirdropViewState
|
||||
PropertyChanges {target: root; title: d.newAirdropViewPageTitle}
|
||||
PropertyChanges {target: root; previousPageName: d.welcomePageTitle}
|
||||
PropertyChanges {target: root; headerButtonVisible: false}
|
||||
PropertyChanges {target: root; headerWidth: 0}
|
||||
}
|
||||
]
|
||||
|
||||
onHeaderButtonClicked: stackManager.push(d.newAirdropViewState, newAirdropView, null, StackView.Immediate)
|
||||
|
||||
StackViewStates {
|
||||
id: stackManager
|
||||
|
||||
stackView: root.contentItem
|
||||
}
|
||||
|
||||
// Mint tokens possible view contents:
|
||||
Component {
|
||||
id: welcomeView
|
||||
|
||||
CommunityWelcomeSettingsView {
|
||||
viewWidth: root.viewWidth
|
||||
image: Style.png("community/airdrops8_1")
|
||||
title: qsTr("Airdrop community tokens")
|
||||
subtitle: qsTr("You can mint custom tokens and collectibles for your community")
|
||||
checkersModel: [
|
||||
qsTr("Reward individual members with custom tokens for their contribution"),
|
||||
qsTr("Incentivise joining, retention, moderation and desired behaviour"),
|
||||
qsTr("Require holding a token or NFT to obtain exclusive membership rights")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: newAirdropView
|
||||
|
||||
CommunityNewAirdropView {
|
||||
assetsModel: root.assetsModel
|
||||
collectiblesModel: root.collectiblesModel
|
||||
|
||||
onAirdropClicked: {
|
||||
root.airdropClicked(airdropTokens, address)
|
||||
stackManager.clear(d.welcomeViewState, StackView.Immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
CommunityAirdropsSettingsPanel 1.0 CommunityAirdropsSettingsPanel.qml
|
||||
CommunityColumnHeaderPanel 1.0 CommunityColumnHeaderPanel.qml
|
||||
CommunityMintTokensSettingsPanel 1.0 CommunityMintTokensSettingsPanel.qml
|
||||
CommunityPermissionsSettingsPanel 1.0 CommunityPermissionsSettingsPanel.qml
|
||||
|
|
|
@ -55,4 +55,9 @@ QtObject {
|
|||
}
|
||||
])
|
||||
}
|
||||
|
||||
// Airdrop tokens:
|
||||
function airdrop(airdropTokens, address) {
|
||||
console.warn("TODO: Airdrop backend call!")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@ StatusSectionLayout {
|
|||
property var settingsMenuModel: [{name: qsTr("Overview"), icon: "show", enabled: true},
|
||||
{name: qsTr("Members"), icon: "group-chat", enabled: true},
|
||||
{name: qsTr("Permissions"), icon: "objects", enabled: root.rootStore.communityPermissionsEnabled},
|
||||
{name: qsTr("Mint Tokens"), icon: "token", enabled: root.rootStore.communityTokensEnabled}]
|
||||
{name: qsTr("Mint Tokens"), icon: "token", enabled: root.rootStore.communityTokensEnabled},
|
||||
{name: qsTr("Airdrops"), icon: "airdrop", enabled: root.rootStore.communityTokensEnabled}]
|
||||
// TODO: Next community settings options:
|
||||
// {name: qsTr("Airdrops"), icon: "airdrop"},
|
||||
// {name: qsTr("Token sales"), icon: "token-sale"},
|
||||
// {name: qsTr("Subscriptions"), icon: "subscription"},
|
||||
property var rootStore
|
||||
|
@ -310,6 +310,17 @@ StatusSectionLayout {
|
|||
}
|
||||
}
|
||||
|
||||
CommunityAirdropsSettingsPanel {
|
||||
readonly property CommunityTokensStore communityTokensStore:
|
||||
rootStore.communityTokensStore
|
||||
|
||||
assetsModel: rootStore.assetsModel
|
||||
collectiblesModel: rootStore.collectiblesModel
|
||||
|
||||
onPreviousPageNameChanged: root.backButtonName = previousPageName
|
||||
onAirdropClicked: communityTokensStore.airdrop(airdropTokens, chainId, address)
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: root.backButtonName = centerPanelContentLoader.item.children[d.currentIndex].previousPageName
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
import utils 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import AppLayouts.Chat.helpers 1.0
|
||||
import AppLayouts.Chat.panels.communities 1.0
|
||||
import AppLayouts.Chat.controls.community 1.0
|
||||
|
||||
// TEMPORAL - BASIC IMPLEMENTATION
|
||||
StatusScrollView {
|
||||
id: root
|
||||
|
||||
// Token models:
|
||||
required property var assetsModel
|
||||
required property var collectiblesModel
|
||||
|
||||
property int viewWidth: 560 // by design
|
||||
|
||||
// roles: type, key, name, amount, imageSource
|
||||
property var selectedHoldingsModel: ListModel {}
|
||||
|
||||
readonly property bool isFullyFilled: selectedHoldingsModel.count > 0 &&
|
||||
addressess.itemsModel.count > 0
|
||||
|
||||
signal airdropClicked(var airdropTokens, string address)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int maxAirdropTokens: 5
|
||||
readonly property int dropdownHorizontalOffset: 4
|
||||
readonly property int dropdownVerticalOffset: 1
|
||||
}
|
||||
|
||||
contentWidth: mainLayout.width
|
||||
contentHeight: mainLayout.height
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
width: root.viewWidth
|
||||
spacing: 0
|
||||
|
||||
StatusItemSelector {
|
||||
id: tokensSelector
|
||||
|
||||
property int editedIndex: -1
|
||||
|
||||
Layout.fillWidth: true
|
||||
icon: Style.svg("token")
|
||||
title: qsTr("What")
|
||||
defaultItemText: qsTr("Example: 1 SOCK")
|
||||
tagLeftPadding: 2
|
||||
asset.height: 28
|
||||
asset.width: asset.height
|
||||
addButton.visible: itemsModel.count < d.maxAirdropTokens
|
||||
|
||||
itemsModel: HoldingsSelectionModel {
|
||||
sourceModel: root.selectedHoldingsModel
|
||||
|
||||
assetsModel: root.assetsModel
|
||||
collectiblesModel: root.collectiblesModel
|
||||
}
|
||||
|
||||
// TODO: All this code is repeated inside `CommunityNewPermissionView`. Check how to reuse it.
|
||||
HoldingsDropdown {
|
||||
id: dropdown
|
||||
|
||||
assetsModel: root.assetsModel
|
||||
collectiblesModel: root.collectiblesModel
|
||||
isENSTab: false
|
||||
|
||||
function addItem(type, item, amount) {
|
||||
const key = item.key
|
||||
|
||||
root.selectedHoldingsModel.append(
|
||||
{ type, key, amount })
|
||||
}
|
||||
|
||||
function getHoldingIndex(key) {
|
||||
return ModelUtils.indexOf(root.selectedHoldingsModel, "key", key)
|
||||
}
|
||||
|
||||
function prepareUpdateIndex(key) {
|
||||
const itemIndex = tokensSelector.editedIndex
|
||||
const existingIndex = getHoldingIndex(key)
|
||||
|
||||
if (itemIndex !== -1 && existingIndex !== -1 && itemIndex !== existingIndex) {
|
||||
const previousKey = root.selectedHoldingsModel.get(itemIndex).key
|
||||
root.selectedHoldingsModel.remove(existingIndex)
|
||||
return getHoldingIndex(previousKey)
|
||||
}
|
||||
|
||||
if (itemIndex === -1) {
|
||||
return existingIndex
|
||||
}
|
||||
|
||||
return itemIndex
|
||||
}
|
||||
|
||||
onAddAsset: {
|
||||
const modelItem = CommunityPermissionsHelpers.getTokenByKey(
|
||||
root.assetsModel, key)
|
||||
addItem(HoldingTypes.Type.Asset, modelItem, amount)
|
||||
dropdown.close()
|
||||
}
|
||||
|
||||
onAddCollectible: {
|
||||
const modelItem = CommunityPermissionsHelpers.getTokenByKey(
|
||||
root.collectiblesModel, key)
|
||||
addItem(HoldingTypes.Type.Collectible, modelItem, amount)
|
||||
dropdown.close()
|
||||
}
|
||||
|
||||
onUpdateAsset: {
|
||||
const itemIndex = prepareUpdateIndex(key)
|
||||
const modelItem = CommunityPermissionsHelpers.getTokenByKey(root.assetsModel, key)
|
||||
|
||||
root.selectedHoldingsModel.set(
|
||||
itemIndex, { type: HoldingTypes.Type.Asset, key, amount })
|
||||
dropdown.close()
|
||||
}
|
||||
|
||||
onUpdateCollectible: {
|
||||
const itemIndex = prepareUpdateIndex(key)
|
||||
const modelItem = CommunityPermissionsHelpers.getTokenByKey(
|
||||
root.collectiblesModel, key)
|
||||
|
||||
root.selectedHoldingsModel.set(
|
||||
itemIndex,
|
||||
{ type: HoldingTypes.Type.Collectible, key, amount })
|
||||
dropdown.close()
|
||||
}
|
||||
|
||||
onRemoveClicked: {
|
||||
root.selectedHoldingsModel.remove(tokensSelector.editedIndex)
|
||||
dropdown.close()
|
||||
}
|
||||
}
|
||||
|
||||
addButton.onClicked: {
|
||||
dropdown.parent = tokensSelector.addButton
|
||||
dropdown.x = tokensSelector.addButton.width + d.dropdownHorizontalOffset
|
||||
dropdown.y = 0
|
||||
dropdown.open()
|
||||
|
||||
editedIndex = -1
|
||||
}
|
||||
|
||||
onItemClicked: {
|
||||
if (mouse.button !== Qt.LeftButton)
|
||||
return
|
||||
|
||||
dropdown.parent = item
|
||||
dropdown.x = mouse.x + d.dropdownHorizontalOffset
|
||||
dropdown.y = d.dropdownVerticalOffset
|
||||
|
||||
const modelItem = tokensSelector.itemsModel.get(index)
|
||||
|
||||
switch(modelItem.type) {
|
||||
case HoldingTypes.Type.Asset:
|
||||
dropdown.assetKey = modelItem.key
|
||||
dropdown.assetAmount = modelItem.amount
|
||||
break
|
||||
case HoldingTypes.Type.Collectible:
|
||||
dropdown.collectibleKey = modelItem.key
|
||||
dropdown.collectibleAmount = modelItem.amount
|
||||
break
|
||||
default:
|
||||
console.warn("Unsupported holdings type.")
|
||||
}
|
||||
|
||||
dropdown.setActiveTab(modelItem.type)
|
||||
dropdown.openUpdateFlow()
|
||||
|
||||
editedIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.leftMargin: 16
|
||||
Layout.preferredWidth: 2
|
||||
Layout.preferredHeight: 24
|
||||
color: Style.current.separator
|
||||
}
|
||||
|
||||
// TEMPORAL
|
||||
StatusInput {
|
||||
id: addressInput
|
||||
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("Example: 0x7F47C2e18a4BBf5487E6fb082eC2D9Ab0E6d7999")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.leftMargin: 16
|
||||
Layout.preferredWidth: 2
|
||||
Layout.preferredHeight: 24
|
||||
color: Style.current.separator
|
||||
}
|
||||
|
||||
StatusItemSelector {
|
||||
id: addressess
|
||||
|
||||
Layout.fillWidth: true
|
||||
icon: Style.svg("member")
|
||||
title: qsTr("To")
|
||||
defaultItemText: qsTr("Example: 12 addresses and 3 members")
|
||||
tagLeftPadding: 2
|
||||
asset.height: 28
|
||||
asset.width: asset.height
|
||||
|
||||
addButton.onClicked: {
|
||||
if(addressInput.text.length > 0)
|
||||
itemsModel.append({text: addressInput.text})
|
||||
}
|
||||
|
||||
onItemClicked: addressess.itemsModel.remove(index)
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
Layout.preferredHeight: 44
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.bigPadding
|
||||
text: qsTr("Create airdrop")
|
||||
enabled: root.isFullyFilled
|
||||
|
||||
onClicked: {
|
||||
const airdropTokens = ModelUtils.modelToArray(
|
||||
root.selectedHoldingsModel,
|
||||
["key", "type", "amount"])
|
||||
|
||||
root.airdropClicked(airdropTokens, addressess.itemsModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
ChannelsSelectionModel 1.0 ChannelsSelectionModel.qml
|
||||
CommunityCollectibleView 1.0 CommunityCollectibleView.qml
|
||||
CommunityNewAirdropView 1.0 CommunityNewAirdropView.qml
|
||||
CommunityMintedTokensView 1.0 CommunityMintedTokensView.qml
|
||||
CommunityNewCollectibleView 1.0 CommunityNewCollectibleView.qml
|
||||
CommunityNewPermissionView 1.0 CommunityNewPermissionView.qml
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="18" viewBox="0 0 16 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.9995 5C12.9995 7.76142 10.7609 10 7.99951 10C5.23809 10 2.99951 7.76142 2.99951 5C2.99951 2.23858 5.23809 0 7.99951 0C10.7609 0 12.9995 2.23858 12.9995 5ZM11.4995 5C11.4995 6.933 9.93251 8.5 7.99951 8.5C6.06651 8.5 4.49951 6.933 4.49951 5C4.49951 3.067 6.06651 1.5 7.99951 1.5C9.93251 1.5 11.4995 3.067 11.4995 5Z" fill="#4360DF"/>
|
||||
<path d="M14.383 17.3874C14.6855 17.7312 15.2215 17.7779 15.5453 17.4541C15.806 17.1933 15.8374 16.7784 15.5976 16.4984C13.7635 14.357 11.0399 13 7.99936 13C4.95884 13 2.23525 14.357 0.401185 16.4984C0.161325 16.7784 0.192703 17.1933 0.453434 17.454C0.777236 17.7779 1.31325 17.7312 1.61575 17.3874C3.17347 15.6171 5.45596 14.5 7.99936 14.5C10.5428 14.5 12.8253 15.6171 14.383 17.3874Z" fill="#4360DF"/>
|
||||
</svg>
|
After Width: | Height: | Size: 892 B |
|
@ -0,0 +1,4 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.09383 13.3807C10.2449 13.6891 11.4157 13.3863 12.2617 12.6713C12.4724 12.4931 12.7863 12.471 12.9928 12.6541L13.3671 12.9861C13.5739 13.1694 13.5943 13.4877 13.3911 13.6749C12.8023 14.2172 12.0897 14.6125 11.3164 14.8243C11.1344 14.8742 10.9865 15.0114 10.9377 15.1936L10.6204 16.3779C10.5489 16.6447 10.2747 16.8029 10.008 16.7315L9.52504 16.6021C9.25831 16.5306 9.10002 16.2564 9.17149 15.9897L9.29443 15.5309C9.37357 15.2355 9.1705 14.9405 8.87263 14.8714C8.81694 14.8584 8.76126 14.8445 8.70561 14.8296C8.65006 14.8147 8.59498 14.799 8.54038 14.7823C8.24787 14.6933 7.92451 14.8473 7.84537 15.1426L7.72243 15.6014C7.65096 15.8682 7.37679 16.0265 7.11006 15.955L6.6271 15.8256C6.36036 15.7541 6.20207 15.4799 6.27354 15.2132L6.59082 14.0291C6.63966 13.8468 6.58014 13.654 6.44745 13.5199C5.23912 12.2981 4.69324 10.4855 5.17007 8.70589C5.64692 6.92625 7.02609 5.62935 8.68347 5.1755C8.86548 5.12566 9.01343 4.98846 9.06227 4.80618L9.37954 3.6221C9.45102 3.35537 9.72518 3.19708 9.99192 3.26855L10.4749 3.39796C10.7416 3.46943 10.8999 3.7436 10.8284 4.01033L10.7055 4.46923C10.6263 4.76457 10.8294 5.05959 11.1272 5.12872C11.1828 5.14161 11.2383 5.15549 11.2938 5.17036C11.3494 5.18525 11.4045 5.20102 11.4591 5.21764C11.7516 5.30671 12.0749 5.15274 12.1541 4.85739L12.277 4.39859C12.3485 4.13186 12.6226 3.97357 12.8894 4.04504L13.3723 4.17445C13.6391 4.24592 13.7974 4.52009 13.7259 4.78682L13.4086 5.97091C13.3598 6.15318 13.4193 6.34594 13.552 6.48011C14.1158 7.05022 14.5354 7.74901 14.7742 8.51307C14.8566 8.77679 14.6797 9.04229 14.409 9.09769L13.9189 9.19799C13.6485 9.25332 13.3877 9.07726 13.2943 8.81757C12.9191 7.77531 12.0566 6.92767 10.9056 6.61925C9.03844 6.11895 7.11926 7.22699 6.61896 9.09412C6.11866 10.9613 7.2267 12.8804 9.09383 13.3807Z" fill="#4360DF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10C0 4.47715 4.47715 0 10 0C15.5228 0 20 4.47715 20 10ZM18.5 10C18.5 14.6944 14.6944 18.5 10 18.5C5.30558 18.5 1.5 14.6944 1.5 10C1.5 5.30558 5.30558 1.5 10 1.5C14.6944 1.5 18.5 5.30558 18.5 10Z" fill="#4360DF"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Loading…
Reference in New Issue