Moving to version 2.0

This commit is contained in:
Tommaso Berlose
2020-05-01 01:09:56 +02:00
parent 05a0308f8f
commit 3aecf9851a
1039 changed files with 6754 additions and 5763 deletions

View File

@ -1,27 +0,0 @@
package com.tommasoberlose.anotherwidget.ui
import android.annotation.SuppressLint
import android.app.Application
import android.content.SharedPreferences
import android.preference.PreferenceManager
import android.util.Log
import com.tommasoberlose.anotherwidget.`object`.Constants
import com.tommasoberlose.anotherwidget.util.MyMigration
import com.tommasoberlose.anotherwidget.util.Util
import io.realm.Realm
import io.realm.RealmConfiguration
class AWApplication : Application() {
@SuppressLint("ApplySharedPref")
override fun onCreate() {
super.onCreate()
Realm.init(this)
val config = RealmConfiguration.Builder()
.schemaVersion(2)
.migration(MyMigration())
.deleteRealmIfMigrationNeeded()
.build()
Realm.setDefaultConfiguration(config)
}
}

View File

@ -0,0 +1,140 @@
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.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.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.*
import net.idik.lib.slimadapter.SlimAdapter
class ChooseApplicationActivity : AppCompatActivity() {
private lateinit var adapter: SlimAdapter
private lateinit var viewModel: ChooseApplicationViewModel
private val pm by lazy { packageManager }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(ChooseApplicationViewModel::class.java)
val binding = DataBindingUtil.setContentView<ActivityChooseApplicationBinding>(this, R.layout.activity_choose_application)
list_view.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(this)
list_view.layoutManager = mLayoutManager
adapter = SlimAdapter.create()
adapter
.register<String>(R.layout.application_info_layout) { _, injector ->
injector
.text(R.id.text, getString(R.string.default_name))
.image(R.id.icon, R.drawable.round_add_to_home_screen)
.with<ImageView>(R.id.icon) {
it.scaleX = 0.8f
it.scaleY = 0.8f
it.setColorFilter(ContextCompat.getColor(this, R.color.colorPrimaryText), android.graphics.PorterDuff.Mode.MULTIPLY)
}
.clicked(R.id.item) {
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, "")
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, "")
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
}
.register<ApplicationInfo>(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) {
}
injector.clicked(R.id.item) {
saveApp(item)
}
}
.attachTo(list_view)
setupListener()
subscribeUi(binding, viewModel)
search.requestFocus()
}
private var filterJob: Job? = null
private fun subscribeUi(binding: ActivityChooseApplicationBinding, viewModel: ChooseApplicationViewModel) {
binding.viewModel = viewModel
viewModel.appList.observe(this, Observer {
adapter.updateData(listOf("Default") + it)
loader.visibility = View.INVISIBLE
})
viewModel.searchInput.observe(this, Observer { search ->
loader.visibility = View.VISIBLE
filterJob?.cancel()
filterJob = lifecycleScope.launch(Dispatchers.IO) {
delay(200)
val list = if (search == null || search == "") {
viewModel.appList.value!!
} else {
viewModel.appList.value!!.filter {
pm.getApplicationLabel(
it
).toString().contains(search, true)
}
}
withContext(Dispatchers.Main) {
adapter.updateData(listOf("Default") + list)
loader.visibility = View.INVISIBLE
}
}
})
}
private fun setupListener() {
action_back.setOnClickListener {
onBackPressed()
}
}
private fun saveApp(app: ApplicationInfo) {
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, pm.getApplicationLabel(app).toString())
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, app.packageName)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
}

View File

@ -0,0 +1,161 @@
package com.tommasoberlose.anotherwidget.ui.activities
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.location.Address
import android.location.Geocoder
import android.os.Bundle
import com.tommasoberlose.anotherwidget.R
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.Window
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.appcompat.app.AppCompatActivity
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.google.android.material.transition.MaterialFadeThrough
import com.google.android.material.transition.MaterialSharedAxis
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.components.events.CustomLocationEvent
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
import com.tommasoberlose.anotherwidget.databinding.ActivityCustomLocationBinding
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
import com.tommasoberlose.anotherwidget.ui.viewmodels.CustomLocationViewModel
import kotlinx.android.synthetic.main.activity_custom_location.*
import kotlinx.coroutines.*
import net.idik.lib.slimadapter.SlimAdapter
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.ThreadMode
import org.greenrobot.eventbus.Subscribe
class CustomLocationActivity : AppCompatActivity() {
private lateinit var adapter: SlimAdapter
private lateinit var viewModel: CustomLocationViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(CustomLocationViewModel::class.java)
val binding = DataBindingUtil.setContentView<ActivityCustomLocationBinding>(this, R.layout.activity_custom_location)
list_view.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(this)
list_view.layoutManager = mLayoutManager
adapter = SlimAdapter.create()
adapter
.register<String>(R.layout.custom_location_item) { _, injector ->
injector
.text(R.id.text, getString(R.string.custom_location_gps))
.clicked(R.id.text) {
requirePermission()
}
}
.register<Address>(R.layout.custom_location_item) { item, injector ->
injector.text(R.id.text, item.getAddressLine(0))
injector.clicked(R.id.text) {
Preferences.bulk {
customLocationLat = item.latitude.toString()
customLocationLon = item.longitude.toString()
customLocationAdd = item.getAddressLine(0)
setResult(Activity.RESULT_OK)
finish()
}
}
}
.attachTo(list_view)
viewModel.addresses.observe(this, Observer {
adapter.updateData(listOf("Default") + it)
})
setupListener()
subscribeUi(binding, viewModel)
location.requestFocus()
}
private var searchJob: Job? = null
private fun subscribeUi(binding: ActivityCustomLocationBinding, viewModel: CustomLocationViewModel) {
binding.viewModel = viewModel
viewModel.addresses.observe(this, Observer {
adapter.updateData(listOf("Default") + it)
loader.visibility = View.INVISIBLE
})
viewModel.locationInput.observe(this, Observer { location ->
loader.visibility = View.VISIBLE
searchJob?.cancel()
searchJob = lifecycleScope.launch(Dispatchers.IO) {
delay(200)
val list = if (location == null || location == "") {
viewModel.addresses.value!!
} else {
val coder = Geocoder(this@CustomLocationActivity)
try {
coder.getFromLocationName(location, 10) as ArrayList<Address>
} catch (ignored: Exception) {
emptyList<Address>()
}
}
withContext(Dispatchers.Main) {
viewModel.addresses.value = list
loader.visibility = View.INVISIBLE
}
}
})
}
private fun requirePermission() {
Dexter.withContext(this)
.withPermissions(
Manifest.permission.ACCESS_FINE_LOCATION
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {
if (report.areAllPermissionsGranted()){
Preferences.bulk {
remove(Preferences::customLocationLat)
remove(Preferences::customLocationLon)
remove(Preferences::customLocationAdd)
}
setResult(Activity.RESULT_OK)
finish()
}
}
}
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?
) {
// Remember to invoke this method when the custom rationale is closed
// or just by default if you don't want to use any custom rationale.
token?.continuePermissionRequest()
}
})
.check()
}
private fun setupListener() {
action_back.setOnClickListener {
onBackPressed()
}
}
}

View File

@ -0,0 +1,198 @@
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.util.TypedValue
import android.widget.LinearLayout
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.ViewModelProvider
import com.google.android.material.tabs.TabLayoutMediator
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.global.RequestCode
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.utils.*
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.launch
import kotlinx.coroutines.withContext
class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
private var mAppWidgetId: Int = -1
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
controlExtras(intent)
// Viewpager
pager.adapter = ViewPagerAdapter(this)
pager.offscreenPageLimit = 4
TabLayoutMediator(tabs, pager) { tab, position ->
tab.text = when (position) {
0 -> getString(R.string.settings_general_title)
1 -> getString(R.string.settings_calendar_title)
2 -> getString(R.string.settings_weather_title)
3 -> getString(R.string.settings_clock_title)
4 -> getString(R.string.advanced_settings_title)
else -> ""
}
}.attach()
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
subscribeUi(viewModel)
updateUI()
}
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)
withContext(Dispatchers.Main) {
// Clock
clock.setTextColor(Util.getFontColor())
clock.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
clock.format12Hour = "hh:mm"
if ((Preferences.showClock && !clock.isVisible) || (!Preferences.showClock && clock.isVisible)) {
if (Preferences.showClock) {
clock.layoutParams = clock.layoutParams.apply {
height = RelativeLayout.LayoutParams.WRAP_CONTENT
}
clock.measure(0, 0)
}
val initialHeight = clock.measuredHeight
ValueAnimator.ofFloat(
if (Preferences.showClock) 0f else 1f,
if (Preferences.showClock) 1f else 0f
).apply {
duration = 500L
addUpdateListener {
val animatedValue = animatedValue as Float
clock.layoutParams = clock.layoutParams.apply {
height = (initialHeight * animatedValue).toInt()
}
}
addListener(
onStart = {
if (Preferences.showClock) {
clock.isVisible = true
}
},
onEnd = {
if (!Preferences.showClock) {
clock.isVisible = false
}
}
)
}.start()
ValueAnimator.ofInt(
preview.measuredHeight,
160.toPixel(this@MainActivity) + if (Preferences.showClock) 100.toPixel(this@MainActivity) else 0
).apply {
duration = 500L
addUpdateListener {
val animatedValue = animatedValue as Int
val layoutParams = preview.layoutParams
layoutParams.height = animatedValue
preview.layoutParams = layoutParams
}
}.start()
}
widget_bitmap.setImageBitmap(bitmap)
}
}
}
private fun subscribeUi(viewModel: MainViewModel) {
viewModel.showWallpaper.observe(this, Observer {
widget_bg.setImageDrawable(if (it) Util.getCurrentWallpaper(this) else null)
})
}
override fun onBackPressed() {
if (mAppWidgetId > 0) {
addNewWidget()
} else {
setResult(Activity.RESULT_OK)
finish()
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (intent != null) {
controlExtras(intent)
}
}
private fun controlExtras(intent: Intent) {
val extras = intent.extras
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID)
if (mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
action_add_widget.visibility = View.VISIBLE
action_add_widget.setOnClickListener {
addNewWidget()
}
}
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()
}
}
}
private fun addNewWidget() {
val resultValue = Intent()
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId)
setResult(Activity.RESULT_OK, resultValue)
finish()
}
override fun onDestroy() {
super.onDestroy()
Preferences.preferences.unregisterOnSharedPreferenceChangeListener(this)
}
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
updateUI()
Util.updateWidget(this)
}
}

View File

@ -0,0 +1,93 @@
package com.tommasoberlose.anotherwidget.ui.activities
import android.app.Activity
import android.content.Intent
import android.location.Address
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.android.billingclient.api.*
import com.android.billingclient.api.BillingClient.BillingResponseCode.OK
import com.android.billingclient.api.BillingClient.BillingResponseCode.USER_CANCELED
import com.chibatching.kotpref.bulk
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.databinding.ActivitySupportDevBinding
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.ui.viewmodels.SupportDevViewModel
import com.tommasoberlose.anotherwidget.utils.toast
import kotlinx.android.synthetic.main.activity_support_dev.*
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
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
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)
list_view.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(this)
list_view.layoutManager = mLayoutManager
adapter = SlimAdapter.create()
adapter
.register<SkuDetails>(R.layout.inapp_product_layout) { item, injector ->
injector
.text(R.id.product_title, item.title.replace("(Another Widget)", ""))
.text(R.id.product_price, item.price)
.clicked(R.id.item) {
viewModel.purchase(this, item)
}
}
.attachTo(list_view)
viewModel.openConnection()
subscribeUi(viewModel)
action_back.setOnClickListener {
onBackPressed()
}
}
private fun subscribeUi(viewModel: SupportDevViewModel) {
viewModel.products.observe(this, Observer {
if (it.isNotEmpty()) {
loader.isVisible = false
}
adapter.updateData(it.sortedWith(compareBy(SkuDetails::getPriceAmountMicros)))
})
}
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
if (billingResult.responseCode == OK && purchases != null) {
for (purchase in purchases) {
if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
viewModel.handlePurchase(purchase)
toast(getString(R.string.thanks))
}
}
} else if (billingResult.responseCode == USER_CANCELED) {
// DO nothing
} else {
toast(getString(R.string.error))
}
}
public override fun onDestroy() {
viewModel.closeConnection()
super.onDestroy()
}
}

View File

@ -0,0 +1,63 @@
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.*
class WeatherProviderActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_weather_provider)
action_back.setOnClickListener {
onBackPressed()
}
action_save.setOnClickListener {
Preferences.weatherProviderApi = api_key.editText?.text.toString()
setResult(Activity.RESULT_OK)
finish()
}
action_open_provider.setOnClickListener {
openURI("https://home.openweathermap.org/users/sign_up")
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
last_info.text = Html.fromHtml(getString(R.string.api_key_info_all_set), Html.FROM_HTML_MODE_LEGACY)
} else {
last_info.text = Html.fromHtml(getString(R.string.api_key_info_all_set))
}
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()
}
}
}

View File

@ -1,140 +0,0 @@
package com.tommasoberlose.anotherwidget.ui.activity
import android.app.Activity
import android.location.Address
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.preference.PreferenceManager
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.`object`.Constants
import com.tommasoberlose.anotherwidget.`object`.CustomLocationEvent
import kotlinx.android.synthetic.main.activity_choose_application.*
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 android.widget.AdapterView
import android.widget.ArrayAdapter
import com.tommasoberlose.anotherwidget.`object`.ApplicationListEvent
import android.content.pm.PackageManager
import android.location.Geocoder
import android.support.v7.widget.LinearLayoutManager
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.View
import com.tommasoberlose.anotherwidget.`object`.AppInfoSavedEvent
import com.tommasoberlose.anotherwidget.ui.adapter.ApplicationInfoAdapter
class ChooseApplicationActivity : AppCompatActivity() {
lateinit var adapter: ApplicationInfoAdapter
val appList = ArrayList<ApplicationInfo>()
val appListFiltered = ArrayList<ApplicationInfo>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_choose_application)
val pm = packageManager
action_default.setOnClickListener {
selectDefaultApp()
}
action_back.setOnClickListener {
onBackPressed()
}
action_none.setOnClickListener {
removeClickAction()
}
list_view.setHasFixedSize(true);
val mLayoutManager = LinearLayoutManager(this);
list_view.layoutManager = mLayoutManager;
adapter = ApplicationInfoAdapter(this, appListFiltered);
list_view.setAdapter(adapter);
location.addTextChangedListener(object: TextWatcher {
override fun afterTextChanged(text: Editable?) {
Thread().run {
val appsFiltered = if (text == null || text.equals("")) appList else appList.filter { pm.getApplicationLabel(it).toString().contains(text.toString(), true) }
EventBus.getDefault().post(ApplicationListEvent(appsFiltered, true))
}
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
})
}
fun selectDefaultApp() {
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, "")
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, "")
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
fun removeClickAction() {
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, getString(R.string.action_none))
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, "_")
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
fun multiEventAction() {
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, getString(R.string.action_go_to_next_event))
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, Constants.PREF_SHOW_NEXT_EVENT)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun saveApp(e: AppInfoSavedEvent) {
val pm = packageManager
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, pm.getApplicationLabel(e.app).toString())
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, e.app.packageName)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
public override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
}
public override fun onResume() {
super.onResume()
Thread().run {
val pm = packageManager
val apps = pm.getInstalledApplications(0)
EventBus.getDefault().post(ApplicationListEvent(apps, false))
}
}
public override fun onStop() {
EventBus.getDefault().unregister(this)
super.onStop()
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onMessageEvent(event: ApplicationListEvent) {
if (!event.filtered) {
appList.clear()
event.apps.mapTo(appList, {it})
}
appListFiltered.clear()
event.apps.mapTo(appListFiltered, {it})
adapter.changeData(appListFiltered)
}
}

