Browse Source

implemented most functionality. notifications cannot be turned off

pull/1/head
Nareshkumar Rao 4 years ago
parent
commit
f937f1553d
  1. 9
      .idea/dictionaries/naresh.xml
  2. 23
      app/build.gradle
  3. 13
      app/src/main/AndroidManifest.xml
  4. BIN
      app/src/main/ic_launcher-playstore.png
  5. 36
      app/src/main/java/com/nareshkumarrao/eiweblog/AboutActivity.kt
  6. 64
      app/src/main/java/com/nareshkumarrao/eiweblog/MainActivity.kt
  7. 17
      app/src/main/java/com/nareshkumarrao/eiweblog/NotificationSettingsActivity.kt
  8. 36
      app/src/main/java/com/nareshkumarrao/eiweblog/UpdateWorker.kt
  9. 115
      app/src/main/java/com/nareshkumarrao/eiweblog/Utilities.kt
  10. 16
      app/src/main/java/com/nareshkumarrao/eiweblog/ui/main/ItemArticleAdapter.kt
  11. 44
      app/src/main/java/com/nareshkumarrao/eiweblog/ui/main/SectionsFragment.kt
  12. 2
      app/src/main/java/com/nareshkumarrao/eiweblog/ui/main/SectionsPagerAdapter.kt
  13. BIN
      app/src/main/res/drawable-hdpi/ic_stat_name.png
  14. BIN
      app/src/main/res/drawable-mdpi/ic_stat_name.png
  15. BIN
      app/src/main/res/drawable-xhdpi/ic_stat_name.png
  16. BIN
      app/src/main/res/drawable-xxhdpi/ic_stat_name.png
  17. BIN
      app/src/main/res/drawable-xxxhdpi/ic_stat_name.png
  18. 7
      app/src/main/res/drawable/toolbar_dropshadow.xml
  19. 116
      app/src/main/res/layout/activity_about.xml
  20. 2
      app/src/main/res/layout/activity_main.xml
  21. 63
      app/src/main/res/layout/activity_notification_settings.xml
  22. 16
      app/src/main/res/layout/fragment_sections.xml
  23. 10
      app/src/main/res/menu/toolbar_menu.xml
  24. 4
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  25. 4
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  26. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  27. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
  28. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  29. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  30. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
  31. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  32. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  33. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
  34. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  35. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  36. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
  37. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  38. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  39. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
  40. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  41. 16
      app/src/main/res/values-night/themes.xml
  42. 4
      app/src/main/res/values/ic_launcher_background.xml
  43. 24
      app/src/main/res/values/strings.xml
  44. 5
      app/src/main/res/values/themes.xml
  45. BIN
      images/launcher.png
  46. 82
      images/launcher.svg

9
.idea/dictionaries/naresh.xml

@ -0,0 +1,9 @@
<component name="ProjectDictionaryState">
<dictionary name="naresh">
<words>
<w>elektro</w>
<w>hsdsans</w>
<w>weblog</w>
</words>
</dictionary>
</component>

23
app/build.gradle

@ -35,16 +35,19 @@ android {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.android.volley:volley:1.2.0' implementation 'com.android.volley:volley:1.2.0'
implementation "com.squareup.okhttp3:okhttp:4.9.0"
implementation "androidx.work:work-runtime-ktx:2.5.0"
} }

13
app/src/main/AndroidManifest.xml

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nareshkumarrao.eiweblog"> package="com.nareshkumarrao.eiweblog">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:allowBackup="true" android:allowBackup="true"
@ -10,6 +11,14 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.EIWeblog"> android:theme="@style/Theme.EIWeblog">
<activity
android:name=".AboutActivity"
android:theme="@style/Theme.EIWeblog.NoActionBar"
android:parentActivityName=".MainActivity" />
<activity
android:name=".NotificationSettingsActivity"
android:theme="@style/Theme.EIWeblog.NoActionBar"
android:parentActivityName=".MainActivity" />
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
@ -19,9 +28,7 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>
</manifest> </manifest>

BIN
app/src/main/ic_launcher-playstore.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

