mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2026-08-28 06:14:00 +02:00
Merge pull request #1869 from AndrolGenhald/reduce-data-usage
Send less data to server with progress update.
This commit is contained in:
@@ -17,6 +17,7 @@ import com.audiobookshelf.app.plugins.AbsLogger
|
|||||||
import com.audiobookshelf.app.managers.SecureStorage
|
import com.audiobookshelf.app.managers.SecureStorage
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
||||||
import com.fasterxml.jackson.core.json.JsonReadFeature
|
import com.fasterxml.jackson.core.json.JsonReadFeature
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.getcapacitor.JSArray
|
import com.getcapacitor.JSArray
|
||||||
@@ -48,7 +49,6 @@ class ApiHandler(var ctx:Context) {
|
|||||||
private var jacksonMapper = jacksonObjectMapper().enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature())
|
private var jacksonMapper = jacksonObjectMapper().enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature())
|
||||||
private var secureStorage = SecureStorage(ctx)
|
private var secureStorage = SecureStorage(ctx)
|
||||||
|
|
||||||
data class LocalSessionsSyncRequestPayload(val sessions:List<PlaybackSession>, val deviceInfo:DeviceInfo)
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
data class LocalSessionSyncResult(val id:String, val success:Boolean, val progressSynced:Boolean?, val error:String?)
|
data class LocalSessionSyncResult(val id:String, val success:Boolean, val progressSynced:Boolean?, val error:String?)
|
||||||
data class LocalSessionsSyncResponsePayload(val results:List<LocalSessionSyncResult>)
|
data class LocalSessionsSyncResponsePayload(val results:List<LocalSessionSyncResult>)
|
||||||
@@ -652,10 +652,29 @@ class ApiHandler(var ctx:Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendLocalProgressSync(playbackSession:PlaybackSession, cb: (Boolean, String?) -> Unit) {
|
private fun createPartialPlaybackSession(playbackSession: PlaybackSession): ObjectNode {
|
||||||
val payload = JSObject(jacksonMapper.writeValueAsString(playbackSession))
|
val json = jacksonMapper.createObjectNode()
|
||||||
|
json.put("id", playbackSession.id)
|
||||||
|
json.put("userId", playbackSession.userId)
|
||||||
|
json.put("libraryItemId", playbackSession.libraryItemId)
|
||||||
|
json.put("episodeId", playbackSession.episodeId)
|
||||||
|
json.put("mediaType", playbackSession.mediaType)
|
||||||
|
json.put("displayTitle", playbackSession.displayTitle)
|
||||||
|
json.put("displayAuthor", playbackSession.displayAuthor)
|
||||||
|
json.put("duration", playbackSession.duration)
|
||||||
|
json.put("playMethod", playbackSession.playMethod)
|
||||||
|
json.put("startedAt", playbackSession.startedAt)
|
||||||
|
json.put("updatedAt", playbackSession.updatedAt)
|
||||||
|
json.put("timeListening", playbackSession.timeListening)
|
||||||
|
json.put("currentTime", playbackSession.currentTime)
|
||||||
|
json.put("mediaPlayer", playbackSession.mediaPlayer)
|
||||||
|
return json
|
||||||
|
}
|
||||||
|
|
||||||
postRequest("/api/session/local", payload, null) {
|
fun sendLocalProgressSync(playbackSession:PlaybackSession, cb: (Boolean, String?) -> Unit) {
|
||||||
|
val partialSession = createPartialPlaybackSession(playbackSession)
|
||||||
|
partialSession.set<ObjectNode>("deviceInfo", jacksonMapper.valueToTree(playbackSession.deviceInfo))
|
||||||
|
postRequest("/api/session/local", JSObject(partialSession.toString()), null) {
|
||||||
if (!it.getString("error").isNullOrEmpty()) {
|
if (!it.getString("error").isNullOrEmpty()) {
|
||||||
cb(false, it.getString("error"))
|
cb(false, it.getString("error"))
|
||||||
} else {
|
} else {
|
||||||
@@ -748,10 +767,12 @@ class ApiHandler(var ctx:Context) {
|
|||||||
val deviceId = Settings.Secure.getString(ctx.contentResolver, Settings.Secure.ANDROID_ID)
|
val deviceId = Settings.Secure.getString(ctx.contentResolver, Settings.Secure.ANDROID_ID)
|
||||||
val deviceInfo = DeviceInfo(deviceId, Build.MANUFACTURER, Build.MODEL, Build.VERSION.SDK_INT, BuildConfig.VERSION_NAME)
|
val deviceInfo = DeviceInfo(deviceId, Build.MANUFACTURER, Build.MODEL, Build.VERSION.SDK_INT, BuildConfig.VERSION_NAME)
|
||||||
|
|
||||||
val payload = JSObject(jacksonMapper.writeValueAsString(LocalSessionsSyncRequestPayload(playbackSessions, deviceInfo)))
|
val json = jacksonMapper.createObjectNode();
|
||||||
|
json.putArray("sessions").addAll(playbackSessions.map(::createPartialPlaybackSession))
|
||||||
|
json.set<ObjectNode>("deviceInfo", jacksonMapper.valueToTree(deviceInfo))
|
||||||
AbsLogger.info("ApiHandler", "sendSyncLocalSessions: Sending ${playbackSessions.size} saved local playback sessions to server (${DeviceManager.serverConnectionConfigName})")
|
AbsLogger.info("ApiHandler", "sendSyncLocalSessions: Sending ${playbackSessions.size} saved local playback sessions to server (${DeviceManager.serverConnectionConfigName})")
|
||||||
|
|
||||||
postRequest("/api/session/local-all", payload, null) {
|
postRequest("/api/session/local-all", JSObject(json.toString()), null) {
|
||||||
if (!it.getString("error").isNullOrEmpty()) {
|
if (!it.getString("error").isNullOrEmpty()) {
|
||||||
AbsLogger.error("ApiHandler", "sendSyncLocalSessions: Failed to sync local sessions. (${it.getString("error")})")
|
AbsLogger.error("ApiHandler", "sendSyncLocalSessions: Failed to sync local sessions. (${it.getString("error")})")
|
||||||
cb(false, it.getString("error"))
|
cb(false, it.getString("error"))
|
||||||
|
|||||||
@@ -511,7 +511,8 @@ class ApiClient {
|
|||||||
|
|
||||||
public static func reportLocalPlaybackProgress(_ session: PlaybackSession) async -> Bool {
|
public static func reportLocalPlaybackProgress(_ session: PlaybackSession) async -> Bool {
|
||||||
return await withCheckedContinuation { continuation in
|
return await withCheckedContinuation { continuation in
|
||||||
postResourceWithTokenRefresh(endpoint: "api/session/local", parameters: session) { success in
|
let payload = PartialPlaybackSessionSyncPayload(from: session, includeDeviceInfo: true)
|
||||||
|
postResourceWithTokenRefresh(endpoint: "api/session/local", parameters: payload) { success in
|
||||||
continuation.resume(returning: success)
|
continuation.resume(returning: success)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -519,7 +520,10 @@ class ApiClient {
|
|||||||
|
|
||||||
public static func reportAllLocalPlaybackSessions(_ sessions: [PlaybackSession]) async -> Bool {
|
public static func reportAllLocalPlaybackSessions(_ sessions: [PlaybackSession]) async -> Bool {
|
||||||
return await withCheckedContinuation { continuation in
|
return await withCheckedContinuation { continuation in
|
||||||
let payload = LocalPlaybackSessionSyncAllPayload(sessions: sessions, deviceInfo: sessions.first?.deviceInfo)
|
let payload = LocalPlaybackSessionSyncAllPayload(
|
||||||
|
sessions: sessions.map { PartialPlaybackSessionSyncPayload(from: $0, includeDeviceInfo: false) },
|
||||||
|
deviceInfo: sessions.first?.deviceInfo
|
||||||
|
)
|
||||||
postResourceWithTokenRefresh(endpoint: "api/session/local-all", parameters: payload) { success in
|
postResourceWithTokenRefresh(endpoint: "api/session/local-all", parameters: payload) { success in
|
||||||
continuation.resume(returning: success)
|
continuation.resume(returning: success)
|
||||||
}
|
}
|
||||||
@@ -668,8 +672,44 @@ struct LocalMediaProgressSyncResultsPayload: Codable {
|
|||||||
var numLocalProgressUpdates: Int?
|
var numLocalProgressUpdates: Int?
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LocalPlaybackSessionSyncAllPayload: Codable {
|
struct PartialPlaybackSessionSyncPayload: Encodable {
|
||||||
var sessions: [PlaybackSession]
|
let id: String
|
||||||
|
let userId: String?
|
||||||
|
let libraryItemId: String?
|
||||||
|
let episodeId: String?
|
||||||
|
let mediaType: String
|
||||||
|
let displayTitle: String?
|
||||||
|
let displayAuthor: String?
|
||||||
|
let duration: Double
|
||||||
|
let playMethod: Int
|
||||||
|
let startedAt: Double?
|
||||||
|
let updatedAt: Double?
|
||||||
|
let timeListening: Double
|
||||||
|
let currentTime: Double
|
||||||
|
let mediaPlayer: String
|
||||||
|
let deviceInfo: [String: String?]?
|
||||||
|
|
||||||
|
init(from session: PlaybackSession, includeDeviceInfo: Bool) {
|
||||||
|
id = session.id
|
||||||
|
userId = session.userId
|
||||||
|
libraryItemId = session.libraryItemId
|
||||||
|
episodeId = session.episodeId
|
||||||
|
mediaType = session.mediaType
|
||||||
|
displayTitle = session.displayTitle
|
||||||
|
displayAuthor = session.displayAuthor
|
||||||
|
duration = session.duration
|
||||||
|
playMethod = session.playMethod
|
||||||
|
startedAt = session.startedAt
|
||||||
|
updatedAt = session.updatedAt
|
||||||
|
timeListening = session.timeListening
|
||||||
|
currentTime = session.currentTime
|
||||||
|
mediaPlayer = session.mediaPlayer
|
||||||
|
deviceInfo = includeDeviceInfo ? session.deviceInfo : nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LocalPlaybackSessionSyncAllPayload: Encodable {
|
||||||
|
var sessions: [PartialPlaybackSessionSyncPayload]
|
||||||
var deviceInfo: [String: String?]?
|
var deviceInfo: [String: String?]?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user