diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a95d2a781..e56d2b92a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -46,7 +46,12 @@
android:label="@string/settings" />
+ android:label="@string/settings">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt b/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt
index 49cbf779d..d0cf6ef3a 100644
--- a/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt
@@ -25,7 +25,10 @@ import org.koitharu.kotatsu.core.local.cookies.persistence.SharedPrefsCookiePers
import org.koitharu.kotatsu.core.parser.UserAgentInterceptor
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.domain.MangaLoaderContext
+import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
+import org.koitharu.kotatsu.domain.history.HistoryRepository
import org.koitharu.kotatsu.ui.utils.AppCrashHandler
+import org.koitharu.kotatsu.ui.widget.WidgetUpdater
import org.koitharu.kotatsu.utils.CacheUtils
import java.util.concurrent.TimeUnit
@@ -48,6 +51,9 @@ class KotatsuApp : Application() {
initErrorHandler()
}
AppCompatDelegate.setDefaultNightMode(AppSettings(this).theme)
+ val widgetUpdater = WidgetUpdater(applicationContext)
+ FavouritesRepository.subscribe(widgetUpdater)
+ HistoryRepository.subscribe(widgetUpdater)
}
private fun initKoin() {
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt
index 1e91e3da3..ec9623306 100644
--- a/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/details/MangaDetailsActivity.kt
@@ -172,7 +172,7 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
companion object {
private const val EXTRA_MANGA = "manga"
- private const val EXTRA_MANGA_ID = "manga_id"
+ const val EXTRA_MANGA_ID = "manga_id"
const val ACTION_MANGA_VIEW = "${BuildConfig.APPLICATION_ID}.action.VIEW_MANGA"
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/SimpleSettingsActivity.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/SimpleSettingsActivity.kt
index 175756b4a..8c7f20ac0 100644
--- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/SimpleSettingsActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/SimpleSettingsActivity.kt
@@ -4,9 +4,11 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.commit
+import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.ui.common.BaseActivity
import org.koitharu.kotatsu.ui.settings.MainSettingsFragment
+import org.koitharu.kotatsu.ui.settings.NetworkSettingsFragment
import org.koitharu.kotatsu.ui.settings.ReaderSettingsFragment
class SimpleSettingsActivity : BaseActivity() {
@@ -15,10 +17,10 @@ class SimpleSettingsActivity : BaseActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings_simple)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
- val section = intent?.getIntExtra(EXTRA_SECTION, 0)
supportFragmentManager.commit {
- replace(R.id.container, when(section) {
- SECTION_READER -> ReaderSettingsFragment()
+ replace(R.id.container, when(intent?.action) {
+ Intent.ACTION_MANAGE_NETWORK_USAGE -> NetworkSettingsFragment()
+ ACTION_READER -> ReaderSettingsFragment()
else -> MainSettingsFragment()
})
}
@@ -26,10 +28,9 @@ class SimpleSettingsActivity : BaseActivity() {
companion object {
- private const val EXTRA_SECTION = "section"
- private const val SECTION_READER = 1
+ private const val ACTION_READER = "${BuildConfig.APPLICATION_ID}.action.MANAGE_READER_SETTINGS"
fun newReaderSettingsIntent(context: Context) = Intent(context, SimpleSettingsActivity::class.java)
- .putExtra(EXTRA_SECTION, SECTION_READER)
+ .setAction(ACTION_READER)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/settings/NetworkSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/ui/settings/NetworkSettingsFragment.kt
new file mode 100644
index 000000000..b4109e45c
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/settings/NetworkSettingsFragment.kt
@@ -0,0 +1,12 @@
+package org.koitharu.kotatsu.ui.settings
+
+import android.os.Bundle
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.ui.common.BasePreferenceFragment
+
+class NetworkSettingsFragment : BasePreferenceFragment(R.string.settings) {
+
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ //TODO https://developer.android.com/training/basics/network-ops/managing
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/widget/WidgetUpdater.kt b/app/src/main/java/org/koitharu/kotatsu/ui/widget/WidgetUpdater.kt
new file mode 100644
index 000000000..ac762dc3c
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/widget/WidgetUpdater.kt
@@ -0,0 +1,31 @@
+package org.koitharu.kotatsu.ui.widget
+
+import android.appwidget.AppWidgetManager
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import org.koitharu.kotatsu.domain.favourites.OnFavouritesChangeListener
+import org.koitharu.kotatsu.domain.history.OnHistoryChangeListener
+import org.koitharu.kotatsu.ui.widget.recent.RecentWidgetProvider
+import org.koitharu.kotatsu.ui.widget.shelf.ShelfWidgetProvider
+
+class WidgetUpdater(private val context: Context) : OnFavouritesChangeListener,
+ OnHistoryChangeListener {
+
+ override fun onFavouritesChanged(mangaId: Long) {
+ updateWidget(ShelfWidgetProvider::class.java)
+ }
+
+ override fun onHistoryChanged() {
+ updateWidget(RecentWidgetProvider::class.java)
+ }
+
+ private fun updateWidget(cls: Class<*>) {
+ val intent = Intent(context, cls)
+ intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
+ val ids = AppWidgetManager.getInstance(context)
+ .getAppWidgetIds(ComponentName(context, cls))
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
+ context.sendBroadcast(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/widget/recent/RecentListFactory.kt b/app/src/main/java/org/koitharu/kotatsu/ui/widget/recent/RecentListFactory.kt
new file mode 100644
index 000000000..27d308ab2
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/widget/recent/RecentListFactory.kt
@@ -0,0 +1,61 @@
+package org.koitharu.kotatsu.ui.widget.recent
+
+import android.content.Context
+import android.content.Intent
+import android.widget.RemoteViews
+import android.widget.RemoteViewsService
+import androidx.core.graphics.drawable.toBitmap
+import coil.Coil
+import coil.api.get
+import kotlinx.coroutines.runBlocking
+import okio.IOException
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.model.Manga
+import org.koitharu.kotatsu.domain.history.HistoryRepository
+import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
+
+class RecentListFactory(context: Context, private val intent: Intent) : RemoteViewsService.RemoteViewsFactory {
+
+ private val packageName = context.packageName
+
+ private val dataSet = ArrayList()
+
+ override fun onCreate() {
+ }
+
+ override fun getLoadingView() = null
+
+ override fun getItemId(position: Int) = dataSet[position].id
+
+ override fun onDataSetChanged() {
+ dataSet.clear()
+ val data = runBlocking { HistoryRepository().getList(0, 10) }
+ dataSet.addAll(data)
+ }
+
+ override fun hasStableIds() = true
+
+ override fun getViewAt(position: Int): RemoteViews {
+ val views = RemoteViews(packageName, R.layout.item_recent)
+ val item = dataSet[position]
+ try {
+ val cover = runBlocking {
+ Coil.loader().get(item.coverUrl).toBitmap()
+ }
+ views.setImageViewBitmap(R.id.imageView_cover, cover)
+ } catch (e: IOException) {
+ views.setImageViewResource(R.id.imageView_cover, R.drawable.ic_placeholder)
+ }
+ val intent = Intent()
+ intent.putExtra(MangaDetailsActivity.EXTRA_MANGA_ID, item.id)
+ views.setOnClickFillInIntent(R.id.imageView_cover, intent)
+ return views
+ }
+
+ override fun getCount() = dataSet.size
+
+ override fun getViewTypeCount() = 1
+
+ override fun onDestroy() {
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/widget/recent/RecentWidgetProvider.kt b/app/src/main/java/org/koitharu/kotatsu/ui/widget/recent/RecentWidgetProvider.kt
new file mode 100644
index 000000000..25f2623e3
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/widget/recent/RecentWidgetProvider.kt
@@ -0,0 +1,39 @@
+package org.koitharu.kotatsu.ui.widget.recent
+
+import android.app.PendingIntent
+import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetProvider
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.widget.RemoteViews
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
+
+class RecentWidgetProvider : AppWidgetProvider() {
+
+ override fun onUpdate(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetIds: IntArray
+ ) {
+ appWidgetIds.forEach { id ->
+ val views = RemoteViews(context.packageName, R.layout.widget_recent)
+ val adapter = Intent(context, RecentWidgetService::class.java)
+ adapter.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id)
+ adapter.data = Uri.parse(adapter.toUri(Intent.URI_INTENT_SCHEME))
+ views.setRemoteAdapter(R.id.stackView, adapter)
+ val intent = Intent(context, MangaDetailsActivity::class.java)
+ intent.action = MangaDetailsActivity.ACTION_MANGA_VIEW
+ views.setPendingIntentTemplate(R.id.stackView, PendingIntent.getActivity(
+ context,
+ 0,
+ intent,
+ PendingIntent.FLAG_UPDATE_CURRENT
+ ))
+ views.setEmptyView(R.id.stackView, R.id.textView_holder)
+ appWidgetManager.updateAppWidget(id, views)
+ }
+ appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.stackView)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/widget/recent/RecentWidgetService.kt b/app/src/main/java/org/koitharu/kotatsu/ui/widget/recent/RecentWidgetService.kt
new file mode 100644
index 000000000..1b1d9691b
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/widget/recent/RecentWidgetService.kt
@@ -0,0 +1,11 @@
+package org.koitharu.kotatsu.ui.widget.recent
+
+import android.content.Intent
+import android.widget.RemoteViewsService
+
+class RecentWidgetService : RemoteViewsService() {
+
+ override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
+ return RecentListFactory(this, intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/widget/shelf/ShelfListFactory.kt b/app/src/main/java/org/koitharu/kotatsu/ui/widget/shelf/ShelfListFactory.kt
new file mode 100644
index 000000000..4f8cc74e1
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/widget/shelf/ShelfListFactory.kt
@@ -0,0 +1,62 @@
+package org.koitharu.kotatsu.ui.widget.shelf
+
+import android.content.Context
+import android.content.Intent
+import android.widget.RemoteViews
+import android.widget.RemoteViewsService
+import androidx.core.graphics.drawable.toBitmap
+import coil.Coil
+import coil.api.get
+import kotlinx.coroutines.runBlocking
+import okio.IOException
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.model.Manga
+import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
+import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
+
+class ShelfListFactory(context: Context, private val intent: Intent) : RemoteViewsService.RemoteViewsFactory {
+
+ private val packageName = context.packageName
+
+ private val dataSet = ArrayList()
+
+ override fun onCreate() {
+ }
+
+ override fun getLoadingView() = null
+
+ override fun getItemId(position: Int) = dataSet[position].id
+
+ override fun onDataSetChanged() {
+ dataSet.clear()
+ val data = runBlocking { FavouritesRepository().getAllManga(0) }
+ dataSet.addAll(data)
+ }
+
+ override fun hasStableIds() = true
+
+ override fun getViewAt(position: Int): RemoteViews {
+ val views = RemoteViews(packageName, R.layout.item_shelf)
+ val item = dataSet[position]
+ views.setTextViewText(R.id.textView_title, item.title)
+ try {
+ val cover = runBlocking {
+ Coil.loader().get(item.coverUrl).toBitmap()
+ }
+ views.setImageViewBitmap(R.id.imageView_cover, cover)
+ } catch (e: IOException) {
+ views.setImageViewResource(R.id.imageView_cover, R.drawable.ic_placeholder)
+ }
+ val intent = Intent()
+ intent.putExtra(MangaDetailsActivity.EXTRA_MANGA_ID, item.id)
+ views.setOnClickFillInIntent(R.id.rootLayout, intent)
+ return views
+ }
+
+ override fun getCount() = dataSet.size
+
+ override fun getViewTypeCount() = 1
+
+ override fun onDestroy() {
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/widget/shelf/ShelfWidgetProvider.kt b/app/src/main/java/org/koitharu/kotatsu/ui/widget/shelf/ShelfWidgetProvider.kt
new file mode 100644
index 000000000..d84dcd882
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/widget/shelf/ShelfWidgetProvider.kt
@@ -0,0 +1,39 @@
+package org.koitharu.kotatsu.ui.widget.shelf
+
+import android.app.PendingIntent
+import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetProvider
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.widget.RemoteViews
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.ui.details.MangaDetailsActivity
+
+class ShelfWidgetProvider : AppWidgetProvider() {
+
+ override fun onUpdate(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetIds: IntArray
+ ) {
+ appWidgetIds.forEach { id ->
+ val views = RemoteViews(context.packageName, R.layout.widget_shelf)
+ val adapter = Intent(context, ShelfWidgetService::class.java)
+ adapter.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id)
+ adapter.data = Uri.parse(adapter.toUri(Intent.URI_INTENT_SCHEME))
+ views.setRemoteAdapter(R.id.gridView, adapter)
+ val intent = Intent(context, MangaDetailsActivity::class.java)
+ intent.action = MangaDetailsActivity.ACTION_MANGA_VIEW
+ views.setPendingIntentTemplate(R.id.gridView, PendingIntent.getActivity(
+ context,
+ 0,
+ intent,
+ PendingIntent.FLAG_UPDATE_CURRENT
+ ))
+ views.setEmptyView(R.id.gridView, R.id.textView_holder)
+ appWidgetManager.updateAppWidget(id, views)
+ }
+ appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.gridView)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/widget/shelf/ShelfWidgetService.kt b/app/src/main/java/org/koitharu/kotatsu/ui/widget/shelf/ShelfWidgetService.kt
new file mode 100644
index 000000000..8882c7f6b
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/ui/widget/shelf/ShelfWidgetService.kt
@@ -0,0 +1,11 @@
+package org.koitharu.kotatsu.ui.widget.shelf
+
+import android.content.Intent
+import android.widget.RemoteViewsService
+
+class ShelfWidgetService : RemoteViewsService() {
+
+ override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
+ return ShelfListFactory(this, intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-nodpi/ic_appwidget_recent.png b/app/src/main/res/drawable-nodpi/ic_appwidget_recent.png
new file mode 100644
index 000000000..f0188ff69
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/ic_appwidget_recent.png differ
diff --git a/app/src/main/res/drawable-nodpi/ic_appwidget_shelf.png b/app/src/main/res/drawable-nodpi/ic_appwidget_shelf.png
new file mode 100644
index 000000000..de6a3094a
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/ic_appwidget_shelf.png differ
diff --git a/app/src/main/res/layout/item_recent.xml b/app/src/main/res/layout/item_recent.xml
new file mode 100644
index 000000000..e5b884dd4
--- /dev/null
+++ b/app/src/main/res/layout/item_recent.xml
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_shelf.xml b/app/src/main/res/layout/item_shelf.xml
new file mode 100644
index 000000000..e9d5575a9
--- /dev/null
+++ b/app/src/main/res/layout/item_shelf.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_recent.xml b/app/src/main/res/layout/widget_recent.xml
new file mode 100644
index 000000000..e10f76b3e
--- /dev/null
+++ b/app/src/main/res/layout/widget_recent.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_shelf.xml b/app/src/main/res/layout/widget_shelf.xml
new file mode 100644
index 000000000..0a5661fba
--- /dev/null
+++ b/app/src/main/res/layout/widget_shelf.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index cd0b772f8..ac2d48d4a 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -130,4 +130,6 @@
Категории помогают упорядочивать избранную мангу. Нажмите «+», чтобы создать категорию
Здесь будет оборажаться манга, которую Вы читаете. Вы можете найти, что почитать, в боковом меню
У Вас пока нет сохранённой манги. Вы можете сохранить мангу из онлайн каталога или импортировать из файла
+ Полка с мангой
+ Recent manga
\ 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 29b58168a..ae01da578 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -131,4 +131,6 @@
You can use categories to organize your favourite manga. Press «+» to create a category
Manga you are reading will be displayed here. You can find what to read in side menu
You have not any saved manga yet. You can save it from online sources or import from file
+ Manga shelf
+ Recent manga
\ No newline at end of file
diff --git a/app/src/main/res/xml/widget_recent.xml b/app/src/main/res/xml/widget_recent.xml
new file mode 100644
index 000000000..5265e8a9a
--- /dev/null
+++ b/app/src/main/res/xml/widget_recent.xml
@@ -0,0 +1,12 @@
+
+
diff --git a/app/src/main/res/xml/widget_shelf.xml b/app/src/main/res/xml/widget_shelf.xml
new file mode 100644
index 000000000..2dab58bf4
--- /dev/null
+++ b/app/src/main/res/xml/widget_shelf.xml
@@ -0,0 +1,12 @@
+
+