Compare commits

..

1 Commits

Author SHA1 Message Date
Quentin Hibon
e65c7de086 Don't accept null urls 2024-04-04 23:55:28 +02:00
19 changed files with 31 additions and 8325 deletions

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"

View File

@@ -1,6 +1,6 @@
plugins { plugins {
val kotlinVersion = "1.9.22" val kotlinVersion = "1.9.22"
id("com.android.application") version "8.4.0" apply (false) id("com.android.application") version "8.1.4" apply (false)
id("org.jetbrains.kotlin.android") version kotlinVersion apply (false) id("org.jetbrains.kotlin.android") version kotlinVersion apply (false)
id("org.jetbrains.kotlin.kapt") version kotlinVersion apply (false) id("org.jetbrains.kotlin.kapt") version kotlinVersion apply (false)
id("org.jetbrains.kotlin.multiplatform") version kotlinVersion apply (false) id("org.jetbrains.kotlin.multiplatform") version kotlinVersion apply (false)

View File

@@ -64,7 +64,6 @@ fail() {
core_build() { core_build() {
log_info "Building uhabits-core..." log_info "Building uhabits-core..."
$GRADLE ktlintCheck || fail $GRADLE ktlintCheck || fail
$GRADLE lintDebug || fail
$GRADLE :uhabits-core:build || fail $GRADLE :uhabits-core:build || fail
} }

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@@ -19,7 +19,7 @@
plugins { plugins {
id("com.github.triplet.play") version "3.8.6" id("com.github.triplet.play") version "3.8.6"
id("com.android.application") version "8.4.0" id("com.android.application") version "8.1.4"
id("org.jetbrains.kotlin.android") id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.kapt") id("org.jetbrains.kotlin.kapt")
id("org.jlleitschuh.gradle.ktlint") id("org.jlleitschuh.gradle.ktlint")
@@ -44,14 +44,12 @@ android {
namespace = "org.isoron.uhabits" namespace = "org.isoron.uhabits"
compileSdk = 34 compileSdk = 34
// compileSdkPreview = "VanillaIceCream"
defaultConfig { defaultConfig {
versionCode = 20200 versionCode = 20200
versionName = "2.2.0" versionName = "2.2.0"
minSdk = 28 minSdk = 28
targetSdk = 34 targetSdk = 34
// targetSdkPreview = "VanillaIceCream"
applicationId = "org.isoron.uhabits" applicationId = "org.isoron.uhabits"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -93,10 +91,6 @@ android {
buildFeatures { buildFeatures {
viewBinding = true viewBinding = true
} }
lint {
abortOnError = false
}
} }
dependencies { dependencies {

File diff suppressed because it is too large Load Diff

View File

@@ -132,7 +132,7 @@ object CommonSteps : BaseUserInterfaceTest() {
} }
@Throws(Exception::class) @Throws(Exception::class)
fun verifyOpensWebsite(url: String?) { fun verifyOpensWebsite(url: String) {
var browserPkg = "org.chromium.webview_shell" var browserPkg = "org.chromium.webview_shell"
if (SDK_INT <= Build.VERSION_CODES.M) { if (SDK_INT <= Build.VERSION_CODES.M) {
browserPkg = "com.android.browser" browserPkg = "com.android.browser"

View File

@@ -26,7 +26,6 @@ import org.isoron.uhabits.BuildConfig
import org.isoron.uhabits.R import org.isoron.uhabits.R
import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.databinding.AboutBinding import org.isoron.uhabits.databinding.AboutBinding
import org.isoron.uhabits.utils.applyRootViewInsets
import org.isoron.uhabits.utils.currentTheme import org.isoron.uhabits.utils.currentTheme
import org.isoron.uhabits.utils.setupToolbar import org.isoron.uhabits.utils.setupToolbar
@@ -55,6 +54,5 @@ class AboutView(
binding.tvTranslate.setOnClickListener { screen.showTranslationWebsite() } binding.tvTranslate.setOnClickListener { screen.showTranslationWebsite() }
binding.tvVersion.setOnClickListener { screen.onPressDeveloperCountdown() } binding.tvVersion.setOnClickListener { screen.onPressDeveloperCountdown() }
binding.tvVersion.text = String.format(version, BuildConfig.VERSION_NAME) binding.tvVersion.text = String.format(version, BuildConfig.VERSION_NAME)
applyRootViewInsets()
} }
} }

View File

@@ -22,6 +22,7 @@ package org.isoron.uhabits.activities.habits.edit
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.text.Html import android.text.Html
import android.text.Spanned import android.text.Spanned
@@ -52,8 +53,7 @@ import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.models.Reminder import org.isoron.uhabits.core.models.Reminder
import org.isoron.uhabits.core.models.WeekdayList import org.isoron.uhabits.core.models.WeekdayList
import org.isoron.uhabits.databinding.ActivityEditHabitBinding import org.isoron.uhabits.databinding.ActivityEditHabitBinding
import org.isoron.uhabits.utils.applyRootViewInsets import org.isoron.uhabits.utils.ColorUtils
import org.isoron.uhabits.utils.applyToolbarInsets
import org.isoron.uhabits.utils.dismissCurrentAndShow import org.isoron.uhabits.utils.dismissCurrentAndShow
import org.isoron.uhabits.utils.formatTime import org.isoron.uhabits.utils.formatTime
import org.isoron.uhabits.utils.toFormattedString import org.isoron.uhabits.utils.toFormattedString
@@ -94,8 +94,6 @@ class EditHabitActivity : AppCompatActivity() {
themeSwitcher.apply() themeSwitcher.apply()
binding = ActivityEditHabitBinding.inflate(layoutInflater) binding = ActivityEditHabitBinding.inflate(layoutInflater)
binding.root.applyRootViewInsets()
binding.toolbar.applyToolbarInsets()
setContentView(binding.root) setContentView(binding.root)
if (intent.hasExtra("habitId")) { if (intent.hasExtra("habitId")) {
@@ -354,7 +352,8 @@ class EditHabitActivity : AppCompatActivity() {
androidColor = themeSwitcher.currentTheme.color(color).toInt() androidColor = themeSwitcher.currentTheme.color(color).toInt()
binding.colorButton.backgroundTintList = ColorStateList.valueOf(androidColor) binding.colorButton.backgroundTintList = ColorStateList.valueOf(androidColor)
if (!themeSwitcher.isNightMode) { if (!themeSwitcher.isNightMode) {
window.statusBarColor = androidColor val darkerAndroidColor = ColorUtils.mixColors(Color.BLACK, androidColor, 0.15f)
window.statusBarColor = darkerAndroidColor
binding.toolbar.setBackgroundColor(androidColor) binding.toolbar.setBackgroundColor(androidColor)
} }
} }

View File

@@ -45,7 +45,6 @@ import org.isoron.uhabits.inject.ActivityContextModule
import org.isoron.uhabits.inject.DaggerHabitsActivityComponent import org.isoron.uhabits.inject.DaggerHabitsActivityComponent
import org.isoron.uhabits.inject.HabitsActivityComponent import org.isoron.uhabits.inject.HabitsActivityComponent
import org.isoron.uhabits.inject.HabitsApplicationComponent import org.isoron.uhabits.inject.HabitsApplicationComponent
import org.isoron.uhabits.utils.applyRootViewInsets
import org.isoron.uhabits.utils.dismissCurrentDialog import org.isoron.uhabits.utils.dismissCurrentDialog
import org.isoron.uhabits.utils.restartWithFade import org.isoron.uhabits.utils.restartWithFade
@@ -101,7 +100,6 @@ class ListHabitsActivity : AppCompatActivity(), Preferences.Listener {
menu = component.listHabitsMenu menu = component.listHabitsMenu
Thread.setDefaultUncaughtExceptionHandler(BaseExceptionHandler(this)) Thread.setDefaultUncaughtExceptionHandler(BaseExceptionHandler(this))
component.listHabitsBehavior.onStartup() component.listHabitsBehavior.onStartup()
rootView.applyRootViewInsets()
setContentView(rootView) setContentView(rootView)
} }

View File

@@ -49,7 +49,6 @@ import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitMenuPresenter
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitPresenter import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitPresenter
import org.isoron.uhabits.core.ui.views.OnDateClickedListener import org.isoron.uhabits.core.ui.views.OnDateClickedListener
import org.isoron.uhabits.intents.IntentFactory import org.isoron.uhabits.intents.IntentFactory
import org.isoron.uhabits.utils.applyRootViewInsets
import org.isoron.uhabits.utils.currentTheme import org.isoron.uhabits.utils.currentTheme
import org.isoron.uhabits.utils.dismissCurrentAndShow import org.isoron.uhabits.utils.dismissCurrentAndShow
import org.isoron.uhabits.utils.dismissCurrentDialog import org.isoron.uhabits.utils.dismissCurrentDialog
@@ -110,7 +109,6 @@ class ShowHabitActivity : AppCompatActivity(), CommandRunner.Listener {
) )
view.setListener(presenter) view.setListener(presenter)
view.applyRootViewInsets()
setContentView(view) setContentView(view)
} }

View File

@@ -25,14 +25,12 @@ import android.widget.FrameLayout
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitPresenter import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitPresenter
import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitState import org.isoron.uhabits.core.ui.screens.habits.show.ShowHabitState
import org.isoron.uhabits.databinding.ShowHabitBinding import org.isoron.uhabits.databinding.ShowHabitBinding
import org.isoron.uhabits.utils.applyToolbarInsets
import org.isoron.uhabits.utils.setupToolbar import org.isoron.uhabits.utils.setupToolbar
class ShowHabitView(context: Context) : FrameLayout(context) { class ShowHabitView(context: Context) : FrameLayout(context) {
private val binding = ShowHabitBinding.inflate(LayoutInflater.from(context)) private val binding = ShowHabitBinding.inflate(LayoutInflater.from(context))
init { init {
binding.toolbar.applyToolbarInsets()
addView(binding.root) addView(binding.root)
} }

View File

@@ -26,7 +26,6 @@ import org.isoron.uhabits.R
import org.isoron.uhabits.activities.AndroidThemeSwitcher import org.isoron.uhabits.activities.AndroidThemeSwitcher
import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.databinding.SettingsActivityBinding import org.isoron.uhabits.databinding.SettingsActivityBinding
import org.isoron.uhabits.utils.applyRootViewInsets
import org.isoron.uhabits.utils.setupToolbar import org.isoron.uhabits.utils.setupToolbar
class SettingsActivity : AppCompatActivity() { class SettingsActivity : AppCompatActivity() {
@@ -43,7 +42,6 @@ class SettingsActivity : AppCompatActivity() {
color = PaletteColor(11), color = PaletteColor(11),
theme = themeSwitcher.currentTheme theme = themeSwitcher.currentTheme
) )
binding.root.applyRootViewInsets()
setContentView(binding.root) setContentView(binding.root)
} }
} }

View File

@@ -24,7 +24,6 @@ import androidx.appcompat.app.AppCompatActivity
import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.HabitsApplication
import org.isoron.uhabits.activities.AndroidThemeSwitcher import org.isoron.uhabits.activities.AndroidThemeSwitcher
import org.isoron.uhabits.core.models.HabitMatcher import org.isoron.uhabits.core.models.HabitMatcher
import org.isoron.uhabits.utils.applyRootViewInsets
class EditSettingActivity : AppCompatActivity() { class EditSettingActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@@ -46,7 +45,6 @@ class EditSettingActivity : AppCompatActivity() {
onSave = controller::onSave, onSave = controller::onSave,
args = args args = args
) )
view.applyRootViewInsets()
setContentView(view) setContentView(view)
} }
} }

View File

@@ -46,8 +46,6 @@ import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import org.isoron.platform.gui.toInt import org.isoron.platform.gui.toInt
import org.isoron.uhabits.HabitsApplication import org.isoron.uhabits.HabitsApplication
@@ -182,10 +180,10 @@ fun View.setupToolbar(
} else { } else {
theme.color(color).toInt() theme.color(color).toInt()
} }
val darkerColor = ColorUtils.mixColors(toolbarColor, Color.BLACK, 0.75f)
toolbar.background = ColorDrawable(toolbarColor) toolbar.background = ColorDrawable(toolbarColor)
toolbar.applyToolbarInsets()
val activity = context as AppCompatActivity val activity = context as AppCompatActivity
activity.window.statusBarColor = toolbarColor activity.window.statusBarColor = darkerColor
activity.setSupportActionBar(toolbar) activity.setSupportActionBar(toolbar)
activity.supportActionBar?.setDisplayHomeAsUpEnabled(displayHomeAsUpEnabled) activity.supportActionBar?.setDisplayHomeAsUpEnabled(displayHomeAsUpEnabled)
} }
@@ -247,25 +245,3 @@ fun View.getCenter(): PointF {
viewLocation[1] -= this.height / 2 viewLocation[1] -= this.height / 2
return PointF(viewLocation[0].toFloat(), viewLocation[1].toFloat()) return PointF(viewLocation[0].toFloat(), viewLocation[1].toFloat())
} }
fun View.applyRootViewInsets() {
ViewCompat.setOnApplyWindowInsetsListener(this) { view, insets ->
val systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val displayCutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout())
val left = maxOf(systemBarsInsets.left, displayCutoutInsets.left)
val right = maxOf(systemBarsInsets.right, displayCutoutInsets.right)
view.setPadding(left, 0, right, 0)
view.background = ColorDrawable(Color.BLACK)
insets
}
}
fun View.applyToolbarInsets() {
ViewCompat.setOnApplyWindowInsetsListener(this) { view, insets ->
val systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val displayCutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout())
val top = maxOf(systemBarsInsets.top, displayCutoutInsets.top)
view.setPadding(0, top, 0, 0)
insets
}
}

