musora-content-services 2.117.0 → 2.117.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/src/contentTypeConfig.js +1 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +2 -0
- package/src/services/contentProgress.js +32 -5
- package/src/services/sync/repositories/base.ts +2 -2
- package/src/services/sync/repositories/content-progress.ts +0 -4
- package/src/services/sync/repositories/practices.ts +10 -2
- package/src/services/userActivity.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [2.117.2](https://github.com/railroadmedia/musora-content-services/compare/v2.117.1...v2.117.2) (2026-01-13)
|
|
6
|
+
|
|
7
|
+
### [2.117.1](https://github.com/railroadmedia/musora-content-services/compare/v2.117.0...v2.117.1) (2026-01-13)
|
|
8
|
+
|
|
5
9
|
## [2.117.0](https://github.com/railroadmedia/musora-content-services/compare/v2.116.0...v2.117.0) (2026-01-13)
|
|
6
10
|
|
|
7
11
|
|
package/package.json
CHANGED
package/src/contentTypeConfig.js
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -109,6 +109,7 @@ import {
|
|
|
109
109
|
contentStatusCompletedMany,
|
|
110
110
|
contentStatusReset,
|
|
111
111
|
contentStatusStarted,
|
|
112
|
+
flushWatchSession,
|
|
112
113
|
getAllCompleted,
|
|
113
114
|
getAllCompletedByIds,
|
|
114
115
|
getAllStarted,
|
|
@@ -568,6 +569,7 @@ declare module 'musora-content-services' {
|
|
|
568
569
|
fetchUserPracticeNotes,
|
|
569
570
|
fetchUserPractices,
|
|
570
571
|
findIncompleteLesson,
|
|
572
|
+
flushWatchSession,
|
|
571
573
|
followThread,
|
|
572
574
|
generateAuthSessionUrl,
|
|
573
575
|
generateCommentUrl,
|
package/src/index.js
CHANGED
|
@@ -113,6 +113,7 @@ import {
|
|
|
113
113
|
contentStatusCompletedMany,
|
|
114
114
|
contentStatusReset,
|
|
115
115
|
contentStatusStarted,
|
|
116
|
+
flushWatchSession,
|
|
116
117
|
getAllCompleted,
|
|
117
118
|
getAllCompletedByIds,
|
|
118
119
|
getAllStarted,
|
|
@@ -567,6 +568,7 @@ export {
|
|
|
567
568
|
fetchUserPracticeNotes,
|
|
568
569
|
fetchUserPractices,
|
|
569
570
|
findIncompleteLesson,
|
|
571
|
+
flushWatchSession,
|
|
570
572
|
followThread,
|
|
571
573
|
generateAuthSessionUrl,
|
|
572
574
|
generateCommentUrl,
|
|
@@ -10,6 +10,7 @@ import { fetchBrandsByContentIds } from './sanity.js'
|
|
|
10
10
|
const STATE_STARTED = STATE.STARTED
|
|
11
11
|
const STATE_COMPLETED = STATE.COMPLETED
|
|
12
12
|
const MAX_DEPTH = 3
|
|
13
|
+
const PUSH_INTERVAL = 30_000
|
|
13
14
|
|
|
14
15
|
export async function getProgressState(contentId, collection = null) {
|
|
15
16
|
return getById(normalizeContentId(contentId), normalizeCollection(collection), 'state', '')
|
|
@@ -414,16 +415,42 @@ export async function recordWatchSession(
|
|
|
414
415
|
contentId = normalizeContentId(contentId)
|
|
415
416
|
collection = normalizeCollection(collection)
|
|
416
417
|
|
|
418
|
+
if (!prevSession) {
|
|
419
|
+
prevSession = {
|
|
420
|
+
practiceSession: new Map(),
|
|
421
|
+
pushInterval: null
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Track practice and progress locally (no immediate push)
|
|
417
426
|
const [session] = await Promise.all([
|
|
418
|
-
trackPractice(contentId, secondsPlayed, prevSession, { instrumentId, categoryId }),
|
|
427
|
+
trackPractice(contentId, secondsPlayed, prevSession.practiceSession, { instrumentId, categoryId }),
|
|
419
428
|
trackProgress(contentId, collection, currentSeconds, mediaLengthSeconds),
|
|
420
429
|
])
|
|
421
430
|
|
|
422
|
-
|
|
431
|
+
if (!prevSession.pushInterval) {
|
|
432
|
+
prevSession.pushInterval = setInterval(() => {
|
|
433
|
+
flushWatchSession()
|
|
434
|
+
}, PUSH_INTERVAL)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
prevSession.practiceSession = session
|
|
438
|
+
|
|
439
|
+
return prevSession
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export async function flushWatchSession(sessionToFlush = null, shouldClearInterval = true) {
|
|
443
|
+
if (shouldClearInterval && sessionToFlush?.pushInterval) {
|
|
444
|
+
clearInterval(sessionToFlush.pushInterval)
|
|
445
|
+
sessionToFlush.pushInterval = null
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
db.contentProgress.requestPushUnsynced()
|
|
449
|
+
db.practices.requestPushUnsynced()
|
|
423
450
|
}
|
|
424
451
|
|
|
425
|
-
async function trackPractice(contentId, secondsPlayed,
|
|
426
|
-
const session =
|
|
452
|
+
async function trackPractice(contentId, secondsPlayed, practiceSession, details = {}) {
|
|
453
|
+
const session = practiceSession || new Map()
|
|
427
454
|
|
|
428
455
|
const secondsSinceLastUpdate = Math.ceil(secondsPlayed - (session.get(contentId) ?? 0))
|
|
429
456
|
session.set(contentId, secondsPlayed)
|
|
@@ -437,7 +464,7 @@ async function trackProgress(contentId, collection, currentSeconds, mediaLengthS
|
|
|
437
464
|
99,
|
|
438
465
|
Math.round(((currentSeconds ?? 0) / Math.max(1, mediaLengthSeconds)) * 100)
|
|
439
466
|
))
|
|
440
|
-
return saveContentProgress(contentId, collection, progress, currentSeconds)
|
|
467
|
+
return saveContentProgress(contentId, collection, progress, currentSeconds, { skipPush: true })
|
|
441
468
|
}
|
|
442
469
|
|
|
443
470
|
export async function contentStatusCompleted(contentId, collection = null) {
|
|
@@ -238,7 +238,7 @@ export default class SyncRepository<TModel extends BaseModel> {
|
|
|
238
238
|
return result
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
requestPushUnsynced() {
|
|
242
|
+
this.store.pushUnsyncedWithRetry()
|
|
243
243
|
}
|
|
244
244
|
}
|
|
@@ -220,10 +220,6 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
|
|
|
220
220
|
return this.deleteOne(ProgressRepository.generateId(contentId, collection), { skipPush })
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
async requestPushUnsynced() {
|
|
224
|
-
await this._requestPushUnsynced()
|
|
225
|
-
}
|
|
226
|
-
|
|
227
223
|
private static generateId(
|
|
228
224
|
contentId: number,
|
|
229
225
|
collection: CollectionParameter | null
|
|
@@ -18,7 +18,7 @@ export default class PracticesRepository extends SyncRepository<Practice> {
|
|
|
18
18
|
return Math.round(totalSeconds / 60)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
async trackAutoPractice(contentId: number, date: string, incrementalDurationSeconds: number) {
|
|
21
|
+
async trackAutoPractice(contentId: number, date: string, incrementalDurationSeconds: number, skipPush = true) {
|
|
22
22
|
return await this.upsertOne(PracticesRepository.generateAutoId(contentId, date), r => {
|
|
23
23
|
r._raw.id = PracticesRepository.generateAutoId(contentId, date);
|
|
24
24
|
r.auto = true;
|
|
@@ -26,7 +26,7 @@ export default class PracticesRepository extends SyncRepository<Practice> {
|
|
|
26
26
|
r.date = date;
|
|
27
27
|
|
|
28
28
|
r.duration_seconds = Math.min((r.duration_seconds || 0) + incrementalDurationSeconds, 59999);
|
|
29
|
-
})
|
|
29
|
+
}, { skipPush })
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async recordManualPractice(date: string, durationSeconds: number, details: Partial<Pick<Practice, 'title' | 'instrument_id' | 'category_id' | 'thumbnail_url'>> = {}) {
|
|
@@ -64,4 +64,12 @@ export default class PracticesRepository extends SyncRepository<Practice> {
|
|
|
64
64
|
private static generateManualId(manualId: string) {
|
|
65
65
|
return `manual:${manualId}`;
|
|
66
66
|
}
|
|
67
|
+
|
|
68
|
+
async getAutoPracticesOnDate(date: string) {
|
|
69
|
+
return await this.queryAll(
|
|
70
|
+
Q.where('date', date),
|
|
71
|
+
Q.where('auto', true),
|
|
72
|
+
Q.sortBy('created_at', 'asc')
|
|
73
|
+
)
|
|
74
|
+
}
|
|
67
75
|
}
|
|
@@ -298,7 +298,7 @@ export async function recordUserPractice(practiceDetails) {
|
|
|
298
298
|
|
|
299
299
|
export async function trackUserPractice(contentId, incSeconds) {
|
|
300
300
|
const day = new Date().toLocaleDateString('sv-SE'); // YYYY-MM-DD wall clock date in user's timezone
|
|
301
|
-
return await db.practices.trackAutoPractice(contentId, day, incSeconds);
|
|
301
|
+
return await db.practices.trackAutoPractice(contentId, day, incSeconds, { skipPush: true }); // NOTE - SKIPS PUSH
|
|
302
302
|
}
|
|
303
303
|
|
|
304
304
|
/**
|