Recent manga app widget
This commit is contained in:
@@ -67,8 +67,11 @@
|
|||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".ui.widget.shelf.ShelfWidgetService"
|
android:name=".ui.widget.shelf.ShelfWidgetService"
|
||||||
android:permission="android.permission.BIND_REMOTEVIEWS">
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
</service>
|
|
||||||
|
<service
|
||||||
|
android:name=".ui.widget.recent.RecentWidgetService"
|
||||||
|
android:permission="android.permission.BIND_REMOTEVIEWS" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".ui.tracker.TrackerJobService"
|
android:name=".ui.tracker.TrackerJobService"
|
||||||
@@ -99,6 +102,15 @@
|
|||||||
android:resource="@xml/widget_shelf" />
|
android:resource="@xml/widget_shelf" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<receiver android:name=".ui.widget.recent.RecentWidgetProvider"
|
||||||
|
android:label="@string/recent_manga">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/widget_recent" />
|
||||||
|
</receiver>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -26,6 +26,7 @@ import org.koitharu.kotatsu.core.parser.UserAgentInterceptor
|
|||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||||
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
||||||
|
import org.koitharu.kotatsu.domain.history.HistoryRepository
|
||||||
import org.koitharu.kotatsu.ui.tracker.TrackerJobService
|
import org.koitharu.kotatsu.ui.tracker.TrackerJobService
|
||||||
import org.koitharu.kotatsu.ui.utils.AppCrashHandler
|
import org.koitharu.kotatsu.ui.utils.AppCrashHandler
|
||||||
import org.koitharu.kotatsu.ui.widget.WidgetUpdater
|
import org.koitharu.kotatsu.ui.widget.WidgetUpdater
|
||||||
@@ -51,6 +52,7 @@ class KotatsuApp : Application() {
|
|||||||
AppCompatDelegate.setDefaultNightMode(AppSettings(this).theme)
|
AppCompatDelegate.setDefaultNightMode(AppSettings(this).theme)
|
||||||
val widgetUpdater = WidgetUpdater(applicationContext)
|
val widgetUpdater = WidgetUpdater(applicationContext)
|
||||||
FavouritesRepository.subscribe(widgetUpdater)
|
FavouritesRepository.subscribe(widgetUpdater)
|
||||||
|
HistoryRepository.subscribe(widgetUpdater)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initKoin() {
|
private fun initKoin() {
|
||||||
|
|||||||
@@ -5,17 +5,27 @@ import android.content.ComponentName
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import org.koitharu.kotatsu.domain.favourites.OnFavouritesChangeListener
|
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
|
import org.koitharu.kotatsu.ui.widget.shelf.ShelfWidgetProvider
|
||||||
|
|
||||||
class WidgetUpdater(private val context: Context) : OnFavouritesChangeListener {
|
class WidgetUpdater(private val context: Context) : OnFavouritesChangeListener,
|
||||||
|
OnHistoryChangeListener {
|
||||||
|
|
||||||
override fun onFavouritesChanged(mangaId: Long) {
|
override fun onFavouritesChanged(mangaId: Long) {
|
||||||
val intent = Intent(context, ShelfWidgetProvider::class.java)
|
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
|
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||||
val ids = AppWidgetManager.getInstance(context)
|
val ids = AppWidgetManager.getInstance(context)
|
||||||
.getAppWidgetIds(ComponentName(context, ShelfWidgetProvider::class.java))
|
.getAppWidgetIds(ComponentName(context, cls))
|
||||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
|
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
|
||||||
context.sendBroadcast(intent)
|
context.sendBroadcast(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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<Manga>()
|
||||||
|
|
||||||
|
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() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
app/src/main/res/drawable-nodpi/ic_appwidget_recent.png
Normal file
BIN
app/src/main/res/drawable-nodpi/ic_appwidget_recent.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
9
app/src/main/res/layout/item_recent.xml
Normal file
9
app/src/main/res/layout/item_recent.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ImageView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/imageView_cover"
|
||||||
|
android:layout_width="92dp"
|
||||||
|
android:layout_height="128dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
23
app/src/main/res/layout/widget_recent.xml
Normal file
23
app/src/main/res/layout/widget_recent.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<StackView
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/stackView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:listitem="@layout/item_shelf" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView_holder"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/history_is_empty"
|
||||||
|
android:textColor="?android:textColorPrimary" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -119,4 +119,5 @@
|
|||||||
<string name="read_from_start">Читать с начала</string>
|
<string name="read_from_start">Читать с начала</string>
|
||||||
<string name="restart">Перезапустить</string>
|
<string name="restart">Перезапустить</string>
|
||||||
<string name="manga_shelf">Полка с мангой</string>
|
<string name="manga_shelf">Полка с мангой</string>
|
||||||
|
<string name="recent_manga">Recent manga</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -120,4 +120,5 @@
|
|||||||
<string name="read_from_start">Read from start</string>
|
<string name="read_from_start">Read from start</string>
|
||||||
<string name="restart">Restart</string>
|
<string name="restart">Restart</string>
|
||||||
<string name="manga_shelf">Manga shelf</string>
|
<string name="manga_shelf">Manga shelf</string>
|
||||||
|
<string name="recent_manga">Recent manga</string>
|
||||||
</resources>
|
</resources>
|
||||||
12
app/src/main/res/xml/widget_recent.xml
Normal file
12
app/src/main/res/xml/widget_recent.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appwidget-provider
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:initialLayout="@layout/widget_recent"
|
||||||
|
android:minWidth="40dp"
|
||||||
|
android:minHeight="110dp"
|
||||||
|
android:minResizeWidth="40dp"
|
||||||
|
android:minResizeHeight="40dp"
|
||||||
|
android:previewImage="@drawable/ic_appwidget_recent"
|
||||||
|
android:resizeMode="horizontal|vertical"
|
||||||
|
android:updatePeriodMillis="0"
|
||||||
|
android:widgetCategory="home_screen" />
|
||||||
Reference in New Issue
Block a user