View File

@ -1,117 +0,0 @@
package com.tommasoberlose.anotherwidget.ui.activity
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.location.Address
import android.location.Geocoder
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.preference.PreferenceManager
import android.transition.Slide
import android.view.Gravity
import com.tommasoberlose.anotherwidget.R
import android.support.v4.view.ViewCompat.setAlpha
import android.support.v4.view.ViewCompat.animate
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.ListView
import android.widget.Toast
import com.tommasoberlose.anotherwidget.`object`.Constants
import com.tommasoberlose.anotherwidget.`object`.CustomLocationEvent
import com.tommasoberlose.anotherwidget.util.WeatherUtil
import kotlinx.android.synthetic.main.activity_custom_location.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.ThreadMode
import org.greenrobot.eventbus.Subscribe
class CustomLocationActivity : AppCompatActivity() {
lateinit var adapter: ArrayAdapter<String>
val addressesList = ArrayList<Address>()
@SuppressLint("ApplySharedPref")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_custom_location)
val SP = PreferenceManager.getDefaultSharedPreferences(this)
adapter = ArrayAdapter(this, R.layout.custom_location_item, addressesList.map { it.getAddressLine(0) })
list_view.adapter = adapter
list_view.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
SP.edit()
.putString(Constants.PREF_CUSTOM_LOCATION_LAT, addressesList[position].latitude.toString())
.putString(Constants.PREF_CUSTOM_LOCATION_LON, addressesList[position].longitude.toString())
.putString(Constants.PREF_CUSTOM_LOCATION_ADD, addressesList[position].getAddressLine(0))
.commit()
setResult(Activity.RESULT_OK)
finish()
}
action_geolocation.setOnClickListener {
SP.edit()
.remove(Constants.PREF_CUSTOM_LOCATION_LAT)
.remove(Constants.PREF_CUSTOM_LOCATION_LON)
.remove(Constants.PREF_CUSTOM_LOCATION_ADD)
.commit()
setResult(Activity.RESULT_OK)
finish()
}
location.addTextChangedListener(object: TextWatcher {
override fun afterTextChanged(text: Editable?) {
if (text != null && !text.equals("")) {
Thread().run {
val coder = Geocoder(this@CustomLocationActivity)
try {
val addresses = coder.getFromLocationName(text.toString(), 10) as ArrayList<Address>
EventBus.getDefault().post(CustomLocationEvent(addresses))
} catch (ignored: Exception) {
EventBus.getDefault().post(CustomLocationEvent(ArrayList<Address>()))
}
}
} else {
EventBus.getDefault().post(CustomLocationEvent(ArrayList<Address>()))
}
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
})
}
public override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
}
public override fun onStop() {
EventBus.getDefault().unregister(this)
super.onStop()
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onMessageEvent(event: CustomLocationEvent) {
adapter.clear()
addressesList.clear()
event.addresses.mapTo(addressesList, {it})
for (a:Address in addressesList) {
adapter.add(a.getAddressLine(0))
}
adapter.notifyDataSetChanged()
}
}

View File

