feat(bookmarks): location identity, origin provenance, KOReader-style labels
- Drop UNIQUE(media_item_id,user_id,title): titles are display labels shared verbatim across clients; same-title bookmarks on different pages now coexist instead of 500ing (deleting over a tombstone no longer blocks future creates with that title) - Add origin_source column recording the creating client (android/web/ koreader), set once at insert, exposed in API responses - Web reader auto-title mirrors KOReader's 'in <chapter>' convention, falling back to 'Bookmark'; adds bookmark rename in the drawer
This commit is contained in:
@@ -185,6 +185,7 @@ type MediaBookmarks struct {
|
||||
ChapterReference pgtype.Int4 `db:"chapter_reference" json:"chapter_reference"`
|
||||
Deleted pgtype.Bool `db:"deleted" json:"deleted"`
|
||||
DeletedAt pgtype.Timestamptz `db:"deleted_at" json:"deleted_at"`
|
||||
OriginSource pgtype.Text `db:"origin_source" json:"origin_source"`
|
||||
}
|
||||
|
||||
type MediaHighlights struct {
|
||||
|
||||
@@ -624,7 +624,7 @@ func (q *Queries) CreateLibrary(ctx context.Context, arg CreateLibraryParams) (L
|
||||
const CreateMediaBookmark = `-- name: CreateMediaBookmark :one
|
||||
INSERT INTO media_bookmarks (media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at
|
||||
RETURNING id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at, origin_source
|
||||
`
|
||||
|
||||
type CreateMediaBookmarkParams struct {
|
||||
@@ -670,6 +670,7 @@ func (q *Queries) CreateMediaBookmark(ctx context.Context, arg CreateMediaBookma
|
||||
&i.ChapterReference,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.OriginSource,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -680,10 +681,10 @@ INSERT INTO media_bookmarks (
|
||||
cfi_position, title, position, notes,
|
||||
percentage_location, epubcfi_location, chapter_reference,
|
||||
dedup_key, last_modified_at, last_modified_source,
|
||||
device_sync_data
|
||||
device_sync_data, origin_source
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15
|
||||
) RETURNING id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16
|
||||
) RETURNING id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at, origin_source
|
||||
`
|
||||
|
||||
type CreateMediaBookmarkFullParams struct {
|
||||
@@ -702,6 +703,7 @@ type CreateMediaBookmarkFullParams struct {
|
||||
LastModifiedAt pgtype.Timestamptz `db:"last_modified_at" json:"last_modified_at"`
|
||||
LastModifiedSource pgtype.Text `db:"last_modified_source" json:"last_modified_source"`
|
||||
DeviceSyncData []byte `db:"device_sync_data" json:"device_sync_data"`
|
||||
OriginSource pgtype.Text `db:"origin_source" json:"origin_source"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateMediaBookmarkFull(ctx context.Context, arg CreateMediaBookmarkFullParams) (MediaBookmarks, error) {
|
||||
@@ -721,6 +723,7 @@ func (q *Queries) CreateMediaBookmarkFull(ctx context.Context, arg CreateMediaBo
|
||||
arg.LastModifiedAt,
|
||||
arg.LastModifiedSource,
|
||||
arg.DeviceSyncData,
|
||||
arg.OriginSource,
|
||||
)
|
||||
var i MediaBookmarks
|
||||
err := row.Scan(
|
||||
@@ -743,6 +746,7 @@ func (q *Queries) CreateMediaBookmarkFull(ctx context.Context, arg CreateMediaBo
|
||||
&i.ChapterReference,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.OriginSource,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -4524,7 +4528,7 @@ func (q *Queries) GetLibraryWithType(ctx context.Context, id pgtype.UUID) (GetLi
|
||||
}
|
||||
|
||||
const GetMediaBookmark = `-- name: GetMediaBookmark :one
|
||||
SELECT id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at FROM media_bookmarks WHERE id = $1
|
||||
SELECT id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at, origin_source FROM media_bookmarks WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetMediaBookmark(ctx context.Context, id pgtype.UUID) (MediaBookmarks, error) {
|
||||
@@ -4550,13 +4554,14 @@ func (q *Queries) GetMediaBookmark(ctx context.Context, id pgtype.UUID) (MediaBo
|
||||
&i.ChapterReference,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.OriginSource,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetMediaBookmarkByDedupKey = `-- name: GetMediaBookmarkByDedupKey :one
|
||||
|
||||
SELECT id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at FROM media_bookmarks
|
||||
SELECT id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at, origin_source FROM media_bookmarks
|
||||
WHERE user_id = $1 AND media_item_id = $2 AND dedup_key = $3
|
||||
ORDER BY deleted ASC, deleted_at DESC NULLS LAST
|
||||
LIMIT 1
|
||||
@@ -4594,12 +4599,13 @@ func (q *Queries) GetMediaBookmarkByDedupKey(ctx context.Context, arg GetMediaBo
|
||||
&i.ChapterReference,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.OriginSource,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const GetMediaBookmarks = `-- name: GetMediaBookmarks :many
|
||||
SELECT id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at FROM media_bookmarks
|
||||
SELECT id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at, origin_source FROM media_bookmarks
|
||||
WHERE media_item_id = $1 AND user_id = $2 AND COALESCE(deleted, FALSE) = FALSE
|
||||
ORDER BY created_at DESC
|
||||
`
|
||||
@@ -4638,6 +4644,7 @@ func (q *Queries) GetMediaBookmarks(ctx context.Context, arg GetMediaBookmarksPa
|
||||
&i.ChapterReference,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.OriginSource,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -11513,7 +11520,7 @@ SET
|
||||
position = $4,
|
||||
last_modified_at = NOW()
|
||||
WHERE id = $1 AND user_id = $5
|
||||
RETURNING id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at
|
||||
RETURNING id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at, origin_source
|
||||
`
|
||||
|
||||
type UpdateMediaBookmarkParams struct {
|
||||
@@ -11553,6 +11560,7 @@ func (q *Queries) UpdateMediaBookmark(ctx context.Context, arg UpdateMediaBookma
|
||||
&i.ChapterReference,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.OriginSource,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -11575,7 +11583,7 @@ UPDATE media_bookmarks SET
|
||||
deleted = FALSE,
|
||||
deleted_at = NULL
|
||||
WHERE id = $1
|
||||
RETURNING id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at
|
||||
RETURNING id, media_item_id, user_id, page_number, chapter_number, cfi_position, title, position, notes, created_at, dedup_key, last_modified_at, last_modified_source, device_sync_data, percentage_location, epubcfi_location, chapter_reference, deleted, deleted_at, origin_source
|
||||
`
|
||||
|
||||
type UpdateMediaBookmarkForSyncParams struct {
|
||||
@@ -11631,6 +11639,7 @@ func (q *Queries) UpdateMediaBookmarkForSync(ctx context.Context, arg UpdateMedi
|
||||
&i.ChapterReference,
|
||||
&i.Deleted,
|
||||
&i.DeletedAt,
|
||||
&i.OriginSource,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -898,9 +898,9 @@ INSERT INTO media_bookmarks (
|
||||
cfi_position, title, position, notes,
|
||||
percentage_location, epubcfi_location, chapter_reference,
|
||||
dedup_key, last_modified_at, last_modified_source,
|
||||
device_sync_data
|
||||
device_sync_data, origin_source
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16
|
||||
) RETURNING *;
|
||||
|
||||
-- name: UpdateMediaBookmarkForSync :one
|
||||
|
||||
Reference in New Issue
Block a user