View File

@@ -18,8 +18,7 @@
~ with this program. If not, see <http://www.gnu.org/licenses/>. ~ with this program. If not, see <http://www.gnu.org/licenses/>.
--> -->
<LinearLayout <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -62,10 +61,8 @@
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="wrap_content"
android:layout_weight="1" app:layout_behavior="@string/appbar_scrolling_view_behavior">
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:background="?attr/contrast0">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -268,4 +265,4 @@
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</LinearLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -58,10 +58,7 @@
<LinearLayout <LinearLayout
android:id="@+id/formPanel" android:id="@+id/formPanel"
style="@style/dialogFormPanel" style="@style/dialogFormPanel">
android:layout_height="0dp"
android:layout_weight="1"
android:background="?attr/contrast0">
<FrameLayout style="@style/FormOuterBox"> <FrameLayout style="@style/FormOuterBox">
<LinearLayout style="@style/FormInnerBox"> <LinearLayout style="@style/FormInnerBox">

View File

@@ -226,7 +226,6 @@
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
<item name="android:paddingTop">6dp</item> <item name="android:paddingTop">6dp</item>
<item name="android:paddingBottom">6dp</item> <item name="android:paddingBottom">6dp</item>
<item name="android:textAlignment">viewStart</item>
</style> </style>
<style name="About.Item.Language"> <style name="About.Item.Language">
@@ -234,7 +233,6 @@
<item name="android:textSize">@dimen/smallTextSize</item> <item name="android:textSize">@dimen/smallTextSize</item>
<item name="android:gravity">center</item> <item name="android:gravity">center</item>
<item name="android:background">?attr/contrast20</item> <item name="android:background">?attr/contrast20</item>
<item name="android:textAlignment">viewStart</item>
</style> </style>
<style name="About.Item.Clickable"> <style name="About.Item.Clickable">
@@ -245,7 +243,7 @@
<style name="Toolbar"> <style name="Toolbar">
<item name="android:layout_width">match_parent</item> <item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">?actionBarSize</item>
<item name="android:background">?colorPrimary</item> <item name="android:background">?colorPrimary</item>
<item name="android:theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item> <item name="android:theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
</style> </style>

View File

@@ -120,15 +120,10 @@ class DateUtilsTest : BaseUnitTest() {
@Test @Test
fun getWeekdaysInMonth() { fun getWeekdaysInMonth() {
fun getCalendarUTC(year: Int, month: Int, dayOfMonth: Int) = val february = GregorianCalendar(2018, Calendar.FEBRUARY, 1)
GregorianCalendar(year, month, dayOfMonth).apply { val leapFebruary = GregorianCalendar(2020, Calendar.FEBRUARY, 1)
timeZone = TimeZone.getTimeZone("UTC") val month = GregorianCalendar(2020, Calendar.APRIL, 1)
} val longMonth = GregorianCalendar(2020, Calendar.AUGUST, 1)
val february = getCalendarUTC(2018, Calendar.FEBRUARY, 1)
val leapFebruary = getCalendarUTC(2020, Calendar.FEBRUARY, 1)
val month = getCalendarUTC(2020, Calendar.APRIL, 1)
val longMonth = getCalendarUTC(2020, Calendar.AUGUST, 1)
assertThat( assertThat(
arrayOf(4, 4, 4, 4, 4, 4, 4), arrayOf(4, 4, 4, 4, 4, 4, 4),