36
app/src/main/java/com/nareshkumarrao/eiweblog/AboutActivity.kt

@ -0,0 +1,36 @@
package com.nareshkumarrao.eiweblog
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatButton
import androidx.appcompat.widget.Toolbar
class AboutActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_about)
val aboutToolbar = this.findViewById<Toolbar>(R.id.about_toolbar)
setSupportActionBar(aboutToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowTitleEnabled(false)
}
fun sendBeer(view: View) {
startActivity( Intent(
Intent.ACTION_VIEW,
Uri.parse("https://paypal.me/naresh97")
))
}
fun githubRepo(view: View){
startActivity( Intent(
Intent.ACTION_VIEW,
Uri.parse("https://github.com/naresh97/ei-weblog-android")
))
}
}

64
app/src/main/java/com/nareshkumarrao/eiweblog/MainActivity.kt

@ -1,17 +1,23 @@
package com.nareshkumarrao.eiweblog package com.nareshkumarrao.eiweblog
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import com.android.volley.VolleyLog
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.WorkRequest
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.nareshkumarrao.eiweblog.ui.main.Article
import com.nareshkumarrao.eiweblog.ui.main.SectionsPagerAdapter import com.nareshkumarrao.eiweblog.ui.main.SectionsPagerAdapter
import okhttp3.OkHttpClient
import java.util.concurrent.TimeUnit
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
@ -26,50 +32,32 @@ class MainActivity : AppCompatActivity() {
val tabs: TabLayout = findViewById(R.id.tabs) val tabs: TabLayout = findViewById(R.id.tabs)
tabs.setupWithViewPager(viewPager) tabs.setupWithViewPager(viewPager)
val myToolbar = findViewById<View>(R.id.toolbar) as Toolbar
val myToolbar = findViewById<View>(R.id.about_toolbar) as Toolbar
setSupportActionBar(myToolbar) setSupportActionBar(myToolbar)
VolleyLog.DEBUG = true
Utilities.createNotificationChannel(this)
/*val queue = Volley.newRequestQueue(this)
val url = "https://www.reddit.com"
val stringRequest = StringRequest(
Request.Method.GET, url,
{ response ->
Log.d("XMLLIST", "got response!")
Log.d("XMLLIST", "$response")
},
{ error -> Log.e("XMLLIST", error.toString()) })
stringRequest.retryPolicy = DefaultRetryPolicy(
DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 2,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
)
queue.add(stringRequest)*/
val uploadWorkRequest: WorkRequest =
PeriodicWorkRequestBuilder<UpdateWorker>(1, TimeUnit.HOURS)
.build()
WorkManager.getInstance(this).enqueue(uploadWorkRequest)
val thread = Thread {
try {
Log.d("XMLLIST", "Starting network request thread.")
val client = OkHttpClient()
val request = okhttp3.Request.Builder().url("https://google.com/").build()
val response = client.newCall(request).execute()
Log.d("XMLLIST", response.toString())
} catch (e: Exception) {
e.printStackTrace()
}
}
thread.start()
} }
fun logArticles(articles: List<Article>){
Log.i("XMLLIST", articles.toString())
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu?): Boolean {
//Utilities.weblogXML(baseContext, ::logArticles)
menuInflater.inflate(R.menu.toolbar_menu, menu); menuInflater.inflate(R.menu.toolbar_menu, menu);
return true; return true;
} }
fun showNotificationSettings(item: MenuItem){
val intent = Intent(this, NotificationSettingsActivity::class.java)
startActivity(intent)
}
fun showAbout(item: MenuItem){
val intent = Intent(this, AboutActivity::class.java)
startActivity(intent)
}
} }

17
app/src/main/java/com/nareshkumarrao/eiweblog/NotificationSettingsActivity.kt

@ -0,0 +1,17 @@
package com.nareshkumarrao.eiweblog
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.widget.Toolbar
class NotificationSettingsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_notification_settings)
val notificationsToolbar = this.findViewById<Toolbar>(R.id.notification_toolbar)
setSupportActionBar(notificationsToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowTitleEnabled(false)
}
}

