mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2025-01-31 12:38:21 +01:00
Timetable widget improvements (#2219)
This commit is contained in:
parent
398bc513fb
commit
b296926423
@ -124,14 +124,12 @@ class TimetableWidgetFactory(
|
||||
|
||||
val lessonStartTime = lesson.start.toFormattedString(TIME_FORMAT_STYLE)
|
||||
val lessonEndTime = lesson.end.toFormattedString(TIME_FORMAT_STYLE)
|
||||
val roomText = "${context.getString(R.string.timetable_room)} ${lesson.room}"
|
||||
|
||||
val remoteViews = RemoteViews(context.packageName, R.layout.item_widget_timetable).apply {
|
||||
setTextViewText(R.id.timetableWidgetItemNumber, lesson.number.toString())
|
||||
setTextViewText(R.id.timetableWidgetItemTimeStart, lessonStartTime)
|
||||
setTextViewText(R.id.timetableWidgetItemTimeFinish, lessonEndTime)
|
||||
setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject)
|
||||
setTextViewText(R.id.timetableWidgetItemRoom, roomText)
|
||||
setTextViewText(R.id.timetableWidgetItemTeacher, lesson.teacher)
|
||||
setTextViewText(R.id.timetableWidgetItemDescription, lesson.info)
|
||||
setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent())
|
||||
@ -140,6 +138,12 @@ class TimetableWidgetFactory(
|
||||
updateTheme()
|
||||
clearLessonStyles(remoteViews)
|
||||
|
||||
if (lesson.room.isBlank()) {
|
||||
remoteViews.setViewVisibility(R.id.timetableWidgetItemRoom, GONE)
|
||||
} else {
|
||||
remoteViews.setTextViewText(R.id.timetableWidgetItemRoom, lesson.room)
|
||||
}
|
||||
|
||||
when {
|
||||
lesson.canceled -> applyCancelledLessonStyles(remoteViews)
|
||||
lesson.changes or lesson.info.isNotBlank() -> applyChangedLessonStyles(
|
||||
|
@ -8,6 +8,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
import android.graphics.Bitmap
|
||||
import android.widget.RemoteViews
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
@ -76,110 +77,151 @@ class TimetableWidgetProvider : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
GlobalScope.launch {
|
||||
when (intent.action) {
|
||||
ACTION_APPWIDGET_UPDATE -> onUpdate(context, intent)
|
||||
ACTION_APPWIDGET_DELETED -> onDelete(intent)
|
||||
ACTION_APPWIDGET_UPDATE -> onWidgetUpdate(context, intent)
|
||||
ACTION_APPWIDGET_DELETED -> onWidgetDeleted(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun onUpdate(context: Context, intent: Intent) {
|
||||
if (intent.getStringExtra(EXTRA_BUTTON_TYPE) == null) {
|
||||
val isFromConfigure = intent.getBooleanExtra(EXTRA_FROM_CONFIGURE, false)
|
||||
val appWidgetIds = intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS) ?: return
|
||||
private suspend fun onWidgetUpdate(context: Context, intent: Intent) {
|
||||
val pressedButton = intent.getPressedButton()
|
||||
|
||||
appWidgetIds.forEach { appWidgetId ->
|
||||
val student =
|
||||
getStudent(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)
|
||||
val savedDataEpochDay = sharedPref.getLong(getDateWidgetKey(appWidgetId), 0)
|
||||
|
||||
val dateToLoad = if (isFromConfigure && savedDataEpochDay != 0L) {
|
||||
LocalDate.ofEpochDay(savedDataEpochDay)
|
||||
} else {
|
||||
getWidgetDefaultDateToLoad(appWidgetId)
|
||||
}
|
||||
|
||||
updateWidget(context, appWidgetId, dateToLoad, student)
|
||||
}
|
||||
if (pressedButton == null) {
|
||||
val updatedWidgetIds = intent.getWidgetIds() ?: return
|
||||
updatedWidgetIds.forEach { updateWidgetLayout(context, it) }
|
||||
} else {
|
||||
val buttonType = intent.getStringExtra(EXTRA_BUTTON_TYPE)
|
||||
val toggledWidgetId = intent.getIntExtra(EXTRA_TOGGLED_WIDGET_ID, 0)
|
||||
val student = getStudent(
|
||||
sharedPref.getLong(getStudentWidgetKey(toggledWidgetId), 0), toggledWidgetId
|
||||
)
|
||||
val savedDate =
|
||||
LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(toggledWidgetId), 0))
|
||||
val date = when (buttonType) {
|
||||
BUTTON_RESET -> getWidgetDefaultDateToLoad(toggledWidgetId)
|
||||
BUTTON_NEXT -> savedDate.nextSchoolDay
|
||||
BUTTON_PREV -> savedDate.previousSchoolDay
|
||||
else -> getWidgetDefaultDateToLoad(toggledWidgetId)
|
||||
}
|
||||
if (!buttonType.isNullOrBlank()) {
|
||||
analytics.logEvent(
|
||||
"changed_timetable_widget_day", "button" to buttonType
|
||||
)
|
||||
}
|
||||
updateWidget(context, toggledWidgetId, date, student)
|
||||
val widgetId = intent.getToggledWidgetId() ?: return
|
||||
reportChangedDay(pressedButton)
|
||||
updateSavedWidgetDate(widgetId, pressedButton)
|
||||
updateWidgetLayout(context, widgetId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onDelete(intent: Intent) {
|
||||
val appWidgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0)
|
||||
private fun Intent.getPressedButton(): String? {
|
||||
return getStringExtra(EXTRA_BUTTON_TYPE)
|
||||
}
|
||||
|
||||
if (appWidgetId != 0) {
|
||||
with(sharedPref) {
|
||||
delete(getStudentWidgetKey(appWidgetId))
|
||||
delete(getDateWidgetKey(appWidgetId))
|
||||
}
|
||||
private fun Intent.getWidgetIds(): IntArray? {
|
||||
return getIntArrayExtra(EXTRA_APPWIDGET_IDS)
|
||||
}
|
||||
|
||||
private fun Intent.getToggledWidgetId(): Int? {
|
||||
val toggledWidgetId = getIntExtra(EXTRA_TOGGLED_WIDGET_ID, INVALID_APPWIDGET_ID)
|
||||
return toggledWidgetId.takeIf { it != INVALID_APPWIDGET_ID }
|
||||
}
|
||||
|
||||
private fun reportChangedDay(buttonType: String) {
|
||||
if (buttonType.isNotBlank()) {
|
||||
analytics.logEvent("changed_timetable_widget_day", "button" to buttonType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWidget(
|
||||
context: Context, appWidgetId: Int, date: LocalDate, student: Student?
|
||||
private fun updateSavedWidgetDate(widgetId: Int, buttonType: String) {
|
||||
val savedDate = getSavedWidgetDate(widgetId)
|
||||
val newDate = savedDate?.let { getNewDate(it, widgetId, buttonType) }
|
||||
?: getWidgetDefaultDateToLoad(widgetId)
|
||||
setWidgetDate(widgetId, newDate)
|
||||
}
|
||||
|
||||
private fun getSavedWidgetDate(widgetId: Int): LocalDate? {
|
||||
val epochDay = sharedPref.getLong(getDateWidgetKey(widgetId), 0)
|
||||
return if (epochDay == 0L) null else LocalDate.ofEpochDay(epochDay)
|
||||
}
|
||||
|
||||
private fun getNewDate(
|
||||
currentDate: LocalDate,
|
||||
widgetId: Int,
|
||||
selectedButton: String
|
||||
): LocalDate {
|
||||
return when (selectedButton) {
|
||||
BUTTON_NEXT -> currentDate.nextSchoolDay
|
||||
BUTTON_PREV -> currentDate.previousSchoolDay
|
||||
else -> getWidgetDefaultDateToLoad(widgetId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setWidgetDate(widgetId: Int, dateToSet: LocalDate) {
|
||||
val widgetDateKey = getDateWidgetKey(widgetId)
|
||||
sharedPref.putLong(widgetDateKey, dateToSet.toEpochDay(), true)
|
||||
}
|
||||
|
||||
private fun getWidgetDefaultDateToLoad(widgetId: Int): LocalDate {
|
||||
val lastLessonEndDateTime = getLastLessonDateTime(widgetId)
|
||||
|
||||
val todayDate = LocalDate.now()
|
||||
val isLastLessonToday = lastLessonEndDateTime.toLocalDate() == todayDate
|
||||
val isEndOfLessons = LocalDateTime.now() > lastLessonEndDateTime
|
||||
|
||||
return if (isLastLessonToday && isEndOfLessons) {
|
||||
todayDate.nextSchoolDay
|
||||
} else {
|
||||
todayDate.nextOrSameSchoolDay
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLastLessonDateTime(widgetId: Int): LocalDateTime {
|
||||
val lastLessonTimestamp = sharedPref
|
||||
.getLong(getTodayLastLessonEndDateTimeWidgetKey(widgetId), 0)
|
||||
return LocalDateTime.ofEpochSecond(lastLessonTimestamp, 0, ZoneOffset.UTC)
|
||||
}
|
||||
|
||||
private suspend fun updateWidgetLayout(
|
||||
context: Context, widgetId: Int
|
||||
) {
|
||||
val nextNavIntent = createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT)
|
||||
val prevNavIntent = createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV)
|
||||
val resetNavIntent =
|
||||
createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET)
|
||||
val adapterIntent = Intent(context, TimetableWidgetService::class.java).apply {
|
||||
putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
action = appWidgetId.toString() //make Intent unique
|
||||
}
|
||||
val appIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
TIMETABLE_PENDING_INTENT_ID,
|
||||
SplashActivity.getStartIntent(context, Destination.Timetable()),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
|
||||
)
|
||||
val widgetRemoteViews = RemoteViews(context.packageName, R.layout.widget_timetable)
|
||||
|
||||
// Apply the click action intent
|
||||
val appIntent = createPendingAppIntent(context)
|
||||
widgetRemoteViews.setPendingIntentTemplate(R.id.timetableWidgetList, appIntent)
|
||||
|
||||
// Display saved date
|
||||
val date = getSavedWidgetDate(widgetId) ?: getWidgetDefaultDateToLoad(widgetId)
|
||||
val formattedDate = date.toFormattedString("EEE, dd.MM").capitalise()
|
||||
val remoteView = RemoteViews(context.packageName, R.layout.widget_timetable).apply {
|
||||
setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty)
|
||||
setTextViewText(R.id.timetableWidgetDate, formattedDate)
|
||||
setRemoteAdapter(R.id.timetableWidgetList, adapterIntent)
|
||||
widgetRemoteViews.setTextViewText(R.id.timetableWidgetDate, formattedDate)
|
||||
|
||||
// Apply intents to the date switcher buttons
|
||||
val nextNavIntent = createNavButtonIntent(context, widgetId, widgetId, BUTTON_NEXT)
|
||||
val prevNavIntent = createNavButtonIntent(context, -widgetId, widgetId, BUTTON_PREV)
|
||||
val resetNavIntent =
|
||||
createNavButtonIntent(context, Int.MAX_VALUE - widgetId, widgetId, BUTTON_RESET)
|
||||
widgetRemoteViews.run {
|
||||
setOnClickPendingIntent(R.id.timetableWidgetNext, nextNavIntent)
|
||||
setOnClickPendingIntent(R.id.timetableWidgetPrev, prevNavIntent)
|
||||
setOnClickPendingIntent(R.id.timetableWidgetDate, resetNavIntent)
|
||||
setPendingIntentTemplate(R.id.timetableWidgetList, appIntent)
|
||||
}
|
||||
|
||||
student?.let {
|
||||
setupAccountView(context, student, remoteView, appWidgetId)
|
||||
// Setup the lesson list adapter
|
||||
val lessonListAdapterIntent = createLessonListAdapterIntent(context, widgetId)
|
||||
// --- Ensure the selected date is stored in the shared preferences,
|
||||
// --- on which the TimetableWidgetFactory relies
|
||||
setWidgetDate(widgetId, date)
|
||||
// ---
|
||||
widgetRemoteViews.apply {
|
||||
setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty)
|
||||
setRemoteAdapter(R.id.timetableWidgetList, lessonListAdapterIntent)
|
||||
}
|
||||
|
||||
with(sharedPref) {
|
||||
putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true)
|
||||
// Setup profile picture
|
||||
getWidgetStudent(widgetId)?.let { student ->
|
||||
setupAccountView(context, student, widgetRemoteViews, widgetId)
|
||||
}
|
||||
|
||||
// Apply updates
|
||||
with(appWidgetManager) {
|
||||
partiallyUpdateAppWidget(appWidgetId, remoteView)
|
||||
notifyAppWidgetViewDataChanged(appWidgetId, R.id.timetableWidgetList)
|
||||
partiallyUpdateAppWidget(widgetId, widgetRemoteViews)
|
||||
notifyAppWidgetViewDataChanged(widgetId, R.id.timetableWidgetList)
|
||||
}
|
||||
|
||||
Timber.d("TimetableWidgetProvider updated")
|
||||
}
|
||||
|
||||
private fun createNavIntent(
|
||||
private fun createPendingAppIntent(context: Context) = PendingIntent.getActivity(
|
||||
context, TIMETABLE_PENDING_INTENT_ID,
|
||||
SplashActivity.getStartIntent(context, Destination.Timetable()),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
private fun createNavButtonIntent(
|
||||
context: Context, code: Int, appWidgetId: Int, buttonType: String
|
||||
) = PendingIntent.getBroadcast(
|
||||
context, code, Intent(context, TimetableWidgetProvider::class.java).apply {
|
||||
@ -189,6 +231,17 @@ class TimetableWidgetProvider : BroadcastReceiver() {
|
||||
}, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
private fun createLessonListAdapterIntent(context: Context, widgetId: Int) =
|
||||
Intent(context, TimetableWidgetService::class.java).apply {
|
||||
putExtra(EXTRA_APPWIDGET_ID, widgetId)
|
||||
action = widgetId.toString() //make Intent unique
|
||||
}
|
||||
|
||||
private suspend fun getWidgetStudent(widgetId: Int): Student? {
|
||||
val studentId = sharedPref.getLong(getStudentWidgetKey(widgetId), 0)
|
||||
return getStudent(studentId, widgetId)
|
||||
}
|
||||
|
||||
private suspend fun getStudent(studentId: Long, appWidgetId: Int) = try {
|
||||
val students = studentRepository.getSavedStudents(false)
|
||||
val student = students.singleOrNull { it.student.id == studentId }?.student
|
||||
@ -199,6 +252,7 @@ class TimetableWidgetProvider : BroadcastReceiver() {
|
||||
sharedPref.putLong(getStudentWidgetKey(appWidgetId), it.id)
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
@ -208,60 +262,64 @@ class TimetableWidgetProvider : BroadcastReceiver() {
|
||||
null
|
||||
}
|
||||
|
||||
private fun getWidgetDefaultDateToLoad(appWidgetId: Int): LocalDate {
|
||||
val lastLessonEndTimestamp =
|
||||
sharedPref.getLong(getTodayLastLessonEndDateTimeWidgetKey(appWidgetId), 0)
|
||||
val lastLessonEndDateTime =
|
||||
LocalDateTime.ofEpochSecond(lastLessonEndTimestamp, 0, ZoneOffset.UTC)
|
||||
private fun setupAccountView(
|
||||
context: Context, student: Student, remoteViews: RemoteViews, widgetId: Int
|
||||
) {
|
||||
val accountInitials = getAccountInitials(student.nickOrName)
|
||||
val accountPickerPendingIntent = createAccountPickerPendingIntent(context, widgetId)
|
||||
|
||||
val todayDate = LocalDate.now()
|
||||
val isLastLessonEndDateNow = lastLessonEndDateTime.toLocalDate() == todayDate
|
||||
val isLastLessonEndDateAfterNowTime = LocalDateTime.now() > lastLessonEndDateTime
|
||||
getAvatarBackgroundBitmap(context, student.avatarColor)?.let {
|
||||
remoteViews.setImageViewBitmap(R.id.timetableWidgetAccountBackground, it)
|
||||
}
|
||||
|
||||
return if (isLastLessonEndDateNow && isLastLessonEndDateAfterNowTime) {
|
||||
todayDate.nextSchoolDay
|
||||
} else {
|
||||
todayDate.nextOrSameSchoolDay
|
||||
remoteViews.apply {
|
||||
setTextViewText(R.id.timetableWidgetAccountInitials, accountInitials)
|
||||
setOnClickPendingIntent(R.id.timetableWidgetAccount, accountPickerPendingIntent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupAccountView(
|
||||
context: Context,
|
||||
student: Student,
|
||||
remoteViews: RemoteViews,
|
||||
appWidgetId: Int
|
||||
) {
|
||||
val accountInitials = student.nickOrName
|
||||
.split(" ")
|
||||
.mapNotNull { it.firstOrNull() }.take(2)
|
||||
.joinToString(separator = "").uppercase()
|
||||
private fun getAccountInitials(name: String): String {
|
||||
val firstLetters = name.split(" ").mapNotNull { it.firstOrNull() }
|
||||
return firstLetters.joinToString(separator = "").uppercase()
|
||||
}
|
||||
|
||||
val accountPickerIntent = PendingIntent.getActivity(
|
||||
private fun createAccountPickerPendingIntent(context: Context, widgetId: Int) =
|
||||
PendingIntent.getActivity(
|
||||
context,
|
||||
-Int.MAX_VALUE + appWidgetId,
|
||||
-Int.MAX_VALUE + widgetId,
|
||||
Intent(context, TimetableWidgetConfigureActivity::class.java).apply {
|
||||
addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK)
|
||||
putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
putExtra(EXTRA_APPWIDGET_ID, widgetId)
|
||||
putExtra(EXTRA_FROM_PROVIDER, true)
|
||||
},
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
// Create background bitmap
|
||||
private fun getAvatarBackgroundBitmap(context: Context, avatarColor: Long): Bitmap? {
|
||||
val avatarDrawableResource = R.drawable.background_timetable_widget_avatar
|
||||
AppCompatResources.getDrawable(context, avatarDrawableResource)?.let { drawable ->
|
||||
return AppCompatResources.getDrawable(context, avatarDrawableResource)?.let { drawable ->
|
||||
val screenDensity = context.resources.displayMetrics.density
|
||||
val avatarSize = (48 * screenDensity).toInt()
|
||||
val backgroundBitmap = DrawableCompat.wrap(drawable).run {
|
||||
DrawableCompat.setTint(this, student.avatarColor.toInt())
|
||||
DrawableCompat.wrap(drawable).run {
|
||||
DrawableCompat.setTint(this, avatarColor.toInt())
|
||||
toBitmap(avatarSize, avatarSize)
|
||||
}
|
||||
remoteViews.setImageViewBitmap(R.id.timetableWidgetAccountBackground, backgroundBitmap)
|
||||
}
|
||||
}
|
||||
|
||||
remoteViews.apply {
|
||||
setTextViewText(R.id.timetableWidgetAccountInitials, accountInitials)
|
||||
setOnClickPendingIntent(R.id.timetableWidgetAccount, accountPickerIntent)
|
||||
private fun onWidgetDeleted(intent: Intent) {
|
||||
val deletedWidgetId = intent.getWidgetId()
|
||||
deleteWidgetPreferences(deletedWidgetId)
|
||||
}
|
||||
|
||||
private fun Intent.getWidgetId(): Int {
|
||||
return getIntExtra(EXTRA_APPWIDGET_ID, INVALID_APPWIDGET_ID)
|
||||
}
|
||||
|
||||
private fun deleteWidgetPreferences(widgetId: Int) {
|
||||
with(sharedPref) {
|
||||
delete(getStudentWidgetKey(widgetId))
|
||||
delete(getDateWidgetKey(widgetId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,5 +2,5 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#FF000000" />
|
||||
<corners android:radius="12dp" />
|
||||
<corners android:radius="14dp" />
|
||||
</shape>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#FFFFFBFF" />
|
||||
<corners android:radius="12dp" />
|
||||
<corners android:radius="14dp" />
|
||||
</shape>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
|
@ -1,6 +1,6 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
|
BIN
app/src/main/res/drawable/img_timetable_widget_preview.png
Executable file → Normal file
BIN
app/src/main/res/drawable/img_timetable_widget_preview.png
Executable file → Normal file
Binary file not shown.
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 75 KiB |
@ -5,10 +5,10 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/background_widget_timetable"
|
||||
android:backgroundTint="?attr/colorSurface"
|
||||
android:backgroundTint="?attr/colorSecondaryContainer"
|
||||
android:clipToOutline="true"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:theme="@style/Wulkanowy.Widget.Theme"
|
||||
tools:context=".ui.modules.timetablewidget.TimetableWidgetProvider">
|
||||
|
||||
@ -16,23 +16,47 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="16dp">
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/background_timetable_widget_avatar"
|
||||
android:tint="?attr/colorPrimary"
|
||||
app:tint="?attr/colorPrimary"
|
||||
tools:ignore="UseAppTint" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="JK"
|
||||
android:textAppearance="?attr/textAppearanceTitleLarge"
|
||||
android:textColor="?attr/colorOnPrimary"
|
||||
android:textSize="18sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_weight="1"
|
||||
android:lines="1"
|
||||
android:text="Pon, 03.10"
|
||||
android:textAppearance="?attr/textAppearanceHeadline5"
|
||||
android:text="Pon, 19.05"
|
||||
android:textSize="18sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<ImageButton
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/all_prev"
|
||||
android:rotation="180"
|
||||
@ -51,46 +75,273 @@
|
||||
app:tint="?attr/colorPrimary"
|
||||
tools:ignore="UseAppTint" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@drawable/background_timetable_widget_avatar"
|
||||
android:backgroundTint="?attr/colorPrimary"
|
||||
android:contentDescription="@string/account_quick_manager"
|
||||
android:gravity="center"
|
||||
android:text="AW"
|
||||
android:textAppearance="?attr/textAppearanceTitleLarge"
|
||||
android:textColor="?attr/colorOnPrimary" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:showDividers="middle">
|
||||
android:paddingBottom="12dp">
|
||||
|
||||
<ImageView
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/background_widget_item_timetable"
|
||||
app:tint="?attr/backgroundColor" />
|
||||
android:background="@drawable/background_widget_item_timetable"
|
||||
android:backgroundTint="?attr/colorSurface"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="48dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<ImageView
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="1"
|
||||
android:textSize="22sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="08:00"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="09:45"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:text="Wychowanie fizyczne"
|
||||
android:textSize="14sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:text="213"
|
||||
android:textSize="12sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:text="Dorota Nowak"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/background_widget_item_timetable"
|
||||
app:tint="?attr/backgroundColor" />
|
||||
android:background="@drawable/background_widget_item_timetable"
|
||||
android:backgroundTint="?attr/colorSurface"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="48dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<ImageView
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="2"
|
||||
android:textSize="22sp"
|
||||
tools:ignore="HardcodedText"
|
||||
tools:textColor="?attr/colorTimetableChange" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="08:50"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="09:35"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:text="Język polski"
|
||||
android:textColor="?attr/colorTimetableChange"
|
||||
android:textSize="14sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:text="125"
|
||||
android:textSize="12sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:text="Karolina Kowalska"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
android:textColor="?attr/colorTimetableChange"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:contentDescription="@string/timetable_changes"
|
||||
android:tint="?attr/colorTimetableChange"
|
||||
app:tint="?attr/colorTimetableChange"
|
||||
tools:ignore="UseAppTint"
|
||||
tools:src="@drawable/ic_timetable_widget_swap" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/background_widget_item_timetable"
|
||||
app:tint="?attr/backgroundColor" />
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/background_widget_item_timetable"
|
||||
android:backgroundTint="?attr/colorSurface"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="48dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="3"
|
||||
android:textSize="22sp"
|
||||
tools:ignore="HardcodedText"
|
||||
tools:textColor="?attr/colorTimetableCanceled" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="09:45"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="10:30"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:text="Wiedza o społeczeństwie"
|
||||
android:textColor="?attr/colorTimetableCanceled"
|
||||
android:textSize="14sp"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Lekcja odwołana: uczniowie zwolnieni do domu"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
android:textColor="?attr/colorTimetableCanceled"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -6,11 +6,12 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/background_widget_item_timetable"
|
||||
android:backgroundTint="?attr/backgroundColor"
|
||||
android:backgroundTint="?attr/colorSurface"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="48dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="12dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:paddingVertical="8dp"
|
||||
android:theme="@style/Wulkanowy.Widget.Theme"
|
||||
tools:context=".ui.modules.timetablewidget.TimetableWidgetFactory">
|
||||
|
||||
@ -18,15 +19,14 @@
|
||||
android:id="@+id/timetableWidgetItemNumber"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||
android:textSize="24sp"
|
||||
android:textSize="22sp"
|
||||
tools:text="1"
|
||||
tools:textColor="?attr/colorTimetableChange" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
android:id="@+id/timetableWidgetItemTimeFinish"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
tools:text="09:45" />
|
||||
|
||||
@ -60,7 +60,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textAppearance="?attr/textAppearanceTitleMedium"
|
||||
android:textSize="14sp"
|
||||
tools:text="Programowanie aplikacji mobilnych i desktopowych" />
|
||||
|
||||
<LinearLayout
|
||||
@ -72,15 +72,15 @@
|
||||
android:id="@+id/timetableWidgetItemRoom"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
tools:text="Sala 213"
|
||||
tools:text="213"
|
||||
tools:textColor="?attr/colorTimetableChange" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableWidgetItemTeacher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textAppearance="?attr/textAppearanceBodySmall"
|
||||
|
@ -5,35 +5,70 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/background_widget_timetable"
|
||||
android:backgroundTint="?attr/colorSurface"
|
||||
android:backgroundTint="?attr/colorSecondaryContainer"
|
||||
android:clipToOutline="true"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:theme="@style/Wulkanowy.Widget.Theme"
|
||||
tools:context=".ui.modules.timetablewidget.TimetableWidgetProvider">
|
||||
tools:context=".ui.modules.timetablewidget.TimetableWidgetProvider"
|
||||
tools:targetApi="s">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="16dp">
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/timetableWidgetAccount"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/background_timetable_widget_avatar"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
android:clickable="true"
|
||||
android:clipToOutline="true"
|
||||
android:contentDescription="@string/account_quick_manager"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
android:importantForAccessibility="yes"
|
||||
android:outlineProvider="background"
|
||||
tools:targetApi="s">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/timetableWidgetAccountBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAccessibility="no"
|
||||
tools:src="@drawable/background_timetable_widget_avatar"
|
||||
tools:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableWidgetAccountInitials"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:textAppearance="?attr/textAppearanceTitleLarge"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp"
|
||||
tools:text="JK" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableWidgetDate"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_weight="1"
|
||||
android:lines="1"
|
||||
android:textAppearance="?attr/textAppearanceHeadline5"
|
||||
tools:text="Pon, 12.05" />
|
||||
android:textSize="18sp"
|
||||
tools:text="Friday, 19.05" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/timetableWidgetPrev"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/all_prev"
|
||||
android:rotation="180"
|
||||
@ -53,39 +88,6 @@
|
||||
app:tint="?attr/colorPrimary"
|
||||
tools:ignore="UseAppTint" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/timetableWidgetAccount"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@drawable/background_timetable_widget_avatar"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
android:clickable="true"
|
||||
android:clipToOutline="true"
|
||||
android:contentDescription="@string/account_quick_manager"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
android:importantForAccessibility="yes"
|
||||
android:outlineProvider="background">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/timetableWidgetAccountBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAccessibility="no"
|
||||
tools:src="@drawable/background_timetable_widget_avatar"
|
||||
tools:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timetableWidgetAccountInitials"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:textAppearance="?attr/textAppearanceTitleLarge"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="20sp"
|
||||
tools:text="AW" />
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
@ -99,6 +101,7 @@
|
||||
android:clipToPadding="false"
|
||||
android:divider="@android:color/transparent"
|
||||
android:dividerHeight="4dp"
|
||||
android:listSelector="@android:color/transparent"
|
||||
android:paddingBottom="16dp"
|
||||
tools:listfooter="@layout/item_widget_timetable_footer"
|
||||
tools:listitem="@layout/item_widget_timetable" />
|
||||
@ -111,5 +114,7 @@
|
||||
android:text="@string/widget_timetable_no_items"
|
||||
android:textAppearance="?attr/textAppearanceBody1"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -3,15 +3,15 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:configure="io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetConfigureActivity"
|
||||
android:initialLayout="@layout/widget_timetable"
|
||||
android:minWidth="250dp"
|
||||
android:minHeight="110dp"
|
||||
android:minResizeWidth="250dp"
|
||||
android:minResizeHeight="110dp"
|
||||
android:minWidth="245dp"
|
||||
android:minHeight="102dp"
|
||||
android:minResizeWidth="245dp"
|
||||
android:minResizeHeight="102dp"
|
||||
android:previewImage="@drawable/img_timetable_widget_preview"
|
||||
android:previewLayout="@layout/widget_timetable_preview"
|
||||
android:resizeMode="horizontal|vertical"
|
||||
android:targetCellWidth="3"
|
||||
android:targetCellHeight="2"
|
||||
android:targetCellHeight="3"
|
||||
android:updatePeriodMillis="3600000"
|
||||
android:widgetCategory="home_screen"
|
||||
tools:targetApi="s" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user