Merge branch 'master' into translation
* master: Gix switcher, update glance, add glance order, add ampm toggle Merge crud-device Add dividers toggle Add integreations activity, removed long time until intervals Change music fragment to at a glance Update build version Fix #83 Add current song Add clock text color
1
.gitignore
vendored
@ -8,3 +8,4 @@
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
/tasksintegration/build
|
||||
apikey.properties
|
BIN
.idea/caches/build_file_checksums.ser
generated
1
.idea/gradle.xml
generated
@ -11,6 +11,7 @@
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
<option value="$PROJECT_DIR$/googlefit" />
|
||||
<option value="$PROJECT_DIR$/tasksintegration" />
|
||||
</set>
|
||||
</option>
|
||||
|
1
.idea/modules.xml
generated
@ -4,6 +4,7 @@
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Another Widget.iml" filepath="$PROJECT_DIR$/Another Widget.iml" group="Another Widget" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" group="Another Widget/app" />
|
||||
<module fileurl="file://$PROJECT_DIR$/googlefit/googlefit.iml" filepath="$PROJECT_DIR$/googlefit/googlefit.iml" group="Another Widget/googlefit" />
|
||||
<module fileurl="file://$PROJECT_DIR$/tasksintegration/tasksintegration.iml" filepath="$PROJECT_DIR$/tasksintegration/tasksintegration.iml" group="Another Widget/tasksintegration" />
|
||||
</modules>
|
||||
</component>
|
||||
|
@ -18,8 +18,8 @@ android {
|
||||
applicationId "com.tommasoberlose.anotherwidget"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 29
|
||||
versionCode 77
|
||||
versionName "2.0.5"
|
||||
versionCode 83
|
||||
versionName "2.0.6"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@ -53,7 +53,9 @@ android {
|
||||
|
||||
viewBinding.enabled = true
|
||||
|
||||
dynamicFeatures = [":tasksintegration"]
|
||||
dynamicFeatures = [":tasksintegration", ":googlefit"]
|
||||
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -110,9 +112,6 @@ dependencies {
|
||||
implementation "androidx.palette:palette-ktx:1.0.0"
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
|
||||
// Recommended: Add the Firebase SDK for Google Analytics.
|
||||
implementation 'com.google.firebase:firebase-analytics:17.4.0'
|
||||
|
||||
// Add the Firebase SDK for Crashlytics.
|
||||
implementation 'com.google.firebase:firebase-crashlytics:17.0.0'
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.IntegrationsActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
|
||||
|
||||
<receiver android:name=".ui.widgets.MainWidget">
|
||||
@ -139,6 +140,23 @@
|
||||
|
||||
<service android:name=".services.EventListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<service android:name=".receivers.MusicNotificationListener"
|
||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.notification.NotificationListenerService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver android:name=".receivers.BatteryLevelReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
|
||||
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
|
||||
<action android:name="android.intent.action.BATTERY_LOW"/>
|
||||
<action android:name="android.intent.action.BATTERY_OKAY"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,27 @@
|
||||
package com.tommasoberlose.anotherwidget.components
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import kotlinx.android.synthetic.main.custom_notes_dialog_layout.view.*
|
||||
|
||||
class CustomNotesDialog(context: Context) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||
|
||||
init {
|
||||
val view = View.inflate(context, R.layout.custom_notes_dialog_layout, null)
|
||||
view.notes.setText(Preferences.customNotes)
|
||||
|
||||
view.action_positive.setOnClickListener {
|
||||
Preferences.customNotes = view.notes.text.toString()
|
||||
this.dismiss()
|
||||
}
|
||||
|
||||
view.notes.requestFocus()
|
||||
|
||||
setContentView(view)
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package com.tommasoberlose.anotherwidget.components
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||
import com.tommasoberlose.anotherwidget.helpers.GlanceProviderHelper
|
||||
import com.tommasoberlose.anotherwidget.models.GlanceProvider
|
||||
import kotlinx.android.synthetic.main.glance_provider_sort_bottom_menu.view.*
|
||||
import kotlinx.coroutines.*
|
||||
import net.idik.lib.slimadapter.SlimAdapter
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class GlanceProviderSortMenu(
|
||||
context: Context
|
||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||
|
||||
private lateinit var adapter: SlimAdapter
|
||||
|
||||
override fun show() {
|
||||
val view = View.inflate(context, R.layout.glance_provider_sort_bottom_menu, null)
|
||||
|
||||
// Header
|
||||
view.header_text.text = context.getString(R.string.settings_sort_glance_providers_title)
|
||||
|
||||
// List
|
||||
adapter = SlimAdapter.create()
|
||||
|
||||
view.menu.setHasFixedSize(true)
|
||||
val mLayoutManager = LinearLayoutManager(context)
|
||||
view.menu.layoutManager = mLayoutManager
|
||||
|
||||
adapter = SlimAdapter.create()
|
||||
adapter
|
||||
.register<GlanceProvider>(R.layout.glance_provider_item) { item, injector ->
|
||||
injector
|
||||
.text(R.id.title, item.title)
|
||||
.with<ImageView>(R.id.icon) {
|
||||
it.setImageDrawable(ContextCompat.getDrawable(context, item.icon))
|
||||
}
|
||||
}
|
||||
.attachTo(view.menu)
|
||||
|
||||
val mIth = ItemTouchHelper(
|
||||
object : ItemTouchHelper.SimpleCallback(
|
||||
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
|
||||
ItemTouchHelper.LEFT
|
||||
) {
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
val fromPos = viewHolder.adapterPosition
|
||||
val toPos = target.adapterPosition
|
||||
// move item in `fromPos` to `toPos` in adapter.
|
||||
adapter.notifyItemMoved(fromPos, toPos)
|
||||
|
||||
val list = GlanceProviderHelper.getGlanceProviders()
|
||||
Collections.swap(list, fromPos, toPos)
|
||||
GlanceProviderHelper.saveGlanceProviderOrder(list)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSwiped(
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
direction: Int
|
||||
) {
|
||||
// remove from adapter
|
||||
}
|
||||
})
|
||||
|
||||
mIth.attachToRecyclerView(view.menu)
|
||||
|
||||
adapter.updateData(
|
||||
GlanceProviderHelper.getGlanceProviders()
|
||||
.mapNotNull { GlanceProviderHelper.getGlanceProviderById(context, it) }
|
||||
)
|
||||
|
||||
setContentView(view)
|
||||
super.show()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.tommasoberlose.anotherwidget.db
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.chibatching.kotpref.bulk
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
@ -8,6 +9,8 @@ import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmResults
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class EventRepository(val context: Context) {
|
||||
private val realm by lazy { Realm.getDefaultInstance() }
|
||||
@ -36,22 +39,36 @@ class EventRepository(val context: Context) {
|
||||
}
|
||||
|
||||
fun saveNextEventData(event: Event) {
|
||||
Preferences.nextEventId = event.id
|
||||
Preferences.nextEventId = event.eventID
|
||||
}
|
||||
|
||||
fun getNextEvent(): Event? = realm.where(Event::class.java).equalTo("id", Preferences.nextEventId).findFirst() ?: realm.where(Event::class.java).findFirst()
|
||||
fun getNextEvent(): Event? {
|
||||
val nextEvent = getEventByEventId(Preferences.nextEventId)
|
||||
return if (nextEvent != null && nextEvent.endDate > Calendar.getInstance().timeInMillis) {
|
||||
nextEvent
|
||||
} else {
|
||||
val events = getEvents()
|
||||
if (events.isNotEmpty()) {
|
||||
val newNextEvent = events.first()
|
||||
Preferences.nextEventId = newNextEvent!!.eventID
|
||||
newNextEvent
|
||||
} else {
|
||||
resetNextEventData()
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getEventByEventId(id: Long): Event? = realm.where(Event::class.java).equalTo("eventID", id).findFirst()
|
||||
|
||||
fun goToNextEvent() {
|
||||
val eventList = realm.where(Event::class.java).findAll()
|
||||
|
||||
val eventList = getEvents()
|
||||
if (eventList.isNotEmpty()) {
|
||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
||||
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
||||
if (index > -1 && index < eventList.size - 1) {
|
||||
Preferences.nextEventId = eventList[index + 1]!!.id
|
||||
Preferences.nextEventId = eventList[index + 1]!!.eventID
|
||||
} else {
|
||||
Preferences.nextEventId = eventList.first()!!.id
|
||||
Preferences.nextEventId = eventList.first()!!.eventID
|
||||
}
|
||||
} else {
|
||||
resetNextEventData()
|
||||
@ -61,14 +78,13 @@ class EventRepository(val context: Context) {
|
||||
}
|
||||
|
||||
fun goToPreviousEvent() {
|
||||
val eventList = realm.where(Event::class.java).findAll()
|
||||
|
||||
val eventList = getEvents()
|
||||
if (eventList.isNotEmpty()) {
|
||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
||||
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
||||
if (index > 0) {
|
||||
Preferences.nextEventId = eventList[index - 1]!!.id
|
||||
Preferences.nextEventId = eventList[index - 1]!!.eventID
|
||||
} else {
|
||||
Preferences.nextEventId = eventList.last()!!.id
|
||||
Preferences.nextEventId = eventList.last()!!.eventID
|
||||
}
|
||||
} else {
|
||||
resetNextEventData()
|
||||
@ -77,7 +93,10 @@ class EventRepository(val context: Context) {
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
fun getEvents(): RealmResults<Event> = realm.where(Event::class.java).findAll()
|
||||
|
||||
fun getEventsCount(): Int = realm.where(Event::class.java).findAll().size
|
||||
fun getEvents(): RealmResults<Event> {
|
||||
val now = Calendar.getInstance().timeInMillis
|
||||
return realm.where(Event::class.java).greaterThan("endDate", now).findAll()
|
||||
}
|
||||
|
||||
fun getEventsCount(): Int = getEvents().size
|
||||
}
|
@ -14,4 +14,12 @@ object Constants {
|
||||
MEDIUM(2),
|
||||
LARGE(3)
|
||||
}
|
||||
|
||||
enum class GlanceProviderId(val id: String) {
|
||||
PLAYING_SONG("PLAYING_SONG"),
|
||||
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
|
||||
// BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
|
||||
CUSTOM_INFO("CUSTOM_INFO"),
|
||||
// GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS")
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ object Preferences : KotprefModel() {
|
||||
|
||||
var darkThemePreference by intPref(default = MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
|
||||
// Calendar and weather
|
||||
var showEvents by booleanPref(key = "PREF_SHOW_EVENTS", default = false)
|
||||
var showWeather by booleanPref(key = "PREF_SHOW_WEATHER", default = false)
|
||||
var weatherIcon by stringPref(key = "PREF_WEATHER_ICON", default = "")
|
||||
@ -45,6 +46,11 @@ object Preferences : KotprefModel() {
|
||||
var backgroundCardColor by stringPref(default = "#000000")
|
||||
var backgroundCardAlpha by stringPref(default = "00")
|
||||
|
||||
var clockTextColor by stringPref(default = "#FFFFFF")
|
||||
var clockTextAlpha by stringPref(default = "FF")
|
||||
var showAMPMIndicator by booleanPref(default = true)
|
||||
|
||||
// Global
|
||||
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f)
|
||||
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
|
||||
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
|
||||
@ -52,7 +58,6 @@ object Preferences : KotprefModel() {
|
||||
var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false)
|
||||
var clockAppName by stringPref(key = "PREF_CLOCK_APP_NAME", default = "")
|
||||
var clockAppPackage by stringPref(key = "PREF_CLOCK_APP_PACKAGE", default = "")
|
||||
var showNextAlarm by booleanPref(default = false)
|
||||
var textShadow by intPref(key = "PREF_TEXT_SHADOW", default = 1)
|
||||
var showDiffTime by booleanPref(key = "PREF_SHOW_DIFF_TIME", default = true)
|
||||
var showDeclinedEvents by booleanPref(key = "PREF_SHOW_DECLINED_EVENTS", default = false)
|
||||
@ -61,9 +66,31 @@ object Preferences : KotprefModel() {
|
||||
var customFontFile by stringPref(key = "PREF_CUSTOM_FONT_FILE")
|
||||
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
|
||||
|
||||
var showDividers by booleanPref(default = true)
|
||||
|
||||
// Settings
|
||||
var showWallpaper by booleanPref(default = true)
|
||||
var showBigClockWarning by booleanPref(default = true)
|
||||
var showWeatherWarning by booleanPref(default = true)
|
||||
var showPreview by booleanPref(default = true)
|
||||
var showXiaomiWarning by booleanPref(default = true)
|
||||
|
||||
// Glance
|
||||
var showGlance by booleanPref(default = true)
|
||||
var enabledGlanceProviderOrder by stringPref(default = "")
|
||||
var customNotes by stringPref(default = "")
|
||||
var showNextAlarm by booleanPref(default = true)
|
||||
var showBatteryCharging by booleanPref(default = false)
|
||||
var isBatteryLevelLow by booleanPref(default = false)
|
||||
var googleFitSteps by longPref(default = -1)
|
||||
|
||||
var showMusic by booleanPref(default = false)
|
||||
var mediaInfoFormat by stringPref(default = "")
|
||||
var mediaPlayerTitle by stringPref(default = "")
|
||||
var mediaPlayerAlbum by stringPref(default = "")
|
||||
var mediaPlayerArtist by stringPref(default = "")
|
||||
var mediaPlayerPackage by stringPref(default = "")
|
||||
|
||||
// Integrations
|
||||
var installedIntegrations by intPref(default = 0)
|
||||
}
|
||||
|
@ -17,22 +17,41 @@ object BitmapHelper {
|
||||
//Define a bitmap with the same size as the view
|
||||
val measuredWidth = View.MeasureSpec.makeMeasureSpec(width ?: view.width, if (width != null) View.MeasureSpec.EXACTLY else View.MeasureSpec.AT_MOST)
|
||||
val measuredHeight = View.MeasureSpec.makeMeasureSpec(height ?: view.height, if (height != null) View.MeasureSpec.EXACTLY else View.MeasureSpec.UNSPECIFIED)
|
||||
view.measure(measuredWidth, measuredHeight)
|
||||
view.measure(
|
||||
if (measuredWidth > 0) measuredWidth else 0,
|
||||
if (measuredHeight > 0) measuredHeight else 0
|
||||
)
|
||||
|
||||
val calculatedWidth = view.measuredWidth
|
||||
val widgetWidth = if (calculatedWidth in 1..16000) {
|
||||
calculatedWidth
|
||||
} else if (width != null && width > 0) {
|
||||
width
|
||||
} else {
|
||||
1
|
||||
}
|
||||
val calculatedHeight = view.measuredHeight
|
||||
val widgetHeight = if (calculatedHeight in 1..16000) {
|
||||
calculatedHeight
|
||||
} else if (height != null && height > 0) {
|
||||
height
|
||||
} else {
|
||||
1
|
||||
}
|
||||
|
||||
if (draw) {
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("initialWidth", width ?: -1)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("initialHeight", height ?: -1)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("measuredWidth", view.measuredWidth)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("measuredWidth_spec", measuredWidth)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("measuredHeight", view.measuredHeight)
|
||||
FirebaseCrashlytics.getInstance()
|
||||
.setCustomKey("measuredHeight_spec", measuredHeight)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("WIDTH SPEC", measuredWidth)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("HEIGHT SPEC", measuredHeight)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredWidth", view.measuredWidth)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredHeight", view.measuredHeight)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final width", measuredWidth)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final height", view.measuredHeight)
|
||||
}
|
||||
|
||||
return try {
|
||||
val btm = Bitmap.createBitmap(
|
||||
view.measuredWidth,
|
||||
view.measuredHeight,
|
||||
widgetWidth,
|
||||
widgetHeight,
|
||||
if (draw) Bitmap.Config.ARGB_8888 else Bitmap.Config.ALPHA_8
|
||||
)
|
||||
if (draw) {
|
||||
|
@ -4,14 +4,12 @@ import android.Manifest
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.provider.CalendarContract
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.services.EventListenerJob
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.AppMainFragment
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import me.everything.providers.android.calendar.CalendarProvider
|
||||
@ -128,7 +126,7 @@ object CalendarHelper {
|
||||
UpdatesReceiver.setUpdates(context)
|
||||
MainWidget.updateWidget(context)
|
||||
|
||||
EventBus.getDefault().post(AppMainFragment.UpdateUiMessageEvent())
|
||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||
}
|
||||
|
||||
fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> {
|
||||
|
@ -30,6 +30,29 @@ object ColorHelper {
|
||||
Color.parseColor("#000000")
|
||||
}
|
||||
}
|
||||
fun getClockFontColor(): Int {
|
||||
return try {
|
||||
Color.parseColor("#%s%s".format(Preferences.clockTextAlpha, Preferences.clockTextColor.replace("#", "")))
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#FFFFFFFF")
|
||||
}
|
||||
}
|
||||
|
||||
fun getClockFontColorAlpha(): Int {
|
||||
return try {
|
||||
Preferences.clockTextAlpha.toIntValue().toDouble() * 255 / 100
|
||||
} catch (e: Exception) {
|
||||
"FF".toIntValue().toDouble() * 255 / 100
|
||||
}.roundToInt()
|
||||
}
|
||||
|
||||
fun getClockFontColorRgb(): Int {
|
||||
return try {
|
||||
Color.parseColor(Preferences.clockTextColor)
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#000000")
|
||||
}
|
||||
}
|
||||
|
||||
fun getBackgroundColor(): Int {
|
||||
return try {
|
||||
|
@ -0,0 +1,84 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.content.Context
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.models.GlanceProvider
|
||||
import java.util.ArrayList
|
||||
|
||||
object GlanceProviderHelper {
|
||||
fun getGlanceProviders(): ArrayList<Constants.GlanceProviderId> {
|
||||
val enabledProviders = Preferences.enabledGlanceProviderOrder.split(",").filter { it != "" }
|
||||
val providers = Constants.GlanceProviderId.values()
|
||||
|
||||
providers.sortWith(Comparator { p1, p2 ->
|
||||
when {
|
||||
enabledProviders.contains(p1.id) && enabledProviders.contains(p2.id) -> {
|
||||
enabledProviders.indexOf(p1.id).compareTo(enabledProviders.indexOf(p2.id))
|
||||
}
|
||||
enabledProviders.contains(p1.id) -> {
|
||||
-1
|
||||
}
|
||||
enabledProviders.contains(p2.id) -> {
|
||||
1
|
||||
}
|
||||
else -> {
|
||||
p1.id.compareTo(p2.id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return ArrayList(providers.toList())
|
||||
}
|
||||
|
||||
fun getGlanceProviderById(context: Context, providerId: Constants.GlanceProviderId): GlanceProvider? {
|
||||
return when(providerId) {
|
||||
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||
GlanceProvider(providerId.id,
|
||||
context.getString(R.string.settings_show_next_alarm_title),
|
||||
R.drawable.round_alarm
|
||||
)
|
||||
}
|
||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||
GlanceProvider(providerId.id,
|
||||
context.getString(R.string.settings_show_music_title),
|
||||
R.drawable.round_music_note
|
||||
)
|
||||
}
|
||||
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
||||
GlanceProvider(providerId.id,
|
||||
context.getString(R.string.settings_custom_notes_title),
|
||||
R.drawable.round_notes
|
||||
)
|
||||
}
|
||||
// Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||
// GlanceProvider(providerId.id,
|
||||
// context.getString(R.string.settings_low_battery_level_title),
|
||||
// R.drawable.round_battery_charging_full
|
||||
// )
|
||||
// }
|
||||
// Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||
// GlanceProvider(providerId.id,
|
||||
// context.getString(R.string.settings_daily_steps_title),
|
||||
// R.drawable.round_directions_walk
|
||||
// )
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
fun saveGlanceProviderOrder(list: ArrayList<Constants.GlanceProviderId>) {
|
||||
Preferences.enabledGlanceProviderOrder = list.joinToString(separator = ",")
|
||||
}
|
||||
|
||||
fun showSpecialWeather(context: Context): Boolean {
|
||||
return EventRepository(context).getEventsCount() == 0 && (
|
||||
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
|
||||
(MediaPlayerHelper.isSomeonePlaying(context)) ||
|
||||
(Preferences.isBatteryLevelLow) ||
|
||||
(Preferences.customNotes.isNotEmpty()) ||
|
||||
(Preferences.googleFitSteps > 0)
|
||||
)
|
||||
}
|
||||
}
|
@ -160,4 +160,22 @@ object IntentHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getMusicIntent(context: Context): Intent {
|
||||
return when (Preferences.mediaPlayerPackage) {
|
||||
"" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.mediaPlayerPackage)!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Intent()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.app.Notification
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.media.MediaMetadata
|
||||
import android.media.session.MediaController
|
||||
import android.media.session.MediaSession
|
||||
import android.media.session.MediaSessionManager
|
||||
import android.media.session.PlaybackState
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.chibatching.kotpref.bulk
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.receivers.MusicNotificationListener
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import java.lang.Exception
|
||||
|
||||
object MediaPlayerHelper {
|
||||
fun isSomeonePlaying(context: Context) = Preferences.showMusic && NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) && Preferences.mediaPlayerTitle != ""
|
||||
|
||||
fun getMediaInfo(): String {
|
||||
return if (Preferences.mediaPlayerArtist == "") {
|
||||
Preferences.mediaPlayerTitle
|
||||
} else {
|
||||
"%s, %s".format(Preferences.mediaPlayerTitle, Preferences.mediaPlayerArtist)
|
||||
}
|
||||
}
|
||||
|
||||
fun updatePlayingMediaInfo(context: Context) {
|
||||
if (NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName)) {
|
||||
val list = try {
|
||||
(context.getSystemService(Context.MEDIA_SESSION_SERVICE) as MediaSessionManager).getActiveSessions(
|
||||
ComponentName(context.packageName, MusicNotificationListener::class.java.name)
|
||||
)
|
||||
} catch (ex: Exception) {
|
||||
emptyList<MediaController>()
|
||||
}
|
||||
|
||||
if (list.isNotEmpty()) {
|
||||
var isSomeonePlaying = false
|
||||
list.forEach { mc ->
|
||||
val metadata = mc.metadata
|
||||
val isPlaying =
|
||||
mc.playbackState?.state == PlaybackState.STATE_PLAYING || mc.playbackState?.state == PlaybackState.STATE_CONNECTING
|
||||
|
||||
if (isPlaying) {
|
||||
isSomeonePlaying = true
|
||||
if (metadata != null) {
|
||||
Preferences.bulk {
|
||||
mediaPlayerTitle =
|
||||
metadata.getText(MediaMetadata.METADATA_KEY_TITLE)?.toString()
|
||||
?: ""
|
||||
mediaPlayerArtist =
|
||||
metadata.getText(MediaMetadata.METADATA_KEY_ARTIST)?.toString()
|
||||
?: ""
|
||||
mediaPlayerAlbum =
|
||||
metadata.getText(MediaMetadata.METADATA_KEY_ALBUM)?.toString()
|
||||
?: ""
|
||||
}
|
||||
}
|
||||
|
||||
Preferences.mediaPlayerPackage = mc.packageName
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSomeonePlaying) {
|
||||
removeMediaInfo()
|
||||
}
|
||||
|
||||
} else {
|
||||
removeMediaInfo()
|
||||
}
|
||||
} else {
|
||||
removeMediaInfo()
|
||||
}
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
private fun removeMediaInfo() {
|
||||
Preferences.bulk {
|
||||
remove(Preferences::mediaPlayerTitle)
|
||||
remove(Preferences::mediaPlayerArtist)
|
||||
remove(Preferences::mediaPlayerAlbum)
|
||||
remove(Preferences::mediaPlayerPackage)
|
||||
}
|
||||
}
|
||||
}
|
@ -39,7 +39,6 @@ object SettingsStringHelper {
|
||||
return when (info) {
|
||||
0 -> R.string.settings_second_row_info_subtitle_0
|
||||
1 -> R.string.settings_second_row_info_subtitle_1
|
||||
2 -> R.string.settings_second_row_info_subtitle_2
|
||||
else -> R.string.settings_second_row_info_subtitle_0
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,12 @@ package com.tommasoberlose.anotherwidget.helpers
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.EventLog
|
||||
import android.util.Log
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import com.kwabenaberko.openweathermaplib.constants.Units
|
||||
import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper
|
||||
import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeatherCallback
|
||||
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.AppMainFragment
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
@ -39,7 +33,7 @@ object WeatherHelper {
|
||||
Preferences.customLocationLon = location.longitude.toString()
|
||||
|
||||
networkApi.updateWeather()
|
||||
EventBus.getDefault().post(AppMainFragment.UpdateUiMessageEvent())
|
||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
|
||||
object WidgetHelper {
|
||||
class WidgetSizeProvider(
|
||||
|
@ -0,0 +1,7 @@
|
||||
package com.tommasoberlose.anotherwidget.models
|
||||
|
||||
class GlanceProvider(
|
||||
val id: String,
|
||||
val title: String,
|
||||
val icon: Int
|
||||
)
|
@ -1,15 +1,13 @@
|
||||
package com.tommasoberlose.anotherwidget.network
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.kwabenaberko.openweathermaplib.constants.Units
|
||||
import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper
|
||||
import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeatherCallback
|
||||
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.AppMainFragment
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
@ -27,7 +25,7 @@ class WeatherNetworkApi(val context: Context) {
|
||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||
MainWidget.updateWidget(context)
|
||||
|
||||
EventBus.getDefault().post(AppMainFragment.UpdateUiMessageEvent())
|
||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
package com.tommasoberlose.anotherwidget.receivers
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.BatteryManager
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
|
||||
class BatteryLevelReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
when(intent.action) {
|
||||
Intent.ACTION_BATTERY_LOW -> Preferences.isBatteryLevelLow = true
|
||||
Intent.ACTION_BATTERY_OKAY -> Preferences.isBatteryLevelLow = false
|
||||
}
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.tommasoberlose.anotherwidget.receivers
|
||||
|
||||
import android.app.Notification
|
||||
import android.media.MediaMetadata
|
||||
import android.media.session.MediaController
|
||||
import android.media.session.MediaSession
|
||||
import android.media.session.PlaybackState
|
||||
import android.service.notification.NotificationListenerService
|
||||
import android.service.notification.StatusBarNotification
|
||||
import android.util.Log
|
||||
import com.chibatching.kotpref.bulk
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
|
||||
|
||||
class MusicNotificationListener : NotificationListenerService() {
|
||||
override fun onListenerConnected() {
|
||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
||||
super.onListenerConnected()
|
||||
}
|
||||
|
||||
override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
||||
sbn?.notification?.extras?.let { bundle ->
|
||||
bundle.getParcelable<MediaSession.Token>(Notification.EXTRA_MEDIA_SESSION)?.let {
|
||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
||||
}
|
||||
}
|
||||
super.onNotificationPosted(sbn)
|
||||
}
|
||||
|
||||
override fun onNotificationRemoved(sbn: StatusBarNotification?) {
|
||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
||||
super.onNotificationRemoved(sbn)
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ import androidx.core.content.ContextCompat.getSystemService
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import org.joda.time.Period
|
||||
import java.util.*
|
||||
@ -32,19 +33,34 @@ class UpdatesReceiver : BroadcastReceiver() {
|
||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
||||
Actions.ACTION_TIME_UPDATE -> {
|
||||
MainWidget.updateWidget(context)
|
||||
if (intent.hasExtra(EVENT_ID)) {
|
||||
setUpdates(context, intent.getLongExtra(EVENT_ID, -1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val EVENT_ID = "EVENT_ID"
|
||||
|
||||
fun setUpdates(context: Context) {
|
||||
fun setUpdates(context: Context, eventId: Long? = null) {
|
||||
val eventRepository = EventRepository(context)
|
||||
if (eventId == null) {
|
||||
removeUpdates(context)
|
||||
|
||||
|
||||
val eventRepository = EventRepository(context)
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
eventRepository.getEvents().forEach { event ->
|
||||
setEventUpdate(context, event)
|
||||
}
|
||||
} else {
|
||||
val event = eventRepository.getEventByEventId(eventId)
|
||||
if (event != null) {
|
||||
setEventUpdate(context, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setEventUpdate(context: Context, event: Event) {
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
val now = Calendar.getInstance().apply {
|
||||
set(Calendar.SECOND, 0)
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
@ -52,13 +68,29 @@ class UpdatesReceiver : BroadcastReceiver() {
|
||||
val diff = Period(now.timeInMillis, event.startDate)
|
||||
if (event.startDate > now.timeInMillis) {
|
||||
// Update the widget every hour till the event
|
||||
(0..diff.hours).forEach {
|
||||
setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC,
|
||||
if (event.startDate - it * 1000 * 60 * 60 > 60 * 1000) event.startDate - it * 1000 * 60 * 60 else now.timeInMillis + 120000,
|
||||
if (event.startDate - diff.hours * 1000 * 60 * 60 > (now.timeInMillis + 120 * 1000)) event.startDate - diff.hours * 1000 * 60 * 60 else now.timeInMillis + 120000,
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
event.eventID.toInt() + it,
|
||||
event.eventID.toInt(),
|
||||
Intent(context, UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_TIME_UPDATE
|
||||
putExtra(EVENT_ID, event.eventID)
|
||||
},
|
||||
0
|
||||
)
|
||||
)
|
||||
} else {
|
||||
// Update the widget one second after the event is finished
|
||||
val fireTime =
|
||||
if (event.endDate > now.timeInMillis + 120 * 1000) event.endDate else now.timeInMillis + 120000
|
||||
setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC,
|
||||
fireTime,
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
event.eventID.toInt(),
|
||||
Intent(context, UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_TIME_UPDATE
|
||||
},
|
||||
@ -67,24 +99,12 @@ class UpdatesReceiver : BroadcastReceiver() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the widget one second after the event is finished
|
||||
setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC,
|
||||
if (event.endDate > 60 *1000) event.endDate else now.timeInMillis + 120000,
|
||||
PendingIntent.getBroadcast(context, 1, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeUpdates(context: Context) {
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
cancel(PendingIntent.getBroadcast(context, 1, Intent(context, UpdatesReceiver::class.java), 0))
|
||||
EventRepository(context).getEvents().forEach {
|
||||
(0..24).forEach { hour ->
|
||||
cancel(PendingIntent.getBroadcast(context, it.eventID.toInt() * hour, Intent(context, UpdatesReceiver::class.java), 0))
|
||||
}
|
||||
cancel(PendingIntent.getBroadcast(context, it.eventID.toInt(), Intent(context, UpdatesReceiver::class.java), 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.databinding.ActivityIntegrationsBinding
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.IntegrationsViewModel
|
||||
import kotlinx.android.synthetic.main.activity_integrations.*
|
||||
import net.idik.lib.slimadapter.SlimAdapter
|
||||
|
||||
class IntegrationsActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var adapter: SlimAdapter
|
||||
private lateinit var viewModel: IntegrationsViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
viewModel = ViewModelProvider(this).get(IntegrationsViewModel::class.java)
|
||||
val binding = DataBindingUtil.setContentView<ActivityIntegrationsBinding>(this, R.layout.activity_integrations)
|
||||
|
||||
list_view.setHasFixedSize(true)
|
||||
val mLayoutManager = LinearLayoutManager(this)
|
||||
list_view.layoutManager = mLayoutManager
|
||||
|
||||
adapter = SlimAdapter.create()
|
||||
adapter
|
||||
.register<String>(R.layout.application_info_layout) { _, injector ->
|
||||
injector
|
||||
.text(R.id.text, getString(R.string.default_name))
|
||||
|
||||
}
|
||||
.attachTo(list_view)
|
||||
|
||||
setupListener()
|
||||
subscribeUi(binding, viewModel)
|
||||
}
|
||||
|
||||
private fun subscribeUi(binding: ActivityIntegrationsBinding, viewModel: IntegrationsViewModel) {
|
||||
binding.viewModel = viewModel
|
||||
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
action_back.setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
@ -8,14 +8,15 @@ import com.tommasoberlose.anotherwidget.ui.fragments.*
|
||||
class ViewPagerAdapter(fragmentActivity: FragmentActivity) :
|
||||
FragmentStateAdapter(fragmentActivity) {
|
||||
|
||||
override fun getItemCount(): Int = 4
|
||||
override fun getItemCount(): Int = 5
|
||||
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
return when (position) {
|
||||
1 -> CalendarSettingsFragment.newInstance()
|
||||
2 -> WeatherSettingsFragment.newInstance()
|
||||
3 -> ClockSettingsFragment.newInstance()
|
||||
else -> GeneralSettingsFragment.newInstance()
|
||||
1 -> CalendarTabFragment.newInstance()
|
||||
2 -> WeatherTabFragment.newInstance()
|
||||
3 -> ClockTabFragment.newInstance()
|
||||
4 -> GlanceTabFragment.newInstance()
|
||||
else -> GeneralTabFragment.newInstance()
|
||||
}
|
||||
}
|
||||
}
|
@ -4,10 +4,10 @@ import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
@ -43,10 +43,10 @@ import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import kotlin.Comparator
|
||||
|
||||
class CalendarSettingsFragment : Fragment() {
|
||||
class CalendarTabFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = CalendarSettingsFragment()
|
||||
fun newInstance() = CalendarTabFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
@ -129,7 +129,10 @@ class CalendarSettingsFragment : Fragment() {
|
||||
})
|
||||
|
||||
viewModel.showNextEvent.observe(viewLifecycleOwner, Observer {
|
||||
show_multiple_events_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
maintainScrollPosition {
|
||||
show_multiple_events_label?.text =
|
||||
if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.dateFormat.observe(viewLifecycleOwner, Observer {
|
||||
@ -161,6 +164,13 @@ class CalendarSettingsFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
show_events_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||
Preferences.showEvents = enabled
|
||||
if (Preferences.showEvents) {
|
||||
requirePermission()
|
||||
}
|
||||
}
|
||||
|
||||
action_filter_calendar.setOnClickListener {
|
||||
val calendarSelectorList: List<CalendarSelector> = CalendarHelper.getCalendarList(requireContext()).map {
|
||||
CalendarSelector(
|
||||
@ -271,7 +281,7 @@ class CalendarSettingsFragment : Fragment() {
|
||||
action_show_until.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_show_until_title)).setSelectedValue(Preferences.showUntil)
|
||||
intArrayOf(6,7,0,1,2,3,4,5).forEach {
|
||||
intArrayOf(6,7,0,1,2,3).forEach {
|
||||
dialog.addItem(getString(SettingsStringHelper.getShowUntilString(it)), it)
|
||||
}
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
@ -340,6 +350,8 @@ class CalendarSettingsFragment : Fragment() {
|
||||
report?.let {
|
||||
if (report.areAllPermissionsGranted()){
|
||||
checkReadEventsPermission()
|
||||
} else {
|
||||
Preferences.showEvents = false
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
@ -20,29 +19,35 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.chibatching.kotpref.bulk
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentClockSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.toast
|
||||
import kotlinx.android.synthetic.main.fragment_clock_settings.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.lang.Exception
|
||||
|
||||
|
||||
class ClockSettingsFragment : Fragment() {
|
||||
class ClockTabFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = ClockSettingsFragment()
|
||||
fun newInstance() = ClockTabFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
private lateinit var colors: IntArray
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -67,8 +72,13 @@ class ClockSettingsFragment : Fragment() {
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val lazyColors = requireContext().resources.getIntArray(R.array.material_colors)
|
||||
withContext(Dispatchers.Main) {
|
||||
colors = lazyColors
|
||||
}
|
||||
}
|
||||
setupListener()
|
||||
updateNextAlarmWarningUi()
|
||||
}
|
||||
|
||||
private fun subscribeUi(
|
||||
@ -94,6 +104,34 @@ class ClockSettingsFragment : Fragment() {
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showAMPMIndicator.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
ampm_indicator_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.clockTextColor.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.clockTextAlpha == "00") {
|
||||
clock_text_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
clock_text_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor())).toUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.clockTextAlpha.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.clockTextAlpha == "00") {
|
||||
clock_text_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
clock_text_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor())).toUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.clockBottomMargin.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
clock_bottom_margin_label?.text = when (it) {
|
||||
@ -105,10 +143,6 @@ class ClockSettingsFragment : Fragment() {
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showNextAlarm.observe(viewLifecycleOwner, Observer {
|
||||
updateNextAlarmWarningUi()
|
||||
})
|
||||
|
||||
viewModel.clockAppName.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
clock_app_label?.text =
|
||||
@ -126,6 +160,10 @@ class ClockSettingsFragment : Fragment() {
|
||||
Preferences.showClock = !Preferences.showClock
|
||||
}
|
||||
|
||||
show_clock_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||
Preferences.showClock = enabled
|
||||
}
|
||||
|
||||
action_clock_text_size.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.settings_clock_text_size_title)).setSelectedValue(Preferences.clockTextSize)
|
||||
(46 downTo 12).filter { it % 2 == 0 }.forEach {
|
||||
@ -136,8 +174,34 @@ class ClockSettingsFragment : Fragment() {
|
||||
}.show()
|
||||
}
|
||||
|
||||
action_ampm_indicator_size.setOnClickListener {
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_ampm_indicator_title)).setSelectedValue(Preferences.showAMPMIndicator)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.showAMPMIndicator = value
|
||||
}.show()
|
||||
}
|
||||
|
||||
action_clock_text_color.setOnClickListener {
|
||||
BottomSheetColorPicker(requireContext(),
|
||||
colors = colors,
|
||||
header = getString(R.string.settings_font_color_title),
|
||||
getSelected = ColorHelper::getClockFontColorRgb,
|
||||
onColorSelected = { color: Int ->
|
||||
val colorString = Integer.toHexString(color)
|
||||
Preferences.clockTextColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||
},
|
||||
showAlphaSelector = true,
|
||||
alpha = Preferences.clockTextAlpha.toIntValue(),
|
||||
onAlphaChangeListener = { alpha ->
|
||||
Preferences.clockTextAlpha = alpha.toHexValue()
|
||||
}
|
||||
).show()
|
||||
}
|
||||
|
||||
action_clock_bottom_margin_size.setOnClickListener {
|
||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.clockBottomMargin)
|
||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_clock_bottom_margin_title)).setSelectedValue(Preferences.clockBottomMargin)
|
||||
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_none), Constants.ClockBottomMargin.NONE.value)
|
||||
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_small), Constants.ClockBottomMargin.SMALL.value)
|
||||
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_medium), Constants.ClockBottomMargin.MEDIUM.value)
|
||||
@ -154,50 +218,6 @@ class ClockSettingsFragment : Fragment() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
action_show_next_alarm.setOnClickListener {
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.showNextAlarm)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.showNextAlarm = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateNextAlarmWarningUi() {
|
||||
with(requireContext().getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
val alarm = nextAlarmClock
|
||||
if (AlarmHelper.isAlarmProbablyWrong(requireContext()) && alarm != null && alarm.showIntent != null) {
|
||||
val pm = requireContext().packageManager as PackageManager
|
||||
val appNameOrPackage = try {
|
||||
pm.getApplicationLabel(pm.getApplicationInfo(alarm.showIntent?.creatorPackage ?: "", 0))
|
||||
} catch (e: Exception) {
|
||||
alarm.showIntent?.creatorPackage ?: ""
|
||||
}
|
||||
show_next_alarm_warning.text = getString(R.string.next_alarm_warning).format(appNameOrPackage)
|
||||
} else {
|
||||
maintainScrollPosition {
|
||||
show_next_alarm_label?.text = if (Preferences.showNextAlarm) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val nextAlarmChangeBroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
updateNextAlarmWarningUi()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity?.registerReceiver(nextAlarmChangeBroadcastReceiver, IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED))
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
activity?.unregisterReceiver(nextAlarmChangeBroadcastReceiver)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
@ -3,9 +3,7 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -33,10 +31,10 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
||||
class GeneralSettingsFragment : Fragment() {
|
||||
class GeneralTabFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = GeneralSettingsFragment()
|
||||
fun newInstance() = GeneralTabFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
@ -148,6 +146,13 @@ class GeneralSettingsFragment : Fragment() {
|
||||
custom_font_label?.text = getString(SettingsStringHelper.getCustomFontLabel(it))
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showDividers.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_dividers_label?.text =
|
||||
if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun maintainScrollPosition(callback: () -> Unit) {
|
||||
@ -245,6 +250,15 @@ class GeneralSettingsFragment : Fragment() {
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
action_show_dividers.setOnClickListener {
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_multiple_events_title)).setSelectedValue(Preferences.showDividers)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.showDividers = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
@ -0,0 +1,249 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.components.CustomNotesDialog
|
||||
import com.tommasoberlose.anotherwidget.components.GlanceProviderSortMenu
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentGlanceSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.GlanceProviderHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||
import com.tommasoberlose.anotherwidget.models.GlanceProvider
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import kotlinx.android.synthetic.main.fragment_glance_settings.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import net.idik.lib.slimadapter.SlimAdapter
|
||||
import java.util.*
|
||||
|
||||
|
||||
class GlanceTabFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = GlanceTabFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
|
||||
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||
val binding = DataBindingUtil.inflate<FragmentGlanceSettingsBinding>(inflater, R.layout.fragment_glance_settings, container, false)
|
||||
|
||||
subscribeUi(binding, viewModel)
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.viewModel = viewModel
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
setupListener()
|
||||
updateNextAlarmWarningUi()
|
||||
}
|
||||
|
||||
private fun subscribeUi(
|
||||
binding: FragmentGlanceSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
|
||||
viewModel.showGlance.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
binding.isGlanceVisible = it
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showMusic.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
checkNotificationPermission()
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showNextAlarm.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
updateNextAlarmWarningUi()
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showBatteryCharging.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_low_battery_level_warning_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.customInfo.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_custom_notes_label?.text = if (it == "") getString(R.string.settings_not_visible) else it
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
|
||||
action_show_glance.setOnClickListener {
|
||||
Preferences.showGlance = !Preferences.showGlance
|
||||
}
|
||||
|
||||
show_glance_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||
Preferences.showGlance = enabled
|
||||
}
|
||||
|
||||
action_sort_glance_providers.setOnClickListener {
|
||||
GlanceProviderSortMenu(requireContext())
|
||||
.show()
|
||||
}
|
||||
|
||||
action_show_music.setOnClickListener {
|
||||
if (Preferences.showGlance) {
|
||||
BottomSheetMenu<Boolean>(
|
||||
requireContext(),
|
||||
header = getString(R.string.settings_show_music_title)
|
||||
).setSelectedValue(Preferences.showMusic)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.showMusic = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_show_next_alarm.setOnClickListener {
|
||||
if (Preferences.showGlance) {
|
||||
BottomSheetMenu<Boolean>(
|
||||
requireContext(),
|
||||
header = getString(R.string.settings_show_next_alarm_title)
|
||||
).setSelectedValue(Preferences.showNextAlarm)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.showNextAlarm = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_show_low_battery_level_warning.setOnClickListener {
|
||||
if (Preferences.showGlance) {
|
||||
BottomSheetMenu<Boolean>(
|
||||
requireContext(),
|
||||
header = getString(R.string.settings_low_battery_level_title)
|
||||
).setSelectedValue(Preferences.showBatteryCharging)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.showBatteryCharging = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_show_custom_notes.setOnClickListener {
|
||||
if (Preferences.showGlance) {
|
||||
CustomNotesDialog(requireContext()).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateNextAlarmWarningUi() {
|
||||
with(requireContext().getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
val alarm = nextAlarmClock
|
||||
if (AlarmHelper.isAlarmProbablyWrong(requireContext()) && alarm != null && alarm.showIntent != null) {
|
||||
val pm = requireContext().packageManager as PackageManager
|
||||
val appNameOrPackage = try {
|
||||
pm.getApplicationLabel(pm.getApplicationInfo(alarm.showIntent?.creatorPackage ?: "", 0))
|
||||
} catch (e: Exception) {
|
||||
alarm.showIntent?.creatorPackage ?: ""
|
||||
}
|
||||
show_next_alarm_warning.text =
|
||||
getString(R.string.next_alarm_warning).format(appNameOrPackage)
|
||||
} else {
|
||||
show_next_alarm_label?.text = if (Preferences.showNextAlarm) getString(R.string.settings_visible) else getString(
|
||||
R.string.settings_not_visible)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val nextAlarmChangeBroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
updateNextAlarmWarningUi()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity?.registerReceiver(nextAlarmChangeBroadcastReceiver, IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED))
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
activity?.unregisterReceiver(nextAlarmChangeBroadcastReceiver)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
private fun checkNotificationPermission() {
|
||||
if (NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)) {
|
||||
notification_permission_alert?.isVisible = false
|
||||
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
||||
show_music_label?.text = if (Preferences.showMusic) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
} else if (Preferences.showMusic) {
|
||||
notification_permission_alert?.isVisible = true
|
||||
show_music_label?.text = getString(R.string.settings_request_notification_access)
|
||||
notification_permission_alert?.setOnClickListener {
|
||||
activity?.startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
|
||||
}
|
||||
} else {
|
||||
show_music_label?.text = getString(R.string.settings_show_music_disabled_subtitle)
|
||||
notification_permission_alert?.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun maintainScrollPosition(callback: () -> Unit) {
|
||||
val scrollPosition = scrollView.scrollY
|
||||
callback.invoke()
|
||||
lifecycleScope.launch {
|
||||
delay(200)
|
||||
scrollView.smoothScrollTo(0, scrollPosition)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
checkNotificationPermission()
|
||||
}
|
||||
}
|
@ -9,28 +9,26 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.navigation.fragment.FragmentNavigator
|
||||
import com.google.android.material.badge.BadgeDrawable
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentAdvancedSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentAppMainBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.BitmapHelper
|
||||
@ -50,10 +48,11 @@ import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = AppMainFragment()
|
||||
fun newInstance() = MainFragment()
|
||||
private const val PREVIEW_BASE_HEIGHT = 120
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
@ -86,19 +85,20 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
1 -> getString(R.string.settings_calendar_title)
|
||||
2 -> getString(R.string.settings_weather_title)
|
||||
3 -> getString(R.string.settings_clock_title)
|
||||
4 -> getString(R.string.settings_at_a_glance_title)
|
||||
else -> ""
|
||||
}
|
||||
}.attach()
|
||||
|
||||
// Init clock
|
||||
time.setTextColor(ColorHelper.getFontColor())
|
||||
time.setTextColor(ColorHelper.getClockFontColor())
|
||||
time.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext()))
|
||||
time_am_pm.setTextColor(ColorHelper.getFontColor())
|
||||
time_am_pm.setTextColor(ColorHelper.getClockFontColor())
|
||||
time_am_pm.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2)
|
||||
time_container.isVisible = Preferences.showClock
|
||||
|
||||
preview.layoutParams = preview.layoutParams.apply {
|
||||
height = 160.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(requireContext()) else 0
|
||||
height = PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(requireContext()) else 0
|
||||
}
|
||||
subscribeUi(viewModel)
|
||||
updateUI()
|
||||
@ -136,7 +136,6 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
)
|
||||
widget_shape_background.setImageDrawable(BitmapHelper.getTintedDrawable(requireContext(), R.drawable.card_background, ColorHelper.getBackgroundColor()))
|
||||
uiJob = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||
delay(200)
|
||||
val generatedView = MainWidget.generateWidgetView(requireContext())
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
@ -151,8 +150,8 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
// Clock
|
||||
time.setTextColor(ColorHelper.getFontColor())
|
||||
time_am_pm.setTextColor(ColorHelper.getFontColor())
|
||||
time.setTextColor(ColorHelper.getClockFontColor())
|
||||
time_am_pm.setTextColor(ColorHelper.getClockFontColor())
|
||||
time.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext())
|
||||
@ -161,6 +160,7 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
|
||||
)
|
||||
time_am_pm.isVisible = Preferences.showAMPMIndicator
|
||||
|
||||
// Clock bottom margin
|
||||
clock_bottom_margin_none.isVisible =
|
||||
@ -207,7 +207,7 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
160.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
requireContext()
|
||||
) else 0
|
||||
).apply {
|
||||
@ -229,7 +229,7 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
if (preview.height == 0) {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
160.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
requireContext()
|
||||
) else 0
|
||||
).apply {
|
||||
@ -243,8 +243,8 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
}.start()
|
||||
}
|
||||
|
||||
widget_loader.animate().scaleX(0f).scaleY(0f).alpha(0f).setDuration(200L).start()
|
||||
bitmap_container.setImageBitmap(bitmap)
|
||||
widget_loader.animate().scaleX(0f).scaleY(0f).start()
|
||||
widget.animate().alpha(1f).start()
|
||||
}
|
||||
}
|
||||
@ -263,18 +263,7 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
}.start()
|
||||
}
|
||||
|
||||
|
||||
// Calendar error indicator
|
||||
tabs?.getTabAt(1)?.orCreateBadge?.apply {
|
||||
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||
badgeGravity = BadgeDrawable.TOP_END
|
||||
}?.isVisible = Preferences.showEvents && activity?.checkGrantedPermission(Manifest.permission.READ_CALENDAR) != true
|
||||
|
||||
// Weather error indicator
|
||||
tabs?.getTabAt(2)?.orCreateBadge?.apply {
|
||||
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||
badgeGravity = BadgeDrawable.TOP_END
|
||||
}?.isVisible = Preferences.showWeather && (Preferences.weatherProviderApi == "" || (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) != true))
|
||||
showErrorBadge()
|
||||
|
||||
}
|
||||
|
||||
@ -303,8 +292,25 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
private fun showErrorBadge() {
|
||||
// Calendar error indicator
|
||||
tabs?.getTabAt(1)?.orCreateBadge?.apply {
|
||||
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||
badgeGravity = BadgeDrawable.TOP_END
|
||||
}?.isVisible = Preferences.showEvents && activity?.checkGrantedPermission(Manifest.permission.READ_CALENDAR) != true
|
||||
|
||||
// Weather error indicator
|
||||
tabs?.getTabAt(2)?.orCreateBadge?.apply {
|
||||
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||
badgeGravity = BadgeDrawable.TOP_END
|
||||
}?.isVisible = Preferences.showWeather && (Preferences.weatherProviderApi == "" || (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) != true))
|
||||
|
||||
|
||||
// Music error indicator
|
||||
tabs?.getTabAt(4)?.orCreateBadge?.apply {
|
||||
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||
badgeGravity = BadgeDrawable.TOP_END
|
||||
}?.isVisible = Preferences.showMusic && !NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
||||
@ -316,6 +322,8 @@ class AppMainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeL
|
||||
super.onResume()
|
||||
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
|
||||
EventBus.getDefault().register(this)
|
||||
showErrorBadge()
|
||||
updateUI()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
@ -14,7 +14,6 @@ import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.Navigation
|
||||
import com.google.android.material.transition.MaterialContainerTransform
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.karumi.dexter.Dexter
|
||||
import com.karumi.dexter.MultiplePermissionsReport
|
||||
@ -24,16 +23,18 @@ import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
||||
import com.tommasoberlose.anotherwidget.BuildConfig
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentAdvancedSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.SupportDevActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.IntegrationsActivity
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||
import kotlinx.android.synthetic.main.fragment_advanced_settings.*
|
||||
import kotlinx.android.synthetic.main.fragment_settings.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@ -58,7 +59,7 @@ class SettingsFragment : Fragment() {
|
||||
): View {
|
||||
|
||||
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||
val binding = DataBindingUtil.inflate<FragmentAdvancedSettingsBinding>(inflater, R.layout.fragment_advanced_settings, container, false)
|
||||
val binding = DataBindingUtil.inflate<FragmentSettingsBinding>(inflater, R.layout.fragment_settings, container, false)
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.viewModel = viewModel
|
||||
@ -96,6 +97,10 @@ class SettingsFragment : Fragment() {
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.installedIntegrations.observe(viewLifecycleOwner, Observer {
|
||||
integrations_count_label?.text = getString(R.string.label_count_installed_integrations).format(it)
|
||||
})
|
||||
|
||||
viewModel.showPreview.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_widget_preview_label?.text =
|
||||
@ -114,27 +119,6 @@ class SettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
action_change_theme.setOnClickListener {
|
||||
maintainScrollPosition {
|
||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_theme_title))
|
||||
.setSelectedValue(Preferences.darkThemePreference)
|
||||
.addItem(
|
||||
getString(R.string.settings_subtitle_dark_theme_light),
|
||||
AppCompatDelegate.MODE_NIGHT_NO
|
||||
)
|
||||
.addItem(
|
||||
getString(R.string.settings_subtitle_dark_theme_dark),
|
||||
AppCompatDelegate.MODE_NIGHT_YES
|
||||
)
|
||||
.addItem(
|
||||
getString(R.string.settings_subtitle_dark_theme_default),
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
|
||||
)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.darkThemePreference = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_show_widget_preview.setOnClickListener {
|
||||
maintainScrollPosition {
|
||||
@ -176,6 +160,32 @@ class SettingsFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
action_integrations.setOnClickListener {
|
||||
startActivity(Intent(requireContext(), IntegrationsActivity::class.java))
|
||||
}
|
||||
|
||||
action_change_theme.setOnClickListener {
|
||||
maintainScrollPosition {
|
||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_theme_title))
|
||||
.setSelectedValue(Preferences.darkThemePreference)
|
||||
.addItem(
|
||||
getString(R.string.settings_subtitle_dark_theme_light),
|
||||
AppCompatDelegate.MODE_NIGHT_NO
|
||||
)
|
||||
.addItem(
|
||||
getString(R.string.settings_subtitle_dark_theme_dark),
|
||||
AppCompatDelegate.MODE_NIGHT_YES
|
||||
)
|
||||
.addItem(
|
||||
getString(R.string.settings_subtitle_dark_theme_default),
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
|
||||
)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.darkThemePreference = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_translate.setOnClickListener {
|
||||
activity?.openURI("https://github.com/tommasoberlose/another-widget/blob/master/app/src/main/res/values/strings.xml")
|
||||
}
|
||||
@ -195,6 +205,7 @@ class SettingsFragment : Fragment() {
|
||||
action_refresh_widget.setOnClickListener {
|
||||
WeatherHelper.updateWeather(requireContext())
|
||||
CalendarHelper.updateEventList(requireContext())
|
||||
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,10 +41,10 @@ import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class WeatherSettingsFragment : Fragment() {
|
||||
class WeatherTabFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = WeatherSettingsFragment()
|
||||
fun newInstance() = WeatherTabFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
@ -168,6 +168,10 @@ class WeatherSettingsFragment : Fragment() {
|
||||
Preferences.showWeather = !Preferences.showWeather
|
||||
}
|
||||
|
||||
show_weather_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||
Preferences.showWeather = enabled
|
||||
}
|
||||
|
||||
action_weather_provider_api_key.setOnClickListener {
|
||||
if (Preferences.showWeather) {
|
||||
startActivityForResult(
|
@ -0,0 +1,7 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
|
||||
class IntegrationsViewModel(application: Application) : AndroidViewModel(application) {
|
||||
}
|
@ -16,6 +16,7 @@ class MainViewModel : ViewModel() {
|
||||
val textShadow = Preferences.asLiveData(Preferences::textShadow)
|
||||
val customFont = Preferences.asLiveData(Preferences::customFont)
|
||||
val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation)
|
||||
val showDividers = Preferences.asLiveData(Preferences::showDividers)
|
||||
|
||||
// Calendar Settings
|
||||
val showEvents = Preferences.asLiveData(Preferences::showEvents)
|
||||
@ -27,13 +28,14 @@ class MainViewModel : ViewModel() {
|
||||
val openEventDetails = Preferences.asLiveData(Preferences::openEventDetails)
|
||||
val calendarAppName = Preferences.asLiveData(Preferences::calendarAppName)
|
||||
|
||||
|
||||
// Clock Settings
|
||||
val showClock = Preferences.asLiveData(Preferences::showClock)
|
||||
val clockTextSize = Preferences.asLiveData(Preferences::clockTextSize)
|
||||
val clockTextColor = Preferences.asLiveData(Preferences::clockTextColor)
|
||||
val clockTextAlpha = Preferences.asLiveData(Preferences::clockTextAlpha)
|
||||
val showAMPMIndicator = Preferences.asLiveData(Preferences::showAMPMIndicator)
|
||||
|
||||
val clockAppName = Preferences.asLiveData(Preferences::clockAppName)
|
||||
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
|
||||
val dateFormat = Preferences.asLiveData(Preferences::dateFormat)
|
||||
val clockBottomMargin = Preferences.asLiveData(Preferences::clockBottomMargin)
|
||||
|
||||
@ -51,8 +53,16 @@ class MainViewModel : ViewModel() {
|
||||
|
||||
val showWeatherWarning = Preferences.asLiveData(Preferences::showWeatherWarning)
|
||||
|
||||
// Glance
|
||||
val showGlance = Preferences.asLiveData(Preferences::showGlance)
|
||||
val showMusic = Preferences.asLiveData(Preferences::showMusic)
|
||||
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
|
||||
val showBatteryCharging = Preferences.asLiveData(Preferences::showBatteryCharging)
|
||||
val customInfo = Preferences.asLiveData(Preferences::customNotes)
|
||||
|
||||
// Advanced Settings
|
||||
val darkThemePreference = Preferences.asLiveData(Preferences::darkThemePreference)
|
||||
val showWallpaper = Preferences.asLiveData(Preferences::showWallpaper)
|
||||
val showPreview = Preferences.asLiveData(Preferences::showPreview)
|
||||
val installedIntegrations = Preferences.asLiveData(Preferences::installedIntegrations)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.text.format.DateUtils
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
@ -19,14 +20,12 @@ import android.widget.RemoteViews
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.*
|
||||
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper.reduceDimensionWithMaxWidth
|
||||
import com.tommasoberlose.anotherwidget.receivers.*
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
||||
@ -54,6 +53,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
override fun onEnabled(context: Context) {
|
||||
CalendarHelper.updateEventList(context)
|
||||
WeatherReceiver.setUpdates(context)
|
||||
MediaPlayerHelper.updatePlayingMediaInfo(context)
|
||||
|
||||
if (Preferences.showEvents) {
|
||||
CalendarHelper.setEventUpdatesAndroidN(context)
|
||||
@ -149,6 +149,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.second_row_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
|
||||
|
||||
val calPIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
@ -260,14 +261,62 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||
} else if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||
val clockIntent = PendingIntent.getActivity(
|
||||
} else if (Preferences.showGlance) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders()) {
|
||||
when (provider) {
|
||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
||||
val musicIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
widgetID,
|
||||
IntentHelper.getMusicIntent(context),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, musicIntent)
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||
if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||
val alarmIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
widgetID,
|
||||
IntentHelper.getClockIntent(context),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, clockIntent)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, alarmIntent)
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
// Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||
// if (Preferences.isBatteryLevelLow) {
|
||||
// val alarmIntent = PendingIntent.getActivity(
|
||||
// context,
|
||||
// widgetID,
|
||||
// IntentHelper.getClockIntent(context),
|
||||
// 0
|
||||
// )
|
||||
// views.setOnClickPendingIntent(R.id.second_row_rect, alarmIntent)
|
||||
// break@loop
|
||||
// }
|
||||
// }
|
||||
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
||||
if (Preferences.customNotes.isNotEmpty()) {
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
// Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||
// if (Preferences.googleFitSteps > 0) {
|
||||
// break@loop
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
views.setImageViewBitmap(
|
||||
R.id.next_event_rect,
|
||||
@ -278,10 +327,11 @@ class MainWidget : AppWidgetProvider() {
|
||||
R.id.second_row_rect,
|
||||
BitmapHelper.getBitmapFromView(v.second_row, draw = false)
|
||||
)
|
||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||
|
||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||
views.setOnClickPendingIntent(R.id.next_event_rect, calPIntent)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
@ -296,6 +346,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
||||
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.calendar_weather_rect, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.special_weather_rect, View.VISIBLE)
|
||||
|
||||
val i = Intent(context, WidgetClickListenerReceiver::class.java)
|
||||
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
|
||||
@ -303,6 +354,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
|
||||
views.setOnClickPendingIntent(R.id.calendar_weather_rect, weatherPIntent)
|
||||
views.setOnClickPendingIntent(R.id.special_weather_rect, weatherPIntent)
|
||||
|
||||
views.setImageViewBitmap(
|
||||
R.id.weather_rect,
|
||||
@ -313,9 +365,21 @@ class MainWidget : AppWidgetProvider() {
|
||||
R.id.calendar_weather_rect,
|
||||
BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false)
|
||||
)
|
||||
|
||||
views.setImageViewBitmap(
|
||||
R.id.special_weather_rect,
|
||||
BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false)
|
||||
)
|
||||
|
||||
if (GlanceProviderHelper.showSpecialWeather(context)) {
|
||||
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
|
||||
} else {
|
||||
views.setViewVisibility(R.id.special_weather_rect, View.GONE)
|
||||
}
|
||||
} else {
|
||||
views.setViewVisibility(R.id.weather_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.special_weather_rect, View.GONE)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
@ -334,8 +398,8 @@ class MainWidget : AppWidgetProvider() {
|
||||
views.setViewVisibility(R.id.clock_bottom_margin_medium, View.GONE)
|
||||
views.setViewVisibility(R.id.clock_bottom_margin_large, View.GONE)
|
||||
} else {
|
||||
views.setTextColor(R.id.time, ColorHelper.getFontColor())
|
||||
views.setTextColor(R.id.time_am_pm, ColorHelper.getFontColor())
|
||||
views.setTextColor(R.id.time, ColorHelper.getClockFontColor())
|
||||
views.setTextColor(R.id.time_am_pm, ColorHelper.getClockFontColor())
|
||||
views.setTextViewTextSize(
|
||||
R.id.time,
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
@ -355,7 +419,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
views.setOnClickPendingIntent(R.id.time, clockPIntent)
|
||||
views.setOnClickPendingIntent(R.id.time_am_pm, clockPIntent)
|
||||
views.setViewVisibility(R.id.time, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.time_am_pm, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.time_am_pm, if (Preferences.showAMPMIndicator) View.VISIBLE else View.GONE)
|
||||
|
||||
views.setViewVisibility(
|
||||
R.id.clock_bottom_margin_none,
|
||||
@ -392,6 +456,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
v.empty_layout.visibility = View.VISIBLE
|
||||
v.calendar_layout.visibility = View.GONE
|
||||
v.next_event_difference_time.visibility = View.GONE
|
||||
v.action_next.isVisible = false
|
||||
v.action_previous.isVisible = false
|
||||
|
||||
@ -459,22 +524,76 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
v.empty_layout.visibility = View.GONE
|
||||
v.calendar_layout.visibility = View.VISIBLE
|
||||
} else if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||
} else if (Preferences.showGlance) {
|
||||
v.second_row_icon.isVisible = true
|
||||
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders()) {
|
||||
when (provider) {
|
||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
||||
v.second_row_icon.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.round_music_note
|
||||
)
|
||||
)
|
||||
v.next_event_date.text = MediaPlayerHelper.getMediaInfo()
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||
if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||
v.second_row_icon.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.round_alarm
|
||||
)
|
||||
)
|
||||
v.next_event.text = DateHelper.getDateText(context, now)
|
||||
v.next_event_date.text = AlarmHelper.getNextAlarm(context)
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
// Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||
// if (Preferences.isBatteryLevelLow) {
|
||||
// v.second_row_icon.setImageDrawable(
|
||||
// ContextCompat.getDrawable(
|
||||
// context,
|
||||
// R.drawable.round_battery_charging_full
|
||||
// )
|
||||
// )
|
||||
// v.next_event_date.text = context.getString(R.string.battery_low_warning)
|
||||
// break@loop
|
||||
// }
|
||||
// }
|
||||
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
||||
if (Preferences.customNotes.isNotEmpty()) {
|
||||
v.second_row_icon.isVisible = false
|
||||
v.next_event_date.text = Preferences.customNotes
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
// Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||
// if (Preferences.googleFitSteps > 0) {
|
||||
// v.second_row_icon.setImageDrawable(
|
||||
// ContextCompat.getDrawable(
|
||||
// context,
|
||||
// R.drawable.round_directions_walk
|
||||
// )
|
||||
// )
|
||||
// v.next_event_date.text = ""
|
||||
// break@loop
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
v.next_event.text = DateHelper.getDateText(context, now)
|
||||
v.empty_layout.visibility = View.GONE
|
||||
v.calendar_layout.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
|
||||
// Color
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp).forEach {
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp, v.divider3, v.special_temp).forEach {
|
||||
it.setTextColor(ColorHelper.getFontColor())
|
||||
}
|
||||
|
||||
@ -485,13 +604,15 @@ class MainWidget : AppWidgetProvider() {
|
||||
// Text Size
|
||||
listOf<Pair<TextView, Float>>(
|
||||
v.empty_date to Preferences.textMainSize,
|
||||
v.divider1 to Preferences.textMainSize,
|
||||
v.divider1 to (Preferences.textMainSize - 2),
|
||||
v.temp to Preferences.textMainSize,
|
||||
v.next_event to Preferences.textMainSize,
|
||||
v.next_event_difference_time to Preferences.textMainSize,
|
||||
v.next_event_date to Preferences.textSecondSize,
|
||||
v.divider2 to Preferences.textSecondSize,
|
||||
v.calendar_temp to Preferences.textSecondSize
|
||||
v.divider2 to (Preferences.textSecondSize - 2),
|
||||
v.calendar_temp to Preferences.textSecondSize,
|
||||
v.divider3 to (Preferences.textMainSize - 2),
|
||||
v.special_temp to Preferences.textMainSize
|
||||
).forEach {
|
||||
it.first.setTextSize(TypedValue.COMPLEX_UNIT_SP, it.second)
|
||||
}
|
||||
@ -512,6 +633,9 @@ class MainWidget : AppWidgetProvider() {
|
||||
v.action_previous.scaleX = Preferences.textMainSize / 28f
|
||||
v.action_previous.scaleY = Preferences.textMainSize / 28f
|
||||
|
||||
v.special_weather_icon.scaleX = Preferences.textMainSize / 20f
|
||||
v.special_weather_icon.scaleY = Preferences.textMainSize / 20f
|
||||
|
||||
|
||||
// Shadows
|
||||
val shadowRadius = when (Preferences.textShadow) {
|
||||
@ -533,14 +657,14 @@ class MainWidget : AppWidgetProvider() {
|
||||
else -> 0f
|
||||
}
|
||||
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp).forEach {
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp, v.divider3, v.special_temp).forEach {
|
||||
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
|
||||
}
|
||||
|
||||
// Custom Font
|
||||
if (Preferences.customFont == Constants.CUSTOM_FONT_PRODUCT_SANS) {
|
||||
val productSans: Typeface = Typeface.createFromAsset(context.assets, "fonts/product_sans_regular.ttf")
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp).forEach {
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp, v.divider3, v.special_temp).forEach {
|
||||
it.typeface = productSans
|
||||
}
|
||||
}
|
||||
@ -549,24 +673,41 @@ class MainWidget : AppWidgetProvider() {
|
||||
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
||||
v.weather.visibility = View.VISIBLE
|
||||
v.calendar_weather.visibility = View.VISIBLE
|
||||
v.special_weather.visibility = View.VISIBLE
|
||||
val currentTemp = String.format(Locale.getDefault(), "%.0f °%s", Preferences.weatherTemp, Preferences.weatherRealTempUnit)
|
||||
|
||||
val icon: String = Preferences.weatherIcon
|
||||
if (icon == "") {
|
||||
v.weather_icon.visibility = View.GONE
|
||||
v.empty_weather_icon.visibility = View.GONE
|
||||
v.special_weather_icon.visibility = View.GONE
|
||||
} else {
|
||||
v.weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
||||
v.empty_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
||||
v.special_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
||||
v.weather_icon.visibility = View.VISIBLE
|
||||
v.empty_weather_icon.visibility = View.VISIBLE
|
||||
v.special_weather_icon.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
v.temp.text = currentTemp
|
||||
v.calendar_temp.text = currentTemp
|
||||
v.special_temp.text = currentTemp
|
||||
|
||||
if (GlanceProviderHelper.showSpecialWeather(context)) {
|
||||
v.calendar_weather.visibility = View.GONE
|
||||
} else {
|
||||
v.special_weather.visibility = View.GONE
|
||||
}
|
||||
} else {
|
||||
v.weather.visibility = View.GONE
|
||||
v.calendar_weather.visibility = View.GONE
|
||||
v.special_weather.visibility = View.GONE
|
||||
}
|
||||
|
||||
// Dividers
|
||||
arrayOf(v.divider1, v.divider2, v.divider3).forEach {
|
||||
it.isVisible = Preferences.showDividers
|
||||
}
|
||||
|
||||
return v
|
||||
|
BIN
app/src/main/res/drawable-hdpi/round_all_inclusive.png
Normal file
After Width: | Height: | Size: 465 B |
BIN
app/src/main/res/drawable-hdpi/round_all_inclusive_black_18.png
Normal file
After Width: | Height: | Size: 399 B |
BIN
app/src/main/res/drawable-hdpi/round_all_inclusive_black_36.png
Normal file
After Width: | Height: | Size: 665 B |
BIN
app/src/main/res/drawable-hdpi/round_all_inclusive_black_48.png
Normal file
After Width: | Height: | Size: 867 B |
BIN
app/src/main/res/drawable-hdpi/round_battery_charging_full.png
Normal file
After Width: | Height: | Size: 426 B |
After Width: | Height: | Size: 238 B |
After Width: | Height: | Size: 263 B |
After Width: | Height: | Size: 355 B |
After Width: | Height: | Size: 186 B |
After Width: | Height: | Size: 184 B |
After Width: | Height: | Size: 241 B |
After Width: | Height: | Size: 248 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_4.png
Normal file
After Width: | Height: | Size: 616 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_4_black_18.png
Normal file
After Width: | Height: | Size: 324 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_4_black_24.png
Normal file
After Width: | Height: | Size: 372 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_4_black_36.png
Normal file
After Width: | Height: | Size: 517 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_5.png
Normal file
After Width: | Height: | Size: 361 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_5_black_18.png
Normal file
After Width: | Height: | Size: 333 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_5_black_36.png
Normal file
After Width: | Height: | Size: 509 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_5_black_48.png
Normal file
After Width: | Height: | Size: 642 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_7.png
Normal file
After Width: | Height: | Size: 393 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_7_black_24.png
Normal file
After Width: | Height: | Size: 441 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_7_black_36.png
Normal file
After Width: | Height: | Size: 628 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_7_black_48.png
Normal file
After Width: | Height: | Size: 802 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_low.png
Normal file
After Width: | Height: | Size: 399 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_low_black_18.png
Normal file
After Width: | Height: | Size: 362 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_low_black_36.png
Normal file
After Width: | Height: | Size: 541 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_low_black_48.png
Normal file
After Width: | Height: | Size: 689 B |
BIN
app/src/main/res/drawable-hdpi/round_category.png
Normal file
After Width: | Height: | Size: 345 B |
BIN
app/src/main/res/drawable-hdpi/round_category_black_18.png
Normal file
After Width: | Height: | Size: 292 B |
BIN
app/src/main/res/drawable-hdpi/round_category_black_36.png
Normal file
After Width: | Height: | Size: 469 B |
BIN
app/src/main/res/drawable-hdpi/round_category_black_48.png
Normal file
After Width: | Height: | Size: 590 B |
BIN
app/src/main/res/drawable-hdpi/round_collections_bookmark.png
Normal file
After Width: | Height: | Size: 231 B |
After Width: | Height: | Size: 241 B |
After Width: | Height: | Size: 335 B |
After Width: | Height: | Size: 409 B |
BIN
app/src/main/res/drawable-hdpi/round_directions_walk.png
Normal file
After Width: | Height: | Size: 705 B |
After Width: | Height: | Size: 318 B |
After Width: | Height: | Size: 407 B |
After Width: | Height: | Size: 561 B |
BIN
app/src/main/res/drawable-hdpi/round_drag_handle.png
Normal file
After Width: | Height: | Size: 182 B |
BIN
app/src/main/res/drawable-hdpi/round_drag_handle_black_18.png
Normal file
After Width: | Height: | Size: 138 B |
BIN
app/src/main/res/drawable-hdpi/round_drag_handle_black_24.png
Normal file
After Width: | Height: | Size: 143 B |
BIN
app/src/main/res/drawable-hdpi/round_drag_handle_black_36.png
Normal file
After Width: | Height: | Size: 162 B |
BIN
app/src/main/res/drawable-hdpi/round_drag_indicator_black_18.png
Normal file
After Width: | Height: | Size: 296 B |
BIN
app/src/main/res/drawable-hdpi/round_drag_indicator_black_24.png
Normal file
After Width: | Height: | Size: 229 B |
BIN
app/src/main/res/drawable-hdpi/round_drag_indicator_black_36.png
Normal file
After Width: | Height: | Size: 414 B |
BIN
app/src/main/res/drawable-hdpi/round_drag_indicator_black_48.png
Normal file
After Width: | Height: | Size: 371 B |
BIN
app/src/main/res/drawable-hdpi/round_dynamic_feed.png
Normal file
After Width: | Height: | Size: 249 B |
BIN
app/src/main/res/drawable-hdpi/round_dynamic_feed_black_18.png
Normal file
After Width: | Height: | Size: 258 B |
BIN
app/src/main/res/drawable-hdpi/round_dynamic_feed_black_36.png
Normal file
After Width: | Height: | Size: 325 B |
BIN
app/src/main/res/drawable-hdpi/round_dynamic_feed_black_48.png
Normal file
After Width: | Height: | Size: 363 B |
BIN
app/src/main/res/drawable-hdpi/round_extension.png
Normal file
After Width: | Height: | Size: 279 B |
BIN
app/src/main/res/drawable-hdpi/round_extension_black_24.png
Normal file
After Width: | Height: | Size: 322 B |
BIN
app/src/main/res/drawable-hdpi/round_extension_black_36.png
Normal file
After Width: | Height: | Size: 435 B |
BIN
app/src/main/res/drawable-hdpi/round_extension_black_48.png
Normal file
After Width: | Height: | Size: 503 B |
BIN
app/src/main/res/drawable-hdpi/round_flip_to_front_black_18.png
Normal file
After Width: | Height: | Size: 244 B |
BIN
app/src/main/res/drawable-hdpi/round_flip_to_front_black_24.png
Normal file
After Width: | Height: | Size: 250 B |
BIN
app/src/main/res/drawable-hdpi/round_flip_to_front_black_36.png
Normal file
After Width: | Height: | Size: 315 B |
BIN
app/src/main/res/drawable-hdpi/round_flip_to_front_black_48.png
Normal file
After Width: | Height: | Size: 356 B |
BIN
app/src/main/res/drawable-hdpi/round_format_quote.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
app/src/main/res/drawable-hdpi/round_format_quote_black_18.png
Normal file
After Width: | Height: | Size: 227 B |