Merge branch 'main' of https://github.com/believethehype/amethyst
@@ -18,7 +18,7 @@
|
||||
android:name=".Amethyst"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@drawable/amethyst"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:supportsRtl="true"
|
||||
|
||||
|
After Width: | Height: | Size: 30 KiB |
@@ -6,14 +6,16 @@ import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.R
|
||||
fun checkForHashtagWithIcon(tag: String): HashtagIcon? {
|
||||
return when (tag.lowercase()) {
|
||||
"bitcoin", "btc" -> HashtagIcon(R.drawable.ht_btc, "Bitcoin", Color.Unspecified, Modifier.padding(2.dp, 2.dp, 0.dp, 0.dp))
|
||||
"nostr", "nostrich", "nostriches", "nostrichs" -> HashtagIcon(R.drawable.ht_nostr, "Nostr", Color.Unspecified, Modifier.padding(1.dp, 2.dp, 0.dp, 0.dp))
|
||||
"bitcoin", "btc", "timechain" -> HashtagIcon(R.drawable.ht_btc, "Bitcoin", Color.Unspecified, Modifier.padding(2.dp, 2.dp, 0.dp, 0.dp))
|
||||
"nostr", "nostrich", "nostriches" -> HashtagIcon(R.drawable.ht_nostr, "Nostr", Color.Unspecified, Modifier.padding(1.dp, 2.dp, 0.dp, 0.dp))
|
||||
"lightning", "lightningnetwork" -> HashtagIcon(R.drawable.ht_lightning, "Lightning", Color.Unspecified, Modifier.padding(1.dp, 3.dp, 0.dp, 0.dp))
|
||||
"zap", "zaps", "zapper", "zappers", "zapping", "zapped", "zapathon", "zapraiser", "zaplife", "zapchain" -> HashtagIcon(R.drawable.zap, "Zap", Color.Unspecified, Modifier.padding(1.dp, 3.dp, 0.dp, 0.dp))
|
||||
"amethyst" -> HashtagIcon(R.drawable.amethyst, "Amethyst", Color.Unspecified, Modifier.padding(3.dp, 2.dp, 0.dp, 0.dp))
|
||||
"plebs", "pleb", "plebchain" -> HashtagIcon(R.drawable.plebs, "Pleb", Color.Unspecified, Modifier.padding(2.dp, 2.dp, 0.dp, 1.dp))
|
||||
"coffee", "coffeechain" -> HashtagIcon(R.drawable.coffee, "Coffee", Color.Unspecified, Modifier.padding(2.dp, 2.dp, 0.dp, 0.dp))
|
||||
"coffee", "coffeechain", "cafe" -> HashtagIcon(R.drawable.coffee, "Coffee", Color.Unspecified, Modifier.padding(2.dp, 2.dp, 0.dp, 0.dp))
|
||||
"skullofsatoshi" -> HashtagIcon(R.drawable.skull, "SkullofSatoshi", Color.Unspecified, Modifier.padding(2.dp, 1.dp, 0.dp, 0.dp))
|
||||
"grownostr", "#permaculture", "#gardening", "#garden" -> HashtagIcon(R.drawable.grownostr, "GrowNostr", Color.Unspecified, Modifier.padding(0.dp, 1.dp, 0.dp, 1.dp))
|
||||
"footstr" -> HashtagIcon(R.drawable.footstr, "Footstr", Color.Unspecified, Modifier.padding(1.dp, 1.dp, 0.dp, 0.dp))
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.vitorpamplona.amethyst.service.NostrAccountDataSource.account
|
||||
import com.vitorpamplona.amethyst.service.model.*
|
||||
import com.vitorpamplona.amethyst.service.relays.Relay
|
||||
import com.vitorpamplona.amethyst.ui.components.BundledInsert
|
||||
@@ -594,6 +595,16 @@ object LocalCache {
|
||||
fun consume(event: LnZapEvent) {
|
||||
val note = getOrCreateNote(event.id)
|
||||
|
||||
var decryptedContent = LnZapRequestEvent.checkForPrivateZap(event.zapRequest!!, account.loggedIn.privKey!!)
|
||||
if (decryptedContent != null) {
|
||||
Log.e(
|
||||
"DC",
|
||||
"Decrypted Content from Anon Tag: Sender: {${decryptedContent.pubKey}}, Message: {${decryptedContent.content}} "
|
||||
|
||||
// TODO Update Notification with this Sender and Message
|
||||
)
|
||||
}
|
||||
|
||||
// Already processed this event.
|
||||
if (note.event != null) return
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class LnZapEvent(
|
||||
// This event is also kept in LocalCache (same object)
|
||||
@Transient val zapRequest: LnZapRequestEvent?
|
||||
|
||||
private fun containedPost(): LnZapRequestEvent? = try {
|
||||
override fun containedPost(): LnZapRequestEvent? = try {
|
||||
description()?.ifBlank { null }?.let {
|
||||
fromJson(it, Client.lenient)
|
||||
} as? LnZapRequestEvent
|
||||
@@ -53,8 +53,7 @@ class LnZapEvent(
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun message(): String {
|
||||
override fun content(): String {
|
||||
return content
|
||||
}
|
||||
|
||||
@@ -68,7 +67,7 @@ class LnZapEvent(
|
||||
|
||||
enum class ZapType() {
|
||||
PUBLIC,
|
||||
PRIVATE, // not yet implemented
|
||||
PRIVATE,
|
||||
ANONYMOUS,
|
||||
NONZAP
|
||||
}
|
||||
|
||||
@@ -16,5 +16,5 @@ interface LnZapEventInterface : EventInterface {
|
||||
|
||||
fun amount(): BigDecimal?
|
||||
|
||||
fun message(): String
|
||||
fun containedPost(): Event?
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package com.vitorpamplona.amethyst.service.model
|
||||
|
||||
import com.vitorpamplona.amethyst.model.HexKey
|
||||
import com.vitorpamplona.amethyst.model.toHexKey
|
||||
import com.vitorpamplona.amethyst.model.*
|
||||
import nostr.postr.Bech32
|
||||
import nostr.postr.Utils
|
||||
import java.util.Date
|
||||
import java.nio.charset.Charset
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
import javax.crypto.BadPaddingException
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
class LnZapRequestEvent(
|
||||
id: HexKey,
|
||||
@@ -30,7 +36,7 @@ class LnZapRequestEvent(
|
||||
zapType: LnZapEvent.ZapType,
|
||||
createdAt: Long = Date().time / 1000
|
||||
): LnZapRequestEvent {
|
||||
val content = message
|
||||
var content = message
|
||||
var privkey = privateKey
|
||||
var pubKey = Utils.pubkeyCreate(privateKey).toHexKey()
|
||||
var tags = listOf(
|
||||
@@ -48,6 +54,14 @@ class LnZapRequestEvent(
|
||||
tags = tags + listOf(listOf("anon", ""))
|
||||
privkey = Utils.privkeyCreate()
|
||||
pubKey = Utils.pubkeyCreate(privkey).toHexKey()
|
||||
} else if (zapType == LnZapEvent.ZapType.PRIVATE) {
|
||||
var encryptionPrivateKey = createEncryptionPrivateKey(privateKey.toHexKey(), originalNote.id(), createdAt)
|
||||
var noteJson = (create(privkey, 9733, listOf(tags[0], tags[1]), message)).toJson()
|
||||
var encryptedContent = encryptPrivateZapMessage(noteJson, encryptionPrivateKey, originalNote.pubKey().toByteArray())
|
||||
tags = tags + listOf(listOf("anon", encryptedContent))
|
||||
content = "" // make sure public content is empty, as the content is encrypted
|
||||
privkey = encryptionPrivateKey // sign event with generated privkey
|
||||
pubKey = Utils.pubkeyCreate(encryptionPrivateKey).toHexKey() // updated event with according pubkey
|
||||
}
|
||||
val id = generateId(pubKey, createdAt, kind, tags, content)
|
||||
val sig = Utils.sign(id, privkey)
|
||||
@@ -62,7 +76,7 @@ class LnZapRequestEvent(
|
||||
zapType: LnZapEvent.ZapType,
|
||||
createdAt: Long = Date().time / 1000
|
||||
): LnZapRequestEvent {
|
||||
val content = message
|
||||
var content = message
|
||||
var privkey = privateKey
|
||||
var pubKey = Utils.pubkeyCreate(privateKey).toHexKey()
|
||||
var tags = listOf(
|
||||
@@ -70,18 +84,90 @@ class LnZapRequestEvent(
|
||||
listOf("relays") + relays
|
||||
)
|
||||
if (zapType == LnZapEvent.ZapType.ANONYMOUS) {
|
||||
tags = tags + listOf(listOf("anon", ""))
|
||||
privkey = Utils.privkeyCreate()
|
||||
pubKey = Utils.pubkeyCreate(privkey).toHexKey()
|
||||
tags = tags + listOf(listOf("anon", ""))
|
||||
} else if (zapType == LnZapEvent.ZapType.PRIVATE) {
|
||||
var encryptionPrivateKey = createEncryptionPrivateKey(privateKey.toHexKey(), userHex, createdAt)
|
||||
var noteJson = (create(privkey, 9733, listOf(tags[0], tags[1]), message)).toJson()
|
||||
var encryptedContent = encryptPrivateZapMessage(noteJson, encryptionPrivateKey, userHex.toByteArray())
|
||||
tags = tags + listOf(listOf("anon", encryptedContent))
|
||||
content = ""
|
||||
privkey = encryptionPrivateKey
|
||||
pubKey = Utils.pubkeyCreate(encryptionPrivateKey).toHexKey()
|
||||
}
|
||||
|
||||
val id = generateId(pubKey, createdAt, kind, tags, content)
|
||||
val sig = Utils.sign(id, privkey)
|
||||
return LnZapRequestEvent(id.toHexKey(), pubKey, createdAt, tags, content, sig.toHexKey())
|
||||
}
|
||||
|
||||
fun createEncryptionPrivateKey(privkey: String, id: String, createdAt: Long): ByteArray {
|
||||
var str = privkey + id + createdAt.toString()
|
||||
var strbyte = str.toByteArray(Charset.forName("utf-8"))
|
||||
return sha256.digest(strbyte)
|
||||
}
|
||||
|
||||
fun encryptPrivateZapMessage(msg: String, privkey: ByteArray, pubkey: ByteArray): String {
|
||||
var sharedSecret = Utils.getSharedSecret(privkey, pubkey)
|
||||
val iv = ByteArray(16)
|
||||
SecureRandom().nextBytes(iv)
|
||||
|
||||
val keySpec = SecretKeySpec(sharedSecret, "AES")
|
||||
val ivSpec = IvParameterSpec(iv)
|
||||
|
||||
var utf8message = msg.toByteArray(Charset.forName("utf-8"))
|
||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec)
|
||||
val encryptedMsg = cipher.doFinal(utf8message)
|
||||
|
||||
val encryptedMsgBech32 = Bech32.encode("pzap", Bech32.eight2five(encryptedMsg), Bech32.Encoding.Bech32)
|
||||
val ivBech32 = Bech32.encode("iv", Bech32.eight2five(iv), Bech32.Encoding.Bech32)
|
||||
|
||||
return encryptedMsgBech32 + "_" + ivBech32
|
||||
}
|
||||
|
||||
fun decryptPrivateZapMessage(msg: String, privkey: ByteArray, pubkey: ByteArray): String {
|
||||
var sharedSecret = Utils.getSharedSecret(privkey, pubkey)
|
||||
if (sharedSecret.size != 16 && sharedSecret.size != 32) {
|
||||
throw IllegalArgumentException("Invalid shared secret size")
|
||||
}
|
||||
val parts = msg.split("_")
|
||||
if (parts.size != 2) {
|
||||
throw IllegalArgumentException("Invalid message format")
|
||||
}
|
||||
val iv = parts[1].run { Bech32.decode(this) }
|
||||
val encryptedMsg = parts.first().run { Bech32.decode(this) }
|
||||
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
|
||||
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(sharedSecret, "AES"), IvParameterSpec(Bech32.five2eight(iv.second, 0)))
|
||||
|
||||
try {
|
||||
val decryptedMsgBytes = cipher.doFinal(Bech32.five2eight(encryptedMsg.second, 0))
|
||||
return String(decryptedMsgBytes)
|
||||
} catch (ex: BadPaddingException) {
|
||||
throw IllegalArgumentException("Bad padding")
|
||||
}
|
||||
}
|
||||
|
||||
fun checkForPrivateZap(zaprequest: Event, loggedInUserPrivKey: ByteArray): Event? {
|
||||
val anonTag = zaprequest.tags.firstOrNull { t -> t.count() >= 2 && t[0] == "anon" }
|
||||
if (anonTag != null && anonTag.size > 1) {
|
||||
val encnote = anonTag?.elementAt(1)
|
||||
if (encnote != null && encnote != "") {
|
||||
try {
|
||||
val note = decryptPrivateZapMessage(encnote, loggedInUserPrivKey, zaprequest.pubKey.toByteArray())
|
||||
val decryptedEvent = fromJson(note)
|
||||
if (decryptedEvent.kind == 9733) {
|
||||
return decryptedEvent
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"pubkey": "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
|
||||
|
||||
@@ -162,16 +162,18 @@ fun ZoomableContentView(content: ZoomableContent, images: List<ZoomableContent>
|
||||
}
|
||||
)
|
||||
|
||||
if (imageState !is AsyncImagePainter.State.Success) {
|
||||
if (content.bluehash != null) {
|
||||
DisplayBlueHash(content, mainImageModifier)
|
||||
} else {
|
||||
DisplayUrlWithLoadingSymbol(content)
|
||||
}
|
||||
} else {
|
||||
if (imageState is AsyncImagePainter.State.Success) {
|
||||
HashVerificationSymbol(verifiedHash, Modifier.align(Alignment.TopEnd))
|
||||
}
|
||||
}
|
||||
|
||||
if (imageState !is AsyncImagePainter.State.Success) {
|
||||
if (content.bluehash != null) {
|
||||
DisplayBlueHash(content, mainImageModifier)
|
||||
} else {
|
||||
DisplayUrlWithLoadingSymbol(content)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VideoView(content.url) { dialogOpen = true }
|
||||
}
|
||||
@@ -183,7 +185,7 @@ fun ZoomableContentView(content: ZoomableContent, images: List<ZoomableContent>
|
||||
|
||||
@Composable
|
||||
private fun DisplayUrlWithLoadingSymbol(content: ZoomableContent) {
|
||||
ClickableUrl(urlText = "$content ", url = content.url)
|
||||
ClickableUrl(urlText = "${content.url} ", url = content.url)
|
||||
|
||||
val myId = "inlineContent"
|
||||
val emptytext = buildAnnotatedString {
|
||||
|
||||
@@ -375,7 +375,7 @@ fun NoteComposeInner(
|
||||
baseNote = replyingDirectlyTo,
|
||||
isQuotedNote = true,
|
||||
modifier = Modifier
|
||||
.padding(0.dp)
|
||||
.padding(top = 5.dp)
|
||||
.fillMaxWidth()
|
||||
.clip(shape = RoundedCornerShape(15.dp))
|
||||
.border(
|
||||
|
||||
@@ -67,6 +67,7 @@ fun ZapCustomDialog(onClose: () -> Unit, account: Account, accountViewModel: Acc
|
||||
|
||||
val zapTypes = listOf(
|
||||
Pair(LnZapEvent.ZapType.PUBLIC, "Public"),
|
||||
Pair(LnZapEvent.ZapType.PRIVATE, "Private"),
|
||||
Pair(LnZapEvent.ZapType.ANONYMOUS, "Anonymous"),
|
||||
Pair(LnZapEvent.ZapType.NONZAP, "Non-Zap")
|
||||
)
|
||||
|
||||
@@ -89,6 +89,8 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
||||
if (zappedPost != null) {
|
||||
val zapRequest = zappedPost.zaps.filter { it.value == zapEvent }.keys.firstOrNull()
|
||||
if (zapRequest != null) {
|
||||
// var newZapRequestEvent = LocalCache.checkPrivateZap(zapRequest.event as Event)
|
||||
// zapRequest.event = newZapRequestEvent
|
||||
zapsPerEvent.getOrPut(zappedPost, { mutableMapOf() }).put(zapRequest, zapEvent)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="236dp"
|
||||
android:height="236dp"
|
||||
android:viewportWidth="236"
|
||||
android:viewportHeight="236">
|
||||
|
||||
<path
|
||||
android:fillColor="#E102C2"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M168,2 C166.799,8.18727,164.947,14.0171,163,20 L173,19 C172.51,13.3852,171.014,6.79588,168,2 M180,142 C184.601,142.041,190.655,144.838,194.96,143.242 C198.824,141.81,201.214,137.39,203.124,134 C210.078,121.662,205.608,109.019,208.529,96 C209.595,91.2476,211.618,86.9521,211.907,82 C212.185,77.2133,210.665,72.7095,210.17,68 C209.701,63.5467,209.857,58.574,205.786,55.608 C201.265,52.3132,197.605,56.5867,197.109,61.0008 C196.625,65.3034,197.297,69.6886,196.896,74 C196.545,77.7718,195.281,81.1715,195.192,85 C195.122,88.0362,193.994,92.9444,190,92.9444 C182.816,92.9444,184.436,81.2708,183.471,77 C181.705,69.1818,178.855,62.145,178.174,54 C177.671,47.9876,179.574,42.0776,178.815,36 C178.301,31.8835,176.341,26.0742,171.957,24.6474 C165.913,22.6804,163.112,29.2432,163.019,34 C162.92,39.1355,164.73,43.9125,164.961,49 C165.331,57.1618,165.938,65.6008,166.06,73.7145 C166.102,76.5167,164.978,79.1797,165.148,82.0008 C165.401,86.2009,171.219,91.7501,168.342,95.6366 C164.867,100.33,159.865,95.1623,157.698,91.9992 C153.406,85.7334,150.568,78.4766,146.637,72.0193 C144.788,68.9835,141.904,66.4794,138.105,67.4529 C127.951,70.0551,136.163,83.457,139.475,88 C148.178,99.9397,155.763,112.385,165.069,124 C170.248,130.463,177.624,133.778,180,142 M201,31 C201.873,37.4822,203,43.4025,203,50 L211,53 C210.634,44.6039,207.808,36.2575,201,31 M134,45 C130.221,51.7137,128.788,59.5176,131,67 C133.684,65.6449,136.047,64.5637,139,64 C138.115,58.0095,136.467,50.4928,134,45 M69,46 C67.7386,52.0951,65.8947,58.0744,64,64 L75,65 C73.0087,58.8781,72.0169,51.6331,69,46 M58,187 C60.1785,179.456,65.298,178.506,69.5756,172.891 C76.4258,163.899,83.8065,155.158,90.3627,146 C93.3233,141.864,95.3809,137.163,98.3634,133 C101.618,128.457,110.219,115.016,99.9452,112.453 C96.1093,111.496,93.2422,113.949,91.3627,117.019 C87.4224,123.456,84.5515,130.765,80.3009,136.999 C78.2049,140.073,73.9249,144.782,70.3727,140.793 C66.7916,136.772,72.5283,131.392,72.8765,127 C73.1057,124.109,72.0273,121.426,71.99,118.576 C71.8412,107.222,73.1025,95.215,74.6998,84 C75.461,78.656,74.6292,66.8531,66.0432,69.6474 C61.6591,71.0742,59.6995,76.8835,59.1852,81 C58.5106,86.3994,60.0712,91.6669,59.6752,97 C59.0126,105.922,56.2059,113.456,54.3897,122 C53.4709,126.322,55.3265,137.793,48,137.793 C43.4396,137.793,42.7212,132.308,42.7153,129 C42.7089,125.453,41.0904,122.469,40.814,119 C40.4715,114.701,41.3203,110.323,40.9414,106.001 C40.5785,101.862,36.9418,97.2305,32.3904,100.032 C28.1086,102.668,28.2839,108.688,27.8302,113 C27.371,117.365,25.9672,121.574,26.054,126 C26.1513,130.962,27.9426,135.298,29.2153,140 C32.8567,153.455,27.7081,166.117,35.0432,179 C37.0472,182.52,39.8521,187.101,44.0008,188.303 C47.9872,189.459,53.7392,187.036,58,187 M36,76 C30.3783,82.2632,27.1802,89.5415,27,98 C29.653,96.7567,32.1579,95.7118,35,95 C35,89.2612,37.5867,81.2251,36,76 M103,90 C102.725,96.2961,100.405,101.927,99,108 C101.839,109.086,104.364,110.488,107,112 C109.117,104.839,108.468,95.4737,103,90 M180.108,151.742 C169.428,156.306,179.297,171.326,188.907,167.141 C201.335,161.729,191.315,146.953,180.108,151.742 M172,170 C172,176.766,171.53,183.278,171,190 C175.401,185.315,179.315,179.294,183,174 C179.113,173.098,175.607,171.693,172,170 M49.0046,196.533 C37.7274,199.326,45.4118,214.867,55,212.412 C61.5523,210.735,65.5024,202.582,59.581,197.603 C56.911,195.359,52.1706,195.749,49.0046,196.533 M65,215 C61.7705,216.818,58.5543,217.97,55,219 C59.1283,224.051,63.1959,229.072,66,235 C67.2105,229.96,67.0167,219.806,65,215 Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="128dp"
|
||||
android:height="128dp"
|
||||
android:viewportWidth="128"
|
||||
android:viewportHeight="128">
|
||||
|
||||
<path
|
||||
android:fillColor="#FF3700B3"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M18,1 C18.9992,13.6607,22.1338,27.7425,34,34.6366 C40.7028,38.5308,48.5179,39.5903,56,41 C54.3404,31.8037,49.5418,30.0009,41,30 L41,27 L48,27 C43.5259,17.4059,36.6076,16,27,16 L27,13 L34,13 C32.6931,11.3029,31.5948,10.0267,31,8 C26.6436,5.68091,22.6182,2.74787,18,1 Z" />
|
||||
<path
|
||||
android:fillColor="#FF6200EE"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M20,1 C23.7028,5.01085,28.4333,6.60192,33,9.37886 C37.2327,11.9527,40.6939,15.5138,45,18 C45,16.2032,45.0143,16.4785,46,15 C49.1978,22.5154,52.8144,28.929,57,36 C58.7383,31.8481,57.6225,27.1823,56.2508,23 C50.9595,6.86786,35.7333,1.01042,20,1 Z" />
|
||||
<path
|
||||
android:fillColor="#818181"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M39,4 L40,5 L39,4 Z" />
|
||||
<path
|
||||
android:fillColor="#35b458"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M30,9 C31.3926,10.4336,32.2328,11.0449,34,12 C31.5819,12.7224,29.5283,12.9481,27,13 L27,16 C36.9436,16,42.0965,18.6193,48,27 L41,27 L41,30 C44.205,30.0025,47.9651,29.5304,50.6713,31.6034 C54.7802,34.7509,55.7328,40.3378,57.0108,45 C60.2954,56.9827,62,69.5839,62,82 C62,87.7274,59.4347,99.821,66,102 C66,95.3343,66.0617,88.6654,66,82 C65.9762,79.4328,65.067,76.5127,65.5556,74 C66.6821,68.2063,71.7932,59.9436,75.0278,55 C76.5417,52.6862,78.2725,50.2574,81,49.3333 C84.7977,48.0467,89.9365,50.9632,91,46 L81,47 C87.2435,39.3331,91.8803,35.0279,102,35 L102,33 L95,33 L99,28 C92.7626,28.2768,88.8779,34.5639,84,38 C83.7893,35.2614,83.6975,34.578,81,34 C81.9074,41.9128,77.8444,45.756,73.5046,52 C70.4878,56.3406,67.7521,61.3024,64,65 C63.9237,55.7794,62.0513,45.3541,58.0193,37 C55.6122,32.0127,52.0583,27.809,49.4151,23 C47.9915,20.4099,47.5242,17.5234,46,15 C45.3152,16.2483,45.2512,16.5484,45,18 C40.5825,14.4148,35.9467,8.78864,30,9 Z" />
|
||||
<path
|
||||
android:fillColor="#818181"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M47,9 L48,10 L47,9 Z" />
|
||||
<path
|
||||
android:fillColor="#FF6200EE"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M70,57 C76.3094,50.934,82.6356,42.9806,81,34 C83.0347,35.2259,83.3265,35.7026,84,38 C90.3127,35.0562,94.6995,29.2957,101,26.0247 C103.882,24.5284,105.934,22.6997,109,24 C109.683,22.494,109.826,21.6852,110,20 C92.9496,20.3519,76.459,26.2355,71.2091,44 C69.9432,48.2837,70.0005,52.5793,70,57 Z" />
|
||||
<path
|
||||
android:fillColor="#818181"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M96,21 L97,22 L96,21 Z" />
|
||||
<path
|
||||
android:fillColor="#FF3700B3"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M98,27 C97.4257,29.3388,96.3153,30.952,95,33 L102,33 L102,35 C91.9916,35.0066,86.152,38.087,81,47 C84.4218,46.9717,87.6368,46.6245,91,46 C88.2508,50.2406,84.2142,47.9848,80.0401,49.6034 C75.8011,51.2471,73.6765,56.1154,72,60 C93.0315,59.0947,111.529,44.7797,109,22 C104.967,22.9474,101.721,25.2426,98,27 Z" />
|
||||
<path
|
||||
android:fillColor="#01ff01"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M23,23 L24,24 L23,23 M85,25 L86,26 L85,25 Z" />
|
||||
<path
|
||||
android:fillColor="#818181"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M72,40 L73,41 L72,40 Z" />
|
||||
<path
|
||||
android:fillColor="#f99721"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M18,127 C24.7416,127,33.546,128.5,40,126.437 C43.9557,125.172,46.9708,122.016,51,120.8 C53.8127,119.952,57.0165,120.515,59.7145,119.397 C66.4359,116.613,70.376,110.812,78,109 C73.2583,102.431,64.8777,99.3157,57,102.667 C53.9866,103.95,51.8253,106.485,49,108.066 C46.1443,109.665,42.7844,109.921,40.0147,111.727 C37.7156,113.226,36.0905,115.611,33.7145,116.977 C27.2551,120.69,22.0281,119.305,18,127 Z" />
|
||||
<path
|
||||
android:fillColor="#857f2d"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M62,101 L63,102 L62,101 Z" />
|
||||
<path
|
||||
android:fillColor="#ffff01"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M52,105 L53,106 L52,105 M75,105 L76,106 L75,105 Z" />
|
||||
<path
|
||||
android:fillColor="#df7f07"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M41,127 L110,127 C105.972,119.305,100.745,120.69,94.2855,116.977 C87.4988,113.076,83.904,107.518,75,109.53 C68.1753,111.072,64.8143,116.981,58.8302,119.397 C51.9278,122.185,46.424,120.458,41,127 Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,7 @@
|
||||
<vector android:height="108dp" android:viewportHeight="216"
|
||||
android:viewportWidth="216" android:width="108dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#000000"
|
||||
android:pathData="M90.2,73.6l-17.2,16.6 0,19.7 0,19.7 3,2.9c1.6,1.6 3.3,2.6 3.6,2.2 0.4,-0.4 1,-4.2 1.5,-8.4 0.9,-9.6 4.5,-25.4 6.9,-30.8 0.5,-1.1 1.9,-4.4 3.1,-7.3 1.9,-4.6 2.4,-5.2 4.3,-4.5 1.1,0.5 5.5,0.7 9.6,0.5 10.8,-0.3 13.7,0.3 15.5,3.8 0.8,1.6 1.5,5 1.5,7.5 0,6.1 1,7.7 7,11.4 8,4.9 5.6,8.7 -4.4,6.8 -3.9,-0.7 -6.2,-0.5 -9.6,0.6 -2.5,0.9 -5.8,1.8 -7.3,2.2 -4.4,0.9 -5.7,5.3 -5.7,19.8 0,6.8 -0.5,13.9 -1.1,15.7 -1.1,3 -1,3.4 2.9,7.3l4.1,4.1 5.8,-5.4c3.2,-3 11.3,-10.7 18.1,-17.2l12.2,-11.9 0,-18.9 0,-19 -13.2,-12.8c-14.2,-13.7 -22.3,-21.2 -22.9,-21.2 -0.2,-0 -8.2,7.5 -17.7,16.6z" android:strokeColor="#00000000"/>
|
||||
<path android:fillColor="#000000"
|
||||
android:pathData="M111,91.5c0,3.1 2.6,4.3 4.6,2.3 2,-2 0.7,-4.8 -2.2,-4.8 -1.9,-0 -2.4,0.5 -2.4,2.5z" android:strokeColor="#00000000"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,35 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="192.62"
|
||||
android:viewportHeight="288.93">
|
||||
<group android:scaleX="0.33333334"
|
||||
android:scaleY="0.5"
|
||||
android:translateX="64.206665"
|
||||
android:translateY="72.2325">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="m111.18,103.42c-4.68,-0 -8.47,-3.8 -8.47,-8.48 0,-4.68 3.79,-8.48 8.47,-8.48 4.68,-0 8.48,3.8 8.48,8.48 0,4.68 -3.79,8.48 -8.48,8.48zM96.31,-0 L0,91.3L0,197.63l19.9,18.86c0.63,-43.4 14.08,-106.43 37.41,-146.62 0,-0 6.05,5.23 16.74,5.93 11.02,0.73 36.71,-4.37 48.32,0.36 10.87,4.43 11.66,17.34 10.79,27.84 -1.66,20.02 8.14,25.99 25.54,34.66 8.67,4.32 10.67,9.28 7.87,14.44 -3.09,5.68 -17.49,3.05 -33.55,1.1 -17.16,-2.08 -26.79,9.45 -43.37,8.39 -23.4,30.62 -0.84,73.09 -16.14,104.73l22.81,21.62 96.31,-91.31l0,-106.32z"/>
|
||||
<path
|
||||
android:pathData="m111.18,103.42c-4.68,-0 -8.47,-3.8 -8.47,-8.48 0,-4.68 3.79,-8.48 8.47,-8.48 4.68,-0 8.48,3.8 8.48,8.48 0,4.68 -3.79,8.48 -8.48,8.48zM96.31,-0 L0,91.3L0,197.63l19.9,18.86c0.63,-43.4 14.08,-106.43 37.41,-146.62 0,-0 6.05,5.23 16.74,5.93 11.02,0.73 36.71,-4.37 48.32,0.36 10.87,4.43 11.66,17.34 10.79,27.84 -1.66,20.02 8.14,25.99 25.54,34.66 8.67,4.32 10.67,9.28 7.87,14.44 -3.09,5.68 -17.49,3.05 -33.55,1.1 -17.16,-2.08 -26.79,9.45 -43.37,8.39 -23.4,30.62 -0.84,73.09 -16.14,104.73L96.31,288.93 192.62,197.63L192.62,91.3L96.31,-0"
|
||||
android:strokeWidth="0.04"
|
||||
android:strokeColor="#00000000"
|
||||
android:fillType="nonZero">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startX="33.75"
|
||||
android:startY="252.82"
|
||||
android:endX="158.87"
|
||||
android:endY="36.12"
|
||||
android:tileMode="clamp"
|
||||
android:type="linear">
|
||||
<item android:offset="0" android:color="#FF550066"/>
|
||||
<item android:offset="0" android:color="#FF550066"/>
|
||||
<item android:offset="1" android:color="#FFA75CCC"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@drawable/amethyst_monochrome"/>
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#FFFFFF</color>
|
||||
</resources>
|
||||