Compare commits

...

5 Commits

Author SHA1 Message Date
Koen J 48a67e51a6 Various fixes. 2025-05-07 20:57:55 +02:00
Koen J 5052bad824 Updated submodules. 2025-05-07 15:46:07 +02:00
Koen J 5be92052bb Fixed device vanishing while still being there in the case the device is blacklisted from starting a relay. 2025-05-07 15:43:28 +02:00
Koen e20945692e Merge branch 'add-plugin-curiosity-stream' into 'master'
add Curiosity Stream plugin

See merge request videostreaming/grayjay!94
2025-05-07 13:03:35 +00:00
Stefan 191a6e2460 add Curiosity Stream plugin 2025-05-07 13:03:35 +00:00
15 changed files with 71 additions and 26 deletions
+6
View File
@@ -94,3 +94,9 @@
[submodule "app/src/unstable/assets/sources/tedtalks"]
path = app/src/unstable/assets/sources/tedtalks
url = ../plugins/tedtalks.git
[submodule "app/src/stable/assets/sources/curiositystream"]
path = app/src/stable/assets/sources/curiositystream
url = ../plugins/curiositystream.git
[submodule "app/src/unstable/assets/sources/curiositystream"]
path = app/src/unstable/assets/sources/curiositystream
url = ../plugins/curiositystream.git
@@ -9,6 +9,7 @@ import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.futo.platformplayer.R
import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.setNavigationBarColorAndIcons
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.states.StateSync
@@ -29,6 +30,16 @@ class SyncHomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (StateApp.instance.contextOrNull == null) {
Logger.w(TAG, "No main activity, restarting main.")
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
startActivity(intent)
finish()
return
}
setContentView(R.layout.activity_sync_home)
setNavigationBarColorAndIcons()
@@ -54,7 +65,6 @@ class SyncHomeActivity : AppCompatActivity() {
val view = _viewMap[publicKey]
if (!session.isAuthorized) {
if (view != null) {
_layoutDevices.removeView(view)
_viewMap.remove(publicKey)
}
return@launch
@@ -108,11 +118,12 @@ class SyncHomeActivity : AppCompatActivity() {
private fun updateDeviceView(syncDeviceView: SyncDeviceView, publicKey: String, session: SyncSession?): SyncDeviceView {
val connected = session?.connected ?: false
val authorized = session?.isAuthorized ?: false
syncDeviceView.setLinkType(session?.linkType ?: LinkType.None)
.setName(session?.displayName ?: StateSync.instance.getCachedName(publicKey) ?: publicKey)
//TODO: also display public key?
.setStatus(if (connected) "Connected" else "Disconnected")
.setStatus(if (connected && authorized) "Connected" else "Disconnected or unauthorized")
return syncDeviceView
}
@@ -530,10 +530,17 @@ class StateApp {
//Migration
Logger.i(TAG, "MainApp Started: Check [Migrations]");
migrateStores(context, listOf(
StateSubscriptions.instance.toMigrateCheck(),
StatePlaylists.instance.toMigrateCheck()
).flatten(), 0);
scopeOrNull?.launch(Dispatchers.IO) {
try {
migrateStores(context, listOf(
StateSubscriptions.instance.toMigrateCheck(),
StatePlaylists.instance.toMigrateCheck()
).flatten(), 0)
} catch (e: Throwable) {
Logger.e(TAG, "Failed to migrate stores")
}
}
if(Settings.instance.subscriptions.fetchOnAppBoot) {
scope.launch(Dispatchers.IO) {
@@ -700,15 +707,27 @@ class StateApp {
}
private fun migrateStores(context: Context, managedStores: List<ManagedStore<*>>, index: Int) {
private suspend fun migrateStores(context: Context, managedStores: List<ManagedStore<*>>, index: Int) {
if(managedStores.size <= index)
return;
val store = managedStores[index];
if(store.hasMissingReconstructions())
UIDialogs.showMigrateDialog(context, store) {
migrateStores(context, managedStores, index + 1);
};
else
if(store.hasMissingReconstructions()) {
withContext(Dispatchers.Main) {
try {
UIDialogs.showMigrateDialog(context, store) {
scopeOrNull?.launch(Dispatchers.IO) {
try {
migrateStores(context, managedStores, index + 1);
} catch (e: Throwable) {
Logger.e(TAG, "Failed to migrate store", e)
}
}
}
} catch (e: Throwable) {
Logger.e(TAG, "Failed to migrate stores", e)
}
}
} else
migrateStores(context, managedStores, index + 1);
}
@@ -401,12 +401,15 @@ class StatePlaylists {
companion object {
val TAG = "StatePlaylists";
private var _instance : StatePlaylists? = null;
private var _lockObject = Object()
val instance : StatePlaylists
get(){
if(_instance == null)
_instance = StatePlaylists();
return _instance!!;
};
get() {
synchronized(_lockObject) {
if (_instance == null)
_instance = StatePlaylists();
return _instance!!;
}
}
fun finish() {
_instance?.let {
@@ -57,6 +57,7 @@ import kotlinx.coroutines.withContext
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.io.ByteArrayInputStream
import java.net.Inet4Address
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.ServerSocket
@@ -438,7 +439,7 @@ class StateSync {
Logger.v(TAG, "Received ${connectionInfos.size} devices connection information")
for ((targetKey, connectionInfo) in connectionInfos) {
val potentialLocalAddresses = connectionInfo.ipv4Addresses.union(connectionInfo.ipv6Addresses)
val potentialLocalAddresses = connectionInfo.ipv4Addresses
.filter { it != connectionInfo.remoteIp }
if (connectionInfo.allowLocalDirect && Settings.instance.synchronization.connectLocalDirectThroughRelay) {
Thread {
@@ -1,6 +1,7 @@
package com.futo.platformplayer.stores
import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.states.StateApp
import com.futo.platformplayer.stores.v2.JsonStoreSerializer
import com.futo.platformplayer.stores.v2.ManagedStore
import com.futo.platformplayer.stores.v2.StoreSerializer
@@ -316,7 +316,7 @@ class SyncSocketSession {
val appId = messageBuffer.int.toUInt()
val pairingMessageLength = messageBuffer.int
val pairingMessage = if (pairingMessageLength > 0) ByteArray(pairingMessageLength).also { messageBuffer.get(it) } else byteArrayOf()
val mainLength = messageSize - 4 - 4 - pairingMessageLength
val mainLength = messageBuffer.remaining()
val mainMessage = ByteArray(mainLength).also { messageBuffer.get(it) }
var pairingCode: String? = null
@@ -333,7 +333,7 @@ class SyncSocketSession {
responder.readMessage(mainMessage, 0, mainLength, plaintext, 0)
val remoteKeyBytes = ByteArray(responder.remotePublicKey.publicKeyLength)
responder.remotePublicKey.getPublicKey(remoteKeyBytes, 0)
val remotePublicKey = Base64.getEncoder().encodeToString(remoteKeyBytes)
val remotePublicKey = remoteKeyBytes.toBase64()
val isAllowedToConnect = remotePublicKey != _localPublicKey && (_isHandshakeAllowed?.invoke(LinkType.Direct, this, remotePublicKey, pairingCode, appId) ?: true)
if (!isAllowedToConnect) {
+2 -1
View File
@@ -14,7 +14,8 @@
"9c87e8db-e75d-48f4-afe5-2d203d4b95c5": "sources/dailymotion/build/DailymotionConfig.json",
"e8b1ad5f-0c6d-497d-a5fa-0a785a16d902": "sources/bitchute/BitchuteConfig.json",
"89ae4889-0420-4d16-ad6c-19c776b28f99": "sources/apple-podcasts/ApplePodcastsConfig.json",
"8d029a7f-5507-4e36-8bd8-c19a3b77d383": "sources/tedtalks/TedTalksConfig.json"
"8d029a7f-5507-4e36-8bd8-c19a3b77d383": "sources/tedtalks/TedTalksConfig.json",
"273b6523-5438-44e2-9f5d-78e0325a8fd9": "sources/curiositystream/CuriosityStreamConfig.json"
},
"SOURCES_EMBEDDED_DEFAULT": [
"35ae969a-a7db-11ed-afa1-0242ac120002"
+2 -1
View File
@@ -14,7 +14,8 @@
"9c87e8db-e75d-48f4-afe5-2d203d4b95c5": "sources/dailymotion/build/DailymotionConfig.json",
"e8b1ad5f-0c6d-497d-a5fa-0a785a16d902": "sources/bitchute/BitchuteConfig.json",
"89ae4889-0420-4d16-ad6c-19c776b28f99": "sources/apple-podcasts/ApplePodcastsConfig.json",
"8d029a7f-5507-4e36-8bd8-c19a3b77d383": "sources/tedtalks/TedTalksConfig.json"
"8d029a7f-5507-4e36-8bd8-c19a3b77d383": "sources/tedtalks/TedTalksConfig.json",
"273b6523-5438-44e2-9f5d-78e0325a8fd9": "sources/curiositystream/CuriosityStreamConfig.json"
},
"SOURCES_EMBEDDED_DEFAULT": [
"35ae969a-a7db-11ed-afa1-0242ac120002"