Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ per-variant entry (`ListScreenJournals/Notes/Tasks.kt`).
- **Repositories:** interface in `core/domain/repository/`, implementation in
`core/data/repository/`.
- **Database:** SQLDelight (`shared/src/commonMain/sqldelight/…`). Schema changes need a
new numbered migration (`13.sqm` next) alongside the `.sq` edit — never edit an
new numbered migration (`14.sqm` next) alongside the `.sq` edit — never edit an
existing `.sqm`.
- **Strings:** source strings only in
`shared/src/commonMain/composeResources/values/strings.xml`. Never hand-edit
Expand Down
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#Kotlin
kotlin.code.style=official
kotlin.daemon.jvmargs=-Xmx3072M
# The JS and Wasm test executables are compiled in this daemon and ran out of memory at 3 GB on CI.
kotlin.daemon.jvmargs=-Xmx6144M

#Gradle
org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8
Expand Down
2 changes: 2 additions & 0 deletions shared/src/commonMain/composeResources/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@
<string name="subtasks_not_supported_in_collection">Not supported in this collection</string>
<string name="url">URL</string>
<string name="add_url">Add URL</string>
<string name="location">Location</string>
<string name="add_location">Add location</string>
<string name="add">Add</string>
<string name="link_file_by_url">Link file by URL</string>
<string name="link_file_by_url_hint">The file stays on its server - Spectacled only stores the link and downloads it when opened.</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ data class ClaudeResponseDto(
description = data.description ?: icalEntry.description,
dtStart = if(icalEntry.isTask() || icalEntry.isJournal()) parseIcsDateTime(data.dtstart) else null,
due = if(icalEntry.isTask()) parseIcsDateTime(data.due) else null,
location = data.location ?: icalEntry.location,
categories = data.categories ?: icalEntry.categories
)
} catch (e: Exception) {
Expand All @@ -52,7 +53,7 @@ data class ClaudeIcalDataDto(
@SerialName("description") val description: String? = null,
@SerialName("dtstart") val dtstart: String? = null,
@SerialName("due") val due: String? = null,
@SerialName("location") val location: String? = null, // Note: IcalEntry currently doesn't have a location field
@SerialName("location") val location: String? = null,
@SerialName("categories") val categories: List<String>? = null
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ enum class KnownIcsPropertyName(val propertyName: String) {
PERCENT_COMPLETE("PERCENT-COMPLETE"),
RELATED_TO("RELATED-TO"),
URL("URL"),
LOCATION("LOCATION"),
ATTACH("ATTACH")
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ class IcalEntryRepositoryImpl(
calendarComponent = icalEntryDto.calendarComponent,
parentUid = icalEntryDto.parentUid,
relType = icalEntryDto.relType,
url = icalEntryDto.url
url = icalEntryDto.url,
location = icalEntryDto.location
)
// insert, but if the UID exists, it will be ignored
db.icalentry_dtoQueries.insertIcalEntry(
Expand Down Expand Up @@ -234,7 +235,8 @@ class IcalEntryRepositoryImpl(
calendarComponent = icalEntryDto.calendarComponent,
parentUid = icalEntryDto.parentUid,
relType = icalEntryDto.relType,
url = icalEntryDto.url
url = icalEntryDto.url,
location = icalEntryDto.location
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ data class IcalEntry(
val calendarComponent: CalendarComponent,
val parentUid: String? = null,
val relType: String? = null,
val url: Url? = null
val url: Url? = null,
val location: String? = null
) {

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ fun IcalEntryDto.toDomain(attachments: List<Attachment> = emptyList()): IcalEntr
calendarComponent = CalendarComponent.entries.find { it.name == this.calendarComponent } ?: CalendarComponent.VJOURNAL,
parentUid = this.parentUid,
relType = this.relType,
url = this.url?.let { Url(it) }
url = this.url?.let { Url(it) },
location = this.location
)
}

Expand Down Expand Up @@ -105,6 +106,7 @@ fun IcalEntry.toDto(): IcalEntryDto {
calendarComponent = this.calendarComponent.name,
parentUid = this.parentUid,
relType = this.relType,
url = this.url?.toString()
url = this.url?.toString(),
location = this.location?.ifEmpty { null }
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,8 @@ fun parseIcalEntryBlock(
calendarComponent = calendarComponent,
parentUid = parentUid,
relType = relType,
url = url
url = url,
location = knownProps[KnownIcsPropertyName.LOCATION.propertyName]?.firstOrNull()?.value?.ifEmpty { null }
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ fun serializeVJournal(icalEntry: IcalEntry, fileManager: FileManager? = null): S
}
icalEntry.summary?.let { lines += "${KnownIcsPropertyName.SUMMARY.propertyName}:${escapeIcsValue(it)}" }
icalEntry.description?.let { lines += "${KnownIcsPropertyName.DESCRIPTION.propertyName}:${escapeIcsValue(it)}" }
icalEntry.location?.let { lines += "${KnownIcsPropertyName.LOCATION.propertyName}:${escapeIcsValue(it)}" }
icalEntry.color?.let { lines += "${KnownIcsPropertyName.COLOR.propertyName}:${it.toArgb()}" }
icalEntry.status?.let { lines += "${KnownIcsPropertyName.STATUS.propertyName}:${it.rfcName}" }
icalEntry.classification?.let { lines += "${KnownIcsPropertyName.CLASSIFICATION.propertyName}:${it.name}" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ sealed interface DetailsAction {
data class OnUpdateSubtaskProgress(val percent: Long, val subtaskIcalEntryId: Long): DetailsAction
data class OnAddSubtask(val summary: String): DetailsAction
data class OnUpdateUrl(val url: Url?): DetailsAction
data class OnUpdateLocation(val location: String?): DetailsAction
data class OnAddAttachment(val fileName: String, val bytes: ByteArray, val mimeType: String?): DetailsAction
data class OnAddUrlAttachment(val url: Url): DetailsAction
data class OnOpenAttachment(val attachmentUid: String): DetailsAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ import at.techbee.spectacled.screens.core.presentation.components.WavyHorizontal
import at.techbee.spectacled.screens.details.presentation.components.AttachmentCard
import at.techbee.spectacled.screens.details.presentation.components.DateTimeCard
import at.techbee.spectacled.screens.details.presentation.components.FormattingBar
import at.techbee.spectacled.screens.details.presentation.components.LocationCard
import at.techbee.spectacled.screens.details.presentation.components.UrlCard
import at.techbee.spectacled.screens.list.presentation.components.MetaInfoCard
import at.techbee.spectacled.screens.list.presentation.components.TaskListItem
Expand Down Expand Up @@ -388,6 +389,18 @@ fun DetailsScreen(
}
}

AnimatedVisibility(state.icalEntry.location != null) {
Column(modifier = Modifier.fillMaxWidth()) {

LocationCard(
location = state.icalEntry.location?:"",
allowEditing = state.allowEditing(),
onClick = onAction,
modifier = Modifier.padding(vertical = 8.dp)
)
}
}

AnimatedVisibility(state.icalEntry.attachments.isNotEmpty()) {
Column(
verticalArrangement = Arrangement.spacedBy(2.dp),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Label
import androidx.compose.material.icons.outlined.AddBox
import androidx.compose.material.icons.outlined.AddLink
import androidx.compose.material.icons.outlined.AddLocation
import androidx.compose.material.icons.outlined.AddTask
import androidx.compose.material.icons.outlined.Attachment
import androidx.compose.material.icons.outlined.DatasetLinked
Expand Down Expand Up @@ -79,6 +80,7 @@ import at.techbee.spectacled.screens.details.presentation.components.DeleteIcalE
import at.techbee.spectacled.screens.details.presentation.components.DetailsMoreBottomSheet
import at.techbee.spectacled.screens.details.presentation.components.DetailsTopBar
import at.techbee.spectacled.screens.details.presentation.components.DrawingCanvasBottomSheet
import at.techbee.spectacled.screens.details.presentation.components.EditLocationBottomSheet
import at.techbee.spectacled.screens.details.presentation.components.EditUrlBottomSheet
import at.techbee.spectacled.screens.details.presentation.components.JournalStatusPickerBottomSheet
import at.techbee.spectacled.screens.details.presentation.components.MoveIcalEntryDialog
Expand All @@ -91,6 +93,7 @@ import spectacled.shared.generated.resources.Res
import spectacled.shared.generated.resources.add_attachment
import spectacled.shared.generated.resources.add_drawing
import spectacled.shared.generated.resources.add_from_gallery
import spectacled.shared.generated.resources.add_location
import spectacled.shared.generated.resources.add_photo
import spectacled.shared.generated.resources.add_subtask
import spectacled.shared.generated.resources.add_url
Expand Down Expand Up @@ -253,6 +256,12 @@ fun DetailsScreenRoot(
onUrlEdited = { detailsViewModel.onAction(DetailsAction.OnUpdateUrl(it)) },
onDismiss = { detailsViewModel.onAction(DetailsAction.OnShowSheetOrDialog(null)) }
)
DetailsSheetOrDialog.EDIT_LOCATION ->
EditLocationBottomSheet(
initialLocation = detailsState.icalEntry.location,
onLocationEdited = { detailsViewModel.onAction(DetailsAction.OnUpdateLocation(it)) },
onDismiss = { detailsViewModel.onAction(DetailsAction.OnShowSheetOrDialog(null)) }
)
DetailsSheetOrDialog.ADD_ATTACHMENT_URL ->
AddUrlAttachmentBottomSheet(
onUrlConfirmed = { detailsViewModel.onAction(DetailsAction.OnAddUrlAttachment(it)) },
Expand Down Expand Up @@ -464,6 +473,18 @@ fun DetailsScreenRoot(
},
)

if(detailsState.icalEntry.isTask()) {
DropdownMenuItem(
text = { Text(stringResource(Res.string.add_location)) },
leadingIcon = { Icon(Icons.Outlined.AddLocation, stringResource(Res.string.add_location)) },
enabled = detailsState.icalEntry.location == null,
onClick = {
detailsViewModel.onAction(DetailsAction.OnShowSheetOrDialog(DetailsSheetOrDialog.EDIT_LOCATION))
addMoreExpanded = false
},
)
}

DropdownMenuItem(
text = {
Column {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ data class DetailsState @OptIn(ExperimentalTime::class) constructor(
}

enum class DetailsSheetOrDialog {
DELETE, MOVE, MORE, COLOR_SELECTOR, CATEGORY_SELECTOR, JOURNAL_STATUS_PICKER, TASK_STATUS_PICKER, ADD_SUBTASKS, EDIT_URL, ADD_ATTACHMENT_URL
DELETE, MOVE, MORE, COLOR_SELECTOR, CATEGORY_SELECTOR, JOURNAL_STATUS_PICKER, TASK_STATUS_PICKER, ADD_SUBTASKS, EDIT_URL, EDIT_LOCATION, ADD_ATTACHMENT_URL
}

// Action to perform right after the details screen opens
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ class DetailsViewModel(
is DetailsAction.OnUpdateCategories -> onUpdateCategories(action.addCategory, action.removeCategory)
is DetailsAction.OnUpdateColor -> onUpdateColor(action.color)
is DetailsAction.OnUpdateUrl -> onUpdateUrl(action.url)
is DetailsAction.OnUpdateLocation -> onUpdateLocation(action.location)
is DetailsAction.OnUpdateDescription -> onUpdateDescription(action.description)
is DetailsAction.OnUpdateSummary -> onUpdateSummary(action.summary)
DetailsAction.OnDelete -> {
Expand Down Expand Up @@ -532,6 +533,22 @@ class DetailsViewModel(
}
}

private fun onUpdateLocation(newLocation: String?) {

if(!state.value.allowEditing())
return

_state.update {
it.copy(
icalEntry = it.icalEntry.copy(
location = newLocation,
lastModified = IcsDateTime.now(),
syncState = it.icalEntry.syncState.afterLocalEdit()
)
)
}
}

@OptIn(ExperimentalTime::class)
private fun onUpdateDtStart(newDtStart: IcsDateTime?) {

Expand Down
Loading
Loading