diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7cc2e732..fdab5a4c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -49,31 +49,38 @@
android:name=".App"
android:allowBackup="true"
android:banner="@mipmap/ic_banner_foreground"
+ android:enableOnBackInvokedCallback="true"
android:icon="${icon_placeholder}"
android:label="@string/app_name"
android:largeHeap="true"
android:requestLegacyExternalStorage="true"
- android:enableOnBackInvokedCallback="true"
android:roundIcon="${icon_placeholder_round}"
android:supportsRtl="true"
android:theme="@style/Theme.Dantotsu"
android:usesCleartextTraffic="true"
tools:ignore="AllowBackup"
tools:targetApi="tiramisu">
+
+ android:name=".widgets.upcoming.UpcomingWidget"
+ android:exported="true">
+ android:resource="@xml/upcoming_widget_info" />
+
+
+
+
+
-
+ android:parentActivityName=".MainActivity"
+ android:windowSoftInputMode="adjustResize|stateHidden" />
+ android:parentActivityName=".MainActivity"
+ android:windowSoftInputMode="adjustResize|stateHidden" />
+ android:parentActivityName=".MainActivity"
+ android:windowSoftInputMode="adjustResize|stateHidden" />
-
+ android:label="Inbox Activity"
+ android:parentActivityName=".MainActivity" />
-
+ android:parentActivityName=".MainActivity" />
@@ -139,8 +144,9 @@
android:name=".media.CalendarActivity"
android:parentActivityName=".MainActivity" />
-
+
+ android:windowSoftInputMode="adjustResize|stateHidden" />
-
+
+
@@ -306,22 +313,23 @@
android:exported="false"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
-
-
-
-
-
-
+
+
+
{
+ val res = executeQuery(
+ """{MediaListCollection(userId:$id,type:ANIME){lists{name entries{media{id,isFavourite,title{userPreferred,romaji}coverImage{medium}nextAiringEpisode{timeUntilAiring}}}}}}""",
+ force = true
+ )
+ val list = mutableListOf()
+ 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
val res = getUserProfile(Anilist.userid?: return false)
return when (favType) {
diff --git a/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt b/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt
index ea3bb1a9..2aacbda4 100644
--- a/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt
+++ b/app/src/main/java/ani/dantotsu/home/AnimePageAdapter.kt
@@ -4,6 +4,7 @@ import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.util.TypedValue
+import android.view.HapticFeedbackConstants
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -96,6 +97,7 @@ class AnimePageAdapter : RecyclerView.Adapter
+ view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
ContextCompat.startActivity(
view.context,
Intent(view.context, ProfileActivity::class.java)
@@ -167,7 +169,6 @@ class AnimePageAdapter : RecyclerView.Adapter
+ view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
ContextCompat.startActivity(
view.context,
Intent(view.context, ProfileActivity::class.java)
@@ -164,8 +166,9 @@ class MangaPageAdapter : RecyclerView.Adapter? = null,
var staff: ArrayList? = null,
var prequel: Media? = null,
@@ -84,7 +86,7 @@ data class Media(
name = apiMedia.title!!.english,
nameRomaji = apiMedia.title!!.romaji,
userPreferredName = apiMedia.title!!.userPreferred,
- cover = apiMedia.coverImage?.large,
+ cover = apiMedia.coverImage?.large ?: apiMedia.coverImage?.medium,
banner = apiMedia.bannerImage,
status = apiMedia.status.toString(),
isFav = apiMedia.isFavourite!!,
@@ -97,6 +99,7 @@ data class Media(
startDate = apiMedia.startDate,
endDate = apiMedia.endDate,
favourites = apiMedia.favourites,
+ timeUntilAiring = apiMedia.nextAiringEpisode?.timeUntilAiring?.let { it.toLong() * 1000},
anime = if (apiMedia.type == MediaType.ANIME) Anime(
totalEpisodes = apiMedia.episodes,
nextAiringEpisode = apiMedia.nextAiringEpisode?.episode?.minus(1)
diff --git a/app/src/main/java/ani/dantotsu/media/SearchActivity.kt b/app/src/main/java/ani/dantotsu/media/SearchActivity.kt
index bb71c46c..d2869be4 100644
--- a/app/src/main/java/ani/dantotsu/media/SearchActivity.kt
+++ b/app/src/main/java/ani/dantotsu/media/SearchActivity.kt
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.os.Bundle
import android.os.Parcelable
import android.view.View
+import android.view.WindowManager
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
@@ -156,7 +157,10 @@ class SearchActivity : AppCompatActivity() {
} else
headerAdaptor.requestFocus?.run()
- if (intent.getBooleanExtra("search", false)) search()
+ if (intent.getBooleanExtra("search", false)) {
+ window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED)
+ search()
+ }
}
}
}
diff --git a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt
index 0ec2d3bf..7e8143a4 100644
--- a/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt
+++ b/app/src/main/java/ani/dantotsu/media/comments/CommentsFragment.kt
@@ -28,6 +28,7 @@ import ani.dantotsu.connections.comments.CommentsAPI
import ani.dantotsu.databinding.FragmentCommentsBinding
import ani.dantotsu.loadImage
import ani.dantotsu.media.MediaDetailsActivity
+import ani.dantotsu.setBaseline
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString
@@ -73,6 +74,9 @@ class CommentsFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity = requireActivity() as MediaDetailsActivity
+
+ binding.commentsList.setBaseline(activity.navBar, activity.binding.commentInputLayout)
+
//get the media id from the intent
val mediaId = arguments?.getInt("mediaId") ?: -1
mediaName = arguments?.getString("mediaName") ?: "unknown"
@@ -366,6 +370,7 @@ class CommentsFragment : Fragment() {
override fun onResume() {
super.onResume()
tag = null
+ binding.commentsList.setBaseline(activity.navBar, activity.binding.commentInputLayout)
section.groups.forEach {
if (it is CommentItem && it.containsGif()) {
it.notifyChanged()
diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/ChapterLoaderDialog.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/ChapterLoaderDialog.kt
index 6c5233b7..699f43dc 100644
--- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/ChapterLoaderDialog.kt
+++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/ChapterLoaderDialog.kt
@@ -37,7 +37,7 @@ class ChapterLoaderDialog : BottomSheetDialogFragment() {
binding.selectorAutoListContainer.visibility = View.VISIBLE
binding.selectorListContainer.visibility = View.GONE
- binding.selectorTitle.text = getString(R.string.loading_next_chap)
+ binding.selectorTitle.text = getString(R.string.loading_chap_number, chp.number)
binding.selectorCancel.setOnClickListener {
dismiss()
}
diff --git a/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt b/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt
index d5c2f0c7..abbe26e5 100644
--- a/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt
+++ b/app/src/main/java/ani/dantotsu/profile/ProfileActivity.kt
@@ -46,7 +46,7 @@ import kotlin.math.abs
class ProfileActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListener {
lateinit var binding: ActivityProfileBinding
private var selected: Int = 0
- private lateinit var navBar: AnimatedBottomBar
+ lateinit var navBar: AnimatedBottomBar
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
diff --git a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt
index d008f966..6fd425be 100644
--- a/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt
+++ b/app/src/main/java/ani/dantotsu/profile/ProfileFragment.kt
@@ -30,6 +30,7 @@ import ani.dantotsu.media.CharacterAdapter
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaAdaptor
import ani.dantotsu.media.user.ListActivity
+import ani.dantotsu.setBaseline
import ani.dantotsu.setSlideIn
import ani.dantotsu.setSlideUp
import ani.dantotsu.util.AniMarkdown.Companion.getFullAniHTML
@@ -59,6 +60,8 @@ class ProfileFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
activity = requireActivity() as ProfileActivity
+ binding.root.setBaseline(activity.navBar)
+
user = arguments?.getSerializableCompat("user") as Query.UserProfile
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
model.setData(user.id)
@@ -144,6 +147,7 @@ class ProfileFragment : Fragment() {
super.onResume()
if (this::binding.isInitialized) {
binding.root.requestLayout()
+ binding.root.setBaseline(activity.navBar)
}
}
diff --git a/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt b/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt
index 2f01cac6..aaf0ed6f 100644
--- a/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt
+++ b/app/src/main/java/ani/dantotsu/profile/StatsFragment.kt
@@ -17,6 +17,7 @@ import ani.dantotsu.profile.ChartBuilder.Companion.ChartPacket
import ani.dantotsu.profile.ChartBuilder.Companion.ChartType
import ani.dantotsu.profile.ChartBuilder.Companion.MediaType
import ani.dantotsu.profile.ChartBuilder.Companion.StatType
+import ani.dantotsu.setBaseline
import ani.dantotsu.statusBarHeight
import com.github.aachartmodel.aainfographics.aachartcreator.AAChartType
import com.xwray.groupie.GroupieAdapter
@@ -49,8 +50,11 @@ class StatsFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity = requireActivity() as ProfileActivity
+
user = arguments?.getSerializableCompat("user") as Query.UserProfile
+ binding.statisticList.setBaseline(activity.navBar)
+
binding.statisticList.adapter = adapter
binding.statisticList.recycledViewPool.setMaxRecycledViews(0, 0)
binding.statisticList.isNestedScrollingEnabled = true
@@ -114,6 +118,7 @@ class StatsFragment :
super.onResume()
if (this::binding.isInitialized) {
binding.statisticList.visibility = View.VISIBLE
+ binding.statisticList.setBaseline(activity.navBar)
binding.root.requestLayout()
if (!loadedFirstTime) {
activity.lifecycleScope.launch {
diff --git a/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt b/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt
index 7ef09eb5..f50502f1 100644
--- a/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt
+++ b/app/src/main/java/ani/dantotsu/profile/activity/FeedFragment.kt
@@ -18,6 +18,7 @@ import ani.dantotsu.connections.anilist.api.Activity
import ani.dantotsu.databinding.FragmentFeedBinding
import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.profile.ProfileActivity
+import ani.dantotsu.setBaseline
import ani.dantotsu.snackString
import ani.dantotsu.util.Logger
import com.xwray.groupie.GroupieAdapter
@@ -48,6 +49,9 @@ class FeedFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity = requireActivity()
+
+ binding.listRecyclerView.setBaseline((activity as ProfileActivity).navBar)
+
binding.listRecyclerView.adapter = adapter
binding.listRecyclerView.layoutManager =
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
@@ -63,6 +67,7 @@ class FeedFragment : Fragment() {
super.onResume()
if (this::binding.isInitialized) {
binding.root.requestLayout()
+ binding.listRecyclerView.setBaseline((activity as ProfileActivity).navBar)
if (!loadedFirstTime) {
activity.lifecycleScope.launch(Dispatchers.IO) {
val nulledId = if (activityId == -1) null else activityId
diff --git a/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt b/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt
index 2c8b0e40..b803fb1b 100644
--- a/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt
+++ b/app/src/main/java/ani/dantotsu/settings/UserInterfaceSettingsActivity.kt
@@ -77,6 +77,11 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
restartApp(binding.root)
}
+ binding.uiSettingsTrendingScroller.isChecked = PrefManager.getVal(PrefName.TrendingScroller)
+ binding.uiSettingsTrendingScroller.setOnCheckedChangeListener { _, isChecked ->
+ PrefManager.setVal(PrefName.TrendingScroller, isChecked)
+ }
+
val map = mapOf(
2f to 0.5f,
1.75f to 0.625f,
diff --git a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt
index 28fb7a9a..76e80bb2 100644
--- a/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt
+++ b/app/src/main/java/ani/dantotsu/settings/saving/Preferences.kt
@@ -68,6 +68,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
),
BannerAnimations(Pref(Location.UI, Boolean::class, true)),
LayoutAnimations(Pref(Location.UI, Boolean::class, true)),
+ TrendingScroller(Pref(Location.UI, Boolean::class, true)),
AnimationSpeed(Pref(Location.UI, Float::class, 1f)),
ListGrid(Pref(Location.UI, Boolean::class, true)),
PopularMangaList(Pref(Location.UI, Boolean::class, true)),
diff --git a/app/src/main/java/ani/dantotsu/util/BitmapUtil.kt b/app/src/main/java/ani/dantotsu/util/BitmapUtil.kt
new file mode 100644
index 00000000..a4c4e7b6
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/util/BitmapUtil.kt
@@ -0,0 +1,33 @@
+package ani.dantotsu.util
+
+import android.graphics.Bitmap
+import android.graphics.BitmapShader
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.RectF
+import android.graphics.Shader
+import android.graphics.drawable.Drawable
+
+class BitmapUtil {
+ companion object {
+ fun roundCorners(bitmap: Bitmap, cornerRadius: Float = 20f): Bitmap {
+ 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
+ }
+
+ fun convertDrawableToBitmap(drawable: Drawable, width: Int, height: Int): Bitmap {
+ val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
+ val canvas = Canvas(bitmap)
+ drawable.setBounds(0, 0, canvas.width, canvas.height)
+ drawable.draw(canvas)
+ return bitmap
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt
deleted file mode 100644
index 8cf8029a..00000000
--- a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsFactory.kt
+++ /dev/null
@@ -1,138 +0,0 @@
-package ani.dantotsu.widgets
-
-import android.content.Context
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.widget.RemoteViews
-import android.widget.RemoteViewsService
-import ani.dantotsu.R
-import ani.dantotsu.util.Logger
-import java.io.InputStream
-import java.net.HttpURLConnection
-import java.net.URL
-
-class CurrentlyAiringRemoteViewsFactory(private val context: Context) :
- RemoteViewsService.RemoteViewsFactory {
- private var widgetItems = mutableListOf()
-
- override fun onCreate() {
- // 4 items for testing
- widgetItems.clear()
- Logger.log("CurrentlyAiringRemoteViewsFactory onCreate")
- widgetItems = List(4) {
- WidgetItem(
- "Show $it",
- "$it days $it hours $it minutes",
- "https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
- )
- }.toMutableList()
- }
-
- override fun onDataSetChanged() {
- // 4 items for testing
- Logger.log("CurrentlyAiringRemoteViewsFactory onDataSetChanged")
- widgetItems.clear()
- widgetItems.add(
- WidgetItem(
- "Show 1",
- "1 day 2 hours 3 minutes",
- "https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
- )
- )
- widgetItems.add(
- WidgetItem(
- "Show 2",
- "2 days 3 hours 4 minutes",
- "https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
- )
- )
- widgetItems.add(
- WidgetItem(
- "Show 3",
- "3 days 4 hours 5 minutes",
- "https://s4.anilist.co/file/anilistcdn/media/anime/cover/large/bx14741-alxqoP4yx6WF.jpg"
- )
- )
- 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() {
- widgetItems.clear()
- }
-
- override fun getCount(): Int {
- return widgetItems.size
- }
-
- override fun getViewAt(position: Int): RemoteViews {
- Logger.log("CurrentlyAiringRemoteViewsFactory getViewAt")
- val item = widgetItems[position]
- 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_countdown, item.countdown)
- val bitmap = downloadImageAsBitmap(item.image)
- //setImageViewUri(R.id.image_show_icon, Uri.parse(item.image))
- setImageViewBitmap(R.id.image_show_icon, bitmap)
- }
-
- return rv
- }
-
- private fun downloadImageAsBitmap(imageUrl: String): Bitmap? {
- var bitmap: Bitmap? = null
- var inputStream: InputStream? = null
- var urlConnection: HttpURLConnection? = null
-
- try {
- val url = URL(imageUrl)
- urlConnection = url.openConnection() as HttpURLConnection
- urlConnection.requestMethod = "GET"
- urlConnection.connect()
-
- if (urlConnection.responseCode == HttpURLConnection.HTTP_OK) {
- inputStream = urlConnection.inputStream
- bitmap = BitmapFactory.decodeStream(inputStream)
- }
- } catch (e: Exception) {
- e.printStackTrace()
- // Handle the error according to your needs
- } finally {
- // Clean up resources
- inputStream?.close()
- urlConnection?.disconnect()
- }
-
- return bitmap
- }
-
- override fun getLoadingView(): RemoteViews {
- return RemoteViews(context.packageName, R.layout.item_currently_airing_widget)
- }
-
- override fun getViewTypeCount(): Int {
- return 1
- }
-
- override fun getItemId(p0: Int): Long {
- return p0.toLong()
- }
-
- override fun hasStableIds(): Boolean {
- return true
- }
-}
-
-data class WidgetItem(val title: String, val countdown: String, val image: String)
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt
deleted file mode 100644
index 4d042b33..00000000
--- a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringRemoteViewsService.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package ani.dantotsu.widgets
-
-import android.content.Intent
-import android.widget.RemoteViewsService
-import ani.dantotsu.util.Logger
-
-class CurrentlyAiringRemoteViewsService : RemoteViewsService() {
- override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
- Logger.log("CurrentlyAiringRemoteViewsFactory onGetViewFactory")
- return CurrentlyAiringRemoteViewsFactory(applicationContext)
- }
-}
diff --git a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringWidget.kt b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringWidget.kt
deleted file mode 100644
index b2c3948c..00000000
--- a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringWidget.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package ani.dantotsu.widgets
-
-import android.app.PendingIntent
-import android.appwidget.AppWidgetManager
-import android.appwidget.AppWidgetProvider
-import android.content.Context
-import android.content.Intent
-import android.graphics.Bitmap
-import android.graphics.Canvas
-import android.graphics.Color
-import android.graphics.drawable.Drawable
-import android.graphics.drawable.GradientDrawable
-import android.net.Uri
-import android.widget.RemoteViews
-import androidx.core.content.res.ResourcesCompat
-import ani.dantotsu.R
-
-/**
- * Implementation of App Widget functionality.
- * App Widget Configuration implemented in [CurrentlyAiringWidgetConfigureActivity]
- */
-class CurrentlyAiringWidget : AppWidgetProvider() {
- override fun onUpdate(
- context: Context,
- appWidgetManager: AppWidgetManager,
- appWidgetIds: IntArray
- ) {
- appWidgetIds.forEach { appWidgetId ->
- val intent = Intent(context, CurrentlyAiringRemoteViewsService::class.java).apply {
- 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)
- }
- super.onUpdate(context, appWidgetManager, appWidgetIds)
- }
-
- override fun onDeleted(context: Context, appWidgetIds: IntArray) {
- // When the user deletes the widget, delete the preference associated with it.
- for (appWidgetId in appWidgetIds) {
- deleteTitlePref(context, appWidgetId)
- }
- super.onDeleted(context, appWidgetIds)
- }
-
- override fun onEnabled(context: Context) {
- super.onEnabled(context)
- }
-
- override fun onDisabled(context: Context) {
- super.onDisabled(context)
- }
-
- companion object {
- fun updateAppWidget(
- context: Context,
- appWidgetManager: AppWidgetManager,
- appWidgetId: Int,
- color: Int
- ) {
- // Create an intent to launch the configuration activity when the widget is clicked
- val intent = Intent(context, CurrentlyAiringWidgetConfigureActivity::class.java)
- val pendingIntent =
- PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
-
- // Get the gradient drawable resource and update its start color with the user-selected color
- val gradientDrawable = ResourcesCompat.getDrawable(
- context.resources,
- R.drawable.gradient_background,
- null
- ) as GradientDrawable
- gradientDrawable.colors = intArrayOf(color, Color.GRAY) // End color is gray.
-
- // Create the RemoteViews object and set the background
- val views = RemoteViews(context.packageName, R.layout.currently_airing_widget).apply {
- //setImageViewBitmap(R.id.backgroundView, convertDrawableToBitmap(gradientDrawable))
- //setOnClickPendingIntent(R.id.backgroundView, pendingIntent)
- }
-
- // Instruct the widget manager to update the widget
- appWidgetManager.updateAppWidget(appWidgetId, views)
- }
-
- private fun convertDrawableToBitmap(drawable: Drawable): Bitmap {
- val bitmap = Bitmap.createBitmap(100, 300, Bitmap.Config.ARGB_8888)
- val canvas = Canvas(bitmap)
- drawable.setBounds(0, 0, canvas.width, canvas.height)
- drawable.draw(canvas)
- return bitmap
- }
- }
-}
-
-internal fun updateAppWidget(
- context: Context,
- appWidgetManager: AppWidgetManager,
- appWidgetId: Int
-) {
- val widgetText = loadTitlePref(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)
-}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringWidgetConfigureActivity.kt b/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringWidgetConfigureActivity.kt
deleted file mode 100644
index 186f5151..00000000
--- a/app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringWidgetConfigureActivity.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-package ani.dantotsu.widgets
-
-import android.app.Activity
-import android.appwidget.AppWidgetManager
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import android.view.View
-import android.widget.EditText
-import ani.dantotsu.R
-import ani.dantotsu.databinding.CurrentlyAiringWidgetConfigureBinding
-import ani.dantotsu.themes.ThemeManager
-
-/**
- * The configuration screen for the [CurrentlyAiringWidget] AppWidget.
- */
-class CurrentlyAiringWidgetConfigureActivity : Activity() {
- private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
- private lateinit var appWidgetText: EditText
- private var onClickListener = View.OnClickListener {
- 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)
- //updateAppWidget(context, appWidgetManager, appWidgetId)
-
-
- CurrentlyAiringWidget.updateAppWidget(
- context,
- appWidgetManager,
- appWidgetId,
- -1
- )
-
- // Make sure we pass back the original appWidgetId
- val resultValue = Intent()
- resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
- setResult(RESULT_OK, resultValue)
- finish()
- }
- private lateinit var binding: CurrentlyAiringWidgetConfigureBinding
-
- public override fun onCreate(icicle: Bundle?) {
-
- ThemeManager(this).applyTheme()
- 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)
-
- binding = CurrentlyAiringWidgetConfigureBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
- appWidgetText = binding.appwidgetText
- binding.addButton.setOnClickListener(onClickListener)
-
- // Find the widget id from the intent.
- val intent = intent
- val extras = intent.extras
- if (extras != null) {
- appWidgetId = extras.getInt(
- AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID
- )
- }
-
- // If this activity was started with an intent without an app widget ID, finish with an error.
- if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
- finish()
- return
- }
-
- appWidgetText.setText(
- loadTitlePref(
- this@CurrentlyAiringWidgetConfigureActivity,
- appWidgetId
- )
- )
-
- }
-
-}
-
-private const val PREFS_NAME = "ani.dantotsu.parsers.CurrentlyAiringWidget"
-private const val PREF_PREFIX_KEY = "appwidget_"
-
-// Write the prefix to the SharedPreferences object for this widget
-internal fun saveTitlePref(context: Context, appWidgetId: Int, text: String) {
- val prefs = context.getSharedPreferences(PREFS_NAME, 0).edit()
- prefs.putString(PREF_PREFIX_KEY + appWidgetId, text)
- prefs.apply()
-}
-
-// Read the prefix from the SharedPreferences object for this widget.
-// If there is no preference saved, get the default from a resource
-internal fun loadTitlePref(context: Context, appWidgetId: Int): String {
- val prefs = context.getSharedPreferences(PREFS_NAME, 0)
- val titleValue = prefs.getString(PREF_PREFIX_KEY + appWidgetId, null)
- return titleValue ?: context.getString(R.string.appwidget_text)
-}
-
-internal fun deleteTitlePref(context: Context, appWidgetId: Int) {
- val prefs = context.getSharedPreferences(PREFS_NAME, 0).edit()
- prefs.remove(PREF_PREFIX_KEY + appWidgetId)
- prefs.apply()
-}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/widgets/WidgetSizeProvider.kt b/app/src/main/java/ani/dantotsu/widgets/WidgetSizeProvider.kt
new file mode 100644
index 00000000..3b5af9ca
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/widgets/WidgetSizeProvider.kt
@@ -0,0 +1,40 @@
+package ani.dantotsu.widgets
+
+import android.appwidget.AppWidgetManager
+import android.content.Context
+
+class WidgetSizeProvider(
+ private val context: Context // Do not pass Application context
+) {
+
+ private val appWidgetManager = AppWidgetManager.getInstance(context)
+
+ fun getWidgetsSize(widgetId: Int): Pair {
+ val isPortrait = context.resources.configuration.orientation == 1
+ val width = getWidgetWidth(isPortrait, widgetId)
+ val height = getWidgetHeight(isPortrait, widgetId)
+ val widthInPx = context.dip(width)
+ val heightInPx = context.dip(height)
+ return widthInPx to heightInPx
+ }
+
+ private fun getWidgetWidth(isPortrait: Boolean, widgetId: Int): Int =
+ if (isPortrait) {
+ getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
+ } else {
+ getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
+ }
+
+ private fun getWidgetHeight(isPortrait: Boolean, widgetId: Int): Int =
+ if (isPortrait) {
+ getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
+ } else {
+ getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
+ }
+
+ private fun getWidgetSizeInDp(widgetId: Int, key: String): Int =
+ appWidgetManager.getAppWidgetOptions(widgetId).getInt(key, 0)
+
+ private fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingRemoteViewsFactory.kt b/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingRemoteViewsFactory.kt
new file mode 100644
index 00000000..0991b2a4
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingRemoteViewsFactory.kt
@@ -0,0 +1,142 @@
+package ani.dantotsu.widgets.upcoming
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Color
+import android.widget.RemoteViews
+import android.widget.RemoteViewsService
+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.BitmapUtil.Companion.roundCorners
+import ani.dantotsu.util.Logger
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import java.io.InputStream
+import java.net.HttpURLConnection
+import java.net.URL
+
+class UpcomingRemoteViewsFactory(private val context: Context) :
+ RemoteViewsService.RemoteViewsFactory {
+ private var widgetItems = mutableListOf()
+ private var refreshing = false
+ private val prefs =
+ context.getSharedPreferences(UpcomingWidget.PREFS_NAME, Context.MODE_PRIVATE)
+
+ override fun onCreate() {
+ Logger.log("UpcomingRemoteViewsFactory onCreate")
+ fillWidgetItems()
+ }
+
+ private fun timeUntil(timeUntil: Long): String {
+ val days = timeUntil / (1000 * 60 * 60 * 24)
+ val hours = (timeUntil % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
+ val minutes = ((timeUntil % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60)) / (1000 * 60)
+ return "$days days $hours hours $minutes minutes"
+ }
+
+ override fun onDataSetChanged() {
+ if (refreshing) return
+ Logger.log("UpcomingRemoteViewsFactory onDataSetChanged")
+ widgetItems.clear()
+ fillWidgetItems()
+
+ }
+
+ private fun fillWidgetItems() {
+ refreshing = true
+ val userId = PrefManager.getVal(PrefName.AnilistUserId)
+ runBlocking(Dispatchers.IO) {
+ val upcoming = Anilist.query.getUpcomingAnime(userId)
+ upcoming.forEach {
+ widgetItems.add(
+ WidgetItem(
+ it.userPreferredName,
+ timeUntil(it.timeUntilAiring ?: 0),
+ it.cover ?: "",
+ it.id
+ )
+ )
+ }
+ refreshing = false
+ }
+ }
+
+ override fun onDestroy() {
+ widgetItems.clear()
+ }
+
+ override fun getCount(): Int {
+ return widgetItems.size
+ }
+
+ override fun getViewAt(position: Int): RemoteViews {
+ Logger.log("UpcomingRemoteViewsFactory getViewAt")
+ val item = widgetItems[position]
+ val titleTextColor = prefs.getInt(UpcomingWidget.PREF_TITLE_TEXT_COLOR, Color.WHITE)
+ val countdownTextColor =
+ prefs.getInt(UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR, Color.WHITE)
+ val rv = RemoteViews(context.packageName, R.layout.item_upcoming_widget).apply {
+ setTextViewText(R.id.text_show_title, item.title)
+ 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)
+ setImageViewBitmap(R.id.image_show_icon, bitmap)
+ val fillInIntent = Intent().apply {
+ putExtra("mediaId", item.id)
+ }
+ setOnClickFillInIntent(R.id.widget_item, fillInIntent)
+ }
+
+ return rv
+ }
+
+ private fun downloadImageAsBitmap(imageUrl: String): Bitmap? {
+ var bitmap: Bitmap? = null
+ var inputStream: InputStream? = null
+ var urlConnection: HttpURLConnection? = null
+
+ try {
+ val url = URL(imageUrl)
+ urlConnection = url.openConnection() as HttpURLConnection
+ urlConnection.requestMethod = "GET"
+ urlConnection.connect()
+
+ if (urlConnection.responseCode == HttpURLConnection.HTTP_OK) {
+ inputStream = urlConnection.inputStream
+ bitmap = BitmapFactory.decodeStream(inputStream)
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ } finally {
+ inputStream?.close()
+ urlConnection?.disconnect()
+ }
+ return bitmap?.let { roundCorners(it) }
+ }
+
+
+
+
+ override fun getLoadingView(): RemoteViews {
+ return RemoteViews(context.packageName, R.layout.item_upcoming_widget)
+ }
+
+ override fun getViewTypeCount(): Int {
+ return 1
+ }
+
+ override fun getItemId(p0: Int): Long {
+ return p0.toLong()
+ }
+
+ override fun hasStableIds(): Boolean {
+ return true
+ }
+}
+
+data class WidgetItem(val title: String, val countdown: String, val image: String, val id: Int)
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingRemoteViewsService.kt b/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingRemoteViewsService.kt
new file mode 100644
index 00000000..7e704fc2
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingRemoteViewsService.kt
@@ -0,0 +1,12 @@
+package ani.dantotsu.widgets.upcoming
+
+import android.content.Intent
+import android.widget.RemoteViewsService
+import ani.dantotsu.util.Logger
+
+class UpcomingRemoteViewsService : RemoteViewsService() {
+ override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
+ Logger.log("UpcomingRemoteViewsFactory onGetViewFactory")
+ return UpcomingRemoteViewsFactory(applicationContext)
+ }
+}
diff --git a/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingWidget.kt b/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingWidget.kt
new file mode 100644
index 00000000..a9f22130
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingWidget.kt
@@ -0,0 +1,147 @@
+package ani.dantotsu.widgets.upcoming
+
+import android.app.PendingIntent
+import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetProvider
+import android.content.Context
+import android.content.Intent
+import android.graphics.Color
+import android.graphics.drawable.GradientDrawable
+import android.net.Uri
+import android.os.Bundle
+import android.widget.RemoteViews
+import androidx.core.content.ContextCompat
+import androidx.core.content.res.ResourcesCompat
+import ani.dantotsu.MainActivity
+import ani.dantotsu.R
+import ani.dantotsu.util.BitmapUtil.Companion.convertDrawableToBitmap
+import ani.dantotsu.widgets.WidgetSizeProvider
+
+/**
+ * Implementation of App Widget functionality.
+ * App Widget Configuration implemented in [UpcomingWidgetConfigureActivity]
+ */
+class UpcomingWidget : AppWidgetProvider() {
+ override fun onUpdate(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetIds: IntArray
+ ) {
+ appWidgetIds.forEach { appWidgetId ->
+ val rv = updateAppWidget(context, appWidgetId)
+ appWidgetManager.updateAppWidget(appWidgetId, rv)
+ }
+ super.onUpdate(context, appWidgetManager, appWidgetIds)
+ }
+
+ override fun onDeleted(context: Context, appWidgetIds: IntArray) {
+ for (appWidgetId in appWidgetIds) {
+ context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE).edit().clear().apply()
+ }
+ super.onDeleted(context, appWidgetIds)
+ }
+
+ override fun onEnabled(context: Context) {
+ super.onEnabled(context)
+ }
+
+ override fun onDisabled(context: Context) {
+ super.onDisabled(context)
+ }
+
+ override fun onAppWidgetOptionsChanged(
+ context: Context?,
+ appWidgetManager: AppWidgetManager?,
+ appWidgetId: Int,
+ newOptions: Bundle?
+ ) {
+ super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)
+ if (context != null && appWidgetManager != null) {
+ val views = updateAppWidget(context, appWidgetId)
+ appWidgetManager.updateAppWidget(appWidgetId, views)
+ }
+ }
+
+ companion object {
+ fun updateAppWidget(
+ context: Context,
+ appWidgetId: Int,
+ ): RemoteViews {
+ val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
+ val backgroundColor =
+ prefs.getInt(PREF_BACKGROUND_COLOR, ContextCompat.getColor(context, R.color.theme))
+ val backgroundFade = prefs.getInt(PREF_BACKGROUND_FADE, Color.GRAY)
+ val titleTextColor = prefs.getInt(PREF_TITLE_TEXT_COLOR, Color.WHITE)
+ val countdownTextColor = prefs.getInt(PREF_COUNTDOWN_TEXT_COLOR, Color.WHITE)
+
+ val intent = Intent(context, UpcomingRemoteViewsService::class.java).apply {
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
+ data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
+ }
+ val gradientDrawable = ResourcesCompat.getDrawable(
+ context.resources,
+ R.drawable.gradient_background,
+ null
+ ) as GradientDrawable
+ gradientDrawable.colors = intArrayOf(backgroundColor, backgroundFade)
+ val widgetSizeProvider = WidgetSizeProvider(context)
+ var (width, height) = widgetSizeProvider.getWidgetsSize(appWidgetId)
+ if (width > 0 && height > 0) {
+ gradientDrawable.cornerRadius = 50f
+ } else {
+ width = 300
+ height = 300
+ }
+
+ val intentTemplate = Intent(context, MainActivity::class.java)
+ intentTemplate.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ intentTemplate.putExtra("fromWidget", true)
+
+ val views = RemoteViews(context.packageName, R.layout.upcoming_widget).apply {
+ setImageViewBitmap(R.id.backgroundView, convertDrawableToBitmap(gradientDrawable, width, height))
+ 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, UpcomingWidgetConfigureActivity::class.java).apply {
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
+ },
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ )
+ )
+ }
+ return views
+ }
+
+ const val PREFS_NAME = "ani.dantotsu.widgets.UpcomingWidget"
+ 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"
+ }
+}
+
+internal fun updateAppWidget(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetId: Int
+) {
+ val views = UpcomingWidget.updateAppWidget(context, appWidgetId)
+ appWidgetManager.updateAppWidget(appWidgetId, views)
+ appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widgetListView)
+}
\ No newline at end of file
diff --git a/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingWidgetConfigureActivity.kt b/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingWidgetConfigureActivity.kt
new file mode 100644
index 00000000..f14efaa7
--- /dev/null
+++ b/app/src/main/java/ani/dantotsu/widgets/upcoming/UpcomingWidgetConfigureActivity.kt
@@ -0,0 +1,195 @@
+package ani.dantotsu.widgets.upcoming
+
+import android.appwidget.AppWidgetManager
+import android.content.Context
+import android.content.Intent
+import android.graphics.Color
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import ani.dantotsu.R
+import ani.dantotsu.databinding.UpcomingWidgetConfigureBinding
+import ani.dantotsu.themes.ThemeManager
+import eltos.simpledialogfragment.SimpleDialog
+import eltos.simpledialogfragment.color.SimpleColorDialog
+
+/**
+ * The configuration screen for the [UpcomingWidget] AppWidget.
+ */
+class UpcomingWidgetConfigureActivity : AppCompatActivity(),
+ SimpleDialog.OnDialogResultListener {
+ private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
+
+ private var onClickListener = View.OnClickListener {
+ val context = this@UpcomingWidgetConfigureActivity
+ val appWidgetManager = AppWidgetManager.getInstance(context)
+
+ updateAppWidget(
+ context,
+ appWidgetManager,
+ appWidgetId,
+ )
+
+ val resultValue = Intent()
+ resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
+ setResult(RESULT_OK, resultValue)
+ finish()
+ }
+ private lateinit var binding: UpcomingWidgetConfigureBinding
+
+ public override fun onCreate(icicle: Bundle?) {
+ ThemeManager(this).applyTheme()
+ super.onCreate(icicle)
+ setResult(RESULT_CANCELED)
+
+ binding = UpcomingWidgetConfigureBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ val prefs = getSharedPreferences(UpcomingWidget.PREFS_NAME, Context.MODE_PRIVATE)
+
+ binding.topBackgroundButton.setOnClickListener {
+ val tag = UpcomingWidget.PREF_BACKGROUND_COLOR
+ SimpleColorDialog().title(R.string.custom_theme)
+ .colorPreset(
+ prefs.getInt(
+ UpcomingWidget.PREF_BACKGROUND_COLOR,
+ ContextCompat.getColor(this, R.color.theme)
+ )
+ )
+ .colors(
+ this@UpcomingWidgetConfigureActivity,
+ SimpleColorDialog.MATERIAL_COLOR_PALLET
+ )
+ .setupColorWheelAlpha(true)
+ .allowCustom(true)
+ .showOutline(0x46000000)
+ .gridNumColumn(5)
+ .choiceMode(SimpleColorDialog.SINGLE_CHOICE)
+ .neg()
+ .show(this@UpcomingWidgetConfigureActivity, tag)
+ }
+ binding.bottomBackgroundButton.setOnClickListener {
+ val tag = UpcomingWidget.PREF_BACKGROUND_FADE
+ SimpleColorDialog().title(R.string.custom_theme)
+ .colorPreset(prefs.getInt(UpcomingWidget.PREF_BACKGROUND_FADE, Color.GRAY))
+ .colors(
+ this@UpcomingWidgetConfigureActivity,
+ SimpleColorDialog.MATERIAL_COLOR_PALLET
+ )
+ .setupColorWheelAlpha(true)
+ .allowCustom(true)
+ .showOutline(0x46000000)
+ .gridNumColumn(5)
+ .choiceMode(SimpleColorDialog.SINGLE_CHOICE)
+ .neg()
+ .show(this@UpcomingWidgetConfigureActivity, tag)
+ }
+ binding.titleColorButton.setOnClickListener {
+ val tag = UpcomingWidget.PREF_TITLE_TEXT_COLOR
+ SimpleColorDialog().title(R.string.custom_theme)
+ .colorPreset(prefs.getInt(UpcomingWidget.PREF_TITLE_TEXT_COLOR, Color.WHITE))
+ .colors(
+ this@UpcomingWidgetConfigureActivity,
+ SimpleColorDialog.MATERIAL_COLOR_PALLET
+ )
+ .allowCustom(true)
+ .showOutline(0x46000000)
+ .gridNumColumn(5)
+ .choiceMode(SimpleColorDialog.SINGLE_CHOICE)
+ .neg()
+ .show(this@UpcomingWidgetConfigureActivity, tag)
+ }
+ binding.countdownColorButton.setOnClickListener {
+ val tag = UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR
+ SimpleColorDialog().title(R.string.custom_theme)
+ .colorPreset(
+ prefs.getInt(
+ UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR,
+ Color.WHITE
+ )
+ )
+ .colors(
+ this@UpcomingWidgetConfigureActivity,
+ SimpleColorDialog.MATERIAL_COLOR_PALLET
+ )
+ .allowCustom(true)
+ .showOutline(0x46000000)
+ .gridNumColumn(5)
+ .choiceMode(SimpleColorDialog.SINGLE_CHOICE)
+ .neg()
+ .show(this@UpcomingWidgetConfigureActivity, tag)
+ }
+
+ binding.addButton.setOnClickListener(onClickListener)
+
+ val intent = intent
+ val extras = intent.extras
+ if (extras != null) {
+ appWidgetId = extras.getInt(
+ AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID
+ )
+ }
+
+ if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
+ finish()
+ return
+ }
+ }
+
+ override fun onResult(dialogTag: String, which: Int, extras: Bundle): Boolean {
+ if (which == SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE) {
+ when (dialogTag) {
+ UpcomingWidget.PREF_BACKGROUND_COLOR -> {
+ getSharedPreferences(
+ UpcomingWidget.PREFS_NAME,
+ Context.MODE_PRIVATE
+ ).edit()
+ .putInt(
+ UpcomingWidget.PREF_BACKGROUND_COLOR,
+ extras.getInt(SimpleColorDialog.COLOR)
+ )
+ .apply()
+ }
+
+ UpcomingWidget.PREF_BACKGROUND_FADE -> {
+ getSharedPreferences(
+ UpcomingWidget.PREFS_NAME,
+ Context.MODE_PRIVATE
+ ).edit()
+ .putInt(
+ UpcomingWidget.PREF_BACKGROUND_FADE,
+ extras.getInt(SimpleColorDialog.COLOR)
+ )
+ .apply()
+ }
+
+ UpcomingWidget.PREF_TITLE_TEXT_COLOR -> {
+ getSharedPreferences(
+ UpcomingWidget.PREFS_NAME,
+ Context.MODE_PRIVATE
+ ).edit()
+ .putInt(
+ UpcomingWidget.PREF_TITLE_TEXT_COLOR,
+ extras.getInt(SimpleColorDialog.COLOR)
+ )
+ .apply()
+ }
+
+ UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR -> {
+ getSharedPreferences(
+ UpcomingWidget.PREFS_NAME,
+ Context.MODE_PRIVATE
+ ).edit()
+ .putInt(
+ UpcomingWidget.PREF_COUNTDOWN_TEXT_COLOR,
+ extras.getInt(SimpleColorDialog.COLOR)
+ )
+ .apply()
+ }
+
+ }
+ }
+ return true
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/gradient_background.xml b/app/src/main/res/drawable/gradient_background.xml
index 20e9ffd6..d4b19a1f 100644
--- a/app/src/main/res/drawable/gradient_background.xml
+++ b/app/src/main/res/drawable/gradient_background.xml
@@ -4,5 +4,5 @@
+ android:startColor="@color/theme"/>
diff --git a/app/src/main/res/layout-land/activity_profile.xml b/app/src/main/res/layout-land/activity_profile.xml
index 0aefbb9d..7e01d082 100644
--- a/app/src/main/res/layout-land/activity_profile.xml
+++ b/app/src/main/res/layout-land/activity_profile.xml
@@ -141,11 +141,11 @@
android:layout_gravity="bottom"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
- android:layout_marginTop="210dp"
+ android:layout_marginTop="200dp"
android:layout_marginBottom="2dp"
android:backgroundTint="?attr/colorSurfaceVariant"
android:baselineAligned="false"
- app:cardCornerRadius="16dp">
+ app:cardCornerRadius="24dp">
-
-
+ app:cardCornerRadius="24dp">
+
+
+
+
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_comments.xml b/app/src/main/res/layout/fragment_comments.xml
index 4004a427..59f93c50 100644
--- a/app/src/main/res/layout/fragment_comments.xml
+++ b/app/src/main/res/layout/fragment_comments.xml
@@ -1,5 +1,6 @@
-
-
@@ -56,7 +55,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
- android:layout_marginTop="64dp" />
+ android:layout_marginTop="64dp"
+ tools:visibility="gone"/>
-
diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml
index bf4e0c34..b7b12e47 100644
--- a/app/src/main/res/layout/fragment_profile.xml
+++ b/app/src/main/res/layout/fragment_profile.xml
@@ -1,6 +1,7 @@
-
@@ -153,103 +153,101 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
- app:layout_constrainedWidth="true"
- app:layout_constraintHorizontal_bias="0.0"
android:fontFamily="@font/poppins_semi_bold"
android:maxLines="8"
android:scrollHorizontally="false"
android:text="@string/slogan"
android:textSize="12sp"
+ app:layout_constrainedWidth="true"
+ app:layout_constraintEnd_toStartOf="@+id/linearLayout7"
app:layout_constraintHeight_max="200dp"
+ app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/linearLayout5"
- app:layout_constraintEnd_toStartOf="@+id/linearLayout7"
app:layout_constraintTop_toBottomOf="@+id/commentUserDetailsLayout" />
-
-
@@ -287,38 +285,37 @@
android:id="@+id/commentRepliesDivider"
android:layout_width="32dp"
android:layout_height="3dp"
- app:layout_constraintTop_toBottomOf="@+id/commentReply"
- app:layout_constraintStart_toEndOf="@+id/linearLayout5"
- android:layout_marginTop="8dp"
android:layout_gravity="center"
android:layout_marginStart="4dp"
- android:background="@color/nav_tab" />
+ android:layout_marginTop="8dp"
+ android:background="@color/nav_tab"
+ app:layout_constraintStart_toEndOf="@+id/linearLayout5"
+ app:layout_constraintTop_toBottomOf="@+id/commentReply" />
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_currently_airing_widget.xml b/app/src/main/res/layout/item_upcoming_widget.xml
similarity index 67%
rename from app/src/main/res/layout/item_currently_airing_widget.xml
rename to app/src/main/res/layout/item_upcoming_widget.xml
index 540b8e6a..0265c096 100644
--- a/app/src/main/res/layout/item_currently_airing_widget.xml
+++ b/app/src/main/res/layout/item_upcoming_widget.xml
@@ -1,17 +1,21 @@
+ android:paddingTop="4dp"
+ android:paddingBottom="4dp">
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:shapeAppearanceOverlay="@style/roundedImageView"
+ android:contentDescription="@string/airing_image"/>
+
diff --git a/app/src/main/res/layout/currently_airing_widget.xml b/app/src/main/res/layout/upcoming_widget.xml
similarity index 79%
rename from app/src/main/res/layout/currently_airing_widget.xml
rename to app/src/main/res/layout/upcoming_widget.xml
index 028ef044..209b300e 100644
--- a/app/src/main/res/layout/currently_airing_widget.xml
+++ b/app/src/main/res/layout/upcoming_widget.xml
@@ -16,12 +16,12 @@
android:id="@+id/widgetContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="16dp">
+ android:padding="8dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-v31/themes.xml b/app/src/main/res/values-v31/themes.xml
index 517c8008..9c5aff6a 100644
--- a/app/src/main/res/values-v31/themes.xml
+++ b/app/src/main/res/values-v31/themes.xml
@@ -8,4 +8,14 @@
- @android:dimen/system_app_widget_background_radius
- @android:dimen/system_app_widget_inner_radius
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 5a4dcc12..065f0e6b 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -19,6 +19,7 @@
#A9FFFFFF
#80FFFFFF
#ad5edd
+ #B313DC
#291B65
#54FF8400
#FF0000
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 230a227a..a6945a88 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -307,6 +307,7 @@
Animations
Banner Animations
Layout Animations
+ Trending Scroller
Overall Speed
Looks like you don\'t like anything,\nTry liking a show to keep it here.
Favourite Anime
@@ -406,7 +407,7 @@
Subscriptions Update Frequency
Amount of time for Dantotsu to periodically check for new Episodes/Chapters\n(Less time will cause more battery consumption)
Don\'t Update
- Loading Next Chapter
+ Loading Chapter %1$s
Sort by Release Date
Crop Borders
NOTE
@@ -422,7 +423,7 @@
Congrats Vro
Please Reload.
Copied "%1$s"
- Please perform BACK again to Exit
+ Press BACK again to exit
No Internet Connection
Seems like that wasn\'t found on Anilist.
Disabled Auto Skipping OP & ED
@@ -658,6 +659,12 @@
Display dantotsu in the second button
Display your AniList profile
Set up your own custom button
+ Discord Rich Presence
+ Stream on Dantotsu
+ View My AniList
+ Button Text
+ Button Link
+ Sample
Warning
View Anime
View Manga
@@ -683,6 +690,7 @@
Configure
Add widget
This is an app widget description
+ Upcoming Anime
Airing Image
animeDownloads
Delete all Anime downloads
@@ -725,7 +733,7 @@
Mutual
Success
- Currently Airing
+ Upcoming
No shows to display
Extension Name
version
@@ -816,10 +824,10 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
donate :)
Do it!
Password
- Discord Rich Presence
- Stream on Dantotsu
- View My AniList
- Button Text
- Button Link
- Sample
+
+ Top background color
+ Bottom Background Color
+ Countdown Text Color
+ Title Color
+ Placeholder
diff --git a/app/src/main/res/values/style.xml b/app/src/main/res/values/style.xml
index fd5798c0..7ccb02ce 100644
--- a/app/src/main/res/values/style.xml
+++ b/app/src/main/res/values/style.xml
@@ -101,5 +101,5 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/xml-v31/currently_airing_widget_info.xml b/app/src/main/res/xml-v31/currently_airing_widget_info.xml
deleted file mode 100644
index 30d7c6f0..00000000
--- a/app/src/main/res/xml-v31/currently_airing_widget_info.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
\ No newline at end of file
diff --git a/app/src/main/res/xml-v31/upcoming_widget_info.xml b/app/src/main/res/xml-v31/upcoming_widget_info.xml
new file mode 100644
index 00000000..e8376331
--- /dev/null
+++ b/app/src/main/res/xml-v31/upcoming_widget_info.xml
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/currently_airing_widget_info.xml b/app/src/main/res/xml/currently_airing_widget_info.xml
deleted file mode 100644
index ac32ee7a..00000000
--- a/app/src/main/res/xml/currently_airing_widget_info.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
\ No newline at end of file
diff --git a/app/src/main/res/xml/upcoming_widget_info.xml b/app/src/main/res/xml/upcoming_widget_info.xml
new file mode 100644
index 00000000..e82356cc
--- /dev/null
+++ b/app/src/main/res/xml/upcoming_widget_info.xml
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file