Compare commits
29 Commits
v2.0.5-bet
...
v2.0.5
Author | SHA1 | Date | |
---|---|---|---|
9e2eacef73 | |||
60531061d7 | |||
d86d2cadd4 | |||
cb6c2c7764 | |||
6a4cfdf22b | |||
0b9e9e081e | |||
15884bd9b2 | |||
0adf192965 | |||
d72ba08960 | |||
1848951a74 | |||
5ca06e817e | |||
37cb43dc80 | |||
ea372dd76d | |||
7076311e94 | |||
2e684e0902 | |||
e2503decd2 | |||
f13cee24d5 | |||
f5c4ee7eb0 | |||
4feb72381d | |||
bea0803c3a | |||
dd450443c8 | |||
6279846cea | |||
364d8b2307 | |||
e990b229c8 | |||
c97127e3ab | |||
9d72c168b6 | |||
614d001df8 | |||
890101b2b3 | |||
a4b37ad5ad |
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: tommasoberlose
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. OnePlus 6]
|
||||
- OS Version: [e.g. Android 9.0]
|
||||
- App Version (that you can find inside the advanced settings) [e.g. v2.0.5 (71)]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: tommasoberlose
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
1
.gitignore
vendored
@ -7,3 +7,4 @@
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
/tasksintegration/build
|
BIN
.idea/caches/build_file_checksums.ser
generated
52
.idea/navEditor.xml
generated
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="navEditor-manualLayoutAlgorithm2">
|
||||
<option name="myPositions">
|
||||
<map>
|
||||
<entry key="nav_graph.xml">
|
||||
<value>
|
||||
<LayoutPositions>
|
||||
<option name="myPositions">
|
||||
<map>
|
||||
<entry key="appMainFragment">
|
||||
<value>
|
||||
<LayoutPositions>
|
||||
<option name="myPosition">
|
||||
<Point>
|
||||
<option name="x" value="242" />
|
||||
<option name="y" value="352" />
|
||||
</Point>
|
||||
</option>
|
||||
<option name="myPositions">
|
||||
<map>
|
||||
<entry key="action_appMainFragment_to_appSettingsFragment">
|
||||
<value>
|
||||
<LayoutPositions />
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</LayoutPositions>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="appSettingsFragment">
|
||||
<value>
|
||||
<LayoutPositions>
|
||||
<option name="myPosition">
|
||||
<Point>
|
||||
<option name="x" value="532" />
|
||||
<option name="y" value="353" />
|
||||
</Point>
|
||||
</option>
|
||||
</LayoutPositions>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</LayoutPositions>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Tommaso Berlose
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
20
README.md
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
<img src="hero.png"/>
|
||||
|
||||
Another Widget
|
||||
========
|
||||
|
||||
Another Widget intelligently summarizes the information you need most.
|
||||
Watch the next events, the weather, and the information you want in an intuitive and elegant way. (Nope, reminders cannot be displayed because it's not allowed.)
|
||||
|
||||
While respecting the design of the application, there is a great opportunity to customize the information displayed and widget components.
|
||||
Also, as much as possible, there are always updates and new features in the short run.
|
||||
|
||||
Help me developing with feedback and support me on how you can.
|
||||
<div style="text-align:center"><a href="https://play.google.com/store/apps/details?id=com.tommasoberlose.anotherwidget" target="_blank"><img src="google-play-badge.png" height="100" /></a></div>
|
||||
|
||||
License
|
||||
-------
|
||||
Copyright (C) 2017-2020 Tommaso Berlose (http://tommasoberlose.com)
|
||||
|
||||
Another Widget binaries and source code can be used according to the [MIT Licence](LICENSE).
|
@ -18,7 +18,7 @@ android {
|
||||
applicationId "com.tommasoberlose.anotherwidget"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 29
|
||||
versionCode 59
|
||||
versionCode 79
|
||||
versionName "2.0.5"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
@ -59,15 +59,14 @@ android {
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
testImplementation 'junit:junit:4.13'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
|
||||
// UI
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'com.google.android.material:material:1.2.0-alpha06'
|
||||
implementation 'androidx.browser:browser:1.2.0'
|
||||
implementation 'net.idik:slimadapter:2.1.2'
|
||||
@ -78,6 +77,8 @@ dependencies {
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
|
||||
implementation "androidx.work:work-runtime-ktx:2.3.4"
|
||||
|
||||
// EventBus
|
||||
implementation 'org.greenrobot:eventbus:3.1.1'
|
||||
|
||||
@ -89,6 +90,9 @@ dependencies {
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'joda-time:joda-time:2.9.9'
|
||||
implementation 'me.everything:providers-android:1.0.1'
|
||||
implementation 'com.github.warkiz.widget:indicatorseekbar:2.1.2'
|
||||
|
||||
//Glide
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
|
||||
@ -104,6 +108,7 @@ dependencies {
|
||||
implementation "androidx.core:core-ktx:1.2.0"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
|
||||
implementation "androidx.palette:palette-ktx:1.0.0"
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
|
||||
// Recommended: Add the Firebase SDK for Google Analytics.
|
||||
implementation 'com.google.firebase:firebase-analytics:17.4.0'
|
||||
|
@ -1,9 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.tommasoberlose.anotherwidget">
|
||||
|
||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="com.android.vending.BILLING" />
|
||||
@ -11,24 +13,26 @@
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="@xml/my_backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:name=".AWApplication"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main">
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".ui.activities.ChooseApplicationActivity" android:launchMode="singleInstance" />
|
||||
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" />
|
||||
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" />
|
||||
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" />
|
||||
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" />
|
||||
<activity android:name=".ui.activities.ChooseApplicationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||
|
||||
|
||||
<receiver android:name=".ui.widgets.MainWidget">
|
||||
@ -62,11 +66,14 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_CALENDAR_UPDATE" />
|
||||
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_TIME_UPDATE" />
|
||||
<action android:name="com.sec.android.widgetapp.APPWIDGET_RESIZE" />
|
||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||
<action android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
|
||||
<action android:name="android.intent.action.DATE_CHANGED" />
|
||||
<action android:name="android.intent.action.TIME_SET" />
|
||||
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
|
||||
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
@ -79,6 +86,36 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||
<action android:name="android.intent.action.TIME_SET" />
|
||||
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
|
||||
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.PlayerReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.music.metachanged" />
|
||||
<action android:name="com.android.music.playstatechanged" />
|
||||
<action android:name="com.android.music.playbackcomplete" />
|
||||
<action android:name="com.android.music.queuechanged" />
|
||||
|
||||
<action android:name="com.htc.music.metachanged" />
|
||||
<action android:name="fm.last.android.metachanged" />
|
||||
<action android:name="com.sec.android.app.music.metachanged" />
|
||||
<action android:name="com.nullsoft.winamp.metachanged" />
|
||||
<action android:name="com.amazon.mp3.metachanged" />
|
||||
<action android:name="com.miui.player.metachanged" />
|
||||
<action android:name="com.real.IMP.metachanged" />
|
||||
<action android:name="com.sonyericsson.music.metachanged" />
|
||||
<action android:name="com.rdio.android.metachanged" />
|
||||
<action android:name="com.samsung.sec.android.MusicPlayer.metachanged" />
|
||||
<action android:name="com.andrew.apollo.metachanged" />
|
||||
<action android:name="com.spotify.music.playbackstatechanged"/>
|
||||
<action android:name="com.spotify.music.metadatachanged"/>
|
||||
<action android:name="com.spotify.music.queuechanged"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
@ -91,6 +128,15 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".receivers.CrashlyticsReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_REPORT_CRASH" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name=".services.EventListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
</application>
|
||||
|
@ -34,7 +34,7 @@ class AWApplication : Application() {
|
||||
private fun calibrateVersions() {
|
||||
// 2.0 Tolerance
|
||||
if (Preferences.clockTextSize > 50f) {
|
||||
Preferences.clockTextSize = 46f
|
||||
Preferences.clockTextSize = 32f
|
||||
}
|
||||
|
||||
if (Preferences.textMainSize > 36f) {
|
||||
|
@ -8,80 +8,132 @@ import android.text.TextWatcher
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.GridLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.SeekBar
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||
import com.tommasoberlose.anotherwidget.utils.expand
|
||||
import com.tommasoberlose.anotherwidget.utils.reveal
|
||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||
import com.warkiz.widget.IndicatorSeekBar
|
||||
import com.warkiz.widget.OnSeekChangeListener
|
||||
import com.warkiz.widget.SeekParams
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.*
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.view.*
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.view.color_loader
|
||||
import kotlinx.android.synthetic.main.color_picker_menu_item.view.*
|
||||
import kotlinx.coroutines.*
|
||||
import net.idik.lib.slimadapter.SlimAdapter
|
||||
import java.lang.Exception
|
||||
import java.util.prefs.Preferences
|
||||
|
||||
class BottomSheetColorPicker(
|
||||
context: Context,
|
||||
private val colors: IntArray = intArrayOf(),
|
||||
private val selected: Int? = null,
|
||||
private val getSelected: (() -> Int)? = null,
|
||||
private val header: String? = null,
|
||||
private val onColorSelected: ((selectedValue: Int) -> Unit)? = null
|
||||
private val onColorSelected: ((selectedValue: Int) -> Unit)? = null,
|
||||
private val showAlphaSelector: Boolean = false,
|
||||
private val alpha: Int = 0,
|
||||
private val onAlphaChangeListener: ((alpha: Int) -> Unit)? = null
|
||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||
|
||||
private val loadingJob: Job? = null
|
||||
private var loadingJobs: ArrayList<Job> = ArrayList()
|
||||
private lateinit var adapter: SlimAdapter
|
||||
|
||||
override fun show() {
|
||||
val view = View.inflate(context, R.layout.bottom_sheet_menu_hor, null)
|
||||
|
||||
window?.setDimAmount(0f)
|
||||
|
||||
// Header
|
||||
view.header.isVisible = header != null
|
||||
view.header_text.text = header ?: ""
|
||||
|
||||
val itemViews: ArrayList<View> = ArrayList()
|
||||
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
for (@ColorInt color: Int in colors) {
|
||||
val itemView = View.inflate(context, R.layout.color_picker_menu_item, null)
|
||||
itemView.color.setCardBackgroundColor(ColorStateList.valueOf(color))
|
||||
itemView.check.setColorFilter(ContextCompat.getColor(context,
|
||||
if (color.isColorDark()) android.R.color.white else android.R.color.black
|
||||
), android.graphics.PorterDuff.Mode.MULTIPLY)
|
||||
itemView.check.isVisible = selected == color
|
||||
itemView.color.setOnClickListener {
|
||||
onColorSelected?.invoke(color)
|
||||
this@BottomSheetColorPicker.dismiss()
|
||||
// Alpha
|
||||
view.alpha_selector_container.isVisible = showAlphaSelector
|
||||
view.alpha_selector.setProgress(alpha.toFloat())
|
||||
view.text_alpha.text = "%s: %s%%".format(context.getString(R.string.alpha), alpha)
|
||||
view.alpha_selector.onSeekChangeListener = object : OnSeekChangeListener {
|
||||
override fun onSeeking(seekParams: SeekParams?) {
|
||||
seekParams?.let {
|
||||
view.text_alpha.text = "%s: %s%%".format(context.getString(R.string.alpha), it.progress)
|
||||
onAlphaChangeListener?.invoke(it.progress)
|
||||
}
|
||||
itemViews.add(itemView)
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
itemViews.forEach {
|
||||
view.menu.addView(it, GridLayout.LayoutParams(
|
||||
GridLayout.spec(GridLayout.UNDEFINED, 1f),
|
||||
GridLayout.spec(GridLayout.UNDEFINED, 1f)
|
||||
))
|
||||
}
|
||||
color_loader.isVisible = false
|
||||
view.menu.isVisible = true
|
||||
this@BottomSheetColorPicker.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
override fun onStartTrackingTouch(seekBar: IndicatorSeekBar?) {
|
||||
}
|
||||
override fun onStopTrackingTouch(seekBar: IndicatorSeekBar?) {
|
||||
}
|
||||
}
|
||||
|
||||
// Menu
|
||||
// List
|
||||
|
||||
adapter = SlimAdapter.create()
|
||||
|
||||
loadingJobs.add(GlobalScope.launch(Dispatchers.IO) {
|
||||
val listView = View.inflate(context, R.layout.bottom_sheet_menu_list, null) as RecyclerView
|
||||
listView.setHasFixedSize(true)
|
||||
val mLayoutManager = GridLayoutManager(context, 6)
|
||||
listView.layoutManager = mLayoutManager
|
||||
|
||||
adapter
|
||||
.register<Int>(R.layout.color_picker_menu_item) { item, injector ->
|
||||
injector
|
||||
.with<MaterialCardView>(R.id.color) {
|
||||
it.setCardBackgroundColor(ColorStateList.valueOf(item))
|
||||
}
|
||||
.with<AppCompatImageView>(R.id.check) {
|
||||
if (getSelected?.invoke() == item) {
|
||||
it.setColorFilter(
|
||||
ContextCompat.getColor(
|
||||
context,
|
||||
if (item.isColorDark()) android.R.color.white else android.R.color.black
|
||||
),
|
||||
android.graphics.PorterDuff.Mode.MULTIPLY
|
||||
)
|
||||
it.isVisible = true
|
||||
} else {
|
||||
it.isVisible = false
|
||||
}
|
||||
}
|
||||
.clicked(R.id.color) {
|
||||
adapter.notifyItemChanged(adapter.data.indexOf(getSelected?.invoke()))
|
||||
onColorSelected?.invoke(item)
|
||||
val position = adapter.data.indexOf(item)
|
||||
adapter.notifyItemChanged(position)
|
||||
(listView.layoutManager as GridLayoutManager).scrollToPositionWithOffset(position,0)
|
||||
}
|
||||
}
|
||||
.attachTo(listView)
|
||||
|
||||
adapter.updateData(colors.toList())
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
view.color_loader.isVisible = false
|
||||
view.list_container.addView(listView)
|
||||
this@BottomSheetColorPicker.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
view.list_container.isVisible = true
|
||||
}
|
||||
})
|
||||
|
||||
setContentView(view)
|
||||
super.show()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
loadingJob?.cancel()
|
||||
loadingJobs.forEach { it.cancel() }
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,11 @@
|
||||
package com.tommasoberlose.anotherwidget.components
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.MenuRes
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_menu.view.*
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_item.view.*
|
||||
@ -21,7 +15,7 @@ import kotlinx.android.synthetic.main.bottom_sheet_menu_item.view.*
|
||||
* theme which sets a rounded background to the dialog
|
||||
* and doesn't dim the navigation bar
|
||||
*/
|
||||
open class BottomSheetMenu<T>(context: Context, private val header: String? = null, private val isMultiSelection: Boolean = false) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||
open class BottomSheetMenu<T>(context: Context, private val header: String? = null, private val message: String? = null, private val isMessageWarning: Boolean = false, private val isMultiSelection: Boolean = false) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||
|
||||
private val items: ArrayList<MenuItem<T>> = ArrayList()
|
||||
private var selectedRes: ArrayList<T> = ArrayList()
|
||||
@ -60,6 +54,10 @@ open class BottomSheetMenu<T>(context: Context, private val header: String? = nu
|
||||
view.header.isVisible = header != null
|
||||
view.header_text.text = header ?: ""
|
||||
|
||||
view.warning_text.isVisible = message != null
|
||||
view.warning_text.text = message ?: ""
|
||||
view.warning_text.setTextColor(ContextCompat.getColor(context, if (isMessageWarning) R.color.warningColorText else R.color.colorSecondaryText))
|
||||
|
||||
// Menu
|
||||
for (item in items) {
|
||||
if (item.value != null) {
|
||||
|
@ -0,0 +1,63 @@
|
||||
package com.tommasoberlose.anotherwidget.components
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import kotlinx.android.synthetic.main.bottom_sheet_dialog.view.*
|
||||
|
||||
typealias DialogCallback = () -> Unit
|
||||
|
||||
class MaterialBottomSheetDialog(
|
||||
context: Context,
|
||||
private val title: String? = "",
|
||||
private val message: String? = ""
|
||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||
|
||||
private var positiveButtonLabel: String? = null
|
||||
private var negativeButtonLabel: String? = null
|
||||
private var positiveCallback: DialogCallback? = null
|
||||
private var negativeCallback: DialogCallback? = null
|
||||
|
||||
fun setPositiveButton(label: String? = context.getString(android.R.string.ok), callback: DialogCallback? = null): MaterialBottomSheetDialog {
|
||||
positiveButtonLabel = label
|
||||
positiveCallback = callback
|
||||
return this
|
||||
}
|
||||
|
||||
fun setNegativeButton(label: String? = context.getString(android.R.string.cancel), callback: DialogCallback? = null): MaterialBottomSheetDialog {
|
||||
negativeButtonLabel = label
|
||||
negativeCallback = callback
|
||||
return this
|
||||
}
|
||||
|
||||
override fun show() {
|
||||
val view = View.inflate(context, R.layout.bottom_sheet_dialog, null)
|
||||
|
||||
// Header
|
||||
view.message.isVisible = title != null
|
||||
view.title.text = title ?: ""
|
||||
|
||||
view.message.isVisible = message != null
|
||||
view.message.text = message ?: ""
|
||||
|
||||
view.action_positive.isVisible = positiveButtonLabel != null
|
||||
view.action_positive.text = positiveButtonLabel ?: ""
|
||||
view.action_positive.setOnClickListener {
|
||||
positiveCallback?.invoke()
|
||||
this.dismiss()
|
||||
}
|
||||
|
||||
view.action_negative.isVisible = negativeButtonLabel != null
|
||||
view.action_negative.text = negativeButtonLabel ?: ""
|
||||
view.action_negative.setOnClickListener {
|
||||
negativeCallback?.invoke()
|
||||
this.dismiss()
|
||||
}
|
||||
|
||||
setContentView(view)
|
||||
super.show()
|
||||
}
|
||||
|
||||
}
|
@ -33,17 +33,16 @@ class EventRepository(val context: Context) {
|
||||
remove(Preferences::nextEventEndDate)
|
||||
remove(Preferences::nextEventCalendarId)
|
||||
}
|
||||
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
fun saveNextEventData(event: Event) {
|
||||
Preferences.nextEventId = event.id
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
fun getNextEvent(): Event? = realm.where(Event::class.java).equalTo("id", Preferences.nextEventId).findFirst() ?: realm.where(Event::class.java).findFirst()
|
||||
|
||||
fun getEventByEventId(id: Long): Event? = realm.where(Event::class.java).equalTo("eventID", id).findFirst()
|
||||
|
||||
fun goToNextEvent() {
|
||||
val eventList = realm.where(Event::class.java).findAll()
|
||||
|
||||
|
@ -4,10 +4,11 @@ object Actions {
|
||||
const val ACTION_EXTRA_OPEN_WEATHER_PROVIDER = "ACTION_EXTRA_OPEN_WEATHER_PROVIDER"
|
||||
const val ACTION_EXTRA_DISABLE_GPS_NOTIFICATION = "ACTION_EXTRA_DISABLE_GPS_NOTIFICATION"
|
||||
|
||||
const val ACTION_TIME_UPDATE = "com.tommasoberlose.anotherwidget.action.ACTION_TIME_UPDATE"
|
||||
const val ACTION_CALENDAR_UPDATE = "com.tommasoberlose.anotherwidget.action.ACTION_CALENDAR_UPDATE"
|
||||
const val ACTION_WEATHER_UPDATE = "com.tommasoberlose.anotherwidget.action.ACTION_WEATHER_UPDATE"
|
||||
const val ACTION_OPEN_WEATHER_INTENT = "com.tommasoberlose.anotherwidget.action.ACTION_OPEN_WEATHER_INTENT"
|
||||
const val ACTION_TIME_UPDATE = "com.tommasoberlose.anotherwidget.action.TIME_UPDATE"
|
||||
const val ACTION_CALENDAR_UPDATE = "com.tommasoberlose.anotherwidget.action.CALENDAR_UPDATE"
|
||||
const val ACTION_WEATHER_UPDATE = "com.tommasoberlose.anotherwidget.action.WEATHER_UPDATE"
|
||||
const val ACTION_OPEN_WEATHER_INTENT = "com.tommasoberlose.anotherwidget.action.OPEN_WEATHER_INTENT"
|
||||
const val ACTION_GO_TO_NEXT_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_NEXT_EVENT"
|
||||
const val ACTION_GO_TO_PREVIOUS_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_PREVIOUS_EVENT"
|
||||
const val ACTION_REPORT_CRASH = "com.tommasoberlose.anotherwidget.action.REPORT_CRASH"
|
||||
}
|
@ -7,63 +7,11 @@ object Constants {
|
||||
const val RESULT_APP_NAME = "RESULT_APP_NAME"
|
||||
const val RESULT_APP_PACKAGE = "RESULT_APP_PACKAGE"
|
||||
|
||||
const val PREF_SHOW_EVENTS = "PREF_SHOW_EVENTS"
|
||||
const val PREF_SHOW_WEATHER = "PREF_SHOW_WEATHER"
|
||||
const val PREF_WEATHER_ICON = "PREF_WEATHER_ICON"
|
||||
const val PREF_WEATHER_TEMP = "PREF_WEATHER_TEMP"
|
||||
const val PREF_WEATHER_TEMP_UNIT = "PREF_WEATHER_TEMP_UNIT"
|
||||
const val PREF_WEATHER_REAL_TEMP_UNIT = "PREF_WEATHER_REAL_TEMP_UNIT"
|
||||
const val PREF_CALENDAR_ALL_DAY = "PREF_CALENDAR_ALL_DAY"
|
||||
const val PREF_CALENDAR_FILTER = "PREF_CALENDAR_FILTER"
|
||||
|
||||
const val PREF_EVENT_ID = "PREF_EVENT_ID"
|
||||
const val PREF_NEXT_EVENT_ID = "PREF_NEXT_EVENT_ID"
|
||||
const val PREF_NEXT_EVENT_NAME = "PREF_NEXT_EVENT_NAME"
|
||||
const val PREF_NEXT_EVENT_START_DATE = "PREF_NEXT_EVENT_START_DATE"
|
||||
const val PREF_NEXT_EVENT_ALL_DAY = "PREF_NEXT_EVENT_ALL_DAY"
|
||||
const val PREF_NEXT_EVENT_LOCATION = "PREF_NEXT_EVENT_LOCATION"
|
||||
const val PREF_NEXT_EVENT_END_DATE = "PREF_NEXT_EVENT_END_DATE"
|
||||
const val PREF_NEXT_EVENT_CALENDAR_ID = "PREF_NEXT_EVENT_CALENDAR_ID"
|
||||
const val PREF_CUSTOM_LOCATION_LAT = "PREF_CUSTOM_LOCATION_LAT"
|
||||
const val PREF_CUSTOM_LOCATION_LON = "PREF_CUSTOM_LOCATION_LON"
|
||||
const val PREF_CUSTOM_LOCATION_ADD = "PREF_CUSTOM_LOCATION_ADD"
|
||||
const val PREF_HOUR_FORMAT = "PREF_HOUR_FORMAT"
|
||||
const val PREF_ITA_FORMAT_DATE = "PREF_ITA_FORMAT_DATE"
|
||||
const val PREF_WEATHER_REFRESH_PERIOD = "PREF_WEATHER_REFRESH_PERIOD"
|
||||
const val PREF_SHOW_UNTIL = "PREF_SHOW_UNTIL"
|
||||
const val PREF_CALENDAR_APP_NAME = "PREF_CALENDAR_APP_NAME"
|
||||
const val PREF_CALENDAR_APP_PACKAGE = "PREF_CALENDAR_APP_PACKAGE"
|
||||
const val PREF_WEATHER_APP_NAME = "PREF_WEATHER_APP_NAME"
|
||||
const val PREF_WEATHER_APP_PACKAGE = "PREF_WEATHER_APP_PACKAGE"
|
||||
const val PREF_WEATHER_PROVIDER_API_KEY = "PREF_WEATHER_PROVIDER_API_KEY"
|
||||
const val PREF_EVENT_APP_NAME = "PREF_EVENT_APP_NAME"
|
||||
const val PREF_EVENT_APP_PACKAGE = "PREF_EVENT_APP_PACKAGE"
|
||||
const val PREF_SHOW_EVENT_LOCATION = "PREF_SHOW_EVENT_LOCATION"
|
||||
const val PREF_TEXT_COLOR = "PREF_TEXT_COLOR"
|
||||
const val PREF_TEXT_MAIN_SIZE = "PREF_TEXT_MAIN_SIZE"
|
||||
const val PREF_TEXT_SECOND_SIZE = "PREF_TEXT_SECOND_SIZE"
|
||||
const val PREF_TEXT_CLOCK_SIZE = "PREF_TEXT_CLOCK_SIZE"
|
||||
const val PREF_WEATHER_PROVIDER = "PREF_WEATHER_PROVIDER"
|
||||
const val PREF_SHOW_CLOCK = "PREF_SHOW_CLOCK"
|
||||
const val PREF_CLOCK_APP_NAME = "PREF_CLOCK_APP_NAME"
|
||||
const val PREF_CLOCK_APP_PACKAGE = "PREF_CLOCK_APP_PACKAGE"
|
||||
const val PREF_TEXT_SHADOW = "PREF_TEXT_SHADOW"
|
||||
const val PREF_SHOW_DIFF_TIME = "PREF_SHOW_DIFF_TIME"
|
||||
const val PREF_SHOW_DECLINED_EVENTS = "PREF_SHOW_DECLINED_EVENTS"
|
||||
const val PREF_OPEN_WEATHER_API_KEY = "PREF_OPEN_WEATHER_API_KEY"
|
||||
const val PREF_DARK_SKY_API_KEY = "PREF_DARK_SKY_API_KEY"
|
||||
const val PREF_WU_API_KEY = "PREF_WU_API_KEY"
|
||||
const val PREF_SECOND_ROW_INFORMATION = "PREF_SECOND_ROW_INFORMATION"
|
||||
const val PREF_CUSTOM_FONT = "PREF_CUSTOM_FONT"
|
||||
const val PREF_CUSTOM_FONT_FILE = "PREF_CUSTOM_FONT_FILE"
|
||||
const val PREF_SHOW_NEXT_EVENT = "PREF_SHOW_NEXT_EVENT"
|
||||
const val PREF_SHOW_WIDGET_PREVIEW = "PREF_SHOW_WIDGET_PREVIEW"
|
||||
const val PREF_SHOW_GPS_NOTIFICATION = "PREF_SHOW_GPS_NOTIFICATION"
|
||||
|
||||
const val CUSTOM_FONT_PRODUCT_SANS = 1
|
||||
|
||||
const val itDateFormat = "EEEE, d MMM"
|
||||
const val engDateFormat = "EEEE, MMM d"
|
||||
const val goodHourFormat = "HH:mm"
|
||||
const val badHourFormat = "hh:mm a"
|
||||
enum class ClockBottomMargin(val value: Int) {
|
||||
NONE(0),
|
||||
SMALL(1),
|
||||
MEDIUM(2),
|
||||
LARGE(3)
|
||||
}
|
||||
}
|
@ -7,18 +7,17 @@ import com.chibatching.kotpref.KotprefModel
|
||||
object Preferences : KotprefModel() {
|
||||
override val commitAllPropertiesByDefault: Boolean = true
|
||||
|
||||
var darkThemePreference by intPref(default = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) MODE_NIGHT_FOLLOW_SYSTEM else MODE_NIGHT_AUTO_BATTERY)
|
||||
var darkThemePreference by intPref(default = MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
|
||||
var showEvents by booleanPref(key = "PREF_SHOW_EVENTS", default = false)
|
||||
var showWeather by booleanPref(key = "PREF_SHOW_WEATHER")
|
||||
var weatherIcon by stringPref(key = "PREF_WEATHER_ICON")
|
||||
var weatherTemp by floatPref(key = "PREF_WEATHER_TEMP")
|
||||
var showWeather by booleanPref(key = "PREF_SHOW_WEATHER", default = false)
|
||||
var weatherIcon by stringPref(key = "PREF_WEATHER_ICON", default = "")
|
||||
var weatherTemp by floatPref(key = "PREF_WEATHER_TEMP", default = 0f)
|
||||
var weatherTempUnit by stringPref(key = "PREF_WEATHER_TEMP_UNIT", default = "F")
|
||||
var weatherRealTempUnit by stringPref(key = "PREF_WEATHER_REAL_TEMP_UNIT", default = "F")
|
||||
var calendarAllDay by booleanPref(key = "PREF_CALENDAR_ALL_DAY", default = false)
|
||||
var calendarAllDay by booleanPref(key = "PREF_CALENDAR_ALL_DAY", default = true)
|
||||
var calendarFilter by stringPref(key = "PREF_CALENDAR_FILTER", default = "")
|
||||
|
||||
var eventId by intPref(key = "PREF_EVENT_ID", default = -1)
|
||||
var nextEventId by longPref(key = "PREF_NEXT_EVENT_ID", default = -1)
|
||||
var nextEventName by stringPref(key = "PREF_NEXT_EVENT_NAME")
|
||||
var nextEventStartDate by longPref(key = "PREF_NEXT_EVENT_START_DATE")
|
||||
@ -29,7 +28,6 @@ object Preferences : KotprefModel() {
|
||||
var customLocationLat by stringPref(key = "PREF_CUSTOM_LOCATION_LAT", default = "")
|
||||
var customLocationLon by stringPref(key = "PREF_CUSTOM_LOCATION_LON", default = "")
|
||||
var customLocationAdd by stringPref(key = "PREF_CUSTOM_LOCATION_ADD", default = "")
|
||||
var hourFormat by stringPref(key = "PREF_HOUR_FORMAT", default = "12")
|
||||
var dateFormat by stringPref(default = "")
|
||||
var weatherRefreshPeriod by intPref(key = "PREF_WEATHER_REFRESH_PERIOD", default = 1)
|
||||
var showUntil by intPref(key = "PREF_SHOW_UNTIL", default = 1)
|
||||
@ -40,28 +38,35 @@ object Preferences : KotprefModel() {
|
||||
var weatherProviderApi by stringPref(key = "PREF_WEATHER_PROVIDER_API_KEY", default = "")
|
||||
var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "")
|
||||
var eventAppPackage by stringPref(key = "PREF_EVENT_APP_PACKAGE", default = "")
|
||||
var showEventLocation by stringPref(key = "PREF_SHOW_EVENT_LOCATION", default = "")
|
||||
var openEventDetails by booleanPref(default = true)
|
||||
var textGlobalColor by stringPref(key = "PREF_TEXT_COLOR", default = "#FFFFFF")
|
||||
var textGlobalAlpha by stringPref(default = "FF")
|
||||
|
||||
var backgroundCardColor by stringPref(default = "#000000")
|
||||
var backgroundCardAlpha by stringPref(default = "00")
|
||||
|
||||
var clockTextColor by stringPref(default = "#FFFFFF")
|
||||
var clockTextAlpha by stringPref(default = "FF")
|
||||
|
||||
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f)
|
||||
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
|
||||
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
|
||||
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.value)
|
||||
var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false)
|
||||
var clockAppName by stringPref(key = "PREF_CLOCK_APP_NAME", default = "")
|
||||
var clockAppPackage by stringPref(key = "PREF_CLOCK_APP_PACKAGE", default = "")
|
||||
var showNextAlarm by booleanPref(default = true)
|
||||
var showNextAlarm by booleanPref(default = false)
|
||||
var textShadow by intPref(key = "PREF_TEXT_SHADOW", default = 1)
|
||||
var showDiffTime by booleanPref(key = "PREF_SHOW_DIFF_TIME")
|
||||
var showDeclinedEvents by booleanPref(key = "PREF_SHOW_DECLINED_EVENTS", default = true)
|
||||
var openWeatherApiKey by stringPref(key = "PREF_OPEN_WEATHER_API_KEY", default = "")
|
||||
var darkSkyApiKey by stringPref(key = "PREF_DARK_SKY_API_KEY", default = "")
|
||||
var wuApiKey by stringPref(key = "PREF_WU_API_KEY", default = "")
|
||||
var secondRowInformation by intPref(key = "PREF_SECOND_ROW_INFORMATION", default = 1)
|
||||
var showDiffTime by booleanPref(key = "PREF_SHOW_DIFF_TIME", default = true)
|
||||
var showDeclinedEvents by booleanPref(key = "PREF_SHOW_DECLINED_EVENTS", default = false)
|
||||
var secondRowInformation by intPref(key = "PREF_SECOND_ROW_INFORMATION", default = 0)
|
||||
var customFont by intPref(key = "PREF_CUSTOM_FONT", default = Constants.CUSTOM_FONT_PRODUCT_SANS)
|
||||
var customFontFile by stringPref(key = "PREF_CUSTOM_FONT_FILE")
|
||||
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
|
||||
var showGpsInformation by booleanPref(key = "PREF_SHOW_GPS_NOTIFICATION", default = true)
|
||||
|
||||
var showWallpaper by booleanPref(default = false)
|
||||
var showWallpaper by booleanPref(default = true)
|
||||
var showBigClockWarning by booleanPref(default = true)
|
||||
var showWeatherWarning by booleanPref(default = true)
|
||||
var showPreview by booleanPref(default = true)
|
||||
var showXiaomiWarning by booleanPref(default = true)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.tommasoberlose.anotherwidget.helpers
|
||||
import android.app.AlarmManager
|
||||
import android.content.Context
|
||||
import android.text.format.DateFormat
|
||||
import android.util.Log
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@ -11,7 +12,7 @@ object AlarmHelper {
|
||||
val alarm = nextAlarmClock
|
||||
return if (
|
||||
alarm != null
|
||||
&& alarm.triggerTime - Calendar.getInstance().timeInMillis > 2 * 60 * 1000
|
||||
&& alarm.triggerTime - Calendar.getInstance().timeInMillis > 10 * 60 * 1000
|
||||
&& alarm.triggerTime - Calendar.getInstance().timeInMillis < 12 * 60 * 60 * 1000
|
||||
) {
|
||||
"%s %s".format(
|
||||
@ -22,4 +23,14 @@ object AlarmHelper {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
fun isAlarmProbablyWrong(context: Context): Boolean {
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
val alarm = nextAlarmClock
|
||||
return (
|
||||
alarm != null
|
||||
&& alarm.triggerTime - Calendar.getInstance().timeInMillis < 5 * 60 * 1000
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -2,27 +2,57 @@ package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import java.lang.Exception
|
||||
|
||||
|
||||
object BitmapHelper {
|
||||
|
||||
fun getBitmapFromView(view: View, width: Int? = null, height: Int? = null, draw: Boolean = true): Bitmap {
|
||||
//Define a bitmap with the same size as the view
|
||||
val measuredWidth = View.MeasureSpec.makeMeasureSpec(width ?: view.width, if (width != null) View.MeasureSpec.EXACTLY else View.MeasureSpec.UNSPECIFIED)
|
||||
val measuredWidth = View.MeasureSpec.makeMeasureSpec(width ?: view.width, if (width != null) View.MeasureSpec.EXACTLY else View.MeasureSpec.AT_MOST)
|
||||
val measuredHeight = View.MeasureSpec.makeMeasureSpec(height ?: view.height, if (height != null) View.MeasureSpec.EXACTLY else View.MeasureSpec.UNSPECIFIED)
|
||||
view.measure(measuredWidth, measuredHeight)
|
||||
view.measure(
|
||||
if (measuredWidth > 0) measuredWidth else 0,
|
||||
if (measuredHeight > 0) measuredHeight else 0
|
||||
)
|
||||
|
||||
val calculatedWidth = view.measuredWidth
|
||||
val widgetWidth = if (calculatedWidth in 1..16000) {
|
||||
calculatedWidth
|
||||
} else if (width != null && width > 0) {
|
||||
width
|
||||
} else {
|
||||
1
|
||||
}
|
||||
val calculatedHeight = view.measuredHeight
|
||||
val widgetHeight = if (calculatedHeight in 1..16000) {
|
||||
calculatedHeight
|
||||
} else if (height != null && height > 0) {
|
||||
height
|
||||
} else {
|
||||
1
|
||||
}
|
||||
|
||||
if (draw) {
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("WIDTH SPEC", measuredWidth)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("HEIGHT SPEC", measuredHeight)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredWidth", view.measuredWidth)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredHeight", view.measuredHeight)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final width", measuredWidth)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final height", view.measuredHeight)
|
||||
}
|
||||
|
||||
return try {
|
||||
val btm = Bitmap.createBitmap(
|
||||
view.measuredWidth,
|
||||
view.measuredHeight,
|
||||
Bitmap.Config.ARGB_8888
|
||||
widgetWidth,
|
||||
widgetHeight,
|
||||
if (draw) Bitmap.Config.ARGB_8888 else Bitmap.Config.ALPHA_8
|
||||
)
|
||||
if (draw) {
|
||||
//Bind a canvas to it
|
||||
@ -35,7 +65,7 @@ object BitmapHelper {
|
||||
btm
|
||||
} catch (ex: Exception) {
|
||||
FirebaseCrashlytics.getInstance().recordException(ex)
|
||||
Bitmap.createBitmap(5, 5, Bitmap.Config.ARGB_8888)
|
||||
Bitmap.createBitmap(5, 5, Bitmap.Config.ALPHA_8)
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,4 +102,30 @@ object BitmapHelper {
|
||||
|
||||
return resultBitmap
|
||||
}
|
||||
|
||||
fun drawableToBitmap(drawable: Drawable): Bitmap? {
|
||||
var bitmap: Bitmap? = null
|
||||
if (drawable is BitmapDrawable) {
|
||||
if (drawable.bitmap != null) {
|
||||
return drawable.bitmap
|
||||
}
|
||||
}
|
||||
bitmap = if (drawable.intrinsicWidth <= 0 || drawable.intrinsicHeight <= 0) {
|
||||
Bitmap.createBitmap(
|
||||
1,
|
||||
1,
|
||||
Bitmap.Config.ARGB_8888
|
||||
) // Single color bitmap will be created of 1x1 pixel
|
||||
} else {
|
||||
Bitmap.createBitmap(
|
||||
drawable.intrinsicWidth,
|
||||
drawable.intrinsicHeight,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
}
|
||||
val canvas = Canvas(bitmap)
|
||||
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||
drawable.draw(canvas)
|
||||
return bitmap
|
||||
}
|
||||
}
|
@ -4,13 +4,12 @@ import android.Manifest
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.provider.CalendarContract
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.services.EventListenerJob
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import me.everything.providers.android.calendar.CalendarProvider
|
||||
@ -127,7 +126,7 @@ object CalendarHelper {
|
||||
UpdatesReceiver.setUpdates(context)
|
||||
MainWidget.updateWidget(context)
|
||||
|
||||
EventBus.getDefault().post(MainActivity.UpdateUiMessageEvent())
|
||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||
}
|
||||
|
||||
fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> {
|
||||
|
@ -1,14 +1,80 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object ColorHelper {
|
||||
fun getFontColor(): Int {
|
||||
return try {
|
||||
Color.parseColor("#%s%s".format(Preferences.textGlobalAlpha, Preferences.textGlobalColor.replace("#", "")))
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#FFFFFFFF")
|
||||
}
|
||||
}
|
||||
|
||||
fun getFontColorAlpha(): Int {
|
||||
return try {
|
||||
Preferences.textGlobalAlpha.toIntValue().toDouble() * 255 / 100
|
||||
} catch (e: Exception) {
|
||||
"FF".toIntValue().toDouble() * 255 / 100
|
||||
}.roundToInt()
|
||||
}
|
||||
|
||||
fun getFontColorRgb(): Int {
|
||||
return try {
|
||||
Color.parseColor(Preferences.textGlobalColor)
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#FFFFFF")
|
||||
Color.parseColor("#000000")
|
||||
}
|
||||
}
|
||||
fun getClockFontColor(): Int {
|
||||
return try {
|
||||
Color.parseColor("#%s%s".format(Preferences.clockTextAlpha, Preferences.clockTextColor.replace("#", "")))
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#FFFFFFFF")
|
||||
}
|
||||
}
|
||||
|
||||
fun getClockFontColorAlpha(): Int {
|
||||
return try {
|
||||
Preferences.clockTextAlpha.toIntValue().toDouble() * 255 / 100
|
||||
} catch (e: Exception) {
|
||||
"FF".toIntValue().toDouble() * 255 / 100
|
||||
}.roundToInt()
|
||||
}
|
||||
|
||||
fun getClockFontColorRgb(): Int {
|
||||
return try {
|
||||
Color.parseColor(Preferences.clockTextColor)
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#000000")
|
||||
}
|
||||
}
|
||||
|
||||
fun getBackgroundColor(): Int {
|
||||
return try {
|
||||
Color.parseColor("#%s%s".format(Preferences.backgroundCardAlpha, Preferences.backgroundCardColor.replace("#", "")))
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#00000000")
|
||||
}
|
||||
}
|
||||
|
||||
fun getBackgroundAlpha(): Int {
|
||||
return try {
|
||||
Preferences.backgroundCardAlpha.toIntValue().toDouble() * 255 / 100
|
||||
} catch (e: Exception) {
|
||||
"00".toIntValue().toDouble() * 255 / 100
|
||||
}.roundToInt()
|
||||
}
|
||||
|
||||
fun getBackgroundColorRgb(): Int {
|
||||
return try {
|
||||
Color.parseColor(Preferences.backgroundCardColor)
|
||||
} catch (e: Exception) {
|
||||
Color.parseColor("#000000")
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,4 +86,16 @@ object ColorHelper {
|
||||
1 - (0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255
|
||||
return darkness >= threshold
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
fun Int.toHexValue(): String {
|
||||
val intValue = (this * 255 / 100).toDouble().roundToInt()
|
||||
val hexValue = intValue.toString(16)
|
||||
return hexValue.padStart(2, '0').toUpperCase()
|
||||
}
|
||||
|
||||
fun String.toIntValue(): Int {
|
||||
val hexValue = this.toInt(16).toDouble()
|
||||
return (hexValue * 100 / 255).roundToInt()
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.ComponentName
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
@ -12,11 +13,23 @@ import android.provider.CalendarContract.Events
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import java.util.*
|
||||
|
||||
|
||||
object IntentHelper {
|
||||
|
||||
fun getGoogleMapsIntentFromAddress(context: Context, address:String): Intent {
|
||||
fun getWidgetUpdateIntent(context: Context): Intent {
|
||||
val widgetManager = AppWidgetManager.getInstance(context)
|
||||
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
||||
val widgetIds = widgetManager.getAppWidgetIds(widgetComponent)
|
||||
return Intent(context, MainWidget::class.java).apply {
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds)
|
||||
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||
}
|
||||
}
|
||||
|
||||
fun getGoogleMapsIntentFromAddress(context: Context, address: String): Intent {
|
||||
val gmmIntentUri: Uri = Uri.parse("geo:0,0?q=$address")
|
||||
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
||||
mapIntent.`package` = "com.google.android.apps.maps"
|
||||
@ -30,35 +43,6 @@ object IntentHelper {
|
||||
}
|
||||
}
|
||||
|
||||
fun getCalendarIntent(context: Context): Intent {
|
||||
return when (Preferences.calendarAppPackage) {
|
||||
"" -> {
|
||||
Intent(Intent.ACTION_MAIN).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
addCategory(Intent.CATEGORY_APP_CALENDAR)
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
Intent()
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Intent(Intent.ACTION_MAIN).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
addCategory(Intent.CATEGORY_APP_CALENDAR)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getWeatherIntent(context: Context): Intent {
|
||||
return when (Preferences.weatherAppPackage) {
|
||||
"" -> {
|
||||
@ -91,15 +75,16 @@ object IntentHelper {
|
||||
}
|
||||
}
|
||||
|
||||
fun getEventIntent(context: Context, e: Event): Intent {
|
||||
return when (Preferences.eventAppPackage) {
|
||||
fun getCalendarIntent(context: Context): Intent {
|
||||
val calendarUri = CalendarContract.CONTENT_URI
|
||||
.buildUpon()
|
||||
.appendPath("time")
|
||||
.appendPath(Calendar.getInstance().timeInMillis.toString())
|
||||
.build()
|
||||
return when (Preferences.calendarAppPackage) {
|
||||
"" -> {
|
||||
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = uri
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
data = calendarUri
|
||||
}
|
||||
}
|
||||
"_" -> {
|
||||
@ -107,28 +92,50 @@ object IntentHelper {
|
||||
}
|
||||
else -> {
|
||||
val pm: PackageManager = context.packageManager
|
||||
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
|
||||
try {
|
||||
pm.getLaunchIntentForPackage(Preferences.eventAppPackage)!!.apply {
|
||||
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
data = uri
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
// addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
// putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
// putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
data = calendarUri
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = uri
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
data = calendarUri
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getEventIntent(context: Context, e: Event, forceEventDetails: Boolean = false): Intent {
|
||||
return when (Preferences.openEventDetails || forceEventDetails) {
|
||||
true -> {
|
||||
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
|
||||
if (Preferences.calendarAppPackage == "") {
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = uri
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
// putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, if (e.allDay) 1 else 0)
|
||||
// type = "vnd.android.cursor.item/event"
|
||||
}
|
||||
} else {
|
||||
getCalendarIntent(context).apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
data = uri
|
||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||
// putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, if (e.allDay) 1 else 0)
|
||||
// type = "vnd.android.cursor.item/event"
|
||||
}
|
||||
}
|
||||
}
|
||||
false -> {
|
||||
getCalendarIntent(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getClockIntent(context: Context): Intent {
|
||||
return when (Preferences.clockAppPackage) {
|
||||
"" -> {
|
||||
|
@ -73,7 +73,7 @@ object SettingsStringHelper {
|
||||
return ""
|
||||
}
|
||||
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS).toString()
|
||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||
}
|
||||
eventDate.dayOfYear == nowDate.plusDays(1).dayOfYear -> {
|
||||
return String.format("%s", context.getString(R.string.tomorrow))
|
||||
@ -82,7 +82,7 @@ object SettingsStringHelper {
|
||||
return String.format("%s", context.getString(R.string.today))
|
||||
}
|
||||
else -> {
|
||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.DAY_IN_MILLIS).toString()
|
||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.DAY_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,16 +2,15 @@ package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import com.kwabenaberko.openweathermaplib.constants.Units
|
||||
import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper
|
||||
import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeatherCallback
|
||||
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
|
||||
/**
|
||||
@ -24,7 +23,7 @@ object WeatherHelper {
|
||||
val networkApi = WeatherNetworkApi(context)
|
||||
if (Preferences.customLocationAdd != "") {
|
||||
networkApi.updateWeather()
|
||||
} else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||
} else if (context.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||
LocationServices.getFusedLocationProviderClient(context).lastLocation.addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
val location = task.result
|
||||
@ -33,6 +32,7 @@ object WeatherHelper {
|
||||
Preferences.customLocationLon = location.longitude.toString()
|
||||
|
||||
networkApi.updateWeather()
|
||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -41,7 +41,7 @@ object WeatherHelper {
|
||||
|
||||
fun removeWeather(context: Context) {
|
||||
Preferences.remove(Preferences::weatherTemp)
|
||||
Preferences.remove(Preferences::weatherTempUnit)
|
||||
Preferences.remove(Preferences::weatherRealTempUnit)
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,54 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
|
||||
object WidgetHelper {
|
||||
class WidgetSizeProvider(
|
||||
private val context: Context,
|
||||
private val appWidgetManager: AppWidgetManager
|
||||
) {
|
||||
|
||||
fun getWidgetsSize(widgetId: Int): Pair<Int, Int> {
|
||||
val isPortrait = context.resources.configuration.orientation == ORIENTATION_PORTRAIT
|
||||
val width = getWidgetWidth(isPortrait, widgetId)
|
||||
val height = getWidgetHeight(isPortrait, widgetId)
|
||||
val widthInPx = context.dip(width)
|
||||
val heightInPx = context.dip(height)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("widthInPx", widthInPx)
|
||||
FirebaseCrashlytics.getInstance().setCustomKey("heightInPx", heightInPx)
|
||||
return widthInPx to heightInPx
|
||||
}
|
||||
|
||||
private fun getWidgetWidth(isPortrait: Boolean, widgetId: Int): Int =
|
||||
if (isPortrait) {
|
||||
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
|
||||
} else {
|
||||
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
|
||||
}
|
||||
|
||||
private fun getWidgetHeight(isPortrait: Boolean, widgetId: Int): Int =
|
||||
if (isPortrait) {
|
||||
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
|
||||
} else {
|
||||
getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
|
||||
}
|
||||
|
||||
private fun getWidgetSizeInDp(widgetId: Int, key: String): Int =
|
||||
appWidgetManager.getAppWidgetOptions(widgetId).getInt(key, 0)
|
||||
|
||||
private fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()
|
||||
|
||||
}
|
||||
|
||||
fun Pair<Int, Int>.reduceDimensionWithMaxWidth(width: Int): Pair<Int, Int> {
|
||||
return if (first < width) {
|
||||
this
|
||||
} else {
|
||||
val factor = width / first
|
||||
width to second * factor
|
||||
}
|
||||
}
|
||||
}
|
@ -14,9 +14,8 @@ open class Event(var id: Long = 0,
|
||||
var endDate: Long = 0,
|
||||
var calendarID: Int = 0,
|
||||
var allDay: Boolean = false,
|
||||
var address: String = "") : RealmObject(){
|
||||
|
||||
var address: String = "") : RealmObject() {
|
||||
override fun toString(): String {
|
||||
return "Event:\nID: " + id + "\nTITLE: " + title + "\nSTART DATE: " + Date(startDate) + "\nEND DATE: " + Date(endDate) + "\nCAL DAY: " + calendarID + "\nADDRESS: " + address
|
||||
return "Event:\nEVENT ID: " + eventID + "\nTITLE: " + title + "\nSTART DATE: " + Date(startDate) + "\nEND DATE: " + Date(endDate) + "\nCAL ID: " + calendarID + "\nADDRESS: " + address
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeathe
|
||||
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
|
||||
@ -23,11 +23,9 @@ class WeatherNetworkApi(val context: Context) {
|
||||
Preferences.weatherTemp = currentWeather.main.temp.toFloat()
|
||||
Preferences.weatherIcon = currentWeather.weather[0].icon
|
||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||
MainWidget.updateWidget(
|
||||
context
|
||||
)
|
||||
MainWidget.updateWidget(context)
|
||||
|
||||
EventBus.getDefault().post(MainActivity.UpdateUiMessageEvent())
|
||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
package com.tommasoberlose.anotherwidget.receivers
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import java.lang.Exception
|
||||
|
||||
class CrashlyticsReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action == Actions.ACTION_REPORT_CRASH) {
|
||||
val exception: Exception = intent.getSerializableExtra(EXCEPTION) as Exception
|
||||
FirebaseCrashlytics.getInstance().recordException(exception)
|
||||
FirebaseCrashlytics.getInstance().sendUnsentReports()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private const val EXCEPTION = "EXCEPTION"
|
||||
|
||||
fun sendCrash(context: Context, exception: Exception) {
|
||||
context.sendBroadcast(Intent(context, CrashlyticsReceiver::class.java).apply {
|
||||
action = Actions.ACTION_REPORT_CRASH
|
||||
putExtra(EXCEPTION, exception)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -12,7 +12,6 @@ class NewCalendarEventReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val eventRepository = EventRepository(context)
|
||||
Log.d("ciao", "nuovo evento")
|
||||
when (intent.action) {
|
||||
Intent.ACTION_PROVIDER_CHANGED,
|
||||
Intent.ACTION_TIME_CHANGED -> {
|
||||
|
@ -0,0 +1,22 @@
|
||||
package com.tommasoberlose.anotherwidget.receivers
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
|
||||
|
||||
class PlayerReceiver : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
Log.d("ciao", "player ok")
|
||||
|
||||
// val cmd = intent.getStringExtra("command")
|
||||
// Log.v("tag ", "$action / $cmd")
|
||||
// val artist = intent.getStringExtra("artist")
|
||||
// val album = intent.getStringExtra("album")
|
||||
// val track = intent.getStringExtra("track")
|
||||
// Log.v("tag", "$artist:$album:$track")
|
||||
|
||||
}
|
||||
}
|
@ -1,17 +1,18 @@
|
||||
package com.tommasoberlose.anotherwidget.receivers
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.util.Log
|
||||
import androidx.core.app.AlarmManagerCompat
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import org.joda.time.Period
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
@ -21,37 +22,57 @@ class UpdatesReceiver : BroadcastReceiver() {
|
||||
when (intent.action) {
|
||||
Intent.ACTION_BOOT_COMPLETED,
|
||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||
Intent.ACTION_TIME_CHANGED,
|
||||
Intent.ACTION_TIMEZONE_CHANGED,
|
||||
Intent.ACTION_LOCALE_CHANGED,
|
||||
Actions.ACTION_CALENDAR_UPDATE -> CalendarHelper.updateEventList(context)
|
||||
|
||||
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
||||
Intent.ACTION_DATE_CHANGED,
|
||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED -> MainWidget.updateWidget(context)
|
||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
||||
Actions.ACTION_TIME_UPDATE -> {
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun setUpdates(context: Context) {
|
||||
removeUpdates(context)
|
||||
|
||||
|
||||
val eventRepository = EventRepository(context)
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
eventRepository.getEvents().forEach { event ->
|
||||
val hoursDiff = Period(Calendar.getInstance().timeInMillis, event.startDate).hours
|
||||
|
||||
// Update the widget every hour till the event
|
||||
(0 .. hoursDiff).forEach {
|
||||
setExact(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
(event.startDate + 1000) - it * 1000 * 60* 60,
|
||||
PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0)
|
||||
)
|
||||
val now = Calendar.getInstance().apply {
|
||||
set(Calendar.SECOND, 0)
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
}
|
||||
val diff = Period(now.timeInMillis, event.startDate)
|
||||
if (event.startDate > now.timeInMillis) {
|
||||
// Update the widget every hour till the event
|
||||
(0..diff.hours).forEach {
|
||||
setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC,
|
||||
if (event.startDate - it * 1000 * 60 * 60 > 60 * 1000) event.startDate - it * 1000 * 60 * 60 else now.timeInMillis + 120000,
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
event.eventID.toInt() + it,
|
||||
Intent(context, UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_TIME_UPDATE
|
||||
},
|
||||
0
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the widget one second after the event is finished
|
||||
setExact(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
event.endDate + 1000,
|
||||
PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0)
|
||||
setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC,
|
||||
if (event.endDate > 60 *1000) event.endDate else now.timeInMillis + 120000,
|
||||
PendingIntent.getBroadcast(context, 1, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -59,7 +80,12 @@ class UpdatesReceiver : BroadcastReceiver() {
|
||||
|
||||
fun removeUpdates(context: Context) {
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
cancel(PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java), 0))
|
||||
cancel(PendingIntent.getBroadcast(context, 1, Intent(context, UpdatesReceiver::class.java), 0))
|
||||
EventRepository(context).getEvents().forEach {
|
||||
(0..24).forEach { hour ->
|
||||
cancel(PendingIntent.getBroadcast(context, it.eventID.toInt() * hour, Intent(context, UpdatesReceiver::class.java), 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||
@ -17,68 +18,63 @@ class WeatherReceiver : BroadcastReceiver() {
|
||||
when (intent.action) {
|
||||
Intent.ACTION_BOOT_COMPLETED,
|
||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||
Intent.ACTION_TIMEZONE_CHANGED,
|
||||
Intent.ACTION_LOCALE_CHANGED,
|
||||
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
|
||||
|
||||
Actions.ACTION_WEATHER_UPDATE -> WeatherHelper.updateWeather(context)
|
||||
Actions.ACTION_WEATHER_UPDATE -> {
|
||||
WeatherHelper.updateWeather(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MINUTE = 60 * 1000L
|
||||
fun setUpdates(context: Context) {
|
||||
removeUpdates(context)
|
||||
|
||||
if (Preferences.showWeather && Preferences.weatherProviderApi != "") {
|
||||
WeatherHelper.updateWeather(context)
|
||||
|
||||
val interval = MINUTE * when (Preferences.weatherRefreshPeriod) {
|
||||
0 -> 30
|
||||
1 -> 60
|
||||
2 -> 60L * 3
|
||||
3 -> 60L * 6
|
||||
4 -> 60L * 12
|
||||
5 -> 60L * 24
|
||||
else -> 60
|
||||
}
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
val pi = PendingIntent.getBroadcast(
|
||||
context,
|
||||
1,
|
||||
Intent(context, WeatherReceiver::class.java).apply {
|
||||
action = Actions.ACTION_WEATHER_UPDATE
|
||||
},
|
||||
0
|
||||
setRepeating(
|
||||
AlarmManager.RTC,
|
||||
Calendar.getInstance().timeInMillis,
|
||||
interval,
|
||||
PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
||||
)
|
||||
|
||||
val refresh: Long = when (Preferences.weatherRefreshPeriod) {
|
||||
0 -> 30
|
||||
1 -> 60
|
||||
2 -> 60 * 3
|
||||
3 -> 60 * 6
|
||||
4 -> 60 * 12
|
||||
5 -> 60 * 24
|
||||
else -> 60
|
||||
}
|
||||
val now = Calendar.getInstance().apply {
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
set(Calendar.SECOND, 0)
|
||||
}
|
||||
|
||||
setRepeating(AlarmManager.RTC_WAKEUP, now.timeInMillis, 1000 * 60 * refresh, pi)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setOneTimeUpdate(context: Context) {
|
||||
// Update the weather in a few minuter when the api key has been changed
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
val pi = PendingIntent.getBroadcast(context, 1, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
||||
val now = Calendar.getInstance().apply {
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
set(Calendar.SECOND, 0)
|
||||
}
|
||||
|
||||
listOf(10, 15, 20).forEach {
|
||||
setExact(AlarmManager.RTC_WAKEUP, now.timeInMillis + 1000 * 60 * it, pi)
|
||||
if (Preferences.showWeather && Preferences.weatherProviderApi != "") {
|
||||
listOf(10, 20, 30).forEach {
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC,
|
||||
it * MINUTE,
|
||||
PendingIntent.getBroadcast(context, it, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeUpdates(context: Context) {
|
||||
val intent = Intent(context, WeatherReceiver::class.java)
|
||||
val sender = PendingIntent.getBroadcast(context, 1, intent, 0)
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
alarmManager.cancel(sender)
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
cancel(PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0))
|
||||
listOf(10, 20, 30).forEach {
|
||||
cancel(PendingIntent.getBroadcast(context, it, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.location.Address
|
||||
import android.location.Geocoder
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import android.text.Editable
|
||||
@ -125,7 +126,7 @@ class CustomLocationActivity : AppCompatActivity() {
|
||||
private fun requirePermission() {
|
||||
Dexter.withContext(this)
|
||||
.withPermissions(
|
||||
Manifest.permission.ACCESS_FINE_LOCATION
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
|
||||
).withListener(object: MultiplePermissionsListener {
|
||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||
report?.let {
|
||||
|
@ -1,50 +1,72 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.activities
|
||||
|
||||
import android.Manifest
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Activity
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Matrix
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.Navigation
|
||||
import com.google.android.material.badge.BadgeDrawable
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
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.MaterialBottomSheetDialog
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.helpers.BitmapHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.getCurrentWallpaper
|
||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.android.synthetic.main.the_widget_sans.*
|
||||
import kotlinx.coroutines.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
|
||||
class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private var mAppWidgetId: Int = -1
|
||||
private lateinit var viewModel: MainViewModel
|
||||
private val mainNavController: NavController? by lazy {
|
||||
Navigation.findNavController(
|
||||
this,
|
||||
R.id.content_fragment
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -53,131 +75,19 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
||||
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()
|
||||
|
||||
// Init clock
|
||||
clock.setTextColor(ColorHelper.getFontColor())
|
||||
clock.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
|
||||
clock.format12Hour = "hh:mm"
|
||||
clock.isVisible = Preferences.showClock
|
||||
|
||||
preview.layoutParams = preview.layoutParams.apply {
|
||||
height = 160.toPixel(this@MainActivity) + if (Preferences.showClock) 100.toPixel(this@MainActivity) else 0
|
||||
}
|
||||
|
||||
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
|
||||
subscribeUi(viewModel)
|
||||
updateUI()
|
||||
|
||||
CalendarHelper.updateEventList(this)
|
||||
WeatherHelper.updateWeather(this)
|
||||
}
|
||||
|
||||
private var uiJob: Job? = null
|
||||
|
||||
private fun updateUI() {
|
||||
preview.setCardBackgroundColor(getColor(if (ColorHelper.getFontColor().isColorDark()) android.R.color.white else R.color.colorAccent))
|
||||
val generatedView = MainWidget.generateWidgetView(this@MainActivity)
|
||||
generatedView.measure(0, 0)
|
||||
preview.measure(0, 0)
|
||||
|
||||
uiJob?.cancel()
|
||||
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||
val bitmap = BitmapHelper.getBitmapFromView(generatedView, if (preview.width > 0) preview.width else generatedView.measuredWidth, generatedView.measuredHeight)
|
||||
withContext(Dispatchers.Main) {
|
||||
// Clock
|
||||
clock.setTextColor(ColorHelper.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.height,
|
||||
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()
|
||||
} else {
|
||||
clock.layoutParams = clock.layoutParams.apply {
|
||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
clock.measure(0, 0)
|
||||
}
|
||||
|
||||
widget_bitmap.setImageBitmap(bitmap)
|
||||
widget_loader.animate().scaleX(0f).scaleY(0f).start()
|
||||
widget.animate().alpha(1f).start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun subscribeUi(viewModel: MainViewModel) {
|
||||
viewModel.showWallpaper.observe(this, Observer {
|
||||
widget_bg.setImageDrawable(if (it) getCurrentWallpaper() else null)
|
||||
})
|
||||
|
||||
logo.setOnClickListener {
|
||||
// startActivity(Intent(this, SupportDevActivity::class.java))
|
||||
}
|
||||
requirePermission()
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (mAppWidgetId > 0) {
|
||||
addNewWidget()
|
||||
if (mainNavController?.currentDestination?.id == R.id.appMainFragment) {
|
||||
if (mAppWidgetId > 0) {
|
||||
addNewWidget()
|
||||
} else {
|
||||
setResult(Activity.RESULT_OK)
|
||||
finish()
|
||||
}
|
||||
} else {
|
||||
setResult(Activity.RESULT_OK)
|
||||
finish()
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,30 +127,27 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
Preferences.preferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
private fun requirePermission() {
|
||||
Dexter.withContext(this)
|
||||
.withPermissions(
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
).withListener(object : MultiplePermissionsListener {
|
||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||
report?.let {
|
||||
Preferences.showWallpaper = false
|
||||
Preferences.showWallpaper = report.areAllPermissionsGranted()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
||||
updateUI()
|
||||
MainWidget.updateWidget(this)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
EventBus.getDefault().register(this)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
EventBus.getDefault().unregister(this)
|
||||
}
|
||||
|
||||
class UpdateUiMessageEvent
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onMessageEvent(ignore: UpdateUiMessageEvent?) {
|
||||
updateUI()
|
||||
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?.cancelPermissionRequest()
|
||||
}
|
||||
})
|
||||
.check()
|
||||
}
|
||||
}
|
||||
|
@ -8,15 +8,14 @@ import com.tommasoberlose.anotherwidget.ui.fragments.*
|
||||
class ViewPagerAdapter(fragmentActivity: FragmentActivity) :
|
||||
FragmentStateAdapter(fragmentActivity) {
|
||||
|
||||
override fun getItemCount(): Int = 5
|
||||
override fun getItemCount(): Int = 4
|
||||
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
return when (position) {
|
||||
1 -> CalendarSettingsFragment.newInstance()
|
||||
2 -> WeatherSettingsFragment.newInstance()
|
||||
3 -> ClockSettingsFragment.newInstance()
|
||||
4 -> AdvancedSettingsFragment.newInstance()
|
||||
else -> GeneralSettingsFragment.newInstance()
|
||||
1 -> CalendarTabFragment.newInstance()
|
||||
2 -> WeatherTabFragment.newInstance()
|
||||
3 -> ClockTabFragment.newInstance()
|
||||
else -> GeneralTabFragment.newInstance()
|
||||
}
|
||||
}
|
||||
}
|
@ -2,14 +2,11 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.DialogInterface
|
||||
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.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
@ -42,14 +39,13 @@ import kotlinx.android.synthetic.main.fragment_calendar_settings.*
|
||||
import kotlinx.android.synthetic.main.fragment_calendar_settings.scrollView
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.Comparator
|
||||
|
||||
class CalendarSettingsFragment : Fragment() {
|
||||
class CalendarTabFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = CalendarSettingsFragment()
|
||||
fun newInstance() = CalendarTabFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
@ -99,7 +95,7 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
viewModel.calendarAllDay.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
all_day_label.text =
|
||||
all_day_label?.text =
|
||||
if (it) getString(R.string.settings_all_day_subtitle_visible) else getString(R.string.settings_all_day_subtitle_gone)
|
||||
}
|
||||
checkReadEventsPermission()
|
||||
@ -107,49 +103,49 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
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)
|
||||
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(SettingsStringHelper.getSecondRowInfoString(it))
|
||||
second_row_info_label?.text = getString(SettingsStringHelper.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)
|
||||
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(SettingsStringHelper.getShowUntilString(it))
|
||||
show_until_label?.text = getString(SettingsStringHelper.getShowUntilString(it))
|
||||
}
|
||||
checkReadEventsPermission()
|
||||
})
|
||||
|
||||
viewModel.showNextEvent.observe(viewLifecycleOwner, Observer {
|
||||
show_multiple_events_label.setTextKeepState(if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible))
|
||||
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 {
|
||||
date_format_label.text = DateHelper.getDateText(requireContext(), Calendar.getInstance())
|
||||
date_format_label?.text = DateHelper.getDateText(requireContext(), Calendar.getInstance())
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.calendarAppName.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
calendar_app_label.text = if (it != "") it else getString(R.string.default_calendar_app)
|
||||
calendar_app_label?.text = if (it != "") it else getString(R.string.default_calendar_app)
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.eventAppName.observe(viewLifecycleOwner, Observer {
|
||||
viewModel.openEventDetails.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
event_app_label.text = if (it != "") it else getString(R.string.default_calendar_app)
|
||||
open_event_details_label?.text = if (it) getString(R.string.default_event_app) else getString(R.string.default_calendar_app)
|
||||
}
|
||||
})
|
||||
|
||||
@ -159,6 +155,9 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
action_show_events.setOnClickListener {
|
||||
Preferences.showEvents = !Preferences.showEvents
|
||||
if (Preferences.showEvents) {
|
||||
requirePermission()
|
||||
}
|
||||
}
|
||||
|
||||
action_filter_calendar.setOnClickListener {
|
||||
@ -301,8 +300,15 @@ class CalendarSettingsFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
action_event_app.setOnClickListener {
|
||||
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java), RequestCode.EVENT_APP_REQUEST_CODE.code)
|
||||
action_open_event_details.setOnClickListener {
|
||||
if (Preferences.showEvents) {
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_event_app_title)).setSelectedValue(Preferences.openEventDetails)
|
||||
.addItem(getString(R.string.default_event_app), true)
|
||||
.addItem(getString(R.string.default_calendar_app), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.openEventDetails = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_calendar_app.setOnClickListener {
|
||||
@ -312,13 +318,13 @@ class CalendarSettingsFragment : Fragment() {
|
||||
|
||||
private fun checkReadEventsPermission(showEvents: Boolean = Preferences.showEvents) {
|
||||
if (activity?.checkGrantedPermission(Manifest.permission.READ_CALENDAR) == true) {
|
||||
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
|
||||
show_events_label?.text = if (showEvents) getString(R.string.show_events_visible) else getString(R.string.show_events_not_visible)
|
||||
read_calendar_permission_alert?.isVisible = false
|
||||
CalendarHelper.updateEventList(requireContext())
|
||||
} else {
|
||||
show_events_label.text = if (showEvents) getString(R.string.description_permission_calendar) else getString(R.string.show_events_not_visible)
|
||||
read_calendar_permission_alert_icon.isVisible = showEvents
|
||||
read_calendar_permission_alert_icon.setOnClickListener {
|
||||
show_events_label?.text = if (showEvents) getString(R.string.description_permission_calendar) else getString(R.string.show_events_not_visible)
|
||||
read_calendar_permission_alert?.isVisible = showEvents
|
||||
read_calendar_permission_alert?.setOnClickListener {
|
||||
requirePermission()
|
||||
}
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
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.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentClockSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
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.showBigClockWarning.observe(viewLifecycleOwner, Observer {
|
||||
large_clock_warning.isVisible = it
|
||||
small_clock_warning.isVisible = !it
|
||||
})
|
||||
|
||||
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_hide_large_clock_warning.setOnClickListener {
|
||||
Preferences.showBigClockWarning = false
|
||||
}
|
||||
|
||||
action_show_clock.setOnClickListener {
|
||||
Preferences.showClock = !Preferences.showClock
|
||||
}
|
||||
|
||||
action_clock_text_size.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.settings_clock_text_size_title)).setSelectedValue(Preferences.clockTextSize)
|
||||
(46 downTo 12).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(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.showNextAlarm)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.showNextAlarm = value
|
||||
}.show()
|
||||
}
|
||||
|
||||
action_clock_app.setOnClickListener {
|
||||
if (Preferences.showClock) {
|
||||
startActivityForResult(Intent(requireContext(), 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)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,271 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlarmManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.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.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentClockSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import kotlinx.android.synthetic.main.fragment_clock_settings.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.lang.Exception
|
||||
|
||||
|
||||
class ClockTabFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = ClockTabFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
private lateinit var colors: IntArray
|
||||
|
||||
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)
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val lazyColors = requireContext().resources.getIntArray(R.array.material_colors)
|
||||
withContext(Dispatchers.Main) {
|
||||
colors = lazyColors
|
||||
}
|
||||
}
|
||||
setupListener()
|
||||
updateNextAlarmWarningUi()
|
||||
}
|
||||
|
||||
private fun subscribeUi(
|
||||
binding: FragmentClockSettingsBinding,
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
viewModel.showBigClockWarning.observe(viewLifecycleOwner, Observer {
|
||||
large_clock_warning?.isVisible = it
|
||||
small_clock_warning?.isVisible = !it
|
||||
})
|
||||
|
||||
viewModel.showClock.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_clock_label?.text =
|
||||
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.clockTextColor.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.clockTextAlpha == "00") {
|
||||
clock_text_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
clock_text_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor())).toUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.clockTextAlpha.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.clockTextAlpha == "00") {
|
||||
clock_text_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
clock_text_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor())).toUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.clockBottomMargin.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
clock_bottom_margin_label?.text = when (it) {
|
||||
Constants.ClockBottomMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
|
||||
Constants.ClockBottomMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
|
||||
Constants.ClockBottomMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
|
||||
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showNextAlarm.observe(viewLifecycleOwner, Observer {
|
||||
updateNextAlarmWarningUi()
|
||||
})
|
||||
|
||||
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_hide_large_clock_warning.setOnClickListener {
|
||||
Preferences.showBigClockWarning = false
|
||||
}
|
||||
|
||||
action_show_clock.setOnClickListener {
|
||||
Preferences.showClock = !Preferences.showClock
|
||||
}
|
||||
|
||||
action_clock_text_size.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.settings_clock_text_size_title)).setSelectedValue(Preferences.clockTextSize)
|
||||
(46 downTo 12).filter { it % 2 == 0 }.forEach {
|
||||
dialog.addItem("${it}sp", it.toFloat())
|
||||
}
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
Preferences.clockTextSize = value
|
||||
}.show()
|
||||
}
|
||||
|
||||
action_clock_text_color.setOnClickListener {
|
||||
BottomSheetColorPicker(requireContext(),
|
||||
colors = colors,
|
||||
header = getString(R.string.settings_font_color_title),
|
||||
getSelected = ColorHelper::getClockFontColorRgb,
|
||||
onColorSelected = { color: Int ->
|
||||
val colorString = Integer.toHexString(color)
|
||||
Preferences.clockTextColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||
},
|
||||
showAlphaSelector = true,
|
||||
alpha = Preferences.clockTextAlpha.toIntValue(),
|
||||
onAlphaChangeListener = { alpha ->
|
||||
Preferences.clockTextAlpha = alpha.toHexValue()
|
||||
}
|
||||
).show()
|
||||
}
|
||||
|
||||
action_clock_bottom_margin_size.setOnClickListener {
|
||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.clockBottomMargin)
|
||||
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_none), Constants.ClockBottomMargin.NONE.value)
|
||||
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_small), Constants.ClockBottomMargin.SMALL.value)
|
||||
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_medium), Constants.ClockBottomMargin.MEDIUM.value)
|
||||
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_large), Constants.ClockBottomMargin.LARGE.value)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.clockBottomMargin = value
|
||||
}.show()
|
||||
}
|
||||
|
||||
action_clock_app.setOnClickListener {
|
||||
if (Preferences.showClock) {
|
||||
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java),
|
||||
RequestCode.CLOCK_APP_REQUEST_CODE.code
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
action_show_next_alarm.setOnClickListener {
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.showNextAlarm)
|
||||
.addItem(getString(R.string.settings_visible), true)
|
||||
.addItem(getString(R.string.settings_not_visible), false)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.showNextAlarm = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateNextAlarmWarningUi() {
|
||||
with(requireContext().getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
val alarm = nextAlarmClock
|
||||
if (AlarmHelper.isAlarmProbablyWrong(requireContext()) && alarm != null && alarm.showIntent != null) {
|
||||
val pm = requireContext().packageManager as PackageManager
|
||||
val appNameOrPackage = try {
|
||||
pm.getApplicationLabel(pm.getApplicationInfo(alarm.showIntent?.creatorPackage ?: "", 0))
|
||||
} catch (e: Exception) {
|
||||
alarm.showIntent?.creatorPackage ?: ""
|
||||
}
|
||||
show_next_alarm_warning.text = getString(R.string.next_alarm_warning).format(appNameOrPackage)
|
||||
} else {
|
||||
maintainScrollPosition {
|
||||
show_next_alarm_label?.text = if (Preferences.showNextAlarm) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val nextAlarmChangeBroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
updateNextAlarmWarningUi()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
activity?.registerReceiver(nextAlarmChangeBroadcastReceiver, IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED))
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
activity?.unregisterReceiver(nextAlarmChangeBroadcastReceiver)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -18,6 +18,9 @@ import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentGeneralSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
@ -28,10 +31,10 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
||||
class GeneralSettingsFragment : Fragment() {
|
||||
class GeneralTabFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = GeneralSettingsFragment()
|
||||
fun newInstance() = GeneralTabFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
@ -71,42 +74,76 @@ class GeneralSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
private fun subscribeUi(
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
|
||||
viewModel.textMainSize.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
main_text_size_label.text = String.format("%.0fsp", it)
|
||||
main_text_size_label?.text = String.format("%.0fsp", it)
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.textSecondSize.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
second_text_size_label.text = String.format("%.0fsp", it)
|
||||
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"
|
||||
if (Preferences.textGlobalAlpha == "00") {
|
||||
font_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
font_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getFontColor())).toUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.textGlobalAlpha.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.textGlobalAlpha == "00") {
|
||||
font_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
font_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getFontColor())).toUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.backgroundCardColor.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.backgroundCardAlpha == "00") {
|
||||
background_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
background_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor())).toUpperCase()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.backgroundCardAlpha.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
if (Preferences.backgroundCardAlpha == "00") {
|
||||
background_color_label?.text = getString(R.string.transparent)
|
||||
} else {
|
||||
background_color_label?.text =
|
||||
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor())).toUpperCase()
|
||||
}
|
||||
font_color_label.text = it.toUpperCase()
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.textShadow.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
text_shadow_label.text = getString(SettingsStringHelper.getTextShadowString(it))
|
||||
text_shadow_label?.text = getString(SettingsStringHelper.getTextShadowString(it))
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.customFont.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
custom_font_label.text = getString(SettingsStringHelper.getCustomFontLabel(it))
|
||||
custom_font_label?.text = getString(SettingsStringHelper.getCustomFontLabel(it))
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -142,19 +179,35 @@ class GeneralSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
action_font_color.setOnClickListener {
|
||||
val textColor = try {
|
||||
Color.parseColor(Preferences.textGlobalColor)
|
||||
} catch (e: Exception) {
|
||||
Preferences.textGlobalColor = "#FFFFFF"
|
||||
Color.parseColor(Preferences.textGlobalColor)
|
||||
}
|
||||
BottomSheetColorPicker(requireContext(),
|
||||
colors = colors,
|
||||
header = getString(R.string.settings_font_color_title),
|
||||
selected = textColor,
|
||||
getSelected = ColorHelper::getFontColorRgb,
|
||||
onColorSelected = { color: Int ->
|
||||
val colorString = Integer.toHexString(color)
|
||||
Preferences.textGlobalColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||
},
|
||||
showAlphaSelector = true,
|
||||
alpha = Preferences.textGlobalAlpha.toIntValue(),
|
||||
onAlphaChangeListener = { alpha ->
|
||||
Preferences.textGlobalAlpha = alpha.toHexValue()
|
||||
}
|
||||
).show()
|
||||
}
|
||||
|
||||
action_background_color.setOnClickListener {
|
||||
BottomSheetColorPicker(requireContext(),
|
||||
colors = colors,
|
||||
header = getString(R.string.settings_background_color_title),
|
||||
getSelected = { ColorHelper.getBackgroundColorRgb() },
|
||||
onColorSelected = { color: Int ->
|
||||
val colorString = Integer.toHexString(color)
|
||||
Preferences.backgroundCardColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||
},
|
||||
showAlphaSelector = true,
|
||||
alpha = Preferences.backgroundCardAlpha.toIntValue(),
|
||||
onAlphaChangeListener = { alpha ->
|
||||
Preferences.backgroundCardAlpha = alpha.toHexValue()
|
||||
}
|
||||
).show()
|
||||
}
|
@ -0,0 +1,331 @@
|
||||
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.Navigation
|
||||
import com.google.android.material.badge.BadgeDrawable
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentAdvancedSettingsBinding
|
||||
import com.tommasoberlose.anotherwidget.databinding.FragmentAppMainBinding
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.BitmapHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.getCurrentWallpaper
|
||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||
import kotlinx.android.synthetic.main.fragment_app_main.*
|
||||
import kotlinx.android.synthetic.main.the_widget_sans.*
|
||||
import kotlinx.coroutines.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = MainFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
enterTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, true)
|
||||
reenterTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, false)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||
return inflater.inflate(R.layout.fragment_app_main, container, false)
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
subscribeUi(viewModel)
|
||||
|
||||
// Viewpager
|
||||
pager.adapter = ViewPagerAdapter(requireActivity())
|
||||
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)
|
||||
else -> ""
|
||||
}
|
||||
}.attach()
|
||||
|
||||
// Init clock
|
||||
time.setTextColor(ColorHelper.getClockFontColor())
|
||||
time.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext()))
|
||||
time_am_pm.setTextColor(ColorHelper.getClockFontColor())
|
||||
time_am_pm.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2)
|
||||
time_container.isVisible = Preferences.showClock
|
||||
|
||||
preview.layoutParams = preview.layoutParams.apply {
|
||||
height = 160.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(requireContext()) else 0
|
||||
}
|
||||
subscribeUi(viewModel)
|
||||
updateUI()
|
||||
|
||||
// Warnings
|
||||
if (getString(R.string.xiaomi_manufacturer).equals(Build.MANUFACTURER, ignoreCase = true) && Preferences.showXiaomiWarning) {
|
||||
MaterialBottomSheetDialog(requireContext(), getString(R.string.xiaomi_warning_title), getString(R.string.xiaomi_warning_message))
|
||||
.setNegativeButton(getString(R.string.action_ignore)) {
|
||||
Preferences.showXiaomiWarning = false
|
||||
}
|
||||
.setPositiveButton(getString(R.string.action_grant_permission)) {
|
||||
Preferences.showXiaomiWarning = false
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.parse("package:${activity?.packageName}")
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
private var uiJob: Job? = null
|
||||
|
||||
private fun updateUI() {
|
||||
uiJob?.cancel()
|
||||
|
||||
if (Preferences.showPreview) {
|
||||
preview.setCardBackgroundColor(
|
||||
ContextCompat.getColor(
|
||||
requireContext(),
|
||||
if (ColorHelper.getFontColor()
|
||||
.isColorDark()
|
||||
) android.R.color.white else R.color.colorAccent
|
||||
)
|
||||
)
|
||||
widget_shape_background.setImageDrawable(BitmapHelper.getTintedDrawable(requireContext(), R.drawable.card_background, ColorHelper.getBackgroundColor()))
|
||||
uiJob = viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||
delay(200)
|
||||
val generatedView = MainWidget.generateWidgetView(requireContext())
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
generatedView.measure(0, 0)
|
||||
preview.measure(0, 0)
|
||||
}
|
||||
|
||||
val bitmap = BitmapHelper.getBitmapFromView(
|
||||
generatedView,
|
||||
if (preview.width > 0) preview.width else generatedView.measuredWidth,
|
||||
generatedView.measuredHeight
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
// Clock
|
||||
time.setTextColor(ColorHelper.getClockFontColor())
|
||||
time_am_pm.setTextColor(ColorHelper.getClockFontColor())
|
||||
time.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext())
|
||||
)
|
||||
time_am_pm.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
|
||||
)
|
||||
|
||||
// Clock bottom margin
|
||||
clock_bottom_margin_none.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value
|
||||
clock_bottom_margin_small.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value
|
||||
clock_bottom_margin_medium.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value
|
||||
clock_bottom_margin_large.isVisible =
|
||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value
|
||||
|
||||
if ((Preferences.showClock && !time_container.isVisible) || (!Preferences.showClock && time_container.isVisible)) {
|
||||
if (Preferences.showClock) {
|
||||
time_container.layoutParams = time_container.layoutParams.apply {
|
||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
time_container.measure(0, 0)
|
||||
}
|
||||
val initialHeight = time_container.measuredHeight
|
||||
ValueAnimator.ofFloat(
|
||||
if (Preferences.showClock) 0f else 1f,
|
||||
if (Preferences.showClock) 1f else 0f
|
||||
).apply {
|
||||
duration = 500L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Float
|
||||
time_container.layoutParams = time_container.layoutParams.apply {
|
||||
height = (initialHeight * animatedValue).toInt()
|
||||
}
|
||||
}
|
||||
addListener(
|
||||
onStart = {
|
||||
if (Preferences.showClock) {
|
||||
time_container.isVisible = true
|
||||
}
|
||||
},
|
||||
onEnd = {
|
||||
if (!Preferences.showClock) {
|
||||
time_container.isVisible = false
|
||||
}
|
||||
}
|
||||
)
|
||||
}.start()
|
||||
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
160.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
requireContext()
|
||||
) else 0
|
||||
).apply {
|
||||
duration = 500L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
}
|
||||
}.start()
|
||||
} else {
|
||||
time_container.layoutParams = time_container.layoutParams.apply {
|
||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
time_container.measure(0, 0)
|
||||
}
|
||||
|
||||
if (preview.height == 0) {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
160.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||
requireContext()
|
||||
) else 0
|
||||
).apply {
|
||||
duration = 300L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
bitmap_container.setImageBitmap(bitmap)
|
||||
widget_loader.animate().scaleX(0f).scaleY(0f).start()
|
||||
widget.animate().alpha(1f).start()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ValueAnimator.ofInt(
|
||||
preview.height,
|
||||
0
|
||||
).apply {
|
||||
duration = 300L
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Int
|
||||
val layoutParams = preview.layoutParams
|
||||
layoutParams.height = animatedValue
|
||||
preview.layoutParams = layoutParams
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
|
||||
// Calendar error indicator
|
||||
tabs?.getTabAt(1)?.orCreateBadge?.apply {
|
||||
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||
badgeGravity = BadgeDrawable.TOP_END
|
||||
}?.isVisible = Preferences.showEvents && activity?.checkGrantedPermission(Manifest.permission.READ_CALENDAR) != true
|
||||
|
||||
// Weather error indicator
|
||||
tabs?.getTabAt(2)?.orCreateBadge?.apply {
|
||||
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||
badgeGravity = BadgeDrawable.TOP_END
|
||||
}?.isVisible = Preferences.showWeather && (Preferences.weatherProviderApi == "" || (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) != true))
|
||||
|
||||
}
|
||||
|
||||
private fun subscribeUi(viewModel: MainViewModel) {
|
||||
viewModel.showWallpaper.observe(viewLifecycleOwner, Observer {
|
||||
activity?.let { act ->
|
||||
val wallpaper = act.getCurrentWallpaper()
|
||||
widget_bg.setImageDrawable(if (it) wallpaper else null)
|
||||
widget_bg.layoutParams = widget_bg.layoutParams.apply {
|
||||
|
||||
val metrics = DisplayMetrics()
|
||||
act.windowManager.defaultDisplay.getMetrics(metrics)
|
||||
|
||||
height = metrics.heightPixels
|
||||
width = (wallpaper?.intrinsicWidth ?: 1) * metrics.heightPixels / (wallpaper?.intrinsicWidth ?: 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
logo.setOnClickListener {
|
||||
// startActivity(Intent(this, SupportDevActivity::class.java))
|
||||
}
|
||||
|
||||
action_settings.setOnClickListener {
|
||||
Navigation.findNavController(it).navigate(R.id.action_appMainFragment_to_appSettingsFragment)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
||||
updateUI()
|
||||
MainWidget.updateWidget(requireContext())
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
|
||||
EventBus.getDefault().register(this)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
Preferences.preferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||
EventBus.getDefault().unregister(this)
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
class UpdateUiMessageEvent
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onMessageEvent(ignore: UpdateUiMessageEvent?) {
|
||||
updateUI()
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ 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
|
||||
@ -14,6 +13,9 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.Navigation
|
||||
import com.google.android.material.transition.MaterialContainerTransform
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.karumi.dexter.Dexter
|
||||
import com.karumi.dexter.MultiplePermissionsReport
|
||||
import com.karumi.dexter.PermissionToken
|
||||
@ -28,7 +30,7 @@ import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.SupportDevActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||
import kotlinx.android.synthetic.main.fragment_advanced_settings.*
|
||||
@ -36,16 +38,18 @@ import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
class AdvancedSettingsFragment : Fragment() {
|
||||
class SettingsFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = AdvancedSettingsFragment()
|
||||
fun newInstance() = SettingsFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enterTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, true)
|
||||
returnTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, false)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
@ -56,8 +60,6 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||
val binding = DataBindingUtil.inflate<FragmentAdvancedSettingsBinding>(inflater, R.layout.fragment_advanced_settings, container, false)
|
||||
|
||||
subscribeUi(viewModel)
|
||||
|
||||
binding.lifecycleOwner = this
|
||||
binding.viewModel = viewModel
|
||||
|
||||
@ -67,9 +69,15 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
action_back.setOnClickListener {
|
||||
Navigation.findNavController(it).popBackStack()
|
||||
}
|
||||
|
||||
subscribeUi(viewModel)
|
||||
|
||||
setupListener()
|
||||
|
||||
app_version.text = "v%s".format(BuildConfig.VERSION_NAME)
|
||||
app_version.text = "v%s (%s)".format(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)
|
||||
}
|
||||
|
||||
private fun subscribeUi(
|
||||
@ -77,17 +85,31 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
) {
|
||||
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 -> ""
|
||||
maintainScrollPosition {
|
||||
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.showPreview.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_widget_preview_label?.text =
|
||||
if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
}
|
||||
})
|
||||
|
||||
viewModel.showWallpaper.observe(viewLifecycleOwner, Observer {
|
||||
show_wallpaper_label.text = if (it && activity?.checkGrantedPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == true) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||
maintainScrollPosition {
|
||||
show_wallpaper_label?.text =
|
||||
if (it && activity?.checkGrantedPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == true) getString(
|
||||
R.string.settings_visible
|
||||
) else getString(R.string.settings_not_visible)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -114,10 +136,28 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
action_show_widget_preview.setOnClickListener {
|
||||
maintainScrollPosition {
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.action_show_widget_preview))
|
||||
.setSelectedValue(Preferences.showPreview)
|
||||
.addItem(
|
||||
getString(R.string.settings_visible),
|
||||
true
|
||||
)
|
||||
.addItem(
|
||||
getString(R.string.settings_not_visible),
|
||||
false
|
||||
)
|
||||
.addOnSelectItemListener { value ->
|
||||
Preferences.showPreview = value
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
action_show_wallpaper.setOnClickListener {
|
||||
maintainScrollPosition {
|
||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_title_show_wallpaper))
|
||||
.setSelectedValue(Preferences.showWallpaper)
|
||||
.setSelectedValue(Preferences.showWallpaper && activity?.checkGrantedPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == true)
|
||||
.addItem(
|
||||
getString(R.string.settings_visible),
|
||||
true
|
||||
@ -153,7 +193,7 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
}
|
||||
|
||||
action_refresh_widget.setOnClickListener {
|
||||
MainWidget.updateWidget(requireContext())
|
||||
WeatherHelper.updateWeather(requireContext())
|
||||
CalendarHelper.updateEventList(requireContext())
|
||||
}
|
||||
}
|
||||
@ -174,6 +214,7 @@ class AdvancedSettingsFragment : Fragment() {
|
||||
).withListener(object: MultiplePermissionsListener {
|
||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||
report?.let {
|
||||
Preferences.showWallpaper = false
|
||||
Preferences.showWallpaper = report.areAllPermissionsGranted()
|
||||
}
|
||||
}
|
@ -3,11 +3,12 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
@ -40,10 +41,10 @@ import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class WeatherSettingsFragment : Fragment() {
|
||||
class WeatherTabFragment : Fragment() {
|
||||
|
||||
companion object {
|
||||
fun newInstance() = WeatherSettingsFragment()
|
||||
fun newInstance() = WeatherTabFragment()
|
||||
}
|
||||
|
||||
private lateinit var viewModel: MainViewModel
|
||||
@ -79,13 +80,15 @@ class WeatherSettingsFragment : Fragment() {
|
||||
viewModel: MainViewModel
|
||||
) {
|
||||
viewModel.showWeatherWarning.observe(viewLifecycleOwner, Observer {
|
||||
weather_warning.isVisible = it
|
||||
weather_warning?.isVisible = it
|
||||
checkLocationPermission()
|
||||
})
|
||||
|
||||
viewModel.showWeather.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_weather_label.text =
|
||||
show_weather_label?.text =
|
||||
if (it) getString(R.string.show_weather_visible) else getString(R.string.show_weather_not_visible)
|
||||
checkWeatherProviderConfig()
|
||||
binding.isWeatherVisible = it
|
||||
}
|
||||
checkLocationPermission()
|
||||
@ -93,18 +96,14 @@ class WeatherSettingsFragment : Fragment() {
|
||||
|
||||
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 == ""
|
||||
checkWeatherProviderConfig()
|
||||
}
|
||||
checkLocationPermission()
|
||||
})
|
||||
|
||||
viewModel.customLocationAdd.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
label_custom_location.text =
|
||||
label_custom_location?.text =
|
||||
if (it == "") getString(R.string.custom_location_gps) else it
|
||||
}
|
||||
checkLocationPermission()
|
||||
@ -112,38 +111,54 @@ class WeatherSettingsFragment : Fragment() {
|
||||
|
||||
viewModel.weatherTempUnit.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
temp_unit.text =
|
||||
temp_unit?.text =
|
||||
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
|
||||
}
|
||||
checkLocationPermission()
|
||||
})
|
||||
|
||||
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
label_weather_refresh_period.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
|
||||
label_weather_refresh_period?.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
|
||||
}
|
||||
checkLocationPermission()
|
||||
})
|
||||
|
||||
viewModel.weatherAppName.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
weather_app_label.text =
|
||||
weather_app_label?.text =
|
||||
if (it != "") it else getString(R.string.default_weather_app)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun checkLocationPermission() {
|
||||
if (activity?.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) == true) {
|
||||
location_permission_alert_icon.isVisible = false
|
||||
// Background permission
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && activity?.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) == true && activity?.checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != true) {
|
||||
requirePermission()
|
||||
}
|
||||
|
||||
if (activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) == true) {
|
||||
location_permission_alert?.isVisible = false
|
||||
WeatherReceiver.setUpdates(requireContext())
|
||||
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
|
||||
location_permission_alert_icon.isVisible = true
|
||||
location_permission_alert_icon.setOnClickListener {
|
||||
location_permission_alert?.isVisible = true
|
||||
location_permission_alert?.setOnClickListener {
|
||||
requirePermission()
|
||||
}
|
||||
} else {
|
||||
location_permission_alert?.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkWeatherProviderConfig() {
|
||||
label_weather_provider_api_key?.text =
|
||||
if (Preferences.weatherProviderApi == "") getString(R.string.settings_weather_provider_api_key_subtitle_not_set) else getString(
|
||||
R.string.settings_weather_provider_api_key_subtitle_all_set
|
||||
)
|
||||
label_weather_provider_api_key?.setTextColor(ContextCompat.getColor(requireContext(), if (Preferences.weatherProviderApi == "" && Preferences.showWeather) R.color.errorColorText else R.color.colorSecondaryText))
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
action_hide_weather_warning.setOnClickListener {
|
||||
Preferences.showWeatherWarning = false
|
||||
@ -231,7 +246,7 @@ class WeatherSettingsFragment : Fragment() {
|
||||
private fun requirePermission() {
|
||||
Dexter.withContext(requireContext())
|
||||
.withPermissions(
|
||||
Manifest.permission.ACCESS_FINE_LOCATION
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
|
||||
).withListener(object: MultiplePermissionsListener {
|
||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||
report?.let {
|
@ -8,6 +8,9 @@ class MainViewModel : ViewModel() {
|
||||
|
||||
// General Settings
|
||||
val textGlobalColor = Preferences.asLiveData(Preferences::textGlobalColor)
|
||||
val textGlobalAlpha = Preferences.asLiveData(Preferences::textGlobalAlpha)
|
||||
val backgroundCardColor = Preferences.asLiveData(Preferences::backgroundCardColor)
|
||||
val backgroundCardAlpha = Preferences.asLiveData(Preferences::backgroundCardAlpha)
|
||||
val textMainSize = Preferences.asLiveData(Preferences::textMainSize)
|
||||
val textSecondSize = Preferences.asLiveData(Preferences::textSecondSize)
|
||||
val textShadow = Preferences.asLiveData(Preferences::textShadow)
|
||||
@ -21,18 +24,19 @@ class MainViewModel : ViewModel() {
|
||||
val showDiffTime = Preferences.asLiveData(Preferences::showDiffTime)
|
||||
val showDeclinedEvents = Preferences.asLiveData(Preferences::showDeclinedEvents)
|
||||
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
|
||||
|
||||
val openEventDetails = Preferences.asLiveData(Preferences::openEventDetails)
|
||||
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 clockTextColor = Preferences.asLiveData(Preferences::clockTextColor)
|
||||
val clockTextAlpha = Preferences.asLiveData(Preferences::clockTextAlpha)
|
||||
|
||||
val clockAppName = Preferences.asLiveData(Preferences::clockAppName)
|
||||
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
|
||||
val dateFormat = Preferences.asLiveData(Preferences::dateFormat)
|
||||
val clockBottomMargin = Preferences.asLiveData(Preferences::clockBottomMargin)
|
||||
|
||||
val showBigClockWarning = Preferences.asLiveData(Preferences::showBigClockWarning)
|
||||
|
||||
@ -51,4 +55,5 @@ class MainViewModel : ViewModel() {
|
||||
// Advanced Settings
|
||||
val darkThemePreference = Preferences.asLiveData(Preferences::darkThemePreference)
|
||||
val showWallpaper = Preferences.asLiveData(Preferences::showWallpaper)
|
||||
val showPreview = Preferences.asLiveData(Preferences::showPreview)
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ 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
|
||||
@ -26,15 +25,12 @@ import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.*
|
||||
import com.tommasoberlose.anotherwidget.receivers.NewCalendarEventReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver
|
||||
import com.tommasoberlose.anotherwidget.receivers.*
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.convertSpToPixels
|
||||
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||
import kotlinx.android.synthetic.main.the_widget.view.*
|
||||
import java.lang.Exception
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -65,155 +61,321 @@ class MainWidget : AppWidgetProvider() {
|
||||
}
|
||||
|
||||
override fun onDisabled(context: Context) {
|
||||
UpdatesReceiver.removeUpdates(context)
|
||||
WeatherReceiver.removeUpdates(context)
|
||||
if (getWidgetCount(context) == 0) {
|
||||
UpdatesReceiver.removeUpdates(context)
|
||||
WeatherReceiver.removeUpdates(context)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun updateWidget(context: Context) {
|
||||
context.sendBroadcast(IntentHelper.getWidgetUpdateIntent(context))
|
||||
}
|
||||
|
||||
fun getWidgetCount(context: Context): Int {
|
||||
val widgetManager = AppWidgetManager.getInstance(context)
|
||||
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
||||
val widgetIds = widgetManager.getAppWidgetIds(widgetComponent)
|
||||
val update = Intent(context, MainWidget::class.java)
|
||||
update.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds)
|
||||
update.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||
context.sendBroadcast(update)
|
||||
return widgetManager.getAppWidgetIds(widgetComponent).size
|
||||
}
|
||||
|
||||
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 += Preferences.clockTextSize.convertSpToPixels(context).toInt() + 16.toPixel(context)
|
||||
}
|
||||
if (Preferences.textMainSize > 30 && Preferences.textSecondSize > 22) {
|
||||
height += 24.toPixel(context)
|
||||
}
|
||||
|
||||
generateWidgetView(context, appWidgetId, appWidgetManager, width - 16.toPixel(context))
|
||||
val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId)
|
||||
generateWidgetView(context, appWidgetId, appWidgetManager, dimensions.first - 8.toPixel(context) /*width - 16.toPixel(context)*/)
|
||||
}
|
||||
|
||||
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int) {
|
||||
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
|
||||
|
||||
val generatedView = generateWidgetView(context)
|
||||
views.setImageViewBitmap(R.id.bitmap_container, BitmapHelper.getBitmapFromView(generatedView, width = w - 32.toPixel(context)))
|
||||
try {
|
||||
// Background
|
||||
views.setInt(
|
||||
R.id.widget_shape_background,
|
||||
"setColorFilter",
|
||||
ColorHelper.getBackgroundColorRgb()
|
||||
)
|
||||
views.setInt(
|
||||
R.id.widget_shape_background,
|
||||
"setImageAlpha",
|
||||
ColorHelper.getBackgroundAlpha()
|
||||
)
|
||||
val refreshIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
appWidgetId,
|
||||
IntentHelper.getWidgetUpdateIntent(context),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.widget_shape_background, refreshIntent)
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
CrashlyticsReceiver.sendCrash(context, ex)
|
||||
}
|
||||
|
||||
// Clock
|
||||
views = updateClockView(context, views, appWidgetId)
|
||||
|
||||
// Setup listener
|
||||
views = updateCalendarView(context, generatedView, views, appWidgetId)
|
||||
views = updateWeatherView(context, generatedView, views, appWidgetId)
|
||||
try {
|
||||
val generatedView = generateWidgetView(context)
|
||||
views.setImageViewBitmap(
|
||||
R.id.bitmap_container,
|
||||
BitmapHelper.getBitmapFromView(generatedView, width = w)
|
||||
)
|
||||
views = updateCalendarView(context, generatedView, views, appWidgetId)
|
||||
views = updateWeatherView(context, generatedView, views, appWidgetId)
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
CrashlyticsReceiver.sendCrash(context, ex)
|
||||
}
|
||||
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
}
|
||||
|
||||
private fun updateCalendarView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
|
||||
val eventRepository = EventRepository(context)
|
||||
try {
|
||||
val eventRepository = EventRepository(context)
|
||||
|
||||
views.setImageViewBitmap(R.id.empty_date_rect, BitmapHelper.getBitmapFromView(v.empty_date, draw = false))
|
||||
views.setImageViewBitmap(
|
||||
R.id.empty_date_rect,
|
||||
BitmapHelper.getBitmapFromView(v.empty_date, draw = false)
|
||||
)
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.second_row_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.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, IntentHelper.getCalendarIntent(context), 0)
|
||||
views.setOnClickPendingIntent(R.id.empty_date_rect, calPIntent)
|
||||
val calPIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
widgetID,
|
||||
IntentHelper.getCalendarIntent(context),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.empty_date_rect, calPIntent)
|
||||
|
||||
val nextEvent = eventRepository.getNextEvent()
|
||||
val nextAlarm = AlarmHelper.getNextAlarm(context)
|
||||
val nextEvent = eventRepository.getNextEvent()
|
||||
val nextAlarm = AlarmHelper.getNextAlarm(context)
|
||||
|
||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
||||
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
|
||||
views.setImageViewBitmap(R.id.action_next_rect, BitmapHelper.getBitmapFromView(v.action_next, draw = false))
|
||||
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))
|
||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
||||
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
|
||||
views.setImageViewBitmap(
|
||||
R.id.action_next_rect,
|
||||
BitmapHelper.getBitmapFromView(v.action_next, draw = false)
|
||||
)
|
||||
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
|
||||
)
|
||||
)
|
||||
|
||||
views.setImageViewBitmap(R.id.action_previous_rect, BitmapHelper.getBitmapFromView(v.action_previous, draw = false))
|
||||
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)
|
||||
views.setImageViewBitmap(
|
||||
R.id.action_previous_rect,
|
||||
BitmapHelper.getBitmapFromView(v.action_previous, draw = false)
|
||||
)
|
||||
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,
|
||||
IntentHelper.getEventIntent(context, nextEvent),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.next_event_rect, pIntent)
|
||||
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, pIntent)
|
||||
|
||||
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
|
||||
views.setImageViewBitmap(
|
||||
R.id.next_event_difference_time_rect,
|
||||
BitmapHelper.getBitmapFromView(
|
||||
v.next_event_difference_time,
|
||||
draw = false
|
||||
)
|
||||
)
|
||||
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,
|
||||
IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, mapIntent)
|
||||
} else {
|
||||
val pIntentDetail = PendingIntent.getActivity(
|
||||
context,
|
||||
widgetID,
|
||||
IntentHelper.getEventIntent(
|
||||
context,
|
||||
nextEvent,
|
||||
forceEventDetails = true
|
||||
),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, pIntentDetail)
|
||||
}
|
||||
|
||||
views.setImageViewBitmap(
|
||||
R.id.next_event_rect,
|
||||
BitmapHelper.getBitmapFromView(v.next_event, draw = false)
|
||||
)
|
||||
|
||||
views.setImageViewBitmap(
|
||||
R.id.second_row_rect,
|
||||
BitmapHelper.getBitmapFromView(v.second_row, draw = false)
|
||||
)
|
||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||
} else if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||
val alarmIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
widgetID,
|
||||
IntentHelper.getClockIntent(context),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, alarmIntent)
|
||||
|
||||
views.setImageViewBitmap(
|
||||
R.id.next_event_rect,
|
||||
BitmapHelper.getBitmapFromView(v.next_event, draw = false)
|
||||
)
|
||||
|
||||
views.setImageViewBitmap(
|
||||
R.id.second_row_rect,
|
||||
BitmapHelper.getBitmapFromView(v.second_row, draw = false)
|
||||
)
|
||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||
views.setOnClickPendingIntent(R.id.next_event_rect, calPIntent)
|
||||
}
|
||||
|
||||
val pIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getEventIntent(context, nextEvent), 0)
|
||||
views.setOnClickPendingIntent(R.id.next_event_rect, pIntent)
|
||||
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, pIntent)
|
||||
|
||||
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
|
||||
views.setImageViewBitmap(R.id.next_event_difference_time_rect, BitmapHelper.getBitmapFromView(v.next_event_difference_time, draw = false))
|
||||
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, IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address), 0)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, mapIntent)
|
||||
} else {
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, pIntent)
|
||||
}
|
||||
|
||||
views.setImageViewBitmap(R.id.next_event_rect, BitmapHelper.getBitmapFromView(v.next_event, draw = false))
|
||||
|
||||
views.setImageViewBitmap(R.id.second_row_rect, BitmapHelper.getBitmapFromView(v.second_row, draw = false))
|
||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||
} else if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||
val clockIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getClockIntent(context), 0)
|
||||
views.setOnClickPendingIntent(R.id.second_row_rect, clockIntent)
|
||||
|
||||
views.setImageViewBitmap(R.id.next_event_rect, BitmapHelper.getBitmapFromView(v.next_event, draw = false))
|
||||
|
||||
views.setImageViewBitmap(R.id.second_row_rect, BitmapHelper.getBitmapFromView(v.second_row, draw = false))
|
||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||
|
||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
CrashlyticsReceiver.sendCrash(context, ex)
|
||||
}
|
||||
|
||||
return views
|
||||
}
|
||||
|
||||
private fun updateWeatherView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
|
||||
try {
|
||||
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
||||
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.calendar_weather_rect, View.VISIBLE)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
|
||||
views.setOnClickPendingIntent(R.id.calendar_weather_rect, weatherPIntent)
|
||||
views.setImageViewBitmap(
|
||||
R.id.weather_rect,
|
||||
BitmapHelper.getBitmapFromView(v.weather, draw = false)
|
||||
)
|
||||
|
||||
views.setImageViewBitmap(R.id.weather_rect, BitmapHelper.getBitmapFromView(v.weather, draw = false))
|
||||
|
||||
views.setImageViewBitmap(R.id.calendar_weather_rect, BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false))
|
||||
} else {
|
||||
views.setViewVisibility(R.id.weather_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
|
||||
views.setImageViewBitmap(
|
||||
R.id.calendar_weather_rect,
|
||||
BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false)
|
||||
)
|
||||
} else {
|
||||
views.setViewVisibility(R.id.weather_rect, View.GONE)
|
||||
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
CrashlyticsReceiver.sendCrash(context, ex)
|
||||
}
|
||||
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, ColorHelper.getFontColor())
|
||||
views.setTextViewTextSize(R.id.time, TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(context))
|
||||
val clockPIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getClockIntent(context), 0)
|
||||
views.setOnClickPendingIntent(R.id.time, clockPIntent)
|
||||
views.setViewVisibility(R.id.time, View.VISIBLE)
|
||||
try {
|
||||
if (!Preferences.showClock) {
|
||||
views.setViewVisibility(R.id.time, View.GONE)
|
||||
views.setViewVisibility(R.id.time_am_pm, View.GONE)
|
||||
views.setViewVisibility(R.id.clock_bottom_margin_none, View.GONE)
|
||||
views.setViewVisibility(R.id.clock_bottom_margin_small, View.GONE)
|
||||
views.setViewVisibility(R.id.clock_bottom_margin_medium, View.GONE)
|
||||
views.setViewVisibility(R.id.clock_bottom_margin_large, View.GONE)
|
||||
} else {
|
||||
views.setTextColor(R.id.time, ColorHelper.getClockFontColor())
|
||||
views.setTextColor(R.id.time_am_pm, ColorHelper.getClockFontColor())
|
||||
views.setTextViewTextSize(
|
||||
R.id.time,
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(context)
|
||||
)
|
||||
views.setTextViewTextSize(
|
||||
R.id.time_am_pm,
|
||||
TypedValue.COMPLEX_UNIT_SP,
|
||||
Preferences.clockTextSize.toPixel(context) / 5 * 2
|
||||
)
|
||||
val clockPIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
widgetID,
|
||||
IntentHelper.getClockIntent(context),
|
||||
0
|
||||
)
|
||||
views.setOnClickPendingIntent(R.id.time, clockPIntent)
|
||||
views.setOnClickPendingIntent(R.id.time_am_pm, clockPIntent)
|
||||
views.setViewVisibility(R.id.time, View.VISIBLE)
|
||||
views.setViewVisibility(R.id.time_am_pm, View.VISIBLE)
|
||||
|
||||
views.setViewVisibility(
|
||||
R.id.clock_bottom_margin_none,
|
||||
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value) View.VISIBLE else View.GONE
|
||||
)
|
||||
views.setViewVisibility(
|
||||
R.id.clock_bottom_margin_small,
|
||||
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||
)
|
||||
views.setViewVisibility(
|
||||
R.id.clock_bottom_margin_medium,
|
||||
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||
)
|
||||
views.setViewVisibility(
|
||||
R.id.clock_bottom_margin_large,
|
||||
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||
)
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
CrashlyticsReceiver.sendCrash(context, ex)
|
||||
}
|
||||
|
||||
return views
|
||||
|
@ -32,8 +32,8 @@ import java.util.*
|
||||
|
||||
fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
|
||||
|
||||
fun Context.toast(message: String) {
|
||||
val toast = Toast.makeText(this, message, Toast.LENGTH_SHORT)
|
||||
fun Context.toast(message: String, long: Boolean = false) {
|
||||
val toast = Toast.makeText(this, message, if (long) Toast.LENGTH_LONG else Toast.LENGTH_SHORT)
|
||||
// toast.setGravity(Gravity.CENTER, 0, 0)
|
||||
toast.show()
|
||||
}
|
||||
|
BIN
app/src/main/res/drawable-hdpi/round_arrow_back.png
Normal file
After Width: | Height: | Size: 183 B |
BIN
app/src/main/res/drawable-hdpi/round_aspect_ratio.png
Normal file
After Width: | Height: | Size: 295 B |
BIN
app/src/main/res/drawable-hdpi/round_aspect_ratio_black_18.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
app/src/main/res/drawable-hdpi/round_aspect_ratio_black_36.png
Normal file
After Width: | Height: | Size: 399 B |
BIN
app/src/main/res/drawable-hdpi/round_aspect_ratio_black_48.png
Normal file
After Width: | Height: | Size: 428 B |
BIN
app/src/main/res/drawable-hdpi/round_compare.png
Normal file
After Width: | Height: | Size: 314 B |
BIN
app/src/main/res/drawable-hdpi/round_compare_black_18.png
Normal file
After Width: | Height: | Size: 285 B |
BIN
app/src/main/res/drawable-hdpi/round_compare_black_36.png
Normal file
After Width: | Height: | Size: 440 B |
BIN
app/src/main/res/drawable-hdpi/round_compare_black_48.png
Normal file
After Width: | Height: | Size: 509 B |
BIN
app/src/main/res/drawable-hdpi/round_crop_3_2.png
Normal file
After Width: | Height: | Size: 327 B |
BIN
app/src/main/res/drawable-hdpi/round_crop_3_2_black_18.png
Normal file
After Width: | Height: | Size: 192 B |
BIN
app/src/main/res/drawable-hdpi/round_crop_3_2_black_24.png
Normal file
After Width: | Height: | Size: 214 B |
BIN
app/src/main/res/drawable-hdpi/round_crop_3_2_black_36.png
Normal file
After Width: | Height: | Size: 279 B |
BIN
app/src/main/res/drawable-hdpi/round_crop_original.png
Normal file
After Width: | Height: | Size: 479 B |
BIN
app/src/main/res/drawable-hdpi/round_crop_original_black_18.png
Normal file
After Width: | Height: | Size: 239 B |
BIN
app/src/main/res/drawable-hdpi/round_crop_original_black_24.png
Normal file
After Width: | Height: | Size: 283 B |
BIN
app/src/main/res/drawable-hdpi/round_crop_original_black_36.png
Normal file
After Width: | Height: | Size: 403 B |
After Width: | Height: | Size: 237 B |
After Width: | Height: | Size: 240 B |
After Width: | Height: | Size: 338 B |
After Width: | Height: | Size: 369 B |
BIN
app/src/main/res/drawable-hdpi/round_gradient.png
Normal file
After Width: | Height: | Size: 254 B |
BIN
app/src/main/res/drawable-hdpi/round_gradient_black_24.png
Normal file
After Width: | Height: | Size: 233 B |
BIN
app/src/main/res/drawable-hdpi/round_gradient_black_36.png
Normal file
After Width: | Height: | Size: 306 B |
BIN
app/src/main/res/drawable-hdpi/round_gradient_black_48.png
Normal file
After Width: | Height: | Size: 319 B |
BIN
app/src/main/res/drawable-hdpi/round_short_text.png
Normal file
After Width: | Height: | Size: 198 B |
BIN
app/src/main/res/drawable-hdpi/round_short_text_black_18.png
Normal file
After Width: | Height: | Size: 144 B |
BIN
app/src/main/res/drawable-hdpi/round_short_text_black_24.png
Normal file
After Width: | Height: | Size: 151 B |
BIN
app/src/main/res/drawable-hdpi/round_short_text_black_36.png
Normal file
After Width: | Height: | Size: 190 B |
BIN
app/src/main/res/drawable-hdpi/round_update_black_18.png
Normal file
After Width: | Height: | Size: 389 B |
BIN
app/src/main/res/drawable-hdpi/round_update_black_24.png
Normal file
After Width: | Height: | Size: 492 B |
BIN
app/src/main/res/drawable-hdpi/round_update_black_36.png
Normal file
After Width: | Height: | Size: 699 B |
BIN
app/src/main/res/drawable-hdpi/round_update_black_48.png
Normal file
After Width: | Height: | Size: 876 B |
BIN
app/src/main/res/drawable-mdpi/round_arrow_back.png
Normal file
After Width: | Height: | Size: 138 B |
BIN
app/src/main/res/drawable-mdpi/round_aspect_ratio.png
Normal file
After Width: | Height: | Size: 185 B |
BIN
app/src/main/res/drawable-mdpi/round_aspect_ratio_black_18.png
Normal file
After Width: | Height: | Size: 211 B |
BIN
app/src/main/res/drawable-mdpi/round_aspect_ratio_black_36.png
Normal file
After Width: | Height: | Size: 295 B |
BIN
app/src/main/res/drawable-mdpi/round_aspect_ratio_black_48.png
Normal file
After Width: | Height: | Size: 304 B |
BIN
app/src/main/res/drawable-mdpi/round_compare.png
Normal file
After Width: | Height: | Size: 218 B |
BIN
app/src/main/res/drawable-mdpi/round_compare_black_18.png
Normal file
After Width: | Height: | Size: 218 B |
BIN
app/src/main/res/drawable-mdpi/round_compare_black_36.png
Normal file
After Width: | Height: | Size: 314 B |
BIN
app/src/main/res/drawable-mdpi/round_compare_black_48.png
Normal file
After Width: | Height: | Size: 361 B |
BIN
app/src/main/res/drawable-mdpi/round_crop_3_2.png
Normal file
After Width: | Height: | Size: 228 B |
BIN
app/src/main/res/drawable-mdpi/round_crop_3_2_black_18.png
Normal file
After Width: | Height: | Size: 151 B |
BIN
app/src/main/res/drawable-mdpi/round_crop_3_2_black_24.png
Normal file
After Width: | Height: | Size: 139 B |
BIN
app/src/main/res/drawable-mdpi/round_crop_3_2_black_36.png
Normal file
After Width: | Height: | Size: 214 B |
BIN
app/src/main/res/drawable-mdpi/round_crop_original.png
Normal file
After Width: | Height: | Size: 324 B |
BIN
app/src/main/res/drawable-mdpi/round_crop_original_black_18.png
Normal file
After Width: | Height: | Size: 196 B |
BIN
app/src/main/res/drawable-mdpi/round_crop_original_black_24.png
Normal file
After Width: | Height: | Size: 190 B |
BIN
app/src/main/res/drawable-mdpi/round_crop_original_black_36.png
Normal file
After Width: | Height: | Size: 283 B |
After Width: | Height: | Size: 177 B |
After Width: | Height: | Size: 163 B |
After Width: | Height: | Size: 240 B |
After Width: | Height: | Size: 254 B |