diff --git a/app/build.gradle b/app/build.gradle
index 697573c..7fea453 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,5 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
+apply plugin: 'com.mikepenz.aboutlibraries.plugin'
android {
@@ -24,7 +25,6 @@ android {
viewBinding true
}
-
namespace 'de.msdevs.einschlafhilfe'
compileOptions {
@@ -50,6 +50,8 @@ dependencies {
implementation("ru.gildor.coroutines:kotlin-coroutines-okhttp:1.0")
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10"
implementation 'com.github.AppIntro:AppIntro:6.3.1'
+ implementation "com.mikepenz:aboutlibraries-core:10.9.1"
+ implementation "com.mikepenz:aboutlibraries:10.9.1"
}
repositories {
mavenCentral()
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e95e854..f760253 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -42,7 +42,12 @@
-
+
diff --git a/app/src/main/java/de/msdevs/einschlafhilfe/AboutActivity.kt b/app/src/main/java/de/msdevs/einschlafhilfe/AboutActivity.kt
index 0b91b15..bfa90a9 100644
--- a/app/src/main/java/de/msdevs/einschlafhilfe/AboutActivity.kt
+++ b/app/src/main/java/de/msdevs/einschlafhilfe/AboutActivity.kt
@@ -52,6 +52,8 @@ class AboutActivity : BaseActivity() {
opennUrl("https://github.com/MarvinStelter/DieDreiFragezeichenEinschlafhilfe")
}
btnLicenses.setOnClickListener{
+ startActivity(Intent(this@AboutActivity, AboutLibrariesActivity::class.java))
+
if(expandableLayout.isExpanded){
expandableLayout.collapse()
}else{
diff --git a/app/src/main/java/de/msdevs/einschlafhilfe/AboutLibrariesActivity.kt b/app/src/main/java/de/msdevs/einschlafhilfe/AboutLibrariesActivity.kt
new file mode 100644
index 0000000..560039a
--- /dev/null
+++ b/app/src/main/java/de/msdevs/einschlafhilfe/AboutLibrariesActivity.kt
@@ -0,0 +1,18 @@
+package de.msdevs.einschlafhilfe
+import android.os.Bundle
+import com.mikepenz.aboutlibraries.LibsBuilder
+import com.mikepenz.aboutlibraries.ui.LibsActivity
+
+
+class AboutLibrariesActivity : LibsActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ intent = LibsBuilder()
+ .withEdgeToEdge(true)
+ .withAboutMinimalDesign(true)
+ .withActivityTitle(getString(R.string.about_libs))
+ .withSearchEnabled(true)
+ .intent(this)
+ super.onCreate(savedInstanceState)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/msdevs/einschlafhilfe/FilterActivity.kt b/app/src/main/java/de/msdevs/einschlafhilfe/FilterActivity.kt
index f6ca4d7..37ad12c 100644
--- a/app/src/main/java/de/msdevs/einschlafhilfe/FilterActivity.kt
+++ b/app/src/main/java/de/msdevs/einschlafhilfe/FilterActivity.kt
@@ -1,57 +1,79 @@
package de.msdevs.einschlafhilfe
+import android.database.sqlite.SQLiteDatabase
import android.os.Bundle
import android.util.Log
+import android.view.ScaleGestureDetector
import android.view.View
-import android.widget.AdapterView
import android.widget.ArrayAdapter
-import android.widget.AutoCompleteTextView
+import android.widget.FrameLayout
+import android.widget.HorizontalScrollView
+import android.widget.ScrollView
+import android.widget.TextView
+import android.widget.Toast
import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.textfield.MaterialAutoCompleteTextView
+import de.msdevs.einschlafhilfe.adapter.FilterListeAdapter
+import de.msdevs.einschlafhilfe.database.DatabaseHelper
import de.msdevs.einschlafhilfe.databinding.ActivityFilterBinding
import de.msdevs.einschlafhilfe.models.JsonResponse
import de.msdevs.einschlafhilfe.utils.NetworkUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import okhttp3.OkHttpClient
-import okhttp3.Request
import org.json.JSONObject
-import ru.gildor.coroutines.okhttp.await
-
-
-class FilterActivity : BaseActivity(){
+import java.io.BufferedReader
+class FilterActivity : BaseActivity(), FilterListeAdapter.OnDeleteItemListener{
+ private lateinit var rvFilterListe : RecyclerView
+ private lateinit var tvNothingAdded : TextView
private lateinit var binding : ActivityFilterBinding
+ private lateinit var folgen_database: SQLiteDatabase
+ private lateinit var databaseHelper: DatabaseHelper
private lateinit var tvInput : MaterialAutoCompleteTextView
private val episodeList = ArrayList()
+ private var filterList = ArrayList()
+ private var jsonIndexSeperator = HashMap()
+ private var apiCallCounter = 0
private lateinit var networkUtils: NetworkUtils
+ private lateinit var folgenListe : String
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityFilterBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
iniViews()
+ refreshList()
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
lifecycleScope.launch {
withContext(Dispatchers.IO) {
- apiCall()
+ apiCall("ddf")
+ apiCall("d3")
+ apiCall("kids")
+ apiCall("sonderfolgen")
}
}
+
}
- private suspend fun apiCall() {
- val urlExtraParameter = "folgen.json"
- episodeList.clear()
+ private suspend fun apiCall(extraParameter : String) {
try {
if(networkUtils.isConnected(this)){
- val client = OkHttpClient.Builder().build()
- val request =
- Request.Builder().url(getString(R.string.base_url) + urlExtraParameter)
- .build()
- val folgenListe = client.newCall(request).await().body()?.string().toString()
+ if(extraParameter == "ddf"){
+ folgenListe = assets.open("offline_list.txt").bufferedReader().use(BufferedReader::readText)
+ }else if (extraParameter == "d3"){
+ folgenListe = assets.open("offline_list_dd.txt").bufferedReader().use(BufferedReader::readText)
+ }else if(extraParameter == "kids"){
+ folgenListe = assets.open("offline_list_kids.txt").bufferedReader().use(BufferedReader::readText)
+ }else{
+ folgenListe = assets.open("offline_list_sonderfolgen_ddf.txt").bufferedReader().use(BufferedReader::readText)
+ }
val jsonObject = JSONObject(folgenListe)
val jsonArray = jsonObject.optJSONArray("folgen")
if (jsonArray != null) {
@@ -61,12 +83,18 @@ class FilterActivity : BaseActivity(){
JsonResponse(
name = jsonObject.optString("name"),
beschreibung = jsonObject.optString("beschreibung"),
- spotify = jsonObject.optString("spotify")
+ spotify = jsonObject.optString("spotify"),
+ nummer = jsonObject.optInt("nummer"),
+ type = extraParameter
)
)
}
- runOnUiThread {
- iniAutoComplete()
+ jsonIndexSeperator[extraParameter] = jsonArray.length()
+ apiCallCounter++
+ if(apiCallCounter == 4){
+ runOnUiThread {
+ iniAutoComplete()
+ }
}
}
@@ -85,11 +113,59 @@ class FilterActivity : BaseActivity(){
textView.setOnItemClickListener { parent, view, position, id ->
val selectedName = parent.getItemAtPosition(position) as String
+ databaseHelper.insertFilterFolge(folgen_database,selectedName,getEpisodeNumber(selectedName),getEpisodeType(selectedName))
+ textView.text = null
+ refreshList()
+ }
+ }
+ private fun refreshList(){
+ filterList = databaseHelper.getFilterList(folgen_database)
+ val adapter = FilterListeAdapter(filterList,this)
+ val layoutManger = LinearLayoutManager(this)
+ if(filterList.isNotEmpty()){
+ tvNothingAdded.visibility = View.GONE
+ }else{
+ tvNothingAdded.visibility = View.VISIBLE
}
+ rvFilterListe.layoutManager = layoutManger
+ rvFilterListe.adapter = adapter
+
}
private fun iniViews(){
+ folgen_database = openOrCreateDatabase("app_list",MODE_PRIVATE,null)
+ databaseHelper = DatabaseHelper(this)
+ databaseHelper.createTables(folgen_database)
+
networkUtils = NetworkUtils()
tvInput = binding.tvFolge
+ rvFilterListe = binding.rvFilterListe
+ tvNothingAdded = binding.tvNoEpisodesAdded
+ }
+
+ private fun getEpisodeNumber(nameToFind: String): String? {
+ for (jsonResponse in episodeList) {
+ if (jsonResponse.name == nameToFind) {
+ return jsonResponse.nummer.toString()
+ }
+ }
+ return null
+ }
+ private fun getEpisodeType(nameToFind: String): String? {
+ for (jsonResponse in episodeList) {
+ if (jsonResponse.name == nameToFind) {
+ return jsonResponse.type
+ }
+ }
+ return null
+ }
+ override fun onSupportNavigateUp(): Boolean {
+ onBackPressed()
+ return true
+ }
+
+ override fun onDeleteItem(name: String) {
+ databaseHelper.removeFromList(folgen_database,name)
+ refreshList()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/de/msdevs/einschlafhilfe/MainActivity.kt b/app/src/main/java/de/msdevs/einschlafhilfe/MainActivity.kt
index 740e89c..a81340a 100644
--- a/app/src/main/java/de/msdevs/einschlafhilfe/MainActivity.kt
+++ b/app/src/main/java/de/msdevs/einschlafhilfe/MainActivity.kt
@@ -271,7 +271,7 @@ class MainActivity : BaseActivity() {
if (jsonArray != null) {
for (i in 0 until jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(i)
- episodeList.add(JsonResponse(name = jsonObject.optString("name"), beschreibung = jsonObject.optString("beschreibung"), spotify = jsonObject.optString("spotify")))
+ episodeList.add(JsonResponse(name = jsonObject.optString("name"), beschreibung = jsonObject.optString("beschreibung"), spotify = jsonObject.optString("spotify"), nummer = jsonObject.optInt("nummer"), type = ""))
}
}
}
diff --git a/app/src/main/java/de/msdevs/einschlafhilfe/adapter/AutoCompleteTextViewAdapter.kt b/app/src/main/java/de/msdevs/einschlafhilfe/adapter/AutoCompleteTextViewAdapter.kt
deleted file mode 100644
index b123ff6..0000000
--- a/app/src/main/java/de/msdevs/einschlafhilfe/adapter/AutoCompleteTextViewAdapter.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package de.msdevs.einschlafhilfe.adapter
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ArrayAdapter
-import android.widget.TextView
-import de.msdevs.einschlafhilfe.models.JsonResponse
-import de.msdevs.einschlafhilfe.R
-
-class AutoCompleteTextViewAdapter(context: Context, resource: Int, objects: ArrayList) :
- ArrayAdapter(context, resource, objects) {
-
- override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
- val item = getItem(position)
- val view = convertView ?: LayoutInflater.from(context)
- .inflate(R.layout.layout_autocomplete, parent, false)
-
- val textView: TextView = view.findViewById(R.id.tv_folgen_name)
- textView.text = item?.name
-
- return view
- }
-
- override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
- return getView(position, convertView, parent)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/de/msdevs/einschlafhilfe/adapter/FilterListeAdapter.kt b/app/src/main/java/de/msdevs/einschlafhilfe/adapter/FilterListeAdapter.kt
new file mode 100644
index 0000000..54bb0c9
--- /dev/null
+++ b/app/src/main/java/de/msdevs/einschlafhilfe/adapter/FilterListeAdapter.kt
@@ -0,0 +1,79 @@
+package de.msdevs.einschlafhilfe.adapter
+
+import android.content.Context
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import android.widget.ImageView
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import de.msdevs.einschlafhilfe.databinding.ItemFolgeBinding
+import de.msdevs.einschlafhilfe.models.JsonResponse
+import de.msdevs.einschlafhilfe.utils.NetworkUtils
+import de.msdevs.einschlafhilfe.R
+
+class FilterListeAdapter(private val folgeList: List, private val onDeleteItemListener: OnDeleteItemListener? = null) :
+ RecyclerView.Adapter() {
+ private var networkUtils = NetworkUtils()
+
+ inner class FolgeViewHolder(private val binding: ItemFolgeBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+
+ fun bind(folgeTitle: String, nummer : String, type : String) {
+ binding.tvFolgenName.text = folgeTitle
+ binding.tvFolgenNummer.text = binding.tvFolgenNummer.context.getString(R.string.nummer, nummer)
+ loadCover(nummer,type, binding.ivCover)
+
+ binding.ivDelete.setOnClickListener{
+ onDeleteItemListener?.onDeleteItem(folgeTitle)
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FolgeViewHolder {
+ val binding =
+ ItemFolgeBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return FolgeViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: FolgeViewHolder, position: Int) {
+ val item = folgeList[position]
+ holder.bind(item.name,item.nummer.toString(), item.type)
+ }
+
+ override fun getItemCount(): Int {
+ return folgeList.size
+ }
+
+ private fun loadCover(nummer : String, type : String, iv : ImageView){
+ val context : Context = iv.context
+ var prefix = ""
+ if(type == "ddf"){
+ prefix = ""
+ }else if(type == "d3"){
+ prefix = "dd"
+ }else if(type == "kids"){
+ prefix = "k"
+ }else if(type == "sonderfolgen"){
+ prefix = "x"
+ }else{
+ prefix = "s"
+ }
+ val url : String = if(prefix == "dd"){
+ context.getString(R.string.cover_citroncode_dd_url) + (nummer) + ".png"
+ }else{
+ context.getString(R.string.cover_citroncode_url) + prefix + (nummer) + ".png"
+ }
+ Log.e("FilterListeAdapter", "Cover URL: $url")
+ if(networkUtils.isConnected(context)){
+ Glide.with(context)
+ .load(url)
+ .diskCacheStrategy(DiskCacheStrategy.ALL)
+ .into(iv)
+ }
+ }
+ interface OnDeleteItemListener {
+ fun onDeleteItem(name: String)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/msdevs/einschlafhilfe/database/DatabaseHelper.kt b/app/src/main/java/de/msdevs/einschlafhilfe/database/DatabaseHelper.kt
new file mode 100644
index 0000000..cc00456
--- /dev/null
+++ b/app/src/main/java/de/msdevs/einschlafhilfe/database/DatabaseHelper.kt
@@ -0,0 +1,57 @@
+package de.msdevs.einschlafhilfe.database
+
+import android.content.ContentValues
+import android.content.Context
+import android.database.Cursor
+import android.database.sqlite.SQLiteDatabase
+import android.util.Log
+import de.msdevs.einschlafhilfe.models.JsonResponse
+
+
+class DatabaseHelper(private val c: Context) {
+ fun insertFilterFolge(
+ database: SQLiteDatabase,
+ name: String?,
+ nummer: String?,
+ type: String?
+ ) {
+ val initialValues = ContentValues()
+ initialValues.put("name", name)
+ initialValues.put("nummer", nummer)
+ initialValues.put("type", type)
+ database.insert("filter", null, initialValues)
+ }
+
+ fun createTables(database: SQLiteDatabase) {
+ database.execSQL("CREATE TABLE IF NOT EXISTS filter(name VARCHAR, nummer VARCHAR, type VARCHAR);")
+ }
+
+
+ fun removeFromList(database: SQLiteDatabase, name: String) {
+ database.delete("filter", "name=?", arrayOf(name))
+ }
+
+ fun getFilterList(database: SQLiteDatabase): ArrayList {
+ val app_names = ArrayList()
+ var cursor: Cursor? = null
+ try {
+ cursor = database.rawQuery("Select * from filter", null)
+ if (cursor.moveToFirst()) {
+ do {
+ try {
+ app_names.add(JsonResponse(cursor.getString(0),"N/A","N/A",Integer.parseInt(cursor.getString(1)), cursor.getString(2)))
+ } catch (e: Exception) {
+ Log.e("DatabaseHelper", "Error: " + e.message)
+ }
+ } while (cursor.moveToNext())
+ }
+ } catch (e: Exception) {
+ Log.e("DatabaseHelper", "Error: " + e.message)
+ } finally {
+ cursor?.close()
+ }
+ return app_names
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/msdevs/einschlafhilfe/models/JsonResponse.kt b/app/src/main/java/de/msdevs/einschlafhilfe/models/JsonResponse.kt
index 73872c2..7964ce5 100644
--- a/app/src/main/java/de/msdevs/einschlafhilfe/models/JsonResponse.kt
+++ b/app/src/main/java/de/msdevs/einschlafhilfe/models/JsonResponse.kt
@@ -3,5 +3,7 @@ package de.msdevs.einschlafhilfe.models
class JsonResponse(
val name: String,
val beschreibung: String,
- val spotify: String
+ val spotify: String,
+ val nummer: Int,
+ val type : String
)
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml
new file mode 100644
index 0000000..60a0fd7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_delete.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_filter.xml b/app/src/main/res/layout/activity_filter.xml
index 762f67c..0ce85cd 100644
--- a/app/src/main/res/layout/activity_filter.xml
+++ b/app/src/main/res/layout/activity_filter.xml
@@ -3,31 +3,40 @@
android:layout_width="match_parent"
android:background="@color/black"
android:layout_height="match_parent">
-
-
-
-
-
+
+
+
-
+ android:layout_margin="10dp"
+ android:layout_height="wrap_content">
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_folge.xml b/app/src/main/res/layout/item_folge.xml
new file mode 100644
index 0000000..d55f94a
--- /dev/null
+++ b/app/src/main/res/layout/item_folge.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_autocomplete.xml b/app/src/main/res/layout/layout_autocomplete.xml
deleted file mode 100644
index a66924a..0000000
--- a/app/src/main/res/layout/layout_autocomplete.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0c92bfd..fadbafb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -68,6 +68,7 @@
Bob
Justus
Peter
+ Drittanbieter Bibliotheken
theme
Die drei ??? Sonderfolgen
Die drei ??? Kids Sonderfolgen
@@ -76,4 +77,6 @@
Klick auf den Button unten, um Folgen auszublenden, die du z. B. nicht im Besitz hast oder nicht gerne hörst.
Folgen auswählen
Es wurden noch keine Folgen hinzugefügt
+ Nummer: %1$s
+ Name der Folge
diff --git a/build.gradle b/build.gradle
index 0d39da9..0a84534 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,6 +8,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:8.3.0-rc01'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10"
+
}
}