Phase 2: core-crash from floret-kit; complete the core-time wiring
All checks were successful
CI / ci (push) Successful in 9m16s
All checks were successful
CI / ci (push) Successful in 9m16s
Adds crash reporting to Agendula by drawing the kit's new core-crash module (first Android-library module in floret-kit), and finishes the core-time wiring that a Phase 0 staging slip left uncommitted on main. core-crash (NEW capability — Agendula had none): - CrashReporter.install() in AgendulaApp captures uncaught exceptions on-device (allowlist-only report, chains to the platform handler, uploads nothing). - MainActivity routes to a standalone CrashReportActivity on a startup crash-loop, and surfaces a single captured crash as a dialog on next launch; markHealthy on resume. App label + issue-tracker URL flow in via CrashConfig. - Thin app-side CrashReportActivity uses AgendulaTheme; the reusable machinery (reporter, dialog, submit, config) lives in the kit. Submodule re-pinned to the core-crash kit commit. Completes Phase 0 (was only partially committed inec7b696): - Repoint DayWindow + Instant formatting imports to de.jeanlucmakiola.floret.time (the app copies were deleted inec7b696but the imports/includeBuild/dependency were never staged, leaving main non-building). - settings.gradle.kts includeBuild("floret-kit"); app depends on core-time. Also fixes the CI checkout YAML: the submodules block was mis-indented under 'uses:' (invalid step mapping) — dedented to a proper sibling. Clean composite build + unit tests + lintDebug + debug assemble green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
@@ -73,6 +75,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
@@ -322,6 +326,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
- name: Extract changelog section for this tag
|
- name: Extract changelog section for this tag
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.kotlinx.datetime)
|
implementation(libs.kotlinx.datetime)
|
||||||
implementation(libs.kotlinx.coroutines.core)
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
|
implementation("de.jeanlucmakiola.floret:core-time")
|
||||||
|
implementation("de.jeanlucmakiola.floret:core-crash")
|
||||||
|
|
||||||
debugImplementation(libs.androidx.ui.tooling)
|
debugImplementation(libs.androidx.ui.tooling)
|
||||||
debugImplementation(libs.androidx.ui.test.manifest)
|
debugImplementation(libs.androidx.ui.test.manifest)
|
||||||
|
|||||||
@@ -52,6 +52,14 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<!-- Standalone crash-report surface; MainActivity routes here on a
|
||||||
|
startup crash-loop. Not exported, kept out of recents. -->
|
||||||
|
<activity
|
||||||
|
android:name=".ui.crash.CrashReportActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:launchMode="singleTask" />
|
||||||
|
|
||||||
<!-- Reminder alarm fires here (internal PendingIntent → not exported). -->
|
<!-- Reminder alarm fires here (internal PendingIntent → not exported). -->
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".data.reminders.DueReminderReceiver"
|
android:name=".data.reminders.DueReminderReceiver"
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import dagger.hilt.android.EntryPointAccessors
|
|||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import de.jeanlucmakiola.agendula.data.reminders.ReminderScheduler
|
import de.jeanlucmakiola.agendula.data.reminders.ReminderScheduler
|
||||||
|
import de.jeanlucmakiola.floret.crash.CrashConfig
|
||||||
|
import de.jeanlucmakiola.floret.crash.CrashReporter
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
@@ -22,6 +24,17 @@ class AgendulaApp : Application() {
|
|||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
// Install first thing so startup crashes are captured too (privacy-
|
||||||
|
// respecting, on-device; the user submits the report by hand).
|
||||||
|
CrashReporter.install(
|
||||||
|
this,
|
||||||
|
CrashConfig(
|
||||||
|
appLabel = getString(R.string.app_name),
|
||||||
|
newIssueUrl = getString(R.string.report_issue_url),
|
||||||
|
chooseIssueUrl = getString(R.string.report_issue_url),
|
||||||
|
issueTitle = getString(R.string.crash_report_issue_title),
|
||||||
|
),
|
||||||
|
)
|
||||||
val scheduler = EntryPointAccessors
|
val scheduler = EntryPointAccessors
|
||||||
.fromApplication(this, ReminderEntryPoint::class.java)
|
.fromApplication(this, ReminderEntryPoint::class.java)
|
||||||
.reminderScheduler()
|
.reminderScheduler()
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import androidx.activity.enableEdgeToEdge
|
|||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
@@ -17,8 +19,12 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
import de.jeanlucmakiola.agendula.data.demo.DemoSeeder
|
import de.jeanlucmakiola.agendula.data.demo.DemoSeeder
|
||||||
import de.jeanlucmakiola.agendula.data.prefs.ThemeMode
|
import de.jeanlucmakiola.agendula.data.prefs.ThemeMode
|
||||||
import de.jeanlucmakiola.agendula.ui.RootScreen
|
import de.jeanlucmakiola.agendula.ui.RootScreen
|
||||||
|
import de.jeanlucmakiola.agendula.ui.crash.CrashReportActivity
|
||||||
import de.jeanlucmakiola.agendula.ui.settings.SettingsViewModel
|
import de.jeanlucmakiola.agendula.ui.settings.SettingsViewModel
|
||||||
import de.jeanlucmakiola.agendula.ui.theme.AgendulaTheme
|
import de.jeanlucmakiola.agendula.ui.theme.AgendulaTheme
|
||||||
|
import de.jeanlucmakiola.floret.crash.CrashReportDialog
|
||||||
|
import de.jeanlucmakiola.floret.crash.CrashReporter
|
||||||
|
import de.jeanlucmakiola.floret.crash.submitCrashReport
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -32,10 +38,28 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
@Inject lateinit var demoSeeder: DemoSeeder
|
@Inject lateinit var demoSeeder: DemoSeeder
|
||||||
|
|
||||||
|
// A captured crash report awaiting the user's decision, surfaced as a dialog
|
||||||
|
// over the app on the next launch (the single-crash path). A startup
|
||||||
|
// crash-loop is handled out of band, before setContent — see below.
|
||||||
|
private var pendingCrashReport by mutableStateOf<String?>(null)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// If the app keeps crashing as it starts, the main UI can't be trusted
|
||||||
|
// to come up. Route to the standalone report screen instead of
|
||||||
|
// re-entering the crashing graph.
|
||||||
|
if (CrashReporter.isCrashLoop(this)) {
|
||||||
|
startActivity(Intent(this, CrashReportActivity::class.java))
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
|
|
||||||
|
// Surface a single captured crash as a dialog on the next launch.
|
||||||
|
if (CrashReporter.shouldPrompt(this)) pendingCrashReport = CrashReporter.pendingReport(this)
|
||||||
|
|
||||||
// Debug-only sample data: `am start ... --ez agendula_seed true`. Seeds a
|
// Debug-only sample data: `am start ... --ez agendula_seed true`. Seeds a
|
||||||
// local (non-syncing) demo list once; no-op without the extra.
|
// local (non-syncing) demo list once; no-op without the extra.
|
||||||
if (BuildConfig.DEBUG && intent.getBooleanExtra(EXTRA_SEED, false)) {
|
if (BuildConfig.DEBUG && intent.getBooleanExtra(EXTRA_SEED, false)) {
|
||||||
@@ -51,10 +75,31 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
AgendulaTheme(darkTheme = darkTheme, dynamicColor = ui.settings.dynamicColor) {
|
AgendulaTheme(darkTheme = darkTheme, dynamicColor = ui.settings.dynamicColor) {
|
||||||
RootScreen(modifier = Modifier.fillMaxSize())
|
RootScreen(modifier = Modifier.fillMaxSize())
|
||||||
|
pendingCrashReport?.let { report ->
|
||||||
|
CrashReportDialog(
|
||||||
|
report = report,
|
||||||
|
onSend = {
|
||||||
|
submitCrashReport(this@MainActivity, report)
|
||||||
|
CrashReporter.clearReport(this@MainActivity)
|
||||||
|
pendingCrashReport = null
|
||||||
|
},
|
||||||
|
onDismiss = {
|
||||||
|
CrashReporter.dismissPrompt(this@MainActivity)
|
||||||
|
pendingCrashReport = null
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
// A successful start breaks any loop; reset the timing trail so a later
|
||||||
|
// ordinary crash isn't mistaken for a loop.
|
||||||
|
CrashReporter.markHealthy(this)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val EXTRA_TASK_ID = "de.jeanlucmakiola.agendula.extra.TASK_ID"
|
const val EXTRA_TASK_ID = "de.jeanlucmakiola.agendula.extra.TASK_ID"
|
||||||
private const val EXTRA_SEED = "agendula_seed"
|
private const val EXTRA_SEED = "agendula_seed"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package de.jeanlucmakiola.agendula.data.demo
|
|||||||
|
|
||||||
import de.jeanlucmakiola.agendula.data.di.IoDispatcher
|
import de.jeanlucmakiola.agendula.data.di.IoDispatcher
|
||||||
import de.jeanlucmakiola.agendula.data.tasks.TasksRepository
|
import de.jeanlucmakiola.agendula.data.tasks.TasksRepository
|
||||||
import de.jeanlucmakiola.agendula.domain.DayWindow
|
import de.jeanlucmakiola.floret.time.DayWindow
|
||||||
import de.jeanlucmakiola.agendula.domain.Priority
|
import de.jeanlucmakiola.agendula.domain.Priority
|
||||||
import de.jeanlucmakiola.agendula.domain.TaskForm
|
import de.jeanlucmakiola.agendula.domain.TaskForm
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package de.jeanlucmakiola.agendula.data.tasks
|
package de.jeanlucmakiola.agendula.data.tasks
|
||||||
|
|
||||||
import de.jeanlucmakiola.agendula.data.di.IoDispatcher
|
import de.jeanlucmakiola.agendula.data.di.IoDispatcher
|
||||||
import de.jeanlucmakiola.agendula.domain.DayWindow
|
import de.jeanlucmakiola.floret.time.DayWindow
|
||||||
import de.jeanlucmakiola.agendula.domain.Task
|
import de.jeanlucmakiola.agendula.domain.Task
|
||||||
import de.jeanlucmakiola.agendula.domain.TaskDetail
|
import de.jeanlucmakiola.agendula.domain.TaskDetail
|
||||||
import de.jeanlucmakiola.agendula.domain.TaskFilter
|
import de.jeanlucmakiola.agendula.domain.TaskFilter
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package de.jeanlucmakiola.agendula.ui.common
|
package de.jeanlucmakiola.agendula.ui.common
|
||||||
|
|
||||||
|
import de.jeanlucmakiola.floret.time.formatDateTime
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package de.jeanlucmakiola.agendula.ui.crash
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import de.jeanlucmakiola.agendula.ui.theme.AgendulaTheme
|
||||||
|
import de.jeanlucmakiola.floret.crash.CrashReportDialog
|
||||||
|
import de.jeanlucmakiola.floret.crash.CrashReporter
|
||||||
|
import de.jeanlucmakiola.floret.crash.submitCrashReport
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standalone surface for a captured crash report. [MainActivity] routes here
|
||||||
|
* when it detects a startup crash-loop (see [CrashReporter.isCrashLoop]): the
|
||||||
|
* main UI can't be trusted to start, so this screen stays clear of the app's
|
||||||
|
* Hilt graph, DataStore-backed theme and Compose content — it only reads the
|
||||||
|
* report file and shows the kit's report dialog. Plain [AgendulaTheme] defaults
|
||||||
|
* (follow-system, dynamic colour) avoid touching anything that might be the
|
||||||
|
* cause of the crash. The reusable machinery lives in floret-kit's core-crash.
|
||||||
|
*/
|
||||||
|
class CrashReportActivity : ComponentActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
val report = CrashReporter.pendingReport(this)
|
||||||
|
if (report == null) {
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
enableEdgeToEdge()
|
||||||
|
setContent {
|
||||||
|
AgendulaTheme {
|
||||||
|
// Opaque backdrop so the dialog doesn't float over a bare task.
|
||||||
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.surface) {}
|
||||||
|
CrashReportDialog(
|
||||||
|
report = report,
|
||||||
|
onSend = {
|
||||||
|
submitCrashReport(this, report)
|
||||||
|
CrashReporter.clearReport(this)
|
||||||
|
finish()
|
||||||
|
},
|
||||||
|
onDismiss = {
|
||||||
|
CrashReporter.clearReport(this)
|
||||||
|
finish()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
// Reaching this screen breaks the loop; reset the timing trail so a
|
||||||
|
// later ordinary crash isn't mistaken for a loop.
|
||||||
|
CrashReporter.markHealthy(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -72,8 +72,8 @@ import de.jeanlucmakiola.agendula.domain.Task
|
|||||||
import de.jeanlucmakiola.agendula.domain.TaskDetail
|
import de.jeanlucmakiola.agendula.domain.TaskDetail
|
||||||
import de.jeanlucmakiola.agendula.ui.common.GroupedSurface
|
import de.jeanlucmakiola.agendula.ui.common.GroupedSurface
|
||||||
import de.jeanlucmakiola.agendula.ui.common.PriorityChip
|
import de.jeanlucmakiola.agendula.ui.common.PriorityChip
|
||||||
import de.jeanlucmakiola.agendula.ui.common.formatDate
|
import de.jeanlucmakiola.floret.time.formatDate
|
||||||
import de.jeanlucmakiola.agendula.ui.common.formatTime
|
import de.jeanlucmakiola.floret.time.formatTime
|
||||||
import de.jeanlucmakiola.agendula.ui.common.pastelize
|
import de.jeanlucmakiola.agendula.ui.common.pastelize
|
||||||
import de.jeanlucmakiola.agendula.ui.common.positionOf
|
import de.jeanlucmakiola.agendula.ui.common.positionOf
|
||||||
import de.jeanlucmakiola.agendula.ui.tasklist.priorityLabel
|
import de.jeanlucmakiola.agendula.ui.tasklist.priorityLabel
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import de.jeanlucmakiola.agendula.R
|
import de.jeanlucmakiola.agendula.R
|
||||||
import de.jeanlucmakiola.agendula.domain.DayWindow
|
import de.jeanlucmakiola.floret.time.DayWindow
|
||||||
import de.jeanlucmakiola.agendula.domain.Priority
|
import de.jeanlucmakiola.agendula.domain.Priority
|
||||||
import de.jeanlucmakiola.agendula.domain.Task
|
import de.jeanlucmakiola.agendula.domain.Task
|
||||||
import de.jeanlucmakiola.agendula.domain.TaskFormError
|
import de.jeanlucmakiola.agendula.domain.TaskFormError
|
||||||
@@ -98,8 +98,8 @@ import de.jeanlucmakiola.agendula.ui.common.GroupedRow
|
|||||||
import de.jeanlucmakiola.agendula.ui.common.InlineTextField
|
import de.jeanlucmakiola.agendula.ui.common.InlineTextField
|
||||||
import de.jeanlucmakiola.agendula.ui.common.OptionCard
|
import de.jeanlucmakiola.agendula.ui.common.OptionCard
|
||||||
import de.jeanlucmakiola.agendula.ui.common.priorityFill
|
import de.jeanlucmakiola.agendula.ui.common.priorityFill
|
||||||
import de.jeanlucmakiola.agendula.ui.common.formatDate
|
import de.jeanlucmakiola.floret.time.formatDate
|
||||||
import de.jeanlucmakiola.agendula.ui.common.formatTime
|
import de.jeanlucmakiola.floret.time.formatTime
|
||||||
import de.jeanlucmakiola.agendula.ui.common.localToInstant
|
import de.jeanlucmakiola.agendula.ui.common.localToInstant
|
||||||
import de.jeanlucmakiola.agendula.ui.common.pastelize
|
import de.jeanlucmakiola.agendula.ui.common.pastelize
|
||||||
import de.jeanlucmakiola.agendula.ui.common.positionOf
|
import de.jeanlucmakiola.agendula.ui.common.positionOf
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import de.jeanlucmakiola.agendula.data.tasks.TasksRepository
|
import de.jeanlucmakiola.agendula.data.tasks.TasksRepository
|
||||||
import de.jeanlucmakiola.agendula.domain.DayWindow
|
import de.jeanlucmakiola.floret.time.DayWindow
|
||||||
import de.jeanlucmakiola.agendula.domain.SmartList
|
import de.jeanlucmakiola.agendula.domain.SmartList
|
||||||
import de.jeanlucmakiola.agendula.domain.Task
|
import de.jeanlucmakiola.agendula.domain.Task
|
||||||
import de.jeanlucmakiola.agendula.domain.TaskFilter
|
import de.jeanlucmakiola.agendula.domain.TaskFilter
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import de.jeanlucmakiola.agendula.R
|
import de.jeanlucmakiola.agendula.R
|
||||||
import de.jeanlucmakiola.agendula.domain.DayWindow
|
import de.jeanlucmakiola.floret.time.DayWindow
|
||||||
import de.jeanlucmakiola.agendula.domain.Priority
|
import de.jeanlucmakiola.agendula.domain.Priority
|
||||||
import de.jeanlucmakiola.agendula.domain.SmartList
|
import de.jeanlucmakiola.agendula.domain.SmartList
|
||||||
import de.jeanlucmakiola.agendula.domain.Task
|
import de.jeanlucmakiola.agendula.domain.Task
|
||||||
@@ -91,7 +91,7 @@ import de.jeanlucmakiola.agendula.domain.TaskSections
|
|||||||
import de.jeanlucmakiola.agendula.ui.common.ListNameChip
|
import de.jeanlucmakiola.agendula.ui.common.ListNameChip
|
||||||
import de.jeanlucmakiola.agendula.ui.common.Position
|
import de.jeanlucmakiola.agendula.ui.common.Position
|
||||||
import de.jeanlucmakiola.agendula.ui.common.PriorityChip
|
import de.jeanlucmakiola.agendula.ui.common.PriorityChip
|
||||||
import de.jeanlucmakiola.agendula.ui.common.formatDateTime
|
import de.jeanlucmakiola.floret.time.formatDateTime
|
||||||
import de.jeanlucmakiola.agendula.ui.common.pastelize
|
import de.jeanlucmakiola.agendula.ui.common.pastelize
|
||||||
import de.jeanlucmakiola.agendula.ui.common.positionOf
|
import de.jeanlucmakiola.agendula.ui.common.positionOf
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
|
|||||||
@@ -176,6 +176,7 @@
|
|||||||
<string name="settings_report_problem">Report a problem</string>
|
<string name="settings_report_problem">Report a problem</string>
|
||||||
<string name="settings_report_problem_hint">Open the issue tracker</string>
|
<string name="settings_report_problem_hint">Open the issue tracker</string>
|
||||||
<string name="about_source_url" translatable="false">https://gitea.jeanlucmakiola.de/makiolaj/agendula</string>
|
<string name="about_source_url" translatable="false">https://gitea.jeanlucmakiola.de/makiolaj/agendula</string>
|
||||||
|
<string name="crash_report_issue_title">Crash report</string>
|
||||||
<string name="report_issue_url" translatable="false">https://gitea.jeanlucmakiola.de/makiolaj/agendula/issues/new</string>
|
<string name="report_issue_url" translatable="false">https://gitea.jeanlucmakiola.de/makiolaj/agendula/issues/new</string>
|
||||||
<string name="about_license_url" translatable="false">https://gitea.jeanlucmakiola.de/makiolaj/agendula/src/branch/main/LICENSE</string>
|
<string name="about_license_url" translatable="false">https://gitea.jeanlucmakiola.de/makiolaj/agendula/src/branch/main/LICENSE</string>
|
||||||
<string name="about_support_url" translatable="false">https://ko-fi.com/jeanlucmakiola</string>
|
<string name="about_support_url" translatable="false">https://ko-fi.com/jeanlucmakiola</string>
|
||||||
|
|||||||
Submodule floret-kit updated: d3ae83f1a4...19c2f8a677
@@ -25,3 +25,4 @@ dependencyResolutionManagement {
|
|||||||
|
|
||||||
rootProject.name = "Agendula"
|
rootProject.name = "Agendula"
|
||||||
include(":app")
|
include(":app")
|
||||||
|
includeBuild("floret-kit")
|
||||||
|
|||||||
Reference in New Issue
Block a user