feat: currently airing widget
This commit is contained in:
parent
95cddbd409
commit
df23b2f62f
15 changed files with 446 additions and 182 deletions
|
@ -49,20 +49,21 @@
|
||||||
android:name=".App"
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:banner="@mipmap/ic_banner_foreground"
|
android:banner="@mipmap/ic_banner_foreground"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:icon="${icon_placeholder}"
|
android:icon="${icon_placeholder}"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:enableOnBackInvokedCallback="true"
|
|
||||||
android:roundIcon="${icon_placeholder_round}"
|
android:roundIcon="${icon_placeholder_round}"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Dantotsu"
|
android:theme="@style/Theme.Dantotsu"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
tools:ignore="AllowBackup"
|
tools:ignore="AllowBackup"
|
||||||
tools:targetApi="tiramisu">
|
tools:targetApi="tiramisu">
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.CurrentlyAiringWidget"
|
android:name=".widgets.CurrentlyAiringWidget"
|
||||||
android:exported="false">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
@ -71,9 +72,15 @@
|
||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/currently_airing_widget_info" />
|
android:resource="@xml/currently_airing_widget_info" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
<activity
|
||||||
|
android:name=".widgets.CurrentlyAiringWidgetConfigureActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
<receiver android:name=".notifications.IncognitoNotificationClickReceiver" />
|
<receiver android:name=".notifications.IncognitoNotificationClickReceiver" />
|
||||||
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".media.novel.novelreader.NovelReaderActivity"
|
android:name=".media.novel.novelreader.NovelReaderActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
|
@ -106,27 +113,25 @@
|
||||||
android:parentActivityName=".MainActivity" />
|
android:parentActivityName=".MainActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".settings.ExtensionsActivity"
|
android:name=".settings.ExtensionsActivity"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden"
|
android:parentActivityName=".MainActivity"
|
||||||
android:parentActivityName=".MainActivity" />
|
android:windowSoftInputMode="adjustResize|stateHidden" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".profile.ProfileActivity"
|
android:name=".profile.ProfileActivity"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden"
|
android:parentActivityName=".MainActivity"
|
||||||
android:parentActivityName=".MainActivity" />
|
android:windowSoftInputMode="adjustResize|stateHidden" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".profile.FollowActivity"
|
android:name=".profile.FollowActivity"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden"
|
android:parentActivityName=".MainActivity"
|
||||||
android:parentActivityName=".MainActivity" />
|
android:windowSoftInputMode="adjustResize|stateHidden" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".profile.activity.FeedActivity"
|
android:name=".profile.activity.FeedActivity"
|
||||||
android:label="Inbox Activity"
|
|
||||||
android:configChanges="orientation|screenSize|screenLayout"
|
android:configChanges="orientation|screenSize|screenLayout"
|
||||||
android:parentActivityName=".MainActivity" >
|
android:label="Inbox Activity"
|
||||||
</activity>
|
android:parentActivityName=".MainActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".profile.activity.NotificationActivity"
|
android:name=".profile.activity.NotificationActivity"
|
||||||
android:label="Inbox Activity"
|
android:label="Inbox Activity"
|
||||||
android:parentActivityName=".MainActivity" >
|
android:parentActivityName=".MainActivity" />
|
||||||
</activity>
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".others.imagesearch.ImageSearchActivity"
|
android:name=".others.imagesearch.ImageSearchActivity"
|
||||||
android:parentActivityName=".MainActivity" />
|
android:parentActivityName=".MainActivity" />
|
||||||
|
@ -139,8 +144,9 @@
|
||||||
android:name=".media.CalendarActivity"
|
android:name=".media.CalendarActivity"
|
||||||
android:parentActivityName=".MainActivity" />
|
android:parentActivityName=".MainActivity" />
|
||||||
<activity android:name=".media.user.ListActivity" />
|
<activity android:name=".media.user.ListActivity" />
|
||||||
<activity android:name=".profile.SingleStatActivity"
|
<activity
|
||||||
android:parentActivityName=".profile.ProfileActivity"/>
|
android:name=".profile.SingleStatActivity"
|
||||||
|
android:parentActivityName=".profile.ProfileActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".media.manga.mangareader.MangaReaderActivity"
|
android:name=".media.manga.mangareader.MangaReaderActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
|
@ -152,7 +158,7 @@
|
||||||
android:name=".media.MediaDetailsActivity"
|
android:name=".media.MediaDetailsActivity"
|
||||||
android:parentActivityName=".MainActivity"
|
android:parentActivityName=".MainActivity"
|
||||||
android:theme="@style/Theme.Dantotsu.NeverCutout"
|
android:theme="@style/Theme.Dantotsu.NeverCutout"
|
||||||
android:windowSoftInputMode="adjustResize|stateHidden"/>
|
android:windowSoftInputMode="adjustResize|stateHidden" />
|
||||||
<activity android:name=".media.CharacterDetailsActivity" />
|
<activity android:name=".media.CharacterDetailsActivity" />
|
||||||
<activity android:name=".home.NoInternet" />
|
<activity android:name=".home.NoInternet" />
|
||||||
<activity
|
<activity
|
||||||
|
@ -234,7 +240,6 @@
|
||||||
<data android:host="discord.dantotsu.com" />
|
<data android:host="discord.dantotsu.com" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".connections.anilist.UrlMedia"
|
android:name=".connections.anilist.UrlMedia"
|
||||||
android:configChanges="orientation|screenSize|layoutDirection"
|
android:configChanges="orientation|screenSize|layoutDirection"
|
||||||
|
@ -293,7 +298,9 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
<data android:scheme="content" />
|
<data android:scheme="content" />
|
||||||
<data android:mimeType="*/*" />
|
<data android:mimeType="*/*" />
|
||||||
<data android:pathPattern=".*\\.ani" />
|
<data android:pathPattern=".*\\.ani" />
|
||||||
|
@ -306,22 +313,23 @@
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||||
|
|
||||||
<receiver android:name=".notifications.AlarmPermissionStateReceiver"
|
<receiver
|
||||||
|
android:name=".notifications.AlarmPermissionStateReceiver"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" />
|
<action android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
<receiver
|
||||||
<receiver android:name=".notifications.BootCompletedReceiver"
|
android:name=".notifications.BootCompletedReceiver"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver android:name=".notifications.anilist.AnilistNotificationReceiver"/>
|
<receiver android:name=".notifications.anilist.AnilistNotificationReceiver" />
|
||||||
<receiver android:name=".notifications.comment.CommentNotificationReceiver"/>
|
<receiver android:name=".notifications.comment.CommentNotificationReceiver" />
|
||||||
<receiver android:name=".notifications.subscription.SubscriptionNotificationReceiver"/>
|
<receiver android:name=".notifications.subscription.SubscriptionNotificationReceiver" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="preloaded_fonts"
|
android:name="preloaded_fonts"
|
||||||
|
|
|
@ -154,6 +154,7 @@ class App : MultiDexApplication() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private var instance: App? = null
|
private var instance: App? = null
|
||||||
|
|
||||||
/** Reference to the application context.
|
/** Reference to the application context.
|
||||||
*
|
*
|
||||||
* USE WITH EXTREME CAUTION!**/
|
* USE WITH EXTREME CAUTION!**/
|
||||||
|
|
|
@ -1430,6 +1430,24 @@ Page(page:$page,perPage:50) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getUpcomingAnime(id: String): List<Media> {
|
||||||
|
val res = executeQuery<Query.MediaListCollection>(
|
||||||
|
"""{MediaListCollection(userId:$id,type:ANIME){lists{name entries{media{id,isFavourite,title{userPreferred,romaji}coverImage{medium}nextAiringEpisode{timeUntilAiring}}}}}}""",
|
||||||
|
force = true
|
||||||
|
)
|
||||||
|
val list = mutableListOf<Media>()
|
||||||
|
res?.data?.mediaListCollection?.lists?.forEach { listEntry ->
|
||||||
|
listEntry.entries?.forEach { entry ->
|
||||||
|
entry.media?.nextAiringEpisode?.timeUntilAiring?.let {
|
||||||
|
list.add(Media(entry.media!!))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list.sortedBy { it.timeUntilAiring }
|
||||||
|
.distinctBy { it.id }
|
||||||
|
.filter { it.timeUntilAiring != null }
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun isUserFav(favType: AnilistMutations.FavType, id: Int): Boolean { //anilist isFavourite is broken, so we need to check it manually
|
suspend fun isUserFav(favType: AnilistMutations.FavType, id: Int): Boolean { //anilist isFavourite is broken, so we need to check it manually
|
||||||
val res = getUserProfile(Anilist.userid?: return false)
|
val res = getUserProfile(Anilist.userid?: return false)
|
||||||
return when (favType) {
|
return when (favType) {
|
||||||
|
|
|
@ -58,6 +58,8 @@ data class Media(
|
||||||
var endDate: FuzzyDate? = null,
|
var endDate: FuzzyDate? = null,
|
||||||
var popularity: Int? = null,
|
var popularity: Int? = null,
|
||||||
|
|
||||||
|
var timeUntilAiring: Long? = null,
|
||||||
|
|
||||||
var characters: ArrayList<Character>? = null,
|
var characters: ArrayList<Character>? = null,
|
||||||
var staff: ArrayList<Author>? = null,
|
var staff: ArrayList<Author>? = null,
|
||||||
var prequel: Media? = null,
|
var prequel: Media? = null,
|
||||||
|
@ -84,7 +86,7 @@ data class Media(
|
||||||
name = apiMedia.title!!.english,
|
name = apiMedia.title!!.english,
|
||||||
nameRomaji = apiMedia.title!!.romaji,
|
nameRomaji = apiMedia.title!!.romaji,
|
||||||
userPreferredName = apiMedia.title!!.userPreferred,
|
userPreferredName = apiMedia.title!!.userPreferred,
|
||||||
cover = apiMedia.coverImage?.large,
|
cover = apiMedia.coverImage?.large ?: apiMedia.coverImage?.medium,
|
||||||
banner = apiMedia.bannerImage,
|
banner = apiMedia.bannerImage,
|
||||||
status = apiMedia.status.toString(),
|
status = apiMedia.status.toString(),
|
||||||
isFav = apiMedia.isFavourite!!,
|
isFav = apiMedia.isFavourite!!,
|
||||||
|
@ -97,6 +99,7 @@ data class Media(
|
||||||
startDate = apiMedia.startDate,
|
startDate = apiMedia.startDate,
|
||||||
endDate = apiMedia.endDate,
|
endDate = apiMedia.endDate,
|
||||||
favourites = apiMedia.favourites,
|
favourites = apiMedia.favourites,
|
||||||
|
timeUntilAiring = apiMedia.nextAiringEpisode?.timeUntilAiring?.let { it.toLong() * 1000},
|
||||||
anime = if (apiMedia.type == MediaType.ANIME) Anime(
|
anime = if (apiMedia.type == MediaType.ANIME) Anime(
|
||||||
totalEpisodes = apiMedia.episodes,
|
totalEpisodes = apiMedia.episodes,
|
||||||
nextAiringEpisode = apiMedia.nextAiringEpisode?.episode?.minus(1)
|
nextAiringEpisode = apiMedia.nextAiringEpisode?.episode?.minus(1)
|
||||||
|
|
|
@ -1,12 +1,24 @@
|
||||||
package ani.dantotsu.widgets
|
package ani.dantotsu.widgets
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.BitmapShader
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.RectF
|
||||||
|
import android.graphics.Shader
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
import android.widget.RemoteViewsService
|
import android.widget.RemoteViewsService
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.util.Logger
|
import ani.dantotsu.util.Logger
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
@ -14,59 +26,47 @@ import java.net.URL
|
||||||
class CurrentlyAiringRemoteViewsFactory(private val context: Context) :
|
class CurrentlyAiringRemoteViewsFactory(private val context: Context) :
|
||||||
RemoteViewsService.RemoteViewsFactory {
|
RemoteViewsService.RemoteViewsFactory {
|
||||||
private var widgetItems = mutableListOf<WidgetItem>()
|
private var widgetItems = mutableListOf<WidgetItem>()
|
||||||
|
private var refreshing = false
|
||||||
|
private val prefs =
|
||||||
|
context.getSharedPreferences(CurrentlyAiringWidget.PREFS_NAME, Context.MODE_PRIVATE)
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
// 4 items for testing
|
|
||||||
widgetItems.clear()
|
|
||||||
Logger.log("CurrentlyAiringRemoteViewsFactory onCreate")
|
Logger.log("CurrentlyAiringRemoteViewsFactory onCreate")
|
||||||
widgetItems = List(4) {
|
fillWidgetItems()
|
||||||
WidgetItem(
|
}
|
||||||
"Show $it",
|
|
||||||
"$it days $it hours $it minutes",
|
private fun timeUntil(timeUntil: Long): String {
|
||||||
"https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
|
val days = timeUntil / (1000 * 60 * 60 * 24)
|
||||||
)
|
val hours = (timeUntil % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
|
||||||
}.toMutableList()
|
val minutes = ((timeUntil % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60)) / (1000 * 60)
|
||||||
|
return "$days days $hours hours $minutes minutes"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDataSetChanged() {
|
override fun onDataSetChanged() {
|
||||||
// 4 items for testing
|
if (refreshing) return
|
||||||
Logger.log("CurrentlyAiringRemoteViewsFactory onDataSetChanged")
|
Logger.log("CurrentlyAiringRemoteViewsFactory onDataSetChanged")
|
||||||
widgetItems.clear()
|
widgetItems.clear()
|
||||||
widgetItems.add(
|
fillWidgetItems()
|
||||||
WidgetItem(
|
|
||||||
"Show 1",
|
}
|
||||||
"1 day 2 hours 3 minutes",
|
|
||||||
"https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
|
private fun fillWidgetItems() {
|
||||||
)
|
refreshing = true
|
||||||
)
|
val userId = PrefManager.getVal<String>(PrefName.AnilistUserId)
|
||||||
widgetItems.add(
|
runBlocking(Dispatchers.IO) {
|
||||||
WidgetItem(
|
val upcoming = Anilist.query.getUpcomingAnime(userId)
|
||||||
"Show 2",
|
upcoming.forEach {
|
||||||
"2 days 3 hours 4 minutes",
|
widgetItems.add(
|
||||||
"https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
|
WidgetItem(
|
||||||
)
|
it.userPreferredName,
|
||||||
)
|
timeUntil(it.timeUntilAiring ?: 0),
|
||||||
widgetItems.add(
|
it.cover ?: "",
|
||||||
WidgetItem(
|
it.id
|
||||||
"Show 3",
|
)
|
||||||
"3 days 4 hours 5 minutes",
|
)
|
||||||
"https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
|
}
|
||||||
)
|
refreshing = false
|
||||||
)
|
}
|
||||||
widgetItems.add(
|
|
||||||
WidgetItem(
|
|
||||||
"Show 4",
|
|
||||||
"4 days 5 hours 6 minutes",
|
|
||||||
"https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
widgetItems.add(
|
|
||||||
WidgetItem(
|
|
||||||
"Show 5",
|
|
||||||
"5 days 6 hours 7 minutes",
|
|
||||||
"https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
@ -80,12 +80,20 @@ class CurrentlyAiringRemoteViewsFactory(private val context: Context) :
|
||||||
override fun getViewAt(position: Int): RemoteViews {
|
override fun getViewAt(position: Int): RemoteViews {
|
||||||
Logger.log("CurrentlyAiringRemoteViewsFactory getViewAt")
|
Logger.log("CurrentlyAiringRemoteViewsFactory getViewAt")
|
||||||
val item = widgetItems[position]
|
val item = widgetItems[position]
|
||||||
|
val titleTextColor = prefs.getInt(CurrentlyAiringWidget.PREF_TITLE_TEXT_COLOR, Color.WHITE)
|
||||||
|
val countdownTextColor =
|
||||||
|
prefs.getInt(CurrentlyAiringWidget.PREF_COUNTDOWN_TEXT_COLOR, Color.WHITE)
|
||||||
val rv = RemoteViews(context.packageName, R.layout.item_currently_airing_widget).apply {
|
val rv = RemoteViews(context.packageName, R.layout.item_currently_airing_widget).apply {
|
||||||
setTextViewText(R.id.text_show_title, item.title)
|
setTextViewText(R.id.text_show_title, item.title)
|
||||||
setTextViewText(R.id.text_show_countdown, item.countdown)
|
setTextViewText(R.id.text_show_countdown, item.countdown)
|
||||||
|
setTextColor(R.id.text_show_title, titleTextColor)
|
||||||
|
setTextColor(R.id.text_show_countdown, countdownTextColor)
|
||||||
val bitmap = downloadImageAsBitmap(item.image)
|
val bitmap = downloadImageAsBitmap(item.image)
|
||||||
//setImageViewUri(R.id.image_show_icon, Uri.parse(item.image))
|
|
||||||
setImageViewBitmap(R.id.image_show_icon, bitmap)
|
setImageViewBitmap(R.id.image_show_icon, bitmap)
|
||||||
|
val fillInIntent = Intent().apply {
|
||||||
|
putExtra("mediaId", item.id)
|
||||||
|
}
|
||||||
|
setOnClickFillInIntent(R.id.widget_item, fillInIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv
|
return rv
|
||||||
|
@ -108,16 +116,27 @@ class CurrentlyAiringRemoteViewsFactory(private val context: Context) :
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
// Handle the error according to your needs
|
|
||||||
} finally {
|
} finally {
|
||||||
// Clean up resources
|
|
||||||
inputStream?.close()
|
inputStream?.close()
|
||||||
urlConnection?.disconnect()
|
urlConnection?.disconnect()
|
||||||
}
|
}
|
||||||
|
return bitmap?.let { roundCorners(it) }
|
||||||
return bitmap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun roundCorners(bitmap: Bitmap): Bitmap {
|
||||||
|
val cornerRadius = 20f
|
||||||
|
val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(output)
|
||||||
|
val paint = Paint()
|
||||||
|
paint.isAntiAlias = true
|
||||||
|
paint.shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
|
||||||
|
val rect = RectF(0f, 0f, bitmap.width.toFloat(), bitmap.height.toFloat())
|
||||||
|
canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paint)
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun getLoadingView(): RemoteViews {
|
override fun getLoadingView(): RemoteViews {
|
||||||
return RemoteViews(context.packageName, R.layout.item_currently_airing_widget)
|
return RemoteViews(context.packageName, R.layout.item_currently_airing_widget)
|
||||||
}
|
}
|
||||||
|
@ -135,4 +154,4 @@ class CurrentlyAiringRemoteViewsFactory(private val context: Context) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class WidgetItem(val title: String, val countdown: String, val image: String)
|
data class WidgetItem(val title: String, val countdown: String, val image: String, val id: Int)
|
|
@ -12,7 +12,9 @@ import android.graphics.drawable.Drawable
|
||||||
import android.graphics.drawable.GradientDrawable
|
import android.graphics.drawable.GradientDrawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
import ani.dantotsu.MainActivity
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,25 +28,15 @@ class CurrentlyAiringWidget : AppWidgetProvider() {
|
||||||
appWidgetIds: IntArray
|
appWidgetIds: IntArray
|
||||||
) {
|
) {
|
||||||
appWidgetIds.forEach { appWidgetId ->
|
appWidgetIds.forEach { appWidgetId ->
|
||||||
val intent = Intent(context, CurrentlyAiringRemoteViewsService::class.java).apply {
|
val rv = updateAppWidget(context, appWidgetId)
|
||||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
|
||||||
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
|
||||||
}
|
|
||||||
|
|
||||||
val rv = RemoteViews(context.packageName, R.layout.currently_airing_widget).apply {
|
|
||||||
setRemoteAdapter(R.id.widgetListView, intent)
|
|
||||||
setEmptyView(R.id.widgetListView, R.id.empty_view)
|
|
||||||
}
|
|
||||||
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, rv)
|
appWidgetManager.updateAppWidget(appWidgetId, rv)
|
||||||
}
|
}
|
||||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
|
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
|
||||||
// When the user deletes the widget, delete the preference associated with it.
|
|
||||||
for (appWidgetId in appWidgetIds) {
|
for (appWidgetId in appWidgetIds) {
|
||||||
deleteTitlePref(context, appWidgetId)
|
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE).edit().clear().apply()
|
||||||
}
|
}
|
||||||
super.onDeleted(context, appWidgetIds)
|
super.onDeleted(context, appWidgetIds)
|
||||||
}
|
}
|
||||||
|
@ -57,34 +49,65 @@ class CurrentlyAiringWidget : AppWidgetProvider() {
|
||||||
super.onDisabled(context)
|
super.onDisabled(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun updateAppWidget(
|
fun updateAppWidget(
|
||||||
context: Context,
|
context: Context,
|
||||||
appWidgetManager: AppWidgetManager,
|
|
||||||
appWidgetId: Int,
|
appWidgetId: Int,
|
||||||
color: Int
|
): RemoteViews {
|
||||||
) {
|
val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||||
// Create an intent to launch the configuration activity when the widget is clicked
|
val backgroundColor =
|
||||||
val intent = Intent(context, CurrentlyAiringWidgetConfigureActivity::class.java)
|
prefs.getInt(PREF_BACKGROUND_COLOR, ContextCompat.getColor(context, R.color.theme))
|
||||||
val pendingIntent =
|
val backgroundFade = prefs.getInt(PREF_BACKGROUND_FADE, Color.GRAY)
|
||||||
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
|
val titleTextColor = prefs.getInt(PREF_TITLE_TEXT_COLOR, Color.WHITE)
|
||||||
|
val countdownTextColor = prefs.getInt(PREF_COUNTDOWN_TEXT_COLOR, Color.WHITE)
|
||||||
|
|
||||||
// Get the gradient drawable resource and update its start color with the user-selected color
|
val intent = Intent(context, CurrentlyAiringRemoteViewsService::class.java).apply {
|
||||||
|
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||||
|
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
||||||
|
}
|
||||||
val gradientDrawable = ResourcesCompat.getDrawable(
|
val gradientDrawable = ResourcesCompat.getDrawable(
|
||||||
context.resources,
|
context.resources,
|
||||||
R.drawable.gradient_background,
|
R.drawable.gradient_background,
|
||||||
null
|
null
|
||||||
) as GradientDrawable
|
) as GradientDrawable
|
||||||
gradientDrawable.colors = intArrayOf(color, Color.GRAY) // End color is gray.
|
gradientDrawable.colors = intArrayOf(backgroundColor, backgroundFade)
|
||||||
|
|
||||||
|
val intentTemplate = Intent(context, MainActivity::class.java)
|
||||||
|
intentTemplate.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
|
intentTemplate.putExtra("fromWidget", true)
|
||||||
|
|
||||||
// Create the RemoteViews object and set the background
|
|
||||||
val views = RemoteViews(context.packageName, R.layout.currently_airing_widget).apply {
|
val views = RemoteViews(context.packageName, R.layout.currently_airing_widget).apply {
|
||||||
//setImageViewBitmap(R.id.backgroundView, convertDrawableToBitmap(gradientDrawable))
|
setImageViewBitmap(R.id.backgroundView, convertDrawableToBitmap(gradientDrawable))
|
||||||
//setOnClickPendingIntent(R.id.backgroundView, pendingIntent)
|
setTextColor(R.id.text_show_title, titleTextColor)
|
||||||
|
setTextColor(R.id.text_show_countdown, countdownTextColor)
|
||||||
|
setTextColor(R.id.widgetTitle, titleTextColor)
|
||||||
|
setRemoteAdapter(R.id.widgetListView, intent)
|
||||||
|
setEmptyView(R.id.widgetListView, R.id.empty_view)
|
||||||
|
setPendingIntentTemplate(
|
||||||
|
R.id.widgetListView,
|
||||||
|
PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
0,
|
||||||
|
intentTemplate,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
setOnClickPendingIntent(
|
||||||
|
R.id.logoView,
|
||||||
|
PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
1,
|
||||||
|
Intent(context, CurrentlyAiringWidgetConfigureActivity::class.java).apply {
|
||||||
|
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||||
|
},
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instruct the widget manager to update the widget
|
return views
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertDrawableToBitmap(drawable: Drawable): Bitmap {
|
private fun convertDrawableToBitmap(drawable: Drawable): Bitmap {
|
||||||
|
@ -94,6 +117,12 @@ class CurrentlyAiringWidget : AppWidgetProvider() {
|
||||||
drawable.draw(canvas)
|
drawable.draw(canvas)
|
||||||
return bitmap
|
return bitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const val PREFS_NAME = "ani.dantotsu.widgets.CurrentlyAiringWidget"
|
||||||
|
const val PREF_BACKGROUND_COLOR = "background_color"
|
||||||
|
const val PREF_BACKGROUND_FADE = "background_fade"
|
||||||
|
const val PREF_TITLE_TEXT_COLOR = "title_text_color"
|
||||||
|
const val PREF_COUNTDOWN_TEXT_COLOR = "countdown_text_color"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,11 +131,7 @@ internal fun updateAppWidget(
|
||||||
appWidgetManager: AppWidgetManager,
|
appWidgetManager: AppWidgetManager,
|
||||||
appWidgetId: Int
|
appWidgetId: Int
|
||||||
) {
|
) {
|
||||||
val widgetText = loadTitlePref(context, appWidgetId)
|
val views = CurrentlyAiringWidget.updateAppWidget(context, appWidgetId)
|
||||||
// Construct the RemoteViews object
|
|
||||||
val views = RemoteViews(context.packageName, R.layout.currently_airing_widget)
|
|
||||||
views.setTextViewText(R.id.appwidget_text, widgetText)
|
|
||||||
|
|
||||||
// Instruct the widget manager to update the widget
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||||
|
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widgetListView)
|
||||||
}
|
}
|
|
@ -1,42 +1,36 @@
|
||||||
package ani.dantotsu.widgets
|
package ani.dantotsu.widgets
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.EditText
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.databinding.CurrentlyAiringWidgetConfigureBinding
|
import ani.dantotsu.databinding.CurrentlyAiringWidgetConfigureBinding
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
|
import eltos.simpledialogfragment.SimpleDialog
|
||||||
|
import eltos.simpledialogfragment.color.SimpleColorDialog
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration screen for the [CurrentlyAiringWidget] AppWidget.
|
* The configuration screen for the [CurrentlyAiringWidget] AppWidget.
|
||||||
*/
|
*/
|
||||||
class CurrentlyAiringWidgetConfigureActivity : Activity() {
|
class CurrentlyAiringWidgetConfigureActivity : AppCompatActivity(),
|
||||||
|
SimpleDialog.OnDialogResultListener {
|
||||||
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
||||||
private lateinit var appWidgetText: EditText
|
|
||||||
private var onClickListener = View.OnClickListener {
|
private var onClickListener = View.OnClickListener {
|
||||||
val context = this@CurrentlyAiringWidgetConfigureActivity
|
val context = this@CurrentlyAiringWidgetConfigureActivity
|
||||||
|
|
||||||
// When the button is clicked, store the string locally
|
|
||||||
val widgetText = appWidgetText.text.toString()
|
|
||||||
saveTitlePref(context, appWidgetId, widgetText)
|
|
||||||
|
|
||||||
// It is the responsibility of the configuration activity to update the app widget
|
|
||||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||||
//updateAppWidget(context, appWidgetManager, appWidgetId)
|
|
||||||
|
|
||||||
|
updateAppWidget(
|
||||||
CurrentlyAiringWidget.updateAppWidget(
|
|
||||||
context,
|
context,
|
||||||
appWidgetManager,
|
appWidgetManager,
|
||||||
appWidgetId,
|
appWidgetId,
|
||||||
-1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Make sure we pass back the original appWidgetId
|
|
||||||
val resultValue = Intent()
|
val resultValue = Intent()
|
||||||
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||||
setResult(RESULT_OK, resultValue)
|
setResult(RESULT_OK, resultValue)
|
||||||
|
@ -45,21 +39,87 @@ class CurrentlyAiringWidgetConfigureActivity : Activity() {
|
||||||
private lateinit var binding: CurrentlyAiringWidgetConfigureBinding
|
private lateinit var binding: CurrentlyAiringWidgetConfigureBinding
|
||||||
|
|
||||||
public override fun onCreate(icicle: Bundle?) {
|
public override fun onCreate(icicle: Bundle?) {
|
||||||
|
|
||||||
ThemeManager(this).applyTheme()
|
ThemeManager(this).applyTheme()
|
||||||
super.onCreate(icicle)
|
super.onCreate(icicle)
|
||||||
|
|
||||||
// Set the result to CANCELED. This will cause the widget host to cancel
|
|
||||||
// out of the widget placement if the user presses the back button.
|
|
||||||
setResult(RESULT_CANCELED)
|
setResult(RESULT_CANCELED)
|
||||||
|
|
||||||
binding = CurrentlyAiringWidgetConfigureBinding.inflate(layoutInflater)
|
binding = CurrentlyAiringWidgetConfigureBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
val prefs = getSharedPreferences(CurrentlyAiringWidget.PREFS_NAME, Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
binding.topBackgroundButton.setOnClickListener {
|
||||||
|
val tag = CurrentlyAiringWidget.PREF_BACKGROUND_COLOR
|
||||||
|
SimpleColorDialog().title(R.string.custom_theme)
|
||||||
|
.colorPreset(
|
||||||
|
prefs.getInt(
|
||||||
|
CurrentlyAiringWidget.PREF_BACKGROUND_COLOR,
|
||||||
|
ContextCompat.getColor(this, R.color.theme)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.colors(
|
||||||
|
this@CurrentlyAiringWidgetConfigureActivity,
|
||||||
|
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||||
|
)
|
||||||
|
.allowCustom(true)
|
||||||
|
.showOutline(0x46000000)
|
||||||
|
.gridNumColumn(5)
|
||||||
|
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||||
|
.neg()
|
||||||
|
.show(this@CurrentlyAiringWidgetConfigureActivity, tag)
|
||||||
|
}
|
||||||
|
binding.bottomBackgroundButton.setOnClickListener {
|
||||||
|
val tag = CurrentlyAiringWidget.PREF_BACKGROUND_FADE
|
||||||
|
SimpleColorDialog().title(R.string.custom_theme)
|
||||||
|
.colorPreset(prefs.getInt(CurrentlyAiringWidget.PREF_BACKGROUND_FADE, Color.GRAY))
|
||||||
|
.colors(
|
||||||
|
this@CurrentlyAiringWidgetConfigureActivity,
|
||||||
|
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||||
|
)
|
||||||
|
.allowCustom(true)
|
||||||
|
.showOutline(0x46000000)
|
||||||
|
.gridNumColumn(5)
|
||||||
|
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||||
|
.neg()
|
||||||
|
.show(this@CurrentlyAiringWidgetConfigureActivity, tag)
|
||||||
|
}
|
||||||
|
binding.titleColorButton.setOnClickListener {
|
||||||
|
val tag = CurrentlyAiringWidget.PREF_TITLE_TEXT_COLOR
|
||||||
|
SimpleColorDialog().title(R.string.custom_theme)
|
||||||
|
.colorPreset(prefs.getInt(CurrentlyAiringWidget.PREF_TITLE_TEXT_COLOR, Color.WHITE))
|
||||||
|
.colors(
|
||||||
|
this@CurrentlyAiringWidgetConfigureActivity,
|
||||||
|
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||||
|
)
|
||||||
|
.allowCustom(true)
|
||||||
|
.showOutline(0x46000000)
|
||||||
|
.gridNumColumn(5)
|
||||||
|
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||||
|
.neg()
|
||||||
|
.show(this@CurrentlyAiringWidgetConfigureActivity, tag)
|
||||||
|
}
|
||||||
|
binding.countdownColorButton.setOnClickListener {
|
||||||
|
val tag = CurrentlyAiringWidget.PREF_COUNTDOWN_TEXT_COLOR
|
||||||
|
SimpleColorDialog().title(R.string.custom_theme)
|
||||||
|
.colorPreset(
|
||||||
|
prefs.getInt(
|
||||||
|
CurrentlyAiringWidget.PREF_COUNTDOWN_TEXT_COLOR,
|
||||||
|
Color.WHITE
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.colors(
|
||||||
|
this@CurrentlyAiringWidgetConfigureActivity,
|
||||||
|
SimpleColorDialog.MATERIAL_COLOR_PALLET
|
||||||
|
)
|
||||||
|
.allowCustom(true)
|
||||||
|
.showOutline(0x46000000)
|
||||||
|
.gridNumColumn(5)
|
||||||
|
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||||
|
.neg()
|
||||||
|
.show(this@CurrentlyAiringWidgetConfigureActivity, tag)
|
||||||
|
}
|
||||||
|
|
||||||
appWidgetText = binding.appwidgetText
|
|
||||||
binding.addButton.setOnClickListener(onClickListener)
|
binding.addButton.setOnClickListener(onClickListener)
|
||||||
|
|
||||||
// Find the widget id from the intent.
|
|
||||||
val intent = intent
|
val intent = intent
|
||||||
val extras = intent.extras
|
val extras = intent.extras
|
||||||
if (extras != null) {
|
if (extras != null) {
|
||||||
|
@ -68,43 +128,66 @@ class CurrentlyAiringWidgetConfigureActivity : Activity() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this activity was started with an intent without an app widget ID, finish with an error.
|
|
||||||
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
appWidgetText.setText(
|
|
||||||
loadTitlePref(
|
|
||||||
this@CurrentlyAiringWidgetConfigureActivity,
|
|
||||||
appWidgetId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
override fun onResult(dialogTag: String, which: Int, extras: Bundle): Boolean {
|
||||||
|
if (which == SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE) {
|
||||||
|
when (dialogTag) {
|
||||||
|
CurrentlyAiringWidget.PREF_BACKGROUND_COLOR -> {
|
||||||
|
getSharedPreferences(
|
||||||
|
CurrentlyAiringWidget.PREFS_NAME,
|
||||||
|
Context.MODE_PRIVATE
|
||||||
|
).edit()
|
||||||
|
.putInt(
|
||||||
|
CurrentlyAiringWidget.PREF_BACKGROUND_COLOR,
|
||||||
|
extras.getInt(SimpleColorDialog.COLOR)
|
||||||
|
)
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
|
||||||
private const val PREFS_NAME = "ani.dantotsu.parsers.CurrentlyAiringWidget"
|
CurrentlyAiringWidget.PREF_BACKGROUND_FADE -> {
|
||||||
private const val PREF_PREFIX_KEY = "appwidget_"
|
getSharedPreferences(
|
||||||
|
CurrentlyAiringWidget.PREFS_NAME,
|
||||||
|
Context.MODE_PRIVATE
|
||||||
|
).edit()
|
||||||
|
.putInt(
|
||||||
|
CurrentlyAiringWidget.PREF_BACKGROUND_FADE,
|
||||||
|
extras.getInt(SimpleColorDialog.COLOR)
|
||||||
|
)
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
|
||||||
// Write the prefix to the SharedPreferences object for this widget
|
CurrentlyAiringWidget.PREF_TITLE_TEXT_COLOR -> {
|
||||||
internal fun saveTitlePref(context: Context, appWidgetId: Int, text: String) {
|
getSharedPreferences(
|
||||||
val prefs = context.getSharedPreferences(PREFS_NAME, 0).edit()
|
CurrentlyAiringWidget.PREFS_NAME,
|
||||||
prefs.putString(PREF_PREFIX_KEY + appWidgetId, text)
|
Context.MODE_PRIVATE
|
||||||
prefs.apply()
|
).edit()
|
||||||
}
|
.putInt(
|
||||||
|
CurrentlyAiringWidget.PREF_TITLE_TEXT_COLOR,
|
||||||
|
extras.getInt(SimpleColorDialog.COLOR)
|
||||||
|
)
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
|
||||||
// Read the prefix from the SharedPreferences object for this widget.
|
CurrentlyAiringWidget.PREF_COUNTDOWN_TEXT_COLOR -> {
|
||||||
// If there is no preference saved, get the default from a resource
|
getSharedPreferences(
|
||||||
internal fun loadTitlePref(context: Context, appWidgetId: Int): String {
|
CurrentlyAiringWidget.PREFS_NAME,
|
||||||
val prefs = context.getSharedPreferences(PREFS_NAME, 0)
|
Context.MODE_PRIVATE
|
||||||
val titleValue = prefs.getString(PREF_PREFIX_KEY + appWidgetId, null)
|
).edit()
|
||||||
return titleValue ?: context.getString(R.string.appwidget_text)
|
.putInt(
|
||||||
}
|
CurrentlyAiringWidget.PREF_COUNTDOWN_TEXT_COLOR,
|
||||||
|
extras.getInt(SimpleColorDialog.COLOR)
|
||||||
|
)
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
internal fun deleteTitlePref(context: Context, appWidgetId: Int) {
|
|
||||||
val prefs = context.getSharedPreferences(PREFS_NAME, 0).edit()
|
|
||||||
prefs.remove(PREF_PREFIX_KEY + appWidgetId)
|
|
||||||
prefs.apply()
|
|
||||||
}
|
}
|
|
@ -4,5 +4,5 @@
|
||||||
<gradient
|
<gradient
|
||||||
android:angle="270"
|
android:angle="270"
|
||||||
android:endColor="@color/grey_20"
|
android:endColor="@color/grey_20"
|
||||||
android:startColor="#B313DC" />
|
android:startColor="@color/theme"/>
|
||||||
</shape>
|
</shape>
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/logoView"
|
android:id="@+id/logoView"
|
||||||
android:layout_width="32dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="32dp"
|
android:layout_height="40dp"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:foregroundGravity="center_vertical"
|
android:foregroundGravity="center_vertical"
|
||||||
|
@ -31,20 +31,24 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/widgetTitle"
|
android:id="@+id/widgetTitle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="40dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_marginStart="0dp"
|
android:layout_marginStart="0dp"
|
||||||
android:layout_toEndOf="@+id/logoView"
|
android:layout_toEndOf="@+id/logoView"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical|start"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
android:text="@string/currently_airing"
|
android:text="@string/currently_airing"
|
||||||
android:textSize="18sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
android:id="@+id/widgetListView"
|
android:id="@+id/widgetListView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:scrollbars="none"
|
||||||
android:layout_below="@id/widgetTitle" />
|
android:layout_below="@id/widgetTitle" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -52,6 +56,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
android:text="@string/no_shows_to_display"
|
android:text="@string/no_shows_to_display"
|
||||||
android:textColor="#ffffff"
|
android:textColor="#ffffff"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="16dp">
|
android:padding="16dp">
|
||||||
|
|
||||||
|
@ -9,14 +10,103 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:labelFor="@id/appwidget_text"
|
|
||||||
android:text="@string/configure" />
|
android:text="@string/configure" />
|
||||||
|
|
||||||
<EditText
|
<Button
|
||||||
android:id="@+id/appwidget_text"
|
android:id="@+id/topBackgroundButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="64dp"
|
||||||
android:inputType="text" />
|
android:layout_marginStart="-31dp"
|
||||||
|
android:layout_marginEnd="-31dp"
|
||||||
|
android:background="@drawable/ui_bg"
|
||||||
|
android:backgroundTint="?attr/colorSecondary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:insetTop="0dp"
|
||||||
|
android:insetBottom="0dp"
|
||||||
|
android:paddingStart="31dp"
|
||||||
|
android:paddingEnd="31dp"
|
||||||
|
android:text="@string/top_background_color"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
app:cornerRadius="0dp"
|
||||||
|
app:icon="@drawable/ic_round_color_picker_24"
|
||||||
|
app:iconPadding="16dp"
|
||||||
|
app:iconSize="24dp"
|
||||||
|
app:iconTint="?attr/colorPrimary" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/bottomBackgroundButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:layout_marginStart="-31dp"
|
||||||
|
android:layout_marginEnd="-31dp"
|
||||||
|
android:background="@drawable/ui_bg"
|
||||||
|
android:backgroundTint="?attr/colorSecondary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:insetTop="0dp"
|
||||||
|
android:insetBottom="0dp"
|
||||||
|
android:paddingStart="31dp"
|
||||||
|
android:paddingEnd="31dp"
|
||||||
|
android:text="@string/bottom_background_color"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
app:cornerRadius="0dp"
|
||||||
|
app:icon="@drawable/ic_round_color_picker_24"
|
||||||
|
app:iconPadding="16dp"
|
||||||
|
app:iconSize="24dp"
|
||||||
|
app:iconTint="?attr/colorPrimary" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/titleColorButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:layout_marginStart="-31dp"
|
||||||
|
android:layout_marginEnd="-31dp"
|
||||||
|
android:background="@drawable/ui_bg"
|
||||||
|
android:backgroundTint="?attr/colorSecondary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:insetTop="0dp"
|
||||||
|
android:insetBottom="0dp"
|
||||||
|
android:paddingStart="31dp"
|
||||||
|
android:paddingEnd="31dp"
|
||||||
|
android:text="@string/title_color"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
app:cornerRadius="0dp"
|
||||||
|
app:icon="@drawable/ic_round_color_picker_24"
|
||||||
|
app:iconPadding="16dp"
|
||||||
|
app:iconSize="24dp"
|
||||||
|
app:iconTint="?attr/colorPrimary" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/countdownColorButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:layout_marginStart="-31dp"
|
||||||
|
android:layout_marginEnd="-31dp"
|
||||||
|
android:background="@drawable/ui_bg"
|
||||||
|
android:backgroundTint="?attr/colorSecondary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:insetTop="0dp"
|
||||||
|
android:insetBottom="0dp"
|
||||||
|
android:paddingStart="31dp"
|
||||||
|
android:paddingEnd="31dp"
|
||||||
|
android:text="@string/countdown_text_color"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
app:cornerRadius="0dp"
|
||||||
|
app:icon="@drawable/ic_round_color_picker_24"
|
||||||
|
app:iconPadding="16dp"
|
||||||
|
app:iconSize="24dp"
|
||||||
|
app:iconTint="?attr/colorPrimary" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/add_button"
|
android:id="@+id/add_button"
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/widget_item"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:padding="8dp">
|
android:padding="8dp">
|
||||||
|
@ -9,9 +11,10 @@
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/image_show_icon"
|
android:id="@+id/image_show_icon"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/airing_image"
|
app:shapeAppearanceOverlay="@style/roundedImageView"
|
||||||
android:src="@drawable/ic_launcher_foreground" />
|
android:contentDescription="@string/airing_image"/>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -25,8 +28,10 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/poppins_bold"
|
android:fontFamily="@font/poppins_bold"
|
||||||
android:text="Placeholder Title"
|
android:text=""
|
||||||
android:textColor="@color/bg_white"
|
android:textColor="@color/bg_white"
|
||||||
|
android:maxLines="3"
|
||||||
|
android:ellipsize="end"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -34,8 +39,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/poppins"
|
android:fontFamily="@font/poppins"
|
||||||
android:text="Placeholder Countdown"
|
android:text=""
|
||||||
android:textColor="@color/grey_60"
|
android:textColor="@color/bg_white"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
<color name="button_icon">#A9FFFFFF</color>
|
<color name="button_icon">#A9FFFFFF</color>
|
||||||
<color name="nav_status">#80FFFFFF</color>
|
<color name="nav_status">#80FFFFFF</color>
|
||||||
<color name="fav">#ad5edd</color>
|
<color name="fav">#ad5edd</color>
|
||||||
|
<color name="theme">#B313DC</color>
|
||||||
<color name="incognito">#291B65</color>
|
<color name="incognito">#291B65</color>
|
||||||
<color name="filler">#54FF8400</color>
|
<color name="filler">#54FF8400</color>
|
||||||
<color name="warning">#FF0000</color>
|
<color name="warning">#FF0000</color>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<string name="discord" translatable="false">https://discord.gg/4HPZ5nAWwM</string>
|
<string name="discord" translatable="false">https://discord.gg/4HPZ5nAWwM</string>
|
||||||
<string name="github" translatable="false">https://github.com/rebelonion/Dantotsu</string>
|
<string name="github" translatable="false">https://github.com/rebelonion/Dantotsu</string>
|
||||||
<string name="telegram" tools:ignore="Typos" translatable="false">https://t.me/+gzBCQExtLQo1YTNh </string>
|
<string name="telegram" translatable="false" tools:ignore="Typos">https://t.me/+gzBCQExtLQo1YTNh </string>
|
||||||
<string name="coffee" translatable="false">https://www.buymeacoffee.com/rebelonion</string>
|
<string name="coffee" translatable="false">https://www.buymeacoffee.com/rebelonion</string>
|
||||||
|
|
||||||
<string name="home">Home</string>
|
<string name="home">Home</string>
|
||||||
|
@ -811,4 +811,9 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
||||||
<string name="donate">donate :)</string>
|
<string name="donate">donate :)</string>
|
||||||
<string name="do_it">Do it!</string>
|
<string name="do_it">Do it!</string>
|
||||||
<string name="password">Password</string>
|
<string name="password">Password</string>
|
||||||
|
<string name="top_background_color">Top background color</string>
|
||||||
|
<string name="bottom_background_color">Bottom Background Color</string>
|
||||||
|
<string name="countdown_text_color">Countdown Text Color</string>
|
||||||
|
<string name="title_color">Title Color</string>
|
||||||
|
<string name="placeholder">Placeholder</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:description="@string/app_widget_description"
|
android:description="@string/app_widget_description"
|
||||||
|
android:configure="ani.dantotsu.widgets.CurrentlyAiringWidgetConfigureActivity"
|
||||||
android:initialKeyguardLayout="@layout/currently_airing_widget"
|
android:initialKeyguardLayout="@layout/currently_airing_widget"
|
||||||
android:initialLayout="@layout/currently_airing_widget"
|
android:initialLayout="@layout/currently_airing_widget"
|
||||||
android:minWidth="160dp"
|
android:minWidth="160dp"
|
||||||
|
@ -8,7 +9,5 @@
|
||||||
android:previewImage="@drawable/example_appwidget_preview"
|
android:previewImage="@drawable/example_appwidget_preview"
|
||||||
android:previewLayout="@layout/currently_airing_widget"
|
android:previewLayout="@layout/currently_airing_widget"
|
||||||
android:resizeMode="horizontal|vertical"
|
android:resizeMode="horizontal|vertical"
|
||||||
android:targetCellWidth="1"
|
android:updatePeriodMillis="3600000"
|
||||||
android:targetCellHeight="1"
|
android:widgetCategory="home_screen"/>
|
||||||
android:updatePeriodMillis="86400000"
|
|
||||||
android:widgetCategory="home_screen"></appwidget-provider>
|
|
|
@ -1,11 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:description="@string/app_widget_description"
|
android:description="@string/app_widget_description"
|
||||||
|
android:configure="ani.dantotsu.widgets.CurrentlyAiringWidgetConfigureActivity"
|
||||||
android:initialKeyguardLayout="@layout/currently_airing_widget"
|
android:initialKeyguardLayout="@layout/currently_airing_widget"
|
||||||
android:initialLayout="@layout/currently_airing_widget"
|
android:initialLayout="@layout/currently_airing_widget"
|
||||||
android:minWidth="160dp"
|
android:minWidth="160dp"
|
||||||
android:minHeight="160dp"
|
android:minHeight="160dp"
|
||||||
android:previewImage="@drawable/example_appwidget_preview"
|
android:previewImage="@drawable/example_appwidget_preview"
|
||||||
android:resizeMode="horizontal|vertical"
|
android:resizeMode="horizontal|vertical"
|
||||||
android:updatePeriodMillis="86400000"
|
android:updatePeriodMillis="3600000"
|
||||||
android:widgetCategory="home_screen"></appwidget-provider>
|
android:widgetCategory="home_screen"/>
|
Loading…
Add table
Add a link
Reference in a new issue