Merge branch 'master' into translation
* master: Update the build version Update event repository Update the events selector. Fix #95 Fix #113, #111, #79, #107, #109 Add weather icon pack, updates frequency and fix google fit Update ui Update icons Fix dark theme toggle issue Bugfixes Update google fit integration Update beta release update gitignore Clean project files Add google fit connection Add google fit integration
1
.gitignore
vendored
@ -9,3 +9,4 @@
|
||||
.externalNativeBuild
|
||||
/tasksintegration/build
|
||||
apikey.properties
|
||||
/app/google-services.json
|
||||
|
BIN
.idea/caches/build_file_checksums.ser
generated
2
.idea/gradle.xml
generated
@ -11,8 +11,6 @@
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
<option value="$PROJECT_DIR$/googlefit" />
|
||||
<option value="$PROJECT_DIR$/tasksintegration" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
|
2
.idea/modules.xml
generated
@ -4,8 +4,6 @@
|
||||
<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>
|
||||
</project>
|
@ -10,6 +10,10 @@ apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
apply plugin: 'realm-android'
|
||||
|
||||
def apiKeyPropertiesFile = rootProject.file("apikey.properties")
|
||||
def apiKeyProperties = new Properties()
|
||||
apiKeyProperties.load(new FileInputStream(apiKeyPropertiesFile))
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.3"
|
||||
@ -18,10 +22,12 @@ android {
|
||||
applicationId "com.tommasoberlose.anotherwidget"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 29
|
||||
versionCode 83
|
||||
versionName "2.0.6"
|
||||
versionCode 90
|
||||
versionName "2.0.9"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
manifestPlaceholders = [ "AWARENESS_API_KEY": apiKeyProperties['AWARENESS_API_KEY']]
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@ -52,10 +58,6 @@ android {
|
||||
}
|
||||
|
||||
viewBinding.enabled = true
|
||||
|
||||
dynamicFeatures = [":tasksintegration", ":googlefit"]
|
||||
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -98,6 +100,10 @@ dependencies {
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
|
||||
// Fitness
|
||||
implementation 'com.google.android.gms:play-services-fitness:18.0.0'
|
||||
implementation 'com.google.android.gms:play-services-auth:18.0.0'
|
||||
|
||||
//Weather
|
||||
implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:2.0.2'
|
||||
implementation 'com.google.android.gms:play-services-location:17.0.0'
|
||||
|
@ -1,40 +0,0 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "791844924473",
|
||||
"firebase_url": "https://anotherwidget-182008.firebaseio.com",
|
||||
"project_id": "anotherwidget-182008",
|
||||
"storage_bucket": "anotherwidget-182008.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:791844924473:android:0ad4f6e3890f1ad320b1e8",
|
||||
"android_client_info": {
|
||||
"package_name": "com.tommasoberlose.anotherwidget"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "791844924473-73dh46rorjq8vm97dgbn6can2dcpqlf0.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyAeJRXstqnzebibxmm3FRM98nbwE_kC8tA"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "791844924473-73dh46rorjq8vm97dgbn6can2dcpqlf0.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
@ -10,6 +10,10 @@
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="com.android.vending.BILLING" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
|
||||
<uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/>
|
||||
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
|
||||
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
@ -21,7 +25,7 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait">
|
||||
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
@ -82,44 +86,16 @@
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_WEATHER_UPDATE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.TIME_SET" />
|
||||
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
|
||||
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.PlayerReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.music.metachanged" />
|
||||
<action android:name="com.android.music.playstatechanged" />
|
||||
<action android:name="com.android.music.playbackcomplete" />
|
||||
<action android:name="com.android.music.queuechanged" />
|
||||
|
||||
<action android:name="com.htc.music.metachanged" />
|
||||
<action android:name="fm.last.android.metachanged" />
|
||||
<action android:name="com.sec.android.app.music.metachanged" />
|
||||
<action android:name="com.nullsoft.winamp.metachanged" />
|
||||
<action android:name="com.amazon.mp3.metachanged" />
|
||||
<action android:name="com.miui.player.metachanged" />
|
||||
<action android:name="com.real.IMP.metachanged" />
|
||||
<action android:name="com.sonyericsson.music.metachanged" />
|
||||
<action android:name="com.rdio.android.metachanged" />
|
||||
<action android:name="com.samsung.sec.android.MusicPlayer.metachanged" />
|
||||
<action android:name="com.andrew.apollo.metachanged" />
|
||||
<action android:name="com.spotify.music.playbackstatechanged"/>
|
||||
<action android:name="com.spotify.music.metadatachanged"/>
|
||||
<action android:name="com.spotify.music.queuechanged"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.WidgetClickListenerReceiver"
|
||||
android:enabled="true"
|
||||
@ -157,6 +133,16 @@
|
||||
<action android:name="android.intent.action.BATTERY_OKAY"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receivers.ActivityDetectionReceiver"
|
||||
android:exported="false"
|
||||
android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
|
||||
<intent-filter>
|
||||
<action android:name="com.mypackage.ACTION_PROCESS_ACTIVITY_TRANSITIONS" />
|
||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -1,6 +1,7 @@
|
||||
package com.tommasoberlose.anotherwidget
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import com.chibatching.kotpref.Kotpref
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
|
@ -16,6 +16,7 @@ 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.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||
import com.tommasoberlose.anotherwidget.helpers.GlanceProviderHelper
|
||||
import com.tommasoberlose.anotherwidget.models.GlanceProvider
|
||||
@ -69,7 +70,7 @@ class GlanceProviderSortMenu(
|
||||
// move item in `fromPos` to `toPos` in adapter.
|
||||
adapter.notifyItemMoved(fromPos, toPos)
|
||||
|
||||
val list = GlanceProviderHelper.getGlanceProviders()
|
||||
val list = GlanceProviderHelper.getGlanceProviders(context)
|
||||
Collections.swap(list, fromPos, toPos)
|
||||
GlanceProviderHelper.saveGlanceProviderOrder(list)
|
||||
return true
|
||||
@ -86,7 +87,7 @@ class GlanceProviderSortMenu(
|
||||
mIth.attachToRecyclerView(view.menu)
|
||||
|
||||
adapter.updateData(
|
||||
GlanceProviderHelper.getGlanceProviders()
|
||||
GlanceProviderHelper.getGlanceProviders(context)
|
||||
.mapNotNull { GlanceProviderHelper.getGlanceProviderById(context, it) }
|
||||
)
|
||||
|
||||
|
@ -16,17 +16,13 @@ class EventRepository(val context: Context) {
|
||||
private val realm by lazy { Realm.getDefaultInstance() }
|
||||
|
||||
fun saveEvents(eventList: ArrayList<Event>) {
|
||||
realm.executeTransactionAsync { realm ->
|
||||
realm.executeTransaction { realm ->
|
||||
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||
realm.copyToRealm(eventList)
|
||||
}
|
||||
}
|
||||
|
||||
fun resetNextEventData() {
|
||||
realm.executeTransactionAsync {
|
||||
it.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||
}
|
||||
|
||||
Preferences.bulk {
|
||||
remove(Preferences::nextEventId)
|
||||
remove(Preferences::nextEventName)
|
||||
@ -44,7 +40,7 @@ class EventRepository(val context: Context) {
|
||||
|
||||
fun getNextEvent(): Event? {
|
||||
val nextEvent = getEventByEventId(Preferences.nextEventId)
|
||||
return if (nextEvent != null && nextEvent.endDate > Calendar.getInstance().timeInMillis) {
|
||||
val event = if (nextEvent != null && nextEvent.endDate > Calendar.getInstance().timeInMillis) {
|
||||
nextEvent
|
||||
} else {
|
||||
val events = getEvents()
|
||||
@ -57,9 +53,21 @@ class EventRepository(val context: Context) {
|
||||
null
|
||||
}
|
||||
}
|
||||
return try {
|
||||
realm.copyFromRealm(event!!)
|
||||
} catch (ex: Exception) {
|
||||
event
|
||||
}
|
||||
}
|
||||
|
||||
fun getEventByEventId(id: Long): Event? = realm.where(Event::class.java).equalTo("eventID", id).findFirst()
|
||||
fun getEventByEventId(id: Long): Event? {
|
||||
val event = realm.where(Event::class.java).equalTo("eventID", id).findFirst()
|
||||
return try {
|
||||
realm.copyFromRealm(event!!)
|
||||
} catch (ex: Exception) {
|
||||
event
|
||||
}
|
||||
}
|
||||
|
||||
fun goToNextEvent() {
|
||||
val eventList = getEvents()
|
||||
@ -95,8 +103,13 @@ class EventRepository(val context: Context) {
|
||||
|
||||
fun getEvents(): RealmResults<Event> {
|
||||
val now = Calendar.getInstance().timeInMillis
|
||||
realm.refresh()
|
||||
return realm.where(Event::class.java).greaterThan("endDate", now).findAll()
|
||||
}
|
||||
|
||||
fun getEventsCount(): Int = getEvents().size
|
||||
|
||||
fun close() {
|
||||
realm.close()
|
||||
}
|
||||
}
|
@ -18,8 +18,19 @@ object Constants {
|
||||
enum class GlanceProviderId(val id: String) {
|
||||
PLAYING_SONG("PLAYING_SONG"),
|
||||
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
|
||||
// BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
|
||||
BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
|
||||
CUSTOM_INFO("CUSTOM_INFO"),
|
||||
// GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS")
|
||||
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS")
|
||||
}
|
||||
|
||||
enum class WidgetUpdateFrequency(val value: Int) {
|
||||
LOW(0),
|
||||
DEFAULT(1),
|
||||
HIGH(2)
|
||||
}
|
||||
|
||||
enum class WeatherIconPack(val value: Int) {
|
||||
DEFAULT(0),
|
||||
MINIMAL(1)
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ object Preferences : KotprefModel() {
|
||||
var customLocationLon by stringPref(key = "PREF_CUSTOM_LOCATION_LON", default = "")
|
||||
var customLocationAdd by stringPref(key = "PREF_CUSTOM_LOCATION_ADD", default = "")
|
||||
var dateFormat by stringPref(default = "")
|
||||
var isDateCapitalize by booleanPref(default = true)
|
||||
var weatherRefreshPeriod by intPref(key = "PREF_WEATHER_REFRESH_PERIOD", default = 1)
|
||||
var showUntil by intPref(key = "PREF_SHOW_UNTIL", default = 1)
|
||||
var calendarAppName by stringPref(key = "PREF_CALENDAR_APP_NAME", default = "")
|
||||
@ -40,9 +41,15 @@ object Preferences : KotprefModel() {
|
||||
var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "")
|
||||
var eventAppPackage by stringPref(key = "PREF_EVENT_APP_PACKAGE", default = "")
|
||||
var openEventDetails by booleanPref(default = true)
|
||||
|
||||
var widgetUpdateFrequency by intPref(default = Constants.WidgetUpdateFrequency.DEFAULT.value)
|
||||
|
||||
var textGlobalColor by stringPref(key = "PREF_TEXT_COLOR", default = "#FFFFFF")
|
||||
var textGlobalAlpha by stringPref(default = "FF")
|
||||
|
||||
var textSecondaryColor by stringPref(default = "#FFFFFF")
|
||||
var textSecondaryAlpha by stringPref(default = "FF")
|
||||
|
||||
var backgroundCardColor by stringPref(default = "#000000")
|
||||
var backgroundCardAlpha by stringPref(default = "00")
|
||||
|
||||
@ -50,6 +57,8 @@ object Preferences : KotprefModel() {
|
||||
var clockTextAlpha by stringPref(default = "FF")
|
||||
var showAMPMIndicator by booleanPref(default = true)
|
||||
|
||||
var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.value)
|
||||
|
||||
// Global
|
||||
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f)
|
||||
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
|
||||
@ -83,6 +92,7 @@ object Preferences : KotprefModel() {
|
||||
var showBatteryCharging by booleanPref(default = false)
|
||||
var isBatteryLevelLow by booleanPref(default = false)
|
||||
var googleFitSteps by longPref(default = -1)
|
||||
var showDailySteps by booleanPref(default = false)
|
||||
|
||||
var showMusic by booleanPref(default = false)
|
||||
var mediaInfoFormat by stringPref(default = "")
|
||||
|
@ -4,6 +4,7 @@ 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
|
||||
@ -30,6 +31,12 @@ object CalendarHelper {
|
||||
val eventList = ArrayList<Event>()
|
||||
|
||||
val now = Calendar.getInstance()
|
||||
val begin = Calendar.getInstance().apply {
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
set(Calendar.SECOND, 0)
|
||||
set(Calendar.MINUTE, 0)
|
||||
set(Calendar.HOUR_OF_DAY, 0)
|
||||
}
|
||||
val limit = Calendar.getInstance()
|
||||
when (Preferences.showUntil) {
|
||||
0 -> limit.add(Calendar.HOUR, 3)
|
||||
@ -44,7 +51,7 @@ object CalendarHelper {
|
||||
}
|
||||
|
||||
val builder = CalendarContract.Instances.CONTENT_URI.buildUpon()
|
||||
ContentUris.appendId(builder, now.timeInMillis)
|
||||
ContentUris.appendId(builder, begin.timeInMillis)
|
||||
ContentUris.appendId(builder, limit.timeInMillis)
|
||||
|
||||
if (!context.checkGrantedPermission(
|
||||
@ -55,13 +62,13 @@ object CalendarHelper {
|
||||
} else {
|
||||
try {
|
||||
val provider = CalendarProvider(context)
|
||||
val data = provider.getInstances(now.timeInMillis, limit.timeInMillis)
|
||||
val data = provider.getInstances(begin.timeInMillis, limit.timeInMillis)
|
||||
if (data != null) {
|
||||
val instances = data.list
|
||||
for (instance in instances) {
|
||||
try {
|
||||
val e = provider.getEvent(instance.eventId)
|
||||
if (e != null && !e.deleted && instance.begin <= limit.timeInMillis && (Preferences.calendarAllDay || !e.allDay) && !getFilteredCalendarIdList().contains(
|
||||
if (e != null && !e.deleted && instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end && (Preferences.calendarAllDay || !e.allDay) && !getFilteredCalendarIdList().contains(
|
||||
e.calendarId
|
||||
) && (Preferences.showDeclinedEvents || e.selfAttendeeStatus.toInt() != CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED)
|
||||
) {
|
||||
|
@ -30,6 +30,31 @@ object ColorHelper {
|
||||
Color.parseColor("#000000")
|
||||
}
|
||||
}
|
||||
|
||||
fun getSecondaryFontColor(): Int {
|
||||
return try {
|
||||
Color.parseColor("#%s%s".format(Preferences.textSecondaryAlpha, Preferences.textSecondaryColor.replace("#", "")))
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#FFFFFFFF")
|
||||
}
|
||||
}
|
||||
|
||||
fun getSecondaryFontColorAlpha(): Int {
|
||||
return try {
|
||||
Preferences.textSecondaryAlpha.toIntValue().toDouble() * 255 / 100
|
||||
} catch (e: Exception) {
|
||||
"FF".toIntValue().toDouble() * 255 / 100
|
||||
}.roundToInt()
|
||||
}
|
||||
|
||||
fun getSecondaryFontColorRgb(): Int {
|
||||
return try {
|
||||
Color.parseColor(Preferences.textSecondaryColor)
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#000000")
|
||||
}
|
||||
}
|
||||
|
||||
fun getClockFontColor(): Int {
|
||||
return try {
|
||||
Color.parseColor("#%s%s".format(Preferences.clockTextAlpha, Preferences.clockTextColor.replace("#", "")))
|
||||
|
@ -12,27 +12,30 @@ import java.util.*
|
||||
object DateHelper {
|
||||
fun getDateText(context: Context, date: Calendar): String {
|
||||
return if (Preferences.dateFormat != "") {
|
||||
try {
|
||||
val text = try {
|
||||
SimpleDateFormat(Preferences.dateFormat, Locale.getDefault()).format(date.time)
|
||||
} catch (e: Exception) {
|
||||
getDefaultDateText(context, date)
|
||||
}
|
||||
if (Preferences.isDateCapitalize) text.getCapWordString() else text
|
||||
} else {
|
||||
val flags: Int =
|
||||
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||
"%s, %s".format(
|
||||
val text = "%s, %s".format(
|
||||
SimpleDateFormat("EEEE", Locale.getDefault()).format(date.time),
|
||||
DateUtils.formatDateTime(context, date.timeInMillis, flags)
|
||||
).getCapWordString()
|
||||
)
|
||||
if (Preferences.isDateCapitalize) text.getCapWordString() else text
|
||||
}
|
||||
}
|
||||
|
||||
fun getDefaultDateText(context: Context, date: Calendar): String {
|
||||
val flags: Int =
|
||||
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||
return "%s, %s".format(
|
||||
val text = "%s, %s".format(
|
||||
SimpleDateFormat("EEEE", Locale.getDefault()).format(date.time),
|
||||
DateUtils.formatDateTime(context, date.timeInMillis, flags)
|
||||
).getCapWordString()
|
||||
)
|
||||
return if (Preferences.isDateCapitalize) text.getCapWordString() else text
|
||||
}
|
||||
}
|
@ -6,12 +6,18 @@ 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 com.tommasoberlose.anotherwidget.utils.checkIfFitInstalled
|
||||
import java.util.ArrayList
|
||||
|
||||
object GlanceProviderHelper {
|
||||
fun getGlanceProviders(): ArrayList<Constants.GlanceProviderId> {
|
||||
fun getGlanceProviders(context: Context): ArrayList<Constants.GlanceProviderId> {
|
||||
val enabledProviders = Preferences.enabledGlanceProviderOrder.split(",").filter { it != "" }
|
||||
|
||||
val providers = Constants.GlanceProviderId.values()
|
||||
.filter { it != Constants.GlanceProviderId.BATTERY_LEVEL_LOW }
|
||||
.filter {
|
||||
context.checkIfFitInstalled() || it != Constants.GlanceProviderId.GOOGLE_FIT_STEPS
|
||||
}.toTypedArray()
|
||||
|
||||
providers.sortWith(Comparator { p1, p2 ->
|
||||
when {
|
||||
@ -53,18 +59,18 @@ object GlanceProviderHelper {
|
||||
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
|
||||
// )
|
||||
// }
|
||||
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_steps
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,13 +78,13 @@ object GlanceProviderHelper {
|
||||
Preferences.enabledGlanceProviderOrder = list.joinToString(separator = ",")
|
||||
}
|
||||
|
||||
fun showSpecialWeather(context: Context): Boolean {
|
||||
return EventRepository(context).getEventsCount() == 0 && (
|
||||
fun showGlanceProviders(context: Context): Boolean {
|
||||
return Preferences.showGlance && EventRepository(context).getEventsCount() == 0 && (
|
||||
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
|
||||
(MediaPlayerHelper.isSomeonePlaying(context)) ||
|
||||
(Preferences.isBatteryLevelLow) ||
|
||||
(Preferences.customNotes.isNotEmpty()) ||
|
||||
(Preferences.googleFitSteps > 0)
|
||||
(Preferences.showDailySteps && Preferences.googleFitSteps > 0)
|
||||
)
|
||||
}
|
||||
}
|
@ -114,19 +114,40 @@ object IntentHelper {
|
||||
if (Preferences.calendarAppPackage == "") {
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = uri
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
// putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, if (e.allDay) 1 else 0)
|
||||
// type = "vnd.android.cursor.item/event"
|
||||
if (!e.allDay) {
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
} else {
|
||||
val start = Calendar.getInstance().apply {
|
||||
timeInMillis = e.startDate
|
||||
}
|
||||
val end = Calendar.getInstance().apply {
|
||||
timeInMillis = e.endDate
|
||||
}
|
||||
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate + start.timeZone.getOffset(start.timeInMillis))
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate + end.timeZone.getOffset(end.timeInMillis))
|
||||
putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, 1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getCalendarIntent(context).apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
data = uri
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
// putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, if (e.allDay) 1 else 0)
|
||||
// type = "vnd.android.cursor.item/event"
|
||||
if (!e.allDay) {
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
} else {
|
||||
val start = Calendar.getInstance().apply {
|
||||
timeInMillis = e.startDate
|
||||
}
|
||||
val end = Calendar.getInstance().apply {
|
||||
timeInMillis = e.endDate
|
||||
}
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, start.timeInMillis + start.timeZone.getOffset(start.timeInMillis))
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end.timeInMillis + end.timeZone.getOffset(end.timeInMillis))
|
||||
putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,4 +199,15 @@ object IntentHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getFitIntent(context: Context): Intent {
|
||||
val pm: PackageManager = context.packageManager
|
||||
return try {
|
||||
pm.getLaunchIntentForPackage("com.google.android.apps.fitness")!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Intent()
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@ package com.tommasoberlose.anotherwidget.helpers
|
||||
import android.content.Context
|
||||
import android.text.format.DateUtils
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import org.joda.time.DateTime
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@ -68,9 +70,21 @@ object SettingsStringHelper {
|
||||
difference += 60 * 1000 - (difference % (60 * 1000))
|
||||
|
||||
when {
|
||||
difference <= 0 || TimeUnit.MILLISECONDS.toHours(difference) < 1 -> {
|
||||
difference <= 0 -> {
|
||||
return ""
|
||||
}
|
||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.value && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
|
||||
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||
}
|
||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.value && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
|
||||
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||
}
|
||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.value -> {
|
||||
return context.getString(R.string.soon)
|
||||
}
|
||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 -> {
|
||||
return context.getString(R.string.now)
|
||||
}
|
||||
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import android.os.Build
|
||||
import com.google.android.gms.location.LocationServices
|
||||
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.network.WeatherNetworkApi
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||
@ -49,79 +50,79 @@ object WeatherHelper {
|
||||
fun getWeatherIconResource(icon: String): Int {
|
||||
when (icon) {
|
||||
"01d" -> {
|
||||
return R.drawable.clear_day
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.clear_day else R.drawable.clear_day_2
|
||||
}
|
||||
"02d" -> {
|
||||
return R.drawable.partly_cloudy
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.partly_cloudy else R.drawable.partly_cloudy_2
|
||||
}
|
||||
"03d" -> {
|
||||
return R.drawable.mostly_cloudy
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.mostly_cloudy else R.drawable.mostly_cloudy_2
|
||||
}
|
||||
"04d" -> {
|
||||
return R.drawable.cloudy_weather
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.cloudy_weather else R.drawable.cloudy_weather_2
|
||||
}
|
||||
"09d" -> {
|
||||
return R.drawable.storm_weather_day
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.storm_weather_day else R.drawable.storm_weather_day_2
|
||||
}
|
||||
"10d" -> {
|
||||
return R.drawable.rainy_day
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.rainy_day else R.drawable.rainy_day_2
|
||||
}
|
||||
"11d" -> {
|
||||
return R.drawable.thunder_day
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.thunder_day else R.drawable.thunder_day_2
|
||||
}
|
||||
"13d" -> {
|
||||
return R.drawable.snow_day
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.snow_day else R.drawable.snow_day_2
|
||||
}
|
||||
"50d" -> {
|
||||
return R.drawable.haze_day
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.haze_day else R.drawable.haze_day_2
|
||||
}
|
||||
"80d" -> {
|
||||
return R.drawable.windy_day
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.windy_day else R.drawable.windy_day_2
|
||||
}
|
||||
"81d" -> {
|
||||
return R.drawable.rain_snow_day
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.rain_snow_day else R.drawable.rain_snow_day_2
|
||||
}
|
||||
"82d" -> {
|
||||
return R.drawable.haze_weather
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.haze_weather else R.drawable.haze_weather_2
|
||||
}
|
||||
|
||||
|
||||
|
||||
"01n" -> {
|
||||
return R.drawable.clear_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.clear_night else R.drawable.clear_night_2
|
||||
}
|
||||
"02n" -> {
|
||||
return R.drawable.partly_cloudy_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.partly_cloudy_night else R.drawable.partly_cloudy_night_2
|
||||
}
|
||||
"03n" -> {
|
||||
return R.drawable.mostly_cloudy_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.mostly_cloudy_night else R.drawable.mostly_cloudy_night_2
|
||||
}
|
||||
"04n" -> {
|
||||
return R.drawable.cloudy_weather
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.cloudy_weather else R.drawable.cloudy_weather_2
|
||||
}
|
||||
"09n" -> {
|
||||
return R.drawable.storm_weather_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.storm_weather_night else R.drawable.storm_weather_night_2
|
||||
}
|
||||
"10n" -> {
|
||||
return R.drawable.rainy_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.rainy_night else R.drawable.rainy_night_2
|
||||
}
|
||||
"11n" -> {
|
||||
return R.drawable.thunder_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.thunder_night else R.drawable.thunder_night_2
|
||||
}
|
||||
"13n" -> {
|
||||
return R.drawable.snow_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.snow_night else R.drawable.snow_night_2
|
||||
}
|
||||
"50n" -> {
|
||||
return R.drawable.haze_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.haze_night else R.drawable.haze_night_2
|
||||
}
|
||||
"80n" -> {
|
||||
return R.drawable.windy_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.windy_night else R.drawable.windy_night_2
|
||||
}
|
||||
"81n" -> {
|
||||
return R.drawable.rain_snow_night
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.rain_snow_night else R.drawable.rain_snow_night_2
|
||||
}
|
||||
"82n" -> {
|
||||
return R.drawable.haze_weather
|
||||
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.haze_weather else R.drawable.haze_weather_2
|
||||
}
|
||||
else -> {
|
||||
return R.drawable.unknown
|
||||
|
@ -3,6 +3,7 @@ package com.tommasoberlose.anotherwidget.helpers
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
||||
import android.util.Log
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
@ -24,19 +25,9 @@ object WidgetHelper {
|
||||
return widthInPx to heightInPx
|
||||
}
|
||||
|
||||
private fun getWidgetWidth(isPortrait: Boolean, widgetId: Int): Int =
|
||||
if (isPortrait) {
|
||||
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
|
||||
} else {
|
||||
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
|
||||
}
|
||||
private fun getWidgetWidth(isPortrait: Boolean, widgetId: Int): Int = getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
|
||||
|
||||
private fun getWidgetHeight(isPortrait: Boolean, widgetId: Int): Int =
|
||||
if (isPortrait) {
|
||||
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
|
||||
} else {
|
||||
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
|
||||
}
|
||||
private fun getWidgetHeight(isPortrait: Boolean, widgetId: Int): Int = getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
|
||||
|
||||
private fun getWidgetSizeInDp(widgetId: Int, key: String): Int =
|
||||
appWidgetManager.getAppWidgetOptions(widgetId).getInt(key, 0)
|
||||
|
@ -0,0 +1,176 @@
|
||||
package com.tommasoberlose.anotherwidget.receivers
|
||||
|
||||
import android.Manifest
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||
import com.google.android.gms.fitness.Fitness
|
||||
import com.google.android.gms.fitness.FitnessOptions
|
||||
import com.google.android.gms.fitness.data.DataType
|
||||
import com.google.android.gms.fitness.data.Field.FIELD_STEPS
|
||||
import com.google.android.gms.fitness.request.DataReadRequest
|
||||
import com.google.android.gms.location.*
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
class ActivityDetectionReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (ActivityTransitionResult.hasResult(intent)) {
|
||||
val result = ActivityTransitionResult.extractResult(intent)!!
|
||||
val lastEvent = result.transitionEvents.last()
|
||||
|
||||
if (lastEvent.activityType == DetectedActivity.WALKING || lastEvent.activityType == DetectedActivity.RUNNING && lastEvent.transitionType == ActivityTransition.ACTIVITY_TRANSITION_EXIT) {
|
||||
requestDailySteps(context)
|
||||
}
|
||||
} else {
|
||||
if (intent.action == Intent.ACTION_BOOT_COMPLETED || intent.action == Intent.ACTION_MY_PACKAGE_REPLACED && Preferences.showDailySteps && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION)) {
|
||||
resetDailySteps()
|
||||
registerFence(context)
|
||||
} else {
|
||||
resetDailySteps()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetDailySteps() {
|
||||
Preferences.googleFitSteps = -1
|
||||
}
|
||||
|
||||
companion object {
|
||||
val FITNESS_OPTIONS: FitnessOptions = FitnessOptions.builder()
|
||||
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
|
||||
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
|
||||
.build()
|
||||
|
||||
fun registerFence(context: Context) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(
|
||||
Manifest.permission.ACTIVITY_RECOGNITION)) {
|
||||
val transitions = mutableListOf<ActivityTransition>()
|
||||
|
||||
transitions +=
|
||||
ActivityTransition.Builder()
|
||||
.setActivityType(DetectedActivity.WALKING)
|
||||
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
|
||||
.build()
|
||||
|
||||
transitions +=
|
||||
ActivityTransition.Builder()
|
||||
.setActivityType(DetectedActivity.RUNNING)
|
||||
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
|
||||
.build()
|
||||
|
||||
val request = ActivityTransitionRequest(transitions)
|
||||
|
||||
// myPendingIntent is the instance of PendingIntent where the app receives callbacks.
|
||||
val task = ActivityRecognition.getClient(context)
|
||||
.requestActivityTransitionUpdates(
|
||||
request,
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
2,
|
||||
Intent(context, ActivityDetectionReceiver::class.java),
|
||||
0
|
||||
)
|
||||
)
|
||||
|
||||
task.addOnFailureListener { e: Exception ->
|
||||
e.printStackTrace()
|
||||
Preferences.showDailySteps = false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun unregisterFence(context: Context) {
|
||||
val task = ActivityRecognition.getClient(context)
|
||||
.removeActivityTransitionUpdates(
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
2,
|
||||
Intent(context, ActivityDetectionReceiver::class.java),
|
||||
0
|
||||
)
|
||||
)
|
||||
|
||||
task.addOnCompleteListener {
|
||||
if (it.isSuccessful) {
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
2,
|
||||
Intent(context, ActivityDetectionReceiver::class.java),
|
||||
0
|
||||
).cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun requestDailySteps(context: Context) {
|
||||
|
||||
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
|
||||
if (account != null && GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
||||
|
||||
val cal: Calendar = Calendar.getInstance()
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0)
|
||||
cal.set(Calendar.MINUTE, 0)
|
||||
cal.set(Calendar.SECOND, 0)
|
||||
cal.set(Calendar.MILLISECOND, 0)
|
||||
val startTime: Long = cal.timeInMillis
|
||||
|
||||
cal.add(Calendar.DAY_OF_YEAR, 1)
|
||||
val endTime: Long = cal.timeInMillis
|
||||
|
||||
val readRequest = DataReadRequest.Builder()
|
||||
.aggregate(
|
||||
DataType.TYPE_STEP_COUNT_DELTA,
|
||||
DataType.AGGREGATE_STEP_COUNT_DELTA
|
||||
)
|
||||
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
|
||||
.bucketByTime(1, TimeUnit.DAYS)
|
||||
.build()
|
||||
|
||||
Fitness.getHistoryClient(context, account)
|
||||
.readData(readRequest)
|
||||
.addOnSuccessListener { response ->
|
||||
Preferences.googleFitSteps = response.buckets.sumBy {
|
||||
try {
|
||||
it.getDataSet(DataType.AGGREGATE_STEP_COUNT_DELTA)?.dataPoints?.get(
|
||||
0
|
||||
)?.getValue(FIELD_STEPS)?.asInt() ?: 0
|
||||
} catch (ex: Exception) {
|
||||
0
|
||||
}
|
||||
}.toLong()
|
||||
MainWidget.updateWidget(context)
|
||||
setTimeout(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setTimeout(context: Context) {
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
cancel(PendingIntent.getBroadcast(context, 5, Intent(context, ActivityDetectionReceiver::class.java), 0))
|
||||
setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC,
|
||||
Calendar.getInstance().timeInMillis + 5 * 60 * 1000,
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
5,
|
||||
Intent(context, ActivityDetectionReceiver::class.java),
|
||||
0
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.BatteryManager
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
package com.tommasoberlose.anotherwidget.receivers
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
|
||||
|
||||
class PlayerReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
Log.d("ciao", "player ok")
|
||||
|
||||
// val cmd = intent.getStringExtra("command")
|
||||
// Log.v("tag ", "$action / $cmd")
|
||||
// val artist = intent.getStringExtra("artist")
|
||||
// val album = intent.getStringExtra("album")
|
||||
// val track = intent.getStringExtra("track")
|
||||
// Log.v("tag", "$artist:$album:$track")
|
||||
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ import androidx.core.app.AlarmManagerCompat
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
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.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
@ -68,24 +70,54 @@ class UpdatesReceiver : BroadcastReceiver() {
|
||||
val diff = Period(now.timeInMillis, event.startDate)
|
||||
if (event.startDate > now.timeInMillis) {
|
||||
// Update the widget every hour till the event
|
||||
setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC,
|
||||
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(),
|
||||
Intent(context, UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_TIME_UPDATE
|
||||
putExtra(EVENT_ID, event.eventID)
|
||||
},
|
||||
0
|
||||
if (diff.hours == 0) {
|
||||
var minutes = 0
|
||||
when (Preferences.widgetUpdateFrequency) {
|
||||
Constants.WidgetUpdateFrequency.DEFAULT.value -> {
|
||||
minutes = when {
|
||||
diff.minutes > 50 -> 50
|
||||
diff.minutes > 30 -> 30
|
||||
diff.minutes > 15 -> 15
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
Constants.WidgetUpdateFrequency.HIGH.value -> {
|
||||
minutes = diff.minutes - (diff.minutes % 5)
|
||||
}
|
||||
}
|
||||
setExact(
|
||||
AlarmManager.RTC,
|
||||
if (event.startDate - minutes * 1000 * 60 > (now.timeInMillis + 120 * 1000)) event.startDate - 60 * 1000 * minutes else now.timeInMillis + 120000,
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
event.eventID.toInt(),
|
||||
Intent(context, UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_TIME_UPDATE
|
||||
putExtra(EVENT_ID, event.eventID)
|
||||
},
|
||||
0
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
setExact(
|
||||
AlarmManager.RTC,
|
||||
event.startDate - diff.hours * 1000 * 60 * 60,
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
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(
|
||||
setExact(
|
||||
AlarmManager.RTC,
|
||||
fireTime,
|
||||
PendingIntent.getBroadcast(
|
||||
|
@ -18,7 +18,9 @@ import com.tommasoberlose.anotherwidget.databinding.ActivityCustomDateBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.DateHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.CustomDateViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||
import com.tommasoberlose.anotherwidget.utils.toast
|
||||
import kotlinx.android.synthetic.main.activity_custom_date.*
|
||||
import kotlinx.android.synthetic.main.activity_custom_location.action_back
|
||||
import kotlinx.android.synthetic.main.activity_custom_location.list_view
|
||||
@ -78,7 +80,7 @@ class CustomDateActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
delay(200)
|
||||
val text = if (dateFormat != "") {
|
||||
var text = if (dateFormat != "") {
|
||||
try {
|
||||
SimpleDateFormat(dateFormat, Locale.getDefault()).format(DATE.time)
|
||||
} catch (e: Exception) {
|
||||
@ -88,6 +90,10 @@ class CustomDateActivity : AppCompatActivity() {
|
||||
"__"
|
||||
}
|
||||
|
||||
if (Preferences.isDateCapitalize) {
|
||||
text = text.getCapWordString()
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
action_save.isVisible = text != ERROR_STRING
|
||||
loader.visibility = View.INVISIBLE
|
||||
@ -96,6 +102,11 @@ class CustomDateActivity : AppCompatActivity() {
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.isDateCapitalize.observe(this, Observer {
|
||||
viewModel.dateInput.value = viewModel.dateInput.value
|
||||
binding.isdCapitalizeEnabled = it
|
||||
})
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
@ -108,6 +119,15 @@ class CustomDateActivity : AppCompatActivity() {
|
||||
finish()
|
||||
}
|
||||
|
||||
action_capitalize.setOnClickListener {
|
||||
Preferences.isDateCapitalize = !Preferences.isDateCapitalize
|
||||
}
|
||||
|
||||
action_capitalize.setOnLongClickListener {
|
||||
toast(getString(R.string.action_capitalize_the_date))
|
||||
true
|
||||
}
|
||||
|
||||
action_date_format_info.setOnClickListener {
|
||||
openURI("https://developer.android.com/reference/java/text/SimpleDateFormat")
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.Navigation
|
||||
import com.chibatching.kotpref.Kotpref
|
||||
import com.google.android.material.badge.BadgeDrawable
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.karumi.dexter.Dexter
|
||||
|
@ -81,6 +81,8 @@ class CalendarTabFragment : Fragment() {
|
||||
binding: FragmentCalendarSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
binding.isCalendarEnabled = Preferences.showEvents
|
||||
|
||||
viewModel.showEvents.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
binding.isCalendarEnabled = it
|
||||
@ -121,6 +123,17 @@ class CalendarTabFragment : Fragment() {
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.widgetUpdateFrequency.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
widget_update_frequency_label?.text = when (it) {
|
||||
Constants.WidgetUpdateFrequency.HIGH.value -> getString(R.string.settings_widget_update_frequency_high)
|
||||
Constants.WidgetUpdateFrequency.DEFAULT.value -> getString(R.string.settings_widget_update_frequency_default)
|
||||
Constants.WidgetUpdateFrequency.LOW.value -> getString(R.string.settings_widget_update_frequency_low)
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showUntil.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_until_label?.text = getString(SettingsStringHelper.getShowUntilString(it))
|
||||
@ -135,12 +148,6 @@ class CalendarTabFragment : Fragment() {
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.dateFormat.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
date_format_label?.text = DateHelper.getDateText(requireContext(), Calendar.getInstance())
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.calendarAppName.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
calendar_app_label?.text = if (it != "") it else getString(R.string.default_calendar_app)
|
||||
@ -266,6 +273,18 @@ class CalendarTabFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
action_widget_update_frequency.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_widget_update_frequency_title), message = getString(R.string.settings_widget_update_frequency_subtitle)).setSelectedValue(Preferences.widgetUpdateFrequency)
|
||||
.addItem(getString(R.string.settings_widget_update_frequency_high), Constants.WidgetUpdateFrequency.HIGH.value)
|
||||
.addItem(getString(R.string.settings_widget_update_frequency_default), Constants.WidgetUpdateFrequency.DEFAULT.value)
|
||||
.addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.value)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.widgetUpdateFrequency = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_second_row_info.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_second_row_info_title)).setSelectedValue(Preferences.secondRowInformation)
|
||||
@ -290,27 +309,6 @@ class CalendarTabFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
action_date_format.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
val now = Calendar.getInstance()
|
||||
val dialog = BottomSheetMenu<String>(requireContext(), header = getString(R.string.settings_date_format_title)).setSelectedValue(Preferences.dateFormat)
|
||||
|
||||
dialog.addItem(DateHelper.getDefaultDateText(requireContext(), now), "")
|
||||
if (Preferences.dateFormat != "") {
|
||||
dialog.addItem(DateHelper.getDateText(requireContext(), now), Preferences.dateFormat)
|
||||
}
|
||||
dialog.addItem(getString(R.string.custom_date_format), "-")
|
||||
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
if (value == "-") {
|
||||
startActivity(Intent(requireContext(), CustomDateActivity::class.java))
|
||||
} else {
|
||||
Preferences.dateFormat = value
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_open_event_details.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_event_app_title)).setSelectedValue(Preferences.openEventDetails)
|
||||
|
@ -85,6 +85,8 @@ class ClockTabFragment : Fragment() {
|
||||
binding: FragmentClockSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
binding.isClockVisible = Preferences.showClock
|
||||
|
||||
viewModel.showBigClockWarning.observe(viewLifecycleOwner, Observer {
|
||||
large_clock_warning?.isVisible = it
|
||||
small_clock_warning?.isVisible = !it
|
||||
|
@ -21,7 +21,9 @@ import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||
import com.tommasoberlose.anotherwidget.helpers.DateHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.CustomDateActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import kotlinx.android.synthetic.main.fragment_general_settings.*
|
||||
@ -29,6 +31,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.*
|
||||
|
||||
|
||||
class GeneralTabFragment : Fragment() {
|
||||
@ -113,6 +116,28 @@ class GeneralTabFragment : Fragment() {
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.textSecondaryColor.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.textSecondaryAlpha == "00") {
|
||||
secondary_font_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
secondary_font_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor())).toUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.textSecondaryAlpha.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.textSecondaryAlpha == "00") {
|
||||
secondary_font_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
secondary_font_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor())).toUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.backgroundCardColor.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.backgroundCardAlpha == "00") {
|
||||
@ -141,6 +166,12 @@ class GeneralTabFragment : Fragment() {
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.dateFormat.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
date_format_label?.text = DateHelper.getDateText(requireContext(), Calendar.getInstance())
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.customFont.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
custom_font_label?.text = getString(SettingsStringHelper.getCustomFontLabel(it))
|
||||
@ -167,7 +198,7 @@ class GeneralTabFragment : Fragment() {
|
||||
private fun setupListener() {
|
||||
action_main_text_size.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_main_text_size)).setSelectedValue(Preferences.textMainSize)
|
||||
(32 downTo 10).filter { it % 2 == 0 }.forEach {
|
||||
(40 downTo 10).filter { it % 2 == 0 }.forEach {
|
||||
dialog.addItem("${it}sp", it.toFloat())
|
||||
}
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
@ -177,7 +208,7 @@ class GeneralTabFragment : Fragment() {
|
||||
|
||||
action_second_text_size.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_second_text_size)).setSelectedValue(Preferences.textSecondSize)
|
||||
(28 downTo 10).filter { it % 2 == 0 }.forEach {
|
||||
(40 downTo 10).filter { it % 2 == 0 }.forEach {
|
||||
dialog.addItem("${it}sp", it.toFloat())
|
||||
}
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
@ -202,6 +233,44 @@ class GeneralTabFragment : Fragment() {
|
||||
).show()
|
||||
}
|
||||
|
||||
action_secondary_font_color.setOnClickListener {
|
||||
BottomSheetColorPicker(requireContext(),
|
||||
colors = colors,
|
||||
header = getString(R.string.settings_secondary_font_color_title),
|
||||
getSelected = ColorHelper::getSecondaryFontColorRgb,
|
||||
onColorSelected = { color: Int ->
|
||||
val colorString = Integer.toHexString(color)
|
||||
Preferences.textSecondaryColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||
},
|
||||
showAlphaSelector = true,
|
||||
alpha = Preferences.textSecondaryAlpha.toIntValue(),
|
||||
onAlphaChangeListener = { alpha ->
|
||||
Preferences.textSecondaryAlpha = alpha.toHexValue()
|
||||
}
|
||||
).show()
|
||||
}
|
||||
|
||||
action_date_format.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
val now = Calendar.getInstance()
|
||||
val dialog = BottomSheetMenu<String>(requireContext(), header = getString(R.string.settings_date_format_title)).setSelectedValue(Preferences.dateFormat)
|
||||
|
||||
dialog.addItem(DateHelper.getDefaultDateText(requireContext(), now), "")
|
||||
if (Preferences.dateFormat != "") {
|
||||
dialog.addItem(DateHelper.getDateText(requireContext(), now), Preferences.dateFormat)
|
||||
}
|
||||
dialog.addItem(getString(R.string.custom_date_format), "-")
|
||||
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
if (value == "-") {
|
||||
startActivity(Intent(requireContext(), CustomDateActivity::class.java))
|
||||
} else {
|
||||
Preferences.dateFormat = value
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_background_color.setOnClickListener {
|
||||
BottomSheetColorPicker(requireContext(),
|
||||
colors = colors,
|
||||
|
@ -1,31 +1,35 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
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.Build
|
||||
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.google.android.gms.auth.api.signin.GoogleSignIn
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
|
||||
import com.google.android.gms.common.api.ApiException
|
||||
import com.karumi.dexter.Dexter
|
||||
import com.karumi.dexter.MultiplePermissionsReport
|
||||
import com.karumi.dexter.PermissionToken
|
||||
import com.karumi.dexter.listener.PermissionRequest
|
||||
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.components.CustomNotesDialog
|
||||
@ -33,16 +37,18 @@ 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.receivers.ActivityDetectionReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver.Companion.FITNESS_OPTIONS
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.checkIfFitInstalled
|
||||
import kotlinx.android.synthetic.main.fragment_calendar_settings.*
|
||||
import kotlinx.android.synthetic.main.fragment_glance_settings.*
|
||||
import kotlinx.android.synthetic.main.fragment_glance_settings.scrollView
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import net.idik.lib.slimadapter.SlimAdapter
|
||||
import java.util.*
|
||||
|
||||
|
||||
class GlanceTabFragment : Fragment() {
|
||||
@ -76,6 +82,8 @@ class GlanceTabFragment : Fragment() {
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
action_show_steps.isVisible = requireContext().checkIfFitInstalled()
|
||||
|
||||
setupListener()
|
||||
updateNextAlarmWarningUi()
|
||||
}
|
||||
@ -84,6 +92,7 @@ class GlanceTabFragment : Fragment() {
|
||||
binding: FragmentGlanceSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
binding.isGlanceVisible = Preferences.showGlance
|
||||
|
||||
viewModel.showGlance.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
@ -109,6 +118,13 @@ class GlanceTabFragment : Fragment() {
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showDailySteps.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_steps_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
}
|
||||
checkFitnessPermission()
|
||||
})
|
||||
|
||||
viewModel.customInfo.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_custom_notes_label?.text = if (it == "") getString(R.string.settings_not_visible) else it
|
||||
@ -174,6 +190,30 @@ class GlanceTabFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
action_show_steps.setOnClickListener {
|
||||
if (Preferences.showGlance) {
|
||||
BottomSheetMenu<Boolean>(
|
||||
requireContext(),
|
||||
header = getString(R.string.settings_daily_steps_title)
|
||||
).setSelectedValue(Preferences.showDailySteps)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
if (value) {
|
||||
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(requireContext())
|
||||
if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
||||
val mGoogleSignInClient = GoogleSignIn.getClient(requireActivity(), GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).addExtension(FITNESS_OPTIONS).build())
|
||||
startActivityForResult(mGoogleSignInClient.signInIntent, 2)
|
||||
} else {
|
||||
Preferences.showDailySteps = true
|
||||
}
|
||||
} else {
|
||||
Preferences.showDailySteps = false
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_show_custom_notes.setOnClickListener {
|
||||
if (Preferences.showGlance) {
|
||||
CustomNotesDialog(requireContext()).show()
|
||||
@ -228,11 +268,93 @@ class GlanceTabFragment : Fragment() {
|
||||
activity?.startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
|
||||
}
|
||||
} else {
|
||||
show_music_label?.text = getString(R.string.settings_show_music_disabled_subtitle)
|
||||
show_music_label?.text = getString(R.string.settings_not_visible)
|
||||
notification_permission_alert?.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkFitnessPermission() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION) == true) {
|
||||
fitness_permission_alert?.isVisible = false
|
||||
if (Preferences.showDailySteps) {
|
||||
ActivityDetectionReceiver.registerFence(requireContext())
|
||||
} else {
|
||||
ActivityDetectionReceiver.unregisterFence(requireContext())
|
||||
}
|
||||
show_steps_label?.text = if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
} else if (Preferences.showDailySteps) {
|
||||
ActivityDetectionReceiver.unregisterFence(requireContext())
|
||||
fitness_permission_alert?.isVisible = true
|
||||
show_steps_label?.text = getString(R.string.settings_request_fitness_access)
|
||||
fitness_permission_alert?.setOnClickListener {
|
||||
requireFitnessPermission()
|
||||
}
|
||||
} else {
|
||||
ActivityDetectionReceiver.unregisterFence(requireContext())
|
||||
show_steps_label?.text = getString(R.string.settings_not_visible)
|
||||
fitness_permission_alert?.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(
|
||||
requestCode: Int,
|
||||
resultCode: Int,
|
||||
data: Intent?
|
||||
) {
|
||||
when (requestCode) {
|
||||
1 -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
checkFitnessPermission()
|
||||
} else {
|
||||
Preferences.showDailySteps = false
|
||||
}
|
||||
}
|
||||
2-> {
|
||||
try {
|
||||
val account: GoogleSignInAccount? = GoogleSignIn.getSignedInAccountFromIntent(data).getResult(ApiException::class.java)
|
||||
if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
||||
GoogleSignIn.requestPermissions(
|
||||
requireActivity(),
|
||||
1,
|
||||
account,
|
||||
FITNESS_OPTIONS)
|
||||
} else {
|
||||
checkFitnessPermission()
|
||||
}
|
||||
} catch (e: ApiException) {
|
||||
e.printStackTrace()
|
||||
Preferences.showDailySteps = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun requireFitnessPermission() {
|
||||
Dexter.withContext(requireContext())
|
||||
.withPermissions(
|
||||
"com.google.android.gms.permission.ACTIVITY_RECOGNITION",
|
||||
"android.gms.permission.ACTIVITY_RECOGNITION",
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACTIVITY_RECOGNITION else "com.google.android.gms.permission.ACTIVITY_RECOGNITION"
|
||||
).withListener(object: MultiplePermissionsListener {
|
||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||
report?.let {
|
||||
if (report.areAllPermissionsGranted()){
|
||||
checkFitnessPermission()
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun onPermissionRationaleShouldBeShown(
|
||||
permissions: MutableList<PermissionRequest>?,
|
||||
token: PermissionToken?
|
||||
) {
|
||||
// Remember to invoke this method when the custom rationale is closed
|
||||
// or just by default if you don't want to use any custom rationale.
|
||||
token?.continuePermissionRequest()
|
||||
}
|
||||
})
|
||||
.check()
|
||||
}
|
||||
|
||||
private fun maintainScrollPosition(callback: () -> Unit) {
|
||||
val scrollPosition = scrollView.scrollY
|
||||
callback.invoke()
|
||||
|
@ -14,6 +14,7 @@ import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
@ -125,8 +126,11 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
private fun updateUI() {
|
||||
uiJob?.cancel()
|
||||
|
||||
preview?.clearAnimation()
|
||||
time_container?.clearAnimation()
|
||||
|
||||
if (Preferences.showPreview) {
|
||||
preview.setCardBackgroundColor(
|
||||
preview?.setCardBackgroundColor(
|
||||
ContextCompat.getColor(
|
||||
requireContext(),
|
||||
if (ColorHelper.getFontColor()
|
||||
@ -134,52 +138,62 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
) android.R.color.white else R.color.colorAccent
|
||||
)
|
||||
)
|
||||
widget_shape_background.setImageDrawable(BitmapHelper.getTintedDrawable(requireContext(), R.drawable.card_background, ColorHelper.getBackgroundColor()))
|
||||
widget_shape_background?.setImageDrawable(
|
||||
BitmapHelper.getTintedDrawable(
|
||||
requireContext(),
|
||||
R.drawable.card_background,
|
||||
ColorHelper.getBackgroundColor()
|
||||
)
|
||||
)
|
||||
uiJob = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||
val generatedView = MainWidget.generateWidgetView(requireContext())
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
generatedView.measure(0, 0)
|
||||
preview.measure(0, 0)
|
||||
preview?.measure(0, 0)
|
||||
}
|
||||
|
||||
val bitmap = BitmapHelper.getBitmapFromView(
|
||||
generatedView,
|
||||
if (preview.width > 0) preview.width else generatedView.measuredWidth,
|
||||
generatedView.measuredHeight
|
||||
)
|
||||
val bitmap = if (preview != null) {
|
||||
BitmapHelper.getBitmapFromView(
|
||||
generatedView,
|
||||
if (preview.width > 0) preview.width else generatedView.measuredWidth,
|
||||
generatedView.measuredHeight
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
// Clock
|
||||
time.setTextColor(ColorHelper.getClockFontColor())
|
||||
time_am_pm.setTextColor(ColorHelper.getClockFontColor())
|
||||
time.setTextSize(
|
||||
time?.setTextColor(ColorHelper.getClockFontColor())
|
||||
time_am_pm?.setTextColor(ColorHelper.getClockFontColor())
|
||||
time?.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext())
|
||||
)
|
||||
time_am_pm.setTextSize(
|
||||
time_am_pm?.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
|
||||
)
|
||||
time_am_pm.isVisible = Preferences.showAMPMIndicator
|
||||
time_am_pm?.isVisible = Preferences.showAMPMIndicator
|
||||
|
||||
// Clock bottom margin
|
||||
clock_bottom_margin_none.isVisible =
|
||||
clock_bottom_margin_none?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value
|
||||
clock_bottom_margin_small.isVisible =
|
||||
clock_bottom_margin_small?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value
|
||||
clock_bottom_margin_medium.isVisible =
|
||||
clock_bottom_margin_medium?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value
|
||||
clock_bottom_margin_large.isVisible =
|
||||
clock_bottom_margin_large?.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value
|
||||
|
||||
if ((Preferences.showClock && !time_container.isVisible) || (!Preferences.showClock && time_container.isVisible)) {
|
||||
if ((Preferences.showClock && time_container?.isVisible == false) || (!Preferences.showClock && time_container?.isVisible == true)) {
|
||||
if (Preferences.showClock) {
|
||||
time_container.layoutParams = time_container.layoutParams.apply {
|
||||
time_container?.layoutParams = time_container.layoutParams.apply {
|
||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
time_container.measure(0, 0)
|
||||
time_container?.measure(0, 0)
|
||||
}
|
||||
val initialHeight = time_container.measuredHeight
|
||||
val initialHeight = time_container?.measuredHeight ?: 0
|
||||
ValueAnimator.ofFloat(
|
||||
if (Preferences.showClock) 0f else 1f,
|
||||
if (Preferences.showClock) 1f else 0f
|
||||
@ -187,46 +201,50 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
duration = 500L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Float
|
||||
time_container.layoutParams = time_container.layoutParams.apply {
|
||||
height = (initialHeight * animatedValue).toInt()
|
||||
}
|
||||
time_container?.layoutParams =
|
||||
time_container.layoutParams.apply {
|
||||
height = (initialHeight * animatedValue).toInt()
|
||||
}
|
||||
time?.alpha = animatedValue
|
||||
}
|
||||
addListener(
|
||||
onStart = {
|
||||
if (Preferences.showClock) {
|
||||
time_container.isVisible = true
|
||||
time_container?.isVisible = true
|
||||
}
|
||||
},
|
||||
onEnd = {
|
||||
if (!Preferences.showClock) {
|
||||
time_container.isVisible = false
|
||||
time_container?.isVisible = false
|
||||
}
|
||||
}
|
||||
)
|
||||
}.start()
|
||||
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
requireContext()
|
||||
) else 0
|
||||
).apply {
|
||||
duration = 500L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
}
|
||||
}.start()
|
||||
if (preview != null) {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
requireContext()
|
||||
) else 0
|
||||
).apply {
|
||||
duration = 500L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
} else {
|
||||
time_container.layoutParams = time_container.layoutParams.apply {
|
||||
time_container?.layoutParams = time_container.layoutParams.apply {
|
||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
time_container.measure(0, 0)
|
||||
time_container?.measure(0, 0)
|
||||
}
|
||||
|
||||
if (preview.height == 0) {
|
||||
if (preview != null && preview.height == 0) {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
@ -238,29 +256,35 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
preview?.layoutParams = layoutParams
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
widget_loader.animate().scaleX(0f).scaleY(0f).alpha(0f).setDuration(200L).start()
|
||||
bitmap_container.setImageBitmap(bitmap)
|
||||
widget.animate().alpha(1f).start()
|
||||
widget_loader?.animate()?.scaleX(0f)?.scaleY(0f)?.alpha(0f)?.setDuration(200L)?.start()
|
||||
bitmap_container?.apply {
|
||||
setImageBitmap(bitmap)
|
||||
scaleX = 0.9f
|
||||
scaleY = 0.9f
|
||||
}
|
||||
widget?.animate()?.alpha(1f)?.start()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
0
|
||||
).apply {
|
||||
duration = 300L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
}
|
||||
}.start()
|
||||
if (preview != null) {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
0
|
||||
).apply {
|
||||
duration = 300L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
|
||||
showErrorBadge()
|
||||
@ -272,13 +296,27 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
activity?.let { act ->
|
||||
val wallpaper = act.getCurrentWallpaper()
|
||||
widget_bg.setImageDrawable(if (it) wallpaper else null)
|
||||
widget_bg.layoutParams = widget_bg.layoutParams.apply {
|
||||
if (wallpaper != null) {
|
||||
widget_bg.layoutParams =
|
||||
(widget_bg.layoutParams as ViewGroup.MarginLayoutParams).apply {
|
||||
|
||||
val metrics = DisplayMetrics()
|
||||
act.windowManager.defaultDisplay.getMetrics(metrics)
|
||||
val metrics = DisplayMetrics()
|
||||
act.windowManager.defaultDisplay.getMetrics(metrics)
|
||||
|
||||
height = metrics.heightPixels
|
||||
width = (wallpaper?.intrinsicWidth ?: 1) * metrics.heightPixels / (wallpaper?.intrinsicWidth ?: 1)
|
||||
val dimensions: Pair<Int, Int> = if (wallpaper.intrinsicWidth >= wallpaper.intrinsicHeight) {
|
||||
metrics.heightPixels to (wallpaper.intrinsicWidth) * metrics.heightPixels / (wallpaper.intrinsicHeight)
|
||||
} else {
|
||||
metrics.widthPixels to (wallpaper.intrinsicHeight) * metrics.widthPixels / (wallpaper.intrinsicWidth)
|
||||
}
|
||||
|
||||
setMargins(
|
||||
if (dimensions.first >= dimensions.second) (-80).toPixel(requireContext()) else 0,
|
||||
(-80).toPixel(requireContext()), 0, 0
|
||||
)
|
||||
|
||||
width = dimensions.first
|
||||
height = dimensions.second
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -313,11 +351,6 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
}?.isVisible = Preferences.showMusic && !NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
||||
updateUI()
|
||||
MainWidget.updateWidget(requireContext())
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
|
||||
@ -332,10 +365,29 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
var delayJob: Job? = null
|
||||
|
||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
||||
delayJob?.cancel()
|
||||
delayJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||
delay(200)
|
||||
withContext(Dispatchers.Main) {
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
MainWidget.updateWidget(requireContext())
|
||||
}
|
||||
|
||||
class UpdateUiMessageEvent
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onMessageEvent(ignore: UpdateUiMessageEvent?) {
|
||||
updateUI()
|
||||
delayJob?.cancel()
|
||||
delayJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||
delay(200)
|
||||
withContext(Dispatchers.Main) {
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import android.Manifest
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -5,6 +5,7 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -79,6 +80,8 @@ class WeatherTabFragment : Fragment() {
|
||||
binding: FragmentWeatherSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
binding.isWeatherVisible = Preferences.showWeather
|
||||
|
||||
viewModel.showWeatherWarning.observe(viewLifecycleOwner, Observer {
|
||||
weather_warning?.isVisible = it
|
||||
checkLocationPermission()
|
||||
@ -124,6 +127,16 @@ class WeatherTabFragment : Fragment() {
|
||||
checkLocationPermission()
|
||||
})
|
||||
|
||||
viewModel.weatherIconPack.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
label_weather_icon_pack?.text = when (it) {
|
||||
Constants.WeatherIconPack.MINIMAL.value -> getString(R.string.settings_weather_icon_pack_minimal)
|
||||
else -> getString(R.string.settings_weather_icon_pack_default)
|
||||
}
|
||||
}
|
||||
checkLocationPermission()
|
||||
})
|
||||
|
||||
viewModel.weatherAppName.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
weather_app_label?.text =
|
||||
@ -215,6 +228,17 @@ class WeatherTabFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
action_weather_icon_pack.setOnClickListener {
|
||||
if (Preferences.showWeather) {
|
||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_weather_icon_pack_title)).setSelectedValue(Preferences.weatherIconPack)
|
||||
.addItem(getString(R.string.settings_weather_icon_pack_default), Constants.WeatherIconPack.DEFAULT.value)
|
||||
.addItem(getString(R.string.settings_weather_icon_pack_minimal), Constants.WeatherIconPack.MINIMAL.value)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.weatherIconPack = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_weather_app.setOnClickListener {
|
||||
if (Preferences.showWeather) {
|
||||
startActivityForResult(
|
||||
|
@ -3,8 +3,10 @@ package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.chibatching.kotpref.livedata.asLiveData
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
|
||||
class CustomDateViewModel(application: Application) : AndroidViewModel(application) {
|
||||
val dateInput: MutableLiveData<String> = MutableLiveData(if (Preferences.dateFormat == "") "EEEE, MMM dd" else Preferences.dateFormat)
|
||||
val isDateCapitalize = Preferences.asLiveData(Preferences::isDateCapitalize)
|
||||
}
|
@ -9,6 +9,8 @@ class MainViewModel : ViewModel() {
|
||||
// General Settings
|
||||
val textGlobalColor = Preferences.asLiveData(Preferences::textGlobalColor)
|
||||
val textGlobalAlpha = Preferences.asLiveData(Preferences::textGlobalAlpha)
|
||||
val textSecondaryColor = Preferences.asLiveData(Preferences::textSecondaryColor)
|
||||
val textSecondaryAlpha = Preferences.asLiveData(Preferences::textSecondaryAlpha)
|
||||
val backgroundCardColor = Preferences.asLiveData(Preferences::backgroundCardColor)
|
||||
val backgroundCardAlpha = Preferences.asLiveData(Preferences::backgroundCardAlpha)
|
||||
val textMainSize = Preferences.asLiveData(Preferences::textMainSize)
|
||||
@ -27,6 +29,7 @@ class MainViewModel : ViewModel() {
|
||||
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
|
||||
val openEventDetails = Preferences.asLiveData(Preferences::openEventDetails)
|
||||
val calendarAppName = Preferences.asLiveData(Preferences::calendarAppName)
|
||||
val widgetUpdateFrequency = Preferences.asLiveData(Preferences::widgetUpdateFrequency)
|
||||
|
||||
// Clock Settings
|
||||
val showClock = Preferences.asLiveData(Preferences::showClock)
|
||||
@ -52,12 +55,14 @@ class MainViewModel : ViewModel() {
|
||||
val customLocationAdd = Preferences.asLiveData(Preferences::customLocationAdd)
|
||||
|
||||
val showWeatherWarning = Preferences.asLiveData(Preferences::showWeatherWarning)
|
||||
val weatherIconPack = Preferences.asLiveData(Preferences::weatherIconPack)
|
||||
|
||||
// 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 showDailySteps = Preferences.asLiveData(Preferences::showDailySteps)
|
||||
val customInfo = Preferences.asLiveData(Preferences::customNotes)
|
||||
|
||||
// Advanced Settings
|
||||
|
@ -35,6 +35,7 @@ import java.lang.Exception
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
class MainWidget : AppWidgetProvider() {
|
||||
@ -85,9 +86,10 @@ class MainWidget : AppWidgetProvider() {
|
||||
appWidgetId: Int) {
|
||||
val displayMetrics = Resources.getSystem().displayMetrics
|
||||
val width = displayMetrics.widthPixels
|
||||
val height = displayMetrics.heightPixels
|
||||
|
||||
val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId)
|
||||
generateWidgetView(context, appWidgetId, appWidgetManager, dimensions.first - 8.toPixel(context) /*width - 16.toPixel(context)*/)
|
||||
generateWidgetView(context, appWidgetId, appWidgetManager, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)))
|
||||
}
|
||||
|
||||
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int) {
|
||||
@ -261,13 +263,8 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||
} else if (Preferences.showGlance) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders()) {
|
||||
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
||||
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
||||
when (provider) {
|
||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
||||
@ -293,28 +290,35 @@ class MainWidget : AppWidgetProvider() {
|
||||
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.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
|
||||
// }
|
||||
// }
|
||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
||||
val fitIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
widgetID,
|
||||
IntentHelper.getFitIntent(context),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, fitIntent)
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -371,7 +375,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false)
|
||||
)
|
||||
|
||||
if (GlanceProviderHelper.showSpecialWeather(context)) {
|
||||
if (GlanceProviderHelper.showGlanceProviders(context)) {
|
||||
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
|
||||
} else {
|
||||
views.setViewVisibility(R.id.special_weather_rect, View.GONE)
|
||||
@ -452,7 +456,10 @@ class MainWidget : AppWidgetProvider() {
|
||||
val eventRepository = EventRepository(context)
|
||||
val v = View.inflate(context, R.layout.the_widget, null)
|
||||
|
||||
val now = Calendar.getInstance()
|
||||
val now = Calendar.getInstance().apply {
|
||||
set(Calendar.SECOND, 0)
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
}
|
||||
|
||||
v.empty_layout.visibility = View.VISIBLE
|
||||
v.calendar_layout.visibility = View.GONE
|
||||
@ -472,7 +479,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
v.next_event.text = nextEvent.title
|
||||
|
||||
if (Preferences.showDiffTime && now.timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
|
||||
if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
|
||||
v.next_event_difference_time.text = if (!nextEvent.allDay) {
|
||||
SettingsStringHelper.getDifferenceText(
|
||||
context,
|
||||
@ -494,8 +501,8 @@ class MainWidget : AppWidgetProvider() {
|
||||
} else {
|
||||
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.round_today))
|
||||
if (!nextEvent.allDay) {
|
||||
val startHour = DateFormat.getTimeInstance(DateFormat.SHORT).format(nextEvent.startDate)
|
||||
val endHour = DateFormat.getTimeInstance(DateFormat.SHORT).format(nextEvent.endDate)
|
||||
val startHour = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(nextEvent.startDate)
|
||||
val endHour = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(nextEvent.endDate)
|
||||
|
||||
var dayDiff = TimeUnit.MILLISECONDS.toDays(nextEvent.endDate - nextEvent.startDate)
|
||||
|
||||
@ -518,15 +525,15 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
} else {
|
||||
val flags: Int = DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||
v.next_event_date.text = DateUtils.formatDateTime(context, now.timeInMillis, flags).getCapWordString()
|
||||
v.next_event_date.text = DateUtils.formatDateTime(context, now.timeInMillis, flags)
|
||||
}
|
||||
}
|
||||
|
||||
v.empty_layout.visibility = View.GONE
|
||||
v.calendar_layout.visibility = View.VISIBLE
|
||||
} else if (Preferences.showGlance) {
|
||||
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
||||
v.second_row_icon.isVisible = true
|
||||
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders()) {
|
||||
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
||||
when (provider) {
|
||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
||||
@ -552,37 +559,38 @@ class MainWidget : AppWidgetProvider() {
|
||||
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.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
|
||||
v.next_event_date.maxLines = 2
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
||||
v.second_row_icon.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.round_steps
|
||||
)
|
||||
)
|
||||
v.next_event_date.text = context.getString(R.string.daily_steps_counter).format(Preferences.googleFitSteps)
|
||||
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
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,14 +601,30 @@ class MainWidget : AppWidgetProvider() {
|
||||
|
||||
|
||||
// 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, v.divider3, v.special_temp).forEach {
|
||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.divider3, v.special_temp).forEach {
|
||||
it.setTextColor(ColorHelper.getFontColor())
|
||||
}
|
||||
|
||||
listOf<ImageView>(v.second_row_icon, v.action_next, v.action_previous).forEach {
|
||||
if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) {
|
||||
listOf<ImageView>(v.action_next, v.action_previous)
|
||||
} else {
|
||||
listOf<ImageView>(v.action_next, v.action_previous, v.empty_weather_icon, v.special_weather_icon)
|
||||
}.forEach {
|
||||
it.setColorFilter(ColorHelper.getFontColor())
|
||||
}
|
||||
|
||||
listOf<TextView>(v.next_event_date, v.divider2, v.calendar_temp).forEach {
|
||||
it.setTextColor(ColorHelper.getSecondaryFontColor())
|
||||
}
|
||||
|
||||
if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) {
|
||||
listOf<ImageView>(v.second_row_icon)
|
||||
} else {
|
||||
listOf<ImageView>(v.second_row_icon, v.weather_icon)
|
||||
}.forEach {
|
||||
it.setColorFilter(ColorHelper.getSecondaryFontColor())
|
||||
}
|
||||
|
||||
// Text Size
|
||||
listOf<Pair<TextView, Float>>(
|
||||
v.empty_date to Preferences.textMainSize,
|
||||
@ -621,11 +645,11 @@ class MainWidget : AppWidgetProvider() {
|
||||
v.second_row_icon.scaleX = Preferences.textSecondSize / 18f
|
||||
v.second_row_icon.scaleY = Preferences.textSecondSize / 18f
|
||||
|
||||
v.weather_icon.scaleX = Preferences.textSecondSize / 16f
|
||||
v.weather_icon.scaleY = Preferences.textSecondSize / 16f
|
||||
v.weather_icon.scaleX = Preferences.textSecondSize / 14f
|
||||
v.weather_icon.scaleY = Preferences.textSecondSize / 14f
|
||||
|
||||
v.empty_weather_icon.scaleX = Preferences.textMainSize / 20f
|
||||
v.empty_weather_icon.scaleY = Preferences.textMainSize / 20f
|
||||
v.empty_weather_icon.scaleX = Preferences.textMainSize / 18f
|
||||
v.empty_weather_icon.scaleY = Preferences.textMainSize / 18f
|
||||
|
||||
v.action_next.scaleX = Preferences.textMainSize / 28f
|
||||
v.action_next.scaleY = Preferences.textMainSize / 28f
|
||||
@ -694,7 +718,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
v.calendar_temp.text = currentTemp
|
||||
v.special_temp.text = currentTemp
|
||||
|
||||
if (GlanceProviderHelper.showSpecialWeather(context)) {
|
||||
if (GlanceProviderHelper.showGlanceProviders(context)) {
|
||||
v.calendar_weather.visibility = View.GONE
|
||||
} else {
|
||||
v.special_weather.visibility = View.GONE
|
||||
|
@ -213,3 +213,12 @@ fun String.getCapWordString(): String {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.checkIfFitInstalled(): Boolean {
|
||||
return try {
|
||||
packageManager.getPackageInfo("com.google.android.apps.fitness", PackageManager.GET_ACTIVITIES)
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
BIN
app/src/main/res/drawable-hdpi/round_access_alarm.png
Normal file
After Width: | Height: | Size: 868 B |
BIN
app/src/main/res/drawable-hdpi/round_access_alarm_black_18.png
Normal file
After Width: | Height: | Size: 459 B |
BIN
app/src/main/res/drawable-hdpi/round_access_alarm_black_24.png
Normal file
After Width: | Height: | Size: 601 B |
BIN
app/src/main/res/drawable-hdpi/round_access_alarm_black_48.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-hdpi/round_filter_none_black_18.png
Normal file
After Width: | Height: | Size: 240 B |
BIN
app/src/main/res/drawable-hdpi/round_filter_none_black_24.png
Normal file
After Width: | Height: | Size: 259 B |
BIN
app/src/main/res/drawable-hdpi/round_filter_none_black_36.png
Normal file
After Width: | Height: | Size: 355 B |
BIN
app/src/main/res/drawable-hdpi/round_filter_none_black_48.png
Normal file
After Width: | Height: | Size: 413 B |
BIN
app/src/main/res/drawable-hdpi/round_format_size.png
Normal file
After Width: | Height: | Size: 206 B |
BIN
app/src/main/res/drawable-hdpi/round_format_size_black_24.png
Normal file
After Width: | Height: | Size: 237 B |
BIN
app/src/main/res/drawable-hdpi/round_format_size_black_36.png
Normal file
After Width: | Height: | Size: 311 B |
BIN
app/src/main/res/drawable-hdpi/round_format_size_black_48.png
Normal file
After Width: | Height: | Size: 306 B |
BIN
app/src/main/res/drawable-hdpi/round_keyboard_capslock.png
Normal file
After Width: | Height: | Size: 306 B |
After Width: | Height: | Size: 167 B |
After Width: | Height: | Size: 204 B |
After Width: | Height: | Size: 268 B |
BIN
app/src/main/res/drawable-hdpi/round_library_alarm.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
app/src/main/res/drawable-hdpi/round_library_books_black_18.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
app/src/main/res/drawable-hdpi/round_library_books_black_24.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
app/src/main/res/drawable-hdpi/round_library_books_black_36.png
Normal file
After Width: | Height: | Size: 372 B |
BIN
app/src/main/res/drawable-hdpi/round_library_books_black_48.png
Normal file
After Width: | Height: | Size: 447 B |
BIN
app/src/main/res/drawable-hdpi/round_library_music.png
Normal file
After Width: | Height: | Size: 415 B |
BIN
app/src/main/res/drawable-hdpi/round_library_music_black_18.png
Normal file
After Width: | Height: | Size: 269 B |
BIN
app/src/main/res/drawable-hdpi/round_library_music_black_24.png
Normal file
After Width: | Height: | Size: 299 B |
BIN
app/src/main/res/drawable-hdpi/round_library_music_black_48.png
Normal file
After Width: | Height: | Size: 494 B |
BIN
app/src/main/res/drawable-hdpi/round_library_steps.png
Normal file
After Width: | Height: | Size: 900 B |
BIN
app/src/main/res/drawable-hdpi/round_steps.png
Normal file
After Width: | Height: | Size: 947 B |
BIN
app/src/main/res/drawable-mdpi/round_access_alarm.png
Normal file
After Width: | Height: | Size: 601 B |
BIN
app/src/main/res/drawable-mdpi/round_access_alarm_black_18.png
Normal file
After Width: | Height: | Size: 309 B |
BIN
app/src/main/res/drawable-mdpi/round_access_alarm_black_24.png
Normal file
After Width: | Height: | Size: 396 B |
BIN
app/src/main/res/drawable-mdpi/round_access_alarm_black_48.png
Normal file
After Width: | Height: | Size: 763 B |
BIN
app/src/main/res/drawable-mdpi/round_filter_none_black_18.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
app/src/main/res/drawable-mdpi/round_filter_none_black_24.png
Normal file
After Width: | Height: | Size: 164 B |
BIN
app/src/main/res/drawable-mdpi/round_filter_none_black_36.png
Normal file
After Width: | Height: | Size: 259 B |
BIN
app/src/main/res/drawable-mdpi/round_filter_none_black_48.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
app/src/main/res/drawable-mdpi/round_format_size.png
Normal file
After Width: | Height: | Size: 159 B |
BIN
app/src/main/res/drawable-mdpi/round_format_size_black_24.png
Normal file
After Width: | Height: | Size: 156 B |
BIN
app/src/main/res/drawable-mdpi/round_format_size_black_36.png
Normal file
After Width: | Height: | Size: 237 B |
BIN
app/src/main/res/drawable-mdpi/round_format_size_black_48.png
Normal file
After Width: | Height: | Size: 232 B |
BIN
app/src/main/res/drawable-mdpi/round_keyboard_capslock.png
Normal file
After Width: | Height: | Size: 243 B |
After Width: | Height: | Size: 147 B |
After Width: | Height: | Size: 151 B |
After Width: | Height: | Size: 204 B |
BIN
app/src/main/res/drawable-mdpi/round_library_alarm.png
Normal file
After Width: | Height: | Size: 556 B |
BIN
app/src/main/res/drawable-mdpi/round_library_books_black_18.png
Normal file
After Width: | Height: | Size: 196 B |
BIN
app/src/main/res/drawable-mdpi/round_library_books_black_24.png
Normal file
After Width: | Height: | Size: 176 B |
BIN
app/src/main/res/drawable-mdpi/round_library_books_black_36.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
app/src/main/res/drawable-mdpi/round_library_books_black_48.png
Normal file
After Width: | Height: | Size: 311 B |
BIN
app/src/main/res/drawable-mdpi/round_library_music.png
Normal file
After Width: | Height: | Size: 299 B |
BIN
app/src/main/res/drawable-mdpi/round_library_music_black_18.png
Normal file
After Width: | Height: | Size: 208 B |
BIN
app/src/main/res/drawable-mdpi/round_library_music_black_24.png
Normal file
After Width: | Height: | Size: 201 B |
BIN
app/src/main/res/drawable-mdpi/round_library_music_black_48.png
Normal file
After Width: | Height: | Size: 351 B |
BIN
app/src/main/res/drawable-mdpi/round_library_steps.png
Normal file
After Width: | Height: | Size: 484 B |
BIN
app/src/main/res/drawable-mdpi/round_steps.png
Normal file
After Width: | Height: | Size: 521 B |
BIN
app/src/main/res/drawable-xhdpi/round_access_alarm.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-xhdpi/round_access_alarm_black_18.png
Normal file
After Width: | Height: | Size: 601 B |
BIN
app/src/main/res/drawable-xhdpi/round_access_alarm_black_24.png
Normal file
After Width: | Height: | Size: 763 B |
BIN
app/src/main/res/drawable-xhdpi/round_access_alarm_black_48.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/drawable-xhdpi/round_filter_none_black_18.png
Normal file
After Width: | Height: | Size: 259 B |
BIN
app/src/main/res/drawable-xhdpi/round_filter_none_black_24.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
app/src/main/res/drawable-xhdpi/round_filter_none_black_36.png
Normal file
After Width: | Height: | Size: 413 B |
BIN
app/src/main/res/drawable-xhdpi/round_filter_none_black_48.png
Normal file
After Width: | Height: | Size: 531 B |