diff --git a/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Github.kt b/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Github.kt new file mode 100644 index 000000000..667f7f8c8 --- /dev/null +++ b/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Github.kt @@ -0,0 +1,135 @@ +package dev.sasikanth.rss.reader.resources.icons + +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.EvenOdd +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.StrokeCap.Companion.Butt +import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.unit.dp + +val TwineIcons.GitHub: ImageVector + get() { + if (github != null) { + return github!! + } + github = + Builder( + name = "Github", + defaultWidth = 20.0.dp, + defaultHeight = 20.0.dp, + viewportWidth = 20.0f, + viewportHeight = 20.0f + ) + .apply { + path( + fill = SolidColor(Color(0xFF000000)), + stroke = null, + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = EvenOdd + ) { + moveTo(8.6786f, 1.9716f) + curveTo(10.4173f, 1.5589f, 12.2286f, 1.5589f, 13.9673f, 1.9716f) + curveTo(14.968f, 1.3384f, 15.7396f, 1.0427f, 16.3086f, 0.9164f) + curveTo(16.6217f, 0.8469f, 16.8724f, 0.8289f, 17.0637f, 0.8342f) + curveTo(17.1592f, 0.8368f, 17.2389f, 0.8452f, 17.3034f, 0.8555f) + curveTo(17.3355f, 0.8606f, 17.3637f, 0.8662f, 17.388f, 0.8717f) + curveTo(17.4002f, 0.8745f, 17.4113f, 0.8772f, 17.4215f, 0.8799f) + lineTo(17.436f, 0.8838f) + lineTo(17.4427f, 0.8857f) + lineTo(17.4459f, 0.8866f) + lineTo(17.4474f, 0.8871f) + curveTo(17.4482f, 0.8873f, 17.449f, 0.8875f, 17.2226f, 1.6508f) + lineTo(17.449f, 0.8875f) + curveTo(17.6759f, 0.9548f, 17.8611f, 1.1196f, 17.9544f, 1.3372f) + curveTo(18.3811f, 2.3327f, 18.4592f, 3.4382f, 18.1846f, 4.4766f) + curveTo(18.5056f, 4.9066f, 18.7505f, 5.3965f, 18.9249f, 5.8646f) + curveTo(19.1515f, 6.473f, 19.2847f, 7.1138f, 19.2847f, 7.6381f) + curveTo(19.2847f, 9.9838f, 18.5671f, 11.5571f, 17.3747f, 12.5597f) + curveTo(16.5735f, 13.2334f, 15.6164f, 13.5977f, 14.6727f, 13.8057f) + curveTo(14.6849f, 13.8369f, 14.6968f, 13.8683f, 14.7082f, 13.8999f) + curveTo(14.8717f, 14.3541f, 14.939f, 14.8372f, 14.9057f, 15.3185f) + verticalLineTo(18.3705f) + curveTo(14.9057f, 18.8102f, 14.5493f, 19.1667f, 14.1095f, 19.1667f) + curveTo(13.6698f, 19.1667f, 13.3134f, 18.8102f, 13.3134f, 18.3705f) + verticalLineTo(15.2893f) + curveTo(13.3134f, 15.2685f, 13.3142f, 15.2476f, 13.3158f, 15.2269f) + curveTo(13.3368f, 14.9599f, 13.3008f, 14.6915f, 13.21f, 14.4395f) + curveTo(13.1193f, 14.1875f, 12.9759f, 13.9577f, 12.7895f, 13.7655f) + curveTo(12.5781f, 13.5474f, 12.5091f, 13.2279f, 12.6119f, 12.9421f) + curveTo(12.7146f, 12.6562f, 12.971f, 12.4537f, 13.2729f, 12.42f) + curveTo(14.4782f, 12.2857f, 15.5649f, 12.001f, 16.3499f, 11.341f) + curveTo(17.0962f, 10.7134f, 17.6923f, 9.6394f, 17.6923f, 7.6381f) + curveTo(17.6923f, 7.3502f, 17.6116f, 6.9007f, 17.4327f, 6.4205f) + curveTo(17.2546f, 5.9424f, 17.0047f, 5.503f, 16.7176f, 5.2014f) + curveTo(16.5075f, 4.9807f, 16.4418f, 4.6595f, 16.5483f, 4.374f) + curveTo(16.7771f, 3.761f, 16.8135f, 3.0972f, 16.6597f, 2.4696f) + curveTo(16.6577f, 2.47f, 16.6557f, 2.4704f, 16.6537f, 2.4709f) + curveTo(16.2654f, 2.5571f, 15.578f, 2.8033f, 14.5529f, 3.4905f) + curveTo(14.3614f, 3.6188f, 14.1237f, 3.6579f, 13.9013f, 3.5976f) + curveTo(12.2128f, 3.14f, 10.433f, 3.14f, 8.7446f, 3.5976f) + curveTo(8.5221f, 3.6579f, 8.2845f, 3.6188f, 8.093f, 3.4905f) + curveTo(7.0679f, 2.8033f, 6.3805f, 2.5571f, 5.9922f, 2.4709f) + curveTo(5.9902f, 2.4704f, 5.9882f, 2.47f, 5.9862f, 2.4696f) + curveTo(5.8323f, 3.0972f, 5.8688f, 3.761f, 6.0975f, 4.374f) + curveTo(6.2041f, 4.6595f, 6.1384f, 4.9807f, 5.9283f, 5.2014f) + curveTo(5.6382f, 5.5061f, 5.3887f, 5.9453f, 5.2117f, 6.4239f) + curveTo(5.0342f, 6.9039f, 4.9535f, 7.359f, 4.9535f, 7.662f) + curveTo(4.9535f, 9.6448f, 5.5481f, 10.7121f, 6.296f, 11.341f) + curveTo(7.0838f, 12.0034f, 8.1736f, 12.2949f, 9.3829f, 12.4451f) + curveTo(9.6824f, 12.4823f, 9.9352f, 12.6857f, 10.0356f, 12.9703f) + curveTo(10.136f, 13.255f, 10.0668f, 13.5719f, 9.8569f, 13.7888f) + curveTo(9.6727f, 13.9792f, 9.5306f, 14.2062f, 9.4399f, 14.4551f) + curveTo(9.3492f, 14.704f, 9.312f, 14.9692f, 9.3305f, 15.2334f) + curveTo(9.3319f, 15.252f, 9.3325f, 15.2707f, 9.3325f, 15.2893f) + verticalLineTo(18.3705f) + curveTo(9.3325f, 18.8102f, 8.976f, 19.1667f, 8.5363f, 19.1667f) + curveTo(8.0966f, 19.1667f, 7.7401f, 18.8102f, 7.7401f, 18.3705f) + verticalLineTo(16.9806f) + curveTo(7.0983f, 17.0788f, 6.5335f, 17.0619f, 6.0286f, 16.9438f) + curveTo(5.2604f, 16.764f, 4.7119f, 16.3686f, 4.291f, 15.9478f) + curveTo(4.0851f, 15.7419f, 3.9077f, 15.5278f, 3.7544f, 15.3357f) + curveTo(3.7023f, 15.2705f, 3.6547f, 15.21f, 3.6098f, 15.1529f) + curveTo(3.5139f, 15.0312f, 3.4299f, 14.9246f, 3.3398f, 14.8188f) + curveTo(3.0786f, 14.5122f, 2.9166f, 14.4025f, 2.77f, 14.3658f) + curveTo(2.3434f, 14.2592f, 2.0841f, 13.8269f, 2.1907f, 13.4003f) + curveTo(2.2973f, 12.9738f, 2.7296f, 12.7144f, 3.1562f, 12.821f) + curveTo(3.8058f, 12.9834f, 4.2409f, 13.4211f, 4.552f, 13.7862f) + curveTo(4.6627f, 13.9163f, 4.7772f, 14.0615f, 4.8819f, 14.1945f) + curveTo(4.9226f, 14.2461f, 4.9619f, 14.2959f, 4.9988f, 14.3423f) + curveTo(5.141f, 14.5203f, 5.2746f, 14.6794f, 5.417f, 14.8218f) + curveTo(5.6929f, 15.0977f, 5.9902f, 15.2994f, 6.3914f, 15.3933f) + curveTo(6.7101f, 15.4679f, 7.1416f, 15.4854f, 7.7401f, 15.3635f) + verticalLineTo(15.3154f) + curveTo(7.7107f, 14.838f, 7.78f, 14.3596f, 7.9438f, 13.91f) + curveTo(7.9549f, 13.8793f, 7.9665f, 13.8488f, 7.9786f, 13.8185f) + curveTo(7.0335f, 13.603f, 6.0738f, 13.2346f, 5.2712f, 12.5597f) + curveTo(4.0803f, 11.5584f, 3.3612f, 9.9943f, 3.3612f, 7.662f) + curveTo(3.3612f, 7.1289f, 3.4915f, 6.4847f, 3.7182f, 5.8717f) + curveTo(3.8926f, 5.3998f, 4.1382f, 4.9083f, 4.4612f, 4.4762f) + curveTo(4.1867f, 3.4379f, 4.2649f, 2.3326f, 4.6915f, 1.3372f) + curveTo(4.7847f, 1.1196f, 4.97f, 0.9548f, 5.1969f, 0.8875f) + lineTo(5.4233f, 1.6508f) + curveTo(5.1969f, 0.8875f, 5.1976f, 0.8873f, 5.1984f, 0.8871f) + lineTo(5.2f, 0.8866f) + lineTo(5.2032f, 0.8857f) + lineTo(5.2099f, 0.8838f) + lineTo(5.2244f, 0.8799f) + curveTo(5.2345f, 0.8772f, 5.2457f, 0.8745f, 5.2578f, 0.8717f) + curveTo(5.2821f, 0.8662f, 5.3103f, 0.8606f, 5.3425f, 0.8555f) + curveTo(5.4069f, 0.8452f, 5.4867f, 0.8368f, 5.5821f, 0.8342f) + curveTo(5.7735f, 0.8289f, 6.0242f, 0.8469f, 6.3373f, 0.9164f) + curveTo(6.9063f, 1.0427f, 7.6779f, 1.3384f, 8.6786f, 1.9716f) + close() + } + } + .build() + return github!! + } + +private var github: ImageVector? = null diff --git a/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Threads.kt b/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Threads.kt new file mode 100644 index 000000000..06ef3f049 --- /dev/null +++ b/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Threads.kt @@ -0,0 +1,89 @@ +package dev.sasikanth.rss.reader.resources.icons + +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.NonZero +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.StrokeCap.Companion.Butt +import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.unit.dp + +val TwineIcons.Threads: ImageVector + get() { + if (threads != null) { + return threads!! + } + threads = + Builder( + name = "Threads", + defaultWidth = 20.0.dp, + defaultHeight = 20.0.dp, + viewportWidth = 20.0f, + viewportHeight = 20.0f + ) + .apply { + path( + fill = SolidColor(Color(0xFF000000)), + stroke = null, + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(14.8568f, 9.3305f) + curveTo(14.7778f, 9.2926f, 14.6976f, 9.2562f, 14.6163f, 9.2213f) + curveTo(14.4748f, 6.6139f, 13.0501f, 5.1211f, 10.6577f, 5.1059f) + curveTo(10.6469f, 5.1058f, 10.6361f, 5.1058f, 10.6253f, 5.1058f) + curveTo(9.1944f, 5.1058f, 8.0043f, 5.7166f, 7.2718f, 6.828f) + lineTo(8.5875f, 7.7306f) + curveTo(9.1347f, 6.9004f, 9.9935f, 6.7234f, 10.6259f, 6.7234f) + curveTo(10.6332f, 6.7234f, 10.6406f, 6.7234f, 10.6478f, 6.7234f) + curveTo(11.4355f, 6.7285f, 12.0299f, 6.9575f, 12.4146f, 7.4041f) + curveTo(12.6946f, 7.7293f, 12.8818f, 8.1786f, 12.9745f, 8.7457f) + curveTo(12.2761f, 8.627f, 11.5208f, 8.5905f, 10.7134f, 8.6368f) + curveTo(8.4389f, 8.7678f, 6.9767f, 10.0943f, 7.0749f, 11.9376f) + curveTo(7.1247f, 12.8726f, 7.5905f, 13.677f, 8.3864f, 14.2024f) + curveTo(9.0594f, 14.6466f, 9.926f, 14.8639f, 10.8268f, 14.8147f) + curveTo(12.0163f, 14.7495f, 12.9495f, 14.2956f, 13.6005f, 13.4658f) + curveTo(14.095f, 12.8356f, 14.4077f, 12.0189f, 14.5458f, 10.9898f) + curveTo(15.1127f, 11.3319f, 15.5328f, 11.7821f, 15.7648f, 12.3234f) + curveTo(16.1594f, 13.2434f, 16.1824f, 14.7552f, 14.9488f, 15.9877f) + curveTo(13.868f, 17.0675f, 12.5688f, 17.5346f, 10.6054f, 17.549f) + curveTo(8.4274f, 17.5329f, 6.7802f, 16.8344f, 5.7093f, 15.473f) + curveTo(4.7064f, 14.1981f, 4.1881f, 12.3568f, 4.1688f, 10.0f) + curveTo(4.1881f, 7.6432f, 4.7064f, 5.8018f, 5.7093f, 4.527f) + curveTo(6.7802f, 3.1656f, 8.4274f, 2.4671f, 10.6053f, 2.4509f) + curveTo(12.7991f, 2.4672f, 14.475f, 3.169f, 15.5869f, 4.537f) + curveTo(16.1322f, 5.2079f, 16.5432f, 6.0515f, 16.8142f, 7.0352f) + lineTo(18.356f, 6.6238f) + curveTo(18.0276f, 5.4131f, 17.5107f, 4.3697f, 16.8073f, 3.5045f) + curveTo(15.3818f, 1.7506f, 13.297f, 0.852f, 10.6107f, 0.8333f) + horizontalLineTo(10.6f) + curveTo(7.9192f, 0.8519f, 5.8577f, 1.754f, 4.4728f, 3.5145f) + curveTo(3.2404f, 5.0812f, 2.6047f, 7.261f, 2.5833f, 9.9936f) + lineTo(2.5833f, 10.0f) + lineTo(2.5833f, 10.0064f) + curveTo(2.6047f, 12.7389f, 3.2404f, 14.9189f, 4.4728f, 16.4855f) + curveTo(5.8577f, 18.246f, 7.9192f, 19.1481f, 10.6f, 19.1667f) + horizontalLineTo(10.6107f) + curveTo(12.9941f, 19.1501f, 14.6741f, 18.5261f, 16.0581f, 17.1434f) + curveTo(17.8688f, 15.3344f, 17.8142f, 13.0669f, 17.2175f, 11.6749f) + curveTo(16.7893f, 10.6767f, 15.973f, 9.8659f, 14.8568f, 9.3305f) + close() + moveTo(10.7416f, 13.1994f) + curveTo(9.7448f, 13.2556f, 8.7091f, 12.8081f, 8.658f, 11.8498f) + curveTo(8.6202f, 11.1391f, 9.1637f, 10.3462f, 10.8028f, 10.2518f) + curveTo(10.9905f, 10.2409f, 11.1747f, 10.2357f, 11.3557f, 10.2357f) + curveTo(11.951f, 10.2357f, 12.508f, 10.2935f, 13.0143f, 10.4042f) + curveTo(12.8255f, 12.7629f, 11.7176f, 13.1459f, 10.7416f, 13.1994f) + close() + } + } + .build() + return threads!! + } + +private var threads: ImageVector? = null diff --git a/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Twitter.kt b/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Twitter.kt new file mode 100644 index 000000000..7f242bf00 --- /dev/null +++ b/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Twitter.kt @@ -0,0 +1,62 @@ +package dev.sasikanth.rss.reader.resources.icons + +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.NonZero +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.StrokeCap.Companion.Butt +import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.unit.dp + +val TwineIcons.Twitter: ImageVector + get() { + if (twitter != null) { + return twitter!! + } + twitter = + Builder( + name = "Twitter", + defaultWidth = 20.0.dp, + defaultHeight = 20.0.dp, + viewportWidth = 20.0f, + viewportHeight = 20.0f + ) + .apply { + path( + fill = SolidColor(Color(0xFF000000)), + stroke = null, + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(14.7673f, 2.5f) + horizontalLineTo(17.3129f) + lineTo(11.7528f, 8.8534f) + lineTo(18.2937f, 17.5f) + horizontalLineTo(13.1735f) + lineTo(9.1603f, 12.2572f) + lineTo(4.5738f, 17.5f) + horizontalLineTo(2.0245f) + lineTo(7.9704f, 10.7031f) + lineTo(1.6999f, 2.5f) + horizontalLineTo(6.95f) + lineTo(10.5737f, 7.2921f) + lineTo(14.7673f, 2.5f) + close() + moveTo(13.873f, 15.9784f) + horizontalLineTo(15.2829f) + lineTo(6.1819f, 3.9423f) + horizontalLineTo(4.6675f) + lineTo(13.873f, 15.9784f) + close() + } + } + .build() + return twitter!! + } + +private var twitter: ImageVector? = null diff --git a/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Website.kt b/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Website.kt new file mode 100644 index 000000000..21a93f272 --- /dev/null +++ b/resources/icons/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/icons/Website.kt @@ -0,0 +1,96 @@ +package dev.sasikanth.rss.reader.resources.icons + +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.EvenOdd +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.StrokeCap.Companion.Butt +import androidx.compose.ui.graphics.StrokeJoin.Companion.Miter +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.unit.dp + +val TwineIcons.Website: ImageVector + get() { + if (website != null) { + return website!! + } + website = + Builder( + name = "Website", + defaultWidth = 20.0.dp, + defaultHeight = 20.0.dp, + viewportWidth = 20.0f, + viewportHeight = 20.0f + ) + .apply { + path( + fill = SolidColor(Color(0xFF000000)), + stroke = null, + strokeLineWidth = 0.0f, + strokeLineCap = Butt, + strokeLineJoin = Miter, + strokeLineMiter = 4.0f, + pathFillType = EvenOdd + ) { + moveTo(18.3334f, 10.0f) + curveTo(18.3334f, 14.6024f, 14.6025f, 18.3333f, 10.0001f, 18.3333f) + curveTo(5.3977f, 18.3333f, 1.6667f, 14.6024f, 1.6667f, 10.0f) + curveTo(1.6667f, 5.3976f, 5.3977f, 1.6667f, 10.0001f, 1.6667f) + curveTo(14.6025f, 1.6667f, 18.3334f, 5.3976f, 18.3334f, 10.0f) + close() + moveTo(10.0001f, 16.6667f) + curveTo(10.0f, 16.6667f, 10.0001f, 16.6667f, 10.0001f, 16.6667f) + curveTo(6.3182f, 16.6667f, 3.3334f, 13.6819f, 3.3334f, 10.0f) + curveTo(3.3334f, 9.7335f, 3.3491f, 9.4707f, 3.3795f, 9.2124f) + lineTo(8.3336f, 14.1665f) + verticalLineTo(14.9998f) + curveTo(8.3336f, 15.4601f, 8.7067f, 15.8332f, 9.1669f, 15.8332f) + horizontalLineTo(10.0002f) + lineTo(10.0001f, 16.6667f) + close() + moveTo(11.667f, 16.4566f) + verticalLineTo(14.9998f) + curveTo(11.667f, 14.5396f, 11.2939f, 14.1665f, 10.8336f, 14.1665f) + horizontalLineTo(10.0002f) + verticalLineTo(13.4761f) + lineTo(9.0238f, 12.4997f) + lineTo(12.5002f, 12.4998f) + verticalLineTo(13.3332f) + curveTo(12.5002f, 13.7934f, 12.8733f, 14.1665f, 13.3336f, 14.1665f) + horizontalLineTo(15.2047f) + curveTo(14.317f, 15.274f, 13.083f, 16.0921f, 11.667f, 16.4566f) + close() + moveTo(16.1822f, 12.4998f) + horizontalLineTo(14.1669f) + verticalLineTo(11.6665f) + curveTo(14.1669f, 11.2062f, 13.7938f, 10.8331f, 13.3336f, 10.8331f) + lineTo(6.6668f, 10.833f) + verticalLineTo(9.1665f) + horizontalLineTo(9.167f) + curveTo(9.6272f, 9.1665f, 10.0003f, 8.7934f, 10.0003f, 8.3331f) + verticalLineTo(6.6665f) + horizontalLineTo(10.8334f) + curveTo(11.7539f, 6.6665f, 12.5001f, 5.9203f, 12.5001f, 4.9998f) + verticalLineTo(3.8179f) + curveTo(14.9433f, 4.8069f, 16.6667f, 7.2022f, 16.6667f, 10.0f) + curveTo(16.6667f, 10.884f, 16.4947f, 11.7278f, 16.1822f, 12.4998f) + close() + moveTo(10.8334f, 3.3849f) + verticalLineTo(4.9998f) + horizontalLineTo(9.167f) + curveTo(8.7067f, 4.9998f, 8.3336f, 5.3729f, 8.3336f, 5.8331f) + verticalLineTo(7.4998f) + horizontalLineTo(5.9763f) + curveTo(5.4372f, 7.4998f, 5.0001f, 7.9369f, 5.0001f, 8.476f) + lineTo(3.8788f, 7.3547f) + curveTo(4.9027f, 4.9888f, 7.258f, 3.3333f, 10.0001f, 3.3333f) + curveTo(10.2823f, 3.3333f, 10.5604f, 3.3509f, 10.8334f, 3.3849f) + close() + } + } + .build() + return website!! + } + +private var website: ImageVector? = null diff --git a/resources/strings/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/strings/EnTwineStrings.kt b/resources/strings/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/strings/EnTwineStrings.kt index 0b8178fad..81369530d 100644 --- a/resources/strings/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/strings/EnTwineStrings.kt +++ b/resources/strings/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/strings/EnTwineStrings.kt @@ -67,5 +67,12 @@ val EnTwineStrings = settingsAboutSubtitle = "Get to know the authors", feeds = "Feeds", editFeeds = "Edit feeds", - comments = "Comments" + comments = "Comments", + about = "About", + aboutRoleDeveloper = "Developer", + aboutRoleDesigner = "Designer", + aboutSocialTwitter = "Twitter", + aboutSocialThreads = "Threads", + aboutSocialGitHub = "GitHub", + aboutSocialWebsite = "Website", ) diff --git a/resources/strings/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/strings/TwineStrings.kt b/resources/strings/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/strings/TwineStrings.kt index 1cdee9285..21b30c2e9 100644 --- a/resources/strings/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/strings/TwineStrings.kt +++ b/resources/strings/src/commonMain/kotlin/dev/sasikanth/rss/reader/resources/strings/TwineStrings.kt @@ -60,7 +60,18 @@ data class TwineStrings( val settingsAboutSubtitle: String, val feeds: String, val editFeeds: String, - val comments: String + val comments: String, + val about: String, + val aboutRoleDeveloper: String, + val aboutRoleDesigner: String, + // don't translate + val aboutSocialTwitter: String, + // don't translate + val aboutSocialThreads: String, + // don't translate + val aboutSocialGitHub: String, + // don't translate + val aboutSocialWebsite: String, ) object Locales { diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/AboutEvent.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/AboutEvent.kt new file mode 100644 index 000000000..7481c4a9a --- /dev/null +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/AboutEvent.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2023 Sasikanth Miriyampalli + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dev.sasikanth.rss.reader.about + +sealed interface AboutEvent { + object BackClicked : AboutEvent +} diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/AboutPresenter.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/AboutPresenter.kt new file mode 100644 index 000000000..382f6776c --- /dev/null +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/AboutPresenter.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Sasikanth Miriyampalli + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dev.sasikanth.rss.reader.about + +import com.arkivanov.decompose.ComponentContext +import me.tatarka.inject.annotations.Assisted +import me.tatarka.inject.annotations.Inject + +@Inject +class AboutPresenter( + @Assisted componentContext: ComponentContext, + @Assisted private val goBack: () -> Unit +) : ComponentContext by componentContext { + + fun dispatch(event: AboutEvent) { + when (event) { + AboutEvent.BackClicked -> goBack() + } + } +} diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/Person.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/Person.kt new file mode 100644 index 000000000..1106c0c2b --- /dev/null +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/Person.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Sasikanth Miriyampalli + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dev.sasikanth.rss.reader.about + +import androidx.compose.ui.graphics.vector.ImageVector + +internal data class Person( + val name: String, + val role: String, + val profilePicture: String, + val socials: List +) + +internal data class Social(val service: String, val link: String, val icon: ImageVector) diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/ui/AboutScreen.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/ui/AboutScreen.kt new file mode 100644 index 000000000..450ee8eb7 --- /dev/null +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/about/ui/AboutScreen.kt @@ -0,0 +1,253 @@ +/* + * Copyright 2023 Sasikanth Miriyampalli + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dev.sasikanth.rss.reader.about.ui + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowBack +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.Divider +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.unit.dp +import dev.sasikanth.rss.reader.about.AboutEvent +import dev.sasikanth.rss.reader.about.AboutPresenter +import dev.sasikanth.rss.reader.about.Person +import dev.sasikanth.rss.reader.about.Social +import dev.sasikanth.rss.reader.components.bottomsheet.fastForEach +import dev.sasikanth.rss.reader.components.image.AsyncImage +import dev.sasikanth.rss.reader.platform.LocalLinkHandler +import dev.sasikanth.rss.reader.resources.icons.GitHub +import dev.sasikanth.rss.reader.resources.icons.Threads +import dev.sasikanth.rss.reader.resources.icons.TwineIcons +import dev.sasikanth.rss.reader.resources.icons.Twitter +import dev.sasikanth.rss.reader.resources.icons.Website +import dev.sasikanth.rss.reader.resources.strings.LocalStrings +import dev.sasikanth.rss.reader.ui.AppTheme +import dev.sasikanth.rss.reader.utils.Constants +import kotlinx.coroutines.launch + +@Composable +internal fun AboutScreen(aboutPresenter: AboutPresenter, modifier: Modifier = Modifier) { + val layoutDirection = LocalLayoutDirection.current + val strings = LocalStrings.current + val persons: List = remember { + listOf( + Person( + name = Constants.ABOUT_SASI_NAME, + role = strings.aboutRoleDeveloper, + profilePicture = Constants.ABOUT_SASI_PIC, + socials = + listOf( + Social( + service = strings.aboutSocialThreads, + link = Constants.ABOUT_SASI_THREADS, + icon = TwineIcons.Threads + ), + Social( + service = strings.aboutSocialTwitter, + link = Constants.ABOUT_SASI_TWITTER, + icon = TwineIcons.Twitter + ), + Social( + service = strings.aboutSocialGitHub, + link = Constants.ABOUT_SASI_GITHUB, + icon = TwineIcons.GitHub + ), + Social( + service = strings.aboutSocialWebsite, + link = Constants.ABOUT_SASI_WEBSITE, + icon = TwineIcons.Website + ), + ) + ), + Person( + name = Constants.ABOUT_ED_NAME, + role = strings.aboutRoleDesigner, + profilePicture = Constants.ABOUT_ED_PIC, + socials = + listOf( + Social( + service = strings.aboutSocialThreads, + link = Constants.ABOUT_ED_THREADS, + icon = TwineIcons.Threads + ), + Social( + service = strings.aboutSocialTwitter, + link = Constants.ABOUT_ED_TWITTER, + icon = TwineIcons.Twitter + ), + ) + ), + ) + } + + Scaffold( + modifier = modifier, + topBar = { + Box { + CenterAlignedTopAppBar( + title = { Text(strings.about) }, + navigationIcon = { + IconButton(onClick = { aboutPresenter.dispatch(AboutEvent.BackClicked) }) { + Icon(Icons.Rounded.ArrowBack, contentDescription = null) + } + }, + colors = + TopAppBarDefaults.topAppBarColors( + containerColor = AppTheme.colorScheme.surface, + navigationIconContentColor = AppTheme.colorScheme.onSurface, + titleContentColor = AppTheme.colorScheme.onSurface, + actionIconContentColor = AppTheme.colorScheme.onSurface + ), + ) + + Divider( + modifier = Modifier.fillMaxWidth().align(Alignment.BottomStart), + color = AppTheme.colorScheme.surfaceContainer + ) + } + }, + content = { padding -> + Box(modifier = Modifier.fillMaxSize()) { + LazyColumn( + contentPadding = + PaddingValues( + start = padding.calculateStartPadding(layoutDirection), + top = padding.calculateTopPadding() + 8.dp, + end = padding.calculateEndPadding(layoutDirection), + bottom = padding.calculateBottomPadding() + 80.dp + ), + ) { + items(persons) { person -> AboutListItem(person) } + } + } + }, + containerColor = AppTheme.colorScheme.surfaceContainerLowest, + contentColor = Color.Unspecified, + ) +} + +@OptIn(ExperimentalLayoutApi::class) +@Composable +private fun AboutListItem(person: Person, modifier: Modifier = Modifier) { + val coroutineScope = rememberCoroutineScope() + Box(modifier = modifier) { + Box(modifier = Modifier.padding(start = 8.dp, top = 32.dp, end = 8.dp, bottom = 24.dp)) { + Column(modifier = Modifier.fillMaxWidth()) { + Row(modifier = Modifier.padding(horizontal = 16.dp)) { + Column(modifier = Modifier.weight(1f)) { + Text( + person.role, + style = MaterialTheme.typography.bodyMedium, + color = AppTheme.colorScheme.onSurfaceVariant + ) + Spacer(Modifier.height(8.dp)) + Text( + person.name, + style = MaterialTheme.typography.titleLarge, + color = AppTheme.colorScheme.onSurface + ) + } + Spacer(Modifier.width(16.dp)) + AsyncImage( + url = person.profilePicture, + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.requiredSize(56.dp).clip(CircleShape), + ) + } + + Spacer(Modifier.height(24.dp)) + + FlowRow { + val linkHandler = LocalLinkHandler.current + person.socials.fastForEach { social -> + SocialButton( + social = social, + onClick = { coroutineScope.launch { linkHandler.openLink(social.link) } } + ) + } + } + } + } + + Divider( + color = AppTheme.colorScheme.surfaceContainer, + modifier = Modifier.align(Alignment.BottomStart) + ) + } +} + +@Composable +private fun SocialButton( + social: Social, + modifier: Modifier = Modifier, + onClick: () -> Unit, +) { + Column( + modifier = + modifier + .clip(MaterialTheme.shapes.large) + .clickable(onClick = onClick) + .padding(horizontal = 16.dp, vertical = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Icon( + imageVector = social.icon, + contentDescription = null, + tint = AppTheme.colorScheme.tintedForeground + ) + Spacer(Modifier.height(4.dp)) + Text( + social.service, + style = MaterialTheme.typography.labelMedium, + color = AppTheme.colorScheme.tintedForeground + ) + } +} diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/App.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/App.kt index d7bd5f038..37dc010d9 100644 --- a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/App.kt +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/App.kt @@ -25,6 +25,7 @@ import androidx.compose.ui.Modifier import com.arkivanov.decompose.extensions.compose.jetbrains.stack.Children import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.StackAnimation import com.arkivanov.essenty.backhandler.BackHandler +import dev.sasikanth.rss.reader.about.ui.AboutScreen import dev.sasikanth.rss.reader.bookmarks.ui.BookmarksScreen import dev.sasikanth.rss.reader.components.DynamicContentTheme import dev.sasikanth.rss.reader.components.LocalDynamicColorState @@ -87,6 +88,9 @@ fun App( is Screen.Settings -> { SettingsScreen(settingsPresenter = screen.presenter, modifier = fillMaxSizeModifier) } + is Screen.About -> { + AboutScreen(aboutPresenter = screen.presenter, modifier = fillMaxSizeModifier) + } } } } diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/AppPresenter.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/AppPresenter.kt index bae953987..761504fdb 100644 --- a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/AppPresenter.kt +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/AppPresenter.kt @@ -27,6 +27,7 @@ import com.arkivanov.essenty.instancekeeper.getOrCreate import com.arkivanov.essenty.lifecycle.doOnStart import com.arkivanov.essenty.parcelable.Parcelable import com.arkivanov.essenty.parcelable.Parcelize +import dev.sasikanth.rss.reader.about.AboutPresenter import dev.sasikanth.rss.reader.bookmarks.BookmarksPresenter import dev.sasikanth.rss.reader.di.scopes.ActivityScope import dev.sasikanth.rss.reader.home.HomePresenter @@ -62,8 +63,15 @@ private typealias SettingsPresenterFactory = ( ComponentContext, goBack: () -> Unit, + openAbout: () -> Unit, ) -> SettingsPresenter +private typealias AboutPresenterFactory = + ( + ComponentContext, + goBack: () -> Unit, + ) -> AboutPresenter + @Inject @ActivityScope class AppPresenter( @@ -73,6 +81,7 @@ class AppPresenter( private val searchPresenter: SearchPresentFactory, private val bookmarksPresenter: BookmarkPresenterFactory, private val settingsPresenter: SettingsPresenterFactory, + private val aboutPresenter: AboutPresenterFactory, private val lastUpdatedAt: LastUpdatedAt, private val rssRepository: RssRepository ) : ComponentContext by componentContext { @@ -124,7 +133,17 @@ class AppPresenter( Screen.Bookmarks(presenter = bookmarksPresenter(componentContext) { navigation.pop() }) } Config.Settings -> { - Screen.Settings(presenter = settingsPresenter(componentContext) { navigation.pop() }) + Screen.Settings( + presenter = + settingsPresenter( + componentContext, + { navigation.pop() }, + { navigation.push(Config.About) } + ) + ) + } + Config.About -> { + Screen.About(presenter = aboutPresenter(componentContext) { navigation.pop() }) } } @@ -158,5 +177,7 @@ class AppPresenter( @Parcelize object Bookmarks : Config @Parcelize object Settings : Config + + @Parcelize object About : Config } } diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/Screens.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/Screens.kt index 883f25d74..d94d641ef 100644 --- a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/Screens.kt +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/Screens.kt @@ -15,6 +15,7 @@ */ package dev.sasikanth.rss.reader.app +import dev.sasikanth.rss.reader.about.AboutPresenter import dev.sasikanth.rss.reader.bookmarks.BookmarksPresenter import dev.sasikanth.rss.reader.home.HomePresenter import dev.sasikanth.rss.reader.search.SearchPresenter @@ -28,4 +29,6 @@ internal sealed interface Screen { class Bookmarks(val presenter: BookmarksPresenter) : Screen class Settings(val presenter: SettingsPresenter) : Screen + + class About(val presenter: AboutPresenter) : Screen } diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/SettingsEvent.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/SettingsEvent.kt index 5a80dad3a..0c1140686 100644 --- a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/SettingsEvent.kt +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/SettingsEvent.kt @@ -24,4 +24,6 @@ sealed interface SettingsEvent { data class UpdateBrowserType(val browserType: BrowserType) : SettingsEvent data class ToggleFeaturedItemBlur(val value: Boolean) : SettingsEvent + + object AboutClicked : SettingsEvent } diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/SettingsPresenter.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/SettingsPresenter.kt index 845718945..f6a4d6eb6 100644 --- a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/SettingsPresenter.kt +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/SettingsPresenter.kt @@ -43,7 +43,8 @@ class SettingsPresenter( private val settingsRepository: SettingsRepository, private val appInfo: AppInfo, @Assisted componentContext: ComponentContext, - @Assisted private val goBack: () -> Unit + @Assisted private val goBack: () -> Unit, + @Assisted private val openAbout: () -> Unit, ) : ComponentContext by componentContext { private val presenterInstance = @@ -60,6 +61,7 @@ class SettingsPresenter( fun dispatch(event: SettingsEvent) { when (event) { SettingsEvent.BackClicked -> goBack() + SettingsEvent.AboutClicked -> openAbout() else -> { // no-op } @@ -105,6 +107,9 @@ class SettingsPresenter( } is SettingsEvent.UpdateBrowserType -> updateBrowserType(event.browserType) is SettingsEvent.ToggleFeaturedItemBlur -> toggleFeaturedItemBlur(event.value) + SettingsEvent.AboutClicked -> { + // no-op + } } } diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/ui/SettingsScreen.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/ui/SettingsScreen.kt index a3412cfc0..d3fdb6df7 100644 --- a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/ui/SettingsScreen.kt +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/settings/ui/SettingsScreen.kt @@ -162,14 +162,7 @@ internal fun SettingsScreen( ) } - // TODO: Remove feature flag after about page is implemented - if (false) { - item { - AboutItem { - // TODO: Open about page - } - } - } + item { AboutItem { settingsPresenter.dispatch(SettingsEvent.AboutClicked) } } } } }, diff --git a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/utils/Constants.kt b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/utils/Constants.kt index d82563536..60accbb55 100644 --- a/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/utils/Constants.kt +++ b/shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/utils/Constants.kt @@ -19,7 +19,18 @@ internal object Constants { const val DATA_STORE_FILE_NAME = "twine.preferences_pb" const val EPSILON = 1e-6f const val REPORT_ISSUE_LINK = "https://github.com/msasikanth/twine/issues" + + const val ABOUT_SASI_NAME = "Sasikanth Miriyampalli" + const val ABOUT_ED_NAME = "Eduardo Pratti" + const val ABOUT_SASI_PIC = "https://www.gravatar.com/avatar/b03fa943d54ac5377813c44bfb8954d2?s=250" const val ABOUT_ED_PIC = "https://www.gravatar.com/avatar/b9fc51480a2bdf036e2e5f6e5a52bf19?s=250" + + const val ABOUT_SASI_THREADS = "https://www.threads.net/@its_sasikanth" + const val ABOUT_SASI_TWITTER = "https://twitter.com/its_sasikanth" + const val ABOUT_SASI_GITHUB = "https://github.com/msasikanth/" + const val ABOUT_SASI_WEBSITE = "https://sasikanth.dev" + const val ABOUT_ED_THREADS = "https://www.threads.net/@edpratti" + const val ABOUT_ED_TWITTER = "https://twitter.com/edpratti" }