diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 7eecce49..776ef91f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,19 +1,19 @@ name: Bug Report description: Let us know about an unexpected error, a crash, or an incorrect behavior. -labels: ["bug", "new"] +labels: ["Bug"] body: - type: markdown attributes: value: | # Thank you for taking the time to fill out this bug report. - + The [grayjay-android](https://github.com/futo-org/grayjay-android) issue tracker is reserved for issues relating to the Grayjay Android Application For general usage questions, please see: [The Official FUTO Grayjay Zulip Channel](https://chat.futo.org/#narrow/stream/46-Grayjay) ## Filing a bug report - To fix your issues faster, we need clear reproduction cases - ideally allowing us to make it happen locally. + To fix your issues faster, we need clear reproduction cases - ideally allowing us to make it happen locally. * Please include all needed context. For example, Device, OS, Application, your Grayjay Configurations and Plugin versioning info. * if you've found out a particular series of UI interactions can introduce buggy behavior, please label those steps 1-n with markdown @@ -41,18 +41,21 @@ body: label: What plugins are you seeing the problem on? multiple: true options: - - All - - Youtube - - BiliBili (CN) - - Twitch - - Odysee - - Rumble - - Kick - - PeerTube - - Patreon - - Nebula - - SoundCloud - - Other + - "All" + - "Youtube" + - "Odysee" + - "Rumble" + - "Kick" + - "Twitch" + - "PeerTube" + - "Patreon" + - "Nebula" + - "BiliBili (CN)" + - "Bitchute" + - "SoundCloud" + - "Dailymotion" + - "Apple Podcasts" + - "Other" validations: required: true @@ -72,6 +75,17 @@ body: - label: While logged out - label: N/A + - type: dropdown + id: vpn + attributes: + label: Are you using a VPN? + multiple: false + options: + - "No" + - "Yes" + validations: + required: true + - type: textarea id: logs attributes: diff --git a/.github/ISSUE_TEMPLATE/documentation_issue.yml b/.github/ISSUE_TEMPLATE/documentation_issue.yml index b547daac..c416d012 100644 --- a/.github/ISSUE_TEMPLATE/documentation_issue.yml +++ b/.github/ISSUE_TEMPLATE/documentation_issue.yml @@ -1,13 +1,13 @@ name: Documentation Issue description: Report an issue or suggest a change in the documentation. -labels: ["documentation", "new"] +labels: ["Documentation"] body: - type: markdown attributes: value: | # Thank you for opening a documentation change request. - The [grayjay-android](https://github.com/futo-org/grayjay-android) issue tracker is reserved for issues relating to the Grayjay Android Application. Use the `Documentation` issue type to report problems with the documentation in our code repositories, inside the application, or on [https://grayjay.app](https://grayjay.app) + The [grayjay-android](https://github.com/futo-org/grayjay-android) issue tracker is reserved for issues relating to the Grayjay Android Application. Use the `Documentation` issue type to report problems with the documentation in our code repositories, inside the application, or on [https://grayjay.app](https://grayjay.app) Technical writers monitor this issue type, so report Grayjay bugs or feature requests with the `Bug report` or `Feature Request` issue types instead to get engineering attention. For general usage questions, please see: [The Official FUTO Grayjay Zulip Channel](https://chat.futo.org/#narrow/stream/46-Grayjay) diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index f079812a..ebba5241 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,6 +1,6 @@ name: Feature Request description: Suggest a new feature or other enhancement. -labels: ["enhancement", "new"] +labels: ["Enhancement"] body: - type: markdown attributes: @@ -9,8 +9,6 @@ body: The [grayjay-android](https://github.com/futo-org/grayjay-android) issue tracker is reserved for issues relating to the Grayjay Android Application - [External Contributions are closed at this time](https://github.com/tom-futo/grayjay-android/blob/master/CONTRIBUTION.md#contributing-to-core) - For discussion related to enhancements, please see: [The FUTO Grayjay Zulip Channel](https://chat.futo.org/#narrow/stream/46-Grayjay) - type: textarea @@ -55,4 +53,4 @@ body: attributes: value: | **Note:** If the submit button is disabled and you have filled out all required fields, please check that you did not forget a **Title** for the issue. - + diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml deleted file mode 100644 index 6819f02d..00000000 --- a/.github/workflows/labeler.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Issue labeler -on: - issues: - types: [ opened ] - -permissions: - contents: read - -jobs: - label-component: - runs-on: ubuntu-latest - - permissions: - # required for all workflows - issues: write - - steps: - - uses: actions/checkout@v3 - - - name: Parse issue form - uses: stefanbuck/github-issue-parser@v3 - id: issue-parser - with: - template-path: .github/ISSUE_TEMPLATE/bug_report.yml - - - name: Set labels based on plugin field - uses: redhat-plumbers-in-action/advanced-issue-labeler@v2 - with: - issue-form: ${{ steps.issue-parser.outputs.jsonString }} - section: plugin - block-list: | - None - Other - token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt index 22f7ffa2..bc606582 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/VideoDetailView.kt @@ -649,18 +649,9 @@ class VideoDetailView : ConstraintLayout { }; var hadDevice = false; - StateSync.instance.deviceUpdatedOrAdded.subscribe(this) { id, session -> - val hasDevice = StateSync.instance.hasAtLeastOneOnlineDevice(); - if(hasDevice != hadDevice) { - hadDevice = hasDevice; - fragment.lifecycleScope.launch(Dispatchers.Main) { - updateMoreButtons(); - } - } - }; - StateSync.instance.deviceRemoved.subscribe(this) { id -> - val hasDevice = StateSync.instance.hasAtLeastOneOnlineDevice(); - if(hasDevice != hadDevice) { + val devicesChanged = { id: String -> + val hasDevice = StateSync.instance.hasAuthorizedDevice(); + if (hasDevice != hadDevice) { hadDevice = hasDevice; fragment.lifecycleScope.launch(Dispatchers.Main) { updateMoreButtons(); @@ -668,6 +659,9 @@ class VideoDetailView : ConstraintLayout { } } + StateSync.instance.deviceUpdatedOrAdded.subscribe(this) { id, _ -> devicesChanged(id) }; + StateSync.instance.deviceRemoved.subscribe(this) { id -> devicesChanged(id) }; + MediaControlReceiver.onLowerVolumeReceived.subscribe(this) { handleLowerVolume() }; MediaControlReceiver.onPlayReceived.subscribe(this) { handlePlay() }; MediaControlReceiver.onPauseReceived.subscribe(this) { handlePause() }; @@ -922,18 +916,25 @@ class VideoDetailView : ConstraintLayout { }; _slideUpOverlay?.hide(); }, - if(StateSync.instance.hasAtLeastOneOnlineDevice()) { + if (StateSync.instance.hasAuthorizedDevice()) { RoundButton(context, R.drawable.ic_device, context.getString(R.string.send_to_device), TAG_SEND_TO_DEVICE) { - val devices = StateSync.instance.getSessions(); + val devices = StateSync.instance.getAuthorizedSessions(); val videoToSend = video ?: return@RoundButton; if(devices.size > 1) { //not implemented - } - else if(devices.size == 1){ + } else if(devices.size == 1){ val device = devices.first(); + Logger.i(TAG, "Send to device? (public key: ${device.remotePublicKey}): " + videoToSend.url) UIDialogs.showConfirmationDialog(context, "Would you like to open\n[${videoToSend.name}]\non ${device.remotePublicKey}" , { + Logger.i(TAG, "Send to device confirmed (public key: ${device.remotePublicKey}): " + videoToSend.url) + fragment.lifecycleScope.launch(Dispatchers.IO) { - device.sendJsonData(GJSyncOpcodes.sendToDevices, SendToDevicePackage(videoToSend.url, (lastPositionMilliseconds/1000).toInt())); + try { + device.sendJsonData(GJSyncOpcodes.sendToDevices, SendToDevicePackage(videoToSend.url, (lastPositionMilliseconds / 1000).toInt())) + Logger.i(TAG, "Send to device packet sent (public key: ${device.remotePublicKey}): " + videoToSend.url) + } catch (e: Throwable) { + Logger.e(TAG, "Send to device packet failed to send", e) + } } }) } diff --git a/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt b/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt index 8b4b5847..87e8f051 100644 --- a/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt +++ b/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt @@ -13,16 +13,15 @@ import com.futo.platformplayer.api.media.models.streams.IVideoSourceDescriptor import com.futo.platformplayer.api.media.models.streams.VideoUnMuxedSourceDescriptor import com.futo.platformplayer.api.media.models.streams.sources.IAudioSource import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlSource -import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlWidevineSource import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestAudioSource import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource +import com.futo.platformplayer.api.media.models.streams.sources.IWidevineSource import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails import com.futo.platformplayer.api.media.platforms.js.models.sources.JSAudioUrlRangeSource import com.futo.platformplayer.api.media.platforms.js.models.sources.JSDashManifestRawAudioSource import com.futo.platformplayer.api.media.platforms.js.models.sources.JSDashManifestRawSource -import com.futo.platformplayer.api.media.platforms.js.models.sources.JSSource import com.futo.platformplayer.api.media.platforms.js.models.sources.JSVideoUrlRangeSource import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.others.Language @@ -47,8 +46,8 @@ class VideoHelper { return false } - fun isDownloadable(source: IVideoSource) = source is IVideoUrlSource || source is IHLSManifestSource || source is JSDashManifestRawSource; - fun isDownloadable(source: IAudioSource) = (source is IAudioUrlSource || source is IHLSManifestAudioSource || source is JSDashManifestRawAudioSource) && source !is IAudioUrlWidevineSource + fun isDownloadable(source: IVideoSource) = (source is IVideoUrlSource || source is IHLSManifestSource || source is JSDashManifestRawSource) && source !is IWidevineSource + fun isDownloadable(source: IAudioSource) = (source is IAudioUrlSource || source is IHLSManifestAudioSource || source is JSDashManifestRawAudioSource) && source !is IWidevineSource fun selectBestVideoSource(desc: IVideoSourceDescriptor, desiredPixelCount : Int, prefContainers : Array) : IVideoSource? = selectBestVideoSource(desc.videoSources.toList(), desiredPixelCount, prefContainers); fun selectBestVideoSource(sources: Iterable, desiredPixelCount : Int, prefContainers : Array) : IVideoSource? { diff --git a/app/src/main/java/com/futo/platformplayer/states/StateHistory.kt b/app/src/main/java/com/futo/platformplayer/states/StateHistory.kt index e7e418a2..3047731d 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StateHistory.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StateHistory.kt @@ -8,6 +8,7 @@ import com.futo.platformplayer.constructs.Event2 import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.models.HistoryVideo import com.futo.platformplayer.models.ImportCache +import com.futo.platformplayer.states.StatePlaylists.Companion import com.futo.platformplayer.stores.FragmentedStorage import com.futo.platformplayer.stores.db.ManagedDBStore import com.futo.platformplayer.stores.db.types.DBHistory @@ -89,12 +90,14 @@ class StateHistory { if(isUserAction && _lastHistoryBroadcast != historyBroadcastSig) { _lastHistoryBroadcast = historyBroadcastSig; StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { - if(StateSync.instance.hasAtLeastOneOnlineDevice()) { + try { Logger.i(TAG, "SyncHistory playback broadcasted (${liveObj.name}: ${position})"); StateSync.instance.broadcastJsonData( GJSyncOpcodes.syncHistory, listOf(historyVideo) ); + } catch (e: Throwable) { + Logger.e(StatePlaylists.TAG, "Failed to broadcast sync history", e) } }; } diff --git a/app/src/main/java/com/futo/platformplayer/states/StatePlaylists.kt b/app/src/main/java/com/futo/platformplayer/states/StatePlaylists.kt index 8c8f9545..29eba44c 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StatePlaylists.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StatePlaylists.kt @@ -227,31 +227,50 @@ class StatePlaylists { private fun broadcastWatchLater(orderOnly: Boolean = false) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { - StateSync.instance.broadcastJsonData(GJSyncOpcodes.syncWatchLater, SyncWatchLaterPackage( - if(orderOnly) listOf() else getWatchLater(), - if(orderOnly) mapOf() else _watchLaterAdds.all(), - if(orderOnly) mapOf() else _watchLaterRemovals.all(), - getWatchLaterLastReorderTime().toEpochSecond(), - _watchlistOrderStore.values.toList())); + try { + StateSync.instance.broadcastJsonData( + GJSyncOpcodes.syncWatchLater, SyncWatchLaterPackage( + if (orderOnly) listOf() else getWatchLater(), + if (orderOnly) mapOf() else _watchLaterAdds.all(), + if (orderOnly) mapOf() else _watchLaterRemovals.all(), + getWatchLaterLastReorderTime().toEpochSecond(), + _watchlistOrderStore.values.toList() + ) + ); + } catch (e: Throwable) { + Logger.w(TAG, "Failed to broadcast watch later", e) + } }; } private fun broadcastWatchLaterAddition(video: SerializedPlatformVideo, time: OffsetDateTime) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { - StateSync.instance.broadcastJsonData(GJSyncOpcodes.syncWatchLater, SyncWatchLaterPackage( - listOf(video), - mapOf(Pair(video.url, time.toEpochSecond())), - mapOf(), + try { + StateSync.instance.broadcastJsonData( + GJSyncOpcodes.syncWatchLater, SyncWatchLaterPackage( + listOf(video), + mapOf(Pair(video.url, time.toEpochSecond())), + mapOf(), - )) + ) + ) + } catch (e: Throwable) { + Logger.w(TAG, "Failed to broadcast watch later addition", e) + } }; } private fun broadcastWatchLaterRemoval(url: String, time: OffsetDateTime) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { - StateSync.instance.broadcastJsonData(GJSyncOpcodes.syncWatchLater, SyncWatchLaterPackage( - listOf(), - mapOf(), - mapOf(Pair(url, time.toEpochSecond())) - )) + try { + StateSync.instance.broadcastJsonData( + GJSyncOpcodes.syncWatchLater, SyncWatchLaterPackage( + listOf(), + mapOf(), + mapOf(Pair(url, time.toEpochSecond())) + ) + ) + } catch (e: Throwable) { + Logger.w(TAG, "Failed to broadcast watch later removal", e) + } }; } @@ -300,12 +319,14 @@ class StatePlaylists { private fun broadcastSyncPlaylist(playlist: Playlist){ StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { - if(StateSync.instance.hasAtLeastOneOnlineDevice()) { + try { Logger.i(StateSubscriptionGroups.TAG, "SyncPlaylist (${playlist.name})"); StateSync.instance.broadcastJsonData( GJSyncOpcodes.syncPlaylists, SyncPlaylistsPackage(listOf(playlist), mapOf()) ); + } catch (e: Throwable) { + Logger.e(TAG, "Failed to broadcast sync playlist", e) } }; } @@ -319,12 +340,14 @@ class StatePlaylists { _playlistRemoved.setAndSave(playlist.id, OffsetDateTime.now()); StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { - if(StateSync.instance.hasAtLeastOneOnlineDevice()) { + try { Logger.i(StateSubscriptionGroups.TAG, "SyncPlaylist (${playlist.name})"); StateSync.instance.broadcastJsonData( GJSyncOpcodes.syncPlaylists, SyncPlaylistsPackage(listOf(), mapOf(Pair(playlist.id, OffsetDateTime.now().toEpochSecond()))) ); + } catch (e: Throwable) { + Logger.e(TAG, "Failed to broadcast sync playlists", e) } }; } diff --git a/app/src/main/java/com/futo/platformplayer/states/StateSubscriptionGroups.kt b/app/src/main/java/com/futo/platformplayer/states/StateSubscriptionGroups.kt index 5ca521ec..7da01216 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StateSubscriptionGroups.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StateSubscriptionGroups.kt @@ -79,12 +79,14 @@ class StateSubscriptionGroups { onGroupsChanged.emit(); if(!preventSync) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { - if(StateSync.instance.hasAtLeastOneOnlineDevice()) { + try { Logger.i(TAG, "SyncSubscriptionGroup (${subGroup.name})"); StateSync.instance.broadcastJsonData( GJSyncOpcodes.syncSubscriptionGroups, SyncSubscriptionGroupsPackage(listOf(subGroup), mapOf()) ); + } catch (e: Throwable) { + Logger.e(TAG, "Failed to broadcast update subscription group", e) } }; } @@ -98,12 +100,14 @@ class StateSubscriptionGroups { if(isUserInteraction) { _groupsRemoved.setAndSave(id, OffsetDateTime.now()); StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { - if(StateSync.instance.hasAtLeastOneOnlineDevice()) { + try { Logger.i(TAG, "SyncSubscriptionGroup delete (${group.name})"); StateSync.instance.broadcastJsonData( GJSyncOpcodes.syncSubscriptionGroups, SyncSubscriptionGroupsPackage(listOf(), mapOf(Pair(id, OffsetDateTime.now().toEpochSecond()))) ); + } catch (e: Throwable) { + Logger.e(TAG, "Failed to delete subscription group", e) } }; } diff --git a/app/src/main/java/com/futo/platformplayer/states/StateSync.kt b/app/src/main/java/com/futo/platformplayer/states/StateSync.kt index 6d47bd8f..0197b856 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StateSync.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StateSync.kt @@ -65,6 +65,12 @@ class StateSync { val deviceRemoved: Event1 = Event1() val deviceUpdatedOrAdded: Event2 = Event2() + fun hasAuthorizedDevice(): Boolean { + synchronized(_sessions) { + return _sessions.any{ it.value.connected && it.value.isAuthorized }; + } + } + fun start() { if (_started) { Logger.i(TAG, "Already started.") @@ -216,6 +222,11 @@ class StateSync { return _sessions.values.toList() }; } + fun getAuthorizedSessions(): List { + return synchronized(_sessions) { + return _sessions.values.filter { it.isAuthorized }.toList() + }; + } fun getSyncSessionData(key: String): SyncSessionData { return _syncSessionData.get(key) ?: SyncSessionData(key); @@ -349,8 +360,12 @@ class StateSync { scope.launch(Dispatchers.Main) { UIDialogs.showConfirmationDialog(activity, "Allow connection from ${remotePublicKey}?", action = { scope.launch(Dispatchers.IO) { - session!!.authorize(s) - Logger.i(TAG, "Connection authorized for ${remotePublicKey} by confirmation") + try { + session!!.authorize(s) + Logger.i(TAG, "Connection authorized for $remotePublicKey by confirmation") + } catch (e: Throwable) { + Logger.e(TAG, "Failed to send authorize", e) + } } }, cancelAction = { scope.launch(Dispatchers.IO) { @@ -404,11 +419,9 @@ class StateSync { broadcast(opcode, subOpcode, data.toByteArray(Charsets.UTF_8)); } fun broadcast(opcode: UByte, subOpcode: UByte, data: ByteArray) { - for(session in getSessions()) { + for(session in getAuthorizedSessions()) { try { - if (session.isAuthorized && session.connected) { - session.send(opcode, subOpcode, data); - } + session.send(opcode, subOpcode, data); } catch(ex: Exception) { Logger.w(TAG, "Failed to broadcast (opcode = ${opcode}, subOpcode = ${subOpcode}) to ${session.remotePublicKey}: ${ex.message}}", ex); @@ -450,17 +463,6 @@ class StateSync { return session } - fun hasAtLeastOneDevice(): Boolean { - synchronized(_authorizedDevices) { - return _authorizedDevices.values.isNotEmpty() - } - } - fun hasAtLeastOneOnlineDevice(): Boolean { - synchronized(_sessions) { - return _sessions.any{ it.value.connected && it.value.isAuthorized }; - } - } - fun getAll(): List { synchronized(_authorizedDevices) { return _authorizedDevices.values.toList() diff --git a/app/src/main/java/com/futo/platformplayer/sync/internal/SyncSession.kt b/app/src/main/java/com/futo/platformplayer/sync/internal/SyncSession.kt index 0fb69734..6281ca23 100644 --- a/app/src/main/java/com/futo/platformplayer/sync/internal/SyncSession.kt +++ b/app/src/main/java/com/futo/platformplayer/sync/internal/SyncSession.kt @@ -398,7 +398,6 @@ class SyncSession : IAuthorizable { } } - inline fun sendJsonData(subOpcode: UByte, data: T) { send(Opcode.DATA.value, subOpcode, Json.encodeToString(data)); } @@ -409,12 +408,29 @@ class SyncSession : IAuthorizable { send(opcode, subOpcode, data.toByteArray(Charsets.UTF_8)); } fun send(opcode: UByte, subOpcode: UByte, data: ByteArray) { - val sock = _socketSessions.firstOrNull(); - if(sock != null){ - sock.send(opcode, subOpcode, ByteBuffer.wrap(data)); + val socketSessions = synchronized(_socketSessions) { + _socketSessions.toList() + } + + if (socketSessions.isEmpty()) { + Logger.v(TAG, "Packet was not sent (opcode = ${opcode}, subOpcode = ${subOpcode}) due to no connected sockets") + return + } + + var sent = false + for (socketSession in socketSessions) { + try { + socketSession.send(opcode, subOpcode, ByteBuffer.wrap(data)) + sent = true + break + } catch (e: Throwable) { + Logger.w(TAG, "Packet failed to send (opcode = ${opcode}, subOpcode = ${subOpcode})", e) + } + } + + if (!sent) { + throw Exception("Packet was not sent (opcode = ${opcode}, subOpcode = ${subOpcode}) due to send errors and no remaining candidates") } - else - throw IllegalStateException("Session has no active sockets"); } private companion object { diff --git a/app/src/main/java/com/futo/platformplayer/sync/internal/SyncSocketSession.kt b/app/src/main/java/com/futo/platformplayer/sync/internal/SyncSocketSession.kt index 585f9562..4a1def91 100644 --- a/app/src/main/java/com/futo/platformplayer/sync/internal/SyncSocketSession.kt +++ b/app/src/main/java/com/futo/platformplayer/sync/internal/SyncSocketSession.kt @@ -300,6 +300,8 @@ class SyncSocketSession { } private fun handlePacket(opcode: UByte, subOpcode: UByte, data: ByteBuffer) { + Logger.i(TAG, "Handle packet (opcode = ${opcode}, subOpcode = ${subOpcode})") + when (opcode) { Opcode.PING.value -> { send(Opcode.PONG.value) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3b55bfcd..fa903f2f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -400,7 +400,7 @@ Allow video to go underneath the screen cutout in full screen.\nMay require restart Enable autoplay by default Autoplay will be enabled by default whenever you watch a video - Allow full-screen portrait + Allow full-screen portrait when watching horizontal videos Delete from WatchLater when watched After you leave a video that you mostly watched, it will be removed from watch later. Switch to Audio in Background diff --git a/app/src/stable/assets/sources/bilibili b/app/src/stable/assets/sources/bilibili index 76431661..72d29773 160000 --- a/app/src/stable/assets/sources/bilibili +++ b/app/src/stable/assets/sources/bilibili @@ -1 +1 @@ -Subproject commit 764316618b245d184b948bfe109447f649f12618 +Subproject commit 72d297735a267427e0839ff328dae08b1143d961 diff --git a/app/src/unstable/assets/sources/bilibili b/app/src/unstable/assets/sources/bilibili index 76431661..72d29773 160000 --- a/app/src/unstable/assets/sources/bilibili +++ b/app/src/unstable/assets/sources/bilibili @@ -1 +1 @@ -Subproject commit 764316618b245d184b948bfe109447f649f12618 +Subproject commit 72d297735a267427e0839ff328dae08b1143d961