@ -1,882 +0,0 @@
package com.tommasoberlose.anotherwidget.ui.activity
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.pm.PackageManager
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.appwidget.AppWidgetManager
import android.content.*
import android.preference.PreferenceManager
import android.view.View
import com.tommasoberlose.anotherwidget.`object`.Constants
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.util.Util
import com.tommasoberlose.anotherwidget.receiver.WeatherReceiver
import java.util.*
import java.util.concurrent.TimeUnit
import android.content.Intent
import android.content.BroadcastReceiver
import com.tommasoberlose.anotherwidget.util.CalendarUtil
import com.tommasoberlose.anotherwidget.util.WeatherUtil
import android.content.DialogInterface
import android.content.res.Resources
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.support.design.widget.BottomSheetDialog
import android.support.v4.content.ContextCompat
import android.text.Html
import android.text.Spannable
import android.text.SpannableString
import android.text.style.RelativeSizeSpan
import android.util.Log
import android.util.TypedValue
import android.widget.Toast
import com.crashlytics.android.Crashlytics
import com.pes.androidmaterialcolorpickerdialog.ColorPicker
import com.tommasoberlose.anotherwidget.`object`.CalendarSelector
import com.tommasoberlose.anotherwidget.receiver.UpdatesReceiver
import io.fabric.sdk.android.Fabric
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.key_time_wait_layout.view.*
import kotlinx.android.synthetic.main.main_menu_layout.view.*
import kotlinx.android.synthetic.main.the_widget.*
import kotlinx.android.synthetic.main.the_widget.view.*
import java.io.File
class MainActivity : AppCompatActivity() {
private var mAppWidgetId: Int = -1
private lateinit var SP: SharedPreferences
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
updateUI()
}
}
@SuppressLint("ApplySharedPref")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Fabric.with(this, Crashlytics())
sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE))
sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE))
SP = PreferenceManager.getDefaultSharedPreferences(this)
controlExtras(intent)
action_menu.setOnClickListener {
val mBottomSheetDialog = BottomSheetDialog(this)
val menuView: View = getLayoutInflater().inflate(R.layout.main_menu_layout, null)
menuView.action_share.setOnClickListener(object: View.OnClickListener {
override fun onClick(p0: View?) {
Util.share(this@MainActivity)
mBottomSheetDialog.dismiss()
}
})
if (SP.getBoolean(Constants.PREF_SHOW_WIDGET_PREVIEW, true)) {
menuView.widget_preview_icon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_action_hide_preview))
menuView.widget_preview_label.text = getString(R.string.action_hide_widget_preview)
menuView.action_toggle_widget_preview.setOnClickListener {
SP.edit()
.putBoolean(Constants.PREF_SHOW_WIDGET_PREVIEW, false)
.commit()
updateUI()
mBottomSheetDialog.dismiss()
}
} else {
menuView.widget_preview_icon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_action_show_preview))
menuView.widget_preview_label.text = getString(R.string.action_show_widget_preview)
menuView.action_toggle_widget_preview.setOnClickListener {
SP.edit()
.putBoolean(Constants.PREF_SHOW_WIDGET_PREVIEW, true)
.commit()
updateUI()
mBottomSheetDialog.dismiss()
}
}
menuView.action_rate.setOnClickListener(object: View.OnClickListener {
override fun onClick(p0: View?) {
Util.rateApp(this@MainActivity, "https://play.google.com/store/apps/details?id=com.tommasoberlose.anotherwidget")
mBottomSheetDialog.dismiss()
}
})
menuView.action_feedback.setOnClickListener(object: View.OnClickListener {
override fun onClick(p0: View?) {
Util.sendEmail(this@MainActivity)
mBottomSheetDialog.dismiss()
}
})
menuView.action_refresh.setOnClickListener {
WeatherUtil.updateWeather(this)
CalendarUtil.updateEventList(this)
Util.updateWidget(this)
mBottomSheetDialog.dismiss()
}
menuView.action_support.setOnClickListener {
startActivity(Intent(this, SupportDevActivity::class.java))
mBottomSheetDialog.dismiss()
}
mBottomSheetDialog.setContentView(menuView)
mBottomSheetDialog.show()
}
}
override fun onBackPressed() {
if (mAppWidgetId > 0) {
addNewWidget()
} else {
setResult(Activity.RESULT_OK)
finish()
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (intent != null) {
controlExtras(intent)
}
}
fun controlExtras(intent: Intent) {
val extras = intent.extras
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID)
if (mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
action_add_widget.visibility = View.VISIBLE
action_add_widget.setOnClickListener {
addNewWidget()
}
}
if (extras.containsKey(Constants.ACTION_EXTRA_OPEN_WEATHER_PROVIDER)) {
startActivityForResult(Intent(this, WeatherProviderActivity::class.java), Constants.WEATHER_PROVIDER_REQUEST_CODE)
}
if (extras.containsKey(Constants.ACTION_EXTRA_DISABLE_GPS_NOTIFICATION)) {
SP.edit()
.putBoolean(Constants.PREF_SHOW_GPS_NOTIFICATION, false)
.apply()
sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE))
finish()
}
}
}
fun addNewWidget() {
val resultValue = Intent()
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId)
setResult(Activity.RESULT_OK, resultValue)
finish()
sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE))
sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE))
}
override fun onResume() {
super.onResume()
val filter = IntentFilter()
filter.addAction(Constants.ACTION_SOMETHING_HAPPENED);
registerReceiver(receiver, filter);
updateUI()
}
override fun onPause() {
unregisterReceiver(receiver);
super.onPause();
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>,
grantResults: IntArray) {
when (requestCode) {
Constants.CALENDAR_REQUEST_CODE -> if (!(permissions.size != 1 || grantResults.size != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED)) {
sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE))
updateAppWidget()
updateSettings()
}
Constants.LOCATION_REQUEST_CODE -> if (!(permissions.size != 1 || grantResults.size != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED)) {
val SP = PreferenceManager.getDefaultSharedPreferences(this)
sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE))
updateAppWidget()
updateSettings()
}
}
}
fun updateUI() {
updateSettings()
updateAppWidget()
updateClockView()
if (SP.getBoolean(Constants.PREF_SHOW_WIDGET_PREVIEW, true)) {
val displayMetrics = Resources.getSystem().displayMetrics
var width = displayMetrics.widthPixels
if (width <= 0) {
width = Util.convertDpToPixel(300f, this).toInt()
}
var height = Util.convertDpToPixel(120f, this).toInt()
if (SP.getBoolean(Constants.PREF_SHOW_CLOCK, false)) {
height += Util.convertSpToPixels(SP.getFloat(Constants.PREF_TEXT_CLOCK_SIZE, 90f), this).toInt() + Util.convertDpToPixel(16f, this).toInt()
}
if (SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f) + SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) > 50) {
height += Util.convertDpToPixel(24f, this).toInt()
}
widget_bitmap.setImageBitmap(Util.getBitmapFromView(main_layout, width, height - Util.convertDpToPixel(32f, this).toInt()))
widget.layoutParams.height = height + Util.convertDpToPixel(16f, this).toInt()
widget.visibility = View.VISIBLE
} else {
widget.visibility = View.GONE
}
}
internal fun updateAppWidget() {
val wallpaper: Drawable? = Util.getCurrentWallpaper(this)
if (wallpaper != null) {
widget_bg.setImageDrawable(wallpaper)
}
widget_bg.setBackgroundColor(Color.WHITE)
updateCalendarView()
updateLocationView()
updateClockView()
}
@SuppressLint("ApplySharedPref")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == Constants.RESULT_CODE_CUSTOM_LOCATION && resultCode == Activity.RESULT_OK) {
sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE))
updateSettings()
} else if (requestCode == Constants.CALENDAR_APP_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
SP.edit()
.putString(Constants.PREF_CALENDAR_APP_NAME, if (data.getStringExtra(Constants.RESULT_APP_NAME) != "") data.getStringExtra(Constants.RESULT_APP_NAME) else getString(R.string.default_calendar_app))
.putString(Constants.PREF_CALENDAR_APP_PACKAGE, data.getStringExtra(Constants.RESULT_APP_PACKAGE))
.commit()
Util.updateWidget(this)
updateSettings()
} else if (requestCode == Constants.WEATHER_APP_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
SP.edit()
.putString(Constants.PREF_WEATHER_APP_NAME, if (data.getStringExtra(Constants.RESULT_APP_NAME) != "") data.getStringExtra(Constants.RESULT_APP_NAME) else getString(R.string.default_weather_app))
.putString(Constants.PREF_WEATHER_APP_PACKAGE, data.getStringExtra(Constants.RESULT_APP_PACKAGE))
.commit()
Util.updateWidget(this)
updateSettings()
} else if (requestCode == Constants.EVENT_APP_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
SP.edit()
.putString(Constants.PREF_EVENT_APP_NAME, if (data.getStringExtra(Constants.RESULT_APP_NAME) != "") data.getStringExtra(Constants.RESULT_APP_NAME) else getString(R.string.default_event_app))
.putString(Constants.PREF_EVENT_APP_PACKAGE, data.getStringExtra(Constants.RESULT_APP_PACKAGE))
.commit()
Util.updateWidget(this)
updateSettings()
} else if (requestCode == Constants.CLOCK_APP_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
SP.edit()
.putString(Constants.PREF_CLOCK_APP_NAME, if (data.getStringExtra(Constants.RESULT_APP_NAME) != "") data.getStringExtra(Constants.RESULT_APP_NAME) else getString(R.string.default_clock_app))
.putString(Constants.PREF_CLOCK_APP_PACKAGE, data.getStringExtra(Constants.RESULT_APP_PACKAGE))
.commit()
Util.updateWidget(this)
updateSettings()
} else if (requestCode == Constants.WEATHER_PROVIDER_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
WeatherReceiver().setOneTimeUpdate(this)
sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE))
updateSettings()
} else if (requestCode == Constants.CUSTOM_FONT_CHOOSER_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
/*val uri = data.data
Log.d("AW", "File Uri: " + uri.toString())
val path = Util.getPath(this, uri)
Log.d("AW", "File Path: " + path)
SP.edit()
.putString(Constants.PREF_CUSTOM_FONT_FILE, path)
.commit()
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
updateSettings()*/
}
}
fun updateClockView() {
if (!SP.getBoolean(Constants.PREF_SHOW_CLOCK, false)) {
time.visibility = View.GONE
} else {
time.visibility = View.VISIBLE
}
val now = Calendar.getInstance()
if (SP.getString(Constants.PREF_HOUR_FORMAT, "12") == "12") {
// time.format12Hour = "hh:mm a"
// val textBadHour = SpannableString(Constants.badHourFormat.format(time.))
// textBadHour.setSpan(RelativeSizeSpan(0.4f), textBadHour.length - 2,
// textBadHour.length, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//
// time.text = textBadHour
} else {
// time.format24Hour = "HH:mm"
// time.text = Constants.goodHourFormat.format(now.timeInMillis)
}
}
fun updateCalendarView() {
val now = Calendar.getInstance()
val calendarLayout = SP.getBoolean(Constants.PREF_SHOW_EVENTS, true) && Util.checkGrantedPermission(this, Manifest.permission.READ_CALENDAR)
empty_layout.visibility = View.VISIBLE
calendar_layout.visibility = View.GONE
var dateStringValue: String = Util.getCapWordString(Constants.engDateFormat.format(now.time))
if (SP.getBoolean(Constants.PREF_ITA_FORMAT_DATE, false)) {
dateStringValue = Util.getCapWordString(Constants.itDateFormat.format(now.time))
}
empty_date.text = dateStringValue
if (calendarLayout) {
val e = CalendarUtil.getNextEvent(this)
if (e.id != 0.toLong()) {
next_event.text = e.title
if (SP.getBoolean(Constants.PREF_SHOW_NEXT_EVENT, false) && CalendarUtil.getEventsCount(this) > 1) {
multiple_events.visibility = View.VISIBLE
} else {
multiple_events.visibility = View.GONE
}
if (SP.getBoolean(Constants.PREF_SHOW_DIFF_TIME, true)) {
next_event_difference_time.text = Util.getDifferenceText(this, now.timeInMillis, e.startDate)
next_event_difference_time.visibility = View.VISIBLE
} else {
next_event_difference_time.visibility = View.GONE
}
if (SP.getInt(Constants.PREF_SECOND_ROW_INFORMATION, 0) == 2 && Util.getNextAlarm(this) != null) {
second_row_icon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_action_alarm))
next_event_date.text = Util.getNextAlarm(this)
} else if (!e.address.equals("") && SP.getInt(Constants.PREF_SECOND_ROW_INFORMATION, 0) == 1) {
second_row_icon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_action_location))
next_event_date.text = e.address
} else {
second_row_icon.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_action_calendar))
if (!e.allDay) {
val startHour: String = if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) Constants.badHourFormat.format(e.startDate) else Constants.goodHourFormat.format(e.startDate)
val endHour: String = if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) Constants.badHourFormat.format(e.endDate) else Constants.goodHourFormat.format(e.endDate)
var dayDiff = TimeUnit.MILLISECONDS.toDays(e.endDate - e.startDate)
val startCal = Calendar.getInstance()
startCal.timeInMillis = e.startDate
val endCal = Calendar.getInstance()
endCal.timeInMillis = e.endDate
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
dayDiff++
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(Calendar.MINUTE) >= endCal.get(Calendar.MINUTE)) {
dayDiff++
}
var multipleDay: String = ""
if (dayDiff > 0) {
multipleDay = String.format(" (+%s%s)", dayDiff, getString(R.string.day_char))
}
next_event_date.text = String.format("%s - %s%s", startHour, endHour, multipleDay)
} else {
next_event_date.text = dateStringValue
}
}
empty_layout.visibility = View.GONE
calendar_layout.visibility = View.VISIBLE
}
}
empty_date.setTextColor(Util.getFontColor(SP))
divider1.setTextColor(Util.getFontColor(SP))
temp.setTextColor(Util.getFontColor(SP))
next_event.setTextColor(Util.getFontColor(SP))
next_event_difference_time.setTextColor(Util.getFontColor(SP))
next_event_date.setTextColor(Util.getFontColor(SP))
divider2.setTextColor(Util.getFontColor(SP))
calendar_temp.setTextColor(Util.getFontColor(SP))
second_row_icon.setColorFilter(Util.getFontColor(SP))
// time.setTextColor(Util.getFontColor(SP))
empty_date.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
divider1.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
temp.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
next_event.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
next_event_difference_time.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
next_event_date.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
divider2.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
calendar_temp.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
// time.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_CLOCK_SIZE, 90f))
second_row_icon.scaleX = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 18f
second_row_icon.scaleY = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 18f
weather_icon.scaleX = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 18f
weather_icon.scaleY = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 18f
empty_weather_icon.scaleX = SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f) / 24f
empty_weather_icon.scaleY = SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f) / 24f
multiple_events.scaleX = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 16f
multiple_events.scaleY = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 16f
val shadowRadius = when (SP.getInt(Constants.PREF_TEXT_SHADOW, 1)) {
0 -> 0f
1 -> 5f
2 -> 4f
else -> 5f
}
val shadowColor = when (SP.getInt(Constants.PREF_TEXT_SHADOW, 1)) {
0 -> Color.TRANSPARENT
1 -> R.color.black_50
2 -> Color.BLACK
else -> R.color.black_50
}
val shadowDy = when (SP.getInt(Constants.PREF_TEXT_SHADOW, 1)) {
0 -> 0f
1 -> 0f
2 -> 1f
else -> 0f
}
empty_date.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
divider1.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
temp.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
next_event.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
next_event_difference_time.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
next_event_date.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
divider2.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
calendar_temp.setShadowLayer(shadowRadius, 0f, 0f, shadowColor)
// time.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
if (SP.getInt(Constants.PREF_CUSTOM_FONT, Constants.CUSTOM_FONT_PRODUCT_SANS) == Constants.CUSTOM_FONT_PRODUCT_SANS) {
val product_sans: Typeface = Typeface.createFromAsset(assets, "fonts/product_sans_regular.ttf")
val product_sans_light: Typeface = Typeface.createFromAsset(assets, "fonts/product_sans_light.ttf")
/*if (SP.getString(Constants.PREF_CUSTOM_FONT_FILE, "") != "") {
val file = File(SP.getString(Constants.PREF_CUSTOM_FONT_FILE, ""))
if (file.exists()) {
Log.d("AW", "OK")
}
// product_sans = Typeface.createFromFile("")
}*/
empty_date.typeface = product_sans
divider1.typeface = product_sans
temp.typeface = product_sans
next_event.typeface = product_sans
next_event_difference_time.typeface = product_sans
next_event_date.typeface = product_sans
divider2.typeface = product_sans
calendar_temp.typeface = product_sans
//time.typeface = product_sans_light
} else {
empty_date.typeface = Typeface.DEFAULT
divider1.typeface = Typeface.DEFAULT
temp.typeface = Typeface.DEFAULT
next_event.typeface = Typeface.DEFAULT
next_event_difference_time.typeface = Typeface.DEFAULT
next_event_date.typeface = Typeface.DEFAULT
divider2.typeface = Typeface.DEFAULT
calendar_temp.typeface = Typeface.DEFAULT
//time.typeface = Typeface.DEFAULT
}
}
fun updateLocationView() {
val locationLayout = SP.getBoolean(Constants.PREF_SHOW_WEATHER, true)
if (locationLayout && SP.contains(Constants.PREF_WEATHER_TEMP) && SP.contains(Constants.PREF_WEATHER_ICON)) {
weather.visibility = View.VISIBLE
calendar_weather.visibility = View.VISIBLE
val currentTemp = String.format(Locale.getDefault(), "%.0f °%s", SP.getFloat(Constants.PREF_WEATHER_TEMP, 0f), SP.getString(Constants.PREF_WEATHER_REAL_TEMP_UNIT, "F"))
weather_icon.visibility = View.VISIBLE
empty_weather_icon.visibility = View.VISIBLE
val icon: String = SP.getString(Constants.PREF_WEATHER_ICON, "")
if (icon.equals("")) {
weather_icon.visibility = View.GONE
empty_weather_icon.visibility = View.GONE
} else {
weather_icon.setImageResource(WeatherUtil.getWeatherIconResource(icon))
empty_weather_icon.setImageResource(WeatherUtil.getWeatherIconResource(icon))
}
temp.text = currentTemp
calendar_temp.text = currentTemp
} else {
weather.visibility = View.GONE
calendar_weather.visibility = View.GONE
}
}
@SuppressLint("ApplySharedPref")
fun updateSettings() {
if (SP.getBoolean(Constants.PREF_SHOW_CLOCK, false)) {
clock_settings.visibility = View.VISIBLE
action_show_clock.setOnClickListener {
SP.edit()
.putBoolean(Constants.PREF_SHOW_CLOCK, false)
.commit()
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
}
show_clock_label.text = getString(R.string.show_clock_visible)
} else {
clock_settings.visibility= View.GONE
action_show_clock.setOnClickListener {
SP.edit()
.putBoolean(Constants.PREF_SHOW_CLOCK, true)
.commit()
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
}
show_clock_label.text = getString(R.string.show_clock_not_visible)
}
if (SP.getBoolean(Constants.PREF_SHOW_EVENTS, true) && Util.checkGrantedPermission(this, Manifest.permission.READ_CALENDAR)) {
calendar_settings.visibility = View.VISIBLE
action_show_events.setOnClickListener {
SP.edit()
.putBoolean(Constants.PREF_SHOW_EVENTS, false)
.commit()
sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE))
updateSettings()
updateAppWidget()
}
show_events_label.text = getString(R.string.show_events_visible)
} else {
calendar_settings.visibility= View.GONE
action_show_events.setOnClickListener {
if (Util.checkGrantedPermission(this, Manifest.permission.READ_CALENDAR)) {
SP.edit()
.putBoolean(Constants.PREF_SHOW_EVENTS, true)
.commit()
sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE))
updateSettings()
updateAppWidget()
} else {
ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.READ_CALENDAR), Constants.CALENDAR_REQUEST_CODE)
}
}
show_events_label.text = if (Util.checkGrantedPermission(this, Manifest.permission.READ_CALENDAR)) getString(R.string.show_events_not_visible) else getString(R.string.description_permission_calendar)
}
if (SP.getBoolean(Constants.PREF_SHOW_WEATHER, true) && Util.checkGrantedPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
weather_settings.visibility = View.VISIBLE
action_show_weather.setOnClickListener {
SP.edit()
.putBoolean(Constants.PREF_SHOW_WEATHER, false)
.commit()
sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE))
updateSettings()
updateAppWidget()
}
show_weather_label.text = getString(R.string.show_weather_visible)
} else {
weather_settings.visibility= View.GONE
action_show_weather.setOnClickListener {
if (Util.checkGrantedPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
SP.edit()
.putBoolean(Constants.PREF_SHOW_WEATHER, true)
.commit()
sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE))
updateSettings()
updateAppWidget()
} else {
ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), Constants.LOCATION_REQUEST_CODE)
}
}
show_weather_label.text = if (Util.checkGrantedPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) getString(R.string.show_weather_not_visible) else getString(R.string.description_permission_location)
}
temp_unit.text = if (SP.getString(Constants.PREF_WEATHER_TEMP_UNIT, "F").equals("F")) getString(R.string.fahrenheit) else getString(R.string.celsius)
action_change_unit.setOnClickListener {
SP.edit().putString(Constants.PREF_WEATHER_TEMP_UNIT, if (SP.getString(Constants.PREF_WEATHER_TEMP_UNIT, "F").equals("F")) "C" else "F").commit()
sendBroadcast(Intent(Constants.ACTION_WEATHER_UPDATE))
updateSettings()
}
all_day_label.text = if (SP.getBoolean(Constants.PREF_CALENDAR_ALL_DAY, false)) getString(R.string.settings_all_day_subtitle_visible) else getString(R.string.settings_all_day_subtitle_gone)
action_show_all_day.setOnClickListener {
SP.edit().putBoolean(Constants.PREF_CALENDAR_ALL_DAY, !SP.getBoolean(Constants.PREF_CALENDAR_ALL_DAY, false)).commit()
sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE))
updateSettings()
}
show_multiple_events_label.text = if (SP.getBoolean(Constants.PREF_SHOW_NEXT_EVENT, true)) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
action_show_multiple_events.setOnClickListener {
SP.edit().putBoolean(Constants.PREF_SHOW_NEXT_EVENT, !SP.getBoolean(Constants.PREF_SHOW_NEXT_EVENT, true)).commit()
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
updateSettings()
}
show_diff_time_label.text = if (SP.getBoolean(Constants.PREF_SHOW_DIFF_TIME, true)) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
action_show_diff_time.setOnClickListener {
SP.edit().putBoolean(Constants.PREF_SHOW_DIFF_TIME, !SP.getBoolean(Constants.PREF_SHOW_DIFF_TIME, true)).commit()
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
updateSettings()
}
show_declined_events_label.text = if (SP.getBoolean(Constants.PREF_SHOW_DECLINED_EVENTS, true)) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
action_show_declined_events.setOnClickListener {
SP.edit().putBoolean(Constants.PREF_SHOW_DECLINED_EVENTS, !SP.getBoolean(Constants.PREF_SHOW_DECLINED_EVENTS, true)).commit()
sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE))
updateSettings()
}
hour_format_label.text = if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) getString(R.string.settings_hour_format_subtitle_12) else getString(R.string.settings_hour_format_subtitle_24)
action_hour_format.setOnClickListener {
SP.edit().putString(Constants.PREF_HOUR_FORMAT, if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) "24" else "12").commit()
Util.updateWidget(this)
updateSettings()
updateAppWidget()
}
second_row_info_label.text = getString(Util.getSecondRowInfoString(SP.getInt(Constants.PREF_SECOND_ROW_INFORMATION, 0)))
action_second_row_info.setOnClickListener {
SP.edit().putInt(Constants.PREF_SECOND_ROW_INFORMATION, when (SP.getInt(Constants.PREF_SECOND_ROW_INFORMATION, 0)) {
0 -> 1
1 -> 2
2 -> 0
else -> 0
}).commit()
updateSettings()
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
}
main_text_size_label.text = String.format("%.0f%s", SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f), "sp")
action_main_text_size.setOnClickListener {
var fontSize = SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f) + 1
if (fontSize > 36) {
fontSize = 20f
}
SP.edit().putFloat(Constants.PREF_TEXT_MAIN_SIZE, fontSize).commit()
Util.updateWidget(this)
updateSettings()
updateAppWidget()
}
second_text_size_label.text = String.format("%.0f%s", SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f), "sp")
action_second_text_size.setOnClickListener {
var fontSize = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) + 1
if (fontSize > 28) {
fontSize = 12f
}
SP.edit().putFloat(Constants.PREF_TEXT_SECOND_SIZE, fontSize).commit()
Util.updateWidget(this)
updateSettings()
}
clock_text_size_label.text = String.format("%.0f%s", SP.getFloat(Constants.PREF_TEXT_CLOCK_SIZE, 90f), "sp")
action_clock_text_size.setOnClickListener {
var fontSize = SP.getFloat(Constants.PREF_TEXT_CLOCK_SIZE, 90f) + 5
if (fontSize > 110) {
fontSize = 50f
}
SP.edit().putFloat(Constants.PREF_TEXT_CLOCK_SIZE, fontSize).commit()
Util.updateWidget(this)
updateSettings()
}
val textColor = try {
Color.parseColor(SP.getString(Constants.PREF_TEXT_COLOR, "#FFFFFF"))
} catch (e: Exception) {
SP.edit().remove(Constants.PREF_TEXT_COLOR).commit()
Color.parseColor(SP.getString(Constants.PREF_TEXT_COLOR, "#FFFFFF"))
}
font_color_label.text = SP.getString(Constants.PREF_TEXT_COLOR, "#FFFFFF").toUpperCase()
action_font_color.setOnClickListener {
val cp: ColorPicker = ColorPicker(this@MainActivity, Color.red(textColor), Color.green(textColor), Color.blue(textColor))
cp.setOnColorSelected { color ->
SP.edit().putString(Constants.PREF_TEXT_COLOR, "#" + Integer.toHexString(color)).commit()
Util.updateWidget(this)
updateSettings()
updateAppWidget()
cp.dismiss()
}
cp.show()
}
val now = Calendar.getInstance()
var dateStringValue: String = String.format("%s%s", Constants.engDateFormat.format(now.time)[0].toUpperCase(), Constants.engDateFormat.format(now.time).substring(1))
if (SP.getBoolean(Constants.PREF_ITA_FORMAT_DATE, false)) {
dateStringValue = String.format("%s%s", Constants.itDateFormat.format(now.time)[0].toUpperCase(), Constants.itDateFormat.format(now.time).substring(1))
}
date_format_label.text = dateStringValue
action_date_format.setOnClickListener {
SP.edit().putBoolean(Constants.PREF_ITA_FORMAT_DATE, !SP.getBoolean(Constants.PREF_ITA_FORMAT_DATE, false)).commit()
Util.updateWidget(this)
updateAppWidget()
updateSettings()
}
label_weather_refresh_period.text = getString(Util.getRefreshPeriodString(SP.getInt(Constants.PREF_WEATHER_REFRESH_PERIOD, 1)))
action_weather_refresh_period.setOnClickListener {
SP.edit().putInt(Constants.PREF_WEATHER_REFRESH_PERIOD, when (SP.getInt(Constants.PREF_WEATHER_REFRESH_PERIOD, 1)) {
0 -> 1
1 -> 2
2 -> 3
3 -> 4
4 -> 5
5 -> 0
else -> 1
}).commit()
updateSettings()
WeatherReceiver().setUpdates(this@MainActivity)
}
show_until_label.text = getString(Util.getShowUntilString(SP.getInt(Constants.PREF_SHOW_UNTIL, 1)))
action_show_until.setOnClickListener {
SP.edit().putInt(Constants.PREF_SHOW_UNTIL, when (SP.getInt(Constants.PREF_SHOW_UNTIL, 1)) {
0 -> 1
1 -> 2
2 -> 3
3 -> 4
4 -> 5
5 -> 6
6 -> 7
7 -> 0
else -> 1
}).commit()
updateSettings()
sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE))
}
text_shadow_label.text = getString(Util.getTextShadowString(SP.getInt(Constants.PREF_TEXT_SHADOW, 1)))
action_text_shadow.setOnClickListener {
SP.edit().putInt(Constants.PREF_TEXT_SHADOW, when (SP.getInt(Constants.PREF_TEXT_SHADOW, 1)) {
0 -> 1
1 -> 2
2 -> 0
else -> 1
}).commit()
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
updateSettings()
updateAppWidget()
}
custom_font_label.text = getString(Util.getCustomFontLabel(SP.getInt(Constants.PREF_CUSTOM_FONT, Constants.CUSTOM_FONT_PRODUCT_SANS)))
action_custom_font.setOnClickListener {
SP.edit().putInt(Constants.PREF_CUSTOM_FONT, when (SP.getInt(Constants.PREF_CUSTOM_FONT, Constants.CUSTOM_FONT_PRODUCT_SANS)) {
0 -> Constants.CUSTOM_FONT_PRODUCT_SANS
Constants.CUSTOM_FONT_PRODUCT_SANS -> 0
else -> Constants.CUSTOM_FONT_PRODUCT_SANS
}).commit()
/*
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "* / *" TO FIX WITHOUT SPACE
intent.addCategory(Intent.CATEGORY_OPENABLE)
try {
startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), Constants.CUSTOM_FONT_CHOOSER_REQUEST_CODE)
} catch (ex: android.content.ActivityNotFoundException) {
Toast.makeText(this, "Please install a File Manager.", Toast.LENGTH_SHORT).show()
}
*/
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
updateSettings()
updateAppWidget()
}
if (SP.getInt(Constants.PREF_WEATHER_PROVIDER, Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS) == Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS) {
action_custom_location.visibility = View.GONE
} else {
label_custom_location.text = SP.getString(Constants.PREF_CUSTOM_LOCATION_ADD, getString(R.string.custom_location_gps))
action_custom_location.setOnClickListener {
startActivityForResult(Intent(this, CustomLocationActivity::class.java), Constants.RESULT_CODE_CUSTOM_LOCATION)
}
action_custom_location.visibility = View.VISIBLE
}
if (SP.getInt(Constants.PREF_WEATHER_PROVIDER, Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS) == Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS) {
label_weather_provider_api_key.text = getString(R.string.provider_google_awareness)
alert_icon.visibility = View.GONE
} else {
if (WeatherUtil.getWeatherProviderKey(this, SP) == ("")) {
label_weather_provider_api_key.text = getString(R.string.settings_weather_provider_api_key_subtitle_not_set)
alert_icon.visibility = View.VISIBLE
} else {
label_weather_provider_api_key.text = getString(when (SP.getInt(Constants.PREF_WEATHER_PROVIDER, Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS)) {
Constants.WEATHER_PROVIDER_OPEN_WEATHER -> R.string.provider_open_weather
else -> R.string.settings_weather_provider_api_key_subtitle_all_set
})
alert_icon.visibility = View.GONE
}
}
action_weather_provider_api_key.setOnClickListener {
startActivityForResult(Intent(this, WeatherProviderActivity::class.java), Constants.WEATHER_PROVIDER_REQUEST_CODE)
}
calendar_app_label.text = SP.getString(Constants.PREF_CALENDAR_APP_NAME, getString(R.string.default_calendar_app))
action_calendar_app.setOnClickListener {
val i = Intent(this, ChooseApplicationActivity::class.java)
i.putExtra("requestCode", Constants.CALENDAR_APP_REQUEST_CODE)
startActivityForResult(i, Constants.CALENDAR_APP_REQUEST_CODE)
}
weather_app_label.text = SP.getString(Constants.PREF_WEATHER_APP_NAME, getString(R.string.default_weather_app))
action_weather_app.setOnClickListener {
startActivityForResult(Intent(this, ChooseApplicationActivity::class.java), Constants.WEATHER_APP_REQUEST_CODE)
}
clock_app_label.text = SP.getString(Constants.PREF_CLOCK_APP_NAME, getString(R.string.default_clock_app))
action_clock_app.setOnClickListener {
startActivityForResult(Intent(this, ChooseApplicationActivity::class.java), Constants.CLOCK_APP_REQUEST_CODE)
}
event_app_label.text = SP.getString(Constants.PREF_EVENT_APP_NAME, getString(R.string.default_event_app))
action_event_app.setOnClickListener {
startActivityForResult(Intent(this, ChooseApplicationActivity::class.java), Constants.EVENT_APP_REQUEST_CODE)
}
action_filter_calendar.setOnClickListener {
val calendarSelectorList: List<CalendarSelector> = CalendarUtil.getCalendarList(this).map { CalendarSelector(it.id.toInt(), it.displayName, it.accountName) }
var calFiltered = SP.getString(Constants.PREF_CALENDAR_FILTER, "")
if (!calendarSelectorList.isEmpty()) {
val calNames = calendarSelectorList.map { if (it.name.equals(it.account_name)) String.format("%s: %s", getString(R.string.main_calendar), it.name) else it.name }.toTypedArray()
val calSelected = calendarSelectorList.map { !calFiltered.contains(" " + Integer.toString(it.id) + ",") }.toBooleanArray()
AlertDialog.Builder(this).setTitle(getString(R.string.settings_filter_calendar_subtitle))
.setMultiChoiceItems(calNames, calSelected,
DialogInterface.OnMultiChoiceClickListener { dialog, item, isChecked ->
val dialogItem: String = String.format(" %s%s", calendarSelectorList.get(item).id, ",")
calFiltered = calFiltered.replace(dialogItem, "");
if (!isChecked) {
calFiltered += dialogItem
}
})
.setPositiveButton(android.R.string.ok, { dialog: DialogInterface, _: Int ->
SP.edit().putString(Constants.PREF_CALENDAR_FILTER, calFiltered).commit()
sendBroadcast(Intent(Constants.ACTION_CALENDAR_UPDATE))
updateSettings()
})
.setNegativeButton(android.R.string.cancel, null)
.show()
} else {
Toast.makeText(this, R.string.calendar_settings_list_error, Toast.LENGTH_SHORT).show()
}
}
}
}

View File

@ -1,121 +0,0 @@
package com.tommasoberlose.anotherwidget.ui.activity
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import com.anjlab.android.iab.v3.BillingProcessor
import com.anjlab.android.iab.v3.TransactionDetails
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.util.Util
import kotlinx.android.synthetic.main.activity_support_dev.*
class SupportDevActivity : AppCompatActivity(), BillingProcessor.IBillingHandler {
internal lateinit var bp: BillingProcessor
internal val BILLING_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAox5CcxuoLJ6CmNS7s6lVQzJ253njKKGF8MoQ/gQ5gEw2Fr03fBvtHpiVMpnjhNLw5NMeIpzRvkVqeQ7BfkC7c0BLCJUqf/fFA11ArQe8na6QKt5O4d+v4sbHtP7mm3GQNPOBaqRzcpFZaiAbfk6mnalo+tzM47GXrQFt5bNSrMctCs7bbChqJfH2cyMW0F8DHWEEeO5xElBmH3lh4FVpwIUTPYJIV3n0yhE3qqRA0WXkDej66g/uAt/rebmMZLmwNwIive5cObU4o41YyKRv2wSAicrv3W40LftzXAOOordIbmzDFN8ksh3VrnESqwCDGG97nZVbPG/+3LD0xHWiRwIDAQAB"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_support_dev)
bp = BillingProcessor(this, BILLING_KEY, this)
action_website.setOnClickListener {
Util.openURI(this, "http://tommasoberlose.com/")
}
action_translate.setOnClickListener {
Util.openURI(this, "https://github.com/tommasoberlose/another-widget/blob/master/app/src/main/res/values/strings.xml")
}
}
override fun onBillingInitialized() {
loader.visibility = View.GONE
try {
val isAvailable = BillingProcessor.isIabServiceAvailable(this)
val isOneTimePurchaseSupported = bp.isOneTimePurchaseSupported
if (isAvailable && isOneTimePurchaseSupported) {
val coffee = bp.getPurchaseListingDetails("donation_coffee")
val donuts = bp.getPurchaseListingDetails("donation_donuts")
val breakfast = bp.getPurchaseListingDetails("donation_breakfast")
val lunch = bp.getPurchaseListingDetails("donation_lunch")
val dinner = bp.getPurchaseListingDetails("donation_dinner")
if (coffee != null) {
import_donation_coffee.text = coffee.priceText
action_donation_coffee.setOnClickListener {
bp.purchase(this, "donation_coffee")
}
} else {
action_donation_coffee.visibility = View.GONE
}
if (donuts != null) {
import_donation_donuts.text = donuts.priceText
action_donation_donuts.setOnClickListener {
bp.purchase(this, "donation_donuts")
}
} else {
action_donation_donuts.visibility = View.GONE
}
if (breakfast != null) {
import_donation_breakfast.text = breakfast.priceText
action_donation_breakfast.setOnClickListener {
bp.purchase(this, "donation_breakfast")
}
} else {
action_donation_breakfast.visibility = View.GONE
}
if (lunch != null) {
import_donation_lunch.text = lunch.priceText
action_donation_lunch.setOnClickListener {
bp.purchase(this, "donation_lunch")
}
} else {
action_donation_lunch.visibility = View.GONE
}
if (dinner != null) {
import_donation_dinner.text = dinner.priceText
action_donation_dinner.setOnClickListener {
bp.purchase(this, "donation_dinner")
}
} else {
action_donation_dinner.visibility = View.GONE
}
products_list.visibility = View.VISIBLE
} else {
products_card.visibility = View.GONE
}
} catch (ignored: Exception) {
products_card.visibility = View.GONE
}
}
override fun onPurchaseHistoryRestored() {
}
override fun onProductPurchased(productId: String, details: TransactionDetails?) {
Toast.makeText(this, R.string.thanks, Toast.LENGTH_SHORT).show()
bp.consumePurchase(productId)
}
override fun onBillingError(errorCode: Int, error: Throwable?) {
Toast.makeText(this, R.string.error, Toast.LENGTH_SHORT).show()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (!bp.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data)
}
}
public override fun onDestroy() {
bp.release()
super.onDestroy()
}
}

View File

@ -1,119 +0,0 @@
package com.tommasoberlose.anotherwidget.ui.activity
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.ClipboardManager
import android.content.Context
import android.content.DialogInterface
import android.content.SharedPreferences
import android.os.Build
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.preference.PreferenceManager
import android.support.design.widget.BottomSheetDialog
import android.text.Editable
import android.text.Html
import android.text.TextWatcher
import android.view.View
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.`object`.Constants
import com.tommasoberlose.anotherwidget.util.CalendarUtil
import com.tommasoberlose.anotherwidget.util.Util
import com.tommasoberlose.anotherwidget.util.WeatherUtil
import kotlinx.android.synthetic.main.activity_weather_provider.*
import kotlinx.android.synthetic.main.key_time_wait_layout.view.*
import kotlinx.android.synthetic.main.main_menu_layout.view.*
import kotlinx.android.synthetic.main.provider_info_layout.view.*
class WeatherProviderActivity : AppCompatActivity() {
lateinit var SP: SharedPreferences
@SuppressLint("ApplySharedPref")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_weather_provider)
SP = PreferenceManager.getDefaultSharedPreferences(this)
updateUI()
action_save.setOnClickListener {
SP.edit()
.putString(WeatherUtil.getWeatherProviderKeyConstant(this, SP), api_key.text.toString())
.commit()
setResult(Activity.RESULT_OK)
finish()
}
api_key.addTextChangedListener(object: TextWatcher {
override fun afterTextChanged(text: Editable?) {
if (text.toString().equals("") || text.toString().equals(
WeatherUtil.getWeatherProviderKey(this@WeatherProviderActivity, SP))) {
Util.collapse(button_container)
} else {
Util.expand(button_container)
}
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
})
action_open_provider.setOnClickListener {
Util.openURI(this, "https://home.openweathermap.org/users/sign_up")
}
}
@SuppressLint("ApplySharedPref")
private fun updateUI() {
val currentProvider = SP.getInt(Constants.PREF_WEATHER_PROVIDER, Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS)
if (currentProvider == Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS) {
api_key_container.visibility = View.GONE
content_info.visibility = View.GONE
} else {
api_key_container.visibility = View.VISIBLE
content_info.visibility = View.VISIBLE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
last_info.text = Html.fromHtml(getString(R.string.api_key_info_all_set), Html.FROM_HTML_MODE_LEGACY)
} else {
last_info.text = Html.fromHtml(getString(R.string.api_key_info_all_set))
}
}
label_weather_provider.text = when (currentProvider) {
Constants.WEATHER_PROVIDER_OPEN_WEATHER -> getString(R.string.provider_open_weather)
else -> getString(R.string.provider_google_awareness)
}
action_change_provider.setOnClickListener {
SP.edit()
.putInt(Constants.PREF_WEATHER_PROVIDER, when (currentProvider) {
Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS -> Constants.WEATHER_PROVIDER_OPEN_WEATHER
else -> Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS
}).commit()
updateUI()
}
Util.collapse(button_container)
api_key.setText(WeatherUtil.getWeatherProviderKey(this, SP))
}
override fun onBackPressed() {
val SP = PreferenceManager.getDefaultSharedPreferences(this)
if (!SP.getInt(Constants.PREF_WEATHER_PROVIDER, Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS).equals(Constants.WEATHER_PROVIDER_GOOGLE_AWARENESS) && (api_key.text.toString().equals("") || !api_key.text.toString().equals(WeatherUtil.getWeatherProviderKey(this, SP)))) {
AlertDialog.Builder(this)
.setMessage(getString(R.string.error_weather_api_key))
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.yes, DialogInterface.OnClickListener { _,_ ->
super.onBackPressed()
})
.show()
} else {
super.onBackPressed()
}
}
}

View File

