diff --git a/src/apis/index.js b/src/apis/index.js
index 7a3707bf0..08d62b425 100644
--- a/src/apis/index.js
+++ b/src/apis/index.js
@@ -24,3 +24,8 @@ export const markAllAsRead = async () => {
const currentUser = await getCurrentUser()
return apiClient.put(`/v1/users/${currentUser.id}/mark-all-as-read`)
}
+
+export const saveEnclosureProgression = async (
+ enclosureId,
+ progress, // enclosureId: number, progress: number
+) => apiClient.put(`/v1/enclosures/${enclosureId}`, { media_progression: progress })
diff --git a/src/components/Article/ArticleDetail.jsx b/src/components/Article/ArticleDetail.jsx
index 771168614..26ad0ff59 100644
--- a/src/components/Article/ArticleDetail.jsx
+++ b/src/components/Article/ArticleDetail.jsx
@@ -223,6 +223,21 @@ const ArticleDetail = forwardRef((_, ref) => {
const { id: categoryId, title: categoryTitle } = activeContent.feed.category
const { id: feedId, title: feedTitle } = activeContent.feed
+ const mediaPlayerEnclosure = activeContent.enclosures?.find(
+ (enclosure) =>
+ enclosure.url !== "" &&
+ (enclosure.mime_type.startsWith("video/") || enclosure.mime_type.startsWith("audio/")),
+ )
+ const enclosure = mediaPlayerEnclosure || null
+
+ const imageEnclosure = activeContent.enclosures?.find(
+ (enclosure) =>
+ enclosure.mime_type.toLowerCase().startsWith("image/") ||
+ /\.(jpg|jpeg|png|gif)$/i.test(enclosure.url),
+ )
+
+ const poster = imageEnclosure?.url || ""
+
// pretty footnotes
useEffect(() => {
littlefoot()
@@ -285,6 +300,7 @@ const ArticleDetail = forwardRef((_, ref) => {
"--article-width": articleWidth,
}}
>
+ {enclosure && }
{parsedHtml}
{},
onError = () => {},
}) => {
@@ -103,6 +105,7 @@ const PlyrPlayer = ({
const mediaRef = useRef(null)
const playerRef = useRef(null)
const hlsRef = useRef(null)
+ const lastSavedTimeRef = useRef(0)
useEffect(() => {
if (!src || !activeContent) {
@@ -127,6 +130,29 @@ const PlyrPlayer = ({
mediaRef.current.src = src
}
+ if (enclosure) {
+ playerRef.current.on("loadeddata", () => {
+ playerRef.current.currentTime = enclosure.media_progression
+ lastSavedTimeRef.current = enclosure.media_progression
+ })
+
+ const updateProgression = () => {
+ const { currentTime } = playerRef.current
+ saveEnclosureProgression(enclosure.id, Math.floor(currentTime))
+ lastSavedTimeRef.current = currentTime
+ }
+
+ playerRef.current.on("timeupdate", () => {
+ const { currentTime } = playerRef.current
+ if (currentTime - lastSavedTimeRef.current >= 10) {
+ updateProgression()
+ }
+ })
+
+ playerRef.current.on("pause", updateProgression)
+ playerRef.current.on("ended", updateProgression)
+ }
+
onPlayerInit(playerRef.current)
} catch (error) {
onError({ type: "init", error })
diff --git a/src/utils/images.js b/src/utils/images.js
index a094d371a..c814eb19b 100644
--- a/src/utils/images.js
+++ b/src/utils/images.js
@@ -16,12 +16,13 @@ export const parseCoverImage = (entry) => {
coverSource = video.getAttribute("poster")
isVideo = true
} else if (entry.enclosures?.[0]) {
- const firstEnclosure = entry.enclosures[0]
- const isImage =
- firstEnclosure.mime_type.toLowerCase().startsWith("image/") ||
- /\.(jpg|jpeg|png|gif)$/i.test(firstEnclosure.url)
- if (isImage) {
- coverSource = firstEnclosure.url
+ const imageEnclosure = entry.enclosures.find(
+ (enclosure) =>
+ enclosure.mime_type.toLowerCase().startsWith("image/") ||
+ /\.(jpg|jpeg|png|gif)$/i.test(enclosure.url),
+ )
+ if (imageEnclosure) {
+ coverSource = imageEnclosure.url
}
// Youtube thumbnail
isVideo = coverSource?.startsWith("https://i.ytimg.com") ?? false