36
app/src/main/java/com/nareshkumarrao/eiweblog/UpdateWorker.kt

@ -0,0 +1,36 @@
package com.nareshkumarrao.eiweblog
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import java.math.BigInteger
import java.security.MessageDigest
class UpdateWorker(private val context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
override fun doWork(): Result {
Utilities.weblogList(context) { articles ->
val lastArticle = Utilities.getLatestRelevantArticle(articles)!!
val hashString = lastArticle.title + lastArticle.content + lastArticle.date
val oldHash = md5(hashString)
Utilities.fetchWeblogXML(applicationContext){newArticles ->
val lastNewArticle = Utilities.getLatestRelevantArticle(newArticles)!!
val newHashString = lastNewArticle.title + lastNewArticle.content + lastNewArticle.date
val newHash = md5(newHashString)
if(oldHash != newHash){
Utilities.sendNotification(context, lastNewArticle, newArticles.size)
}
}
}
return Result.success()
}
private fun md5(input:String): String {
val md = MessageDigest.getInstance("MD5")
return BigInteger(1, md.digest(input.toByteArray())).toString(16).padStart(32, '0')
}
}

115
app/src/main/java/com/nareshkumarrao/eiweblog/Utilities.kt

@ -1,35 +1,74 @@
package com.nareshkumarrao.eiweblog package com.nareshkumarrao.eiweblog
import android.content.ContentValues
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.content.Context import android.content.Context
import android.os.Build
import android.util.Log import android.util.Log
import android.util.Xml import android.util.Xml
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.text.HtmlCompat
import com.android.volley.Request import com.android.volley.Request
import com.android.volley.Response
import com.android.volley.toolbox.StringRequest import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley import com.android.volley.toolbox.Volley
import com.nareshkumarrao.eiweblog.ui.main.Article import com.nareshkumarrao.eiweblog.ui.main.Article
import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParser
import java.io.StringReader import java.io.StringReader
internal object Utilities { internal object Utilities {
fun weblogXML(context: Context, function: (d: List<Article>) -> Unit) {
fun weblogList(context: Context?, function: (d: List<Article>) -> Unit){
val sharedPref = context?.getSharedPreferences(context?.getString(R.string.preference_file_key), Context.MODE_PRIVATE)
val weblogResponse = sharedPref?.getString( context?.getString(R.string.weblog_response_key), null)
if (weblogResponse == null){
fetchWeblogXML(context, function)
return
}
val parser: XmlPullParser = Xml.newPullParser()
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
parser.setInput( StringReader(weblogResponse) )
parser.nextTag()
function(parseXML(parser))
}
fun fetchWeblogXML(context: Context?, function: (d: List<Article>) -> Unit) {
val queue = Volley.newRequestQueue(context) val queue = Volley.newRequestQueue(context)
val url = "https://www.google.com"
val url = context?.getString(R.string.weblog_xml_url)
val stringRequest = StringRequest(Request.Method.GET, url, val stringRequest = StringRequest(Request.Method.GET, url,
{ response -> { response ->
Log.d("XMLLIST", "got response!")
// Display the first 500 characters of the response string.
Log.d("XMLLIST", "$response")
val responseStr = String(response.toByteArray(Charsets.ISO_8859_1), Charsets.UTF_8)
val sharedPref = context?.getSharedPreferences(context?.getString(R.string.preference_file_key), Context.MODE_PRIVATE)
if (sharedPref != null) {
with (sharedPref.edit()) {
putString(context?.getString(R.string.weblog_response_key), responseStr)
apply()
}
}
val parser: XmlPullParser = Xml.newPullParser()
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
//Log.d("XMLLIST", responseStr )
parser.setInput( StringReader(responseStr) )
parser.nextTag()
val articles = parseXML(parser)
function(articles)
}, },
{ error -> Log.e("XMLLIST", error.toString()) }) { error -> Log.e("XMLLIST", error.toString()) })
queue.add(stringRequest) queue.add(stringRequest)
Log.e("XMLLIST", "Adding request to queue from: $url")
} }
private fun parseXML(parser: XmlPullParser): List<Article> { private fun parseXML(parser: XmlPullParser): List<Article> {
@ -56,7 +95,7 @@ internal object Utilities {
continue continue
} }
if (parser.name == "z:row") { if (parser.name == "z:row") {
articles.add(parseZROW(parser))
parseZROW(parser)?.let { articles.add(it) }
} else { } else {
parseSkip(parser) parseSkip(parser)
} }
@ -64,16 +103,21 @@ internal object Utilities {
return articles return articles
} }
private fun parseZROW(parser: XmlPullParser): Article {
private fun parseZROW(parser: XmlPullParser): Article? {
parser.require(XmlPullParser.START_TAG, null, "z:row") parser.require(XmlPullParser.START_TAG, null, "z:row")
val title = parser.getAttributeValue(null, "ows_Title") val title = parser.getAttributeValue(null, "ows_Title")
val content = parser.getAttributeValue(null, "ows_Body") val content = parser.getAttributeValue(null, "ows_Body")
val date = parser.getAttributeValue(null, "ows_Created") val date = parser.getAttributeValue(null, "ows_Created")
val author = parser.getAttributeValue(null, "ows_Autor2") val author = parser.getAttributeValue(null, "ows_Autor2")
val category = parser.getAttributeValue(null, "ows_Kategorie")
parser.nextTag() parser.nextTag()
parser.require(XmlPullParser.END_TAG, null, "link")
parser.require(XmlPullParser.END_TAG, null, "z:row")
if(title == null || content == null || date == null || author == null || category == null){
return null
}
return Article(title, content, date, author)
return Article(title, content, date, author, category)
} }
private fun parseSkip(parser: XmlPullParser) { private fun parseSkip(parser: XmlPullParser) {
@ -88,4 +132,49 @@ internal object Utilities {
} }
} }
} }
fun sendNotification(context: Context?, article: Article, id:Int) {
val intent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
var builder = NotificationCompat.Builder(context!!, context.getString(R.string.channel_id))
.setSmallIcon(R.drawable.ic_stat_name)
.setContentTitle(article.title)
.setStyle(NotificationCompat.BigTextStyle()
.bigText(HtmlCompat.fromHtml(article.content, HtmlCompat.FROM_HTML_MODE_COMPACT)))
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
with(NotificationManagerCompat.from(context)) {
// notificationId is a unique int for each notification that you must define
notify(id, builder.build())
}
}
fun createNotificationChannel(context: Context?){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = context?.getString(R.string.channel_name)
val descriptionText = context?.getString(R.string.channel_description)
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(context?.getString(R.string.channel_id), name, importance).apply {
description = descriptionText
}
val notificationManager: NotificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
fun getLatestRelevantArticle(articles: List<Article>): Article? {
val sortedArticles = articles.sortedByDescending { it.date }
for (article in sortedArticles){
if( article.category == "Lehre" || article.category == "Prüfung" || article.category == "Sonstiges"){
return article
}
}
return null
}
} }

