Merge branch 'dev' into main
This commit is contained in:
commit
74328cf4cf
49 changed files with 973 additions and 225 deletions
|
@ -75,6 +75,12 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
textInputLayout.boxBackgroundColor = (color and 0x00FFFFFF) or 0x28000000.toInt()
|
||||
materialCardView.setCardBackgroundColor((color and 0x00FFFFFF) or 0x28000000.toInt())
|
||||
}
|
||||
val incognito = currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||
?.getBoolean("incognito", false) ?: false
|
||||
if(incognito) {
|
||||
binding.incognitoTextView.visibility = View.VISIBLE
|
||||
binding.incognitoView.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
binding.animeTitleContainer.updatePadding(top = statusBarHeight)
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ani.dantotsu.home
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.os.Build
|
||||
|
@ -19,6 +21,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ani.dantotsu.App
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.Refresh
|
||||
import ani.dantotsu.bottomBar
|
||||
|
@ -71,6 +74,7 @@ class HomeFragment : Fragment() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val scope = lifecycleScope
|
||||
var uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
|
||||
|
||||
fun load() {
|
||||
if (activity != null && _binding != null) lifecycleScope.launch(Dispatchers.Main) {
|
||||
binding.homeUserName.text = Anilist.username
|
||||
|
@ -111,7 +115,12 @@ class HomeFragment : Fragment() {
|
|||
snackString(currContext()?.getString(R.string.please_reload))
|
||||
}
|
||||
}
|
||||
|
||||
val incognito = currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||
?.getBoolean("incognito", false) ?: false
|
||||
if(incognito) {
|
||||
binding.incognitoTextView.visibility = View.VISIBLE
|
||||
binding.incognitoView.visibility = View.VISIBLE
|
||||
}
|
||||
binding.homeUserAvatarContainer.setSafeOnClickListener {
|
||||
val dialogFragment =
|
||||
SettingsDialogFragment.newInstance(SettingsDialogFragment.Companion.PageType.HOME)
|
||||
|
|
|
@ -75,6 +75,13 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
|||
materialCardView.setCardBackgroundColor((color and 0x00FFFFFF) or 0x28000000.toInt())
|
||||
}
|
||||
|
||||
val incognito = currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||
?.getBoolean("incognito", false) ?: false
|
||||
if(incognito) {
|
||||
binding.incognitoTextView.visibility = View.VISIBLE
|
||||
binding.incognitoView.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
binding.mangaTitleContainer.updatePadding(top = statusBarHeight)
|
||||
|
||||
if (uiSettings.smallView) binding.mangaTrendingContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
|
|
|
@ -1101,7 +1101,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
|
|||
if (settings.cursedSpeeds)
|
||||
arrayOf(1f, 1.25f, 1.5f, 1.75f, 2f, 2.5f, 3f, 4f, 5f, 10f, 25f, 50f)
|
||||
else
|
||||
arrayOf(0.25f, 0.33f, 0.5f, 0.66f, 0.75f, 1f, 1.25f, 1.33f, 1.5f, 1.66f, 1.75f, 2f)
|
||||
arrayOf(0.25f, 0.33f, 0.5f, 0.66f, 0.75f, 1f, 1.15f, 1.25f, 1.33f, 1.5f, 1.66f, 1.75f, 2f)
|
||||
|
||||
val speedsName = speeds.map { "${it}x" }.toTypedArray()
|
||||
var curSpeed = loadData("${media.id}_speed", this) ?: settings.defaultSpeed
|
||||
|
@ -1156,14 +1156,18 @@ class ExoplayerView : AppCompatActivity(), Player.Listener {
|
|||
}
|
||||
|
||||
preloading = false
|
||||
val incognito = currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||
?.getBoolean("incognito", false) ?: false
|
||||
val showProgressDialog =
|
||||
if (settings.askIndividual) loadData<Boolean>("${media.id}_progressDialog")
|
||||
?: true else false
|
||||
if (showProgressDialog && Anilist.userid != null && if (media.isAdult) settings.updateForH else true)
|
||||
AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.auto_update, media.userPreferredName))
|
||||
.setMessage(getString(R.string.incognito_will_not_update))
|
||||
.apply {
|
||||
if (incognito) {
|
||||
setMessage(getString(R.string.incognito_will_not_update))
|
||||
}
|
||||
setOnCancelListener { hideSystemBars() }
|
||||
setCancelable(false)
|
||||
setPositiveButton(getString(R.string.yes)) { dialog, _ ->
|
||||
|
|
|
@ -3,6 +3,7 @@ package ani.dantotsu.media.manga.mangareader
|
|||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Bitmap
|
||||
|
@ -795,7 +796,8 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
|
||||
private fun progress(runnable: Runnable) {
|
||||
if (maxChapterPage - currentChapterPage <= 1 && Anilist.userid != null) {
|
||||
if (showProgressDialog) {
|
||||
if (showProgressDialog) {
|
||||
|
||||
val dialogView = layoutInflater.inflate(R.layout.item_custom_dialog, null)
|
||||
val checkbox = dialogView.findViewById<CheckBox>(R.id.dialog_checkbox)
|
||||
checkbox.text = getString(R.string.dont_ask_again, media.userPreferredName)
|
||||
|
@ -803,14 +805,20 @@ class MangaReaderActivity : AppCompatActivity() {
|
|||
saveData("${media.id}_progressDialog", isChecked)
|
||||
showProgressDialog = !isChecked
|
||||
}
|
||||
|
||||
val incognito = currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||
?.getBoolean("incognito", false) ?: false
|
||||
AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(getString(R.string.title_update_progress))
|
||||
.apply {
|
||||
if (incognito) {
|
||||
setMessage(getString(R.string.incognito_will_not_update))
|
||||
}
|
||||
}
|
||||
.setView(dialogView)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(getString(R.string.yes)) { dialog, _ ->
|
||||
saveData("${media.id}_save_progress", true)
|
||||
updateProgress(
|
||||
updateProgress(
|
||||
media,
|
||||
MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||
.toString()
|
||||
|
|
|
@ -62,7 +62,7 @@ class ListActivity : AppCompatActivity() {
|
|||
binding.listTabLayout.setTabTextColors(secondaryTextColor, primaryTextColor)
|
||||
binding.listTabLayout.setSelectedTabIndicatorColor(primaryTextColor)
|
||||
val uiSettings = loadData<UserInterfaceSettings>("ui_settings") ?: UserInterfaceSettings()
|
||||
if (!uiSettings.immersiveMode) {
|
||||
if (!uiSettings.immersiveModeList) {
|
||||
this.window.statusBarColor =
|
||||
ContextCompat.getColor(this, R.color.nav_bg_inv)
|
||||
binding.root.fitsSystemWindows = true
|
||||
|
|
|
@ -2,3 +2,4 @@ package ani.dantotsu.others
|
|||
|
||||
const val DisabledReports = false
|
||||
//Setting this to false, will allow sending crash reports to Dantotsu's Firebase Crashlytics
|
||||
//if you want a custom build without crash reporting, set this to true
|
|
@ -97,7 +97,7 @@ class PlayerSettingsActivity : AppCompatActivity() {
|
|||
|
||||
|
||||
val speeds =
|
||||
arrayOf(0.25f, 0.33f, 0.5f, 0.66f, 0.75f, 1f, 1.25f, 1.33f, 1.5f, 1.66f, 1.75f, 2f)
|
||||
arrayOf(0.25f, 0.33f, 0.5f, 0.66f, 0.75f, 1f, 1.15f, 1.25f, 1.33f, 1.5f, 1.66f, 1.75f, 2f)
|
||||
val cursedSpeeds = arrayOf(1f, 1.25f, 1.5f, 1.75f, 2f, 2.5f, 3f, 4f, 5f, 10f, 25f, 50f)
|
||||
var curSpeedArr = if (settings.cursedSpeeds) cursedSpeeds else speeds
|
||||
var speedsName = curSpeedArr.map { "${it}x" }.toTypedArray()
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
|||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.os.Build.*
|
||||
import android.os.Build.VERSION.*
|
||||
|
@ -11,7 +12,6 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
|
@ -37,7 +37,9 @@ import ani.dantotsu.subcriptions.Subscription.Companion.timeMinutes
|
|||
import ani.dantotsu.themes.ThemeManager
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.skydoves.colorpickerview.listeners.ColorListener
|
||||
import eltos.simpledialogfragment.SimpleDialog
|
||||
import eltos.simpledialogfragment.SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE
|
||||
import eltos.simpledialogfragment.color.SimpleColorDialog
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||
import io.noties.markwon.Markwon
|
||||
|
@ -50,7 +52,7 @@ import uy.kohesive.injekt.api.get
|
|||
import kotlin.random.Random
|
||||
|
||||
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListener {
|
||||
private val restartMainActivity = object : OnBackPressedCallback(false) {
|
||||
override fun handleOnBackPressed() = startMainActivity(this@SettingsActivity)
|
||||
}
|
||||
|
@ -176,31 +178,21 @@ class SettingsActivity : AppCompatActivity() {
|
|||
|
||||
|
||||
binding.customTheme.setOnClickListener {
|
||||
var passedColor: Int = 0
|
||||
val dialogView = layoutInflater.inflate(R.layout.dialog_color_picker, null)
|
||||
val alertDialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle("Custom Theme")
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).edit()
|
||||
.putInt("custom_theme_int", passedColor).apply()
|
||||
logger("Custom Theme: $passedColor")
|
||||
dialog.dismiss()
|
||||
restartApp()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
val colorPickerView =
|
||||
dialogView.findViewById<com.skydoves.colorpickerview.ColorPickerView>(R.id.colorPickerView)
|
||||
colorPickerView.setColorListener(ColorListener { color, fromUser ->
|
||||
val linearLayout = dialogView.findViewById<LinearLayout>(R.id.linear)
|
||||
passedColor = color
|
||||
linearLayout.setBackgroundColor(color)
|
||||
})
|
||||
alertDialog.show()
|
||||
alertDialog.window?.setDimAmount(0.8f)
|
||||
val originalColor = getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getInt(
|
||||
"custom_theme_int",
|
||||
Color.parseColor("#6200EE")
|
||||
)
|
||||
val tag = "colorPicker"
|
||||
SimpleColorDialog.build()
|
||||
.title("Custom Theme")
|
||||
.colorPreset(originalColor)
|
||||
.colors(this, SimpleColorDialog.BEIGE_COLOR_PALLET)
|
||||
.allowCustom(true)
|
||||
.showOutline(0x46000000)
|
||||
.gridNumColumn(5)
|
||||
.choiceMode(SimpleColorDialog.SINGLE_CHOICE)
|
||||
.neg()
|
||||
.show(this, tag)
|
||||
}
|
||||
|
||||
//val animeSource = loadData<Int>("settings_def_anime_source_s")?.let { if (it >= AnimeSources.names.size) 0 else it } ?: 0
|
||||
|
@ -416,6 +408,7 @@ class SettingsActivity : AppCompatActivity() {
|
|||
binding.settingsIncognito.setOnCheckedChangeListener { _, isChecked ->
|
||||
getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).edit()
|
||||
.putBoolean("incognito", isChecked).apply()
|
||||
restartApp()
|
||||
}
|
||||
|
||||
var previousStart: View = when (uiSettings.defaultStartUpTab) {
|
||||
|
@ -770,6 +763,18 @@ class SettingsActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResult(dialogTag: String, which: Int, extras: Bundle): Boolean {
|
||||
if (which == BUTTON_POSITIVE) {
|
||||
if (dialogTag == "colorPicker") {
|
||||
val color = extras.getInt(SimpleColorDialog.COLOR)
|
||||
getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).edit()
|
||||
.putInt("custom_theme_int", color).apply()
|
||||
logger("Custom Theme: $color")
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun restartApp() {
|
||||
Snackbar.make(
|
||||
binding.root,
|
||||
|
|
|
@ -113,19 +113,9 @@ class SettingsDialogFragment() : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
PageType.HOME -> {
|
||||
try {
|
||||
val arrayOfFiles =
|
||||
ContextCompat.getExternalFilesDirs(requireContext(), null)
|
||||
startActivity(
|
||||
if (loadData<Boolean>("sd_dl") == true && arrayOfFiles.size > 1 && arrayOfFiles[0] != null && arrayOfFiles[1] != null) {
|
||||
val parentDirectory = arrayOfFiles[1].toString()
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.setDataAndType(Uri.parse(parentDirectory), "resource/folder")
|
||||
} else Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
|
||||
)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
toast(getString(R.string.file_manager_not_found))
|
||||
}
|
||||
val intent = Intent(activity, DownloadContainerActivity::class.java)
|
||||
intent.putExtra("FRAGMENT_CLASS_NAME", OfflineMangaFragment::class.java.name)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ data class UserInterfaceSettings(
|
|||
|
||||
//App
|
||||
var immersiveMode: Boolean = false,
|
||||
var immersiveModeList: Boolean = false,
|
||||
var smallView: Boolean = true,
|
||||
var defaultStartUpTab: Int = 1,
|
||||
var homeLayoutShow: MutableList<Boolean> = mutableListOf(
|
||||
|
|
|
@ -68,6 +68,12 @@ class UserInterfaceSettingsActivity : AppCompatActivity() {
|
|||
saveData(ui, settings)
|
||||
restartApp()
|
||||
}
|
||||
binding.uiSettingsImmersiveList.isChecked = settings.immersiveModeList
|
||||
binding.uiSettingsImmersiveList.setOnCheckedChangeListener { _, isChecked ->
|
||||
settings.immersiveModeList = isChecked
|
||||
saveData(ui, settings)
|
||||
restartApp()
|
||||
}
|
||||
|
||||
binding.uiSettingsBannerAnimation.isChecked = settings.bannerAnimations
|
||||
binding.uiSettingsBannerAnimation.setOnCheckedChangeListener { _, isChecked ->
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package ani.dantotsu.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.widget.RemoteViews
|
||||
import android.widget.RemoteViewsService
|
||||
import androidx.core.net.toUri
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.logger
|
||||
import java.io.InputStream
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
class CurrentlyAiringRemoteViewsFactory(private val context: Context, intent: Intent) : RemoteViewsService.RemoteViewsFactory {
|
||||
private var widgetItems = mutableListOf<WidgetItem>()
|
||||
|
||||
override fun onCreate() {
|
||||
// 4 items for testing
|
||||
widgetItems.clear()
|
||||
logger("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("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("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)
|
|
@ -0,0 +1,11 @@
|
|||
package ani.dantotsu.widgets
|
||||
|
||||
import android.content.Intent
|
||||
import android.widget.RemoteViewsService
|
||||
import ani.dantotsu.logger
|
||||
class CurrentlyAiringRemoteViewsService : RemoteViewsService() {
|
||||
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
|
||||
logger("CurrentlyAiringRemoteViewsFactory onGetViewFactory")
|
||||
return CurrentlyAiringRemoteViewsFactory(applicationContext, intent)
|
||||
}
|
||||
}
|
101
app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringWidget.kt
Normal file
101
app/src/main/java/ani/dantotsu/widgets/CurrentlyAiringWidget.kt
Normal file
|
@ -0,0 +1,101 @@
|
|||
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)
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
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.others.LangSet
|
||||
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?) {
|
||||
LangSet.setLocale(this)
|
||||
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 as EditText
|
||||
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()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue