Profile Stats Widget (#292)
* feat: create a statistics widget * feat: mirror app color option * fix: the minimum size cut off * feat: make the stat widget decent * fix: prevent bleeding edges * fix: PREVENT BLEEDING EDGES! * fix: we didn't really need an overlay
This commit is contained in:
parent
7bcc01b94e
commit
f83d1d8d84
16 changed files with 652 additions and 2 deletions
|
@ -79,6 +79,18 @@
|
|||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver
|
||||
android:name=".widgets.statistics.ProfileStatsWidget"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/statistics_widget_info" />
|
||||
</receiver>
|
||||
<receiver android:name=".notifications.IncognitoNotificationClickReceiver" />
|
||||
|
||||
<activity
|
||||
|
@ -115,6 +127,14 @@
|
|||
android:name=".settings.ExtensionsActivity"
|
||||
android:parentActivityName=".MainActivity"
|
||||
android:windowSoftInputMode="adjustResize|stateHidden" />
|
||||
<activity
|
||||
android:name=".widgets.statistics.ProfileStatsConfigure"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".profile.ProfileActivity"
|
||||
android:parentActivityName=".MainActivity"
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package ani.dantotsu.widgets.statistics
|
||||
|
||||
import android.app.Activity
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import ani.dantotsu.databinding.StatisticsWidgetConfigureBinding
|
||||
|
||||
import ani.dantotsu.themes.ThemeManager
|
||||
|
||||
/**
|
||||
* The configuration screen for the [ProfileStatsWidget] AppWidget.
|
||||
*/
|
||||
class ProfileStatsConfigure : Activity() {
|
||||
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
|
||||
private var onClickListener = View.OnClickListener {
|
||||
val context = this@ProfileStatsConfigure
|
||||
|
||||
// It is the responsibility of the configuration activity to update the app widget
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
//updateAppWidget(context, appWidgetManager, appWidgetId)
|
||||
|
||||
|
||||
ProfileStatsWidget.updateAppWidget(
|
||||
context,
|
||||
appWidgetManager,
|
||||
appWidgetId
|
||||
)
|
||||
|
||||
// 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: StatisticsWidgetConfigureBinding
|
||||
|
||||
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 = StatisticsWidgetConfigureBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
val typedValueSurface = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValueSurface, true)
|
||||
val backgroundColor = typedValueSurface.data
|
||||
|
||||
val typedValuePrimary = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorPrimary, typedValuePrimary, true)
|
||||
val textColor = typedValuePrimary.data
|
||||
|
||||
val typedValueOutline = TypedValue()
|
||||
theme.resolveAttribute(com.google.android.material.R.attr.colorOutline, typedValueOutline, true)
|
||||
val subTextColor = typedValueOutline.data
|
||||
|
||||
getSharedPreferences(ProfileStatsWidget.PREFS_NAME, Context.MODE_PRIVATE).edit().apply {
|
||||
putInt(ProfileStatsWidget.PREF_BACKGROUND_COLOR, backgroundColor)
|
||||
putInt(ProfileStatsWidget.PREF_BACKGROUND_FADE, backgroundColor)
|
||||
putInt(ProfileStatsWidget.PREF_TITLE_TEXT_COLOR, textColor)
|
||||
apply()
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
// Possibly consider sorting the items or configuring colors
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private const val PROFILE_STATS_PREFS = "ani.dantotsu.widget.ProfileStatsWidget"
|
||||
private const val PROFILE_STATS_PREFS_PREFIX = "appwidget_"
|
|
@ -0,0 +1,245 @@
|
|||
package ani.dantotsu.widgets.statistics
|
||||
|
||||
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.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import ani.dantotsu.MainActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.util.BitmapUtil
|
||||
import ani.dantotsu.widgets.WidgetSizeProvider
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
import java.io.InputStream
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
* Implementation of App Widget functionality.
|
||||
*/
|
||||
class ProfileStatsWidget : AppWidgetProvider() {
|
||||
override fun onUpdate(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetIds: IntArray
|
||||
) {
|
||||
appWidgetIds.forEach { appWidgetId ->
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId)
|
||||
}
|
||||
super.onUpdate(context, appWidgetManager, appWidgetIds)
|
||||
}
|
||||
|
||||
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
|
||||
super.onDeleted(context, appWidgetIds)
|
||||
}
|
||||
|
||||
override fun onEnabled(context: Context) {
|
||||
super.onEnabled(context)
|
||||
}
|
||||
|
||||
override fun onDisabled(context: Context) {
|
||||
super.onDisabled(context)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun downloadImageAsBitmap(imageUrl: String): Bitmap? {
|
||||
var bitmap: Bitmap? = null
|
||||
|
||||
runBlocking(Dispatchers.IO) {
|
||||
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 { BitmapUtil.roundCorners(it) }
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun updateAppWidget(
|
||||
context: Context,
|
||||
appWidgetManager: AppWidgetManager,
|
||||
appWidgetId: Int
|
||||
) {
|
||||
|
||||
val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
val backgroundColor =
|
||||
prefs.getInt(PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
val backgroundFade = prefs.getInt(PREF_BACKGROUND_FADE, Color.parseColor("#00000000"))
|
||||
val titleTextColor = prefs.getInt(PREF_TITLE_TEXT_COLOR, Color.WHITE)
|
||||
|
||||
val gradientDrawable = ResourcesCompat.getDrawable(
|
||||
context.resources,
|
||||
R.drawable.linear_gradient_black,
|
||||
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 = 64f
|
||||
} else {
|
||||
width = 300
|
||||
height = 300
|
||||
}
|
||||
|
||||
launchIO {
|
||||
val userPref = PrefManager.getVal(PrefName.AnilistUserId, "")
|
||||
val userId = if (userPref.isNotEmpty()) userPref.toInt() else Anilist.userid
|
||||
?: if (Anilist.query.getUserData()) Anilist.userid else null
|
||||
userId?.let {
|
||||
val respond = Anilist.query.getUserProfile(it)
|
||||
respond?.data?.user?.let { user ->
|
||||
withContext(Dispatchers.Main) {
|
||||
val views = RemoteViews(context.packageName, R.layout.statistics_widget).apply {
|
||||
setImageViewBitmap(
|
||||
R.id.backgroundView,
|
||||
BitmapUtil.convertDrawableToBitmap(
|
||||
gradientDrawable,
|
||||
width,
|
||||
height
|
||||
)
|
||||
)
|
||||
setTextColor(R.id.topLeftItem, titleTextColor)
|
||||
setTextColor(R.id.topLeftLabel, titleTextColor)
|
||||
setTextColor(R.id.topRightItem, titleTextColor)
|
||||
setTextColor(R.id.topRightLabel, titleTextColor)
|
||||
setTextColor(R.id.bottomLeftItem, titleTextColor)
|
||||
setTextColor(R.id.bottomLeftLabel, titleTextColor)
|
||||
setTextColor(R.id.bottomRightItem, titleTextColor)
|
||||
setTextColor(R.id.bottomRightLabel, titleTextColor)
|
||||
|
||||
setImageViewBitmap(
|
||||
R.id.userAvatar,
|
||||
user.avatar?.medium?.let { it1 -> downloadImageAsBitmap(it1) }
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.userLabel,
|
||||
context.getString(R.string.user_stats, user.name)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.topLeftItem,
|
||||
user.statistics.anime.count.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topLeftLabel,
|
||||
context.getString(R.string.anime_watched)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.topRightItem,
|
||||
user.statistics.anime.episodesWatched.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.topRightLabel,
|
||||
context.getString(R.string.episodes_watched)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.bottomLeftItem,
|
||||
user.statistics.manga.count.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomLeftLabel,
|
||||
context.getString(R.string.manga_read)
|
||||
)
|
||||
|
||||
setTextViewText(
|
||||
R.id.bottomRightItem,
|
||||
user.statistics.manga.chaptersRead.toString()
|
||||
)
|
||||
setTextViewText(
|
||||
R.id.bottomRightLabel,
|
||||
context.getString(R.string.chapters_read)
|
||||
)
|
||||
|
||||
val intent = Intent(context, ProfileActivity::class.java)
|
||||
.putExtra("userId", it)
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
context, 0, intent, PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
setOnClickPendingIntent(R.id.widgetContainer, pendingIntent)
|
||||
}
|
||||
// Instruct the widget manager to update the widget
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
}
|
||||
} ?: showLoginCascade(context, appWidgetManager, appWidgetId)
|
||||
} ?: showLoginCascade(context, appWidgetManager, appWidgetId)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun showLoginCascade(
|
||||
context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int
|
||||
) {
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
val views = RemoteViews(context.packageName, R.layout.statistics_widget)
|
||||
|
||||
views.setTextViewText(R.id.topLeftItem, "")
|
||||
views.setTextViewText(
|
||||
R.id.topLeftLabel,
|
||||
context.getString(R.string.please)
|
||||
)
|
||||
|
||||
views.setTextViewText(R.id.topRightItem, "")
|
||||
views.setTextViewText(
|
||||
R.id.topRightLabel,
|
||||
context.getString(R.string.log_in)
|
||||
)
|
||||
|
||||
views.setTextViewText(
|
||||
R.id.bottomLeftItem,
|
||||
context.getString(R.string.or_join)
|
||||
)
|
||||
views.setTextViewText(R.id.bottomLeftLabel, "")
|
||||
|
||||
views.setTextViewText(
|
||||
R.id.bottomRightItem,
|
||||
context.getString(R.string.anilist)
|
||||
)
|
||||
views.setTextViewText(R.id.bottomRightLabel, "")
|
||||
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
context, 0, intent, PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.widgetContainer, pendingIntent)
|
||||
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
}
|
||||
}
|
||||
|
||||
const val PREFS_NAME = "ani.dantotsu.widgets.ResumableWidget"
|
||||
const val PREF_BACKGROUND_COLOR = "background_color"
|
||||
const val PREF_BACKGROUND_FADE = "background_fade"
|
||||
const val PREF_TITLE_TEXT_COLOR = "title_text_color"
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 69 KiB |
BIN
app/src/main/res/drawable-nodpi/statistics_widget_preview.png
Normal file
BIN
app/src/main/res/drawable-nodpi/statistics_widget_preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
app/src/main/res/drawable-nodpi/upcoming_widget_preview.png
Normal file
BIN
app/src/main/res/drawable-nodpi/upcoming_widget_preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
13
app/src/main/res/drawable/ic_camera_roll_24.xml
Normal file
13
app/src/main/res/drawable/ic_camera_roll_24.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:tint="#000000"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp">
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M14,5c0,-1.1 -0.9,-2 -2,-2h-1L11,2c0,-0.55 -0.45,-1 -1,-1L6,1c-0.55,0 -1,0.45 -1,1v1L4,3c-1.1,0 -2,0.9 -2,2v15c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2h8L22,5h-8zM12,18h-2v-2h2v2zM12,9h-2L10,7h2v2zM16,18h-2v-2h2v2zM16,9h-2L14,7h2v2zM20,18h-2v-2h2v2zM20,9h-2L18,7h2v2z"/>
|
||||
|
||||
</vector>
|
27
app/src/main/res/drawable/widget_stats_rounded.xml
Normal file
27
app/src/main/res/drawable/widget_stats_rounded.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<corners
|
||||
android:topLeftRadius="28dp"
|
||||
android:topRightRadius="28dp"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item
|
||||
android:left="-2dp"
|
||||
android:right="-2dp"
|
||||
android:bottom="-50dp">
|
||||
<shape>
|
||||
<stroke android:width="2dp" android:color="@color/bg_white" />
|
||||
<corners
|
||||
android:topLeftRadius="28dp"
|
||||
android:topRightRadius="28dp"
|
||||
android:bottomLeftRadius="0dp"
|
||||
android:bottomRightRadius="0dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
||||
|
184
app/src/main/res/layout/statistics_widget.xml
Normal file
184
app/src/main/res/layout/statistics_widget.xml
Normal file
|
@ -0,0 +1,184 @@
|
|||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:theme="@style/Theme.Dantotsu.AppWidgetContainer"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/backgroundView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/widget_stats_rounded"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/headerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_margin="4dp"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
<ImageView
|
||||
android:id="@+id/userAvatar"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_dantotsu_round"
|
||||
tools:ignore="ContentDescription"/>
|
||||
<TextView
|
||||
android:id="@+id/userLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="8dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:textSize="18sp"
|
||||
android:text="@string/loading"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="4dp"
|
||||
android:orientation="vertical"
|
||||
android:background="@drawable/widget_stats_rounded"
|
||||
android:layout_below="@id/headerLayout">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
<LinearLayout
|
||||
android:id="@+id/topLeft"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="NestedWeights">
|
||||
<TextView
|
||||
android:id="@+id/topLeftItem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/loading"/>
|
||||
<TextView
|
||||
android:id="@+id/topLeftLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/anime_watched" />
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/dividerTop"
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="4dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/topRight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/topRightItem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/loading"/>
|
||||
<TextView
|
||||
android:id="@+id/topRightLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/episodes_watched"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/dividerMiddle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_margin="4dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomLeft"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:baselineAligned="false">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="NestedWeights">
|
||||
<TextView
|
||||
android:id="@+id/bottomLeftItem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/loading"/>
|
||||
<TextView
|
||||
android:id="@+id/bottomLeftLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/manga_read"
|
||||
android:layout_gravity="center"/>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/dividerBottom"
|
||||
android:layout_width="4dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomRight"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/bottomRightItem"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/loading"/>
|
||||
<TextView
|
||||
android:id="@+id/bottomRightLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/poppins_semi_bold"
|
||||
android:text="@string/chapters_read"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
24
app/src/main/res/layout/statistics_widget_configure.xml
Normal file
24
app/src/main/res/layout/statistics_widget_configure.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/profile_stats_widget" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/add_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/add_widget" />
|
||||
|
||||
</LinearLayout>
|
|
@ -9,6 +9,7 @@
|
|||
<color name="bg_opp">@color/bg_black</color>
|
||||
<color name="fg">#A8000000</color>
|
||||
<color name="bg_black_50" alpha="128">#80000000</color>
|
||||
<color name="bg_white_50" alpha="128">#80FFFFFF</color>
|
||||
<color name="nav_bg">#fff</color>
|
||||
<color name="nav_bg_inv">#00BFAEAE</color>
|
||||
<color name="gradiant_bg_start">#ACACAC</color>
|
||||
|
|
|
@ -820,6 +820,17 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
|||
<string name="donate">donate :)</string>
|
||||
<string name="do_it">Do it!</string>
|
||||
<string name="password">Password</string>
|
||||
|
||||
<string name="profile_stats_widget">Track progress directly from your home screen</string>
|
||||
<string name="anime_watched">Anime Watched</string>
|
||||
<string name="manga_read">Manga Read</string>
|
||||
<string name="loading">Loading…</string>
|
||||
<string name="user_stats">%1$s\'s Stats</string>
|
||||
|
||||
<string name="please">Please</string>
|
||||
<string name="log_in">log in</string>
|
||||
<string name="or_join">or join</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>
|
||||
|
|
15
app/src/main/res/xml-v31/statistics_widget_info.xml
Normal file
15
app/src/main/res/xml-v31/statistics_widget_info.xml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/profile_stats_widget"
|
||||
android:initialKeyguardLayout="@layout/statistics_widget"
|
||||
android:initialLayout="@layout/statistics_widget"
|
||||
android:targetCellWidth="3"
|
||||
android:targetCellHeight="2"
|
||||
android:minResizeWidth="180dp"
|
||||
android:minResizeHeight="110dp"
|
||||
android:previewImage="@drawable/statistics_widget_preview"
|
||||
android:previewLayout="@layout/statistics_widget"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="86400000"
|
||||
android:widgetCategory="home_screen"
|
||||
android:configure="ani.dantotsu.widgets.statistics.ProfileStatsConfigure" />
|
|
@ -6,7 +6,7 @@
|
|||
android:initialLayout="@layout/upcoming_widget"
|
||||
android:minWidth="160dp"
|
||||
android:minHeight="80dp"
|
||||
android:previewImage="@drawable/example_appwidget_preview"
|
||||
android:previewImage="@drawable/upcoming_widget_preview"
|
||||
android:previewLayout="@layout/upcoming_widget"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="3600000"
|
||||
|
|
14
app/src/main/res/xml/statistics_widget_info.xml
Normal file
14
app/src/main/res/xml/statistics_widget_info.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:description="@string/profile_stats_widget"
|
||||
android:initialKeyguardLayout="@layout/statistics_widget"
|
||||
android:initialLayout="@layout/statistics_widget"
|
||||
android:minWidth="180dp"
|
||||
android:minHeight="110dp"
|
||||
android:minResizeWidth="180dp"
|
||||
android:minResizeHeight="110dp"
|
||||
android:previewImage="@drawable/statistics_widget_preview"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="86400000"
|
||||
android:widgetCategory="home_screen"
|
||||
android:configure="ani.dantotsu.widgets.statistics.ProfileStatsConfigure" />
|
|
@ -6,7 +6,7 @@
|
|||
android:initialLayout="@layout/upcoming_widget"
|
||||
android:minWidth="160dp"
|
||||
android:minHeight="80dp"
|
||||
android:previewImage="@drawable/example_appwidget_preview"
|
||||
android:previewImage="@drawable/upcoming_widget_preview"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:updatePeriodMillis="3600000"
|
||||
android:widgetCategory="home_screen"/>
|
Loading…
Add table
Add a link
Reference in a new issue