Start creating a separate sync queue for android highlight changes
This commit is contained in:
File diff suppressed because one or more lines are too long
@ -1,12 +1,17 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.graphql.generated.type.HighlightType
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import app.omnivore.omnivore.networking.*
|
||||
import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItemAndHighlightCrossRef
|
||||
import app.omnivore.omnivore.persistence.entities.saveHighlightChange
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.*
|
||||
|
||||
@ -33,6 +38,8 @@ suspend fun DataService.createWebHighlight(jsonString: String, colorName: String
|
||||
|
||||
highlight.serverSyncStatus = ServerSyncStatus.NEEDS_CREATION.rawValue
|
||||
|
||||
saveHighlightChange(db.highlightChangesDao(), createHighlightInput.articleId, highlight)
|
||||
|
||||
val crossRef = SavedItemAndHighlightCrossRef(
|
||||
highlightId = createHighlightInput.id,
|
||||
savedItemId = createHighlightInput.articleId
|
||||
@ -73,6 +80,8 @@ suspend fun DataService.createNoteHighlight(savedItemId: String, note: String):
|
||||
|
||||
highlight.serverSyncStatus = ServerSyncStatus.NEEDS_CREATION.rawValue
|
||||
|
||||
saveHighlightChange(db.highlightChangesDao(), savedItemId, highlight)
|
||||
|
||||
val crossRef = SavedItemAndHighlightCrossRef(
|
||||
highlightId = createHighlightId,
|
||||
savedItemId = savedItemId
|
||||
@ -103,18 +112,33 @@ suspend fun DataService.createNoteHighlight(savedItemId: String, note: String):
|
||||
|
||||
suspend fun DataService.mergeWebHighlights(jsonString: String) {
|
||||
val mergeHighlightInput = Gson().fromJson(jsonString, MergeHighlightsParams::class.java).asMergeHighlightInput()
|
||||
Log.d("sync", "mergeHighlightInput: " + mergeHighlightInput.id + ": " + mergeHighlightInput)
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
val highlight = db.highlightDao().findById(highlightId = mergeHighlightInput.id) ?: return@withContext
|
||||
highlight.shortId = mergeHighlightInput.shortId
|
||||
highlight.quote = mergeHighlightInput.quote
|
||||
highlight.patch = mergeHighlightInput.patch
|
||||
highlight.prefix = mergeHighlightInput.prefix.getOrNull()
|
||||
highlight.annotation = mergeHighlightInput.annotation.getOrNull()
|
||||
highlight.serverSyncStatus = ServerSyncStatus.NEEDS_UPDATE.rawValue
|
||||
val highlight = Highlight(
|
||||
type = "HIGHLIGHT",
|
||||
highlightId = mergeHighlightInput.id,
|
||||
shortId = mergeHighlightInput.shortId,
|
||||
quote = mergeHighlightInput.quote,
|
||||
prefix = null,
|
||||
suffix = null,
|
||||
patch = mergeHighlightInput.patch,
|
||||
annotation = mergeHighlightInput.annotation.getOrNull(),
|
||||
createdAt = null,
|
||||
updatedAt = null,
|
||||
createdByMe = false,
|
||||
color = mergeHighlightInput.color.getOrNull(),
|
||||
highlightPositionPercent = mergeHighlightInput.highlightPositionPercent.getOrNull() ?: 0.0,
|
||||
highlightPositionAnchorIndex = mergeHighlightInput.highlightPositionAnchorIndex.getOrNull() ?: 0
|
||||
)
|
||||
|
||||
highlight.serverSyncStatus = ServerSyncStatus.NEEDS_CREATION.rawValue
|
||||
|
||||
saveHighlightChange(db.highlightChangesDao(), mergeHighlightInput.articleId, highlight)
|
||||
|
||||
Log.d("sync", "overlapHighlightIdList: " + mergeHighlightInput.overlapHighlightIdList)
|
||||
for (highlightID in mergeHighlightInput.overlapHighlightIdList) {
|
||||
deleteHighlight(highlightID)
|
||||
deleteHighlight(mergeHighlightInput.articleId, highlightID)
|
||||
}
|
||||
|
||||
val crossRef = SavedItemAndHighlightCrossRef(
|
||||
@ -122,11 +146,10 @@ suspend fun DataService.mergeWebHighlights(jsonString: String) {
|
||||
savedItemId = mergeHighlightInput.articleId
|
||||
)
|
||||
|
||||
db.highlightDao().insertAll(listOf(highlight))
|
||||
db.savedItemAndHighlightCrossRefDao().insertAll(listOf(crossRef))
|
||||
db.highlightDao().update(highlight)
|
||||
|
||||
val isUpdatedOnServer = networker.mergeHighlights(mergeHighlightInput)
|
||||
|
||||
if (isUpdatedOnServer) {
|
||||
highlight.serverSyncStatus = ServerSyncStatus.IS_SYNCED.rawValue
|
||||
db.highlightDao().update(highlight)
|
||||
@ -135,16 +158,22 @@ suspend fun DataService.mergeWebHighlights(jsonString: String) {
|
||||
}
|
||||
|
||||
suspend fun DataService.updateWebHighlight(jsonString: String) {
|
||||
val updateHighlightParams = Gson().fromJson(jsonString, UpdateHighlightParams::class.java).asUpdateHighlightInput()
|
||||
val updateHighlightParams = Gson().fromJson(jsonString, UpdateHighlightParams::class.java)
|
||||
|
||||
if (updateHighlightParams.highlightId == null || updateHighlightParams.libraryItemId == null) {
|
||||
Log.d("error","ERROR INVALID HIGHLIGHT DATA")
|
||||
}
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
val highlight = db.highlightDao().findById(highlightId = updateHighlightParams.highlightId) ?: return@withContext
|
||||
val highlight = db.highlightDao().findById(highlightId = updateHighlightParams.highlightId ?: "") ?: return@withContext
|
||||
|
||||
highlight.annotation = updateHighlightParams.annotation.getOrNull()
|
||||
highlight.annotation = updateHighlightParams.annotation
|
||||
highlight.serverSyncStatus = ServerSyncStatus.NEEDS_UPDATE.rawValue
|
||||
db.highlightDao().update(highlight)
|
||||
|
||||
val isUpdatedOnServer = networker.updateHighlight(updateHighlightParams)
|
||||
saveHighlightChange(db.highlightChangesDao(), updateHighlightParams.libraryItemId ?: "", highlight)
|
||||
|
||||
val isUpdatedOnServer = networker.updateHighlight(updateHighlightParams.asUpdateHighlightInput())
|
||||
|
||||
if (isUpdatedOnServer) {
|
||||
highlight.serverSyncStatus = ServerSyncStatus.IS_SYNCED.rawValue
|
||||
@ -153,24 +182,31 @@ suspend fun DataService.updateWebHighlight(jsonString: String) {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun DataService.deleteHighlights(jsonString: String) {
|
||||
val highlightIDs = Gson().fromJson(jsonString, DeleteHighlightParams::class.java).asIdList()
|
||||
|
||||
for (highlightID in highlightIDs) {
|
||||
deleteHighlight(highlightID)
|
||||
}
|
||||
suspend fun DataService.deleteHighlightFromJSON(jsonString: String) {
|
||||
Log.d("sync", "DELETION STRING: " + jsonString)
|
||||
val deleteHighlightParams = Gson().fromJson(jsonString, DeleteHighlightParams::class.java)
|
||||
deleteHighlight(deleteHighlightParams.libraryItemId, deleteHighlightParams.highlightId)
|
||||
}
|
||||
|
||||
private suspend fun DataService.deleteHighlight(highlightID: String) {
|
||||
private suspend fun DataService.deleteHighlight(savedItemId: String, highlightID: String) {
|
||||
withContext(Dispatchers.IO) {
|
||||
val highlight = db.highlightDao().findById(highlightId = highlightID) ?: return@withContext
|
||||
highlight.serverSyncStatus = ServerSyncStatus.NEEDS_DELETION.rawValue
|
||||
db.highlightDao().update(highlight)
|
||||
val highlight = db.highlightDao().findById(highlightId = highlightID)
|
||||
|
||||
val isUpdatedOnServer = networker.deleteHighlights(listOf(highlightID))
|
||||
highlight?.let {
|
||||
highlight.serverSyncStatus = ServerSyncStatus.NEEDS_DELETION.rawValue
|
||||
db.highlightDao().update(highlight)
|
||||
|
||||
if (isUpdatedOnServer) {
|
||||
db.highlightDao().deleteById(highlightId = highlightID)
|
||||
saveHighlightChange(db.highlightChangesDao(), savedItemId, highlight)
|
||||
|
||||
val isUpdatedOnServer = networker.deleteHighlights(listOf(highlightID))
|
||||
Log.d("sync","DELETING HIGHLIGHT" + highlightID)
|
||||
|
||||
if (isUpdatedOnServer) {
|
||||
Log.d("sync","DELETED HIGHLIGHT" + highlightID)
|
||||
db.highlightDao().deleteById(highlightId = highlightID)
|
||||
}
|
||||
} ?: run {
|
||||
Log.d("sync","Could not find highlight for deletion" + savedItemId + "," + highlightID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package app.omnivore.omnivore.dataService
|
||||
|
||||
import android.util.Log
|
||||
import app.omnivore.omnivore.graphql.generated.type.CreateHighlightInput
|
||||
import app.omnivore.omnivore.graphql.generated.type.UpdateHighlightInput
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
@ -8,8 +9,10 @@ import app.omnivore.omnivore.persistence.entities.Highlight
|
||||
import app.omnivore.omnivore.persistence.entities.SavedItem
|
||||
import com.apollographql.apollo3.api.Optional
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlin.math.log
|
||||
|
||||
suspend fun DataService.startSyncChannels() {
|
||||
Log.d("sync", "Starting sync channels")
|
||||
for (savedItem in savedItemSyncChannel) {
|
||||
syncSavedItem(savedItem)
|
||||
}
|
||||
@ -21,7 +24,8 @@ suspend fun DataService.startSyncChannels() {
|
||||
|
||||
suspend fun DataService.syncOfflineItemsWithServerIfNeeded() {
|
||||
val unSyncedSavedItems = db.savedItemDao().getUnSynced()
|
||||
val unSyncedHighlights = db.highlightDao().getUnSynced()
|
||||
val unSyncedHighlights = db.highlightChangesDao().getUnSynced()
|
||||
Log.d("sync","UNSYNC CHANGES: " + unSyncedHighlights)
|
||||
|
||||
for (savedItem in unSyncedSavedItems) {
|
||||
delay(250)
|
||||
@ -30,7 +34,7 @@ suspend fun DataService.syncOfflineItemsWithServerIfNeeded() {
|
||||
|
||||
for (highlight in unSyncedHighlights) {
|
||||
delay(250)
|
||||
highlightSyncChannel.send(highlight)
|
||||
// highlightSyncChannel.send(highlight)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@ data class CreateHighlightParams(
|
||||
|
||||
data class UpdateHighlightParams(
|
||||
val highlightId: String?,
|
||||
val libraryItemId: String?,
|
||||
val `annotation`: String?,
|
||||
val sharedAt: String?,
|
||||
) {
|
||||
@ -73,9 +74,10 @@ data class MergeHighlightsParams(
|
||||
}
|
||||
|
||||
data class DeleteHighlightParams(
|
||||
val highlightId: String?
|
||||
val highlightId: String,
|
||||
val libraryItemId: String
|
||||
) {
|
||||
fun asIdList() = listOf(highlightId ?: "")
|
||||
fun asIdList() = listOf(highlightId)
|
||||
}
|
||||
|
||||
suspend fun Networker.deleteHighlight(jsonString: String): Boolean {
|
||||
|
||||
@ -10,15 +10,17 @@ import app.omnivore.omnivore.persistence.entities.*
|
||||
SavedItem::class,
|
||||
SavedItemLabel::class,
|
||||
Highlight::class,
|
||||
HighlightChange::class,
|
||||
SavedItemAndSavedItemLabelCrossRef::class,
|
||||
SavedItemAndHighlightCrossRef::class
|
||||
],
|
||||
version = 15
|
||||
version = 20
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun viewerDao(): ViewerDao
|
||||
abstract fun savedItemDao(): SavedItemDao
|
||||
abstract fun highlightDao(): HighlightDao
|
||||
abstract fun highlightChangesDao(): HighlightChangesDao
|
||||
abstract fun savedItemLabelDao(): SavedItemLabelDao
|
||||
abstract fun savedItemWithLabelsAndHighlightsDao(): SavedItemWithLabelsAndHighlightsDao
|
||||
abstract fun savedItemAndSavedItemLabelCrossRefDao(): SavedItemAndSavedItemLabelCrossRefDao
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
package app.omnivore.omnivore.persistence.entities
|
||||
|
||||
import android.util.Log
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.Query
|
||||
import app.omnivore.omnivore.models.ServerSyncStatus
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
@Entity
|
||||
data class HighlightChange(
|
||||
@PrimaryKey val highlightId: String,
|
||||
val savedItemId: String,
|
||||
|
||||
val type: String,
|
||||
var annotation: String?,
|
||||
val createdAt: String?,
|
||||
val createdByMe: Boolean = true,
|
||||
val markedForDeletion: Boolean = false,
|
||||
var patch: String?,
|
||||
var prefix: String?,
|
||||
var quote: String?,
|
||||
var serverSyncStatus: Int = ServerSyncStatus.IS_SYNCED.rawValue,
|
||||
var shortId: String,
|
||||
val suffix: String?,
|
||||
val updatedAt: String?,
|
||||
val color: String?,
|
||||
val highlightPositionPercent: Double?,
|
||||
val highlightPositionAnchorIndex: Int?
|
||||
)
|
||||
|
||||
fun saveHighlightChange(dao: HighlightChangesDao, savedItemId: String, highlight: Highlight): HighlightChange {
|
||||
Log.d("sync", "saving highlight change: " + savedItemId + ", " + highlight)
|
||||
val change = HighlightChange(
|
||||
savedItemId = savedItemId,
|
||||
highlightId = highlight.highlightId,
|
||||
type = highlight.type,
|
||||
shortId = highlight.shortId,
|
||||
quote = highlight.quote,
|
||||
prefix = highlight.prefix,
|
||||
suffix = highlight.suffix,
|
||||
patch = highlight.patch,
|
||||
annotation = highlight.annotation,
|
||||
createdAt = highlight.createdAt,
|
||||
updatedAt = highlight.updatedAt,
|
||||
createdByMe = highlight.createdByMe,
|
||||
color =highlight.color,
|
||||
highlightPositionPercent = highlight.highlightPositionPercent,
|
||||
highlightPositionAnchorIndex = highlight.highlightPositionAnchorIndex,
|
||||
serverSyncStatus = highlight.serverSyncStatus
|
||||
)
|
||||
dao.insertAll(listOf(change))
|
||||
return change
|
||||
}
|
||||
|
||||
@Dao
|
||||
interface HighlightChangesDao {
|
||||
@Query("SELECT * FROM highlightChange WHERE serverSyncStatus != 0 ORDER BY updatedAt ASC")
|
||||
fun getUnSynced(): List<HighlightChange>
|
||||
|
||||
@Query("DELETE FROM highlightChange WHERE highlightId = :highlightId")
|
||||
fun deleteById(highlightId: String)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insertAll(items: List<HighlightChange>)
|
||||
}
|
||||
|
||||
@ -333,7 +333,7 @@ class WebReaderViewModel @Inject constructor(
|
||||
"deleteHighlight" -> {
|
||||
Log.d("Loggo", "receive delete highlight action: $jsonString")
|
||||
viewModelScope.launch {
|
||||
dataService.deleteHighlights(jsonString)
|
||||
dataService.deleteHighlightFromJSON(jsonString)
|
||||
}
|
||||
}
|
||||
"updateHighlight" -> {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -83,8 +83,8 @@ const App = () => {
|
||||
articleMutations={{
|
||||
createHighlightMutation: (input) =>
|
||||
mutation('createHighlight', input),
|
||||
deleteHighlightMutation: (highlightId) =>
|
||||
mutation('deleteHighlight', { highlightId }),
|
||||
deleteHighlightMutation: (libraryItemId, highlightId) =>
|
||||
mutation('deleteHighlight', { libraryItemId, highlightId }),
|
||||
mergeHighlightMutation: (input) =>
|
||||
mutation('mergeHighlight', input),
|
||||
updateHighlightMutation: (input) =>
|
||||
|
||||
@ -82,6 +82,7 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
|
||||
;(async () => {
|
||||
const success = await updateHighlightMutation({
|
||||
annotation: text,
|
||||
libraryItemId: props.targetId,
|
||||
highlightId: props.highlight?.id,
|
||||
})
|
||||
if (success) {
|
||||
|
||||
@ -52,6 +52,7 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
|
||||
;(async () => {
|
||||
const success = await updateHighlightMutation({
|
||||
annotation: text,
|
||||
libraryItemId: props.targetId,
|
||||
highlightId: props.highlight?.id,
|
||||
})
|
||||
if (success) {
|
||||
|
||||
@ -16,6 +16,7 @@ type HighlightNoteModalProps = {
|
||||
author: string
|
||||
title: string
|
||||
highlight?: Highlight
|
||||
libraryItemId: string
|
||||
onUpdate: (updatedHighlight: Highlight) => void
|
||||
onOpenChange: (open: boolean) => void
|
||||
createHighlightForNote?: (note?: string) => Promise<Highlight | undefined>
|
||||
@ -38,6 +39,7 @@ export function HighlightNoteModal(
|
||||
const saveNoteChanges = useCallback(async () => {
|
||||
if (noteContent != props.highlight?.annotation && props.highlight?.id) {
|
||||
const result = await updateHighlightMutation({
|
||||
libraryItemId: props.libraryItemId,
|
||||
highlightId: props.highlight?.id,
|
||||
annotation: noteContent,
|
||||
color: props.highlight?.color,
|
||||
|
||||
@ -187,7 +187,10 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
}
|
||||
|
||||
const didDeleteHighlight =
|
||||
await props.articleMutations.deleteHighlightMutation(highlightId)
|
||||
await props.articleMutations.deleteHighlightMutation(
|
||||
props.articleId,
|
||||
highlightId
|
||||
)
|
||||
|
||||
if (didDeleteHighlight) {
|
||||
removeHighlights(
|
||||
@ -222,6 +225,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
updateHighlightsCallback(highlight)
|
||||
;(async () => {
|
||||
const update = await props.articleMutations.updateHighlightMutation({
|
||||
libraryItemId: props.articleId,
|
||||
highlightId: highlight.id,
|
||||
color: color,
|
||||
})
|
||||
@ -705,6 +709,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
const annotation = event.annotation ?? ''
|
||||
|
||||
const result = await props.articleMutations.updateHighlightMutation({
|
||||
libraryItemId: props.articleId,
|
||||
highlightId: focusedHighlight.id,
|
||||
annotation: event.annotation ?? '',
|
||||
})
|
||||
@ -788,6 +793,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
||||
highlight={highlightModalAction.highlight}
|
||||
author={props.articleAuthor}
|
||||
title={props.articleTitle}
|
||||
libraryItemId={props.articleId}
|
||||
onUpdate={updateHighlightsCallback}
|
||||
onOpenChange={() =>
|
||||
setHighlightModalAction({ highlightModalAction: 'none' })
|
||||
|
||||
@ -76,6 +76,7 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
||||
(note: Highlight, text: string, startTime: Date) => {
|
||||
;(async () => {
|
||||
const result = await updateHighlightMutation({
|
||||
libraryItemId: props.item.id,
|
||||
highlightId: note.id,
|
||||
annotation: text,
|
||||
})
|
||||
@ -195,7 +196,7 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
||||
highlights
|
||||
?.filter((h) => h.type === 'NOTE')
|
||||
.forEach(async (h) => {
|
||||
const result = await deleteHighlightMutation(h.id)
|
||||
const result = await deleteHighlightMutation(props.item.id, h.id)
|
||||
if (!result) {
|
||||
showErrorToast('Error deleting note')
|
||||
}
|
||||
@ -325,6 +326,7 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
|
||||
;(async () => {
|
||||
const highlightId = showConfirmDeleteHighlightId
|
||||
const success = await deleteHighlightMutation(
|
||||
props.item.id,
|
||||
showConfirmDeleteHighlightId
|
||||
)
|
||||
mutate()
|
||||
|
||||
@ -113,7 +113,7 @@ export default function PdfArticleContainer(
|
||||
.delete(annotation)
|
||||
.then(() => {
|
||||
if (annotationId) {
|
||||
return deleteHighlightMutation(annotationId)
|
||||
return deleteHighlightMutation(props.article.id, annotationId)
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
@ -229,7 +229,7 @@ export default function PdfArticleContainer(
|
||||
}
|
||||
const annotationId = annotationOmnivoreId(annotation)
|
||||
if (annotationId) {
|
||||
await deleteHighlightMutation(annotationId)
|
||||
await deleteHighlightMutation(props.article.id, annotationId)
|
||||
}
|
||||
})
|
||||
|
||||
@ -512,7 +512,7 @@ export default function PdfArticleContainer(
|
||||
const storedId = annotationOmnivoreId(annotation)
|
||||
if (storedId == annotationId) {
|
||||
await instance.delete(annotation)
|
||||
await deleteHighlightMutation(annotationId)
|
||||
await deleteHighlightMutation(props.article.id, annotationId)
|
||||
|
||||
const highlightIdx = highlightsRef.current.findIndex((value) => {
|
||||
return value.id == annotationId
|
||||
@ -576,6 +576,7 @@ export default function PdfArticleContainer(
|
||||
{noteTarget && (
|
||||
<HighlightNoteModal
|
||||
highlight={noteTarget}
|
||||
libraryItemId={props.articleId}
|
||||
author={props.article.author ?? ''}
|
||||
title={props.article.title}
|
||||
onUpdate={(highlight: Highlight) => {
|
||||
|
||||
@ -8,7 +8,10 @@ export type ArticleMutations = {
|
||||
createHighlightMutation: (
|
||||
input: CreateHighlightInput
|
||||
) => Promise<Highlight | undefined>
|
||||
deleteHighlightMutation: (highlightId: string) => Promise<boolean>
|
||||
deleteHighlightMutation: (
|
||||
libraryItemId: string,
|
||||
highlightId: string
|
||||
) => Promise<boolean>
|
||||
mergeHighlightMutation: (
|
||||
input: MergeHighlightInput
|
||||
) => Promise<Highlight | undefined>
|
||||
|
||||
@ -2,6 +2,7 @@ import { gql } from 'graphql-request'
|
||||
import { gqlFetcher } from '../networkHelpers'
|
||||
|
||||
export async function deleteHighlightMutation(
|
||||
libraryItemId: string,
|
||||
highlightId: string
|
||||
): Promise<boolean> {
|
||||
const mutation = gql`
|
||||
|
||||
@ -3,6 +3,7 @@ import { gqlFetcher } from '../networkHelpers'
|
||||
|
||||
export type UpdateHighlightInput = {
|
||||
highlightId: string
|
||||
libraryItemId?: string
|
||||
annotation?: string
|
||||
sharedAt?: string
|
||||
color?: string
|
||||
|
||||
Reference in New Issue
Block a user