Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CXAN-464 Add mentions related models and APIs #627

Merged
merged 6 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
package com.vimeo.networking2.config

import com.squareup.moshi.Moshi
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter
import com.vimeo.networking2.internal.ErrorHandlingCallAdapterFactory
import com.vimeo.networking2.internal.adapters.Iso8601NoMillisAdapter
import com.vimeo.networking2.internal.adapters.RichTextStringJsonAdapter
import com.vimeo.networking2.internal.adapters.TimeAdapter
import com.vimeo.networking2.internal.interceptor.AcceptHeaderInterceptor
import com.vimeo.networking2.internal.interceptor.CacheControlHeaderInterceptor
Expand All @@ -36,6 +38,12 @@ import com.vimeo.networking2.internal.params.SafeObjectJsonAdapterFactory
import com.vimeo.networking2.internal.params.StringValueJsonAdapterFactory
import com.vimeo.networking2.internal.params.VimeoParametersConverterFactory
import com.vimeo.networking2.logging.VimeoLogger
import com.vimeo.networking2.richtext.Mention
import com.vimeo.networking2.richtext.RichText
import com.vimeo.networking2.richtext.RichTextContainer
import com.vimeo.networking2.richtext.RichTextType
import com.vimeo.networking2.richtext.Text
import com.vimeo.networking2.richtext.UnknownRichTextNode
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.OkHttpClient
Expand All @@ -60,6 +68,15 @@ object RetrofitSetupModule {
.add(IntValueJsonAdapterFactory())
.add(TimeAdapter())
.add(Iso8601NoMillisAdapter())
.add(RichTextStringJsonAdapter())
.add(
PolymorphicJsonAdapterFactory.of(RichText::class.java, RichText.TYPE_FIELD)
.withSubtype(RichTextContainer::class.java, RichTextType.DOC.value)
.withSubtype(RichTextContainer::class.java, RichTextType.PARAGRAPH.value)
.withSubtype(Mention::class.java, RichTextType.MENTION.value)
.withSubtype(Text::class.java, RichTextType.TEXT.value)
.withDefaultValue(UnknownRichTextNode())
)
.build()

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.vimeo.networking2.internal.adapters

import com.squareup.moshi.FromJson
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.ToJson
import com.vimeo.networking2.annotations.RichTextString
import com.vimeo.networking2.richtext.RichText

/**
* Json adapter for [RichText] properties annotated with [RichTextString].
*/
class RichTextStringJsonAdapter {

/**
* Converts JSON string rich text representation to [RichText].
*/
@FromJson
@RichTextString
fun fromJson(
jsonReader: JsonReader,
adapter: JsonAdapter<RichText>,
): RichText? = if (jsonReader.peek() == JsonReader.Token.NULL) {
jsonReader.nextNull()
} else {
adapter.fromJson(jsonReader.nextString())
}

/**
* Converts [RichText] instance to JSON string.
*/
@ToJson
fun toJson(
jsonWriter: JsonWriter,
@RichTextString value: RichText?,
adapter: JsonAdapter<RichText>,
) {
jsonWriter.value(value?.let(adapter::toJson))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,15 @@ import com.vimeo.networking2.enums.StringValue
* A [JsonAdapter] that can convert [StringValue] implementation to its JSON value.
*/
class StringValueJsonAdapter<T : StringValue>(
private val creator: (String) -> T
private val creator: (String) -> T,
) : JsonAdapter<T>() {

constructor(values: Array<T>, fallback: T? = null) : this({ value ->
values.firstOrNull { it.value == value }
?: fallback
?: error("No value matching: \"$value\". Provide fallback.")
})

override fun fromJson(reader: JsonReader): T? = if (reader.peek() == JsonReader.Token.NULL) {
reader.nextNull()
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.vimeo.networking2.enums.ScheduleType
import com.vimeo.networking2.enums.StringValue
import com.vimeo.networking2.richtext.RichTextType
import java.lang.reflect.Type

/**
Expand All @@ -34,10 +35,12 @@ import java.lang.reflect.Type
class StringValueJsonAdapterFactory : JsonAdapter.Factory {
override fun create(type: Type, annotations: MutableSet<out Annotation>, moshi: Moshi): JsonAdapter<*>? =
if (type is Class<*> && StringValue::class.java.isAssignableFrom(type)) {
if (ScheduleType::class.java.isAssignableFrom(type)) {
StringValueJsonAdapter { value -> ScheduleType.values().first { it.value == value } }
} else {
StringValueJsonAdapter.NON_READING
when {
ScheduleType::class.java.isAssignableFrom(type) ->
StringValueJsonAdapter(ScheduleType.values())
RichTextType::class.java.isAssignableFrom(type) ->
StringValueJsonAdapter(RichTextType.values(), RichTextType.UNKNOWN)
else -> StringValueJsonAdapter.NON_READING
}
} else {
null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.vimeo.networking2.annotations

import com.squareup.moshi.JsonQualifier

@Retention(AnnotationRetention.RUNTIME)
@JsonQualifier
annotation class RichTextString
11 changes: 11 additions & 0 deletions models/src/main/java/com/vimeo/networking2/Note.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package com.vimeo.networking2

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.vimeo.networking2.annotations.RichTextString
import com.vimeo.networking2.enums.asEnum
import com.vimeo.networking2.richtext.RichText
import java.util.Date

/**
Expand All @@ -17,6 +19,8 @@ import java.util.Date
* @param rawStatus The status of the note.
* @param timeCode Time code at which point in the video the note was left.
* @param coordinates Point on the video surface which note relates to.
* @param richText The content of the note in rich text format.
* @param guestName A guest name if the user is not logged in.
*/
@JsonClass(generateAdapter = true)
data class Note(
Expand Down Expand Up @@ -47,6 +51,13 @@ data class Note(

@Json(name = "coordinates")
val coordinates: Coordinates? = null,

@RichTextString
@Json(name = "richtext")
val richText: RichText? = null,

@Json(name = "name")
val guestName: String? = null,
) : AbstractComment

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.vimeo.networking2.annotations.Internal
*
* @param comments Information about the comments on this video.
* @param notes Information about the notes on this video.
* @param privateComments Information about the private comments on this video.
* @param credit Information about the users credited in this video.
* @param likes Information about the users who have liked this video.
* @param liveStats Information about this video's live stream stats.
Expand Down Expand Up @@ -37,6 +38,9 @@ data class VideoConnections(
@Json(name = "notes")
val notes: BasicConnection? = null,

@Json(name = "private_comments")
val privateComments: BasicConnection? = null,

@Json(name = "credit")
val credit: BasicConnection? = null,

Expand Down
23 changes: 23 additions & 0 deletions models/src/main/java/com/vimeo/networking2/richtext/Mention.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.vimeo.networking2.richtext

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

/**
* [RichText] node model for mentions.
*
* @param attrs The attributes of the mention.
* @param text The text this node represents.
*/
@JsonClass(generateAdapter = true)
data class Mention(
@Json(name = "attrs")
val attrs: MentionAttrs? = null,

@Json(name = "text")
val text: String? = null
) : RichText {

@Json(name = "type")
override val type: RichTextType = RichTextType.MENTION
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.vimeo.networking2.richtext

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

/**
* Attributes of [Mention] rich text node.
*
* @param label The label of the mention.
* @param userId The user id of the user this mention represents.
* @param name The name of the user this mention represents.
* @param avatar The avatar URL of the user this mention represents.
* @param email The email of the user this mention represents.
*/
@JsonClass(generateAdapter = true)
data class MentionAttrs(
@Json(name = "label")
val label: String? = null,

@Json(name = "userId")
val userId: Long? = null,

@Json(name = "name")
val name: String? = null,

@Json(name = "avatar")
val avatar: String? = null,

@Json(name = "email")
val email: String? = null,
)
18 changes: 18 additions & 0 deletions models/src/main/java/com/vimeo/networking2/richtext/RichText.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.vimeo.networking2.richtext

/**
* Interface for all models representing rich text nodes.
*/
sealed interface RichText {
/**
* The [RichTextType] of this node.
*/
val type: RichTextType?

companion object {
/**
* The name of the JSON field representing type of the rich text node.
*/
const val TYPE_FIELD = "type"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.vimeo.networking2.richtext

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

/**
* [RichText] node model that that contains other nodes.
*
* @param type The [RichTextType] of this node.
* @param content The [RichText] nodes this node contains.
*/
@JsonClass(generateAdapter = true)
data class RichTextContainer(
@Json(name = "type")
override val type: RichTextType? = null,

@Json(name = "content")
val content: List<RichText>? = null,
) : RichText
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.vimeo.networking2.richtext

import com.vimeo.networking2.enums.StringValue

/**
* Enum with types of [RichText] nodes.
*/
enum class RichTextType(override val value: String?) : StringValue {

/**
* Type of node that represents document.
*/
DOC("doc"),

/**
* Type of node that represents paragraph.
*/
PARAGRAPH("paragraph"),

/**
* Type of node that represents mention.
*/
MENTION("mention"),

/**
* Type of node that represents simple text.
*/
TEXT("text"),

/**
* Unknown node type.
*/
UNKNOWN(null),
}
19 changes: 19 additions & 0 deletions models/src/main/java/com/vimeo/networking2/richtext/Text.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.vimeo.networking2.richtext

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

/**
* [RichText] node model for simple text.
*
* @param text The text this node represents.
*/
@JsonClass(generateAdapter = true)
data class Text(
@Json(name = "text")
val text: String? = null
) : RichText {

@Json(name = "type")
override val type: RichTextType = RichTextType.TEXT
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.vimeo.networking2.richtext

/**
* The fallback [RichText] node.
*
* Appears on unknown type.
*/
class UnknownRichTextNode : RichText {
override val type: RichTextType get() = RichTextType.UNKNOWN
}
32 changes: 32 additions & 0 deletions request/src/main/java/com/vimeo/networking2/VimeoApiClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,38 @@ interface VimeoApiClient {
callback: VimeoCallback<Note>,
): VimeoRequest

/**
* Create a note on a [Video].
*
* @param uri The URI of the [Video] note endpoint or other note replies endpoint.
* @param password The optional password will be needed to note on the [Video] if it is password protected.
* @param note The note object with supplied note arguments.
* @param callback The callback which will be notified of the request completion.
*
* @return A [VimeoRequest] object to cancel API requests.
*/
fun createNote(
uri: String,
password: String?,
note: Note,
callback: VimeoCallback<Note>,
): VimeoRequest

/**
* Edit a [Note].
*
* @param uri The URI of the [Video] note endpoint or other note replies endpoint.
* @param note The note object with supplied note arguments.
* @param callback The callback which will be notified of the request completion.
*
* @return A [VimeoRequest] object to cancel API requests.
*/
fun editNote(
uri: String,
note: Note,
callback: VimeoCallback<Note>,
): VimeoRequest

/**
* Fetch the products that a consumer can purchase from Vimeo.
*
Expand Down
Loading
Loading