Compare commits
1 Commits
4e498de051
...
renovate/g
| Author | SHA1 | Date | |
|---|---|---|---|
| 47e9acc43a |
@@ -90,8 +90,6 @@ android {
|
|||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
// BuildConfig.DEBUG gates the in-app debug ribbon (see DebugRibbon).
|
|
||||||
buildConfig = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't embed AGP's dependency-metadata block in the APK signing block. It's
|
// Don't embed AGP's dependency-metadata block in the APK signing block. It's
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Debug-only launcher-icon background. Production is slate (#5C6B7A); the
|
|
||||||
debug build paints the adaptive-icon background burnt orange instead, so the
|
|
||||||
debug icon reads at a glance as "not the real app" on the home screen. The
|
|
||||||
off-white foreground mark contrasts on both. See drawable/ic_launcher_background.
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<color name="ic_launcher_background">#FFB23B00</color>
|
|
||||||
</resources>
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Debug-build resource overrides. Merged on top of src/main for the `debug`
|
|
||||||
build type only (release/releaseTest keep the production values), so the
|
|
||||||
debug app is unmistakable on the launcher: its own label, alongside the
|
|
||||||
real app thanks to the `.debug` applicationId suffix.
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<string name="app_name">Calendula Debug</string>
|
|
||||||
</resources>
|
|
||||||
@@ -8,7 +8,6 @@ import androidx.activity.compose.setContent
|
|||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -30,7 +29,6 @@ import de.jeanlucmakiola.calendula.ui.common.LocalShowHourLines
|
|||||||
import de.jeanlucmakiola.calendula.ui.common.LocalUse24HourFormat
|
import de.jeanlucmakiola.calendula.ui.common.LocalUse24HourFormat
|
||||||
import de.jeanlucmakiola.calendula.ui.WidgetNavRequest
|
import de.jeanlucmakiola.calendula.ui.WidgetNavRequest
|
||||||
import de.jeanlucmakiola.calendula.ui.common.CalendarView
|
import de.jeanlucmakiola.calendula.ui.common.CalendarView
|
||||||
import de.jeanlucmakiola.calendula.ui.common.DebugRibbon
|
|
||||||
import de.jeanlucmakiola.calendula.ui.crash.CrashReportActivity
|
import de.jeanlucmakiola.calendula.ui.crash.CrashReportActivity
|
||||||
import de.jeanlucmakiola.calendula.ui.crash.CrashReportDialog
|
import de.jeanlucmakiola.calendula.ui.crash.CrashReportDialog
|
||||||
import de.jeanlucmakiola.calendula.ui.crash.submitCrashReport
|
import de.jeanlucmakiola.calendula.ui.crash.submitCrashReport
|
||||||
@@ -103,7 +101,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
darkTheme = darkTheme,
|
darkTheme = darkTheme,
|
||||||
dynamicColor = settings.dynamicColor,
|
dynamicColor = settings.dynamicColor,
|
||||||
) {
|
) {
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalUse24HourFormat provides use24Hour,
|
LocalUse24HourFormat provides use24Hour,
|
||||||
LocalShowHourLines provides settings.showHourLines,
|
LocalShowHourLines provides settings.showHourLines,
|
||||||
@@ -118,10 +115,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
onImportConsumed = { requestedImportUri = null },
|
onImportConsumed = { requestedImportUri = null },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// A persistent corner marker so a debug build is never
|
|
||||||
// mistaken for the production app; compiled out of release.
|
|
||||||
if (BuildConfig.DEBUG) DebugRibbon()
|
|
||||||
}
|
|
||||||
pendingCrashReport?.let { report ->
|
pendingCrashReport?.let { report ->
|
||||||
CrashReportDialog(
|
CrashReportDialog(
|
||||||
report = report,
|
report = report,
|
||||||
|
|||||||
@@ -118,14 +118,8 @@ internal fun buildEventUpdateValues(
|
|||||||
* provider clone the series row and apply these on top. Unlike the series
|
* provider clone the series row and apply these on top. Unlike the series
|
||||||
* update there is no dirty check — the exception is a fresh row, so every
|
* update there is no dirty check — the exception is a fresh row, so every
|
||||||
* form-backed column is written (empty optionals as explicit NULLs, since the
|
* form-backed column is written (empty optionals as explicit NULLs, since the
|
||||||
* clone starts from the parent's values).
|
* clone starts from the parent's values). An exception is a single event:
|
||||||
*
|
* DTEND, never RRULE/DURATION.
|
||||||
* The occurrence's length travels as DURATION, never DTEND: the provider
|
|
||||||
* rejects DTEND on an exception outright (`CalendarProvider2`:
|
|
||||||
* "Exceptions can't overwrite dtend") and derives the instance end from
|
|
||||||
* DTSTART + DURATION itself, clearing the inherited RRULE in the process. This
|
|
||||||
* matches how AOSP Calendar/Etar write exceptions; sending DTEND is what made
|
|
||||||
* "only this event" fail on-device (Codeberg #16).
|
|
||||||
*/
|
*/
|
||||||
internal fun buildOccurrenceExceptionValues(
|
internal fun buildOccurrenceExceptionValues(
|
||||||
form: EventForm,
|
form: EventForm,
|
||||||
@@ -137,7 +131,7 @@ internal fun buildOccurrenceExceptionValues(
|
|||||||
put(CalendarContract.Events.TITLE, form.title.trim())
|
put(CalendarContract.Events.TITLE, form.title.trim())
|
||||||
put(CalendarContract.Events.ALL_DAY, if (form.isAllDay) 1 else 0)
|
put(CalendarContract.Events.ALL_DAY, if (form.isAllDay) 1 else 0)
|
||||||
put(CalendarContract.Events.DTSTART, times.dtStartMillis)
|
put(CalendarContract.Events.DTSTART, times.dtStartMillis)
|
||||||
put(CalendarContract.Events.DURATION, times.toRfc2445Duration(form.isAllDay))
|
put(CalendarContract.Events.DTEND, times.dtEndMillis)
|
||||||
put(CalendarContract.Events.EVENT_TIMEZONE, times.timezone)
|
put(CalendarContract.Events.EVENT_TIMEZONE, times.timezone)
|
||||||
put(CalendarContract.Events.AVAILABILITY, form.availability.toProviderValue())
|
put(CalendarContract.Events.AVAILABILITY, form.availability.toProviderValue())
|
||||||
put(CalendarContract.Events.ACCESS_LEVEL, form.accessLevel.toProviderValue())
|
put(CalendarContract.Events.ACCESS_LEVEL, form.accessLevel.toProviderValue())
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
package de.jeanlucmakiola.calendula.ui.common
|
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
|
||||||
import androidx.compose.foundation.layout.offset
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.rotate
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import androidx.compose.ui.zIndex
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Flutter-style "DEBUG" corner ribbon, drawn across the top-right corner of
|
|
||||||
* the app. Deliberately a stark, un-themed marker (not a product component) so a
|
|
||||||
* debug build is unmistakable at a glance — gate it on `BuildConfig.DEBUG` at the
|
|
||||||
* call site so it never reaches a release build. Non-interactive: it's a plain
|
|
||||||
* label with no pointer handler, so taps fall through to whatever is beneath it.
|
|
||||||
*
|
|
||||||
* Drop it in as the last child of a full-screen [androidx.compose.foundation.layout.Box]
|
|
||||||
* so it overlays the UI.
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
fun BoxScope.DebugRibbon() {
|
|
||||||
Text(
|
|
||||||
text = "DEBUG",
|
|
||||||
color = Color.White,
|
|
||||||
fontSize = 10.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
letterSpacing = 1.sp,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier
|
|
||||||
.align(Alignment.TopEnd)
|
|
||||||
.zIndex(1f)
|
|
||||||
// Push the band out so its midline crosses the very corner, then
|
|
||||||
// rotate it to the classic 45° ribbon.
|
|
||||||
.offset(x = 36.dp, y = 24.dp)
|
|
||||||
.rotate(45f)
|
|
||||||
.background(Color(0xFFB23B00))
|
|
||||||
.width(140.dp)
|
|
||||||
.padding(vertical = 2.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -199,12 +199,11 @@ class EventWriteMapperTest {
|
|||||||
assertThat(values[CalendarContract.Events.TITLE]).isEqualTo("Moved")
|
assertThat(values[CalendarContract.Events.TITLE]).isEqualTo("Moved")
|
||||||
assertThat(values[CalendarContract.Events.EVENT_LOCATION]).isEqualTo("Berlin")
|
assertThat(values[CalendarContract.Events.EVENT_LOCATION]).isEqualTo("Berlin")
|
||||||
assertThat(values[CalendarContract.Events.DTSTART]).isEqualTo(1_781_164_800_000L)
|
assertThat(values[CalendarContract.Events.DTSTART]).isEqualTo(1_781_164_800_000L)
|
||||||
// The occurrence's length travels as DURATION, never DTEND — the provider
|
assertThat(values[CalendarContract.Events.DTEND])
|
||||||
// rejects DTEND on an exception ("Exceptions can't overwrite dtend") and
|
.isEqualTo(1_781_164_800_000L + 5_400_000L)
|
||||||
// derives the end from DTSTART + DURATION, clearing the inherited RRULE.
|
// A single occurrence never carries its own rule.
|
||||||
assertThat(values[CalendarContract.Events.DURATION]).isEqualTo("P5400S")
|
|
||||||
assertThat(values).doesNotContainKey(CalendarContract.Events.DTEND)
|
|
||||||
assertThat(values).doesNotContainKey(CalendarContract.Events.RRULE)
|
assertThat(values).doesNotContainKey(CalendarContract.Events.RRULE)
|
||||||
|
assertThat(values).doesNotContainKey(CalendarContract.Events.DURATION)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
|
||||||
distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f
|
distributionSha256Sum=bafc141b619ad6350fd975fc903156dd5c151998cc8b058e8c1044ab5f7b031f
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
|
|||||||
Reference in New Issue
Block a user