16
app/src/main/java/com/nareshkumarrao/eiweblog/ui/main/ItemArticleAdapter.kt

@ -1,26 +1,38 @@
package com.nareshkumarrao.eiweblog.ui.main package com.nareshkumarrao.eiweblog.ui.main
import android.os.Build
import android.text.Html
import android.text.util.Linkify
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.core.text.HtmlCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.nareshkumarrao.eiweblog.R import com.nareshkumarrao.eiweblog.R
import org.w3c.dom.Text
data class Article(val title: String, val content: String, val date: String, val author: String)
data class Article(val title: String, val content: String, val date: String, val author: String, val category: String)
class ItemArticleAdapter(private val articles: List<Article>) : RecyclerView.Adapter<ItemArticleAdapter.ViewHolder>() { class ItemArticleAdapter(private val articles: List<Article>) : RecyclerView.Adapter<ItemArticleAdapter.ViewHolder>() {
inner class ViewHolder(inflater: LayoutInflater, parent: ViewGroup) : RecyclerView.ViewHolder(inflater.inflate(R.layout.item_article, parent, false)) { inner class ViewHolder(inflater: LayoutInflater, parent: ViewGroup) : RecyclerView.ViewHolder(inflater.inflate(R.layout.item_article, parent, false)) {
private var title: TextView? = null private var title: TextView? = null
private var content: TextView? = null private var content: TextView? = null
private var date: TextView? = null
private var author: TextView? = null
init { init {
title = itemView.findViewById(R.id.titleText) title = itemView.findViewById(R.id.titleText)
content = itemView.findViewById(R.id.contentText) content = itemView.findViewById(R.id.contentText)
date = itemView.findViewById(R.id.dateText)
author = itemView.findViewById(R.id.authorText)
} }
fun bind(article: Article) { fun bind(article: Article) {
title?.text = article.title title?.text = article.title
content?.text = article.content
content?.text = HtmlCompat.fromHtml(article.content, HtmlCompat.FROM_HTML_MODE_COMPACT)
content?.let { Linkify.addLinks(it, Linkify.WEB_URLS) };
author?.text = article.author
date?.text = article.date
} }
} }

44
app/src/main/java/com/nareshkumarrao/eiweblog/ui/main/SectionsFragment.kt

@ -7,11 +7,23 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.nareshkumarrao.eiweblog.R import com.nareshkumarrao.eiweblog.R
import com.nareshkumarrao.eiweblog.Utilities
class SectionsFragment() : Fragment() {
private var swipeRefreshLayout: SwipeRefreshLayout? = null
class SectionsFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_sections, container, false)
val rootView = inflater.inflate(R.layout.fragment_sections, container, false)
this.swipeRefreshLayout = rootView.findViewById<SwipeRefreshLayout>(R.id.sectionsSwipeRefresh)
this.swipeRefreshLayout?.setOnRefreshListener {
Utilities.fetchWeblogXML(this.context, ::updateView)
}
return rootView
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -20,12 +32,36 @@ class SectionsFragment : Fragment() {
layoutManager = LinearLayoutManager(activity) layoutManager = LinearLayoutManager(activity)
adapter = ItemArticleAdapter(listOf()) adapter = ItemArticleAdapter(listOf())
} }
Utilities.weblogList(this.context, ::updateView)
}
companion object {
private const val ARG_SECTION_NAME = "section_title"
@JvmStatic
fun newInstance(title: String): SectionsFragment {
return SectionsFragment().apply {
arguments = Bundle().apply {
putString(ARG_SECTION_NAME, title)
}
}
}
} }
fun updateView(get_articles: List<Article>){
private fun updateView(get_articles: List<Article>){
this.swipeRefreshLayout?.isRefreshing=false
var articles: MutableList<Article> = mutableListOf()
val title = arguments?.getString(ARG_SECTION_NAME) ?: return
for (article in get_articles){
if(article.category == title){
articles.add(article)
}
}
articles.sortByDescending { it.date }
view?.findViewById<RecyclerView>(R.id.sectionsRecylerView)?.apply { view?.findViewById<RecyclerView>(R.id.sectionsRecylerView)?.apply {
layoutManager = LinearLayoutManager(activity) layoutManager = LinearLayoutManager(activity)
adapter = ItemArticleAdapter(get_articles)
adapter = ItemArticleAdapter(articles)
} }
} }
} }

