1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2025-01-31 22:02:45 +01:00

Add dark theme for app widgets (#509)

This commit is contained in:
Rafał Borcz 2019-09-25 22:44:55 +02:00 committed by Mikołaj Pich
parent d6ece78eff
commit d4b73fb73e
20 changed files with 614 additions and 214 deletions

View File

@ -6,6 +6,7 @@ import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_IDS
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
@ -25,6 +26,8 @@ class LuckyNumberWidgetConfigureActivity : BaseActivity<LuckyNumberWidgetConfigu
@Inject @Inject
override lateinit var presenter: LuckyNumberWidgetConfigurePresenter override lateinit var presenter: LuckyNumberWidgetConfigurePresenter
private var dialog: AlertDialog? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setResult(RESULT_CANCELED) setResult(RESULT_CANCELED)
@ -36,11 +39,27 @@ class LuckyNumberWidgetConfigureActivity : BaseActivity<LuckyNumberWidgetConfigu
} }
override fun initView() { override fun initView() {
widgetConfigureRecycler.apply { with(widgetConfigureRecycler) {
adapter = configureAdapter adapter = configureAdapter
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)
} }
configureAdapter.setOnItemClickListener { presenter.onItemSelect(it) }
configureAdapter.setOnItemClickListener(presenter::onItemSelect)
}
override fun showThemeDialog() {
val items = arrayOf(
getString(R.string.widget_timetable_theme_light),
getString(R.string.widget_timetable_theme_dark)
)
dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher)
.setTitle(R.string.widget_timetable_theme_title)
.setOnDismissListener { presenter.onDismissThemeView() }
.setSingleChoiceItems(items, -1) { _, which ->
presenter.onThemeSelect(which)
}
.show()
} }
override fun updateData(data: List<LuckyNumberWidgetConfigureItem>) { override fun updateData(data: List<LuckyNumberWidgetConfigureItem>) {
@ -70,4 +89,9 @@ class LuckyNumberWidgetConfigureActivity : BaseActivity<LuckyNumberWidgetConfigu
override fun openLoginView() { override fun openLoginView() {
startActivity(LoginActivity.getStartIntent(this)) startActivity(LoginActivity.getStartIntent(this))
} }
override fun onDestroy() {
super.onDestroy()
dialog?.dismiss()
}
} }

View File

