From caa62fa5af1b888330c0f4e7a841acff7879fc43 Mon Sep 17 00:00:00 2001 From: gooday Date: Thu, 12 Mar 2020 15:09:15 +0200 Subject: [PATCH] Ultimedia added --- .../gapps/videonoapi/ui/base/BaseActivity.kt | 14 ++- .../gapps/videonoapi/ui/main/MainActivity.kt | 10 +- app/src/main/res/values/colors.xml | 4 + .../com/gapps/library/api/VideoLoadHelper.kt | 11 ++- .../com/gapps/library/api/VideoService.kt | 9 +- .../api/models/api/UltimediaVideoInfoModel.kt | 29 ++++++ .../video/ultimedia/UltimediaResponse.kt | 44 +++++++++ .../com/gapps/library/cache/VideoModelORM.kt | 2 +- .../ui/bottom_menu/BottomVideoController.kt | 93 +++++++++++++++---- ...ntent_copy.xml => ic_vna_content_copy.xml} | 0 .../main/res/layout/layout_hc_video_view.xml | 12 ++- 11 files changed, 194 insertions(+), 34 deletions(-) create mode 100644 library/src/main/java/com/gapps/library/api/models/api/UltimediaVideoInfoModel.kt create mode 100644 library/src/main/java/com/gapps/library/api/models/video/ultimedia/UltimediaResponse.kt rename library/src/main/res/drawable/{vna_ic_content_copy.xml => ic_vna_content_copy.xml} (100%) diff --git a/app/src/main/java/com/gapps/videonoapi/ui/base/BaseActivity.kt b/app/src/main/java/com/gapps/videonoapi/ui/base/BaseActivity.kt index 7a10fee..ae1c785 100644 --- a/app/src/main/java/com/gapps/videonoapi/ui/base/BaseActivity.kt +++ b/app/src/main/java/com/gapps/videonoapi/ui/base/BaseActivity.kt @@ -7,8 +7,9 @@ import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.gapps.library.api.models.video.VideoPreviewModel import com.gapps.library.ui.bottom_menu.BottomVideoController +import com.gapps.videonoapi.R -abstract class BaseActivity: AppCompatActivity() { +abstract class BaseActivity : AppCompatActivity() { protected fun showVideo(model: VideoPreviewModel) { val host = model.videoHosting @@ -31,7 +32,16 @@ abstract class BaseActivity: AppCompatActivity() { setSize(model.width, model.height) setTitle(title) setVideoUrl(initUrl) - setProgressView(TextView(this@BaseActivity).apply { text = "Loading" }) + setBackgroundColor(R.color.colorBackground) + setTextColor(R.color.colorHostName) + setTitleColor(R.color.colorVideoTitle) + setLeftButtonText(R.string.vna_close) + setRightButtonText(R.string.vna_open_in) + setRightButtonTextColor(R.color.colorVideoTitle) + setLeftButtonTextColor(R.color.colorVideoTitle) + setCenterButtonIcon(R.drawable.ic_vna_content_copy) + setCenterButtonIconTint(R.color.colorVideoTitle) + setProgressView(TextView(this@BaseActivity).apply { text = "Loading"; setTextColor(-1) }) show() } } diff --git a/app/src/main/java/com/gapps/videonoapi/ui/main/MainActivity.kt b/app/src/main/java/com/gapps/videonoapi/ui/main/MainActivity.kt index de88257..b1662d8 100644 --- a/app/src/main/java/com/gapps/videonoapi/ui/main/MainActivity.kt +++ b/app/src/main/java/com/gapps/videonoapi/ui/main/MainActivity.kt @@ -36,11 +36,11 @@ class MainActivity : BaseActivity() { "https://vzaar.com/videos/401431", "http://www.hulu.com/w/154323", "https://ustream.tv/channel/6540154", + "https://ustream.tv/recorded/101541339", "https://www.ted.com/talks/jill_bolte_taylor_my_stroke_of_insight", "https://coub.com/view/um0um0", - "https://ustream.tv/recorded/101541339", - "https://asdasdasdasd.tv/recorded/101541339", - "https://www.ultimedia.com/default/index/videogeneric/id/pzkk35/" + "https://www.ultimedia.com/default/index/videogeneric/id/pzkk35/", + "https://notAVideoHost.tv/recorded/101541339" ) override fun onCreate(savedInstanceState: Bundle?) { @@ -65,8 +65,8 @@ class MainActivity : BaseActivity() { videoService = VideoService.build { with(this@MainActivity) httpClient(okHttpClient) - enableCache(false) - enableLog(true) + enableCache(true) + enableLog(false) withCustomVideoInfoModels(UltimediaVideoInfoModel(), MyYoutubeVideoInfoModel()) } } diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index a491964..2629591 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -3,4 +3,8 @@ #008577 #00574B #D81B60 + #161627 + #AAAAE2 + #ffffff + diff --git a/library/src/main/java/com/gapps/library/api/VideoLoadHelper.kt b/library/src/main/java/com/gapps/library/api/VideoLoadHelper.kt index 06acd99..2d28821 100644 --- a/library/src/main/java/com/gapps/library/api/VideoLoadHelper.kt +++ b/library/src/main/java/com/gapps/library/api/VideoLoadHelper.kt @@ -1,6 +1,7 @@ package com.gapps.library.api import android.content.Context +import android.util.Log import com.gapps.library.api.models.api.base.VideoInfoModel import com.gapps.library.api.models.video.VideoPreviewModel import com.gapps.library.api.models.video.base.BaseVideoResponse @@ -20,7 +21,8 @@ import kotlin.coroutines.CoroutineContext internal class VideoLoadHelper( private val context: Context?, private val client: OkHttpClient, - private val isCacheEnabled: Boolean + private val isCacheEnabled: Boolean, + val isLogEnabled: Boolean ) : CoroutineScope { private val job = Job() override val coroutineContext: CoroutineContext @@ -30,6 +32,7 @@ internal class VideoLoadHelper( private var gson = GsonBuilder() .setLenient() + .setPrettyPrinting() .create() fun getVideoInfo( @@ -69,13 +72,17 @@ internal class VideoLoadHelper( try { val jsonBody = makeCallGetBody(client, finalUrl) + if (isLogEnabled) { + Log.i(VideoService.TAG, "a response from $originalUrl:\n${gson.toJson(jsonBody)}") + } + if (jsonBody == null) { onSuccess.invoke(VideoPreviewModel.error(originalUrl, "$ERROR_2 \n---> Response is null")) return@launch } - val result = fromJson(jsonBody, videoInfoModel.type) + val result = (gson.fromJson(jsonBody, videoInfoModel.type) as BaseVideoResponse) .toPreview(originalUrl, playLink, videoInfoModel.hostingName, videoId) onSuccess.invoke(result) diff --git a/library/src/main/java/com/gapps/library/api/VideoService.kt b/library/src/main/java/com/gapps/library/api/VideoService.kt index 948cd13..1d5692b 100644 --- a/library/src/main/java/com/gapps/library/api/VideoService.kt +++ b/library/src/main/java/com/gapps/library/api/VideoService.kt @@ -18,6 +18,8 @@ class VideoService( private val customModels: List> ) { companion object { + const val TAG = "VideoService" + val videoInfoModelsList = mutableListOf( CoubVideoInfoModel(), DailymotionVideoInfoModel(), @@ -30,7 +32,8 @@ class VideoService( VzaarVideoInfoModel(), WistiaVideoInfoModel(), YoutubeMusicVideoInfoModel(), - YoutubeVideoInfoModel() + YoutubeVideoInfoModel(), + UltimediaVideoInfoModel() ) inline fun build(block: Builder.() -> Unit) = Builder().apply(block).build() @@ -51,7 +54,7 @@ class VideoService( videoInfoModelsList.addAll(customModels) } - private val videoHelper = VideoLoadHelper(context, client, isCacheEnabled) + private val videoHelper = VideoLoadHelper(context, client, isCacheEnabled, isLogEnabled) fun loadVideoPreview( url: String, @@ -59,7 +62,7 @@ class VideoService( onError: ((String, String) -> Unit)? = null ) { if (isLogEnabled) { - Log.i("VideoService", "loading url: $url") + Log.i(TAG, "loading url: $url") } val callback: (VideoPreviewModel) -> Unit = { model: VideoPreviewModel -> diff --git a/library/src/main/java/com/gapps/library/api/models/api/UltimediaVideoInfoModel.kt b/library/src/main/java/com/gapps/library/api/models/api/UltimediaVideoInfoModel.kt new file mode 100644 index 0000000..7a9217a --- /dev/null +++ b/library/src/main/java/com/gapps/library/api/models/api/UltimediaVideoInfoModel.kt @@ -0,0 +1,29 @@ +package com.gapps.library.api.models.api + +import com.gapps.library.api.FORMAT +import com.gapps.library.api.FORMAT_JSON +import com.gapps.library.api.URL +import com.gapps.library.api.models.api.base.VideoInfoModel +import com.gapps.library.api.models.video.ultimedia.UltimediaResponse + +class UltimediaVideoInfoModel: VideoInfoModel() { + override val baseUrl: String + get() = "https://www.ultimedia.com" + //https://regex101.com/r/2AsrOc/1 + override val pattern: String + get() = "(?:http[s]?:\\/\\/)?(?:www)?\\.?ultimedia\\.com\\/(?:deliver|default|api)\\/.*\\/([_a-zA-Z0-9]+)\\S*" + override val idPattern: String + get() = pattern + override val type: Class + get() = UltimediaResponse::class.java + override val hostingName: String + get() = "Ultimedia" + + override fun getInfoUrl(incomingUrl: String?): String? { + return "$baseUrl/api/search/oembed?$FORMAT=$FORMAT_JSON&$URL=$incomingUrl" + } + + override fun getPlayLink(videoId: String): String { + return "https://www.ultimedia.com/deliver/generic/iframe/src/$videoId/" + } +} \ No newline at end of file diff --git a/library/src/main/java/com/gapps/library/api/models/video/ultimedia/UltimediaResponse.kt b/library/src/main/java/com/gapps/library/api/models/video/ultimedia/UltimediaResponse.kt new file mode 100644 index 0000000..9919e8e --- /dev/null +++ b/library/src/main/java/com/gapps/library/api/models/video/ultimedia/UltimediaResponse.kt @@ -0,0 +1,44 @@ +package com.gapps.library.api.models.video.ultimedia + + +import com.gapps.library.api.models.video.VideoPreviewModel +import com.gapps.library.api.models.video.base.BaseVideoResponse +import com.google.gson.annotations.SerializedName + +data class UltimediaResponse( + @SerializedName("version") + val version: String = "", + @SerializedName("type") + val type: String = "", + @SerializedName("title") + val title: String = "", + @SerializedName("description") + val description: String = "", + @SerializedName("html") + val html: String = "", + @SerializedName("width") + val width: String = "", + @SerializedName("height") + val height: String = "", + @SerializedName("thumbnail_url") + val thumbnailUrl: String = "", + @SerializedName("thumbnail_width") + val thumbnailWidth: String = "", + @SerializedName("thumbnail_height") + val thumbnailHeight: String = "", + @SerializedName("provider_name") + val providerName: String = "", + @SerializedName("provider_url") + val providerUrl: String = "", + @SerializedName("author_name") + val authorName: String = "" +): BaseVideoResponse{ + override fun toPreview(url: String?, linkToPlay: String, hostingName: String, videoId: String): VideoPreviewModel { + return VideoPreviewModel(url, linkToPlay, hostingName, videoId).apply { + this.thumbnailUrl = this@UltimediaResponse.thumbnailUrl + this.videoTitle = this@UltimediaResponse.authorName + this.width = this@UltimediaResponse.width.toInt() + this.height = this@UltimediaResponse.height.toInt() + } + } +} \ No newline at end of file diff --git a/library/src/main/java/com/gapps/library/cache/VideoModelORM.kt b/library/src/main/java/com/gapps/library/cache/VideoModelORM.kt index b8af03e..1ce7598 100644 --- a/library/src/main/java/com/gapps/library/cache/VideoModelORM.kt +++ b/library/src/main/java/com/gapps/library/cache/VideoModelORM.kt @@ -9,7 +9,7 @@ import com.gapps.library.utils.toMD5 import java.util.* -private const val TAG = "VideoModelsORM" +private const val TAG = "VideoServiceORM" private const val TABLE_NAME = "video_model" private const val COMMA_SEP = ", " diff --git a/library/src/main/java/com/gapps/library/ui/bottom_menu/BottomVideoController.kt b/library/src/main/java/com/gapps/library/ui/bottom_menu/BottomVideoController.kt index c2552a1..f7e5804 100644 --- a/library/src/main/java/com/gapps/library/ui/bottom_menu/BottomVideoController.kt +++ b/library/src/main/java/com/gapps/library/ui/bottom_menu/BottomVideoController.kt @@ -20,6 +20,8 @@ import android.widget.FrameLayout import android.widget.LinearLayout import android.widget.TextView import androidx.annotation.ColorRes +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes import androidx.appcompat.widget.AppCompatImageButton import androidx.core.content.ContextCompat import androidx.core.graphics.ColorUtils @@ -39,7 +41,14 @@ class BottomVideoController private constructor( private val hostText: String?, private val playLink: String?, private val size: Pair?, - private val progressView: View? + private val progressView: View?, + private val isBottomControlPanelVisible: Boolean, + @DrawableRes private val centerButtonIcon: Int, + @StringRes private val leftButtonText: Int, + @StringRes private val rightButtonText: Int, + @ColorRes private val leftButtonTextColor: Int, + @ColorRes private val rightButtonTextColor: Int, + @ColorRes private val centerButtonIconTint: Int ) { companion object { var isVisible = false @@ -58,11 +67,18 @@ class BottomVideoController private constructor( builder.hostText, builder.playLink, builder.size, - builder.progressView + builder.progressView, + builder.isBottomControlPanelVisible, + builder.centerButtonIcon, + builder.leftButtonText, + builder.rightButtonText, + builder.leftButtonTextColor, + builder.rightButtonTextColor, + builder.centerButtonIconTint ) @SuppressLint("InflateParams", "SetJavaScriptEnabled") - fun showBottomPopupMenu() { + fun show() { if (isVisible) { return } @@ -81,10 +97,13 @@ class BottomVideoController private constructor( val progressBarContainer = menuView.findViewById(R.id.vna_video_progress_container) val title = menuView.findViewById(R.id.vna_text_url_preview_title) val videoServiceType = menuView.findViewById(R.id.vna_player_type) - val closeVideo = menuView.findViewById(R.id.vna_close_video) - val openVideoIn = menuView.findViewById(R.id.vna_open_video_in) - val copyLink = menuView.findViewById(R.id.vna_copy_video_link) + val leftButton = menuView.findViewById(R.id.vna_left_button) + val rightButton = menuView.findViewById(R.id.vna_right_button) + val centerButton = menuView.findViewById(R.id.vna_center_button) val controlPanelOutline = menuView.findViewById(R.id.vna_control_panel_outline) + val controlPanel = menuView.findViewById(R.id.vna_bottom_control_panel) + + controlPanel.visibility = if (isBottomControlPanelVisible) View.VISIBLE else View.GONE title.apply { this.setTextColor(ContextCompat.getColor(this.context, titleColor)) @@ -98,16 +117,18 @@ class BottomVideoController private constructor( this.text = hostText } - closeVideo.apply { - this.setTextColor(textColorInt) + leftButton.apply { + this.setTextColor(ContextCompat.getColor(context, leftButtonTextColor)) + this.setText(leftButtonText) this.setOnClickListener { bottomSheetDialog.dismiss() } } - openVideoIn.apply { - this.setTextColor(textColorInt) + rightButton.apply { + this.setTextColor(ContextCompat.getColor(context, rightButtonTextColor)) + this.setText(rightButtonText) this.setOnClickListener { listener?.openLinkIn(url) @@ -116,16 +137,17 @@ class BottomVideoController private constructor( } } - copyLink.apply { - setOnClickListener { + centerButton.apply { + this.setImageResource(centerButtonIcon) + this.setColorFilter(ContextCompat.getColor(context, centerButtonIconTint), PorterDuff.Mode.SRC_IN) + + this.setOnClickListener { listener?.copyLink(url) } - - this.setColorFilter(textColorInt, PorterDuff.Mode.SRC_IN) } menuContainer.apply { - setBackgroundColor(ContextCompat.getColor(this.context, backgroundColor)) + this.setBackgroundColor(ContextCompat.getColor(this.context, backgroundColor)) } val outlineColor = ColorUtils.setAlphaComponent(textColorInt, (255 * .1).toInt()) @@ -147,6 +169,8 @@ class BottomVideoController private constructor( } videoView.apply { + setBackgroundColor(ContextCompat.getColor(this.context, backgroundColor)) + layoutParams.apply { this.width = videoViewWidth this.height = videoViewHeight @@ -227,6 +251,9 @@ class BottomVideoController private constructor( var backgroundColor = android.R.color.white private set + var isBottomControlPanelVisible: Boolean = true + private set + var url: String? = null private set @@ -245,6 +272,30 @@ class BottomVideoController private constructor( var progressView: View? = null private set + @DrawableRes + var centerButtonIcon = R.drawable.ic_vna_content_copy + private set + + @ColorRes + var centerButtonIconTint = R.color.vna_color_video_title_text + private set + + @ColorRes + var rightButtonTextColor = R.color.vna_color_video_title_text + private set + + @ColorRes + var leftButtonTextColor = R.color.vna_color_video_title_text + private set + + @StringRes + var rightButtonText = R.string.vna_open_in + private set + + @StringRes + var leftButtonText = R.string.vna_close + private set + fun setVideoUrl(url: String?) = apply { this.url = url } fun setTitle(title: String?) = apply { this.titleText = title } fun setHostText(host: String?) = apply { this.hostText = host } @@ -253,12 +304,22 @@ class BottomVideoController private constructor( fun setProgressView(view: View) = apply { this.progressView = view } fun setListener(listener: Listener) = apply { this.listener = listener } + + //Theme fun setTitleColor(@ColorRes color: Int) = apply { this.titleColor = color } fun setTextColor(@ColorRes color: Int) = apply { this.textColor = color } + fun setLeftButtonTextColor(@ColorRes color: Int) = apply { this.leftButtonTextColor = color } + fun setRightButtonTextColor(@ColorRes color: Int) = apply { this.rightButtonTextColor = color } fun setBackgroundColor(@ColorRes color: Int) = apply { this.backgroundColor = color } + fun setCenterButtonIconTint(@ColorRes color: Int) = apply { this.centerButtonIconTint = color } + + fun setCenterButtonIcon(@DrawableRes resource: Int) = apply { this.centerButtonIcon = resource } + fun setLeftButtonText(@StringRes resource: Int) = apply { this.leftButtonText = resource } + fun setRightButtonText(@StringRes resource: Int) = apply { this.rightButtonText = resource } + fun setBottomControlPanelVisible(isVisible: Boolean) = apply { this.isBottomControlPanelVisible = isVisible } fun build() = BottomVideoController(this) - fun show() = BottomVideoController(this).showBottomPopupMenu() + fun show() = BottomVideoController(this).show() } } \ No newline at end of file diff --git a/library/src/main/res/drawable/vna_ic_content_copy.xml b/library/src/main/res/drawable/ic_vna_content_copy.xml similarity index 100% rename from library/src/main/res/drawable/vna_ic_content_copy.xml rename to library/src/main/res/drawable/ic_vna_content_copy.xml diff --git a/library/src/main/res/layout/layout_hc_video_view.xml b/library/src/main/res/layout/layout_hc_video_view.xml index 8d3acfc..689a7f7 100644 --- a/library/src/main/res/layout/layout_hc_video_view.xml +++ b/library/src/main/res/layout/layout_hc_video_view.xml @@ -67,9 +67,11 @@ + android:orientation="vertical" + > + app:srcCompat="@drawable/ic_vna_content_copy" />