@ -1,52 +0,0 @@
package com.tommasoberlose.anotherwidget.ui.adapter
import android.content.Context
import android.content.pm.ApplicationInfo
import android.support.v7.widget.RecyclerView
import android.util.EventLog
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.`object`.AppInfoSavedEvent
import org.greenrobot.eventbus.EventBus
import java.io.File
/**
* Created by tommaso on 15/10/17.
*/
class ApplicationInfoAdapter (private val context: Context, private var mDataset: ArrayList<ApplicationInfo>) : RecyclerView.Adapter<ApplicationInfoAdapter.ViewHolder>() {
class ViewHolder(var view: View, var text: TextView, var icon: ImageView) : RecyclerView.ViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.application_info_layout, parent, false)
return ViewHolder(v, v.findViewById(R.id.text), v.findViewById(R.id.icon))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val pm = context.packageManager
val app = mDataset[position]
holder.text.text = pm.getApplicationLabel(app).toString()
try {
holder.icon.setImageDrawable(app.loadIcon(pm))
} catch (ignore: Exception) {
}
holder.view.setOnClickListener {
EventBus.getDefault().post(AppInfoSavedEvent(app))
}
}
override fun getItemCount(): Int {
return mDataset.size
}
fun changeData(newData: ArrayList<ApplicationInfo>) {
mDataset = newData
notifyDataSetChanged()
}
}

View File

@ -0,0 +1,22 @@
package com.tommasoberlose.anotherwidget.ui.adapters
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.tommasoberlose.anotherwidget.ui.fragments.*
class ViewPagerAdapter(fragmentActivity: FragmentActivity) :
FragmentStateAdapter(fragmentActivity) {
override fun getItemCount(): Int = 5
override fun createFragment(position: Int): Fragment {
return when (position) {
1 -> CalendarSettingsFragment.newInstance()
2 -> WeatherSettingsFragment.newInstance()
3 -> ClockSettingsFragment.newInstance()
4 -> AdvancedSettingsFragment.newInstance()
else -> GeneralSettingsFragment.newInstance()
}
}
}

View File

@ -0,0 +1,175 @@
package com.tommasoberlose.anotherwidget.ui.fragments
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatDelegate
import androidx.databinding.DataBindingUtil
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.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.utils.openURI
import kotlinx.android.synthetic.main.fragment_advanced_settings.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class AdvancedSettingsFragment : Fragment() {
companion object {
fun newInstance() = AdvancedSettingsFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
val binding = DataBindingUtil.inflate<FragmentAdvancedSettingsBinding>(inflater, R.layout.fragment_advanced_settings, container, false)
subscribeUi(binding, viewModel)
binding.lifecycleOwner = this
binding.viewModel = viewModel
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupListener()
}
private fun subscribeUi(
binding: FragmentAdvancedSettingsBinding,
viewModel: MainViewModel
) {
viewModel.darkThemePreference.observe(viewLifecycleOwner, Observer {
AppCompatDelegate.setDefaultNightMode(it)
theme.text = when (it) {
AppCompatDelegate.MODE_NIGHT_NO -> getString(R.string.settings_subtitle_dark_theme_light)
AppCompatDelegate.MODE_NIGHT_YES -> getString(R.string.settings_subtitle_dark_theme_dark)
AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY -> getString(R.string.settings_subtitle_dark_theme_by_battery_saver)
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -> getString(R.string.settings_subtitle_dark_theme_follow_system)
else -> ""
}
})
viewModel.showWallpaper.observe(viewLifecycleOwner, Observer {
show_wallpaper_label.text = if (it && requireActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
})
}
private fun setupListener() {
action_change_theme.setOnClickListener {
maintainScrollPosition {
BottomSheetMenu<Int>(requireContext())
.selectResource(Preferences.darkThemePreference)
.addItem(
getString(R.string.settings_subtitle_dark_theme_light),
AppCompatDelegate.MODE_NIGHT_NO
)
.addItem(
getString(R.string.settings_subtitle_dark_theme_dark),
AppCompatDelegate.MODE_NIGHT_YES
)
.addItem(
getString(R.string.settings_subtitle_dark_theme_default),
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
)
.addOnSelectItemListener { value ->
Preferences.darkThemePreference = value
}.show()
}
}
action_show_wallpaper.setOnClickListener {
maintainScrollPosition {
if (Preferences.showWallpaper) {
Preferences.showWallpaper = false
} else {
requirePermission()
}
}
}
action_translate.setOnClickListener {
activity?.openURI("https://github.com/tommasoberlose/another-widget/blob/master/app/src/main/res/values/strings.xml")
}
action_website.setOnClickListener {
activity?.openURI("http://tommasoberlose.com/")
}
action_help_dev.setOnClickListener {
startActivity(Intent(requireContext(), SupportDevActivity::class.java))
}
action_refresh_widget.setOnClickListener {
Util.updateWidget(requireContext())
CalendarUtil.updateEventList(requireContext())
}
}
private fun maintainScrollPosition(callback: () -> Unit) {
val scrollPosition = scrollView.scrollY
callback.invoke()
lifecycleScope.launch {
delay(200)
scrollView.smoothScrollTo(0, scrollPosition)
}
}
private fun requirePermission() {
Dexter.withContext(requireContext())
.withPermissions(
Manifest.permission.READ_EXTERNAL_STORAGE
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {
Preferences.showWallpaper = report.areAllPermissionsGranted()
}
}
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?
) {
// Remember to invoke this method when the custom rationale is closed
// or just by default if you don't want to use any custom rationale.
token?.continuePermissionRequest()
}
})
.check()
}
}

View File

@ -0,0 +1,330 @@
package com.tommasoberlose.anotherwidget.ui.fragments
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.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
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.chibatching.kotpref.bulk
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
import com.tommasoberlose.anotherwidget.components.CalendarSelector
import com.tommasoberlose.anotherwidget.databinding.FragmentCalendarSettingsBinding
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
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.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.*
class CalendarSettingsFragment : Fragment() {
companion object {
fun newInstance() = CalendarSettingsFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
val binding = DataBindingUtil.inflate<FragmentCalendarSettingsBinding>(inflater, R.layout.fragment_calendar_settings, container, false)
subscribeUi(binding, viewModel)
binding.lifecycleOwner = this
binding.viewModel = viewModel
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupListener()
}
private fun subscribeUi(
binding: FragmentCalendarSettingsBinding,
viewModel: MainViewModel
) {
viewModel.showEvents.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
binding.isCalendarEnabled = it
}
checkReadEventsPermission()
})
viewModel.calendarAllDay.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
all_day_label.text =
if (it) getString(R.string.settings_all_day_subtitle_visible) else getString(R.string.settings_all_day_subtitle_gone)
}
checkReadEventsPermission()
})
viewModel.showDeclinedEvents.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
show_declined_events_label.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
}
checkReadEventsPermission()
})
viewModel.secondRowInformation.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
second_row_info_label.text = getString(Util.getSecondRowInfoString(it))
}
})
viewModel.showDiffTime.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
show_diff_time_label.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
}
})
viewModel.showUntil.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
show_until_label.text = getString(Util.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)
})
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
}
})
viewModel.calendarAppName.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
calendar_app_label.text = if (it != "") it else getString(R.string.default_calendar_app)
}
})
viewModel.eventAppName.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
event_app_label.text = if (it != "") it else getString(R.string.default_calendar_app)
}
})
}
private fun setupListener() {
action_show_events.setOnClickListener {
Preferences.showEvents = !Preferences.showEvents
}
action_filter_calendar.setOnClickListener {
val calendarSelectorList: List<CalendarSelector> = CalendarUtil.getCalendarList(requireContext()).map { CalendarSelector(it.id.toInt(), it.displayName, it.accountName) }
var calFiltered = Preferences.calendarFilter
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()
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
}
}
.setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int ->
Preferences.calendarFilter = calFiltered
}
.setNegativeButton(android.R.string.cancel, null)
.show()
} else {
requireActivity().toast(getString(R.string.calendar_settings_list_error))
}
}
action_show_all_day.setOnClickListener {
if (Preferences.showEvents) {
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.calendarAllDay)
.addItem(getString(R.string.settings_all_day_subtitle_visible), true)
.addItem(getString(R.string.settings_all_day_subtitle_gone), false)
.addOnSelectItemListener { value ->
Preferences.calendarAllDay = value
}.show()
}
}
action_show_declined_events.setOnClickListener {
if (Preferences.showEvents) {
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.showDeclinedEvents)
.addItem(getString(R.string.settings_visible), true)
.addItem(getString(R.string.settings_not_visible), false)
.addOnSelectItemListener { value ->
Preferences.showDeclinedEvents = value
}.show()
}
}
action_show_multiple_events.setOnClickListener {
if (Preferences.showEvents) {
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.showNextEvent)
.addItem(getString(R.string.settings_visible), true)
.addItem(getString(R.string.settings_not_visible), false)
.addOnSelectItemListener { value ->
Preferences.showNextEvent = value
}.show()
}
}
action_show_diff_time.setOnClickListener {
if (Preferences.showEvents) {
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.showDiffTime)
.addItem(getString(R.string.settings_visible), true)
.addItem(getString(R.string.settings_not_visible), false)
.addOnSelectItemListener { value ->
Preferences.showDiffTime = value
}.show()
}
}
action_second_row_info.setOnClickListener {
if (Preferences.showEvents) {
val dialog = BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.secondRowInformation)
(0 .. 1).forEach {
dialog.addItem(getString(Util.getSecondRowInfoString(it)), it)
}
dialog.addOnSelectItemListener { value ->
Preferences.secondRowInformation = value
}.show()
}
}
action_show_until.setOnClickListener {
if (Preferences.showEvents) {
val dialog = BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.showUntil)
intArrayOf(6,7,0,1,2,3,4,5).forEach {
dialog.addItem(getString(Util.getShowUntilString(it)), it)
}
dialog.addOnSelectItemListener { value ->
Preferences.showUntil = value
}.show()
}
}
action_event_app.setOnClickListener {
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java), RequestCode.EVENT_APP_REQUEST_CODE.code)
}
action_calendar_app.setOnClickListener {
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java), RequestCode.CALENDAR_APP_REQUEST_CODE.code)
}
}
private fun checkReadEventsPermission(showEvents: Boolean = Preferences.showEvents) {
if (requireActivity().checkCallingOrSelfPermission(Manifest.permission.READ_CALENDAR) == PackageManager.PERMISSION_GRANTED) {
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())
} 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
read_calendar_permission_alert_icon.setOnClickListener {
requirePermission()
}
}
}
private fun requirePermission() {
Dexter.withContext(requireActivity())
.withPermissions(
Manifest.permission.READ_CALENDAR
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {
if (report.areAllPermissionsGranted()){
checkReadEventsPermission()
}
}
}
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?
) {
// Remember to invoke this method when the custom rationale is closed
// or just by default if you don't want to use any custom rationale.
token?.continuePermissionRequest()
}
})
.check()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
RequestCode.CALENDAR_APP_REQUEST_CODE.code -> {
Preferences.bulk {
calendarAppName = data?.getStringExtra(Constants.RESULT_APP_NAME) ?: getString(R.string.default_calendar_app)
calendarAppPackage = data?.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: ""
}
}
RequestCode.EVENT_APP_REQUEST_CODE.code -> {
Preferences.bulk {
eventAppName = data?.getStringExtra(Constants.RESULT_APP_NAME) ?: getString(R.string.default_event_app)
eventAppPackage = data?.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: ""
}
}
}
}
super.onActivityResult(requestCode, resultCode, data)
}
private fun maintainScrollPosition(callback: () -> Unit) {
val scrollPosition = scrollView.scrollY
callback.invoke()
lifecycleScope.launch {
delay(200)
scrollView.smoothScrollTo(0, scrollPosition)
}
}
}

View File

@ -0,0 +1,149 @@
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.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
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
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
class ClockSettingsFragment : Fragment() {
companion object {
fun newInstance() = ClockSettingsFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
val binding = DataBindingUtil.inflate<FragmentClockSettingsBinding>(inflater, R.layout.fragment_clock_settings, container, false)
subscribeUi(binding, viewModel)
binding.lifecycleOwner = this
binding.viewModel = viewModel
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupListener()
}
private fun subscribeUi(
binding: FragmentClockSettingsBinding,
viewModel: MainViewModel
) {
viewModel.showClock.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
show_clock_label.text =
if (it) getString(R.string.show_clock_visible) else getString(R.string.show_clock_not_visible)
binding.isClockVisible = it
}
})
viewModel.clockTextSize.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
clock_text_size_label.text = String.format("%.0fsp", it)
}
})
viewModel.showNextAlarm.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
show_next_alarm_label.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
}
})
viewModel.clockAppName.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
clock_app_label.text =
if (Preferences.clockAppName != "") Preferences.clockAppName else getString(R.string.default_clock_app)
}
})
}
private fun setupListener() {
action_show_clock.setOnClickListener {
Preferences.showClock = !Preferences.showClock
}
action_clock_text_size.setOnClickListener {
val dialog = BottomSheetMenu<Float>(requireContext()).selectResource(Preferences.clockTextSize)
(46 downTo 28).filter { it % 2 == 0 }.forEach {
dialog.addItem("${it}sp", it.toFloat())
}
dialog.addOnSelectItemListener { value ->
Preferences.clockTextSize = value
}.show()
}
action_show_next_alarm.setOnClickListener {
BottomSheetMenu<Boolean>(requireContext()).selectResource(Preferences.showNextAlarm)
.addItem(getString(R.string.settings_visible), true)
.addItem(getString(R.string.settings_not_visible), false)
.addOnSelectItemListener { value ->
Preferences.showNextAlarm = value
}.show()
}
action_clock_app.setOnClickListener {
if (Preferences.showClock) {
startActivityForResult(Intent(requireActivity(), ChooseApplicationActivity::class.java),
RequestCode.CLOCK_APP_REQUEST_CODE.code
)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && requestCode == RequestCode.CLOCK_APP_REQUEST_CODE.code) {
Preferences.bulk {
clockAppName = data?.getStringExtra(Constants.RESULT_APP_NAME) ?: getString(R.string.default_clock_app)
clockAppPackage = data?.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: ""
}
}
super.onActivityResult(requestCode, resultCode, data)
}
private fun maintainScrollPosition(callback: () -> Unit) {
val scrollPosition = scrollView.scrollY
callback.invoke()
lifecycleScope.launch {
delay(200)
scrollView.smoothScrollTo(0, scrollPosition)
}
}
}

View File

