mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-09-02 23:56:12 +00:00
Article header support, socket handling improvements
This commit is contained in:
parent
7d5c8347ce
commit
cce117c585
6 changed files with 102 additions and 7 deletions
|
@ -346,6 +346,13 @@ class ArticleImagesSegment extends ArticleSegment {
|
||||||
this.caption = caption;
|
this.caption = caption;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class ArticleHeaderSegment extends ArticleSegment {
|
||||||
|
constructor(content, level) {
|
||||||
|
super(3);
|
||||||
|
this.level = level;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
}
|
||||||
class ArticleNestedSegment extends ArticleSegment {
|
class ArticleNestedSegment extends ArticleSegment {
|
||||||
constructor(nested) {
|
constructor(nested) {
|
||||||
super(9);
|
super(9);
|
||||||
|
|
|
@ -101,6 +101,7 @@ open class JSArticleDetails : JSContent, IPlatformArticleDetails, IPluginSourced
|
||||||
return when(SegmentType.fromInt(obj.getOrThrow(client.config, "type", "JSArticle.Segment"))) {
|
return when(SegmentType.fromInt(obj.getOrThrow(client.config, "type", "JSArticle.Segment"))) {
|
||||||
SegmentType.TEXT -> JSTextSegment(client, obj);
|
SegmentType.TEXT -> JSTextSegment(client, obj);
|
||||||
SegmentType.IMAGES -> JSImagesSegment(client, obj);
|
SegmentType.IMAGES -> JSImagesSegment(client, obj);
|
||||||
|
SegmentType.HEADER -> JSHeaderSegment(client, obj);
|
||||||
SegmentType.NESTED -> JSNestedSegment(client, obj);
|
SegmentType.NESTED -> JSNestedSegment(client, obj);
|
||||||
else -> null;
|
else -> null;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +113,7 @@ enum class SegmentType(val value: Int) {
|
||||||
UNKNOWN(0),
|
UNKNOWN(0),
|
||||||
TEXT(1),
|
TEXT(1),
|
||||||
IMAGES(2),
|
IMAGES(2),
|
||||||
|
HEADER(3),
|
||||||
|
|
||||||
NESTED(9);
|
NESTED(9);
|
||||||
|
|
||||||
|
@ -152,6 +154,17 @@ class JSImagesSegment: IJSArticleSegment {
|
||||||
caption = obj.getOrDefault(client.config, "caption", contextName, "") ?: "";
|
caption = obj.getOrDefault(client.config, "caption", contextName, "") ?: "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class JSHeaderSegment: IJSArticleSegment {
|
||||||
|
override val type = SegmentType.HEADER;
|
||||||
|
val content: String;
|
||||||
|
val level: Int;
|
||||||
|
|
||||||
|
constructor(client: JSClient, obj: V8ValueObject) {
|
||||||
|
val contextName = "JSHeaderSegment";
|
||||||
|
content = obj.getOrDefault(client.config, "content", contextName, "") ?: "";
|
||||||
|
level = obj.getOrDefault(client.config, "level", contextName, 1) ?: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
class JSNestedSegment: IJSArticleSegment {
|
class JSNestedSegment: IJSArticleSegment {
|
||||||
override val type = SegmentType.NESTED;
|
override val type = SegmentType.NESTED;
|
||||||
val nested: IPlatformContent;
|
val nested: IPlatformContent;
|
||||||
|
|
|
@ -188,6 +188,14 @@ class V8Plugin {
|
||||||
whenNotBusy {
|
whenNotBusy {
|
||||||
synchronized(_runtimeLock) {
|
synchronized(_runtimeLock) {
|
||||||
isStopped = true;
|
isStopped = true;
|
||||||
|
|
||||||
|
//Cleanup http
|
||||||
|
for(pack in _depsPackages) {
|
||||||
|
if(pack is PackageHttp) {
|
||||||
|
pack.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_runtime?.let {
|
_runtime?.let {
|
||||||
_runtime = null;
|
_runtime = null;
|
||||||
if(!it.isClosed && !it.isDead) {
|
if(!it.isClosed && !it.isDead) {
|
||||||
|
|
|
@ -41,6 +41,9 @@ class PackageHttp: V8Package {
|
||||||
private var _batchPoolLock: Any = Any();
|
private var _batchPoolLock: Any = Any();
|
||||||
private var _batchPool: ForkJoinPool? = null;
|
private var _batchPool: ForkJoinPool? = null;
|
||||||
|
|
||||||
|
private val aliveSockets = mutableListOf<SocketResult>();
|
||||||
|
private var _cleanedUp = false;
|
||||||
|
|
||||||
|
|
||||||
constructor(plugin: V8Plugin, config: IV8PluginConfig): super(plugin) {
|
constructor(plugin: V8Plugin, config: IV8PluginConfig): super(plugin) {
|
||||||
_config = config;
|
_config = config;
|
||||||
|
@ -50,6 +53,27 @@ class PackageHttp: V8Package {
|
||||||
_packageClientAuth = PackageHttpClient(this, _clientAuth);
|
_packageClientAuth = PackageHttpClient(this, _clientAuth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun cleanup(){
|
||||||
|
Logger.w(TAG, "PackageHttp Cleaning up")
|
||||||
|
val sockets = synchronized(aliveSockets) { aliveSockets.toList() }
|
||||||
|
_cleanedUp = true;
|
||||||
|
for(socket in sockets){
|
||||||
|
try {
|
||||||
|
Logger.w(TAG, "PackageHttp Socket Cleaned Up");
|
||||||
|
socket.close(1001, "Cleanup");
|
||||||
|
}
|
||||||
|
catch(ex: Throwable) {
|
||||||
|
Logger.e(TAG, "Failed to close socket", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(sockets.size > 0) {
|
||||||
|
//Thread.sleep(100); //Give sockets a bit
|
||||||
|
}
|
||||||
|
synchronized(aliveSockets) {
|
||||||
|
aliveSockets.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Automatically adjusting threadpool dedicated per PackageHttp for batch requests.
|
Automatically adjusting threadpool dedicated per PackageHttp for batch requests.
|
||||||
|
@ -455,9 +479,16 @@ class PackageHttp: V8Package {
|
||||||
|
|
||||||
@V8Function
|
@V8Function
|
||||||
fun socket(url: String, headers: Map<String, String>? = null): SocketResult {
|
fun socket(url: String, headers: Map<String, String>? = null): SocketResult {
|
||||||
|
if(_package._cleanedUp)
|
||||||
|
throw IllegalStateException("Plugin shutdown");
|
||||||
val socketHeaders = headers?.toMutableMap() ?: HashMap();
|
val socketHeaders = headers?.toMutableMap() ?: HashMap();
|
||||||
applyDefaultHeaders(socketHeaders);
|
applyDefaultHeaders(socketHeaders);
|
||||||
return SocketResult(this, _client, url, socketHeaders);
|
val socket = SocketResult(_package, this, _client, url, socketHeaders);
|
||||||
|
Logger.w(TAG, "PackageHttp Socket opened");
|
||||||
|
synchronized(_package.aliveSockets) {
|
||||||
|
_package.aliveSockets.add(socket);
|
||||||
|
}
|
||||||
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun applyDefaultHeaders(headerMap: MutableMap<String, String>) {
|
private fun applyDefaultHeaders(headerMap: MutableMap<String, String>) {
|
||||||
|
@ -563,13 +594,15 @@ class PackageHttp: V8Package {
|
||||||
|
|
||||||
private var _listeners: V8ValueObject? = null;
|
private var _listeners: V8ValueObject? = null;
|
||||||
|
|
||||||
|
private val _package: PackageHttp;
|
||||||
private val _packageClient: PackageHttpClient;
|
private val _packageClient: PackageHttpClient;
|
||||||
private val _client: ManagedHttpClient;
|
private val _client: ManagedHttpClient;
|
||||||
private val _url: String;
|
private val _url: String;
|
||||||
private val _headers: Map<String, String>;
|
private val _headers: Map<String, String>;
|
||||||
|
|
||||||
constructor(pack: PackageHttpClient, client: ManagedHttpClient, url: String, headers: Map<String,String>) {
|
constructor(parent: PackageHttp, pack: PackageHttpClient, client: ManagedHttpClient, url: String, headers: Map<String,String>) {
|
||||||
_packageClient = pack;
|
_packageClient = pack;
|
||||||
|
_package = parent;
|
||||||
_client = client;
|
_client = client;
|
||||||
_url = url;
|
_url = url;
|
||||||
_headers = headers;
|
_headers = headers;
|
||||||
|
@ -595,7 +628,7 @@ class PackageHttp: V8Package {
|
||||||
override fun open() {
|
override fun open() {
|
||||||
Logger.i(TAG, "Websocket opened: " + _url);
|
Logger.i(TAG, "Websocket opened: " + _url);
|
||||||
_isOpen = true;
|
_isOpen = true;
|
||||||
if(hasOpen) {
|
if(hasOpen && _listeners?.isClosed != true) {
|
||||||
try {
|
try {
|
||||||
_listeners?.invokeVoid("open", arrayOf<Any>());
|
_listeners?.invokeVoid("open", arrayOf<Any>());
|
||||||
}
|
}
|
||||||
|
@ -605,7 +638,7 @@ class PackageHttp: V8Package {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun message(msg: String) {
|
override fun message(msg: String) {
|
||||||
if(hasMessage) {
|
if(hasMessage && _listeners?.isClosed != true) {
|
||||||
try {
|
try {
|
||||||
_listeners?.invokeVoid("message", msg);
|
_listeners?.invokeVoid("message", msg);
|
||||||
}
|
}
|
||||||
|
@ -613,7 +646,7 @@ class PackageHttp: V8Package {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun closing(code: Int, reason: String) {
|
override fun closing(code: Int, reason: String) {
|
||||||
if(hasClosing)
|
if(hasClosing && _listeners?.isClosed != true)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
_listeners?.invokeVoid("closing", code, reason);
|
_listeners?.invokeVoid("closing", code, reason);
|
||||||
|
@ -625,7 +658,7 @@ class PackageHttp: V8Package {
|
||||||
}
|
}
|
||||||
override fun closed(code: Int, reason: String) {
|
override fun closed(code: Int, reason: String) {
|
||||||
_isOpen = false;
|
_isOpen = false;
|
||||||
if(hasClosed) {
|
if(hasClosed && _listeners?.isClosed != true) {
|
||||||
try {
|
try {
|
||||||
_listeners?.invokeVoid("closed", code, reason);
|
_listeners?.invokeVoid("closed", code, reason);
|
||||||
}
|
}
|
||||||
|
@ -633,11 +666,15 @@ class PackageHttp: V8Package {
|
||||||
Logger.e(TAG, "Socket for [${_packageClient.parentConfig.name}] closed failed: " + ex.message, ex);
|
Logger.e(TAG, "Socket for [${_packageClient.parentConfig.name}] closed failed: " + ex.message, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Logger.w(TAG, "PackageHttp Socket removed");
|
||||||
|
synchronized(_package.aliveSockets) {
|
||||||
|
_package.aliveSockets.remove(this@SocketResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
override fun failure(exception: Throwable) {
|
override fun failure(exception: Throwable) {
|
||||||
_isOpen = false;
|
_isOpen = false;
|
||||||
Logger.e(TAG, "Websocket failure: ${exception.message} (${_url})", exception);
|
Logger.e(TAG, "Websocket failure: ${exception.message} (${_url})", exception);
|
||||||
if(hasFailure) {
|
if(hasFailure && _listeners?.isClosed != true) {
|
||||||
try {
|
try {
|
||||||
_listeners?.invokeVoid("failure", exception.message);
|
_listeners?.invokeVoid("failure", exception.message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.futo.platformplayer.fragment.mainactivity.main
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.graphics.Color
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.graphics.drawable.Animatable
|
import android.graphics.drawable.Animatable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -44,6 +45,7 @@ import com.futo.platformplayer.api.media.models.ratings.RatingLikes
|
||||||
import com.futo.platformplayer.api.media.models.video.IPlatformVideo
|
import com.futo.platformplayer.api.media.models.video.IPlatformVideo
|
||||||
import com.futo.platformplayer.api.media.models.video.SerializedPlatformVideo
|
import com.futo.platformplayer.api.media.models.video.SerializedPlatformVideo
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSArticleDetails
|
import com.futo.platformplayer.api.media.platforms.js.models.JSArticleDetails
|
||||||
|
import com.futo.platformplayer.api.media.platforms.js.models.JSHeaderSegment
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSImagesSegment
|
import com.futo.platformplayer.api.media.platforms.js.models.JSImagesSegment
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSNestedSegment
|
import com.futo.platformplayer.api.media.platforms.js.models.JSNestedSegment
|
||||||
import com.futo.platformplayer.api.media.platforms.js.models.JSTextSegment
|
import com.futo.platformplayer.api.media.platforms.js.models.JSTextSegment
|
||||||
|
@ -54,6 +56,7 @@ import com.futo.platformplayer.fixHtmlWhitespace
|
||||||
import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
|
import com.futo.platformplayer.images.GlideHelper.Companion.crossfade
|
||||||
import com.futo.platformplayer.logging.Logger
|
import com.futo.platformplayer.logging.Logger
|
||||||
import com.futo.platformplayer.setPlatformPlayerLinkMovementMethod
|
import com.futo.platformplayer.setPlatformPlayerLinkMovementMethod
|
||||||
|
import com.futo.platformplayer.sp
|
||||||
import com.futo.platformplayer.states.StateApp
|
import com.futo.platformplayer.states.StateApp
|
||||||
import com.futo.platformplayer.states.StatePlatform
|
import com.futo.platformplayer.states.StatePlatform
|
||||||
import com.futo.platformplayer.states.StatePlayer
|
import com.futo.platformplayer.states.StatePlayer
|
||||||
|
@ -480,6 +483,11 @@ class ArticleDetailFragment : MainFragment {
|
||||||
|
|
||||||
for(seg in value.segments) {
|
for(seg in value.segments) {
|
||||||
when(seg.type) {
|
when(seg.type) {
|
||||||
|
SegmentType.HEADER -> {
|
||||||
|
if(seg is JSHeaderSegment) {
|
||||||
|
_containerSegments.addView(ArticleHeaderBlock(context, seg.content, seg.level))
|
||||||
|
}
|
||||||
|
}
|
||||||
SegmentType.TEXT -> {
|
SegmentType.TEXT -> {
|
||||||
if(seg is JSTextSegment) {
|
if(seg is JSTextSegment) {
|
||||||
_containerSegments.addView(ArticleTextBlock(context, seg.content, seg.textType))
|
_containerSegments.addView(ArticleTextBlock(context, seg.content, seg.textType))
|
||||||
|
@ -690,6 +698,27 @@ class ArticleDetailFragment : MainFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ArticleHeaderBlock : LinearLayout {
|
||||||
|
constructor(context: Context?, content: String, level: Int) : super(context){
|
||||||
|
inflate(context, R.layout.view_segment_text, this);
|
||||||
|
|
||||||
|
findViewById<TextView>(R.id.text_content)?.let {
|
||||||
|
it.text = content;
|
||||||
|
|
||||||
|
val sp = when(level) {
|
||||||
|
1 -> 6.sp(resources);
|
||||||
|
2 -> 8.sp(resources);
|
||||||
|
3 -> 10.sp(resources);
|
||||||
|
4 -> 12.sp(resources);
|
||||||
|
5 -> 14.sp(resources);
|
||||||
|
else -> 6.sp(resources);
|
||||||
|
}
|
||||||
|
it.setTextColor(Color.WHITE);
|
||||||
|
it.setTypeface(Typeface.create(null, 600, false));
|
||||||
|
it.textSize = sp.toFloat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
class ArticleTextBlock : LinearLayout {
|
class ArticleTextBlock : LinearLayout {
|
||||||
constructor(context: Context?, content: String, textType: TextType) : super(context){
|
constructor(context: Context?, content: String, textType: TextType) : super(context){
|
||||||
inflate(context, R.layout.view_segment_text, this);
|
inflate(context, R.layout.view_segment_text, this);
|
||||||
|
|
|
@ -781,6 +781,7 @@ class VideoDetailView : ConstraintLayout {
|
||||||
_lastAudioSource = null;
|
_lastAudioSource = null;
|
||||||
_lastSubtitleSource = null;
|
_lastSubtitleSource = null;
|
||||||
video = null;
|
video = null;
|
||||||
|
_container_content_liveChat?.close();
|
||||||
_player.clear();
|
_player.clear();
|
||||||
cleanupPlaybackTracker();
|
cleanupPlaybackTracker();
|
||||||
Logger.i(TAG, "Keep screen on unset onClose")
|
Logger.i(TAG, "Keep screen on unset onClose")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue