Release v2.0.1
1
.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
Another Widget
|
129
.idea/assetWizardSettings.xml
generated
Normal file
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="WizardSettings">
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="imageWizard">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="imageAssetPanel">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="actionbar">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="clipArt">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="theme" value="HOLO_DARK" />
|
||||
<entry key="themeColor" value="ffffff" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="launcher">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="foregroundImage">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
<entry key="scalingPercent" value="70" />
|
||||
<entry key="trimmed" value="true" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="backgroundAssetType" value="COLOR" />
|
||||
<entry key="backgroundColor" value="ffffff" />
|
||||
<entry key="foregroundImage" value="$USER_HOME$/Desktop/Artboard Copy 3.png" />
|
||||
<entry key="legacyIconShape" value="CIRCLE" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="launcherLegacy">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="clipArt">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="notification">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="children">
|
||||
<map>
|
||||
<entry key="clipArt">
|
||||
<value>
|
||||
<PersistentState>
|
||||
<option name="values">
|
||||
<map>
|
||||
<entry key="color" value="000000" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
BIN
.idea/caches/build_file_checksums.ser
generated
1
.idea/gradle.xml
generated
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
|
@ -18,8 +18,8 @@ android {
|
||||
applicationId "com.tommasoberlose.anotherwidget"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 29
|
||||
versionCode 40
|
||||
versionName "2.0"
|
||||
versionCode 48
|
||||
versionName "2.0.1"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@ -36,6 +36,10 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
@ -65,6 +69,7 @@ dependencies {
|
||||
implementation 'com.google.android.material:material:1.2.0-alpha06'
|
||||
implementation 'androidx.browser:browser:1.2.0'
|
||||
implementation 'net.idik:slimadapter:2.1.2'
|
||||
implementation 'com.google.android:flexbox:2.0.1'
|
||||
|
||||
// Lifecycle
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
@ -81,9 +86,9 @@ dependencies {
|
||||
// Other
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'joda-time:joda-time:2.9.9'
|
||||
implementation "dev.sasikanth:colorsheet:1.0.1"
|
||||
implementation 'com.andkulikov:transitionseverywhere:1.7.6'
|
||||
implementation 'me.everything:providers-android:1.0.1'
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
|
||||
//Weather
|
||||
implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:2.0.2'
|
||||
@ -96,6 +101,7 @@ dependencies {
|
||||
// KTX
|
||||
implementation "androidx.core:core-ktx:1.2.0"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
|
||||
implementation "androidx.palette:palette-ktx:1.0.0"
|
||||
|
||||
// Recommended: Add the Firebase SDK for Google Analytics.
|
||||
implementation 'com.google.firebase:firebase-analytics:17.4.0'
|
||||
|
BIN
app/release/app-release.aab
Normal file
@ -13,7 +13,7 @@
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:name=".components.AWApplication"
|
||||
android:name=".AWApplication"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
@ -28,9 +28,10 @@
|
||||
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" />
|
||||
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" />
|
||||
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" />
|
||||
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" />
|
||||
|
||||
|
||||
<receiver android:name=".ui.widgets.TheWidget">
|
||||
<receiver android:name=".ui.widgets.MainWidget">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
</intent-filter>
|
||||
@ -65,6 +66,7 @@
|
||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||
<action android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
|
||||
<action android:name="android.intent.action.DATE_CHANGED" />
|
||||
<action android:name="android.intent.action.TIME_SET" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
@ -76,6 +78,7 @@
|
||||
<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.TIME_SET" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
@ -88,6 +91,8 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name=".services.EventListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 13 KiB |
@ -1,4 +1,4 @@
|
||||
package com.tommasoberlose.anotherwidget.components
|
||||
package com.tommasoberlose.anotherwidget
|
||||
|
||||
import android.app.Application
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
@ -23,5 +23,22 @@ class AWApplication : Application() {
|
||||
.deleteRealmIfMigrationNeeded()
|
||||
.build()
|
||||
Realm.setDefaultConfiguration(config)
|
||||
|
||||
calibrateVersions()
|
||||
}
|
||||
|
||||
private fun calibrateVersions() {
|
||||
// 2.0 Tolerance
|
||||
if (Preferences.clockTextSize > 50f) {
|
||||
Preferences.clockTextSize = 46f
|
||||
}
|
||||
|
||||
if (Preferences.textMainSize > 36f) {
|
||||
Preferences.textMainSize = 32f
|
||||
}
|
||||
|
||||
if (Preferences.textSecondSize > 28f) {
|
||||
Preferences.textSecondSize = 24f
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.tommasoberlose.anotherwidget.components
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import android.widget.GridLayout
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.view.*
|
||||
import kotlinx.android.synthetic.main.color_picker_menu_item.view.*
|
||||
|
||||
class BottomSheetColorPicker(
|
||||
context: Context,
|
||||
private val colors: IntArray = intArrayOf(),
|
||||
private val selected: Int? = null,
|
||||
private val header: String? = null,
|
||||
private val onColorSelected: ((selectedValue: Int) -> Unit)? = null
|
||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||
|
||||
override fun show() {
|
||||
val view = View.inflate(context, R.layout.bottom_sheet_menu_hor, null)
|
||||
|
||||
// Header
|
||||
view.header.isVisible = header != null
|
||||
view.header_text.text = header ?: ""
|
||||
|
||||
// Menu
|
||||
for (@ColorInt color: Int in colors) {
|
||||
val itemView = View.inflate(context, R.layout.color_picker_menu_item, null)
|
||||
itemView.color.setCardBackgroundColor(ColorStateList.valueOf(color))
|
||||
itemView.check.setColorFilter(ContextCompat.getColor(context,
|
||||
if (color.isColorDark()) android.R.color.white else android.R.color.black
|
||||
), android.graphics.PorterDuff.Mode.MULTIPLY)
|
||||
itemView.check.isVisible = selected == color
|
||||
itemView.color.setOnClickListener {
|
||||
onColorSelected?.invoke(color)
|
||||
this.dismiss()
|
||||
}
|
||||
view.menu.addView(itemView, GridLayout.LayoutParams(
|
||||
GridLayout.spec(GridLayout.UNDEFINED, 1f),
|
||||
GridLayout.spec(GridLayout.UNDEFINED, 1f)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
setContentView(view)
|
||||
super.show()
|
||||
}
|
||||
|
||||
}
|
@ -4,11 +4,14 @@ import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.MenuRes
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_menu.view.*
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_item.view.*
|
||||
@ -18,18 +21,24 @@ import kotlinx.android.synthetic.main.bottom_sheet_menu_item.view.*
|
||||
* theme which sets a rounded background to the dialog
|
||||
* and doesn't dim the navigation bar
|
||||
*/
|
||||
open class BottomSheetMenu<T>(context: Context, private val header: String? = null) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||
open class BottomSheetMenu<T>(context: Context, private val header: String? = null, private val isMultiSelection: Boolean = false) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||
|
||||
private val items: ArrayList<MenuItem<T>> = ArrayList()
|
||||
private var selectedRes: T? = null
|
||||
private var selectedRes: ArrayList<T> = ArrayList()
|
||||
private var callback: ((selectedValue: T) -> Unit)? = null
|
||||
private var multipleSelectionCallback: ((selectedValues: ArrayList<T>) -> Unit)? = null
|
||||
|
||||
fun selectResource(res: T): BottomSheetMenu<T> {
|
||||
selectedRes = res
|
||||
fun setSelectedValue(res: T): BottomSheetMenu<T> {
|
||||
selectedRes = ArrayList(listOf(res))
|
||||
return this
|
||||
}
|
||||
|
||||
fun addItem(title: String, value: T): BottomSheetMenu<T> {
|
||||
fun setSelectedValues(res: List<T>): BottomSheetMenu<T> {
|
||||
selectedRes = ArrayList(res)
|
||||
return this
|
||||
}
|
||||
|
||||
fun addItem(title: String, value: T? = null): BottomSheetMenu<T> {
|
||||
items.add(MenuItem(title, value))
|
||||
return this
|
||||
}
|
||||
@ -39,6 +48,11 @@ open class BottomSheetMenu<T>(context: Context, private val header: String? = nu
|
||||
return this
|
||||
}
|
||||
|
||||
fun addOnMultipleSelectItemListener(multipleSelectionCallback: (selectedValues: ArrayList<T>) -> Unit): BottomSheetMenu<T> {
|
||||
this.multipleSelectionCallback = multipleSelectionCallback
|
||||
return this
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
val view = View.inflate(context, R.layout.bottom_sheet_menu, null)
|
||||
|
||||
@ -48,19 +62,52 @@ open class BottomSheetMenu<T>(context: Context, private val header: String? = nu
|
||||
|
||||
// Menu
|
||||
for (item in items) {
|
||||
val itemView = View.inflate(context, R.layout.bottom_sheet_menu_item, null)
|
||||
itemView.label.text = item.title
|
||||
itemView.isSelected = item.value == selectedRes
|
||||
itemView.setOnClickListener {
|
||||
callback?.invoke(item.value)
|
||||
this.dismiss()
|
||||
if (item.value != null) {
|
||||
val itemView = View.inflate(context, R.layout.bottom_sheet_menu_item, null)
|
||||
itemView.label.text = item.title
|
||||
if (isMultiSelection) {
|
||||
itemView.icon_check.isVisible = selectedRes.contains(item.value)
|
||||
itemView.label.setTextColor(
|
||||
if (selectedRes.contains(item.value)) ContextCompat.getColor(
|
||||
context,
|
||||
R.color.colorPrimaryText
|
||||
) else ContextCompat.getColor(context, R.color.colorSecondaryText)
|
||||
)
|
||||
} else {
|
||||
itemView.isSelected = selectedRes.contains(item.value)
|
||||
}
|
||||
itemView.setOnClickListener {
|
||||
if (!isMultiSelection) {
|
||||
callback?.invoke(item.value)
|
||||
this.dismiss()
|
||||
} else {
|
||||
if (selectedRes.contains(item.value)) {
|
||||
selectedRes.remove(item.value)
|
||||
} else {
|
||||
selectedRes.add(item.value)
|
||||
}
|
||||
|
||||
multipleSelectionCallback?.invoke(selectedRes)
|
||||
itemView.icon_check.isVisible = selectedRes.contains(item.value)
|
||||
itemView.label.setTextColor(
|
||||
if (selectedRes.contains(item.value)) ContextCompat.getColor(
|
||||
context,
|
||||
R.color.colorPrimaryText
|
||||
) else ContextCompat.getColor(context, R.color.colorSecondaryText)
|
||||
)
|
||||
}
|
||||
}
|
||||
view.menu.addView(itemView)
|
||||
} else {
|
||||
val itemView = View.inflate(context, R.layout.bottom_sheet_menu_divider, null)
|
||||
itemView.label.text = item.title
|
||||
view.menu.addView(itemView)
|
||||
}
|
||||
view.menu.addView(itemView)
|
||||
}
|
||||
setContentView(view)
|
||||
super.show()
|
||||
}
|
||||
|
||||
class MenuItem<T>(val title: String, val value: T)
|
||||
class MenuItem<T>(val title: String, val value: T? = null)
|
||||
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.tommasoberlose.anotherwidget.components
|
||||
|
||||
/**
|
||||
* Created by tommaso on 08/10/17.
|
||||
*/
|
||||
class CalendarSelector(id: Int, name: String?, account_name: String?) {
|
||||
var id: Int = 0
|
||||
var name: String = ""
|
||||
var account_name: String = ""
|
||||
|
||||
init {
|
||||
this.id = id
|
||||
this.name = name?: ""
|
||||
this.account_name = account_name?: ""
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package com.tommasoberlose.anotherwidget.components.events
|
||||
|
||||
import android.content.pm.ApplicationInfo
|
||||
|
||||
/**
|
||||
* Created by tommaso on 15/10/17.
|
||||
*/
|
||||
class AppInfoSavedEvent(val app: ApplicationInfo) {
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.tommasoberlose.anotherwidget.components.events
|
||||
|
||||
import android.content.pm.ApplicationInfo
|
||||
|
||||
/**
|
||||
* Created by tommaso on 15/10/17.
|
||||
*/
|
||||
|
||||
class ApplicationListEvent(apps: List<ApplicationInfo>, filtered: Boolean) {
|
||||
var apps: List<ApplicationInfo> = ArrayList()
|
||||
var filtered: Boolean = false
|
||||
init {
|
||||
this.apps = apps
|
||||
this.filtered = filtered
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package com.tommasoberlose.anotherwidget.components.events
|
||||
|
||||
import android.location.Address
|
||||
|
||||
/**
|
||||
* Created by tommaso on 14/10/17.
|
||||
*/
|
||||
|
||||
class CustomLocationEvent(addresses: ArrayList<Address>) {
|
||||
var addresses: ArrayList<Address> = ArrayList()
|
||||
init {
|
||||
this.addresses = addresses
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package com.tommasoberlose.anotherwidget.db
|
||||
|
||||
import android.content.Context
|
||||
import com.chibatching.kotpref.bulk
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmResults
|
||||
|
||||
class EventRepository(val context: Context) {
|
||||
private val realm by lazy { Realm.getDefaultInstance() }
|
||||
|
||||
fun saveEvents(eventList: ArrayList<Event>) {
|
||||
realm.executeTransactionAsync { 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)
|
||||
remove(Preferences::nextEventStartDate)
|
||||
remove(Preferences::nextEventAllDay)
|
||||
remove(Preferences::nextEventLocation)
|
||||
remove(Preferences::nextEventEndDate)
|
||||
remove(Preferences::nextEventCalendarId)
|
||||
}
|
||||
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
fun saveNextEventData(event: Event) {
|
||||
Preferences.nextEventId = event.id
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
fun getNextEvent(): Event? = realm.where(Event::class.java).equalTo("id", Preferences.nextEventId).findFirst() ?: realm.where(Event::class.java).findFirst()
|
||||
|
||||
fun goToNextEvent() {
|
||||
val eventList = realm.where(Event::class.java).findAll()
|
||||
|
||||
if (eventList.isNotEmpty()) {
|
||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
||||
if (index > -1 && index < eventList.size - 1) {
|
||||
Preferences.nextEventId = eventList[index + 1]!!.id
|
||||
} else {
|
||||
Preferences.nextEventId = eventList.first()!!.id
|
||||
}
|
||||
} else {
|
||||
resetNextEventData()
|
||||
}
|
||||
UpdatesReceiver.setUpdates(context)
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
fun goToPreviousEvent() {
|
||||
val eventList = realm.where(Event::class.java).findAll()
|
||||
|
||||
if (eventList.isNotEmpty()) {
|
||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
||||
if (index > 0) {
|
||||
Preferences.nextEventId = eventList[index - 1]!!.id
|
||||
} else {
|
||||
Preferences.nextEventId = eventList.last()!!.id
|
||||
}
|
||||
} else {
|
||||
resetNextEventData()
|
||||
}
|
||||
UpdatesReceiver.setUpdates(context)
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
fun getEvents(): RealmResults<Event> = realm.where(Event::class.java).findAll()
|
||||
|
||||
fun getEventsCount(): Int = realm.where(Event::class.java).findAll().size
|
||||
}
|
@ -30,7 +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 hourFormat by stringPref(key = "PREF_HOUR_FORMAT", default = "12")
|
||||
var dateFormat by booleanPref(key = "PREF_ITA_FORMAT_DATE", default = false)
|
||||
var dateFormat by stringPref(default = "")
|
||||
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 = "")
|
||||
@ -62,4 +62,6 @@ object Preferences : KotprefModel() {
|
||||
var showGpsInformation by booleanPref(key = "PREF_SHOW_GPS_NOTIFICATION", default = true)
|
||||
|
||||
var showWallpaper by booleanPref(default = false)
|
||||
var showBigClockWarning by booleanPref(default = true)
|
||||
var showWeatherWarning by booleanPref(default = true)
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.content.Context
|
||||
import android.text.format.DateFormat
|
||||
import java.util.*
|
||||
|
||||
object AlarmHelper {
|
||||
fun getNextAlarm(context: Context): String = with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
return if (
|
||||
nextAlarmClock != null
|
||||
&& nextAlarmClock.triggerTime - Calendar.getInstance().timeInMillis > 2 * 60 * 1000
|
||||
&& nextAlarmClock.triggerTime - Calendar.getInstance().timeInMillis < 24 * 60 * 60 * 1000
|
||||
) {
|
||||
DateFormat.getTimeFormat(context).format(Date(nextAlarmClock.triggerTime))
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
|
||||
object BitmapHelper {
|
||||
|
||||
|
||||
fun getBitmapFromView(view: View): Bitmap {
|
||||
//Define a bitmap with the same size as the view
|
||||
val measuredWidth = View.MeasureSpec.makeMeasureSpec(view.width, View.MeasureSpec.UNSPECIFIED)
|
||||
val measuredHeight = View.MeasureSpec.makeMeasureSpec(view.height, View.MeasureSpec.UNSPECIFIED)
|
||||
view.measure(measuredWidth, measuredHeight)
|
||||
view.layout(0,0, measuredWidth, measuredHeight)
|
||||
val returnedBitmap = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight, Bitmap.Config.ARGB_8888)
|
||||
//Bind a canvas to it
|
||||
val canvas = Canvas(returnedBitmap)
|
||||
// draw the view on the canvas
|
||||
view.draw(canvas)
|
||||
//return the bitmap
|
||||
return returnedBitmap
|
||||
}
|
||||
|
||||
fun getBitmapFromView(view: View, w: Int, h: Int): Bitmap {
|
||||
//Define a bitmap with the same size as the view
|
||||
val measuredWidth = View.MeasureSpec.makeMeasureSpec(w, View.MeasureSpec.EXACTLY)
|
||||
val measuredHeight = View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.EXACTLY)
|
||||
view.measure(measuredWidth, measuredHeight)
|
||||
view.layout(0,0, measuredWidth, measuredHeight)
|
||||
val returnedBitmap = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight, Bitmap.Config.ARGB_8888)
|
||||
//Bind a canvas to it
|
||||
val canvas = Canvas(returnedBitmap)
|
||||
// draw the view on the canvas
|
||||
view.draw(canvas)
|
||||
//return the bitmap
|
||||
return returnedBitmap
|
||||
}
|
||||
|
||||
fun getResizedBitmap(image: Bitmap, maxSize: Int): Bitmap {
|
||||
var width = image.width
|
||||
var height = image.height
|
||||
|
||||
val bitmapRatio = width.toFloat() / height.toFloat()
|
||||
if (bitmapRatio > 1) {
|
||||
width = maxSize
|
||||
height = (width / bitmapRatio).toInt()
|
||||
} else {
|
||||
height = maxSize
|
||||
width = (height * bitmapRatio).toInt()
|
||||
}
|
||||
|
||||
return Bitmap.createScaledBitmap(image, width, height, true)
|
||||
}
|
||||
|
||||
fun getTintedDrawable(context: Context, inputDrawable: Int, color: Int): Drawable? = ContextCompat.getDrawable(context, inputDrawable)?.apply {
|
||||
DrawableCompat.setTint(this, color)
|
||||
DrawableCompat.setTintMode(this, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
fun changeBitmapColor(sourceBitmap: Bitmap, color: Int): Bitmap {
|
||||
val resultBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0,
|
||||
sourceBitmap.width - 1, sourceBitmap.height - 1)
|
||||
val p = Paint()
|
||||
val filter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
p.colorFilter = filter
|
||||
|
||||
val canvas = Canvas(resultBitmap)
|
||||
canvas.drawBitmap(resultBitmap, 0f, 0f, p)
|
||||
|
||||
return resultBitmap
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.provider.CalendarContract
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.services.EventListenerJob
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import me.everything.providers.android.calendar.CalendarProvider
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.util.*
|
||||
import kotlin.Comparator
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
/**
|
||||
* Created by tommaso on 08/10/17.
|
||||
*/
|
||||
|
||||
object CalendarHelper {
|
||||
|
||||
fun updateEventList(context: Context) {
|
||||
val eventRepository = EventRepository(context)
|
||||
if (Preferences.showEvents) {
|
||||
val eventList = ArrayList<Event>()
|
||||
|
||||
val now = Calendar.getInstance()
|
||||
val limit = Calendar.getInstance()
|
||||
when (Preferences.showUntil) {
|
||||
0 -> limit.add(Calendar.HOUR, 3)
|
||||
1 -> limit.add(Calendar.HOUR, 6)
|
||||
2 -> limit.add(Calendar.HOUR, 12)
|
||||
3 -> limit.add(Calendar.DAY_OF_MONTH, 1)
|
||||
4 -> limit.add(Calendar.DAY_OF_MONTH, 3)
|
||||
5 -> limit.add(Calendar.DAY_OF_MONTH, 7)
|
||||
6 -> limit.add(Calendar.MINUTE, 30)
|
||||
7 -> limit.add(Calendar.HOUR, 1)
|
||||
else -> limit.add(Calendar.HOUR, 6)
|
||||
}
|
||||
|
||||
val builder = CalendarContract.Instances.CONTENT_URI.buildUpon()
|
||||
ContentUris.appendId(builder, now.timeInMillis)
|
||||
ContentUris.appendId(builder, limit.timeInMillis)
|
||||
|
||||
if (!context.checkGrantedPermission(
|
||||
Manifest.permission.READ_CALENDAR
|
||||
)
|
||||
) {
|
||||
eventRepository.resetNextEventData()
|
||||
} else {
|
||||
val provider = CalendarProvider(context)
|
||||
val data = provider.getInstances(now.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(e.calendarId) && (Preferences.showDeclinedEvents || e.selfAttendeeStatus.toInt() != CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED)) {
|
||||
if (e.allDay) {
|
||||
val start = Calendar.getInstance()
|
||||
start.timeInMillis = instance.begin
|
||||
val end = Calendar.getInstance()
|
||||
end.timeInMillis = instance.end
|
||||
instance.begin = start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
|
||||
instance.end = end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
|
||||
}
|
||||
eventList.add(
|
||||
Event(
|
||||
instance.id,
|
||||
e.id,
|
||||
e.title ?: "",
|
||||
instance.begin,
|
||||
instance.end,
|
||||
e.calendarId.toInt(),
|
||||
e.allDay,
|
||||
e.eventLocation ?: ""
|
||||
)
|
||||
)
|
||||
}
|
||||
} catch (ignored: Exception) {}
|
||||
}
|
||||
}
|
||||
|
||||
if (eventList.isEmpty()) {
|
||||
eventRepository.resetNextEventData()
|
||||
} else {
|
||||
eventList.sortWith(Comparator { event: Event, event1: Event ->
|
||||
if (event.allDay && event1.allDay) {
|
||||
event.startDate.compareTo(event1.startDate)
|
||||
} else if (event.allDay) {
|
||||
1
|
||||
} else if (event1.allDay) {
|
||||
-1
|
||||
} else {
|
||||
event1.startDate.compareTo(event.startDate)
|
||||
}
|
||||
})
|
||||
eventList.reverse()
|
||||
Log.d("ciao", "list: $eventList")
|
||||
eventRepository.saveEvents(
|
||||
eventList
|
||||
)
|
||||
eventRepository.saveNextEventData(
|
||||
eventList[0]
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eventRepository.resetNextEventData()
|
||||
}
|
||||
|
||||
UpdatesReceiver.setUpdates(context)
|
||||
MainWidget.updateWidget(context)
|
||||
|
||||
EventBus.getDefault().post(MainActivity.UpdateUiMessageEvent())
|
||||
}
|
||||
|
||||
fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> {
|
||||
val calendarList = ArrayList<me.everything.providers.android.calendar.Calendar>()
|
||||
|
||||
if (!context.checkGrantedPermission(
|
||||
Manifest.permission.READ_CALENDAR
|
||||
)
|
||||
) {
|
||||
return calendarList
|
||||
}
|
||||
val provider = CalendarProvider(context)
|
||||
val data = provider.calendars
|
||||
return if (data != null) {
|
||||
data.list
|
||||
} else {
|
||||
calendarList
|
||||
}
|
||||
}
|
||||
|
||||
fun getFilteredCalendarIdList(): List<Long> {
|
||||
return Preferences.calendarFilter.split(",").map { it.replace(" ", "") }.filter { it != "" }.map { it.toLong() }
|
||||
}
|
||||
|
||||
fun filterCalendar(list: List<Long>) {
|
||||
Preferences.calendarFilter = list.joinToString(separator = ",", prefix = " ")
|
||||
}
|
||||
|
||||
fun setEventUpdatesAndroidN(context: Context) {
|
||||
EventListenerJob.schedule(context)
|
||||
}
|
||||
|
||||
fun removeEventUpdatesAndroidN(context: Context) {
|
||||
EventListenerJob.remove(context)
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.graphics.Color
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
|
||||
object ColorHelper {
|
||||
fun getFontColor(): Int {
|
||||
return try {
|
||||
Color.parseColor(Preferences.textGlobalColor)
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#FFFFFF")
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.isColorDark(threshold: Double = 0.5): Boolean {
|
||||
if (this == Color.TRANSPARENT) {
|
||||
return false
|
||||
}
|
||||
val darkness =
|
||||
1 - (0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255
|
||||
return darkness >= threshold
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.text.format.DateUtils
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
||||
import java.lang.Exception
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
object DateHelper {
|
||||
fun getDateText(context: Context, date: Calendar): String {
|
||||
return if (Preferences.dateFormat != "") {
|
||||
try {
|
||||
SimpleDateFormat(Preferences.dateFormat, Locale.getDefault()).format(date.time)
|
||||
} catch (e: Exception) {
|
||||
getDefaultDateText(context, date)
|
||||
}
|
||||
} else {
|
||||
val flags: Int =
|
||||
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||
"%s, %s".format(
|
||||
SimpleDateFormat("EEEE", Locale.getDefault()).format(date.time),
|
||||
DateUtils.formatDateTime(context, date.timeInMillis, flags)
|
||||
).getCapWordString()
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
SimpleDateFormat("EEEE", Locale.getDefault()).format(date.time),
|
||||
DateUtils.formatDateTime(context, date.timeInMillis, flags)
|
||||
).getCapWordString()
|
||||
}
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.provider.AlarmClock
|
||||
import android.provider.CalendarContract
|
||||
import android.provider.CalendarContract.Events
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
|
||||
|
||||
object IntentHelper {
|
||||
|
||||
fun getGoogleMapsIntentFromAddress(context: Context, address:String): Intent {
|
||||
val gmmIntentUri: Uri = Uri.parse("geo:0,0?q=$address")
|
||||
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
||||
mapIntent.`package` = "com.google.android.apps.maps"
|
||||
|
||||
return if (mapIntent.resolveActivity(context.packageManager) != null) {
|
||||
mapIntent
|
||||
} else {
|
||||
val map = "http://maps.google.co.in/maps?q=$address"
|
||||
val i = Intent(Intent.ACTION_VIEW, Uri.parse(map));
|
||||
i
|
||||
}
|
||||
}
|
||||
|
||||
fun getCalendarIntent(context: Context): Intent {
|
||||
return when (Preferences.calendarAppPackage) {
|
||||
"" -> {
|
||||
Intent(Intent.ACTION_MAIN).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
addCategory(Intent.CATEGORY_APP_CALENDAR)
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Intent(Intent.ACTION_MAIN).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
addCategory(Intent.CATEGORY_APP_CALENDAR)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getWeatherIntent(context: Context): Intent {
|
||||
return when (Preferences.weatherAppPackage) {
|
||||
"" -> {
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
addCategory(Intent.CATEGORY_DEFAULT)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
data = Uri.parse("dynact://velour/weather/ProxyActivity")
|
||||
component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.weatherAppPackage)!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
addCategory(Intent.CATEGORY_DEFAULT)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
data = Uri.parse("dynact://velour/weather/ProxyActivity")
|
||||
component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getEventIntent(context: Context, e: Event): Intent {
|
||||
return when (Preferences.eventAppPackage) {
|
||||
"" -> {
|
||||
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = uri
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.eventAppPackage)!!.apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
data = uri
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = uri
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getClockIntent(context: Context): Intent {
|
||||
return when (Preferences.clockAppPackage) {
|
||||
"" -> {
|
||||
Intent(AlarmClock.ACTION_SHOW_ALARMS).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.clockAppPackage)!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Intent(AlarmClock.ACTION_SHOW_ALARMS).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.text.format.DateUtils
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import org.joda.time.DateTime
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
object SettingsStringHelper {
|
||||
|
||||
|
||||
fun getRefreshPeriodString(period: Int): Int {
|
||||
return when (period) {
|
||||
0 -> R.string.settings_weather_refresh_period_subtitle_0
|
||||
1 -> R.string.settings_weather_refresh_period_subtitle_1
|
||||
2 -> R.string.settings_weather_refresh_period_subtitle_2
|
||||
3 -> R.string.settings_weather_refresh_period_subtitle_3
|
||||
4 -> R.string.settings_weather_refresh_period_subtitle_4
|
||||
5 -> R.string.settings_weather_refresh_period_subtitle_5
|
||||
else -> R.string.settings_weather_refresh_period_subtitle_0
|
||||
}
|
||||
}
|
||||
|
||||
fun getShowUntilString(period: Int): Int {
|
||||
return when (period) {
|
||||
0 -> R.string.settings_show_until_subtitle_0
|
||||
1 -> R.string.settings_show_until_subtitle_1
|
||||
2 -> R.string.settings_show_until_subtitle_2
|
||||
3 -> R.string.settings_show_until_subtitle_3
|
||||
4 -> R.string.settings_show_until_subtitle_4
|
||||
5 -> R.string.settings_show_until_subtitle_5
|
||||
6 -> R.string.settings_show_until_subtitle_6
|
||||
7 -> R.string.settings_show_until_subtitle_7
|
||||
else -> R.string.settings_show_until_subtitle_1
|
||||
}
|
||||
}
|
||||
|
||||
fun getSecondRowInfoString(info: Int): Int {
|
||||
return when (info) {
|
||||
0 -> R.string.settings_second_row_info_subtitle_0
|
||||
1 -> R.string.settings_second_row_info_subtitle_1
|
||||
2 -> R.string.settings_second_row_info_subtitle_2
|
||||
else -> R.string.settings_second_row_info_subtitle_0
|
||||
}
|
||||
}
|
||||
|
||||
fun getTextShadowString(shadow: Int): Int {
|
||||
return when (shadow) {
|
||||
0 -> R.string.settings_text_shadow_subtitle_none
|
||||
1 -> R.string.settings_text_shadow_subtitle_low
|
||||
2 -> R.string.settings_text_shadow_subtitle_high
|
||||
else -> R.string.settings_text_shadow_subtitle_low
|
||||
}
|
||||
}
|
||||
|
||||
fun getCustomFontLabel(shadow: Int): Int {
|
||||
return when (shadow) {
|
||||
0 -> R.string.custom_font_subtitle_0
|
||||
1 -> R.string.custom_font_subtitle_1
|
||||
else -> R.string.custom_font_subtitle_1
|
||||
}
|
||||
}
|
||||
|
||||
fun getDifferenceText(context: Context, now: Long, start: Long): String {
|
||||
val nowDate = DateTime(now)
|
||||
val eventDate = DateTime(start)
|
||||
|
||||
var difference = start - now
|
||||
difference += 60 * 1000 - (difference % (60 * 1000))
|
||||
|
||||
when {
|
||||
difference <= 0 || TimeUnit.MILLISECONDS.toHours(difference) < 1 -> {
|
||||
return ""
|
||||
}
|
||||
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS).toString()
|
||||
}
|
||||
eventDate.dayOfYear == nowDate.plusDays(1).dayOfYear -> {
|
||||
return String.format("%s", context.getString(R.string.tomorrow))
|
||||
}
|
||||
eventDate.dayOfYear == nowDate.dayOfYear -> {
|
||||
return String.format("%s", context.getString(R.string.today))
|
||||
}
|
||||
else -> {
|
||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.DAY_IN_MILLIS).toString()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getAllDayEventDifferenceText(context: Context, now: Long, start: Long): String {
|
||||
val nowDate = DateTime(now)
|
||||
val eventDate = DateTime(start)
|
||||
|
||||
var difference = start - now
|
||||
difference += 60 * 1000 - (difference % (60 * 1000))
|
||||
|
||||
return when (eventDate.dayOfYear) {
|
||||
nowDate.dayOfYear -> {
|
||||
""
|
||||
}
|
||||
nowDate.plusDays(1).dayOfYear -> {
|
||||
String.format("%s", context.getString(R.string.tomorrow))
|
||||
}
|
||||
else -> {
|
||||
DateUtils.getRelativeTimeSpanString(start, now, DateUtils.DAY_IN_MILLIS).toString()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getEmojiByUnicode(unicode: Int): String {
|
||||
return String(Character.toChars(unicode))
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.tommasoberlose.anotherwidget.utils
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.content.Context
|
||||
import com.google.android.gms.location.LocationServices
|
||||
@ -8,56 +8,34 @@ import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeathe
|
||||
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
|
||||
|
||||
/**
|
||||
* Created by tommaso on 08/10/17.
|
||||
*/
|
||||
|
||||
object WeatherUtil {
|
||||
object WeatherHelper {
|
||||
|
||||
fun updateWeather(context: Context) {
|
||||
val networkApi = WeatherNetworkApi(context)
|
||||
if (Preferences.customLocationAdd != "") {
|
||||
weatherNetworkRequest(
|
||||
context
|
||||
)
|
||||
networkApi.updateWeather()
|
||||
} else {
|
||||
LocationServices.getFusedLocationProviderClient(context).lastLocation.addOnSuccessListener {
|
||||
Preferences.customLocationLat = it.latitude.toString()
|
||||
Preferences.customLocationLon = it.longitude.toString()
|
||||
|
||||
weatherNetworkRequest(context)
|
||||
networkApi.updateWeather()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun weatherNetworkRequest(context: Context) {
|
||||
if (Preferences.showWeather && Preferences.weatherProviderApi != "" && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") {
|
||||
val helper = OpenWeatherMapHelper(Preferences.weatherProviderApi)
|
||||
helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC)
|
||||
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object : CurrentWeatherCallback {
|
||||
override fun onSuccess(currentWeather: CurrentWeather?) {
|
||||
currentWeather?.let {
|
||||
Preferences.weatherTemp = currentWeather.main.temp.toFloat()
|
||||
Preferences.weatherIcon = currentWeather.weather[0].icon
|
||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||
Util.updateWidget(context)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(throwable: Throwable?) {
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
removeWeather(context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeWeather(context: Context) {
|
||||
fun removeWeather(context: Context) {
|
||||
Preferences.remove(Preferences::weatherTemp)
|
||||
Preferences.remove(Preferences::weatherTempUnit)
|
||||
Util.updateWidget(context)
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
fun getWeatherIconResource(icon: String): Int {
|
@ -0,0 +1,16 @@
|
||||
package com.tommasoberlose.anotherwidget.models
|
||||
|
||||
/**
|
||||
* Created by tommaso on 08/10/17.
|
||||
*/
|
||||
class CalendarSelector(id: Long, name: String?, accountName: String?) {
|
||||
var id: Long = 0
|
||||
var name: String = ""
|
||||
var accountName: String = ""
|
||||
|
||||
init {
|
||||
this.id = id
|
||||
this.name = name ?: ""
|
||||
this.accountName = accountName ?: ""
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.tommasoberlose.anotherwidget.components.events
|
||||
package com.tommasoberlose.anotherwidget.models
|
||||
|
||||
import io.realm.RealmObject
|
||||
import java.util.Date
|
@ -0,0 +1,44 @@
|
||||
package com.tommasoberlose.anotherwidget.network
|
||||
|
||||
import android.content.Context
|
||||
import com.kwabenaberko.openweathermaplib.constants.Units
|
||||
import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper
|
||||
import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeatherCallback
|
||||
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
class WeatherNetworkApi(val context: Context) {
|
||||
fun updateWeather() {
|
||||
if (Preferences.showWeather && Preferences.weatherProviderApi != "" && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") {
|
||||
val helper = OpenWeatherMapHelper(Preferences.weatherProviderApi)
|
||||
helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC)
|
||||
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object :
|
||||
CurrentWeatherCallback {
|
||||
override fun onSuccess(currentWeather: CurrentWeather?) {
|
||||
currentWeather?.let {
|
||||
Preferences.weatherTemp = currentWeather.main.temp.toFloat()
|
||||
Preferences.weatherIcon = currentWeather.weather[0].icon
|
||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||
MainWidget.updateWidget(
|
||||
context
|
||||
)
|
||||
|
||||
EventBus.getDefault().post(MainActivity.UpdateUiMessageEvent())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(throwable: Throwable?) {
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
WeatherHelper.removeWeather(
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -4,22 +4,25 @@ import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.utils.CalendarUtil
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
|
||||
class NewCalendarEventReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
when {
|
||||
intent.action.equals(Intent.ACTION_PROVIDER_CHANGED) -> {
|
||||
CalendarUtil.updateEventList(context)
|
||||
val eventRepository = EventRepository(context)
|
||||
Log.d("ciao", "nuovo evento")
|
||||
when (intent.action) {
|
||||
Intent.ACTION_PROVIDER_CHANGED,
|
||||
Intent.ACTION_TIME_CHANGED -> {
|
||||
CalendarHelper.updateEventList(context)
|
||||
}
|
||||
intent.action == Actions.ACTION_GO_TO_NEXT_EVENT -> {
|
||||
CalendarUtil.goToNextEvent(context)
|
||||
Actions.ACTION_GO_TO_NEXT_EVENT -> {
|
||||
eventRepository.goToNextEvent()
|
||||
}
|
||||
intent.action == Actions.ACTION_GO_TO_PREVIOUS_EVENT -> {
|
||||
CalendarUtil.goToPreviousEvent(context)
|
||||
Actions.ACTION_GO_TO_PREVIOUS_EVENT -> {
|
||||
eventRepository.goToPreviousEvent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,13 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import com.tommasoberlose.anotherwidget.components.events.Event
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.utils.CalendarUtil
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import org.joda.time.Period
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
@ -20,11 +21,11 @@ class UpdatesReceiver : BroadcastReceiver() {
|
||||
when (intent.action) {
|
||||
Intent.ACTION_BOOT_COMPLETED,
|
||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||
Actions.ACTION_CALENDAR_UPDATE -> CalendarUtil.updateEventList(context)
|
||||
Actions.ACTION_CALENDAR_UPDATE -> CalendarHelper.updateEventList(context)
|
||||
|
||||
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
||||
Intent.ACTION_DATE_CHANGED,
|
||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED -> Util.updateWidget(context)
|
||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED -> MainWidget.updateWidget(context)
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,8 +33,9 @@ class UpdatesReceiver : BroadcastReceiver() {
|
||||
fun setUpdates(context: Context) {
|
||||
removeUpdates(context)
|
||||
|
||||
val eventRepository = EventRepository(context)
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
CalendarUtil.getEvents().forEach { event ->
|
||||
eventRepository.getEvents().forEach { event ->
|
||||
val hoursDiff = Period(Calendar.getInstance().timeInMillis, event.startDate).hours
|
||||
|
||||
// Update the widget every hour till the event
|
||||
|
@ -7,18 +7,19 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.utils.WeatherUtil
|
||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||
import java.util.*
|
||||
|
||||
|
||||
class WeatherReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action == Intent.ACTION_BOOT_COMPLETED || intent.action == Intent.ACTION_MY_PACKAGE_REPLACED) {
|
||||
setUpdates(context)
|
||||
} else if (intent.action == Actions.ACTION_WEATHER_UPDATE) {
|
||||
WeatherUtil.updateWeather(context)
|
||||
when (intent.action) {
|
||||
Intent.ACTION_BOOT_COMPLETED,
|
||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
|
||||
|
||||
Actions.ACTION_WEATHER_UPDATE -> WeatherHelper.updateWeather(context)
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +28,7 @@ class WeatherReceiver : BroadcastReceiver() {
|
||||
removeUpdates(context)
|
||||
|
||||
if (Preferences.showWeather && Preferences.weatherProviderApi != "") {
|
||||
WeatherUtil.updateWeather(context)
|
||||
WeatherHelper.updateWeather(context)
|
||||
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
val pi = PendingIntent.getBroadcast(
|
||||
|
@ -5,8 +5,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
||||
|
||||
|
||||
class WidgetClickListenerReceiver : BroadcastReceiver() {
|
||||
@ -15,10 +14,10 @@ class WidgetClickListenerReceiver : BroadcastReceiver() {
|
||||
if (intent.action == Actions.ACTION_OPEN_WEATHER_INTENT) {
|
||||
context.sendBroadcast(Intent(Actions.ACTION_WEATHER_UPDATE))
|
||||
try {
|
||||
context.startActivity(Util.getWeatherIntent(context))
|
||||
context.startActivity(IntentHelper.getWeatherIntent(context))
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
context.applicationContext.startActivity(Util.getWeatherIntent(context.applicationContext))
|
||||
context.applicationContext.startActivity(IntentHelper.getWeatherIntent(context.applicationContext))
|
||||
} catch (e: Exception) {
|
||||
val uri = Uri.parse("http://www.google.com/#q=weather")
|
||||
val i = Intent(Intent.ACTION_VIEW, uri)
|
||||
|
@ -0,0 +1,55 @@
|
||||
package com.tommasoberlose.anotherwidget.services
|
||||
|
||||
import android.app.job.JobInfo
|
||||
import android.app.job.JobInfo.TriggerContentUri
|
||||
import android.app.job.JobParameters
|
||||
import android.app.job.JobScheduler
|
||||
import android.app.job.JobService
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.provider.CalendarContract
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
|
||||
|
||||
class EventListenerJob : JobService() {
|
||||
override fun onStartJob(params: JobParameters): Boolean {
|
||||
CalendarHelper.updateEventList(this)
|
||||
schedule(
|
||||
this
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onStopJob(params: JobParameters): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val jobId = 1005
|
||||
fun schedule(context: Context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val componentName = ComponentName(
|
||||
context,
|
||||
EventListenerJob::class.java
|
||||
)
|
||||
with(context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler) {
|
||||
schedule(
|
||||
JobInfo.Builder(jobId, componentName)
|
||||
.addTriggerContentUri(TriggerContentUri(
|
||||
CalendarContract.CONTENT_URI,
|
||||
TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS
|
||||
))
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun remove(context: Context) {
|
||||
val js = context.getSystemService(JobScheduler::class.java)
|
||||
js?.cancel(jobId)
|
||||
}
|
||||
}
|
||||
}
|
@ -3,33 +3,22 @@ package com.tommasoberlose.anotherwidget.ui.activities
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import com.tommasoberlose.anotherwidget.components.events.ApplicationListEvent
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.databinding.Observable
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.transition.MaterialFadeThrough
|
||||
import com.tommasoberlose.anotherwidget.components.events.AppInfoSavedEvent
|
||||
import com.bumptech.glide.Glide
|
||||
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentClockSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.toast
|
||||
import kotlinx.android.synthetic.main.activity_choose_application.*
|
||||
import kotlinx.android.synthetic.main.activity_choose_application.list_view
|
||||
import kotlinx.coroutines.*
|
||||
@ -71,14 +60,16 @@ class ChooseApplicationActivity : AppCompatActivity() {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
.register<ApplicationInfo>(R.layout.application_info_layout) { item, injector ->
|
||||
.register<ResolveInfo>(R.layout.application_info_layout) { item, injector ->
|
||||
injector
|
||||
.text(R.id.text, pm.getApplicationLabel(item).toString())
|
||||
|
||||
try {
|
||||
injector.image(R.id.icon, item.loadIcon(pm))
|
||||
} catch (ignore: Exception) {
|
||||
}
|
||||
.text(R.id.text, item.loadLabel(pm))
|
||||
.with<ImageView>(R.id.icon) {
|
||||
Glide
|
||||
.with(this)
|
||||
.load(item.loadIcon(pm))
|
||||
.centerCrop()
|
||||
.into(it)
|
||||
}
|
||||
|
||||
injector.clicked(R.id.item) {
|
||||
saveApp(item)
|
||||
@ -110,9 +101,7 @@ class ChooseApplicationActivity : AppCompatActivity() {
|
||||
viewModel.appList.value!!
|
||||
} else {
|
||||
viewModel.appList.value!!.filter {
|
||||
pm.getApplicationLabel(
|
||||
it
|
||||
).toString().contains(search, true)
|
||||
it.loadLabel(pm).contains(search, true)
|
||||
}
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
@ -130,10 +119,10 @@ class ChooseApplicationActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveApp(app: ApplicationInfo) {
|
||||
private fun saveApp(app: ResolveInfo) {
|
||||
val resultIntent = Intent()
|
||||
resultIntent.putExtra(Constants.RESULT_APP_NAME, pm.getApplicationLabel(app).toString())
|
||||
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, app.packageName)
|
||||
resultIntent.putExtra(Constants.RESULT_APP_NAME, app.loadLabel(pm))
|
||||
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, app.resolvePackageName)
|
||||
setResult(Activity.RESULT_OK, resultIntent)
|
||||
finish()
|
||||
}
|
||||
|
@ -0,0 +1,124 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.location.Address
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.chibatching.kotpref.bulk
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
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.openURI
|
||||
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
|
||||
import kotlinx.coroutines.*
|
||||
import net.idik.lib.slimadapter.SlimAdapter
|
||||
import java.lang.Exception
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class CustomDateActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var adapter: SlimAdapter
|
||||
private lateinit var viewModel: CustomDateViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
viewModel = ViewModelProvider(this).get(CustomDateViewModel::class.java)
|
||||
val binding = DataBindingUtil.setContentView<ActivityCustomDateBinding>(this, R.layout.activity_custom_date)
|
||||
|
||||
|
||||
list_view.setHasFixedSize(true)
|
||||
val mLayoutManager = LinearLayoutManager(this)
|
||||
list_view.layoutManager = mLayoutManager
|
||||
|
||||
adapter = SlimAdapter.create()
|
||||
adapter
|
||||
.register<String>(R.layout.custom_date_example_item) { item, injector ->
|
||||
injector
|
||||
.text(R.id.custom_date_example_format, item)
|
||||
.text(R.id.custom_date_example_value, SimpleDateFormat(item, Locale.getDefault()).format(DATE.time))
|
||||
}
|
||||
.attachTo(list_view)
|
||||
|
||||
adapter.updateData(
|
||||
listOf(
|
||||
"d", "dd", "EE", "EEEE", "MM", "MMM", "MMMM", "yy", "yyyy"
|
||||
)
|
||||
)
|
||||
|
||||
setupListener()
|
||||
subscribeUi(binding, viewModel)
|
||||
|
||||
date_format.requestFocus()
|
||||
|
||||
}
|
||||
private var formatJob: Job? = null
|
||||
|
||||
private fun subscribeUi(binding: ActivityCustomDateBinding, viewModel: CustomDateViewModel) {
|
||||
binding.viewModel = viewModel
|
||||
|
||||
viewModel.dateInput.observe(this, Observer { dateFormat ->
|
||||
formatJob?.cancel()
|
||||
formatJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||
withContext(Dispatchers.Main) {
|
||||
loader.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
delay(200)
|
||||
val text = if (dateFormat != "") {
|
||||
try {
|
||||
SimpleDateFormat(dateFormat, Locale.getDefault()).format(DATE.time)
|
||||
} catch (e: Exception) {
|
||||
ERROR_STRING
|
||||
}
|
||||
} else {
|
||||
"__"
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
action_save.isVisible = text != ERROR_STRING
|
||||
loader.visibility = View.INVISIBLE
|
||||
date_format_value.text = text
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
action_back.setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
action_save.setOnClickListener {
|
||||
Preferences.dateFormat = viewModel.dateInput.value ?: ""
|
||||
finish()
|
||||
}
|
||||
|
||||
action_date_format_info.setOnClickListener {
|
||||
openURI("https://developer.android.com/reference/java/text/SimpleDateFormat")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ERROR_STRING = "--"
|
||||
val DATE: Calendar = Calendar.getInstance().apply {
|
||||
set(Calendar.MONTH, 10)
|
||||
set(Calendar.DAY_OF_MONTH, 1)
|
||||
set(Calendar.YEAR, 1993)
|
||||
}
|
||||
}
|
||||
}
|
@ -27,7 +27,6 @@ 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.components.events.CustomLocationEvent
|
||||
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
|
||||
import com.tommasoberlose.anotherwidget.databinding.ActivityCustomLocationBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
|
@ -2,37 +2,43 @@ package com.tommasoberlose.anotherwidget.ui.activities
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.view.View
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.widget.LinearLayout
|
||||
import android.view.View
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.helpers.BitmapHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.*
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.getCurrentWallpaper
|
||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.TheWidget
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
@ -62,19 +68,38 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
||||
}
|
||||
}.attach()
|
||||
|
||||
// Init clock
|
||||
clock.setTextColor(ColorHelper.getFontColor())
|
||||
clock.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
|
||||
clock.format12Hour = "hh:mm"
|
||||
clock.isVisible = Preferences.showClock
|
||||
|
||||
preview.layoutParams = preview.layoutParams.apply {
|
||||
height = 160.toPixel(this@MainActivity) + if (Preferences.showClock) 100.toPixel(this@MainActivity) else 0
|
||||
}
|
||||
|
||||
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
|
||||
subscribeUi(viewModel)
|
||||
updateUI()
|
||||
|
||||
CalendarHelper.updateEventList(this)
|
||||
WeatherHelper.updateWeather(this)
|
||||
}
|
||||
|
||||
private var uiJob: Job? = null
|
||||
|
||||
private fun updateUI() {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val generatedView = TheWidget.generateWidgetView(this@MainActivity, preview.measuredWidth)
|
||||
generatedView.measure(0, 0)
|
||||
val bitmap = Util.getBitmapFromView(generatedView, generatedView.measuredWidth, generatedView.measuredHeight)
|
||||
preview.setCardBackgroundColor(getColor(if (ColorHelper.getFontColor().isColorDark()) android.R.color.white else R.color.colorAccent))
|
||||
val generatedView = MainWidget.generateWidgetView(this@MainActivity)
|
||||
generatedView.measure(0, 0)
|
||||
preview.measure(0, 0)
|
||||
|
||||
uiJob?.cancel()
|
||||
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||
val bitmap = BitmapHelper.getBitmapFromView(generatedView, if (preview.width > 0) preview.width else generatedView.measuredWidth, generatedView.measuredHeight)
|
||||
withContext(Dispatchers.Main) {
|
||||
// Clock
|
||||
clock.setTextColor(Util.getFontColor())
|
||||
clock.setTextColor(ColorHelper.getFontColor())
|
||||
clock.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
|
||||
clock.format12Hour = "hh:mm"
|
||||
|
||||
@ -112,7 +137,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
||||
}.start()
|
||||
|
||||
ValueAnimator.ofInt(
|
||||
preview.measuredHeight,
|
||||
preview.height,
|
||||
160.toPixel(this@MainActivity) + if (Preferences.showClock) 100.toPixel(this@MainActivity) else 0
|
||||
).apply {
|
||||
duration = 500L
|
||||
@ -126,14 +151,20 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
||||
}
|
||||
|
||||
widget_bitmap.setImageBitmap(bitmap)
|
||||
widget_loader.animate().scaleX(0f).scaleY(0f).start()
|
||||
widget.animate().alpha(1f).start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun subscribeUi(viewModel: MainViewModel) {
|
||||
viewModel.showWallpaper.observe(this, Observer {
|
||||
widget_bg.setImageDrawable(if (it) Util.getCurrentWallpaper(this) else null)
|
||||
widget_bg.setImageDrawable(if (it) getCurrentWallpaper() else null)
|
||||
})
|
||||
|
||||
logo.setOnClickListener {
|
||||
// startActivity(Intent(this, SupportDevActivity::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
@ -171,11 +202,6 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
||||
if (extras.containsKey(Actions.ACTION_EXTRA_OPEN_WEATHER_PROVIDER)) {
|
||||
startActivityForResult(Intent(this, WeatherProviderActivity::class.java), RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code)
|
||||
}
|
||||
if (extras.containsKey(Actions.ACTION_EXTRA_DISABLE_GPS_NOTIFICATION)) {
|
||||
Preferences.showGpsInformation = false
|
||||
sendBroadcast(Intent(Actions.ACTION_WEATHER_UPDATE))
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,6 +219,23 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
||||
|
||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
||||
updateUI()
|
||||
Util.updateWidget(this)
|
||||
MainWidget.updateWidget(this)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
EventBus.getDefault().register(this)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
|
||||
class UpdateUiMessageEvent
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onMessageEvent(ignore: UpdateUiMessageEvent?) {
|
||||
updateUI()
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.content.Intent
|
||||
import android.location.Address
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
@ -26,7 +27,6 @@ import net.idik.lib.slimadapter.SlimAdapter
|
||||
|
||||
class SupportDevActivity : AppCompatActivity(), PurchasesUpdatedListener {
|
||||
|
||||
private val BILLING_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAox5CcxuoLJ6CmNS7s6lVQzJ253njKKGF8MoQ/gQ5gEw2Fr03fBvtHpiVMpnjhNLw5NMeIpzRvkVqeQ7BfkC7c0BLCJUqf/fFA11ArQe8na6QKt5O4d+v4sbHtP7mm3GQNPOBaqRzcpFZaiAbfk6mnalo+tzM47GXrQFt5bNSrMctCs7bbChqJfH2cyMW0F8DHWEEeO5xElBmH3lh4FVpwIUTPYJIV3n0yhE3qqRA0WXkDej66g/uAt/rebmMZLmwNwIive5cObU4o41YyKRv2wSAicrv3W40LftzXAOOordIbmzDFN8ksh3VrnESqwCDGG97nZVbPG/+3LD0xHWiRwIDAQAB"
|
||||
private lateinit var viewModel: SupportDevViewModel
|
||||
private lateinit var adapter: SlimAdapter
|
||||
|
||||
@ -35,7 +35,7 @@ class SupportDevActivity : AppCompatActivity(), PurchasesUpdatedListener {
|
||||
|
||||
viewModel = ViewModelProvider(this).get(SupportDevViewModel::class.java)
|
||||
viewModel.billingClient = BillingClient.newBuilder(this).enablePendingPurchases().setListener(this).build()
|
||||
val binding = DataBindingUtil.setContentView<ActivitySupportDevBinding>(this, R.layout.activity_support_dev)
|
||||
DataBindingUtil.setContentView<ActivitySupportDevBinding>(this, R.layout.activity_support_dev)
|
||||
|
||||
|
||||
list_view.setHasFixedSize(true)
|
||||
|
@ -1,21 +1,14 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.DialogInterface
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.Html
|
||||
import android.text.TextWatcher
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.utils.WeatherUtil
|
||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||
import kotlinx.android.synthetic.main.activity_weather_provider.*
|
||||
|
||||
@ -46,18 +39,4 @@ class WeatherProviderActivity : AppCompatActivity() {
|
||||
}
|
||||
api_key.editText?.setText(Preferences.weatherProviderApi)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (api_key.editText?.text.toString() == "") {
|
||||
AlertDialog.Builder(this)
|
||||
.setMessage(getString(R.string.error_weather_api_key))
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.yes) { _, _ ->
|
||||
super.onBackPressed()
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,23 +14,21 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
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.BuildConfig
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentAdvancedSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.SupportDevActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.CalendarUtil
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||
import kotlinx.android.synthetic.main.fragment_advanced_settings.*
|
||||
import kotlinx.coroutines.delay
|
||||
@ -57,7 +55,7 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||
val binding = DataBindingUtil.inflate<FragmentAdvancedSettingsBinding>(inflater, R.layout.fragment_advanced_settings, container, false)
|
||||
|
||||
subscribeUi(binding, viewModel)
|
||||
subscribeUi(viewModel)
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.viewModel = viewModel
|
||||
@ -69,10 +67,11 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
setupListener()
|
||||
|
||||
app_version.text = "v%s".format(BuildConfig.VERSION_NAME)
|
||||
}
|
||||
|
||||
private fun subscribeUi(
|
||||
binding: FragmentAdvancedSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
viewModel.darkThemePreference.observe(viewLifecycleOwner, Observer {
|
||||
@ -94,8 +93,8 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
private fun setupListener() {
|
||||
action_change_theme.setOnClickListener {
|
||||
maintainScrollPosition {
|
||||
BottomSheetMenu<Int>(requireContext())
|
||||
.selectResource(Preferences.darkThemePreference)
|
||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_theme_title))
|
||||
.setSelectedValue(Preferences.darkThemePreference)
|
||||
.addItem(
|
||||
getString(R.string.settings_subtitle_dark_theme_light),
|
||||
AppCompatDelegate.MODE_NIGHT_NO
|
||||
@ -116,11 +115,23 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
|
||||
action_show_wallpaper.setOnClickListener {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.showWallpaper) {
|
||||
Preferences.showWallpaper = false
|
||||
} else {
|
||||
requirePermission()
|
||||
}
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_title_show_wallpaper))
|
||||
.setSelectedValue(Preferences.showWallpaper)
|
||||
.addItem(
|
||||
getString(R.string.settings_visible),
|
||||
true
|
||||
)
|
||||
.addItem(
|
||||
getString(R.string.settings_not_visible),
|
||||
false
|
||||
)
|
||||
.addOnSelectItemListener { value ->
|
||||
if (value) {
|
||||
requirePermission()
|
||||
} else {
|
||||
Preferences.showWallpaper = value
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,8 +148,8 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
action_refresh_widget.setOnClickListener {
|
||||
Util.updateWidget(requireContext())
|
||||
CalendarUtil.updateEventList(requireContext())
|
||||
MainWidget.updateWidget(requireContext())
|
||||
CalendarHelper.updateEventList(requireContext())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,12 +4,11 @@ import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.SimpleAdapter
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
@ -25,7 +24,7 @@ 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.CalendarSelector
|
||||
import com.tommasoberlose.anotherwidget.models.CalendarSelector
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentCalendarSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
@ -33,16 +32,19 @@ import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.CalendarUtil
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.DateHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.CustomDateActivity
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.toast
|
||||
import kotlinx.android.synthetic.main.fragment_calendar_settings.*
|
||||
import kotlinx.android.synthetic.main.fragment_calendar_settings.scrollView
|
||||
import kotlinx.android.synthetic.main.fragment_weather_settings.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.Comparator
|
||||
|
||||
class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
@ -85,6 +87,12 @@ class CalendarSettingsFragment : Fragment() {
|
||||
viewModel.showEvents.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
binding.isCalendarEnabled = it
|
||||
|
||||
if (it) {
|
||||
CalendarHelper.setEventUpdatesAndroidN(requireContext())
|
||||
} else {
|
||||
CalendarHelper.removeEventUpdatesAndroidN(requireContext())
|
||||
}
|
||||
}
|
||||
checkReadEventsPermission()
|
||||
})
|
||||
@ -106,7 +114,7 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
viewModel.secondRowInformation.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
second_row_info_label.text = getString(Util.getSecondRowInfoString(it))
|
||||
second_row_info_label.text = getString(SettingsStringHelper.getSecondRowInfoString(it))
|
||||
}
|
||||
})
|
||||
|
||||
@ -118,23 +126,18 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
viewModel.showUntil.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_until_label.text = getString(Util.getShowUntilString(it))
|
||||
show_until_label.text = getString(SettingsStringHelper.getShowUntilString(it))
|
||||
}
|
||||
checkReadEventsPermission()
|
||||
})
|
||||
|
||||
viewModel.showNextEvent.observe(viewLifecycleOwner, Observer {
|
||||
show_multiple_events_label.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
show_multiple_events_label.setTextKeepState(if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible))
|
||||
})
|
||||
|
||||
viewModel.dateFormat.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
val now = Calendar.getInstance()
|
||||
var dateStringValue: String = String.format("%s%s", SimpleDateFormat(Constants.engDateFormat, Locale.getDefault()).format(now.time)[0].toUpperCase(), SimpleDateFormat(Constants.engDateFormat, Locale.getDefault()).format(now.time).substring(1))
|
||||
if (it) {
|
||||
dateStringValue = String.format("%s%s", SimpleDateFormat(Constants.itDateFormat, Locale.getDefault()).format(now.time)[0].toUpperCase(), SimpleDateFormat(Constants.itDateFormat, Locale.getDefault()).format(now.time).substring(1))
|
||||
}
|
||||
date_format_label.text = dateStringValue
|
||||
date_format_label.text = DateHelper.getDateText(requireContext(), Calendar.getInstance())
|
||||
}
|
||||
})
|
||||
|
||||
@ -159,26 +162,51 @@ class CalendarSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
action_filter_calendar.setOnClickListener {
|
||||
val calendarSelectorList: List<CalendarSelector> = CalendarUtil.getCalendarList(requireContext()).map { CalendarSelector(it.id.toInt(), it.displayName, it.accountName) }
|
||||
var calFiltered = Preferences.calendarFilter
|
||||
val calendarSelectorList: List<CalendarSelector> = CalendarHelper.getCalendarList(requireContext()).map {
|
||||
CalendarSelector(
|
||||
it.id,
|
||||
it.displayName,
|
||||
it.accountName
|
||||
)
|
||||
}.sortedWith(Comparator { cal1, cal2 ->
|
||||
when {
|
||||
cal1.accountName != cal2.accountName -> {
|
||||
cal1.accountName.compareTo(cal2.accountName)
|
||||
}
|
||||
cal1.accountName == cal1.name -> {
|
||||
-1
|
||||
}
|
||||
cal2.accountName == cal2.accountName -> {
|
||||
1
|
||||
}
|
||||
else -> {
|
||||
cal1.name.compareTo(cal2.name)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (calendarSelectorList.isNotEmpty()) {
|
||||
val calNames = calendarSelectorList.map { if (it.name == it.account_name) String.format("%s: %s", getString(R.string.main_calendar), it.name) else it.name }.toTypedArray()
|
||||
val calSelected = calendarSelectorList.map { !calFiltered.contains(" " + it.id.toString() + ",") }.toBooleanArray()
|
||||
val filteredCalendarIds = CalendarHelper.getFilteredCalendarIdList()
|
||||
val visibleCalendarIds = calendarSelectorList.map { it.id }.filter { id: Long -> !filteredCalendarIds.contains(id) }
|
||||
|
||||
AlertDialog.Builder(requireContext()).setTitle(getString(R.string.settings_filter_calendar_subtitle))
|
||||
.setMultiChoiceItems(calNames, calSelected) { _, item, isChecked ->
|
||||
val dialogItem: String = String.format(" %s%s", calendarSelectorList.get(item).id, ",")
|
||||
calFiltered = calFiltered.replace(dialogItem, "");
|
||||
if (!isChecked) {
|
||||
calFiltered += dialogItem
|
||||
}
|
||||
val dialog = BottomSheetMenu<Long>(requireContext(), header = getString(R.string.settings_filter_calendar_subtitle), isMultiSelection = true)
|
||||
.setSelectedValues(visibleCalendarIds)
|
||||
|
||||
calendarSelectorList.indices.forEach { index ->
|
||||
if (index == 0 || calendarSelectorList[index].accountName != calendarSelectorList[index - 1].accountName) {
|
||||
dialog.addItem(calendarSelectorList[index].accountName)
|
||||
}
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
|
||||
Preferences.calendarFilter = calFiltered
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
|
||||
dialog.addItem(
|
||||
if (calendarSelectorList[index].name == calendarSelectorList[index].accountName) getString(R.string.account_events) else calendarSelectorList[index].name,
|
||||
calendarSelectorList[index].id
|
||||
)
|
||||
}
|
||||
|
||||
dialog.addOnMultipleSelectItemListener { values ->
|
||||
CalendarHelper.filterCalendar(calendarSelectorList.map { it.id }.filter { !values.contains(it) })
|
||||
checkReadEventsPermission()
|
||||
}.show()
|
||||
} else {
|
||||
requireActivity().toast(getString(R.string.calendar_settings_list_error))
|
||||
}
|
||||
@ -186,7 +214,7 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
action_show_all_day.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.calendarAllDay)
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_all_day_title)).setSelectedValue(Preferences.calendarAllDay)
|
||||
.addItem(getString(R.string.settings_all_day_subtitle_visible), true)
|
||||
.addItem(getString(R.string.settings_all_day_subtitle_gone), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
@ -197,7 +225,7 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
action_show_declined_events.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.showDeclinedEvents)
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_declined_events_title)).setSelectedValue(Preferences.showDeclinedEvents)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
@ -208,7 +236,7 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
action_show_multiple_events.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.showNextEvent)
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_multiple_events_title)).setSelectedValue(Preferences.showNextEvent)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
@ -219,7 +247,7 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
action_show_diff_time.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.showDiffTime)
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_diff_time_title)).setSelectedValue(Preferences.showDiffTime)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
@ -230,9 +258,9 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
action_second_row_info.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
val dialog = BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.secondRowInformation)
|
||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_second_row_info_title)).setSelectedValue(Preferences.secondRowInformation)
|
||||
(0 .. 1).forEach {
|
||||
dialog.addItem(getString(Util.getSecondRowInfoString(it)), it)
|
||||
dialog.addItem(getString(SettingsStringHelper.getSecondRowInfoString(it)), it)
|
||||
}
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
Preferences.secondRowInformation = value
|
||||
@ -242,9 +270,9 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
action_show_until.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
val dialog = BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.showUntil)
|
||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_show_until_title)).setSelectedValue(Preferences.showUntil)
|
||||
intArrayOf(6,7,0,1,2,3,4,5).forEach {
|
||||
dialog.addItem(getString(Util.getShowUntilString(it)), it)
|
||||
dialog.addItem(getString(SettingsStringHelper.getShowUntilString(it)), it)
|
||||
}
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
Preferences.showUntil = value
|
||||
@ -252,6 +280,27 @@ class CalendarSettingsFragment : 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(requireActivity(), CustomDateActivity::class.java))
|
||||
} else {
|
||||
Preferences.dateFormat = value
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_event_app.setOnClickListener {
|
||||
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java), RequestCode.EVENT_APP_REQUEST_CODE.code)
|
||||
}
|
||||
@ -262,10 +311,10 @@ class CalendarSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun checkReadEventsPermission(showEvents: Boolean = Preferences.showEvents) {
|
||||
if (requireActivity().checkCallingOrSelfPermission(Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_GRANTED) {
|
||||
if (requireActivity().checkGrantedPermission(Manifest.permission.READ_CALENDAR)) {
|
||||
show_events_label.text = if (showEvents) getString(R.string.show_events_visible) else getString(R.string.show_events_not_visible)
|
||||
read_calendar_permission_alert_icon.isVisible = false
|
||||
CalendarUtil.updateEventList(requireContext())
|
||||
CalendarHelper.updateEventList(requireContext())
|
||||
} else {
|
||||
show_events_label.text = if (showEvents) getString(R.string.description_permission_calendar) else getString(R.string.show_events_not_visible)
|
||||
read_calendar_permission_alert_icon.isVisible = showEvents
|
||||
|
@ -3,10 +3,10 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
@ -15,7 +15,6 @@ import androidx.lifecycle.lifecycleScope
|
||||
import com.chibatching.kotpref.bulk
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentCalendarSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentClockSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
@ -23,8 +22,6 @@ import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.utils.toast
|
||||
import kotlinx.android.synthetic.main.fragment_clock_settings.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
@ -67,6 +64,11 @@ class ClockSettingsFragment : Fragment() {
|
||||
binding: FragmentClockSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
viewModel.showBigClockWarning.observe(viewLifecycleOwner, Observer {
|
||||
large_clock_warning.isVisible = it
|
||||
small_clock_warning.isVisible = !it
|
||||
})
|
||||
|
||||
viewModel.showClock.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_clock_label.text =
|
||||
@ -96,12 +98,16 @@ class ClockSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
action_hide_large_clock_warning.setOnClickListener {
|
||||
Preferences.showBigClockWarning = false
|
||||
}
|
||||
|
||||
action_show_clock.setOnClickListener {
|
||||
Preferences.showClock = !Preferences.showClock
|
||||
}
|
||||
|
||||
action_clock_text_size.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Float>(requireContext()).selectResource(Preferences.clockTextSize)
|
||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.settings_clock_text_size_title)).setSelectedValue(Preferences.clockTextSize)
|
||||
(46 downTo 28).filter { it % 2 == 0 }.forEach {
|
||||
dialog.addItem("${it}sp", it.toFloat())
|
||||
}
|
||||
@ -111,7 +117,7 @@ class ClockSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
action_show_next_alarm.setOnClickListener {
|
||||
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.showNextAlarm)
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.showNextAlarm)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
|
@ -13,20 +13,17 @@ import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentGeneralSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||
import com.tommasoberlose.anotherwidget.utils.toast
|
||||
import dev.sasikanth.colorsheet.ColorSheet
|
||||
import kotlinx.android.synthetic.main.fragment_general_settings.*
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
|
||||
|
||||
class GeneralSettingsFragment : Fragment() {
|
||||
@ -50,7 +47,7 @@ class GeneralSettingsFragment : Fragment() {
|
||||
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||
val binding = DataBindingUtil.inflate<FragmentGeneralSettingsBinding>(inflater, R.layout.fragment_general_settings, container, false)
|
||||
|
||||
subscribeUi(binding, viewModel)
|
||||
subscribeUi(viewModel)
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.viewModel = viewModel
|
||||
@ -66,7 +63,6 @@ class GeneralSettingsFragment : Fragment() {
|
||||
|
||||
|
||||
private fun subscribeUi(
|
||||
binding: FragmentGeneralSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
|
||||
@ -95,13 +91,13 @@ class GeneralSettingsFragment : Fragment() {
|
||||
|
||||
viewModel.textShadow.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
text_shadow_label.text = getString(Util.getTextShadowString(it))
|
||||
text_shadow_label.text = getString(SettingsStringHelper.getTextShadowString(it))
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.customFont.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
custom_font_label.text = getString(Util.getCustomFontLabel(it))
|
||||
custom_font_label.text = getString(SettingsStringHelper.getCustomFontLabel(it))
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -117,7 +113,7 @@ class GeneralSettingsFragment : Fragment() {
|
||||
|
||||
private fun setupListener() {
|
||||
action_main_text_size.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Float>(requireContext()).selectResource(Preferences.textMainSize)
|
||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_main_text_size)).setSelectedValue(Preferences.textMainSize)
|
||||
(32 downTo 20).filter { it % 2 == 0 }.forEach {
|
||||
dialog.addItem("${it}sp", it.toFloat())
|
||||
}
|
||||
@ -127,7 +123,7 @@ class GeneralSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
action_second_text_size.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Float>(requireContext()).selectResource(Preferences.textSecondSize)
|
||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_second_text_size)).setSelectedValue(Preferences.textSecondSize)
|
||||
(24 downTo 12).filter { it % 2 == 0 }.forEach {
|
||||
dialog.addItem("${it}sp", it.toFloat())
|
||||
}
|
||||
@ -143,21 +139,21 @@ class GeneralSettingsFragment : Fragment() {
|
||||
Preferences.textGlobalColor = "#FFFFFF"
|
||||
Color.parseColor(Preferences.textGlobalColor)
|
||||
}
|
||||
ColorSheet()
|
||||
.cornerRadius(16.toPixel(requireContext()))
|
||||
.colorPicker(
|
||||
BottomSheetColorPicker(requireContext(),
|
||||
colors = requireActivity().resources.getIntArray(R.array.grey),
|
||||
selectedColor = textColor,
|
||||
listener = { color ->
|
||||
Preferences.textGlobalColor = "#" + Integer.toHexString(color)
|
||||
})
|
||||
.show(requireActivity().supportFragmentManager)
|
||||
header = getString(R.string.settings_font_color_title),
|
||||
selected = textColor,
|
||||
onColorSelected = { color: Int ->
|
||||
val colorString = Integer.toHexString(color)
|
||||
Preferences.textGlobalColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||
}
|
||||
).show()
|
||||
}
|
||||
|
||||
action_text_shadow.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.textShadow)
|
||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.title_text_shadow)).setSelectedValue(Preferences.textShadow)
|
||||
(2 downTo 0).forEach {
|
||||
dialog.addItem(getString(Util.getTextShadowString(it)), it)
|
||||
dialog.addItem(getString(SettingsStringHelper.getTextShadowString(it)), it)
|
||||
}
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
Preferences.textShadow = value
|
||||
@ -165,9 +161,9 @@ class GeneralSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
action_custom_font.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.customFont)
|
||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_custom_font_title)).setSelectedValue(Preferences.customFont)
|
||||
(0..1).forEach {
|
||||
dialog.addItem(getString(Util.getCustomFontLabel(it)), it)
|
||||
dialog.addItem(getString(SettingsStringHelper.getCustomFontLabel(it)), it)
|
||||
}
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
Preferences.customFont = value
|
||||
|
@ -3,7 +3,6 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -26,13 +25,15 @@ import com.tommasoberlose.anotherwidget.databinding.FragmentWeatherSettingsBindi
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.CustomLocationActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.WeatherProviderActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import kotlinx.android.synthetic.main.fragment_weather_settings.*
|
||||
import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView
|
||||
import kotlinx.coroutines.delay
|
||||
@ -76,6 +77,10 @@ class WeatherSettingsFragment : Fragment() {
|
||||
binding: FragmentWeatherSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
viewModel.showWeatherWarning.observe(viewLifecycleOwner, Observer {
|
||||
weather_warning.isVisible = it
|
||||
})
|
||||
|
||||
viewModel.showWeather.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_weather_label.text =
|
||||
@ -113,7 +118,7 @@ class WeatherSettingsFragment : Fragment() {
|
||||
|
||||
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
label_weather_refresh_period.text = getString(Util.getRefreshPeriodString(it))
|
||||
label_weather_refresh_period.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
|
||||
}
|
||||
checkLocationPermission()
|
||||
})
|
||||
@ -127,7 +132,7 @@ class WeatherSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun checkLocationPermission() {
|
||||
if (requireActivity().checkCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||
if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||
location_permission_alert_icon.isVisible = false
|
||||
WeatherReceiver.setUpdates(requireContext())
|
||||
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
|
||||
@ -139,6 +144,9 @@ class WeatherSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
action_hide_weather_warning.setOnClickListener {
|
||||
Preferences.showWeatherWarning = false
|
||||
}
|
||||
|
||||
action_show_weather.setOnClickListener {
|
||||
Preferences.showWeather = !Preferences.showWeather
|
||||
@ -164,7 +172,7 @@ class WeatherSettingsFragment : Fragment() {
|
||||
|
||||
action_change_unit.setOnClickListener {
|
||||
if (Preferences.showWeather) {
|
||||
BottomSheetMenu<String>(requireContext()).selectResource(Preferences.weatherTempUnit)
|
||||
BottomSheetMenu<String>(requireContext(), header = getString(R.string.settings_unit_title)).setSelectedValue(Preferences.weatherTempUnit)
|
||||
.addItem(getString(R.string.fahrenheit), "F")
|
||||
.addItem(getString(R.string.celsius), "C")
|
||||
.addOnSelectItemListener { value ->
|
||||
@ -176,9 +184,9 @@ class WeatherSettingsFragment : Fragment() {
|
||||
action_weather_refresh_period.setOnClickListener {
|
||||
if (Preferences.showWeather) {
|
||||
val dialog =
|
||||
BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.weatherRefreshPeriod)
|
||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_weather_refresh_period_title)).setSelectedValue(Preferences.weatherRefreshPeriod)
|
||||
(5 downTo 0).forEach {
|
||||
dialog.addItem(getString(Util.getRefreshPeriodString(it)), it)
|
||||
dialog.addItem(getString(SettingsStringHelper.getRefreshPeriodString(it)), it)
|
||||
}
|
||||
dialog
|
||||
.addOnSelectItemListener { value ->
|
||||
@ -202,13 +210,14 @@ class WeatherSettingsFragment : Fragment() {
|
||||
when (requestCode) {
|
||||
Constants.RESULT_CODE_CUSTOM_LOCATION -> {
|
||||
WeatherReceiver.setUpdates(requireContext())
|
||||
checkLocationPermission()
|
||||
}
|
||||
RequestCode.WEATHER_APP_REQUEST_CODE.code -> {
|
||||
Preferences.bulk {
|
||||
weatherAppName = data?.getStringExtra(Constants.RESULT_APP_NAME) ?: getString(R.string.default_weather_app)
|
||||
weatherAppPackage = data?.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: ""
|
||||
}
|
||||
Util.updateWidget(requireContext())
|
||||
MainWidget.updateWidget(requireContext())
|
||||
}
|
||||
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
|
||||
WeatherReceiver.setOneTimeUpdate(requireContext())
|
||||
|
@ -1,17 +1,21 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import androidx.databinding.ObservableField
|
||||
import androidx.lifecycle.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import android.content.pm.ResolveInfo
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.liveData
|
||||
|
||||
class ChooseApplicationViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
val appList: LiveData<List<ApplicationInfo>> = liveData {
|
||||
val app = application.packageManager.getInstalledApplications(0)
|
||||
val appList: LiveData<List<ResolveInfo>> = liveData {
|
||||
val mainIntent = Intent(Intent.ACTION_MAIN, null).apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
val app = application.packageManager.queryIntentActivities( mainIntent, 0)
|
||||
emit(app)
|
||||
}
|
||||
val searchInput: MutableLiveData<String> = MutableLiveData("")
|
||||
|
@ -0,0 +1,10 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
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)
|
||||
}
|
@ -26,7 +26,6 @@ class MainViewModel : ViewModel() {
|
||||
|
||||
val eventAppName = Preferences.asLiveData(Preferences::eventAppName)
|
||||
|
||||
|
||||
// Clock Settings
|
||||
val showClock = Preferences.asLiveData(Preferences::showClock)
|
||||
val clockTextSize = Preferences.asLiveData(Preferences::clockTextSize)
|
||||
@ -35,6 +34,8 @@ class MainViewModel : ViewModel() {
|
||||
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
|
||||
val dateFormat = Preferences.asLiveData(Preferences::dateFormat)
|
||||
|
||||
val showBigClockWarning = Preferences.asLiveData(Preferences::showBigClockWarning)
|
||||
|
||||
// Weather Settings
|
||||
val showWeather = Preferences.asLiveData(Preferences::showWeather)
|
||||
val weatherTempUnit = Preferences.asLiveData(Preferences::weatherTempUnit)
|
||||
@ -45,6 +46,8 @@ class MainViewModel : ViewModel() {
|
||||
|
||||
val customLocationAdd = Preferences.asLiveData(Preferences::customLocationAdd)
|
||||
|
||||
val showWeatherWarning = Preferences.asLiveData(Preferences::showWeatherWarning)
|
||||
|
||||
// Advanced Settings
|
||||
val darkThemePreference = Preferences.asLiveData(Preferences::darkThemePreference)
|
||||
val showWallpaper = Preferences.asLiveData(Preferences::showWallpaper)
|
||||
|
@ -4,10 +4,10 @@ import android.Manifest
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
@ -22,25 +22,27 @@ import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.*
|
||||
import com.tommasoberlose.anotherwidget.receivers.NewCalendarEventReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
||||
import com.tommasoberlose.anotherwidget.utils.CalendarUtil
|
||||
import com.tommasoberlose.anotherwidget.utils.Util
|
||||
import com.tommasoberlose.anotherwidget.utils.WeatherUtil
|
||||
import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.convertSpToPixels
|
||||
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||
import kotlinx.android.synthetic.main.the_widget.view.*
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
class TheWidget : AppWidgetProvider() {
|
||||
class MainWidget : AppWidgetProvider() {
|
||||
|
||||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
||||
for (appWidgetId in appWidgetIds) {
|
||||
@ -54,8 +56,14 @@ class TheWidget : AppWidgetProvider() {
|
||||
}
|
||||
|
||||
override fun onEnabled(context: Context) {
|
||||
CalendarUtil.updateEventList(context)
|
||||
CalendarHelper.updateEventList(context)
|
||||
WeatherReceiver.setUpdates(context)
|
||||
|
||||
if (Preferences.showEvents) {
|
||||
CalendarHelper.setEventUpdatesAndroidN(context)
|
||||
} else {
|
||||
CalendarHelper.removeEventUpdatesAndroidN(context)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDisabled(context: Context) {
|
||||
@ -65,27 +73,37 @@ class TheWidget : AppWidgetProvider() {
|
||||
|
||||
companion object {
|
||||
|
||||
fun updateWidget(context: Context) {
|
||||
val widgetManager = AppWidgetManager.getInstance(context)
|
||||
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
||||
val widgetIds = widgetManager.getAppWidgetIds(widgetComponent)
|
||||
val update = Intent(context, MainWidget::class.java)
|
||||
update.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds)
|
||||
update.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||
context.sendBroadcast(update)
|
||||
}
|
||||
|
||||
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager,
|
||||
appWidgetId: Int) {
|
||||
val displayMetrics = Resources.getSystem().displayMetrics
|
||||
var height = 110.toPixel(context)
|
||||
val width = displayMetrics.widthPixels
|
||||
if (Preferences.showClock) {
|
||||
height += Util.convertSpToPixels(Preferences.clockTextSize, context).toInt() + 16.toPixel(context)
|
||||
height += Preferences.clockTextSize.convertSpToPixels(context).toInt() + 16.toPixel(context)
|
||||
}
|
||||
if (Preferences.textMainSize > 30 && Preferences.textSecondSize > 22) {
|
||||
height += 24.toPixel(context)
|
||||
}
|
||||
|
||||
generateWidgetView(context, appWidgetId, appWidgetManager, width - 16.toPixel(context), height)
|
||||
generateWidgetView(context, appWidgetId, appWidgetManager, width - 16.toPixel(context))
|
||||
}
|
||||
|
||||
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int, h: Int) {
|
||||
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int) {
|
||||
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
|
||||
|
||||
val generatedView = generateWidgetView(context, w)
|
||||
val generatedView = generateWidgetView(context)
|
||||
generatedView.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.bitmap_container, Util.getBitmapFromView(generatedView, w, generatedView.measuredHeight))
|
||||
views.setImageViewBitmap(R.id.bitmap_container, BitmapHelper.getBitmapFromView(generatedView, w - 32.toPixel(context), generatedView.measuredHeight))
|
||||
|
||||
// Clock
|
||||
views = updateClockView(context, views, appWidgetId)
|
||||
@ -98,29 +116,30 @@ class TheWidget : AppWidgetProvider() {
|
||||
}
|
||||
|
||||
private fun updateCalendarView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
|
||||
val eventRepository = EventRepository(context)
|
||||
|
||||
v.empty_date.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.empty_date_rect, Util.getBitmapFromView(v.empty_date))
|
||||
views.setImageViewBitmap(R.id.empty_date_rect, BitmapHelper.getBitmapFromView(v.empty_date))
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.second_row_rect, View.GONE)
|
||||
|
||||
val calPIntent = PendingIntent.getActivity(context, widgetID, Util.getCalendarIntent(context), 0)
|
||||
val calPIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getCalendarIntent(context), 0)
|
||||
views.setOnClickPendingIntent(R.id.empty_date_rect, calPIntent)
|
||||
|
||||
val nextEvent = CalendarUtil.getNextEvent()
|
||||
val nextAlarm = Util.getNextAlarm(context)
|
||||
val nextEvent = eventRepository.getNextEvent()
|
||||
val nextAlarm = AlarmHelper.getNextAlarm(context)
|
||||
|
||||
if (Preferences.showEvents && Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
||||
if (Preferences.showNextEvent && CalendarUtil.getEventsCount() > 1) {
|
||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
||||
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
|
||||
v.action_next.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.action_next_rect, Util.getBitmapFromView(v.action_next))
|
||||
views.setImageViewBitmap(R.id.action_next_rect, BitmapHelper.getBitmapFromView(v.action_next))
|
||||
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
|
||||
views.setOnClickPendingIntent(R.id.action_next_rect, PendingIntent.getBroadcast(context, widgetID, Intent(context, NewCalendarEventReceiver::class.java).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT }, 0))
|
||||
|
||||
v.action_previous.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.action_previous_rect, Util.getBitmapFromView(v.action_previous))
|
||||
views.setImageViewBitmap(R.id.action_previous_rect, BitmapHelper.getBitmapFromView(v.action_previous))
|
||||
views.setViewVisibility(R.id.action_previous_rect, View.VISIBLE)
|
||||
views.setOnClickPendingIntent(R.id.action_previous_rect, PendingIntent.getBroadcast(context, widgetID, Intent(context, NewCalendarEventReceiver::class.java).apply { action = Actions.ACTION_GO_TO_PREVIOUS_EVENT }, 0))
|
||||
} else {
|
||||
@ -128,44 +147,44 @@ class TheWidget : AppWidgetProvider() {
|
||||
views.setViewVisibility(R.id.action_previous_rect, View.GONE)
|
||||
}
|
||||
|
||||
val pIntent = PendingIntent.getActivity(context, widgetID, Util.getEventIntent(context, nextEvent), 0)
|
||||
val pIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getEventIntent(context, nextEvent), 0)
|
||||
views.setOnClickPendingIntent(R.id.next_event_rect, pIntent)
|
||||
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, pIntent)
|
||||
|
||||
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < nextEvent.startDate) {
|
||||
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
|
||||
v.next_event_difference_time.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.next_event_difference_time_rect, Util.getBitmapFromView(v.next_event_difference_time))
|
||||
views.setImageViewBitmap(R.id.next_event_difference_time_rect, BitmapHelper.getBitmapFromView(v.next_event_difference_time))
|
||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.VISIBLE)
|
||||
} else {
|
||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
|
||||
}
|
||||
|
||||
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
||||
val mapIntent = PendingIntent.getActivity(context, widgetID, Util.getGoogleMapsIntentFromAddress(context, nextEvent.address), 0)
|
||||
val mapIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address), 0)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, mapIntent)
|
||||
} else {
|
||||
views.setOnClickPendingIntent(R.id.next_event_rect, pIntent)
|
||||
}
|
||||
|
||||
v.next_event.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.next_event_rect, Util.getBitmapFromView(v.next_event))
|
||||
views.setImageViewBitmap(R.id.next_event_rect, BitmapHelper.getBitmapFromView(v.next_event))
|
||||
|
||||
|
||||
v.second_row.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.second_row_rect, Util.getBitmapFromView(v.second_row))
|
||||
views.setImageViewBitmap(R.id.second_row_rect, BitmapHelper.getBitmapFromView(v.second_row))
|
||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||
} else if (Preferences.secondRowInformation == 2 && nextAlarm != "") {
|
||||
val clockIntent = PendingIntent.getActivity(context, widgetID, Util.getClockIntent(context), 0)
|
||||
} else if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||
val clockIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getClockIntent(context), 0)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, clockIntent)
|
||||
|
||||
v.next_event.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.next_event_rect, Util.getBitmapFromView(v.next_event))
|
||||
views.setImageViewBitmap(R.id.next_event_rect, BitmapHelper.getBitmapFromView(v.next_event))
|
||||
|
||||
v.second_row.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.second_row_rect, Util.getBitmapFromView(v.second_row))
|
||||
views.setImageViewBitmap(R.id.second_row_rect, BitmapHelper.getBitmapFromView(v.second_row))
|
||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||
@ -189,10 +208,10 @@ class TheWidget : AppWidgetProvider() {
|
||||
views.setOnClickPendingIntent(R.id.calendar_weather_rect, weatherPIntent)
|
||||
|
||||
v.weather.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.weather_rect, Util.getBitmapFromView(v.weather))
|
||||
views.setImageViewBitmap(R.id.weather_rect, BitmapHelper.getBitmapFromView(v.weather))
|
||||
|
||||
v.calendar_weather.measure(0, 0)
|
||||
views.setImageViewBitmap(R.id.calendar_weather_rect, Util.getBitmapFromView(v.calendar_weather))
|
||||
views.setImageViewBitmap(R.id.calendar_weather_rect, BitmapHelper.getBitmapFromView(v.calendar_weather))
|
||||
} else {
|
||||
views.setViewVisibility(R.id.weather_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
|
||||
@ -204,9 +223,9 @@ class TheWidget : AppWidgetProvider() {
|
||||
if (!Preferences.showClock) {
|
||||
views.setViewVisibility(R.id.time, View.GONE)
|
||||
} else {
|
||||
views.setTextColor(R.id.time, Util.getFontColor())
|
||||
views.setTextColor(R.id.time, ColorHelper.getFontColor())
|
||||
views.setTextViewTextSize(R.id.time, TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(context))
|
||||
val clockPIntent = PendingIntent.getActivity(context, widgetID, Util.getClockIntent(context), 0)
|
||||
val clockPIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getClockIntent(context), 0)
|
||||
views.setOnClickPendingIntent(R.id.time, clockPIntent)
|
||||
views.setViewVisibility(R.id.time, View.VISIBLE)
|
||||
}
|
||||
@ -214,29 +233,42 @@ class TheWidget : AppWidgetProvider() {
|
||||
return views
|
||||
}
|
||||
|
||||
fun generateWidgetView(context: Context, maxWidth: Int): View {
|
||||
|
||||
// Generates the widget bitmap from the view
|
||||
fun generateWidgetView(context: Context): View {
|
||||
val eventRepository = EventRepository(context)
|
||||
val v = View.inflate(context, R.layout.the_widget, null)
|
||||
|
||||
val now = Calendar.getInstance()
|
||||
|
||||
v.empty_layout.visibility = View.VISIBLE
|
||||
v.calendar_layout.visibility = View.GONE
|
||||
v.action_next.isVisible = false
|
||||
v.action_previous.isVisible = false
|
||||
|
||||
val flags: Int = DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||
v.empty_date.text = Util.getCapWordString("${SimpleDateFormat("EEEE", Locale.getDefault()).format(now.time)}, ${DateUtils.formatDateTime(context, now.timeInMillis, flags)}")
|
||||
v.empty_date.text = DateHelper.getDateText(context, now)
|
||||
|
||||
val nextEvent = CalendarUtil.getNextEvent()
|
||||
val nextAlarm = Util.getNextAlarm(context)
|
||||
val nextEvent = eventRepository.getNextEvent()
|
||||
val nextAlarm = AlarmHelper.getNextAlarm(context)
|
||||
|
||||
if (Preferences.showEvents && Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
||||
// Multiple counter
|
||||
v.action_next.isVisible = Preferences.showNextEvent && CalendarUtil.getEventsCount() > 1
|
||||
v.action_previous.isVisible = Preferences.showNextEvent && CalendarUtil.getEventsCount() > 1
|
||||
v.action_next.isVisible = Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
||||
v.action_previous.isVisible = Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
||||
|
||||
v.next_event.text = nextEvent.title
|
||||
|
||||
if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
|
||||
v.next_event_difference_time.text = Util.getDifferenceText(context, now.timeInMillis, nextEvent.startDate).toLowerCase(Locale.getDefault())
|
||||
if (Preferences.showDiffTime && now.timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
|
||||
v.next_event_difference_time.text = if (!nextEvent.allDay) {
|
||||
SettingsStringHelper.getDifferenceText(
|
||||
context,
|
||||
now.timeInMillis,
|
||||
nextEvent.startDate
|
||||
)
|
||||
.toLowerCase(Locale.getDefault())
|
||||
} else {
|
||||
SettingsStringHelper.getAllDayEventDifferenceText(context, now.timeInMillis, nextEvent.startDate).toLowerCase(Locale.getDefault())
|
||||
}
|
||||
v.next_event_difference_time.visibility = View.VISIBLE
|
||||
} else {
|
||||
v.next_event_difference_time.visibility = View.GONE
|
||||
@ -271,21 +303,22 @@ class TheWidget : AppWidgetProvider() {
|
||||
v.next_event_date.text = String.format("%s - %s%s", startHour, endHour, multipleDay)
|
||||
|
||||
} else {
|
||||
v.next_event_date.text = Util.getCapWordString(DateUtils.formatDateTime(context, now.timeInMillis, flags))
|
||||
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.empty_layout.visibility = View.GONE
|
||||
v.calendar_layout.visibility = View.VISIBLE
|
||||
} else if (Preferences.secondRowInformation == 2 && nextAlarm != "") {
|
||||
} else if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||
v.second_row_icon.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
context,
|
||||
R.drawable.round_alarm
|
||||
)
|
||||
)
|
||||
v.next_event.text = Util.getCapWordString("${SimpleDateFormat("EEEE", Locale.getDefault()).format(now.time)}, ${DateUtils.formatDateTime(context, now.timeInMillis, flags)}")
|
||||
v.next_event_date.text = Util.getNextAlarm(context)
|
||||
v.next_event.text = DateHelper.getDateText(context, now)
|
||||
v.next_event_date.text = AlarmHelper.getNextAlarm(context)
|
||||
v.empty_layout.visibility = View.GONE
|
||||
v.calendar_layout.visibility = View.VISIBLE
|
||||
}
|
||||
@ -293,11 +326,11 @@ class TheWidget : 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).forEach {
|
||||
it.setTextColor(Util.getFontColor())
|
||||
it.setTextColor(ColorHelper.getFontColor())
|
||||
}
|
||||
|
||||
listOf<ImageView>(v.second_row_icon, v.action_next, v.action_previous).forEach {
|
||||
it.setColorFilter(Util.getFontColor())
|
||||
it.setColorFilter(ColorHelper.getFontColor())
|
||||
}
|
||||
|
||||
// Text Size
|
||||
@ -318,8 +351,8 @@ class TheWidget : AppWidgetProvider() {
|
||||
v.second_row_icon.scaleX = Preferences.textSecondSize / 18f
|
||||
v.second_row_icon.scaleY = Preferences.textSecondSize / 18f
|
||||
|
||||
v.weather_icon.scaleX = Preferences.textSecondSize / 18f
|
||||
v.weather_icon.scaleY = Preferences.textSecondSize / 18f
|
||||
v.weather_icon.scaleX = Preferences.textSecondSize / 16f
|
||||
v.weather_icon.scaleY = Preferences.textSecondSize / 16f
|
||||
|
||||
v.empty_weather_icon.scaleX = Preferences.textMainSize / 20f
|
||||
v.empty_weather_icon.scaleY = Preferences.textMainSize / 20f
|
||||
@ -374,8 +407,8 @@ class TheWidget : AppWidgetProvider() {
|
||||
v.weather_icon.visibility = View.GONE
|
||||
v.empty_weather_icon.visibility = View.GONE
|
||||
} else {
|
||||
v.weather_icon.setImageResource(WeatherUtil.getWeatherIconResource(icon))
|
||||
v.empty_weather_icon.setImageResource(WeatherUtil.getWeatherIconResource(icon))
|
||||
v.weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
||||
v.empty_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
||||
v.weather_icon.visibility = View.VISIBLE
|
||||
v.empty_weather_icon.visibility = View.VISIBLE
|
||||
}
|
||||
@ -387,9 +420,6 @@ class TheWidget : AppWidgetProvider() {
|
||||
v.calendar_weather.visibility = View.GONE
|
||||
}
|
||||
|
||||
// Apply max width
|
||||
v.main_layout.layoutParams = RelativeLayout.LayoutParams(maxWidth, RelativeLayout.LayoutParams.WRAP_CONTENT)
|
||||
|
||||
return v
|
||||
}
|
||||
}
|
@ -1,186 +0,0 @@
|
||||
package com.tommasoberlose.anotherwidget.utils
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.provider.CalendarContract
|
||||
import android.util.Log
|
||||
import com.chibatching.kotpref.blockingBulk
|
||||
import com.chibatching.kotpref.bulk
|
||||
import com.tommasoberlose.anotherwidget.components.events.Event
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmResults
|
||||
import me.everything.providers.android.calendar.CalendarProvider
|
||||
import java.util.*
|
||||
import kotlin.Comparator
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
/**
|
||||
* Created by tommaso on 08/10/17.
|
||||
*/
|
||||
|
||||
object CalendarUtil {
|
||||
|
||||
fun updateEventList(context: Context) {
|
||||
if (Preferences.showEvents) {
|
||||
val eventList = ArrayList<Event>()
|
||||
|
||||
val now = Calendar.getInstance()
|
||||
val limit = Calendar.getInstance()
|
||||
when (Preferences.showUntil) {
|
||||
0 -> limit.add(Calendar.HOUR, 3)
|
||||
1 -> limit.add(Calendar.HOUR, 6)
|
||||
2 -> limit.add(Calendar.HOUR, 12)
|
||||
3 -> limit.add(Calendar.DAY_OF_MONTH, 1)
|
||||
4 -> limit.add(Calendar.DAY_OF_MONTH, 3)
|
||||
5 -> limit.add(Calendar.DAY_OF_MONTH, 7)
|
||||
6 -> limit.add(Calendar.MINUTE, 30)
|
||||
7 -> limit.add(Calendar.HOUR, 1)
|
||||
else -> limit.add(Calendar.HOUR, 6)
|
||||
}
|
||||
|
||||
val builder = CalendarContract.Instances.CONTENT_URI.buildUpon()
|
||||
ContentUris.appendId(builder, now.timeInMillis)
|
||||
ContentUris.appendId(builder, limit.timeInMillis)
|
||||
|
||||
if (!Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR)) {
|
||||
resetNextEventData(context)
|
||||
} else {
|
||||
val provider = CalendarProvider(context)
|
||||
val data = provider.getInstances(now.timeInMillis, limit.timeInMillis)
|
||||
if (data != null) {
|
||||
val instances = data.list
|
||||
for (instance in instances) {
|
||||
try {
|
||||
val e = provider.getEvent(instance.eventId)
|
||||
if (e != null && instance.begin <= limit.timeInMillis && (Preferences.calendarAllDay || !e.allDay) && !(Preferences.calendarFilter.contains(" " + e.calendarId + ",")) && (Preferences.showDeclinedEvents || e.selfAttendeeStatus.toInt() != CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED)) {
|
||||
if (e.allDay) {
|
||||
val start = Calendar.getInstance()
|
||||
start.timeInMillis = instance.begin
|
||||
val end = Calendar.getInstance()
|
||||
end.timeInMillis = instance.end
|
||||
instance.begin = start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
|
||||
instance.end = end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
|
||||
}
|
||||
eventList.add(Event(instance.id, e.id, e.title ?: "", instance.begin, instance.end, e.calendarId.toInt(), e.allDay, e.eventLocation ?: ""))
|
||||
}
|
||||
} catch (ignored: Exception) {}
|
||||
}
|
||||
}
|
||||
|
||||
if (eventList.isEmpty()) {
|
||||
resetNextEventData(context)
|
||||
} else {
|
||||
eventList.sortWith(Comparator { event: Event, event1: Event ->
|
||||
if (event.allDay && event1.allDay) {
|
||||
event.startDate.compareTo(event1.startDate)
|
||||
} else if (event.allDay) {
|
||||
1
|
||||
} else if (event1.allDay) {
|
||||
-1
|
||||
} else {
|
||||
event1.startDate.compareTo(event.startDate)
|
||||
}
|
||||
})
|
||||
eventList.reverse()
|
||||
saveEvents(eventList)
|
||||
saveNextEventData(context, eventList[0])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resetNextEventData(context)
|
||||
}
|
||||
|
||||
UpdatesReceiver.setUpdates(context)
|
||||
Util.updateWidget(context)
|
||||
}
|
||||
|
||||
fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> {
|
||||
val calendarList = ArrayList<me.everything.providers.android.calendar.Calendar>()
|
||||
|
||||
if (!Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR)) {
|
||||
return calendarList
|
||||
}
|
||||
val provider = CalendarProvider(context)
|
||||
val data = provider.calendars
|
||||
return if (data != null) {
|
||||
data.list
|
||||
} else {
|
||||
calendarList
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveEvents(eventList: ArrayList<Event>) {
|
||||
Realm.getDefaultInstance().executeTransactionAsync { realm ->
|
||||
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||
realm.copyToRealm(eventList)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetNextEventData(context: Context) {
|
||||
Realm.getDefaultInstance().executeTransactionAsync {
|
||||
it.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||
}
|
||||
|
||||
Preferences.bulk {
|
||||
remove(Preferences::nextEventId)
|
||||
remove(Preferences::nextEventName)
|
||||
remove(Preferences::nextEventStartDate)
|
||||
remove(Preferences::nextEventAllDay)
|
||||
remove(Preferences::nextEventLocation)
|
||||
remove(Preferences::nextEventEndDate)
|
||||
remove(Preferences::nextEventCalendarId)
|
||||
}
|
||||
|
||||
Util.updateWidget(context)
|
||||
}
|
||||
|
||||
private fun saveNextEventData(context: Context, event: Event) {
|
||||
Preferences.nextEventId = event.id
|
||||
Util.updateWidget(context)
|
||||
}
|
||||
|
||||
fun getNextEvent(): Event? {
|
||||
val realm = Realm.getDefaultInstance()
|
||||
return realm.where(Event::class.java).equalTo("id", Preferences.nextEventId).findFirst() ?: realm.where(Event::class.java).findFirst()
|
||||
}
|
||||
|
||||
fun goToNextEvent(context: Context) {
|
||||
val eventList = Realm.getDefaultInstance().where(Event::class.java).findAll()
|
||||
|
||||
if (eventList.isNotEmpty()) {
|
||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
||||
if (index > -1 && index < eventList.size - 1) {
|
||||
Preferences.nextEventId = eventList[index + 1]!!.id
|
||||
} else {
|
||||
Preferences.nextEventId = eventList.first()!!.id
|
||||
}
|
||||
} else {
|
||||
resetNextEventData(context)
|
||||
}
|
||||
UpdatesReceiver.setUpdates(context)
|
||||
Util.updateWidget(context)
|
||||
}
|
||||
|
||||
fun goToPreviousEvent(context: Context) {
|
||||
val eventList = Realm.getDefaultInstance().where(Event::class.java).findAll()
|
||||
|
||||
if (eventList.isNotEmpty()) {
|
||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
||||
if (index > 0) {
|
||||
Preferences.nextEventId = eventList[index - 1]!!.id
|
||||
} else {
|
||||
Preferences.nextEventId = eventList.last()!!.id
|
||||
}
|
||||
} else {
|
||||
resetNextEventData(context)
|
||||
}
|
||||
UpdatesReceiver.setUpdates(context)
|
||||
Util.updateWidget(context)
|
||||
}
|
||||
|
||||
fun getEvents(): RealmResults<Event> = Realm.getDefaultInstance().where(Event::class.java).findAll()
|
||||
fun getEventsCount(): Int = Realm.getDefaultInstance().where(Event::class.java).findAll().size
|
||||
}
|
@ -8,6 +8,7 @@ import android.widget.Toast
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.app.Activity
|
||||
import android.app.WallpaperManager
|
||||
import android.content.*
|
||||
import android.net.Uri
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
@ -18,8 +19,15 @@ import android.util.Patterns
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import kotlin.math.max
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.Transformation
|
||||
import android.widget.LinearLayout
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import java.util.*
|
||||
|
||||
|
||||
fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
|
||||
@ -33,10 +41,11 @@ fun Context.toast(message: String) {
|
||||
fun Int.toPixel(context: Context): Int = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), context.resources.displayMetrics).toInt()
|
||||
fun Float.toPixel(context: Context): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, context.resources.displayMetrics)
|
||||
|
||||
fun View.reveal(initialX: Int, initialY: Int) {
|
||||
fun View.reveal(initialX: Int? = null, initialY: Int? = null) {
|
||||
|
||||
when (visibility) {
|
||||
View.VISIBLE -> {
|
||||
val anim = ViewAnimationUtils.createCircularReveal(this, initialX, initialY, max(width.toFloat(), height.toFloat()), 0f)
|
||||
val anim = ViewAnimationUtils.createCircularReveal(this, initialX ?: this.measuredWidth / 2, initialY ?: this.measuredHeight / 2, max(width.toFloat(), height.toFloat()), 0f)
|
||||
.apply {
|
||||
duration = 200
|
||||
}
|
||||
@ -48,7 +57,7 @@ fun View.reveal(initialX: Int, initialY: Int) {
|
||||
})
|
||||
anim.start()
|
||||
} else -> {
|
||||
val anim = ViewAnimationUtils.createCircularReveal(this, initialX, initialY, 0f, max(width.toFloat(), height.toFloat()))
|
||||
val anim = ViewAnimationUtils.createCircularReveal(this, initialX ?: this.measuredWidth / 2, initialY ?: this.measuredHeight / 2, 0f, max(width.toFloat(), height.toFloat()))
|
||||
.apply {
|
||||
duration = 200
|
||||
}
|
||||
@ -58,6 +67,58 @@ fun View.reveal(initialX: Int, initialY: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun View.expand() {
|
||||
if (visibility != View.VISIBLE) {
|
||||
measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
val targetHeight = measuredHeight
|
||||
|
||||
layoutParams.height = 0
|
||||
visibility = View.VISIBLE
|
||||
val a = object : Animation() {
|
||||
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
|
||||
layoutParams.height = if (interpolatedTime == 1f)
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
else
|
||||
(targetHeight * interpolatedTime).toInt()
|
||||
translationY = 0f
|
||||
requestLayout()
|
||||
}
|
||||
|
||||
override fun willChangeBounds(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
a.duration = 500L
|
||||
startAnimation(a)
|
||||
}
|
||||
}
|
||||
|
||||
fun View.collapse() {
|
||||
if (visibility != View.GONE) {
|
||||
val initialHeight = measuredHeight
|
||||
|
||||
val a = object : Animation() {
|
||||
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
|
||||
if (interpolatedTime == 1f) {
|
||||
visibility = View.GONE
|
||||
} else {
|
||||
layoutParams.height = initialHeight - (initialHeight * interpolatedTime).toInt()
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
|
||||
override fun willChangeBounds(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
a.duration = 500L //(initialHeight / v.context.resources.displayMetrics.density).toLong()
|
||||
startAnimation(a)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.openURI(url: String) {
|
||||
try {
|
||||
val builder: CustomTabsIntent.Builder = CustomTabsIntent.Builder()
|
||||
@ -117,14 +178,38 @@ fun Activity.isDarkTheme(): Boolean {
|
||||
|
||||
fun Activity.isNotificationAccessGranted(): Boolean = Settings.Secure.getString(this.contentResolver,"enabled_notification_listeners").contains(this.packageName)
|
||||
|
||||
//fun Activity.sendEmailTo(email: String) {
|
||||
// val i = Intent(Intent.ACTION_VIEW).apply {
|
||||
// data = Uri.parse("mailto:$email")
|
||||
// }
|
||||
// try {
|
||||
// startActivity(Intent.createChooser(i, getString(R.string.settings_title_feedback)))
|
||||
// } catch (ex: java.lang.Exception) {
|
||||
// toast(getString(R.string.generic_error))
|
||||
// }
|
||||
//
|
||||
//}
|
||||
fun Float.convertDpToPixel(context: Context): Float {
|
||||
val resources: Resources = context.resources
|
||||
val metrics: DisplayMetrics = resources.displayMetrics
|
||||
val px: Float = this * (metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT)
|
||||
return px
|
||||
}
|
||||
|
||||
fun Float.convertSpToPixels(context: Context): Float {
|
||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this, context.resources.displayMetrics)
|
||||
}
|
||||
|
||||
fun Context.checkGrantedPermission(permission: String): Boolean {
|
||||
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
fun Context.getCurrentWallpaper(): Drawable? = try {
|
||||
WallpaperManager.getInstance(this).drawable
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
fun String.getCapWordString(): String {
|
||||
return try {
|
||||
val ar = this.split(" ")
|
||||
var newText = ""
|
||||
for (t: String in ar) {
|
||||
newText += " "
|
||||
newText += t.substring(0, 1).toUpperCase(Locale.getDefault())
|
||||
newText += t.substring(1)
|
||||
}
|
||||
newText.substring(1)
|
||||
} catch (e: Exception) {
|
||||
this
|
||||
}
|
||||
}
|
@ -1,521 +0,0 @@
|
||||
package com.tommasoberlose.anotherwidget.utils
|
||||
|
||||
import android.app.*
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.*
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Resources
|
||||
import android.graphics.*
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.util.DisplayMetrics
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.util.TypedValue
|
||||
import android.content.Intent
|
||||
import android.content.ComponentName
|
||||
import android.provider.AlarmClock
|
||||
import android.provider.CalendarContract
|
||||
import android.text.format.DateFormat
|
||||
import android.text.format.DateUtils
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.Transformation
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import com.tommasoberlose.anotherwidget.components.events.Event
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.TheWidget
|
||||
import org.joda.time.DateTime
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
||||
/**
|
||||
* Created by tommaso on 05/10/17.
|
||||
*/
|
||||
|
||||
object Util {
|
||||
|
||||
fun checkGrantedPermission(context: Context, permission: String): Boolean {
|
||||
return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
fun updateWidget(context: Context) {
|
||||
val widgetManager = AppWidgetManager.getInstance(context)
|
||||
val widgetComponent = ComponentName(context, TheWidget::class.java)
|
||||
val widgetIds = widgetManager.getAppWidgetIds(widgetComponent)
|
||||
val update = Intent(context, TheWidget::class.java)
|
||||
update.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds)
|
||||
update.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||
context.sendBroadcast(update)
|
||||
}
|
||||
|
||||
fun showWeatherErrorNotification(context: Context) {
|
||||
TODO("weather notification")
|
||||
// val mNotificationManager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
// val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
// val SP = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
//
|
||||
// if (SP.getBoolean(Constants.PREF_SHOW_GPS_NOTIFICATION, true) && !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && SP.getInt(Constants.PREF_WEATHER_PROVIDER, Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS) == Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS) {
|
||||
// val settingsIntent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
|
||||
// val pi: PendingIntent = PendingIntent.getActivity(context, 50, settingsIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
//
|
||||
// val providerIntent2 = Intent(context, MainActivity::class.java)
|
||||
// providerIntent2.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
// providerIntent2.putExtra(Constants.ACTION_EXTRA_OPEN_WEATHER_PROVIDER, true)
|
||||
// val pi2: PendingIntent = PendingIntent.getActivity(context, 51, providerIntent2, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
//
|
||||
// val providerIntentDisable = Intent(context, MainActivity::class.java)
|
||||
// providerIntentDisable.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
// providerIntentDisable.putExtra(Constants.ACTION_EXTRA_DISABLE_GPS_NOTIFICATION, true)
|
||||
// val piDisable: PendingIntent = PendingIntent.getActivity(context, 52, providerIntentDisable, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
//
|
||||
// val mBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, "Error")
|
||||
// .setSmallIcon(R.drawable.ic_stat_name)
|
||||
// .setColor(ContextCompat.getColor(context, R.color.colorPrimary))
|
||||
// .setContentTitle(context.getString(R.string.notification_gps_title))
|
||||
// .setContentText(context.getString(R.string.notification_gps_subtitle))
|
||||
// .addAction(R.drawable.ic_action_sync, context.getString(R.string.change_provider), pi2)
|
||||
// .addAction(R.drawable.ic_action_settings, context.getString(R.string.disable_notification), piDisable)
|
||||
// .setContentIntent(pi)
|
||||
//
|
||||
// mNotificationManager.notify(10, mBuilder.build());
|
||||
// } else {
|
||||
// mNotificationManager.cancel(10)
|
||||
// }
|
||||
}
|
||||
|
||||
fun getGoogleMapsIntentFromAddress(context: Context, address:String): Intent {
|
||||
val gmmIntentUri: Uri = Uri.parse("geo:0,0?q=$address")
|
||||
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
||||
mapIntent.`package` = "com.google.android.apps.maps"
|
||||
|
||||
return if (mapIntent.resolveActivity(context.packageManager) != null) {
|
||||
mapIntent
|
||||
} else {
|
||||
val map = "http://maps.google.co.in/maps?q=$address"
|
||||
val i = Intent(Intent.ACTION_VIEW, Uri.parse(map));
|
||||
i
|
||||
}
|
||||
}
|
||||
|
||||
fun getCurrentWallpaper(context: Context): Drawable? = try {
|
||||
WallpaperManager.getInstance(context).drawable
|
||||
} catch (e: Exception) {
|
||||
// BitmapDrawable(context.resources, getResizedBitmap(BitmapFactory.decodeResource(context.resources, R.drawable.pixel_2_wallpaper), 800))
|
||||
null
|
||||
}
|
||||
|
||||
fun getBitmapFromView(view: View): Bitmap {
|
||||
//Define a bitmap with the same size as the view
|
||||
val measuredWidth = View.MeasureSpec.makeMeasureSpec(view.width, View.MeasureSpec.UNSPECIFIED)
|
||||
val measuredHeight = View.MeasureSpec.makeMeasureSpec(view.height, View.MeasureSpec.UNSPECIFIED)
|
||||
view.measure(measuredWidth, measuredHeight)
|
||||
view.layout(0,0, measuredWidth, measuredHeight)
|
||||
val returnedBitmap = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight, Bitmap.Config.ARGB_8888)
|
||||
//Bind a canvas to it
|
||||
val canvas = Canvas(returnedBitmap)
|
||||
// draw the view on the canvas
|
||||
view.draw(canvas)
|
||||
//return the bitmap
|
||||
return returnedBitmap
|
||||
}
|
||||
|
||||
fun getBitmapFromView(view: View, w: Int, h: Int): Bitmap {
|
||||
//Define a bitmap with the same size as the view
|
||||
val measuredWidth = View.MeasureSpec.makeMeasureSpec(w, View.MeasureSpec.EXACTLY)
|
||||
val measuredHeight = View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.EXACTLY)
|
||||
view.measure(measuredWidth, measuredHeight)
|
||||
view.layout(0,0, measuredWidth, measuredHeight)
|
||||
val returnedBitmap = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight, Bitmap.Config.ARGB_8888)
|
||||
//Bind a canvas to it
|
||||
val canvas = Canvas(returnedBitmap)
|
||||
// draw the view on the canvas
|
||||
view.draw(canvas)
|
||||
//return the bitmap
|
||||
return returnedBitmap
|
||||
}
|
||||
|
||||
fun convertDpToPixel(dp: Float, context: Context): Float {
|
||||
val resources: Resources = context.resources
|
||||
val metrics: DisplayMetrics = resources.displayMetrics
|
||||
val px: Float = dp * (metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT)
|
||||
return px
|
||||
}
|
||||
|
||||
fun convertSpToPixels(sp: Float, context: Context): Float {
|
||||
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.resources.displayMetrics)
|
||||
}
|
||||
|
||||
fun getResizedBitmap(image: Bitmap, maxSize: Int): Bitmap {
|
||||
var width = image.width
|
||||
var height = image.height
|
||||
|
||||
val bitmapRatio = width.toFloat() / height.toFloat()
|
||||
if (bitmapRatio > 1) {
|
||||
width = maxSize
|
||||
height = (width / bitmapRatio).toInt()
|
||||
} else {
|
||||
height = maxSize
|
||||
width = (height * bitmapRatio).toInt()
|
||||
}
|
||||
|
||||
return Bitmap.createScaledBitmap(image, width, height, true)
|
||||
}
|
||||
|
||||
fun getRefreshPeriodString(period: Int): Int {
|
||||
return when (period) {
|
||||
0 -> R.string.settings_weather_refresh_period_subtitle_0
|
||||
1 -> R.string.settings_weather_refresh_period_subtitle_1
|
||||
2 -> R.string.settings_weather_refresh_period_subtitle_2
|
||||
3 -> R.string.settings_weather_refresh_period_subtitle_3
|
||||
4 -> R.string.settings_weather_refresh_period_subtitle_4
|
||||
5 -> R.string.settings_weather_refresh_period_subtitle_5
|
||||
else -> R.string.settings_weather_refresh_period_subtitle_0
|
||||
}
|
||||
}
|
||||
|
||||
fun getShowUntilString(period: Int): Int {
|
||||
return when (period) {
|
||||
0 -> R.string.settings_show_until_subtitle_0
|
||||
1 -> R.string.settings_show_until_subtitle_1
|
||||
2 -> R.string.settings_show_until_subtitle_2
|
||||
3 -> R.string.settings_show_until_subtitle_3
|
||||
4 -> R.string.settings_show_until_subtitle_4
|
||||
5 -> R.string.settings_show_until_subtitle_5
|
||||
6 -> R.string.settings_show_until_subtitle_6
|
||||
7 -> R.string.settings_show_until_subtitle_7
|
||||
else -> R.string.settings_show_until_subtitle_1
|
||||
}
|
||||
}
|
||||
|
||||
fun getSecondRowInfoString(info: Int): Int {
|
||||
return when (info) {
|
||||
0 -> R.string.settings_second_row_info_subtitle_0
|
||||
1 -> R.string.settings_second_row_info_subtitle_1
|
||||
2 -> R.string.settings_second_row_info_subtitle_2
|
||||
else -> R.string.settings_second_row_info_subtitle_0
|
||||
}
|
||||
}
|
||||
|
||||
fun getTextShadowString(shadow: Int): Int {
|
||||
return when (shadow) {
|
||||
0 -> R.string.settings_text_shadow_subtitle_none
|
||||
1 -> R.string.settings_text_shadow_subtitle_low
|
||||
2 -> R.string.settings_text_shadow_subtitle_high
|
||||
else -> R.string.settings_text_shadow_subtitle_low
|
||||
}
|
||||
}
|
||||
|
||||
fun getCustomFontLabel(shadow: Int): Int {
|
||||
return when (shadow) {
|
||||
0 -> R.string.custom_font_subtitle_0
|
||||
1 -> R.string.custom_font_subtitle_1
|
||||
else -> R.string.custom_font_subtitle_1
|
||||
}
|
||||
}
|
||||
|
||||
fun getCalendarIntent(context: Context): Intent {
|
||||
return when (Preferences.calendarAppPackage) {
|
||||
"" -> {
|
||||
Intent(Intent.ACTION_MAIN).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
addCategory(Intent.CATEGORY_APP_CALENDAR)
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Intent(Intent.ACTION_MAIN).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
addCategory(Intent.CATEGORY_APP_CALENDAR)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getWeatherIntent(context: Context): Intent {
|
||||
return when (Preferences.weatherAppPackage) {
|
||||
"" -> {
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
addCategory(Intent.CATEGORY_DEFAULT)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
data = Uri.parse("dynact://velour/weather/ProxyActivity")
|
||||
component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.weatherAppPackage)!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
addCategory(Intent.CATEGORY_DEFAULT)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
data = Uri.parse("dynact://velour/weather/ProxyActivity")
|
||||
component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getEventIntent(context: Context, e: Event): Intent {
|
||||
return when (Preferences.eventAppPackage) {
|
||||
"" -> {
|
||||
val uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, e.eventID)
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = uri
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
putExtra("beginTime", e.startDate)
|
||||
putExtra("endTime", e.endDate)
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.eventAppPackage)!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
val uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, e.id)
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = uri
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
putExtra("beginTime", e.startDate)
|
||||
putExtra("endTime", e.endDate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getClockIntent(context: Context): Intent {
|
||||
return when (Preferences.clockAppPackage) {
|
||||
"" -> {
|
||||
Intent(AlarmClock.ACTION_SHOW_ALARMS).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.clockAppPackage)!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Intent(AlarmClock.ACTION_SHOW_ALARMS).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getCapWordString(text: String): String {
|
||||
return try {
|
||||
val ar = text.split(" ")
|
||||
var newText = ""
|
||||
for (t: String in ar) {
|
||||
newText += " "
|
||||
newText += t.substring(0, 1).toUpperCase(Locale.getDefault())
|
||||
newText += t.substring(1)
|
||||
}
|
||||
newText.substring(1)
|
||||
} catch (e: Exception) {
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
fun showLocationNotification(context: Context, show: Boolean) {
|
||||
TODO("Show location notification")
|
||||
// val mNotificationManager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
|
||||
//
|
||||
// if (show) {
|
||||
// val mBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, "Config")
|
||||
// .setSmallIcon(R.drawable.ic_stat_name)
|
||||
// .setPriority(Notification.PRIORITY_MIN)
|
||||
// .setColor(ContextCompat.getColor(context, R.color.colorPrimary))
|
||||
// .setContentTitle(context.getString(R.string.notification_gps_title))
|
||||
// .setContentText(context.getString(R.string.notification_gps_subtitle))
|
||||
// .setAutoCancel(true);
|
||||
//
|
||||
// val intent: Intent = Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
|
||||
// val pi: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
// mBuilder.setContentIntent(pi);
|
||||
// mNotificationManager.notify(1, mBuilder.build());
|
||||
// } else {
|
||||
// mNotificationManager.cancel(1);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
fun showWeatherNotification(context: Context, show: Boolean) {
|
||||
TODO("Show location notification")
|
||||
// val mNotificationManager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
|
||||
//
|
||||
// if (show) {
|
||||
// val mBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, "Config")
|
||||
// .setSmallIcon(R.drawable.ic_stat_name)
|
||||
// .setColor(ContextCompat.getColor(context, R.color.colorPrimary))
|
||||
// .setContentTitle(context.getString(R.string.settings_weather_provider_api_key_title))
|
||||
// .setContentText(context.getString(R.string.settings_weather_provider_api_key_subtitle_not_set))
|
||||
// .setAutoCancel(true);
|
||||
//
|
||||
// val intent: Intent = Intent(context, MainActivity::class.java);
|
||||
// intent.putExtra(Constants.ACTION_EXTRA_OPEN_WEATHER_PROVIDER, true)
|
||||
// val pi: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
// mBuilder.setContentIntent(pi);
|
||||
// mNotificationManager.notify(2, mBuilder.build());
|
||||
// } else {
|
||||
// mNotificationManager.cancel(2);
|
||||
// }
|
||||
}
|
||||
|
||||
fun expand(v: View) {
|
||||
if (v.visibility != View.VISIBLE) {
|
||||
v.measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
val targetHeight = v.measuredHeight
|
||||
|
||||
v.layoutParams.height = 0
|
||||
v.visibility = View.VISIBLE
|
||||
val a = object : Animation() {
|
||||
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
|
||||
v.layoutParams.height = if (interpolatedTime == 1f)
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
else
|
||||
(targetHeight * interpolatedTime).toInt()
|
||||
v.translationY = 0f
|
||||
v.requestLayout()
|
||||
}
|
||||
|
||||
override fun willChangeBounds(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
a.duration = 500L
|
||||
v.startAnimation(a)
|
||||
}
|
||||
}
|
||||
|
||||
fun collapse(v: View) {
|
||||
if (v.visibility != View.GONE) {
|
||||
val initialHeight = v.measuredHeight
|
||||
|
||||
val a = object : Animation() {
|
||||
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
|
||||
if (interpolatedTime == 1f) {
|
||||
v.visibility = View.GONE
|
||||
} else {
|
||||
v.layoutParams.height = initialHeight - (initialHeight * interpolatedTime).toInt()
|
||||
v.requestLayout()
|
||||
}
|
||||
}
|
||||
|
||||
override fun willChangeBounds(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
a.duration = 500L //(initialHeight / v.context.resources.displayMetrics.density).toLong()
|
||||
v.startAnimation(a)
|
||||
}
|
||||
}
|
||||
|
||||
fun getEmojiByUnicode(unicode: Int): String {
|
||||
return String(Character.toChars(unicode))
|
||||
}
|
||||
|
||||
fun getDifferenceText(context: Context, now: Long, start: Long): String {
|
||||
val nowDate = DateTime(now)
|
||||
val eventDate = DateTime(start)
|
||||
|
||||
var difference = start - now
|
||||
difference += 60 * 1000 - (difference % (60 * 1000))
|
||||
|
||||
when {
|
||||
difference <= 0 || TimeUnit.MILLISECONDS.toHours(difference) < 1 -> {
|
||||
return ""
|
||||
}
|
||||
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS).toString()
|
||||
}
|
||||
eventDate.dayOfYear == nowDate.plusDays(1).dayOfYear -> {
|
||||
return String.format("%s", context.getString(R.string.tomorrow))
|
||||
}
|
||||
eventDate.dayOfYear == nowDate.dayOfYear -> {
|
||||
return String.format("%s", context.getString(R.string.today))
|
||||
}
|
||||
else -> {
|
||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.DAY_IN_MILLIS).toString()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getFontColor(): Int {
|
||||
return try {
|
||||
Color.parseColor(Preferences.textGlobalColor)
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#FFFFFF")
|
||||
}
|
||||
}
|
||||
|
||||
fun getTintedDrawable(context: Context, inputDrawable: Int, color: Int): Drawable? = ContextCompat.getDrawable(context, inputDrawable)?.apply {
|
||||
DrawableCompat.setTint(this, color)
|
||||
DrawableCompat.setTintMode(this, PorterDuff.Mode.SRC_IN)
|
||||
}
|
||||
|
||||
fun changeBitmapColor(sourceBitmap: Bitmap, color: Int): Bitmap {
|
||||
val resultBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0,
|
||||
sourceBitmap.width - 1, sourceBitmap.height - 1)
|
||||
val p = Paint()
|
||||
val filter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)
|
||||
p.colorFilter = filter
|
||||
|
||||
val canvas = Canvas(resultBitmap)
|
||||
canvas.drawBitmap(resultBitmap, 0f, 0f, p)
|
||||
|
||||
return resultBitmap
|
||||
}
|
||||
|
||||
fun getNextAlarm(context: Context): String = with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
return if (nextAlarmClock != null && nextAlarmClock.triggerTime - Calendar.getInstance().timeInMillis > 5 * 60 * 1000) {
|
||||
DateFormat.getTimeFormat(context).format(Date(nextAlarmClock.triggerTime))
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
BIN
app/src/main/res/drawable-hdpi/round_check_black_18.png
Normal file
After Width: | Height: | Size: 154 B |
BIN
app/src/main/res/drawable-hdpi/round_check_black_24.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
app/src/main/res/drawable-hdpi/round_check_black_36.png
Normal file
After Width: | Height: | Size: 235 B |
BIN
app/src/main/res/drawable-hdpi/round_check_black_48.png
Normal file
After Width: | Height: | Size: 289 B |
BIN
app/src/main/res/drawable-hdpi/round_help_outline.png
Normal file
After Width: | Height: | Size: 848 B |
BIN
app/src/main/res/drawable-hdpi/round_help_outline_black_18.png
Normal file
After Width: | Height: | Size: 476 B |
BIN
app/src/main/res/drawable-hdpi/round_help_outline_black_24.png
Normal file
After Width: | Height: | Size: 577 B |
BIN
app/src/main/res/drawable-hdpi/round_help_outline_black_48.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-mdpi/round_check_black_18.png
Normal file
After Width: | Height: | Size: 125 B |
BIN
app/src/main/res/drawable-mdpi/round_check_black_24.png
Normal file
After Width: | Height: | Size: 141 B |
BIN
app/src/main/res/drawable-mdpi/round_check_black_36.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
app/src/main/res/drawable-mdpi/round_check_black_48.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
app/src/main/res/drawable-mdpi/round_help_outline.png
Normal file
After Width: | Height: | Size: 577 B |
BIN
app/src/main/res/drawable-mdpi/round_help_outline_black_18.png
Normal file
After Width: | Height: | Size: 323 B |
BIN
app/src/main/res/drawable-mdpi/round_help_outline_black_24.png
Normal file
After Width: | Height: | Size: 398 B |
BIN
app/src/main/res/drawable-mdpi/round_help_outline_black_48.png
Normal file
After Width: | Height: | Size: 752 B |
BIN
app/src/main/res/drawable-xhdpi/round_check_black_18.png
Normal file
After Width: | Height: | Size: 177 B |
BIN
app/src/main/res/drawable-xhdpi/round_check_black_24.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
app/src/main/res/drawable-xhdpi/round_check_black_36.png
Normal file
After Width: | Height: | Size: 289 B |
BIN
app/src/main/res/drawable-xhdpi/round_check_black_48.png
Normal file
After Width: | Height: | Size: 356 B |
BIN
app/src/main/res/drawable-xhdpi/round_help_outline.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-xhdpi/round_help_outline_black_18.png
Normal file
After Width: | Height: | Size: 577 B |
BIN
app/src/main/res/drawable-xhdpi/round_help_outline_black_24.png
Normal file
After Width: | Height: | Size: 752 B |
BIN
app/src/main/res/drawable-xhdpi/round_help_outline_black_48.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/drawable-xxhdpi/round_check_black_18.png
Normal file
After Width: | Height: | Size: 235 B |
BIN
app/src/main/res/drawable-xxhdpi/round_check_black_24.png
Normal file
After Width: | Height: | Size: 289 B |
BIN
app/src/main/res/drawable-xxhdpi/round_check_black_36.png
Normal file
After Width: | Height: | Size: 390 B |
BIN
app/src/main/res/drawable-xxhdpi/round_check_black_48.png
Normal file
After Width: | Height: | Size: 491 B |
BIN
app/src/main/res/drawable-xxhdpi/round_help_outline.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/drawable-xxhdpi/round_help_outline_black_18.png
Normal file
After Width: | Height: | Size: 848 B |
BIN
app/src/main/res/drawable-xxhdpi/round_help_outline_black_24.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-xxhdpi/round_help_outline_black_48.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/round_check_black_18.png
Normal file
After Width: | Height: | Size: 289 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_check_black_24.png
Normal file
After Width: | Height: | Size: 356 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_check_black_36.png
Normal file
After Width: | Height: | Size: 491 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_check_black_48.png
Normal file
After Width: | Height: | Size: 654 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_help_outline.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.5 KiB |
10
app/src/main/res/drawable/round_check.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M9,16.17L5.53,12.7c-0.39,-0.39 -1.02,-0.39 -1.41,0 -0.39,0.39 -0.39,1.02 0,1.41l4.18,4.18c0.39,0.39 1.02,0.39 1.41,0L20.29,7.71c0.39,-0.39 0.39,-1.02 0,-1.41 -0.39,-0.39 -1.02,-0.39 -1.41,0L9,16.17z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/round_help_outline_24.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,16h2v2h-2zM12.61,6.04c-2.06,-0.3 -3.88,0.97 -4.43,2.79 -0.18,0.58 0.26,1.17 0.87,1.17h0.2c0.41,0 0.74,-0.29 0.88,-0.67 0.32,-0.89 1.27,-1.5 2.3,-1.28 0.95,0.2 1.65,1.13 1.57,2.1 -0.1,1.34 -1.62,1.63 -2.45,2.88 0,0.01 -0.01,0.01 -0.01,0.02 -0.01,0.02 -0.02,0.03 -0.03,0.05 -0.09,0.15 -0.18,0.32 -0.25,0.5 -0.01,0.03 -0.03,0.05 -0.04,0.08 -0.01,0.02 -0.01,0.04 -0.02,0.07 -0.12,0.34 -0.2,0.75 -0.2,1.25h2c0,-0.42 0.11,-0.77 0.28,-1.07 0.02,-0.03 0.03,-0.06 0.05,-0.09 0.08,-0.14 0.18,-0.27 0.28,-0.39 0.01,-0.01 0.02,-0.03 0.03,-0.04 0.1,-0.12 0.21,-0.23 0.33,-0.34 0.96,-0.91 2.26,-1.65 1.99,-3.56 -0.24,-1.74 -1.61,-3.21 -3.35,-3.47z"/>
|
||||
</vector>
|
@ -34,6 +34,7 @@
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_centerVertical="true"
|
||||
android:id="@+id/action_back"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:tint="@color/colorPrimaryText"
|
||||
android:src="@drawable/round_arrow_back" />
|
||||
<TextView
|
||||
@ -68,8 +69,9 @@
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:inputType="textCapWords"
|
||||
android:textAlignment="viewStart"
|
||||
android:id="@+id/search"
|
||||
android:gravity="center_vertical"
|
||||
android:gravity="center_vertical|start"
|
||||
android:hint="@string/search"
|
||||
android:text="@={viewModel.searchInput}"
|
||||
android:autofillHints="" />
|
||||
|
156
app/src/main/res/layout/activity_custom_date.xml
Normal file
@ -0,0 +1,156 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<data>
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="com.tommasoberlose.anotherwidget.ui.viewmodels.CustomDateViewModel" />
|
||||
</data>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/colorPrimaryDark">
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
android:id="@+id/toolbar"
|
||||
app:cardBackgroundColor="@color/colorPrimary">
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:padding="10dp"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_centerVertical="true"
|
||||
android:id="@+id/action_back"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:tint="@color/colorPrimaryText"
|
||||
android:src="@drawable/round_arrow_back" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="@string/custom_date_format"
|
||||
android:gravity="center"
|
||||
style="@style/AnotherWidget.Main.Title"/>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/action_save"
|
||||
android:gravity="center"
|
||||
android:layout_centerVertical="true"
|
||||
android:padding="16dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:textColor="@color/colorAccent"
|
||||
android:id="@+id/action_save"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Button"/>
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:cardBackgroundColor="@color/colorPrimary">
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardBackgroundColor="@color/colorPrimaryDark"
|
||||
app:cardCornerRadius="9dp"
|
||||
app:cardElevation="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp">
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<EditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="@color/colorPrimaryDark"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="56dp"
|
||||
android:id="@+id/date_format"
|
||||
android:gravity="center_vertical|start"
|
||||
android:textDirection="locale"
|
||||
android:textAlignment="viewStart"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:hint="@string/settings_date_format_title"
|
||||
android:text="@={viewModel.dateInput}"
|
||||
android:autofillHints=""
|
||||
tools:ignore="TextFields" />
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="8dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/round_help_outline"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
app:tint="@color/colorSecondaryText"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:id="@+id/action_date_format_info" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:cardBackgroundColor="@color/colorPrimary">
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:id="@+id/date_format_value"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Button"
|
||||
android:letterSpacing="0"
|
||||
android:textColor="@color/colorPrimaryText"
|
||||
android:textSize="20sp"
|
||||
app:textAllCaps="false"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateTint="@color/colorAccent"
|
||||
android:layout_marginTop="-7dp"
|
||||
android:id="@+id/loader"
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:clipToPadding="false"
|
||||
android:id="@+id/list_view" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</layout>
|
@ -33,6 +33,7 @@
|
||||
android:padding="10dp"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:id="@+id/action_back"
|
||||
android:tint="@color/colorPrimaryText"
|
||||
android:src="@drawable/round_arrow_back" />
|
||||
@ -69,8 +70,10 @@
|
||||
android:paddingRight="16dp"
|
||||
android:inputType="textCapWords"
|
||||
android:id="@+id/location"
|
||||
android:gravity="center_vertical"
|
||||
android:gravity="center_vertical|start"
|
||||
android:hint="@string/search"
|
||||
android:textAlignment="viewStart"
|
||||
android:textDirection="locale"
|
||||
android:text="@={viewModel.locationInput}"
|
||||
android:autofillHints="" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
@ -25,13 +25,26 @@
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
<TextView
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_splash_logo"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginBottom="3dp"
|
||||
android:id="@+id/logo"/>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="@string/app_name"
|
||||
android:gravity="center"
|
||||
style="@style/AnotherWidget.Main.Title"/>
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_centerInParent="true">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/app_name"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="1dp"
|
||||
style="@style/AnotherWidget.Main.Title"/>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
@ -40,8 +53,6 @@
|
||||
android:id="@+id/preview"
|
||||
android:animateLayoutChanges="true"
|
||||
app:cardBackgroundColor="@color/colorPrimary"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
app:cardCornerRadius="9dp"
|
||||
@ -61,6 +72,7 @@
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/widget"
|
||||
android:alpha="0"
|
||||
android:gravity="center">
|
||||
<TextClock
|
||||
android:id="@+id/clock"
|
||||
@ -79,6 +91,13 @@
|
||||
android:id="@+id/widget_bitmap"
|
||||
tools:ignore="ContentDescription" />
|
||||
</LinearLayout>
|
||||
<ProgressBar
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateTint="@android:color/white"
|
||||
android:id="@+id/widget_loader" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
@ -126,14 +145,19 @@
|
||||
android:visibility="gone"
|
||||
app:cardBackgroundColor="@color/colorAccent"
|
||||
app:cardCornerRadius="0dp"
|
||||
android:id="@+id/action_add_widget"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardElevation="4dp">
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="72dp"
|
||||
android:text="@string/add_widget"
|
||||
android:layout_marginTop="-8dp"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/white"
|
||||
android:id="@+id/action_add_widget"
|
||||
app:cornerRadius="0dp"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"/>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
@ -38,6 +38,7 @@
|
||||
android:padding="10dp"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:id="@+id/action_back"
|
||||
android:tint="@color/colorPrimaryText"
|
||||
android:src="@drawable/round_arrow_back" />
|
||||
@ -57,7 +58,7 @@
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textSize="16sp"
|
||||
android:gravity="center"
|
||||
android:text="This is a single developer project,\nso thank you for the support!" />
|
||||
android:text="@string/support_dev_subtitle" />
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
android:padding="10dp"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:id="@+id/action_back"
|
||||
android:tint="@color/colorPrimaryText"
|
||||
android:src="@drawable/round_arrow_back" />
|
||||
@ -42,7 +42,7 @@
|
||||
android:text="@string/action_save"
|
||||
android:gravity="center"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:padding="16dp"
|
||||
android:textColor="@color/colorAccent"
|
||||
android:id="@+id/action_save"
|
||||
@ -74,17 +74,21 @@
|
||||
android:textStyle="bold"
|
||||
android:nextFocusUp="@id/api_key"
|
||||
android:nextFocusLeft="@id/api_key"
|
||||
android:gravity="center_vertical"
|
||||
android:gravity="center_vertical|start"
|
||||
android:textColor="@color/colorPrimaryText"
|
||||
app:boxBackgroundColor="@color/colorPrimaryDark"
|
||||
app:boxStrokeColor="@color/colorAccent"
|
||||
app:hintTextColor="@color/colorAccent"
|
||||
android:hint="@string/api_key_hint"
|
||||
android:textAlignment="viewStart"
|
||||
android:textDirection="locale"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
android:textAlignment="viewStart"
|
||||
android:textDirection="locale"
|
||||
android:gravity="center_vertical|start" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@ -99,6 +103,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/AnotherWidget.Settings.Title"
|
||||
android:gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:text="@string/api_key_title_1"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
@ -106,12 +112,15 @@
|
||||
style="@style/AnotherWidget.Main.Subtitle"
|
||||
android:textSize="16sp"
|
||||
android:gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:text="@string/api_key_subtitle_1"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/AnotherWidget.Settings.Title"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:text="@string/api_key_title_2"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
@ -119,12 +128,15 @@
|
||||
style="@style/AnotherWidget.Main.Subtitle"
|
||||
android:textSize="16sp"
|
||||
android:gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:text="@string/api_key_subtitle_2"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/AnotherWidget.Settings.Title"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:text="@string/api_key_title_3"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
@ -132,6 +144,7 @@
|
||||
style="@style/AnotherWidget.Main.Subtitle"
|
||||
android:textSize="16sp"
|
||||
android:gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:text="@string/api_key_subtitle_3"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
@ -139,6 +152,7 @@
|
||||
style="@style/AnotherWidget.Main.Subtitle"
|
||||
android:textSize="16sp"
|
||||
android:gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:id="@+id/last_info"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_width="match_parent"
|
||||
@ -148,6 +162,7 @@
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="start|center_vertical"
|
||||
android:textAlignment="viewStart"
|
||||
android:layout_marginStart="-8dp"
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||
android:textAllCaps="false"
|
||||
|
@ -7,9 +7,13 @@
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/item"
|
||||
android:gravity="center_vertical">
|
||||
android:gravity="center_vertical|start">
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
@ -22,10 +26,14 @@
|
||||
tools:ignore="HardcodedText" />
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:gravity="center_vertical|start"
|
||||
android:paddingEnd="24dp"
|
||||
android:lines="1"
|
||||
android:textAlignment="viewStart"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:textColor="@color/colorPrimaryText"
|
||||
style="@style/AnotherWidget.Settings.Title"/>
|
||||
</LinearLayout>
|