@ -0,0 +1,208 @@
package com.tommasoberlose.anotherwidget.ui.fragments
import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.tommasoberlose.anotherwidget.R
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.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() {
companion object {
fun newInstance() = GeneralSettingsFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
val binding = DataBindingUtil.inflate<FragmentGeneralSettingsBinding>(inflater, R.layout.fragment_general_settings, container, false)
subscribeUi(binding, viewModel)
binding.lifecycleOwner = this
binding.viewModel = viewModel
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupListener()
}
private fun subscribeUi(
binding: FragmentGeneralSettingsBinding,
viewModel: MainViewModel
) {
viewModel.textMainSize.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
main_text_size_label.text = String.format("%.0fsp", it)
}
})
viewModel.textSecondSize.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
second_text_size_label.text = String.format("%.0fsp", it)
}
})
viewModel.textGlobalColor.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
try {
Color.parseColor(it)
} catch (e: Exception) {
Preferences.textGlobalColor = "#FFFFFF"
}
font_color_label.text = it.toUpperCase()
}
})
viewModel.textShadow.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
text_shadow_label.text = getString(Util.getTextShadowString(it))
}
})
viewModel.customFont.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
custom_font_label.text = getString(Util.getCustomFontLabel(it))
}
})
}
private fun maintainScrollPosition(callback: () -> Unit) {
val scrollPosition = scrollView.scrollY
callback.invoke()
lifecycleScope.launch {
delay(200)
scrollView.smoothScrollTo(0, scrollPosition)
}
}
private fun setupListener() {
action_main_text_size.setOnClickListener {
val dialog = BottomSheetMenu<Float>(requireContext()).selectResource(Preferences.textMainSize)
(32 downTo 20).filter { it % 2 == 0 }.forEach {
dialog.addItem("${it}sp", it.toFloat())
}
dialog.addOnSelectItemListener { value ->
Preferences.textMainSize = value
}.show()
}
action_second_text_size.setOnClickListener {
val dialog = BottomSheetMenu<Float>(requireContext()).selectResource(Preferences.textSecondSize)
(24 downTo 12).filter { it % 2 == 0 }.forEach {
dialog.addItem("${it}sp", it.toFloat())
}
dialog.addOnSelectItemListener { value ->
Preferences.textSecondSize = value
}.show()
}
action_font_color.setOnClickListener {
val textColor = try {
Color.parseColor(Preferences.textGlobalColor)
} catch (e: Exception) {
Preferences.textGlobalColor = "#FFFFFF"
Color.parseColor(Preferences.textGlobalColor)
}
ColorSheet()
.cornerRadius(16.toPixel(requireContext()))
.colorPicker(
colors = requireActivity().resources.getIntArray(R.array.grey),
selectedColor = textColor,
listener = { color ->
Preferences.textGlobalColor = "#" + Integer.toHexString(color)
})
.show(requireActivity().supportFragmentManager)
}
action_text_shadow.setOnClickListener {
val dialog = BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.textShadow)
(2 downTo 0).forEach {
dialog.addItem(getString(Util.getTextShadowString(it)), it)
}
dialog.addOnSelectItemListener { value ->
Preferences.textShadow = value
}.show()
}
action_custom_font.setOnClickListener {
val dialog = BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.customFont)
(0..1).forEach {
dialog.addItem(getString(Util.getCustomFontLabel(it)), it)
}
dialog.addOnSelectItemListener { value ->
Preferences.customFont = value
}.show()
/*
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "* / *" TO FIX WITHOUT SPACE
intent.addCategory(Intent.CATEGORY_OPENABLE)
try {
startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), Constants.CUSTOM_FONT_CHOOSER_REQUEST_CODE)
} catch (ex: android.content.ActivityNotFoundException) {
Toast.makeText(this, "Please install a File Manager.", Toast.LENGTH_SHORT).show()
}
*/
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code -> {
/*val uri = data.data
Log.d("AW", "File Uri: " + uri.toString())
val path = Util.getPath(this, uri)
Log.d("AW", "File Path: " + path)
SP.edit()
.putString(Constants.PREF_CUSTOM_FONT_FILE, path)
.commit()
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
updateSettings()*/
}
}
}
super.onActivityResult(requestCode, resultCode, data)
}
}

View File

@ -0,0 +1,253 @@
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
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.chibatching.kotpref.bulk
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
import com.tommasoberlose.anotherwidget.databinding.FragmentWeatherSettingsBinding
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.global.RequestCode
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 kotlinx.android.synthetic.main.fragment_weather_settings.*
import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class WeatherSettingsFragment : Fragment() {
companion object {
fun newInstance() = WeatherSettingsFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
val binding = DataBindingUtil.inflate<FragmentWeatherSettingsBinding>(inflater, R.layout.fragment_weather_settings, container, false)
subscribeUi(binding, viewModel)
binding.lifecycleOwner = this
binding.viewModel = viewModel
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupListener()
}
private fun subscribeUi(
binding: FragmentWeatherSettingsBinding,
viewModel: MainViewModel
) {
viewModel.showWeather.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
show_weather_label.text =
if (it) getString(R.string.show_weather_visible) else getString(R.string.show_weather_not_visible)
binding.isWeatherVisible = it
}
checkLocationPermission()
})
viewModel.weatherProviderApi.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
label_weather_provider_api_key.text =
if (it == "") getString(R.string.settings_weather_provider_api_key_subtitle_not_set) else getString(
R.string.settings_weather_provider_api_key_subtitle_all_set
)
api_key_alert_icon.isVisible = it == ""
}
checkLocationPermission()
})
viewModel.customLocationAdd.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
label_custom_location.text =
if (it == "") getString(R.string.custom_location_gps) else it
}
checkLocationPermission()
})
viewModel.weatherTempUnit.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
temp_unit.text =
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
}
})
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
label_weather_refresh_period.text = getString(Util.getRefreshPeriodString(it))
}
checkLocationPermission()
})
viewModel.weatherAppName.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
weather_app_label.text =
if (it != "") it else getString(R.string.default_weather_app)
}
})
}
private fun checkLocationPermission() {
if (requireActivity().checkCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
location_permission_alert_icon.isVisible = false
WeatherReceiver.setUpdates(requireContext())
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
location_permission_alert_icon.isVisible = true
location_permission_alert_icon.setOnClickListener {
requirePermission()
}
}
}
private fun setupListener() {
action_show_weather.setOnClickListener {
Preferences.showWeather = !Preferences.showWeather
}
action_weather_provider_api_key.setOnClickListener {
if (Preferences.showWeather) {
startActivityForResult(
Intent(requireContext(), WeatherProviderActivity::class.java),
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code
)
}
}
action_custom_location.setOnClickListener {
if (Preferences.showWeather) {
startActivityForResult(
Intent(requireContext(), CustomLocationActivity::class.java),
Constants.RESULT_CODE_CUSTOM_LOCATION
)
}
}
action_change_unit.setOnClickListener {
if (Preferences.showWeather) {
BottomSheetMenu<String>(requireContext()).selectResource(Preferences.weatherTempUnit)
.addItem(getString(R.string.fahrenheit), "F")
.addItem(getString(R.string.celsius), "C")
.addOnSelectItemListener { value ->
Preferences.weatherTempUnit = value
}.show()
}
}
action_weather_refresh_period.setOnClickListener {
if (Preferences.showWeather) {
val dialog =
BottomSheetMenu<Int>(requireContext()).selectResource(Preferences.weatherRefreshPeriod)
(5 downTo 0).forEach {
dialog.addItem(getString(Util.getRefreshPeriodString(it)), it)
}
dialog
.addOnSelectItemListener { value ->
Preferences.weatherRefreshPeriod = value
}.show()
}
}
action_weather_app.setOnClickListener {
if (Preferences.showWeather) {
startActivityForResult(
Intent(requireContext(), ChooseApplicationActivity::class.java),
RequestCode.WEATHER_APP_REQUEST_CODE.code
)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
Constants.RESULT_CODE_CUSTOM_LOCATION -> {
WeatherReceiver.setUpdates(requireContext())
}
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())
}
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
WeatherReceiver.setOneTimeUpdate(requireContext())
}
}
}
super.onActivityResult(requestCode, resultCode, data)
}
private fun requirePermission() {
Dexter.withContext(requireActivity())
.withPermissions(
Manifest.permission.ACCESS_FINE_LOCATION
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {
if (report.areAllPermissionsGranted()){
checkLocationPermission()
}
}
}
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?
) {
// Remember to invoke this method when the custom rationale is closed
// or just by default if you don't want to use any custom rationale.
token?.continuePermissionRequest()
}
})
.check()
}
private fun maintainScrollPosition(callback: () -> Unit) {
val scrollPosition = scrollView.scrollY
callback.invoke()
lifecycleScope.launch {
delay(200)
scrollView.smoothScrollTo(0, scrollPosition)
}
}
}

View File

@ -1,38 +0,0 @@
package com.tommasoberlose.anotherwidget.ui.view
import android.graphics.Paint
import android.graphics.Typeface
import android.text.TextPaint
import android.text.style.TypefaceSpan
class CustomTypefaceSpan(family: String, private val newType: Typeface) : TypefaceSpan(family) {
override fun updateDrawState(ds: TextPaint) {
applyCustomTypeFace(ds, newType)
}
override fun updateMeasureState(paint: TextPaint) {
applyCustomTypeFace(paint, newType)
}
private fun applyCustomTypeFace(paint: Paint, tf: Typeface) {
val oldStyle: Int
val old = paint.typeface
if (old == null) {
oldStyle = 0
} else {
oldStyle = old.style
}
val fake = oldStyle and tf.style.inv()
if (fake and Typeface.BOLD != 0) {
paint.isFakeBoldText = true
}
if (fake and Typeface.ITALIC != 0) {
paint.textSkewX = -0.25f
}
paint.typeface = tf
}
}

View File

@ -1,49 +0,0 @@
package com.tommasoberlose.anotherwidget.ui.view
import android.content.Context
import android.graphics.Typeface
import android.content.res.TypedArray
import android.util.AttributeSet
import android.util.Log
import android.widget.TextView
import com.tommasoberlose.anotherwidget.R
/**
* Created by tommaso on 12/10/17.
*/
class TitleTextView : TextView {
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
init(context, attrs)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(context, attrs)
}
constructor(context: Context) : super(context) {}
fun init(context: Context, attrs: AttributeSet) {
try {
val ta = context.obtainStyledAttributes(attrs, R.styleable.FontText)
if (ta != null) {
val fontAsset = ta.getString(R.styleable.FontText_typefaceAsset)
if (fontAsset != null && !fontAsset.isEmpty()) {
val tf = Typeface.createFromAsset(getContext().assets, fontAsset)
if (tf != null)
typeface = tf
else
Log.i("FontText", String.format("Could not create a font from asset: %s", fontAsset))
}
ta.recycle()
}
} catch (e: Exception) {
Log.i("FontText", "Could not create a font from asset")
}
}
}

View File

@ -0,0 +1,18 @@
package com.tommasoberlose.anotherwidget.ui.viewmodels
import android.app.Application
import android.content.pm.ApplicationInfo
import androidx.databinding.ObservableField
import androidx.lifecycle.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class ChooseApplicationViewModel(application: Application) : AndroidViewModel(application) {
val appList: LiveData<List<ApplicationInfo>> = liveData {
val app = application.packageManager.getInstalledApplications(0)
emit(app)
}
val searchInput: MutableLiveData<String> = MutableLiveData("")
}

View File

@ -0,0 +1,17 @@
package com.tommasoberlose.anotherwidget.ui.viewmodels
import android.app.Application
import android.content.pm.ApplicationInfo
import android.location.Address
import android.location.Geocoder
import androidx.lifecycle.*
import com.tommasoberlose.anotherwidget.global.Preferences
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
class CustomLocationViewModel(application: Application) : AndroidViewModel(application) {
val addresses: MutableLiveData<List<Address>> = MutableLiveData(emptyList())
val locationInput: MutableLiveData<String> = MutableLiveData(Preferences.customLocationAdd)
}

View File

@ -0,0 +1,51 @@
package com.tommasoberlose.anotherwidget.ui.viewmodels
import androidx.lifecycle.*
import com.chibatching.kotpref.livedata.asLiveData
import com.tommasoberlose.anotherwidget.global.Preferences
class MainViewModel : ViewModel() {
// General Settings
val textGlobalColor = Preferences.asLiveData(Preferences::textGlobalColor)
val textMainSize = Preferences.asLiveData(Preferences::textMainSize)
val textSecondSize = Preferences.asLiveData(Preferences::textSecondSize)
val textShadow = Preferences.asLiveData(Preferences::textShadow)
val customFont = Preferences.asLiveData(Preferences::customFont)
val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation)
// Calendar Settings
val showEvents = Preferences.asLiveData(Preferences::showEvents)
val calendarAllDay = Preferences.asLiveData(Preferences::calendarAllDay)
val showUntil = Preferences.asLiveData(Preferences::showUntil)
val showDiffTime = Preferences.asLiveData(Preferences::showDiffTime)
val showDeclinedEvents = Preferences.asLiveData(Preferences::showDeclinedEvents)
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
val calendarAppName = Preferences.asLiveData(Preferences::calendarAppName)
val eventAppName = Preferences.asLiveData(Preferences::eventAppName)
// Clock Settings
val showClock = Preferences.asLiveData(Preferences::showClock)
val clockTextSize = Preferences.asLiveData(Preferences::clockTextSize)
val clockAppName = Preferences.asLiveData(Preferences::clockAppName)
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
val dateFormat = Preferences.asLiveData(Preferences::dateFormat)
// Weather Settings
val showWeather = Preferences.asLiveData(Preferences::showWeather)
val weatherTempUnit = Preferences.asLiveData(Preferences::weatherTempUnit)
val weatherRefreshPeriod = Preferences.asLiveData(Preferences::weatherRefreshPeriod)
val weatherAppName = Preferences.asLiveData(Preferences::weatherAppName)
val weatherProviderApi = Preferences.asLiveData(Preferences::weatherProviderApi)
val customLocationAdd = Preferences.asLiveData(Preferences::customLocationAdd)
// Advanced Settings
val darkThemePreference = Preferences.asLiveData(Preferences::darkThemePreference)
val showWallpaper = Preferences.asLiveData(Preferences::showWallpaper)
}

View File

@ -0,0 +1,68 @@
package com.tommasoberlose.anotherwidget.ui.viewmodels
import android.app.Activity
import android.content.Context
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.android.billingclient.api.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class SupportDevViewModel : ViewModel() {
lateinit var billingClient: BillingClient
val products: MutableLiveData<List<SkuDetails>> = MutableLiveData(emptyList())
fun openConnection() {
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
val params = SkuDetailsParams.newBuilder()
params.setSkusList(listOf("donation_coffee", "donation_donuts", "donation_breakfast", "donation_lunch", "donation_dinner")).setType(BillingClient.SkuType.INAPP)
viewModelScope.launch(Dispatchers.IO) {
val skuDetailsList = billingClient.querySkuDetails(params.build()).skuDetailsList
withContext(Dispatchers.Main) {
products.value = skuDetailsList
}
}
}
}
override fun onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
})
}
fun purchase(activity: Activity, product: SkuDetails) {
val flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(product)
.build()
billingClient.launchBillingFlow(activity, flowParams)
}
fun handlePurchase(purchase: Purchase) {
if (!purchase.isAcknowledged) {
viewModelScope.launch(Dispatchers.IO) {
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
billingClient.acknowledgePurchase(acknowledgePurchaseParams.build())
val consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
.build()
billingClient.consumePurchase(consumeParams)
}
}
}
fun closeConnection() {
billingClient.endConnection()
}
}

View File