@ -7,6 +7,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getThemeWidgetKey
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import javax.inject.Inject import javax.inject.Inject
@ -19,6 +20,8 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
private var appWidgetId: Int? = null private var appWidgetId: Int? = null
private var selectedStudent: Student? = null
fun onAttachView(view: LuckyNumberWidgetConfigureView, appWidgetId: Int?) { fun onAttachView(view: LuckyNumberWidgetConfigureView, appWidgetId: Int?) {
super.onAttachView(view) super.onAttachView(view)
this.appWidgetId = appWidgetId this.appWidgetId = appWidgetId
@ -28,10 +31,22 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
fun onItemSelect(item: AbstractFlexibleItem<*>) { fun onItemSelect(item: AbstractFlexibleItem<*>) {
if (item is LuckyNumberWidgetConfigureItem) { if (item is LuckyNumberWidgetConfigureItem) {
registerStudent(item.student) selectedStudent = item.student
view?.showThemeDialog()
} }
} }
fun onThemeSelect(index: Int) {
appWidgetId?.let {
sharedPref.putLong(getThemeWidgetKey(it), index.toLong())
}
registerStudent(selectedStudent)
}
fun onDismissThemeView(){
view?.finishView()
}
private fun loadData() { private fun loadData() {
disposable.add(studentRepository.getSavedStudents(false) disposable.add(studentRepository.getSavedStudents(false)
.map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } } .map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } }
@ -49,12 +64,14 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
}, { errorHandler.dispatch(it) })) }, { errorHandler.dispatch(it) }))
} }
private fun registerStudent(student: Student) { private fun registerStudent(student: Student?) {
appWidgetId?.also { requireNotNull(student)
sharedPref.putLong(getStudentWidgetKey(it), student.id)
view?.apply { appWidgetId?.let { id ->
updateLuckyNumberWidget(it) sharedPref.putLong(getStudentWidgetKey(id), student.id)
setSuccessResult(it) view?.run {
updateLuckyNumberWidget(id)
setSuccessResult(id)
} }
} }
view?.finishView() view?.finishView()

View File

@ -1,12 +1,13 @@
package io.github.wulkanowy.ui.modules.luckynumberwidget package io.github.wulkanowy.ui.modules.luckynumberwidget
import io.github.wulkanowy.ui.base.BaseView import io.github.wulkanowy.ui.base.BaseView
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetConfigureItem
interface LuckyNumberWidgetConfigureView : BaseView { interface LuckyNumberWidgetConfigureView : BaseView {
fun initView() fun initView()
fun showThemeDialog()
fun updateData(data: List<LuckyNumberWidgetConfigureItem>) fun updateData(data: List<LuckyNumberWidgetConfigureItem>)
fun updateLuckyNumberWidget(widgetId: Int) fun updateLuckyNumberWidget(widgetId: Int)

View File

@ -55,7 +55,10 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
lateinit var sharedPref: SharedPrefProvider lateinit var sharedPref: SharedPrefProvider
companion object { companion object {
fun getStudentWidgetKey(appWidgetId: Int) = "lucky_number_widget_student_$appWidgetId" fun getStudentWidgetKey(appWidgetId: Int) = "lucky_number_widget_student_$appWidgetId"
fun getThemeWidgetKey(appWidgetId: Int) = "lucky_number_widget_theme_$appWidgetId"
} }
@TargetApi(Build.VERSION_CODES.JELLY_BEAN) @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@ -70,24 +73,26 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
private fun onUpdate(context: Context, intent: Intent) { private fun onUpdate(context: Context, intent: Intent) {
intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS)?.forEach { appWidgetId -> intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS)?.forEach { appWidgetId ->
RemoteViews(context.packageName, R.layout.widget_luckynumber).apply { val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0)
setTextViewText(R.id.luckyNumberWidgetNumber, val layoutId = if (savedTheme == 0L) R.layout.widget_luckynumber else R.layout.widget_luckynumber_dark
getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)?.luckyNumber?.toString() ?: "#"
) val luckyNumber = getLuckyNumber(sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0), appWidgetId)
setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, val appIntent = PendingIntent.getActivity(context, MainView.Section.LUCKY_NUMBER.id,
PendingIntent.getActivity(context, MainView.Section.LUCKY_NUMBER.id, MainActivity.getStartIntent(context, MainView.Section.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT)
MainActivity.getStartIntent(context, MainView.Section.LUCKY_NUMBER, true), FLAG_UPDATE_CURRENT))
}.also { val remoteView = RemoteViews(context.packageName, layoutId).apply {
setStyles(it, intent) setTextViewText(R.id.luckyNumberWidgetNumber, luckyNumber?.luckyNumber?.toString() ?: "#")
appWidgetManager.updateAppWidget(appWidgetId, it) setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, appIntent)
} }
setStyles(remoteView, intent)
appWidgetManager.updateAppWidget(appWidgetId, remoteView)
} }
} }
private fun onDelete(intent: Intent) { private fun onDelete(intent: Intent) {
intent.getIntExtra(EXTRA_APPWIDGET_ID, 0).let { val appWidgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0)
if (it != 0) sharedPref.delete(getStudentWidgetKey(it)) if (appWidgetId != 0) sharedPref.delete(getStudentWidgetKey(appWidgetId))
}
} }
private fun getLuckyNumber(studentId: Long, appWidgetId: Int): LuckyNumber? { private fun getLuckyNumber(studentId: Long, appWidgetId: Int): LuckyNumber? {
@ -96,8 +101,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
.filter { true } .filter { true }
.flatMap { studentRepository.getSavedStudents().toMaybe() } .flatMap { studentRepository.getSavedStudents().toMaybe() }
.flatMap { students -> .flatMap { students ->
students.singleOrNull { student -> student.id == studentId } val student = students.singleOrNull { student -> student.id == studentId }
.let { student ->
when { when {
student != null -> Maybe.just(student) student != null -> Maybe.just(student)
studentId != 0L -> { studentId != 0L -> {
@ -109,7 +113,6 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
else -> Maybe.empty() else -> Maybe.empty()
} }
} }
}
.flatMap { semesterRepository.getCurrentSemester(it).toMaybe() } .flatMap { semesterRepository.getCurrentSemester(it).toMaybe() }
.flatMap { luckyNumberRepository.getLuckyNumber(it) } .flatMap { luckyNumberRepository.getLuckyNumber(it) }
.subscribeOn(schedulers.backgroundThread) .subscribeOn(schedulers.backgroundThread)
@ -123,11 +126,14 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
} }
private fun onOptionsChange(context: Context, intent: Intent) { private fun onOptionsChange(context: Context, intent: Intent) {
intent.extras?.let { extras -> intent.extras?.getInt(EXTRA_APPWIDGET_ID)?.let { appWidgetId ->
RemoteViews(context.packageName, R.layout.widget_luckynumber).apply { val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0)
setStyles(this, intent) val layoutId = if (savedTheme == 0L) R.layout.widget_luckynumber else R.layout.widget_luckynumber_dark
appWidgetManager.updateAppWidget(extras.getInt(EXTRA_APPWIDGET_ID), this)
} val remoteView = RemoteViews(context.packageName, layoutId)
setStyles(remoteView, intent)
appWidgetManager.updateAppWidget(appWidgetId, remoteView)
} }
} }
@ -144,7 +150,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
// 1x1 // 1x1
maxWidth < 150 && maxHeight < 110 -> { maxWidth < 150 && maxHeight < 110 -> {
Timber.d("Lucky number widget size: 1x1") Timber.d("Lucky number widget size: 1x1")
views.run { with(views) {
setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE) setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE)
setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE) setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE)
setViewVisibility(R.id.luckyNumberWidgetTitle, GONE) setViewVisibility(R.id.luckyNumberWidgetTitle, GONE)
@ -154,7 +160,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
// 1x2 // 1x2
maxWidth < 150 && maxHeight > 110 -> { maxWidth < 150 && maxHeight > 110 -> {
Timber.d("Lucky number widget size: 1x2") Timber.d("Lucky number widget size: 1x2")
views.run { with(views) {
setViewVisibility(R.id.luckyNumberWidgetImageTop, VISIBLE) setViewVisibility(R.id.luckyNumberWidgetImageTop, VISIBLE)
setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE) setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE)
setViewVisibility(R.id.luckyNumberWidgetTitle, GONE) setViewVisibility(R.id.luckyNumberWidgetTitle, GONE)
@ -164,7 +170,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
// 2x1 // 2x1
maxWidth >= 150 && maxHeight <= 110 -> { maxWidth >= 150 && maxHeight <= 110 -> {
Timber.d("Lucky number widget size: 2x1") Timber.d("Lucky number widget size: 2x1")
views.run { with(views) {
setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE) setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE)
setViewVisibility(R.id.luckyNumberWidgetImageLeft, VISIBLE) setViewVisibility(R.id.luckyNumberWidgetImageLeft, VISIBLE)
setViewVisibility(R.id.luckyNumberWidgetTitle, GONE) setViewVisibility(R.id.luckyNumberWidgetTitle, GONE)
@ -174,7 +180,7 @@ class LuckyNumberWidgetProvider : BroadcastReceiver() {
// 2x2 and bigger // 2x2 and bigger
else -> { else -> {
Timber.d("Lucky number widget size: 2x2 and bigger") Timber.d("Lucky number widget size: 2x2 and bigger")
views.run { with(views) {
setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE) setViewVisibility(R.id.luckyNumberWidgetImageTop, GONE)
setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE) setViewVisibility(R.id.luckyNumberWidgetImageLeft, GONE)
setViewVisibility(R.id.luckyNumberWidgetTitle, VISIBLE) setViewVisibility(R.id.luckyNumberWidgetTitle, VISIBLE)

View File

@ -7,6 +7,7 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.widget.Toast import android.widget.Toast
import android.widget.Toast.LENGTH_LONG import android.widget.Toast.LENGTH_LONG
import androidx.appcompat.app.AlertDialog
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
@ -27,6 +28,8 @@ class TimetableWidgetConfigureActivity : BaseActivity<TimetableWidgetConfigurePr
@Inject @Inject
override lateinit var presenter: TimetableWidgetConfigurePresenter override lateinit var presenter: TimetableWidgetConfigurePresenter
private var dialog: AlertDialog? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setResult(RESULT_CANCELED) setResult(RESULT_CANCELED)
@ -38,11 +41,27 @@ class TimetableWidgetConfigureActivity : BaseActivity<TimetableWidgetConfigurePr
} }
override fun initView() { override fun initView() {
widgetConfigureRecycler.apply { with(widgetConfigureRecycler) {
adapter = configureAdapter adapter = configureAdapter
layoutManager = SmoothScrollLinearLayoutManager(context) layoutManager = SmoothScrollLinearLayoutManager(context)
} }
configureAdapter.setOnItemClickListener { presenter.onItemSelect(it) }
configureAdapter.setOnItemClickListener(presenter::onItemSelect)
}
override fun showThemeDialog() {
val items = arrayOf(
getString(R.string.widget_timetable_theme_light),
getString(R.string.widget_timetable_theme_dark)
)
dialog = AlertDialog.Builder(this, R.style.WulkanowyTheme_WidgetAccountSwitcher)
.setTitle(R.string.widget_timetable_theme_title)
.setOnDismissListener { presenter.onDismissThemeView() }
.setSingleChoiceItems(items, -1) { _, which ->
presenter.onThemeSelect(which)
}
.show()
} }
override fun updateData(data: List<TimetableWidgetConfigureItem>) { override fun updateData(data: List<TimetableWidgetConfigureItem>) {
@ -72,4 +91,9 @@ class TimetableWidgetConfigureActivity : BaseActivity<TimetableWidgetConfigurePr
override fun openLoginView() { override fun openLoginView() {
startActivity(LoginActivity.getStartIntent(this)) startActivity(LoginActivity.getStartIntent(this))
} }
override fun onDestroy() {
super.onDestroy()
dialog?.dismiss()
}
} }

View File

@ -7,6 +7,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
import io.github.wulkanowy.ui.base.ErrorHandler import io.github.wulkanowy.ui.base.ErrorHandler
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getThemeWidgetKey
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import javax.inject.Inject import javax.inject.Inject
@ -21,6 +22,8 @@ class TimetableWidgetConfigurePresenter @Inject constructor(
private var isFromProvider = false private var isFromProvider = false
private var selectedStudent: Student? = null
fun onAttachView(view: TimetableWidgetConfigureView, appWidgetId: Int?, isFromProvider: Boolean?) { fun onAttachView(view: TimetableWidgetConfigureView, appWidgetId: Int?, isFromProvider: Boolean?) {
super.onAttachView(view) super.onAttachView(view)
this.appWidgetId = appWidgetId this.appWidgetId = appWidgetId
@ -31,10 +34,24 @@ class TimetableWidgetConfigurePresenter @Inject constructor(
fun onItemSelect(item: AbstractFlexibleItem<*>) { fun onItemSelect(item: AbstractFlexibleItem<*>) {
if (item is TimetableWidgetConfigureItem) { if (item is TimetableWidgetConfigureItem) {
registerStudent(item.student) selectedStudent = item.student
if (isFromProvider) registerStudent(selectedStudent)
else view?.showThemeDialog()
} }
} }
fun onThemeSelect(index: Int) {
appWidgetId?.let {
sharedPref.putLong(getThemeWidgetKey(it), index.toLong())
}
registerStudent(selectedStudent)
}
fun onDismissThemeView(){
view?.finishView()
}
private fun loadData() { private fun loadData() {
disposable.add(studentRepository.getSavedStudents(false) disposable.add(studentRepository.getSavedStudents(false)
.map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } } .map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } }
@ -46,18 +63,23 @@ class TimetableWidgetConfigurePresenter @Inject constructor(
.subscribe({ .subscribe({
when { when {
it.isEmpty() -> view?.openLoginView() it.isEmpty() -> view?.openLoginView()
it.size == 1 && !isFromProvider -> registerStudent(it.single().student) it.size == 1 && !isFromProvider -> {
selectedStudent = it.single().student
view?.showThemeDialog()
}
else -> view?.updateData(it) else -> view?.updateData(it)
} }
}, { errorHandler.dispatch(it) })) }, { errorHandler.dispatch(it) }))
} }
private fun registerStudent(student: Student) { private fun registerStudent(student: Student?) {
appWidgetId?.also { requireNotNull(student)
sharedPref.putLong(getStudentWidgetKey(it), student.id)
view?.apply { appWidgetId?.let { id ->
updateTimetableWidget(it) sharedPref.putLong(getStudentWidgetKey(id), student.id)
setSuccessResult(it) view?.run {
updateTimetableWidget(id)
setSuccessResult(id)
} }
} }
view?.finishView() view?.finishView()

View File

@ -10,6 +10,8 @@ interface TimetableWidgetConfigureView : BaseView {
fun updateTimetableWidget(widgetId: Int) fun updateTimetableWidget(widgetId: Int)
fun showThemeDialog()
fun setSuccessResult(widgetId: Int) fun setSuccessResult(widgetId: Int)
fun finishView() fun finishView()

View File

@ -1,5 +1,6 @@
package io.github.wulkanowy.ui.modules.timetablewidget package io.github.wulkanowy.ui.modules.timetablewidget
import android.annotation.SuppressLint
import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@ -18,6 +19,7 @@ import io.github.wulkanowy.data.repositories.student.StudentRepository
import io.github.wulkanowy.data.repositories.timetable.TimetableRepository import io.github.wulkanowy.data.repositories.timetable.TimetableRepository
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getDateWidgetKey import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getDateWidgetKey
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getStudentWidgetKey
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider.Companion.getThemeWidgetKey
import io.github.wulkanowy.utils.SchedulersProvider import io.github.wulkanowy.utils.SchedulersProvider
import io.github.wulkanowy.utils.toFormattedString import io.github.wulkanowy.utils.toFormattedString
import io.reactivex.Maybe import io.reactivex.Maybe
@ -36,6 +38,8 @@ class TimetableWidgetFactory(
private var lessons = emptyList<Timetable>() private var lessons = emptyList<Timetable>()
private var layoutId: Int? = null
override fun getLoadingView() = null override fun getLoadingView() = null
override fun hasStableIds() = true override fun hasStableIds() = true
@ -55,17 +59,19 @@ class TimetableWidgetFactory(
val date = LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(appWidgetId), 0)) val date = LocalDate.ofEpochDay(sharedPref.getLong(getDateWidgetKey(appWidgetId), 0))
val studentId = sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0) val studentId = sharedPref.getLong(getStudentWidgetKey(appWidgetId), 0)
val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0)
layoutId = if (savedTheme == 0L) R.layout.item_widget_timetable else R.layout.item_widget_timetable_dark
lessons = try { lessons = try {
studentRepository.isStudentSaved() studentRepository.isStudentSaved()
.filter { true } .filter { true }
.flatMap { studentRepository.getSavedStudents().toMaybe() } .flatMap { studentRepository.getSavedStudents().toMaybe() }
.flatMap { .flatMap {
it.singleOrNull { student -> student.id == studentId } val student = it.singleOrNull { student -> student.id == studentId }
.let { student ->
if (student != null) Maybe.just(student) if (student != null) Maybe.just(student)
else Maybe.empty() else Maybe.empty()
} }
}
.flatMap { semesterRepository.getCurrentSemester(it).toMaybe() } .flatMap { semesterRepository.getCurrentSemester(it).toMaybe() }
.flatMap { timetableRepository.getTimetable(it, date, date).toMaybe() } .flatMap { timetableRepository.getTimetable(it, date, date).toMaybe() }
.map { item -> item.sortedBy { it.number } } .map { item -> item.sortedBy { it.number } }
@ -78,39 +84,42 @@ class TimetableWidgetFactory(
} }
} }
@SuppressLint("DefaultLocale")
override fun getViewAt(position: Int): RemoteViews? { override fun getViewAt(position: Int): RemoteViews? {
if (position == INVALID_POSITION || lessons.getOrNull(position) == null) return null if (position == INVALID_POSITION || lessons.getOrNull(position) == null) return null
return RemoteViews(context.packageName, R.layout.item_widget_timetable).apply { return RemoteViews(context.packageName, layoutId!!).apply {
lessons[position].let { val lesson = lessons[position]
setTextViewText(R.id.timetableWidgetItemSubject, it.subject)
setTextViewText(R.id.timetableWidgetItemNumber, it.number.toString())
setTextViewText(R.id.timetableWidgetItemTime, it.start.toFormattedString("HH:mm") +
" - ${it.end.toFormattedString("HH:mm")}")
if (it.room.isNotBlank()) { setTextViewText(R.id.timetableWidgetItemSubject, lesson.subject)
setTextViewText(R.id.timetableWidgetItemRoom, "${context.getString(R.string.timetable_room)} ${it.room}") setTextViewText(R.id.timetableWidgetItemNumber, lesson.number.toString())
setTextViewText(R.id.timetableWidgetItemTime, lesson.start.toFormattedString("HH:mm") +
" - ${lesson.end.toFormattedString("HH:mm")}")
if (lesson.room.isNotBlank()) {
setTextViewText(R.id.timetableWidgetItemRoom, "${context.getString(R.string.timetable_room)} ${lesson.room}")
} else setTextViewText(R.id.timetableWidgetItemRoom, "") } else setTextViewText(R.id.timetableWidgetItemRoom, "")
if (it.info.isNotBlank()) { if (lesson.info.isNotBlank()) {
setViewVisibility(R.id.timetableWidgetItemDescription, VISIBLE) setViewVisibility(R.id.timetableWidgetItemDescription, VISIBLE)
setTextViewText(R.id.timetableWidgetItemDescription, it.run { setTextViewText(R.id.timetableWidgetItemDescription,
with(lesson) {
when (true) { when (true) {
canceled && !changes -> "Lekcja odwołana: $info" canceled && !changes -> "Lekcja odwołana: ${lesson.info}"
changes && teacher.isNotBlank() -> "Zastępstwo: $teacher" changes && teacher.isNotBlank() -> "Zastępstwo: ${lesson.teacher}"
changes && teacher.isBlank() -> "Zastępstwo, ${info.decapitalize()}" changes && teacher.isBlank() -> "Zastępstwo, ${lesson.info.decapitalize()}"
else -> it.info.capitalize() else -> info.capitalize()
} }
}) })
} else setViewVisibility(R.id.timetableWidgetItemDescription, GONE) } else setViewVisibility(R.id.timetableWidgetItemDescription, GONE)
if (it.canceled) { if (lesson.canceled) {
setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", setInt(R.id.timetableWidgetItemSubject, "setPaintFlags",
STRIKE_THRU_TEXT_FLAG or ANTI_ALIAS_FLAG) STRIKE_THRU_TEXT_FLAG or ANTI_ALIAS_FLAG)
} else { } else {
setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", ANTI_ALIAS_FLAG) setInt(R.id.timetableWidgetItemSubject, "setPaintFlags", ANTI_ALIAS_FLAG)
} }
}
setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent()) setOnClickFillInIntent(R.id.timetableWidgetItemContainer, Intent())
} }
} }

View File

@ -54,21 +54,24 @@ class TimetableWidgetProvider : BroadcastReceiver() {
lateinit var analytics: FirebaseAnalyticsHelper lateinit var analytics: FirebaseAnalyticsHelper
companion object { companion object {
private const val EXTRA_TOGGLED_WIDGET_ID = "extraToggledWidget"
private const val EXTRA_BUTTON_TYPE = "extraButtonType"
private const val BUTTON_NEXT = "buttonNext"
private const val BUTTON_PREV = "buttonPrev"
private const val BUTTON_RESET = "buttonReset"
const val EXTRA_FROM_PROVIDER = "extraFromProvider" const val EXTRA_FROM_PROVIDER = "extraFromProvider"
const val EXTRA_TOGGLED_WIDGET_ID = "extraToggledWidget"
const val EXTRA_BUTTON_TYPE = "extraButtonType"
const val BUTTON_NEXT = "buttonNext"
const val BUTTON_PREV = "buttonPrev"
const val BUTTON_RESET = "buttonReset"
fun getDateWidgetKey(appWidgetId: Int) = "timetable_widget_date_$appWidgetId" fun getDateWidgetKey(appWidgetId: Int) = "timetable_widget_date_$appWidgetId"
fun getStudentWidgetKey(appWidgetId: Int) = "timetable_widget_student_$appWidgetId" fun getStudentWidgetKey(appWidgetId: Int) = "timetable_widget_student_$appWidgetId"
fun getThemeWidgetKey(appWidgetId: Int) = "timetable_widget_theme_$appWidgetId"
} }
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
@ -102,45 +105,56 @@ class TimetableWidgetProvider : BroadcastReceiver() {
} }
private fun onDelete(intent: Intent) { private fun onDelete(intent: Intent) {
intent.getIntExtra(EXTRA_APPWIDGET_ID, 0).let { val appWidgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0)
if (it != 0) {
sharedPref.apply { if (appWidgetId != 0) {
delete(getStudentWidgetKey(it)) with(sharedPref) {
delete(getDateWidgetKey(it)) delete(getStudentWidgetKey(appWidgetId))
} delete(getDateWidgetKey(appWidgetId))
} }
} }
} }
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
private fun updateWidget(context: Context, appWidgetId: Int, date: LocalDate, student: Student?) { private fun updateWidget(context: Context, appWidgetId: Int, date: LocalDate, student: Student?) {
RemoteViews(context.packageName, R.layout.widget_timetable).apply { val savedTheme = sharedPref.getLong(getThemeWidgetKey(appWidgetId), 0)
setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty) val layoutId = if (savedTheme == 0L) R.layout.widget_timetable else R.layout.widget_timetable_dark
setTextViewText(R.id.timetableWidgetDate, "${date.shortcutWeekDayName.capitalize()} ${date.toFormattedString()}")
setTextViewText(R.id.timetableWidgetName, student?.studentName ?: context.getString(R.string.all_no_data)) val nextNavIntent = createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT)
setRemoteAdapter(R.id.timetableWidgetList, Intent(context, TimetableWidgetService::class.java) val prevNavIntent = createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV)
.apply { putExtra(EXTRA_APPWIDGET_ID, appWidgetId) }) val resetNavIntent = createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET)
setOnClickPendingIntent(R.id.timetableWidgetNext, createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT)) val adapterIntent = Intent(context, TimetableWidgetService::class.java)
setOnClickPendingIntent(R.id.timetableWidgetPrev, createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV)) .apply {
createNavIntent(context, Int.MAX_VALUE - appWidgetId, appWidgetId, BUTTON_RESET).let { putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
setOnClickPendingIntent(R.id.timetableWidgetDate, it) //make Intent unique
setOnClickPendingIntent(R.id.timetableWidgetName, it) action = appWidgetId.toString()
} }
setOnClickPendingIntent(R.id.timetableWidgetAccount, PendingIntent.getActivity(context, -Int.MAX_VALUE + appWidgetId, val accountIntent = PendingIntent.getActivity(context, -Int.MAX_VALUE + appWidgetId,
Intent(context, TimetableWidgetConfigureActivity::class.java).apply { Intent(context, TimetableWidgetConfigureActivity::class.java).apply {
addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK) addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK)
putExtra(EXTRA_APPWIDGET_ID, appWidgetId) putExtra(EXTRA_APPWIDGET_ID, appWidgetId)
putExtra(EXTRA_FROM_PROVIDER, true) putExtra(EXTRA_FROM_PROVIDER, true)
}, FLAG_UPDATE_CURRENT)) }, FLAG_UPDATE_CURRENT)
setPendingIntentTemplate(R.id.timetableWidgetList, val appIntent = PendingIntent.getActivity(context, MainView.Section.TIMETABLE.id,
PendingIntent.getActivity(context, MainView.Section.TIMETABLE.id, MainActivity.getStartIntent(context, MainView.Section.TIMETABLE, true), FLAG_UPDATE_CURRENT)
MainActivity.getStartIntent(context, MainView.Section.TIMETABLE, true), FLAG_UPDATE_CURRENT))
}.also { val remoteView = RemoteViews(context.packageName, layoutId).apply {
sharedPref.putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true) setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty)
appWidgetManager.apply { setTextViewText(R.id.timetableWidgetDate, "${date.shortcutWeekDayName.capitalize()} ${date.toFormattedString()}")
notifyAppWidgetViewDataChanged(appWidgetId, R.id.timetableWidgetList) setTextViewText(R.id.timetableWidgetName, student?.studentName ?: context.getString(R.string.all_no_data))
updateAppWidget(appWidgetId, it) setRemoteAdapter(R.id.timetableWidgetList, adapterIntent)
setOnClickPendingIntent(R.id.timetableWidgetNext, nextNavIntent)
setOnClickPendingIntent(R.id.timetableWidgetPrev, prevNavIntent)
setOnClickPendingIntent(R.id.timetableWidgetDate, resetNavIntent)
setOnClickPendingIntent(R.id.timetableWidgetName, resetNavIntent)
setOnClickPendingIntent(R.id.timetableWidgetAccount, accountIntent)
setPendingIntentTemplate(R.id.timetableWidgetList, appIntent)
} }
sharedPref.putLong(getDateWidgetKey(appWidgetId), date.toEpochDay(), true)
with(appWidgetManager) {
notifyAppWidgetViewDataChanged(appWidgetId, R.id.timetableWidgetList)
updateAppWidget(appWidgetId, remoteView)
} }
} }
@ -159,8 +173,7 @@ class TimetableWidgetProvider : BroadcastReceiver() {
.filter { true } .filter { true }
.flatMap { studentRepository.getSavedStudents(false).toMaybe() } .flatMap { studentRepository.getSavedStudents(false).toMaybe() }
.flatMap { students -> .flatMap { students ->
students.singleOrNull { student -> student.id == studentId } val student = students.singleOrNull { student -> student.id == studentId }
.let { student ->
when { when {
student != null -> Maybe.just(student) student != null -> Maybe.just(student)
studentId != 0L -> { studentId != 0L -> {
@ -172,7 +185,6 @@ class TimetableWidgetProvider : BroadcastReceiver() {
else -> Maybe.empty() else -> Maybe.empty()
} }
} }
}
.subscribeOn(schedulers.backgroundThread) .subscribeOn(schedulers.backgroundThread)
.blockingGet() .blockingGet()
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<solid android:color="#FFF" /> <solid android:color="@android:color/white" />
<corners android:radius="5dp" /> <corners android:radius="5dp" />
</shape> </shape>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/colorWidgetBackground" />
<corners android:radius="5dp" />
</shape>

View File

@ -1,14 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/timetableWidgetItemContainer" android:id="@+id/timetableWidgetItemContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/ic_all_divider"
android:minHeight="45dp" android:minHeight="45dp"
android:orientation="horizontal" android:orientation="vertical"
tools:context=".ui.modules.timetablewidget.TimetableWidgetFactory"> tools:context=".ui.modules.timetablewidget.TimetableWidgetFactory">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white">
<TextView <TextView
android:id="@+id/timetableWidgetItemNumber" android:id="@+id/timetableWidgetItemNumber"
android:layout_width="45dp" android:layout_width="45dp"
@ -32,7 +36,7 @@
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_toEndOf="@id/timetableWidgetItemNumber" android:layout_toEndOf="@id/timetableWidgetItemNumber"
android:layout_toRightOf="@id/timetableWidgetItemNumber" android:layout_toRightOf="@id/timetableWidgetItemNumber"
android:textColor="@android:color/secondary_text_light" android:textColor="@android:color/black"
android:textSize="13sp" android:textSize="13sp"
tools:text="08:00 - 08:45" /> tools:text="08:00 - 08:45" />
@ -47,7 +51,7 @@
android:layout_marginRight="25dp" android:layout_marginRight="25dp"
android:layout_toEndOf="@id/timetableWidgetItemTime" android:layout_toEndOf="@id/timetableWidgetItemTime"
android:layout_toRightOf="@id/timetableWidgetItemTime" android:layout_toRightOf="@id/timetableWidgetItemTime"
android:textColor="@android:color/secondary_text_light" android:textColor="@android:color/black"
android:textSize="13sp" android:textSize="13sp"
tools:text="@tools:sample/lorem" /> tools:text="@tools:sample/lorem" />
@ -79,7 +83,13 @@
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:layout_toEndOf="@id/timetableWidgetItemNumber" android:layout_toEndOf="@id/timetableWidgetItemNumber"
android:layout_toRightOf="@id/timetableWidgetItemNumber" android:layout_toRightOf="@id/timetableWidgetItemNumber"
android:textColor="@android:color/secondary_text_light" android:textColor="@android:color/black"
android:textSize="12sp" android:textSize="12sp"
tools:text="Sala 25" /> tools:text="Sala 25" />
</RelativeLayout> </RelativeLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorDivider" />
</LinearLayout>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/timetableWidgetItemContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="45dp"
android:orientation="vertical"
tools:context=".ui.modules.timetablewidget.TimetableWidgetFactory">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorWidgetBackground">
<TextView
android:id="@+id/timetableWidgetItemNumber"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_centerVertical="true"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:gravity="center"
android:maxLines="1"
android:textColor="@android:color/white"
android:textSize="25sp"
tools:text="1" />
<TextView
android:id="@+id/timetableWidgetItemTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:layout_toEndOf="@id/timetableWidgetItemNumber"
android:layout_toRightOf="@id/timetableWidgetItemNumber"
android:textColor="@android:color/white"
android:textSize="13sp"
tools:text="08:00 - 08:45" />
<TextView
android:id="@+id/timetableWidgetItemSubject"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="25dp"
android:layout_marginRight="25dp"
android:layout_toEndOf="@id/timetableWidgetItemTime"
android:layout_toRightOf="@id/timetableWidgetItemTime"
android:textColor="@android:color/white"
android:textSize="13sp"
tools:text="@tools:sample/lorem" />
<TextView
android:id="@+id/timetableWidgetItemDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/timetableWidgetItemSubject"
android:layout_marginStart="15dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="3dp"
android:layout_marginEnd="25dp"
android:layout_marginRight="25dp"
android:layout_marginBottom="5dp"
android:layout_toEndOf="@id/timetableWidgetItemTime"
android:layout_toRightOf="@id/timetableWidgetItemTime"
android:textColor="@color/colorPrimaryLight"
android:textSize="12sp"
tools:text="Lekcja odwołana: uczniowie zwolnieni do domu" />
<TextView
android:id="@+id/timetableWidgetItemRoom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/timetableWidgetItemTime"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="3dp"
android:layout_marginBottom="5dp"
android:layout_toEndOf="@id/timetableWidgetItemNumber"
android:layout_toRightOf="@id/timetableWidgetItemNumber"
android:textColor="@android:color/white"
android:textSize="12sp"
tools:text="Sala 25" />
</RelativeLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorDividerInverse" />
</LinearLayout>

View File

@ -4,7 +4,7 @@
android:id="@+id/luckyNumberWidgetContainer" android:id="@+id/luckyNumberWidgetContainer"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:background="@drawable/backgorund_luckynumber_widget" android:background="@drawable/background_luckynumber_widget"
android:gravity="center" android:gravity="center"
android:padding="10dp" android:padding="10dp"
tools:context=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider"> tools:context=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider">

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/luckyNumberWidgetContainer"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background_luckynumber_widget_dark"
android:gravity="center"
android:padding="10dp"
tools:context=".ui.modules.luckynumberwidget.LuckyNumberWidgetProvider">
<ImageView
android:id="@+id/luckyNumberWidgetImageTop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/luckyNumberWidgetNumber"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:contentDescription="@string/lucky_number_title"
android:gravity="center"
android:src="@drawable/ic_widget_clover"
android:tint="@android:color/white"
android:visibility="gone"
tools:visibility="visible" />
<TextView
android:id="@+id/luckyNumberWidgetTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:gravity="center"
android:labelFor="@id/luckyNumberWidgetImageTop"
android:text="@string/lucky_number_title"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="22sp"
android:visibility="gone"
tools:visibility="visible" />
<ImageView
android:id="@+id/luckyNumberWidgetImageLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/luckyNumberWidgetNumber"
android:contentDescription="@string/lucky_number_title"
android:src="@drawable/ic_widget_clover"
android:tint="@android:color/white"
android:visibility="gone"
tools:visibility="visible" />
<TextView
android:id="@+id/luckyNumberWidgetNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/luckyNumberWidgetTitle"
android:layout_toEndOf="@id/luckyNumberWidgetImageLeft"
android:layout_toRightOf="@id/luckyNumberWidgetImageLeft"
android:gravity="center"
android:text="#"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="34sp"
tools:ignore="HardcodedText"
tools:text="13" />
</RelativeLayout>

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorWidgetBackground"
tools:context=".ui.modules.timetablewidget.TimetableWidgetProvider">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@color/colorWidgetTopBar">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/timetableWidgetAccount"
android:layout_toLeftOf="@id/timetableWidgetAccount"
android:layout_toEndOf="@id/timetableWidgetNext"
android:layout_toRightOf="@id/timetableWidgetNext"
android:orientation="vertical">
<TextView
android:id="@+id/timetableWidgetDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:maxLines="1"
android:textColor="@android:color/white"
android:textSize="15sp"
tools:text="Pon. 30.03.2019" />
<TextView
android:id="@+id/timetableWidgetName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:maxLines="1"
android:textColor="@android:color/white"
android:textSize="13sp"
tools:text="Jan Kowalski" />
</LinearLayout>
<ImageButton
android:id="@+id/timetableWidgetAccount"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:background="?android:selectableItemBackground"
android:contentDescription="@string/account_title"
android:src="@drawable/ic_widget_account" />
<ImageButton
android:id="@+id/timetableWidgetPrev"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="10dp"
android:layout_marginLeft="10dp"
android:backgroundTint="@color/colorWidgetNavButton"
android:contentDescription="@string/all_prev"
android:src="@drawable/ic_widget_chevron"
tools:targetApi="lollipop" />
<ImageButton
android:id="@+id/timetableWidgetNext"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@id/timetableWidgetPrev"
android:layout_toRightOf="@id/timetableWidgetPrev"
android:backgroundTint="@color/colorWidgetNavButton"
android:contentDescription="@string/all_next"
android:rotation="180"
android:src="@drawable/ic_widget_chevron"
tools:targetApi="lollipop" />
</RelativeLayout>
<ListView
android:id="@+id/timetableWidgetList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="56dp"
tools:listitem="@layout/item_widget_timetable_dark" />
<TextView
android:id="@+id/timetableWidgetEmpty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/widget_timetable_no_items"
android:textColor="@android:color/white"
android:textSize="20sp"
tools:visibility="invisible" />
</FrameLayout>

View File

@ -260,6 +260,9 @@
<!--Timetable Widget--> <!--Timetable Widget-->
<string name="widget_timetable_no_items">Brak lekcji</string> <string name="widget_timetable_no_items">Brak lekcji</string>
<string name="widget_timetable_theme_title">Wybierz motyw</string>
<string name="widget_timetable_theme_light">Jasny</string>
<string name="widget_timetable_theme_dark">Ciemny</string>
<!--Preferences--> <!--Preferences-->

View File

@ -31,9 +31,10 @@
<color name="grade_vulcan_one">#d65757</color> <color name="grade_vulcan_one">#d65757</color>
<color name="grade_vulcan_default">#3d5f9c</color> <color name="grade_vulcan_default">#3d5f9c</color>
<color name="chip_backgroundColor_inverse">#595959</color>
<color name="chip_labelColor_inverse">#fefefe</color> <!--Dark color resource for app widgets-->
<color name="chip_detailed_backgroundColor">#fefefe</color>
<color name="filterable_list_backgroundColor_inverse">#393939</color> <color name="colorWidgetBackground">#121212</color>
<color name="filterable_list_textColor_inverse">#fefefe</color> <color name="colorWidgetTopBar">#272727</color>
<color name="colorWidgetNavButton">#383838</color>
</resources> </resources>

View File

@ -244,6 +244,9 @@
<!--Timetable Widget--> <!--Timetable Widget-->
<string name="widget_timetable_no_items">No lessons</string> <string name="widget_timetable_no_items">No lessons</string>
<string name="widget_timetable_theme_title">Choose theme</string>
<string name="widget_timetable_theme_light">Light</string>
<string name="widget_timetable_theme_dark">Dark</string>
<!--Preferences--> <!--Preferences-->

View File

@ -23,6 +23,7 @@
<style name="WulkanowyTheme.WidgetAccountSwitcher" parent="Theme.MaterialComponents.Light.Dialog"> <style name="WulkanowyTheme.WidgetAccountSwitcher" parent="Theme.MaterialComponents.Light.Dialog">
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorSecondary">@color/colorPrimary</item>
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item> <item name="windowNoTitle">true</item>
<item name="android:textColor">?android:textColorPrimary</item> <item name="android:textColor">?android:textColorPrimary</item>