2
app/src/main/java/com/nareshkumarrao/eiweblog/ui/main/SectionsPagerAdapter.kt

@ -16,7 +16,7 @@ class SectionsPagerAdapter(private val context: Context, fm: FragmentManager)
: FragmentPagerAdapter(fm) { : FragmentPagerAdapter(fm) {
override fun getItem(position: Int): Fragment { override fun getItem(position: Int): Fragment {
return SectionsFragment()
return SectionsFragment.newInstance( context.resources.getString(TAB_TITLES[position]) )
} }
override fun getPageTitle(position: Int): CharSequence? { override fun getPageTitle(position: Int): CharSequence? {

BIN
app/src/main/res/drawable-hdpi/ic_stat_name.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

BIN
app/src/main/res/drawable-mdpi/ic_stat_name.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

BIN
app/src/main/res/drawable-xhdpi/ic_stat_name.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

BIN
app/src/main/res/drawable-xxhdpi/ic_stat_name.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
app/src/main/res/drawable-xxxhdpi/ic_stat_name.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

7
app/src/main/res/drawable/toolbar_dropshadow.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:startColor="@android:color/transparent"
android:endColor="#EEEEEEEE"
android:angle="90"/>
</shape>

116
app/src/main/res/layout/activity_about.xml

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AboutActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/about_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetStart="0px"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/hsdsans_elektro"
android:minHeight="?actionBarSize"
android:padding="@dimen/appbar_padding"
android:text="@string/about_title"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
android:textColor="@color/black"
android:textSize="25sp"
android:paddingStart="0px"
android:paddingLeft="0px"
tools:ignore="RtlSymmetry" />
</androidx.appcompat.widget.Toolbar>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:fadeScrollbars="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/about_toolbar">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="match_parent"
android:layout_height="5dp"
app:layout_constraintTop_toTopOf="parent"
android:background="@drawable/toolbar_dropshadow"/>
<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="@string/about_text"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="16dp"
android:background="#FFFFFF"
android:onClick="githubRepo"
android:text="GitHub Repository"
android:textColor="@color/white"
app:backgroundTint="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/textView"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/license_info"
android:textColor="@color/black"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="@+id/textView2"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/button"
app:layout_constraintTop_toBottomOf="@+id/button" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:onClick="sendBeer"
android:text="@string/send_beer"
android:textColor="@color/white"
app:backgroundTint="@color/fh_red"
app:layout_constraintStart_toStartOf="@+id/textView2"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

2
app/src/main/res/layout/activity_main.xml

@ -14,7 +14,7 @@
android:theme="@style/Theme.EIWeblog.AppBarOverlay"> android:theme="@style/Theme.EIWeblog.AppBarOverlay">
<androidx.appcompat.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:id="@+id/about_toolbar"
app:contentInsetStart="0px" app:contentInsetStart="0px"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">

63
app/src/main/res/layout/activity_notification_settings.xml

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".NotificationSettingsActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/notification_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentInsetStart="0px"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/hsdsans_elektro"
android:minHeight="?actionBarSize"
android:padding="@dimen/appbar_padding"
android:text="@string/notifications_title"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
android:textColor="@color/black"
android:textSize="25sp"
android:paddingStart="0px"
android:paddingLeft="0px"
tools:ignore="RtlSymmetry" />
</androidx.appcompat.widget.Toolbar>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
app:layout_constraintBottom_toBottomOf="@+id/textView4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/textView4" />
<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:text="@string/enable_notifications"
android:textColor="@color/black"
android:textSize="18sp"
app:layout_constraintEnd_toStartOf="@+id/switch1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/notification_toolbar" />
</androidx.constraintlayout.widget.ConstraintLayout>

16
app/src/main/res/layout/fragment_sections.xml

@ -3,8 +3,16 @@
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/sectionsRecylerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/sectionsSwipeRefresh"
android:layout_height="match_parent"
android:layout_width="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/sectionsRecylerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

10
app/src/main/res/menu/toolbar_menu.xml

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto" <menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/notifications" app:showAsAction="never"/>
<item android:title="@string/about" app:showAsAction="never"/>
<item
android:onClick="showNotificationSettings"
android:title="@string/notifications"
app:showAsAction="never" />
<item
android:onClick="showAbout"
android:title="@string/about"
app:showAsAction="never" />
</menu> </menu>

4
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

4
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

16
app/src/main/res/values-night/themes.xml

@ -1,16 +0,0 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.EIWeblog" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

4
app/src/main/res/values/ic_launcher_background.xml

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FFFFFF</color>
</resources>

24
app/src/main/res/values/strings.xml

@ -5,8 +5,30 @@
<string name="tab_sonstiges">Sonstiges</string> <string name="tab_sonstiges">Sonstiges</string>
<string name="hsd_symbol">HSD</string> <string name="hsd_symbol">HSD</string>
<string name="weblog_xml_url"><![CDATA[ <string name="weblog_xml_url"><![CDATA[
https://ei.hs-duesseldorf.de/weblog/_vti_bin/owssvr.dll?Cmd=Display&List=%7B169417ED-6982-4CDA-9CAC-F63FCB1757EF%7D&XMLDATA=TRUE&RowLimit=0&Queue=*
https://ei.hs-duesseldorf.de/weblog/_vti_bin/owssvr.dll?Cmd=Display&List=%7B169417ED-6982-4CDA-9CAC-F63FCB1757EF%7D&XMLDATA=TRUE&RowLimit=0&Query=*
]]></string> ]]></string>
<string name="notifications">Benachrichtigungen</string> <string name="notifications">Benachrichtigungen</string>
<string name="about">Information</string> <string name="about">Information</string>
<string name="preference_file_key">com.nareshkumarrao.eiweblog.preferences</string>
<string name="weblog_response_key">weblog_response</string>
<string name="tab_veranstaltungen">Veranstaltungen</string>
<string name="about_text">
My name is Naresh and I am doing my Master\'s in Automation at the HSD.\n
\nI wrote this app because I was unsatisfied with the EI weblog that was always silently being
updated. The other option would be to develop enough self-discipline to check it regulary.
Yeah no thanks.\n
\nI put too many hours of work into this app, and if you like it and found it useful, I would really
appreciate it if you bought me a beer, or maybe a tasty döner.
</string>
<string name="about_title">Information</string>
<string name="send_beer">Send me €5 for beer on PayPal</string>
<string name="license_info">This project is developed open-source and is to be distributed freely
as contained within the terms of the GPLv3 license. More information about the license and the
source code of this project can be found on its GitHub repository.
</string>
<string name="channel_name">EI Weblog Notifications</string>
<string name="channel_description">Latest updates from the EI Weblog</string>
<string name="channel_id">com.nareshkumarrao.eiweblog.update</string>
<string name="notifications_title">Benachrichtigungen</string>
<string name="enable_notifications">Notify me when new updates are posted to the weblog</string>
</resources> </resources>

5
app/src/main/res/values/themes.xml

@ -1,6 +1,6 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.EIWeblog" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.EIWeblog" parent="Theme.MaterialComponents.Light.DarkActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item> <item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorPrimaryVariant">@color/purple_700</item>
@ -12,11 +12,14 @@
<!-- Status bar color. --> <!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item> <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
</style> </style>
<style name="Theme.EIWeblog.NoActionBar"> <style name="Theme.EIWeblog.NoActionBar">
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item> <item name="windowNoTitle">true</item>
<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
</style> </style>
<style name="Theme.EIWeblog.AppBarOverlay" parent="ThemeOverlay.AppCompat.Light" /> <style name="Theme.EIWeblog.AppBarOverlay" parent="ThemeOverlay.AppCompat.Light" />

BIN
images/launcher.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

82
images/launcher.svg

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="186.17953mm"
height="186.18573mm"
viewBox="0 0 186.17954 186.18573"
version="1.1"
id="svg8"
inkscape:export-filename="/home/naresh/Pictures/EI.png"
inkscape:export-xdpi="69.848534"
inkscape:export-ydpi="69.848534"
inkscape:version="1.0.2 (1.0.2+r75+1)"
sodipodi:docname="launcher.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="271.00222"
inkscape:cy="-215.6691"
inkscape:document-units="mm"
inkscape:current-layer="layer2"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="957"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
transform="translate(-20.145545,-54.038641)">
<circle
style="fill:none;stroke:#e60028;stroke-width:7.937;stroke-miterlimit:4;stroke-dasharray:190.488, 7.937;stroke-dashoffset:0;stroke-opacity:1"
id="path840"
cx="113.23561"
cy="147.13202"
r="89.120903" />
</g>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-20.145545,-54.038641)">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:111.943px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.79858"
x="57.510078"
y="188.86467"
id="text835"><tspan
sodipodi:role="line"
id="tspan833"
x="57.510078"
y="188.86467"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'HSD Sans';-inkscape-font-specification:'HSD Sans';stroke-width:2.79858">EI</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

Loading…
Cancel
Save