@ -1,543 +0,0 @@
package com.tommasoberlose.anotherwidget.ui.widget
import android.Manifest
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.preference.PreferenceManager
import android.view.View
import android.widget.RemoteViews
import com.tommasoberlose.anotherwidget.`object`.Constants
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.receiver.UpdatesReceiver
import com.tommasoberlose.anotherwidget.util.Util
import com.tommasoberlose.anotherwidget.receiver.WeatherReceiver
import java.util.Calendar
import java.util.Locale
import java.util.concurrent.TimeUnit
import android.app.PendingIntent
import android.provider.CalendarContract
import android.content.ContentUris
import android.util.Log
import com.tommasoberlose.anotherwidget.util.CalendarUtil
import com.tommasoberlose.anotherwidget.util.WeatherUtil
import android.graphics.Typeface
import android.net.Uri
import android.widget.TextClock
import android.widget.TextView
import android.content.ComponentName
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.support.v4.content.ContextCompat.startActivity
import android.provider.CalendarContract.Events
import android.support.v4.content.ContextCompat
import android.text.Spannable
import android.text.SpannableString
import android.text.style.RelativeSizeSpan
import android.text.style.StyleSpan
import android.util.DisplayMetrics
import android.util.TypedValue
import android.widget.LinearLayout
import com.tommasoberlose.anotherwidget.receiver.OpenWeatherIntentReceiver
import com.tommasoberlose.anotherwidget.ui.view.CustomTypefaceSpan
import kotlinx.android.synthetic.main.the_widget.*
import kotlinx.android.synthetic.main.the_widget.view.*
import kotlinx.android.synthetic.main.the_widget_sans.view.*
/**
* Implementation of App Widget functionality.
*/
class TheWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
Util.updateSettingsByDefault(context)
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onAppWidgetOptionsChanged(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int, newOptions: Bundle?) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)
updateAppWidget(context, appWidgetManager, appWidgetId)
}
override fun onEnabled(context: Context) {
UpdatesReceiver().setUpdates(context)
WeatherReceiver().setUpdates(context)
}
override fun onDisabled(context: Context) {
UpdatesReceiver().removeUpdates(context)
WeatherReceiver().removeUpdates(context)
}
companion object {
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager,
appWidgetId: Int) {
val SP = PreferenceManager.getDefaultSharedPreferences(context)
val displayMetrics = Resources.getSystem().displayMetrics
var height = Util.convertDpToPixel(110f, context).toInt()
val width = displayMetrics.widthPixels
if (SP.getBoolean(Constants.PREF_SHOW_CLOCK, false)) {
height += Util.convertSpToPixels(SP.getFloat(Constants.PREF_TEXT_CLOCK_SIZE, 90f), context).toInt() + Util.convertDpToPixel(16f, context).toInt()
}
if (SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f) > 30 && SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) > 22) {
height += Util.convertDpToPixel(24f, context).toInt()
}
generateWidgetView(context, appWidgetId, appWidgetManager, width - Util.convertDpToPixel(16f, context).toInt(), height)
}
fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int, h: Int) {
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
var v = View.inflate(context, R.layout.the_widget, null)
val SP = PreferenceManager.getDefaultSharedPreferences(context)
views.setTextColor(R.id.empty_date, Util.getFontColor(SP))
views.setTextColor(R.id.divider1, Util.getFontColor(PreferenceManager.getDefaultSharedPreferences(context)))
views.setTextColor(R.id.temp, Util.getFontColor(PreferenceManager.getDefaultSharedPreferences(context)))
views.setTextColor(R.id.next_event, Util.getFontColor(PreferenceManager.getDefaultSharedPreferences(context)))
views.setTextColor(R.id.next_event_difference_time, Util.getFontColor(PreferenceManager.getDefaultSharedPreferences(context)))
views.setTextColor(R.id.next_event_date, Util.getFontColor(PreferenceManager.getDefaultSharedPreferences(context)))
views.setTextColor(R.id.divider2, Util.getFontColor(PreferenceManager.getDefaultSharedPreferences(context)))
views.setTextColor(R.id.calendar_temp, Util.getFontColor(PreferenceManager.getDefaultSharedPreferences(context)))
//views.setTextColor(R.id.time, Util.getFontColor(PreferenceManager.getDefaultSharedPreferences(context)))
views.setTextViewTextSize(R.id.empty_date, TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
views.setTextViewTextSize(R.id.divider1, TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
views.setTextViewTextSize(R.id.temp, TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
views.setTextViewTextSize(R.id.next_event, TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
views.setTextViewTextSize(R.id.next_event_difference_time, TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
views.setTextViewTextSize(R.id.next_event_date, TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
views.setTextViewTextSize(R.id.divider2, TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
views.setTextViewTextSize(R.id.calendar_temp, TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
//views.setTextViewTextSize(R.id.time, TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_CLOCK_SIZE, 90f))
v = updateCalendarViewByLayout(context, v)
v = updateLocationViewByLayout(context, v)
v = updateClockViewByLayout(context, v)
views.setImageViewBitmap(R.id.bitmap_container, Util.getBitmapFromView(v, w, h))
views = updateCalendarView(context, views, appWidgetId)
views = updateLocationView(context, views, appWidgetId)
views = updateClockView(context, views, appWidgetId)
views = fixViewsMargin(context, views)
appWidgetManager.updateAppWidget(appWidgetId, views)
}
fun updateCalendarView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews {
val SP = PreferenceManager.getDefaultSharedPreferences(context)
val now = Calendar.getInstance()
val calendarLayout = SP.getBoolean(Constants.PREF_SHOW_EVENTS, true) && Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR)
views.setViewVisibility(R.id.empty_layout, View.VISIBLE)
views.setViewVisibility(R.id.calendar_layout, View.GONE)
var dateStringValue: String = Util.getCapWordString(Constants.engDateFormat.format(now.time))
if (SP.getBoolean(Constants.PREF_ITA_FORMAT_DATE, false)) {
dateStringValue = Util.getCapWordString(Constants.itDateFormat.format(now.time))
}
views.setTextViewText(R.id.empty_date, dateStringValue)
val calPIntent = PendingIntent.getActivity(context, widgetID, Util.getCalendarIntent(context), 0)
views.setOnClickPendingIntent(R.id.empty_date, calPIntent)
if (calendarLayout) {
val e = CalendarUtil.getNextEvent(context)
if (e.id != 0.toLong()) {
views.setTextViewText(R.id.next_event, e.title)
if (SP.getBoolean(Constants.PREF_SHOW_NEXT_EVENT, false) && CalendarUtil.getEventsCount(context) > 1) {
val multipleIntent = PendingIntent.getBroadcast(context, widgetID, Intent(Constants.ACTION_GO_TO_NEXT_EVENT), 0)
views.setViewVisibility(R.id.multiple_events, View.VISIBLE)
views.setOnClickPendingIntent(R.id.multiple_events, multipleIntent)
} else {
views.setViewVisibility(R.id.multiple_events, View.GONE)
}
val pIntent = PendingIntent.getActivity(context, widgetID, Util.getEventIntent(context, e), 0)
views.setOnClickPendingIntent(R.id.next_event, pIntent)
views.setOnClickPendingIntent(R.id.next_event_difference_time, pIntent)
if (SP.getBoolean(Constants.PREF_SHOW_DIFF_TIME, true)) {
views.setTextViewText(R.id.next_event_difference_time, Util.getDifferenceText(context, now.timeInMillis, e.startDate))
views.setViewVisibility(R.id.next_event_difference_time, View.VISIBLE)
} else {
views.setViewVisibility(R.id.next_event_difference_time, View.GONE)
}
if (SP.getInt(Constants.PREF_SECOND_ROW_INFORMATION, 0) == 2 && Util.getNextAlarm(context) != null) {
val source = BitmapFactory.decodeResource(context.resources, R.drawable.ic_action_alarm);
val result = Util.changeBitmapColor(source, Util.getFontColor(SP))
views.setImageViewBitmap(R.id.second_row_icon, result)
views.setTextViewText(R.id.next_event_date, Util.getNextAlarm(context))
val clockIntent = PendingIntent.getActivity(context, widgetID, Util.getClockIntent(context), 0)
views.setOnClickPendingIntent(R.id.next_event_date, clockIntent)
} else if (e.address != "" && SP.getInt(Constants.PREF_SECOND_ROW_INFORMATION, 0) == 1) {
val source = BitmapFactory.decodeResource(context.resources, R.drawable.ic_action_location);
val result = Util.changeBitmapColor(source, Util.getFontColor(SP))
views.setImageViewBitmap(R.id.second_row_icon, result)
views.setTextViewText(R.id.next_event_date, e.address)
val mapIntent = PendingIntent.getActivity(context, widgetID, Util.getGoogleMapsIntentFromAddress(context, e.address), 0)
views.setOnClickPendingIntent(R.id.next_event_date, mapIntent)
} else {
val source = BitmapFactory.decodeResource(context.resources, R.drawable.ic_action_calendar);
val result = Util.changeBitmapColor(source, Util.getFontColor(SP))
views.setImageViewBitmap(R.id.second_row_icon, result)
if (!e.allDay) {
var startHour = Constants.goodHourFormat.format(e.startDate)
var endHour = Constants.goodHourFormat.format(e.endDate)
if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) {
startHour = Constants.badHourFormat.format(e.startDate)
endHour = Constants.badHourFormat.format(e.endDate)
}
var dayDiff = TimeUnit.MILLISECONDS.toDays(e.endDate - e.startDate)
val startCal = Calendar.getInstance()
startCal.timeInMillis = e.startDate
val endCal = Calendar.getInstance()
endCal.timeInMillis = e.endDate
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
dayDiff++
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(Calendar.MINUTE) >= endCal.get(Calendar.MINUTE)) {
dayDiff++
}
var multipleDay = ""
if (dayDiff > 0) {
multipleDay = String.format(" (+%s%s)", dayDiff, context.getString(R.string.day_char))
}
views.setTextViewText(R.id.next_event_date, String.format("%s - %s%s", startHour, endHour, multipleDay))
} else {
views.setTextViewText(R.id.next_event_date, dateStringValue)
}
if (SP.getBoolean(Constants.PREF_SHOW_NEXT_EVENT, false) && CalendarUtil.getEventsCount(context) > 1) {
val multipleIntent = PendingIntent.getBroadcast(context, widgetID, Intent(Constants.ACTION_GO_TO_NEXT_EVENT), 0)
views.setOnClickPendingIntent(R.id.next_event_date, multipleIntent)
} else {
views.setOnClickPendingIntent(R.id.next_event_date, pIntent)
}
}
views.setViewVisibility(R.id.empty_layout, View.GONE)
views.setViewVisibility(R.id.calendar_layout, View.VISIBLE)
}
}
return views
}
fun updateLocationView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews {
val SP = PreferenceManager.getDefaultSharedPreferences(context)
val locationLayout = SP.getBoolean(Constants.PREF_SHOW_WEATHER, true)
if (locationLayout && SP.contains(Constants.PREF_WEATHER_TEMP) && SP.contains(Constants.PREF_WEATHER_ICON)) {
views.setViewVisibility(R.id.weather, View.VISIBLE)
views.setViewVisibility(R.id.calendar_weather, View.VISIBLE)
val temp = String.format(Locale.getDefault(), "%.0f °%s", SP.getFloat(Constants.PREF_WEATHER_TEMP, 0f), SP.getString(Constants.PREF_WEATHER_REAL_TEMP_UNIT, "F"))
views.setViewVisibility(R.id.weather_icon, View.VISIBLE)
views.setViewVisibility(R.id.empty_weather_icon, View.VISIBLE)
val icon: String = SP.getString(Constants.PREF_WEATHER_ICON, "")
if (icon.equals("")) {
views.setViewVisibility(R.id.weather_icon, View.GONE)
views.setViewVisibility(R.id.empty_weather_icon, View.GONE)
} else {
views.setImageViewResource(R.id.weather_icon, WeatherUtil.getWeatherIconResource(icon))
views.setImageViewResource(R.id.empty_weather_icon, WeatherUtil.getWeatherIconResource(icon))
}
views.setTextViewText(R.id.temp, temp)
views.setTextViewText(R.id.calendar_temp, temp)
val i = Intent(context, OpenWeatherIntentReceiver::class.java)
i.action = Constants.ACTION_OPEN_WEATHER_INTENT
val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0)
views.setOnClickPendingIntent(R.id.weather, weatherPIntent)
views.setOnClickPendingIntent(R.id.calendar_weather, weatherPIntent)
} else {
views.setViewVisibility(R.id.weather, View.GONE)
views.setViewVisibility(R.id.calendar_weather, View.GONE)
}
return views
}
fun updateClockView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews {
val SP = PreferenceManager.getDefaultSharedPreferences(context)
if (!SP.getBoolean(Constants.PREF_SHOW_CLOCK, false)) {
views.setViewVisibility(R.id.time, View.GONE)
} else {
// val now = Calendar.getInstance()
// if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) {
// val textBadHour = SpannableString(Constants.badHourFormat.format(now.timeInMillis).replace(" ", ""))
// textBadHour.setSpan(RelativeSizeSpan(0.4f), textBadHour.length - 2,
// textBadHour.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
//
// views.setTextViewText(R.id.time, textBadHour)
// } else {
// views.setTextViewText(R.id.time, Constants.goodHourFormat.format(now.timeInMillis))
// }
val clockPIntent = PendingIntent.getActivity(context, widgetID, Util.getClockIntent(context), 0)
views.setOnClickPendingIntent(R.id.time, clockPIntent)
views.setViewVisibility(R.id.time, View.VISIBLE)
}
return views
}
fun fixViewsMargin(context: Context, views: RemoteViews): RemoteViews {
val SP = PreferenceManager.getDefaultSharedPreferences(context)
views.setViewVisibility(R.id.bottom_divider_24, View.GONE)
views.setViewVisibility(R.id.bottom_divider_16, View.GONE)
views.setViewVisibility(R.id.bottom_divider_8, View.GONE)
val eVisible = SP.getBoolean(Constants.PREF_SHOW_EVENTS, true) && Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR)
if (SP.getBoolean(Constants.PREF_SHOW_CLOCK, false)) {
if (eVisible) {
views.setViewVisibility(R.id.bottom_divider_8, View.VISIBLE)
} else {
views.setViewVisibility(R.id.bottom_divider_24, View.VISIBLE)
}
} else {
if (eVisible) {
views.setViewVisibility(R.id.bottom_divider_8, View.VISIBLE)
}
}
return views
}
fun updateCalendarViewByLayout(context: Context, v: View): View {
val SP = PreferenceManager.getDefaultSharedPreferences(context)
val now = Calendar.getInstance()
val calendarLayout = SP.getBoolean(Constants.PREF_SHOW_EVENTS, true) && Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR)
v.empty_layout.visibility = View.VISIBLE
v.calendar_layout.visibility = View.GONE
var dateStringValue: String = Util.getCapWordString(Constants.engDateFormat.format(now.time))
if (SP.getBoolean(Constants.PREF_ITA_FORMAT_DATE, false)) {
dateStringValue = Util.getCapWordString(Constants.itDateFormat.format(now.time))
}
v.empty_date.text = dateStringValue
if (calendarLayout) {
val e = CalendarUtil.getNextEvent(context)
if (e.id != 0.toLong()) {
v.next_event.text = e.title
if (SP.getBoolean(Constants.PREF_SHOW_NEXT_EVENT, false) && CalendarUtil.getEventsCount(context) > 1) {
v.multiple_events.visibility = View.VISIBLE
} else {
v.multiple_events.visibility = View.GONE
}
if (SP.getBoolean(Constants.PREF_SHOW_DIFF_TIME, true)) {
v.next_event_difference_time.text = Util.getDifferenceText(context, now.timeInMillis, e.startDate)
v.next_event_difference_time.visibility = View.VISIBLE
} else {
v.next_event_difference_time.visibility = View.GONE
}
if (SP.getInt(Constants.PREF_SECOND_ROW_INFORMATION, 0) == 2 && Util.getNextAlarm(context) != null) {
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_action_alarm))
v.next_event_date.text = Util.getNextAlarm(context)
} else if (!e.address.equals("") && SP.getInt(Constants.PREF_SECOND_ROW_INFORMATION, 0) == 1) {
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_action_location))
v.next_event_date.text = e.address
} else {
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_action_calendar))
if (!e.allDay) {
var startHour = Constants.goodHourFormat.format(e.startDate)
var endHour = Constants.goodHourFormat.format(e.endDate)
if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) {
startHour = Constants.badHourFormat.format(e.startDate)
endHour = Constants.badHourFormat.format(e.endDate)
}
var dayDiff = TimeUnit.MILLISECONDS.toDays(e.endDate - e.startDate)
val startCal = Calendar.getInstance()
startCal.timeInMillis = e.startDate
val endCal = Calendar.getInstance()
endCal.timeInMillis = e.endDate
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
dayDiff++
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(Calendar.MINUTE) >= endCal.get(Calendar.MINUTE)) {
dayDiff++
}
var multipleDay: String = ""
if (dayDiff > 0) {
multipleDay = String.format(" (+%s%s)", dayDiff, context.getString(R.string.day_char))
}
v.next_event_date.text = String.format("%s - %s%s", startHour, endHour, multipleDay)
} else {
v.next_event_date.text = dateStringValue
}
}
v.empty_layout.visibility = View.GONE
v.calendar_layout.visibility = View.VISIBLE
}
}
v.empty_date.setTextColor(Util.getFontColor(SP))
v.divider1.setTextColor(Util.getFontColor(SP))
v.temp.setTextColor(Util.getFontColor(SP))
v.next_event.setTextColor(Util.getFontColor(SP))
v.next_event_difference_time.setTextColor(Util.getFontColor(SP))
v.next_event_date.setTextColor(Util.getFontColor(SP))
v.divider2.setTextColor(Util.getFontColor(SP))
v.calendar_temp.setTextColor(Util.getFontColor(SP))
v.second_row_icon.setColorFilter(Util.getFontColor(SP))
v.time.setTextColor(Util.getFontColor(SP))
v.multiple_events.setColorFilter(Util.getFontColor(SP))
v.empty_date.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
v.divider1.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
v.temp.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
v.next_event.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
v.next_event_difference_time.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f))
v.next_event_date.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
v.divider2.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
v.calendar_temp.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f))
v.time.setTextSize(TypedValue.COMPLEX_UNIT_SP, SP.getFloat(Constants.PREF_TEXT_CLOCK_SIZE, 90f))
v.second_row_icon.scaleX = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 18f
v.second_row_icon.scaleY = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 18f
v.weather_icon.scaleX = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 18f
v.weather_icon.scaleY = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 18f
v.empty_weather_icon.scaleX = SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f) / 24f
v.empty_weather_icon.scaleY = SP.getFloat(Constants.PREF_TEXT_MAIN_SIZE, 24f) / 24f
v.multiple_events.scaleX = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 16f
v.multiple_events.scaleY = SP.getFloat(Constants.PREF_TEXT_SECOND_SIZE, 16f) / 16f
val shadowRadius = when (SP.getInt(Constants.PREF_TEXT_SHADOW, 1)) {
0 -> 0f
1 -> 5f
2 -> 5f
else -> 5f
}
val shadowColor = when (SP.getInt(Constants.PREF_TEXT_SHADOW, 1)) {
0 -> Color.TRANSPARENT
1 -> R.color.black_50
2 -> Color.BLACK
else -> R.color.black_50
}
val shadowDy = when (SP.getInt(Constants.PREF_TEXT_SHADOW, 1)) {
0 -> 0f
1 -> 0f
2 -> 1f
else -> 0f
}
v.empty_date.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
v.divider1.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
v.temp.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
v.next_event.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
v.next_event_difference_time.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
v.next_event_date.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
v.divider2.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
v.calendar_temp.setShadowLayer(shadowRadius, 0f, 0f, shadowColor)
v.time.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
if (SP.getInt(Constants.PREF_CUSTOM_FONT, Constants.CUSTOM_FONT_PRODUCT_SANS) == Constants.CUSTOM_FONT_PRODUCT_SANS) {
val product_sans: Typeface = Typeface.createFromAsset(context.assets, "fonts/product_sans_regular.ttf")
val product_sans_light: Typeface = Typeface.createFromAsset(context.assets, "fonts/product_sans_light.ttf")
v.empty_date.typeface = product_sans
v.divider1.typeface = product_sans
v.temp.typeface = product_sans
v.next_event.typeface = product_sans
v.next_event_difference_time.typeface = product_sans
v.next_event_date.typeface = product_sans
v.divider2.typeface = product_sans
v.calendar_temp.typeface = product_sans
v.time.typeface = product_sans_light
}
return v
}
fun updateLocationViewByLayout(context: Context, v: View): View {
val SP = PreferenceManager.getDefaultSharedPreferences(context)
val locationLayout = SP.getBoolean(Constants.PREF_SHOW_WEATHER, true)
if (locationLayout && SP.contains(Constants.PREF_WEATHER_TEMP) && SP.contains(Constants.PREF_WEATHER_ICON)) {
v.weather.visibility = View.VISIBLE
v.calendar_weather.visibility = View.VISIBLE
val currentTemp = String.format(Locale.getDefault(), "%.0f °%s", SP.getFloat(Constants.PREF_WEATHER_TEMP, 0f), SP.getString(Constants.PREF_WEATHER_REAL_TEMP_UNIT, "F"))
v.weather_icon.visibility = View.VISIBLE
v.empty_weather_icon.visibility = View.VISIBLE
val icon: String = SP.getString(Constants.PREF_WEATHER_ICON, "")
if (icon.equals("")) {
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.temp.text = currentTemp
v.calendar_temp.text = currentTemp
} else {
v.weather.visibility = View.GONE
v.calendar_weather.visibility = View.GONE
}
return v
}
fun updateClockViewByLayout(context: Context, v: View): View {
val SP = PreferenceManager.getDefaultSharedPreferences(context)
if (!SP.getBoolean(Constants.PREF_SHOW_CLOCK, false)) {
v.time.visibility = View.GONE
} else {
// val now = Calendar.getInstance()
// if (SP.getString(Constants.PREF_HOUR_FORMAT, "12").equals("12")) {
// val textBadHour = SpannableString(Constants.badHourFormat.format(now.timeInMillis).replace(" ", ""))
// textBadHour.setSpan(RelativeSizeSpan(0.4f), textBadHour.length - 2,
// textBadHour.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
//
// v.time.text = textBadHour
// } else {
// v.time.text = Constants.goodHourFormat.format(now.timeInMillis)
// }
v.time.visibility = View.VISIBLE
}
return v
}
}
}

View File

@ -0,0 +1,397 @@
package com.tommasoberlose.anotherwidget.ui.widgets
import android.Manifest
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
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
import android.text.format.DateUtils
import android.util.Log
import android.util.TypedValue
import android.view.View
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.RemoteViews
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
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.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
class TheWidget : AppWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onAppWidgetOptionsChanged(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int, newOptions: Bundle?) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)
updateAppWidget(context, appWidgetManager, appWidgetId)
}
override fun onEnabled(context: Context) {
CalendarUtil.updateEventList(context)
WeatherReceiver.setUpdates(context)
}
override fun onDisabled(context: Context) {
UpdatesReceiver.removeUpdates(context)
WeatherReceiver.removeUpdates(context)
}
companion object {
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)
}
if (Preferences.textMainSize > 30 && Preferences.textSecondSize > 22) {
height += 24.toPixel(context)
}
generateWidgetView(context, appWidgetId, appWidgetManager, width - 16.toPixel(context), height)
}
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int, h: Int) {
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
val generatedView = generateWidgetView(context, w)
generatedView.measure(0, 0)
views.setImageViewBitmap(R.id.bitmap_container, Util.getBitmapFromView(generatedView, w, generatedView.measuredHeight))
// Clock
views = updateClockView(context, views, appWidgetId)
// Setup listener
views = updateCalendarView(context, generatedView, views, appWidgetId)
views = updateWeatherView(context, generatedView, views, appWidgetId)
appWidgetManager.updateAppWidget(appWidgetId, views)
}
private fun updateCalendarView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
v.empty_date.measure(0, 0)
views.setImageViewBitmap(R.id.empty_date_rect, Util.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)
views.setOnClickPendingIntent(R.id.empty_date_rect, calPIntent)
val nextEvent = CalendarUtil.getNextEvent()
val nextAlarm = Util.getNextAlarm(context)
if (Preferences.showEvents && Util.checkGrantedPermission(context, Manifest.permission.READ_CALENDAR) && nextEvent != null) {
if (Preferences.showNextEvent && CalendarUtil.getEventsCount() > 1) {
v.action_next.measure(0, 0)
views.setImageViewBitmap(R.id.action_next_rect, Util.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.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 {
views.setViewVisibility(R.id.action_next_rect, View.GONE)
views.setViewVisibility(R.id.action_previous_rect, View.GONE)
}
val pIntent = PendingIntent.getActivity(context, widgetID, Util.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) {
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.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)
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))
v.second_row.measure(0, 0)
views.setImageViewBitmap(R.id.second_row_rect, Util.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)
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))
v.second_row.measure(0, 0)
views.setImageViewBitmap(R.id.second_row_rect, Util.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)
}
return views
}
private fun updateWeatherView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
if (Preferences.showWeather && Preferences.weatherIcon != "") {
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
views.setViewVisibility(R.id.calendar_weather_rect, View.VISIBLE)
val i = Intent(context, WidgetClickListenerReceiver::class.java)
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0)
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
views.setOnClickPendingIntent(R.id.calendar_weather_rect, weatherPIntent)
v.weather.measure(0, 0)
views.setImageViewBitmap(R.id.weather_rect, Util.getBitmapFromView(v.weather))
v.calendar_weather.measure(0, 0)
views.setImageViewBitmap(R.id.calendar_weather_rect, Util.getBitmapFromView(v.calendar_weather))
} else {
views.setViewVisibility(R.id.weather_rect, View.GONE)
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
}
return views
}
private fun updateClockView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews {
if (!Preferences.showClock) {
views.setViewVisibility(R.id.time, View.GONE)
} else {
views.setTextColor(R.id.time, Util.getFontColor())
views.setTextViewTextSize(R.id.time, TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(context))
val clockPIntent = PendingIntent.getActivity(context, widgetID, Util.getClockIntent(context), 0)
views.setOnClickPendingIntent(R.id.time, clockPIntent)
views.setViewVisibility(R.id.time, View.VISIBLE)
}
return views
}
fun generateWidgetView(context: Context, maxWidth: Int): View {
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
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)}")
val nextEvent = CalendarUtil.getNextEvent()
val nextAlarm = Util.getNextAlarm(context)
if (Preferences.showEvents && Util.checkGrantedPermission(context, 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.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())
v.next_event_difference_time.visibility = View.VISIBLE
} else {
v.next_event_difference_time.visibility = View.GONE
}
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.round_place))
v.next_event_date.text = nextEvent.address
} else {
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.round_today))
if (!nextEvent.allDay) {
val startHour = DateFormat.getTimeInstance(DateFormat.SHORT).format(nextEvent.startDate)
val endHour = DateFormat.getTimeInstance(DateFormat.SHORT).format(nextEvent.endDate)
var dayDiff = TimeUnit.MILLISECONDS.toDays(nextEvent.endDate - nextEvent.startDate)
val startCal = Calendar.getInstance()
startCal.timeInMillis = nextEvent.startDate
val endCal = Calendar.getInstance()
endCal.timeInMillis = nextEvent.endDate
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
dayDiff++
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(Calendar.MINUTE) >= endCal.get(Calendar.MINUTE)) {
dayDiff++
}
var multipleDay = ""
if (dayDiff > 0) {
multipleDay = String.format(" (+%s%s)", dayDiff, context.getString(R.string.day_char))
}
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))
}
}
v.empty_layout.visibility = View.GONE
v.calendar_layout.visibility = View.VISIBLE
} else if (Preferences.secondRowInformation == 2 && 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.empty_layout.visibility = View.GONE
v.calendar_layout.visibility = View.VISIBLE
}
// Color
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp).forEach {
it.setTextColor(Util.getFontColor())
}
listOf<ImageView>(v.second_row_icon, v.action_next, v.action_previous).forEach {
it.setColorFilter(Util.getFontColor())
}
// Text Size
listOf<Pair<TextView, Float>>(
v.empty_date to Preferences.textMainSize,
v.divider1 to Preferences.textSecondSize,
v.temp to Preferences.textMainSize,
v.next_event to Preferences.textMainSize,
v.next_event_difference_time to Preferences.textMainSize,
v.next_event_date to Preferences.textSecondSize,
v.divider2 to Preferences.textSecondSize,
v.calendar_temp to Preferences.textSecondSize
).forEach {
it.first.setTextSize(TypedValue.COMPLEX_UNIT_SP, it.second)
}
// Icons scale
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.empty_weather_icon.scaleX = Preferences.textMainSize / 20f
v.empty_weather_icon.scaleY = Preferences.textMainSize / 20f
v.action_next.scaleX = Preferences.textMainSize / 28f
v.action_next.scaleY = Preferences.textMainSize / 28f
v.action_previous.scaleX = Preferences.textMainSize / 28f
v.action_previous.scaleY = Preferences.textMainSize / 28f
// Shadows
val shadowRadius = when (Preferences.textShadow) {
0 -> 0f
1 -> 5f
2 -> 5f
else -> 5f
}
val shadowColor = when (Preferences.textShadow) {
0 -> Color.TRANSPARENT
1 -> R.color.black_50
2 -> Color.BLACK
else -> R.color.black_50
}
val shadowDy = when (Preferences.textShadow) {
0 -> 0f
1 -> 0f
2 -> 1f
else -> 0f
}
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp).forEach {
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
}
// Custom Font
if (Preferences.customFont == Constants.CUSTOM_FONT_PRODUCT_SANS) {
val productSans: Typeface = Typeface.createFromAsset(context.assets, "fonts/product_sans_regular.ttf")
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp).forEach {
it.typeface = productSans
}
}
// Weather
if (Preferences.showWeather && Preferences.weatherIcon != "") {
v.weather.visibility = View.VISIBLE
v.calendar_weather.visibility = View.VISIBLE
val currentTemp = String.format(Locale.getDefault(), "%.0f °%s", Preferences.weatherTemp, Preferences.weatherRealTempUnit)
val icon: String = Preferences.weatherIcon
if (icon == "") {
v.weather_icon.visibility = View.GONE
v.empty_weather_icon.visibility = View.GONE
} else {
v.weather_icon.setImageResource(WeatherUtil.getWeatherIconResource(icon))
v.empty_weather_icon.setImageResource(WeatherUtil.getWeatherIconResource(icon))
v.weather_icon.visibility = View.VISIBLE
v.empty_weather_icon.visibility = View.VISIBLE
}
v.temp.text = currentTemp
v.calendar_temp.text = currentTemp
} else {
v.weather.visibility = View.GONE
v.calendar_weather.visibility = View.GONE
}
// Apply max width
v.main_layout.layoutParams = RelativeLayout.LayoutParams(maxWidth, RelativeLayout.LayoutParams.WRAP_CONTENT)
return v
}
}
}