Merge branch 'master' into 'landscape'

# Conflicts:
#   app/src/main/res/layout/activity_polycentric_create_profile.xml
This commit is contained in:
Kai DeLorenzo 2024-11-18 15:03:06 +00:00
commit dc76152166
86 changed files with 353 additions and 102 deletions

View file

@ -49,9 +49,23 @@ We encourage developers to write their own plugins. Please refer to the "Getting
## Contributing to Core ## Contributing to Core
**We are currently not accepting contributions to the core.**
The core is currently licensed under the FUTO Temporary License (FTL). The licensing and ownership of contributions to the core are complex topics that we are still working on. We'll update these guidelines when we have more clarity. ### License
The core is currently licensed under the [Source First License 1.1](./LICENSE.md). All contributors have to sign FUTO Individual Contributor License Agreement before contributions can be accepted. You can read more about it at [https://cla.futo.org/](https://cla.futo.org/).
### How to Contribute
1. Fork the core repository.
2. Clone your fork.
3. Make your changes.
4. Commit and push your changes.
5. Open a pull request.
### Guidelines
- Ensure your code adheres to the existing style.
- Include documentation and unit tests (where applicable).
--- ---

View file

@ -144,7 +144,6 @@ class Settings : FragmentedStorageFileJson() {
fun import() { fun import() {
val act = SettingsActivity.getActivity() ?: return; val act = SettingsActivity.getActivity() ?: return;
val intent = MainActivity.getImportOptionsIntent(act); val intent = MainActivity.getImportOptionsIntent(act);
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK;
act.startActivity(intent); act.startActivity(intent);
} }
@ -906,7 +905,7 @@ class Settings : FragmentedStorageFileJson() {
var enabled: Boolean = true; var enabled: Boolean = true;
@FormField(R.string.broadcast, FieldForm.TOGGLE, R.string.broadcast_description, 1) @FormField(R.string.broadcast, FieldForm.TOGGLE, R.string.broadcast_description, 1)
var broadcast: Boolean = true; var broadcast: Boolean = false;
@FormField(R.string.connect_discovered, FieldForm.TOGGLE, R.string.connect_discovered_description, 2) @FormField(R.string.connect_discovered, FieldForm.TOGGLE, R.string.connect_discovered_description, 2)
var connectDiscovered: Boolean = true; var connectDiscovered: Boolean = true;

View file

@ -1233,28 +1233,28 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
val sourcesIntent = Intent(context, MainActivity::class.java); val sourcesIntent = Intent(context, MainActivity::class.java);
sourcesIntent.action = "TAB"; sourcesIntent.action = "TAB";
sourcesIntent.putExtra("TAB", tab); sourcesIntent.putExtra("TAB", tab);
sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
return sourcesIntent; return sourcesIntent;
} }
fun getVideoIntent(context: Context, videoUrl: String) : Intent { fun getVideoIntent(context: Context, videoUrl: String) : Intent {
val sourcesIntent = Intent(context, MainActivity::class.java); val sourcesIntent = Intent(context, MainActivity::class.java);
sourcesIntent.action = "VIDEO"; sourcesIntent.action = "VIDEO";
sourcesIntent.putExtra("VIDEO", videoUrl); sourcesIntent.putExtra("VIDEO", videoUrl);
sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
return sourcesIntent; return sourcesIntent;
} }
fun getActionIntent(context: Context, action: String) : Intent { fun getActionIntent(context: Context, action: String) : Intent {
val sourcesIntent = Intent(context, MainActivity::class.java); val sourcesIntent = Intent(context, MainActivity::class.java);
sourcesIntent.action = "ACTION"; sourcesIntent.action = "ACTION";
sourcesIntent.putExtra("ACTION", action); sourcesIntent.putExtra("ACTION", action);
sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
return sourcesIntent; return sourcesIntent;
} }
fun getImportOptionsIntent(context: Context): Intent { fun getImportOptionsIntent(context: Context): Intent {
val sourcesIntent = Intent(context, MainActivity::class.java); val sourcesIntent = Intent(context, MainActivity::class.java);
sourcesIntent.action = "IMPORT_OPTIONS"; sourcesIntent.action = "IMPORT_OPTIONS";
sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); sourcesIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
return sourcesIntent; return sourcesIntent;
} }
} }

View file

@ -933,7 +933,7 @@ class VideoDetailView : ConstraintLayout {
val device = devices.first(); val device = devices.first();
UIDialogs.showConfirmationDialog(context, "Would you like to open\n[${videoToSend.name}]\non ${device.remotePublicKey}" , { UIDialogs.showConfirmationDialog(context, "Would you like to open\n[${videoToSend.name}]\non ${device.remotePublicKey}" , {
fragment.lifecycleScope.launch(Dispatchers.IO) { fragment.lifecycleScope.launch(Dispatchers.IO) {
device.sendJson(GJSyncOpcodes.sendToDevices, SendToDevicePackage(videoToSend.url, (lastPositionMilliseconds/1000).toInt())); device.sendJsonData(GJSyncOpcodes.sendToDevices, SendToDevicePackage(videoToSend.url, (lastPositionMilliseconds/1000).toInt()));
} }
}) })
} }
@ -1759,7 +1759,7 @@ class VideoDetailView : ConstraintLayout {
}); });
else else
_player.setArtwork(null); _player.setArtwork(null);
_player.setSource(videoSource, audioSource, _playWhenReady, false); _player.setSource(videoSource, audioSource, _playWhenReady, false, resume = resumePositionMs > 0);
if(subtitleSource != null) if(subtitleSource != null)
_player.swapSubtitles(fragment.lifecycleScope, subtitleSource); _player.swapSubtitles(fragment.lifecycleScope, subtitleSource);
_player.seekTo(resumePositionMs); _player.seekTo(resumePositionMs);

View file

@ -89,7 +89,7 @@ class StateHistory {
StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) {
if(StateSync.instance.hasAtLeastOneOnlineDevice()) { if(StateSync.instance.hasAtLeastOneOnlineDevice()) {
Logger.i(TAG, "SyncHistory playback broadcasted (${liveObj.name}: ${position})"); Logger.i(TAG, "SyncHistory playback broadcasted (${liveObj.name}: ${position})");
StateSync.instance.broadcastJson( StateSync.instance.broadcastJsonData(
GJSyncOpcodes.syncHistory, GJSyncOpcodes.syncHistory,
listOf(historyVideo) listOf(historyVideo)
); );

View file

@ -198,7 +198,7 @@ class StatePlaylists {
StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) {
if(StateSync.instance.hasAtLeastOneOnlineDevice()) { if(StateSync.instance.hasAtLeastOneOnlineDevice()) {
Logger.i(StateSubscriptionGroups.TAG, "SyncPlaylist (${playlist.name})"); Logger.i(StateSubscriptionGroups.TAG, "SyncPlaylist (${playlist.name})");
StateSync.instance.broadcastJson( StateSync.instance.broadcastJsonData(
GJSyncOpcodes.syncPlaylists, GJSyncOpcodes.syncPlaylists,
SyncPlaylistsPackage(listOf(playlist), mapOf()) SyncPlaylistsPackage(listOf(playlist), mapOf())
); );
@ -217,7 +217,7 @@ class StatePlaylists {
StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) {
if(StateSync.instance.hasAtLeastOneOnlineDevice()) { if(StateSync.instance.hasAtLeastOneOnlineDevice()) {
Logger.i(StateSubscriptionGroups.TAG, "SyncPlaylist (${playlist.name})"); Logger.i(StateSubscriptionGroups.TAG, "SyncPlaylist (${playlist.name})");
StateSync.instance.broadcastJson( StateSync.instance.broadcastJsonData(
GJSyncOpcodes.syncPlaylists, GJSyncOpcodes.syncPlaylists,
SyncPlaylistsPackage(listOf(), mapOf(Pair(playlist.id, OffsetDateTime.now().toEpochSecond()))) SyncPlaylistsPackage(listOf(), mapOf(Pair(playlist.id, OffsetDateTime.now().toEpochSecond())))
); );

View file

@ -81,7 +81,7 @@ class StateSubscriptionGroups {
StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) {
if(StateSync.instance.hasAtLeastOneOnlineDevice()) { if(StateSync.instance.hasAtLeastOneOnlineDevice()) {
Logger.i(TAG, "SyncSubscriptionGroup (${subGroup.name})"); Logger.i(TAG, "SyncSubscriptionGroup (${subGroup.name})");
StateSync.instance.broadcastJson( StateSync.instance.broadcastJsonData(
GJSyncOpcodes.syncSubscriptionGroups, GJSyncOpcodes.syncSubscriptionGroups,
SyncSubscriptionGroupsPackage(listOf(subGroup), mapOf()) SyncSubscriptionGroupsPackage(listOf(subGroup), mapOf())
); );
@ -100,7 +100,7 @@ class StateSubscriptionGroups {
StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) {
if(StateSync.instance.hasAtLeastOneOnlineDevice()) { if(StateSync.instance.hasAtLeastOneOnlineDevice()) {
Logger.i(TAG, "SyncSubscriptionGroup delete (${group.name})"); Logger.i(TAG, "SyncSubscriptionGroup delete (${group.name})");
StateSync.instance.broadcastJson( StateSync.instance.broadcastJsonData(
GJSyncOpcodes.syncSubscriptionGroups, GJSyncOpcodes.syncSubscriptionGroups,
SyncSubscriptionGroupsPackage(listOf(), mapOf(Pair(id, OffsetDateTime.now().toEpochSecond()))) SyncSubscriptionGroupsPackage(listOf(), mapOf(Pair(id, OffsetDateTime.now().toEpochSecond())))
); );

View file

@ -250,7 +250,7 @@ class StateSubscriptions {
StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) {
try { try {
StateSync.instance.broadcast( StateSync.instance.broadcastData(
GJSyncOpcodes.syncSubscriptions, Json.encodeToString( GJSyncOpcodes.syncSubscriptions, Json.encodeToString(
SyncSubscriptionsPackage( SyncSubscriptionsPackage(
listOf(subObj), listOf(subObj),
@ -299,7 +299,7 @@ class StateSubscriptions {
StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) { StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) {
try { try {
StateSync.instance.broadcast( StateSync.instance.broadcastData(
GJSyncOpcodes.syncSubscriptions, Json.encodeToString( GJSyncOpcodes.syncSubscriptions, Json.encodeToString(
SyncSubscriptionsPackage( SyncSubscriptionsPackage(
listOf(), listOf(),

View file

@ -370,26 +370,29 @@ class StateSync {
Logger.i(TAG, "Connection authorized for ${remotePublicKey} because initiator") Logger.i(TAG, "Connection authorized for ${remotePublicKey} because initiator")
} }
}, },
onData = { s, opcode, data -> onData = { s, opcode, subOpcode, data ->
session?.handlePacket(s, opcode, data) session?.handlePacket(s, opcode, subOpcode, data)
}) })
} }
inline fun <reified T> broadcastJson(opcode: UByte, data: T) { inline fun <reified T> broadcastJsonData(subOpcode: UByte, data: T) {
broadcast(opcode, Json.encodeToString(data)); broadcast(SyncSocketSession.Opcode.DATA.value, subOpcode, Json.encodeToString(data));
} }
fun broadcast(opcode: UByte, data: String) { fun broadcastData(subOpcode: UByte, data: String) {
broadcast(opcode, data.toByteArray(Charsets.UTF_8)); broadcast(SyncSocketSession.Opcode.DATA.value, subOpcode, data.toByteArray(Charsets.UTF_8));
} }
fun broadcast(opcode: UByte, data: ByteArray) { fun broadcast(opcode: UByte, subOpcode: UByte, data: String) {
broadcast(opcode, subOpcode, data.toByteArray(Charsets.UTF_8));
}
fun broadcast(opcode: UByte, subOpcode: UByte, data: ByteArray) {
for(session in getSessions()) { for(session in getSessions()) {
try { try {
if (session.isAuthorized && session.connected) { if (session.isAuthorized && session.connected) {
session.send(opcode, data); session.send(opcode, subOpcode, data);
} }
} }
catch(ex: Exception) { catch(ex: Exception) {
Logger.w(TAG, "Failed to broadcast ${opcode} to ${session.remotePublicKey}: ${ex.message}}", ex); Logger.w(TAG, "Failed to broadcast (opcode = ${opcode}, subOpcode = ${subOpcode}) to ${session.remotePublicKey}: ${ex.message}}", ex);
} }
} }
} }
@ -398,7 +401,7 @@ class StateSync {
val time = measureTimeMillis { val time = measureTimeMillis {
//val export = StateBackup.export(); //val export = StateBackup.export();
//session.send(GJSyncOpcodes.syncExport, export.asZip()); //session.send(GJSyncOpcodes.syncExport, export.asZip());
session.send(GJSyncOpcodes.syncStateExchange, getSyncSessionDataString(session.remotePublicKey)); session.sendData(GJSyncOpcodes.syncStateExchange, getSyncSessionDataString(session.remotePublicKey));
} }
Logger.i(TAG, "Generated and sent sync export in ${time}ms"); Logger.i(TAG, "Generated and sent sync export in ${time}ms");
} }

View file

@ -45,6 +45,7 @@ class SyncSession : IAuthorizable {
private val _onConnectedChanged: (session: SyncSession, connected: Boolean) -> Unit private val _onConnectedChanged: (session: SyncSession, connected: Boolean) -> Unit
val remotePublicKey: String val remotePublicKey: String
override val isAuthorized get() = _authorized && _remoteAuthorized override val isAuthorized get() = _authorized && _remoteAuthorized
private var _wasAuthorized = false
var connected: Boolean = false var connected: Boolean = false
private set(v) { private set(v) {
@ -94,8 +95,10 @@ class SyncSession : IAuthorizable {
} }
private fun checkAuthorized() { private fun checkAuthorized() {
if (isAuthorized) if (!_wasAuthorized && isAuthorized) {
_wasAuthorized = true
_onAuthorized.invoke(this) _onAuthorized.invoke(this)
}
} }
fun removeSocketSession(socketSession: SyncSocketSession) { fun removeSocketSession(socketSession: SyncSocketSession) {
@ -117,29 +120,34 @@ class SyncSession : IAuthorizable {
_onClose.invoke(this) _onClose.invoke(this)
} }
fun handlePacket(socketSession: SyncSocketSession, opcode: UByte, data: ByteBuffer) { fun handlePacket(socketSession: SyncSocketSession, opcode: UByte, subOpcode: UByte, data: ByteBuffer) {
Logger.i(TAG, "Handle packet (opcode: ${opcode}, data.length: ${data.remaining()})")
when (opcode) {
Opcode.NOTIFY_AUTHORIZED.value -> {
_remoteAuthorized = true
checkAuthorized()
}
Opcode.NOTIFY_UNAUTHORIZED.value -> {
_remoteAuthorized = false
_onUnauthorized(this)
}
//TODO: Handle any kind of packet (that is not necessarily authorized)
}
if (!isAuthorized) {
return
}
Logger.i(TAG, "Received ${opcode} (${data.remaining()} bytes)")
//TODO: Abstract this out
try { try {
Logger.i(TAG, "Handle packet (opcode: ${opcode}, subOpcode: ${subOpcode}, data.length: ${data.remaining()})")
when (opcode) { when (opcode) {
Opcode.NOTIFY_AUTHORIZED.value -> {
_remoteAuthorized = true
checkAuthorized()
}
Opcode.NOTIFY_UNAUTHORIZED.value -> {
_remoteAuthorized = false
_onUnauthorized(this)
}
//TODO: Handle any kind of packet (that is not necessarily authorized)
}
if (!isAuthorized) {
return
}
if (opcode != Opcode.DATA.value) {
Logger.w(TAG, "Unknown opcode received: (opcode = ${opcode}, subOpcode = ${subOpcode})}")
return
}
Logger.i(TAG, "Received (opcode = ${opcode}, subOpcode = ${subOpcode}) (${data.remaining()} bytes)")
//TODO: Abstract this out
when (subOpcode) {
GJSyncOpcodes.sendToDevices -> { GJSyncOpcodes.sendToDevices -> {
StateApp.instance.scopeOrNull?.launch(Dispatchers.Main) { StateApp.instance.scopeOrNull?.launch(Dispatchers.Main) {
val context = StateApp.instance.contextOrNull; val context = StateApp.instance.contextOrNull;
@ -164,13 +172,13 @@ class SyncSession : IAuthorizable {
Logger.i(TAG, "Received SyncSessionData from " + remotePublicKey); Logger.i(TAG, "Received SyncSessionData from " + remotePublicKey);
send(GJSyncOpcodes.syncSubscriptions, StateSubscriptions.instance.getSyncSubscriptionsPackageString()); sendData(GJSyncOpcodes.syncSubscriptions, StateSubscriptions.instance.getSyncSubscriptionsPackageString());
send(GJSyncOpcodes.syncSubscriptionGroups, StateSubscriptionGroups.instance.getSyncSubscriptionGroupsPackageString()); sendData(GJSyncOpcodes.syncSubscriptionGroups, StateSubscriptionGroups.instance.getSyncSubscriptionGroupsPackageString());
send(GJSyncOpcodes.syncPlaylists, StatePlaylists.instance.getSyncPlaylistsPackageString()) sendData(GJSyncOpcodes.syncPlaylists, StatePlaylists.instance.getSyncPlaylistsPackageString())
val recentHistory = StateHistory.instance.getRecentHistory(syncSessionData.lastHistory); val recentHistory = StateHistory.instance.getRecentHistory(syncSessionData.lastHistory);
if(recentHistory.size > 0) if(recentHistory.size > 0)
sendJson(GJSyncOpcodes.syncHistory, recentHistory); sendJsonData(GJSyncOpcodes.syncHistory, recentHistory);
} }
GJSyncOpcodes.syncExport -> { GJSyncOpcodes.syncExport -> {
@ -338,16 +346,19 @@ class SyncSession : IAuthorizable {
} }
inline fun <reified T> sendJson(opcode: UByte, data: T) { inline fun <reified T> sendJsonData(subOpcode: UByte, data: T) {
send(opcode, Json.encodeToString<T>(data)); send(Opcode.DATA.value, subOpcode, Json.encodeToString<T>(data));
} }
fun send(opcode: UByte, data: String) { fun sendData(subOpcode: UByte, data: String) {
send(opcode, data.toByteArray(Charsets.UTF_8)); send(Opcode.DATA.value, subOpcode, data.toByteArray(Charsets.UTF_8));
} }
fun send(opcode: UByte, data: ByteArray) { fun send(opcode: UByte, subOpcode: UByte, data: String) {
send(opcode, subOpcode, data.toByteArray(Charsets.UTF_8));
}
fun send(opcode: UByte, subOpcode: UByte, data: ByteArray) {
val sock = _socketSessions.firstOrNull(); val sock = _socketSessions.firstOrNull();
if(sock != null){ if(sock != null){
sock.send(opcode, ByteBuffer.wrap(data)); sock.send(opcode, subOpcode, ByteBuffer.wrap(data));
} }
else else
throw IllegalStateException("Session has no active sockets"); throw IllegalStateException("Session has no active sockets");

View file

@ -2,6 +2,7 @@ package com.futo.platformplayer.sync.internal
import com.futo.platformplayer.LittleEndianDataInputStream import com.futo.platformplayer.LittleEndianDataInputStream
import com.futo.platformplayer.LittleEndianDataOutputStream import com.futo.platformplayer.LittleEndianDataOutputStream
import com.futo.platformplayer.ensureNotMainThread
import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.logging.Logger
import com.futo.platformplayer.noise.protocol.CipherStatePair import com.futo.platformplayer.noise.protocol.CipherStatePair
import com.futo.platformplayer.noise.protocol.DHState import com.futo.platformplayer.noise.protocol.DHState
@ -18,7 +19,8 @@ class SyncSocketSession {
NOTIFY_UNAUTHORIZED(3u), NOTIFY_UNAUTHORIZED(3u),
STREAM_START(4u), STREAM_START(4u),
STREAM_DATA(5u), STREAM_DATA(5u),
STREAM_END(6u) STREAM_END(6u),
DATA(7u)
} }
private val _inputStream: LittleEndianDataInputStream private val _inputStream: LittleEndianDataInputStream
@ -41,12 +43,12 @@ class SyncSocketSession {
private val _localKeyPair: DHState private val _localKeyPair: DHState
private var _localPublicKey: String private var _localPublicKey: String
val localPublicKey: String get() = _localPublicKey val localPublicKey: String get() = _localPublicKey
private val _onData: (session: SyncSocketSession, opcode: UByte, data: ByteBuffer) -> Unit private val _onData: (session: SyncSocketSession, opcode: UByte, subOpcode: UByte, data: ByteBuffer) -> Unit
var authorizable: IAuthorizable? = null var authorizable: IAuthorizable? = null
val remoteAddress: String val remoteAddress: String
constructor(remoteAddress: String, localKeyPair: DHState, inputStream: LittleEndianDataInputStream, outputStream: LittleEndianDataOutputStream, onClose: (session: SyncSocketSession) -> Unit, onHandshakeComplete: (session: SyncSocketSession) -> Unit, onData: (session: SyncSocketSession, opcode: UByte, data: ByteBuffer) -> Unit) { constructor(remoteAddress: String, localKeyPair: DHState, inputStream: LittleEndianDataInputStream, outputStream: LittleEndianDataOutputStream, onClose: (session: SyncSocketSession) -> Unit, onHandshakeComplete: (session: SyncSocketSession) -> Unit, onData: (session: SyncSocketSession, opcode: UByte, subOpcode: UByte, data: ByteBuffer) -> Unit) {
_inputStream = inputStream _inputStream = inputStream
_outputStream = outputStream _outputStream = outputStream
_onClose = onClose _onClose = onClose
@ -159,10 +161,11 @@ class SyncSocketSession {
} }
private fun performVersionCheck() { private fun performVersionCheck() {
_outputStream.writeInt(1) val CURRENT_VERSION = 2
_outputStream.writeInt(CURRENT_VERSION)
val version = _inputStream.readInt() val version = _inputStream.readInt()
Logger.i(TAG, "performVersionCheck (version = $version)") Logger.i(TAG, "performVersionCheck (version = $version)")
if (version != 1) if (version != CURRENT_VERSION)
throw Exception("Invalid version") throw Exception("Invalid version")
} }
@ -205,8 +208,9 @@ class SyncSocketSession {
throw Exception("Handshake finished without completing") throw Exception("Handshake finished without completing")
} }
fun send(opcode: UByte, subOpcode: UByte, data: ByteBuffer) {
ensureNotMainThread()
fun send(opcode: UByte, data: ByteBuffer) {
if (data.remaining() + HEADER_SIZE > MAXIMUM_PACKET_SIZE) { if (data.remaining() + HEADER_SIZE > MAXIMUM_PACKET_SIZE) {
val segmentSize = MAXIMUM_PACKET_SIZE - HEADER_SIZE val segmentSize = MAXIMUM_PACKET_SIZE - HEADER_SIZE
val segmentData = ByteArray(segmentSize) val segmentData = ByteArray(segmentSize)
@ -223,8 +227,8 @@ class SyncSocketSession {
if (sendOffset == 0) { if (sendOffset == 0) {
segmentOpcode = Opcode.STREAM_START.value segmentOpcode = Opcode.STREAM_START.value
bytesToSend = segmentSize - 4 - 4 - 1 bytesToSend = segmentSize - 4 - 4 - 1 - 1
segmentPacketSize = bytesToSend + 4 + 4 + 1 segmentPacketSize = bytesToSend + 4 + 4 + 1 + 1
} else { } else {
bytesToSend = minOf(segmentSize - 4 - 4, bytesRemaining) bytesToSend = minOf(segmentSize - 4 - 4, bytesRemaining)
segmentOpcode = if (bytesToSend >= bytesRemaining) Opcode.STREAM_END.value else Opcode.STREAM_DATA.value segmentOpcode = if (bytesToSend >= bytesRemaining) Opcode.STREAM_END.value else Opcode.STREAM_DATA.value
@ -236,18 +240,20 @@ class SyncSocketSession {
putInt(if (segmentOpcode == Opcode.STREAM_START.value) data.remaining() else sendOffset) putInt(if (segmentOpcode == Opcode.STREAM_START.value) data.remaining() else sendOffset)
if (segmentOpcode == Opcode.STREAM_START.value) { if (segmentOpcode == Opcode.STREAM_START.value) {
put(opcode.toByte()) put(opcode.toByte())
put(subOpcode.toByte())
} }
put(data.array(), data.position() + sendOffset, bytesToSend) put(data.array(), data.position() + sendOffset, bytesToSend)
} }
send(segmentOpcode, ByteBuffer.wrap(segmentData, 0, segmentPacketSize)) send(segmentOpcode, 0u, ByteBuffer.wrap(segmentData, 0, segmentPacketSize))
sendOffset += bytesToSend sendOffset += bytesToSend
} }
} else { } else {
synchronized(_sendLockObject) { synchronized(_sendLockObject) {
ByteBuffer.wrap(_sendBuffer).order(ByteOrder.LITTLE_ENDIAN).apply { ByteBuffer.wrap(_sendBuffer).order(ByteOrder.LITTLE_ENDIAN).apply {
putInt(data.remaining() + 1) putInt(data.remaining() + 2)
put(opcode.toByte()) put(opcode.toByte())
put(subOpcode.toByte())
put(data.array(), data.position(), data.remaining()) put(data.array(), data.position(), data.remaining())
} }
@ -260,12 +266,15 @@ class SyncSocketSession {
} }
} }
fun send(opcode: UByte) { fun send(opcode: UByte, subOpcode: UByte = 0u) {
synchronized(_sendLockObject) { ensureNotMainThread()
ByteBuffer.wrap(_sendBuffer, 0, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(1)
_sendBuffer.asUByteArray()[4] = opcode
//Logger.i(TAG, "Encrypting message (size = ${HEADER_SIZE})") synchronized(_sendLockObject) {
ByteBuffer.wrap(_sendBuffer, 0, 4).order(ByteOrder.LITTLE_ENDIAN).putInt(2)
_sendBuffer.asUByteArray()[4] = opcode
_sendBuffer.asUByteArray()[5] = subOpcode
//Logger.i(TAG, "Encrypting message (opcode = ${opcode}, subOpcode = ${subOpcode}, size = ${HEADER_SIZE})")
val len = _cipherStatePair!!.sender.encryptWithAd(null, _sendBuffer, 0, _sendBufferEncrypted, 0, HEADER_SIZE) val len = _cipherStatePair!!.sender.encryptWithAd(null, _sendBuffer, 0, _sendBufferEncrypted, 0, HEADER_SIZE)
//Logger.i(TAG, "Sending encrypted message (size = ${len})") //Logger.i(TAG, "Sending encrypted message (size = ${len})")
@ -277,19 +286,19 @@ class SyncSocketSession {
private fun handleData(data: ByteArray, length: Int) { private fun handleData(data: ByteArray, length: Int) {
if (length < HEADER_SIZE) if (length < HEADER_SIZE)
throw Exception("Packet must be at least 5 bytes (header size)") throw Exception("Packet must be at least 6 bytes (header size)")
val size = ByteBuffer.wrap(data, 0, 4).order(ByteOrder.LITTLE_ENDIAN).int val size = ByteBuffer.wrap(data, 0, 4).order(ByteOrder.LITTLE_ENDIAN).int
if (size != length - 4) if (size != length - 4)
throw Exception("Incomplete packet received") throw Exception("Incomplete packet received")
val opcode = data.asUByteArray()[4] val opcode = data.asUByteArray()[4]
val packetData = ByteBuffer.wrap(data, HEADER_SIZE, size - 1) val subOpcode = data.asUByteArray()[5]
val packetData = ByteBuffer.wrap(data, HEADER_SIZE, size - 2)
handlePacket(opcode, packetData.order(ByteOrder.LITTLE_ENDIAN)) handlePacket(opcode, subOpcode, packetData.order(ByteOrder.LITTLE_ENDIAN))
} }
private fun handlePacket(opcode: UByte, data: ByteBuffer) { private fun handlePacket(opcode: UByte, subOpcode: UByte, data: ByteBuffer) {
when (opcode) { when (opcode) {
Opcode.PING.value -> { Opcode.PING.value -> {
send(Opcode.PONG.value) send(Opcode.PONG.value)
@ -302,7 +311,7 @@ class SyncSocketSession {
} }
Opcode.NOTIFY_AUTHORIZED.value, Opcode.NOTIFY_AUTHORIZED.value,
Opcode.NOTIFY_UNAUTHORIZED.value -> { Opcode.NOTIFY_UNAUTHORIZED.value -> {
_onData.invoke(this, opcode, data) _onData.invoke(this, opcode, subOpcode, data)
return return
} }
} }
@ -316,8 +325,9 @@ class SyncSocketSession {
val id = data.int val id = data.int
val expectedSize = data.int val expectedSize = data.int
val op = data.get().toUByte() val op = data.get().toUByte()
val subOp = data.get().toUByte()
val syncStream = SyncStream(expectedSize, op) val syncStream = SyncStream(expectedSize, op, subOp)
if (data.remaining() > 0) { if (data.remaining() > 0) {
syncStream.add(data.array(), data.position(), data.remaining()) syncStream.add(data.array(), data.position(), data.remaining())
} }
@ -362,10 +372,13 @@ class SyncSocketSession {
throw Exception("After sync stream end, the stream must be complete") throw Exception("After sync stream end, the stream must be complete")
} }
handlePacket(syncStream.opcode, syncStream.getBytes().let { ByteBuffer.wrap(it).order(ByteOrder.LITTLE_ENDIAN) }) handlePacket(syncStream.opcode, syncStream.subOpcode, syncStream.getBytes().let { ByteBuffer.wrap(it).order(ByteOrder.LITTLE_ENDIAN) })
}
Opcode.DATA.value -> {
_onData.invoke(this, opcode, subOpcode, data)
} }
else -> { else -> {
_onData.invoke(this, opcode, data) Logger.w(TAG, "Unknown opcode received (opcode = ${opcode}, subOpcode = ${subOpcode})")
} }
} }
} }
@ -374,6 +387,6 @@ class SyncSocketSession {
private const val TAG = "SyncSocketSession" private const val TAG = "SyncSocketSession"
const val MAXIMUM_PACKET_SIZE = 65535 - 16 const val MAXIMUM_PACKET_SIZE = 65535 - 16
const val MAXIMUM_PACKET_SIZE_ENCRYPTED = MAXIMUM_PACKET_SIZE + 16 const val MAXIMUM_PACKET_SIZE_ENCRYPTED = MAXIMUM_PACKET_SIZE + 16
const val HEADER_SIZE = 5 const val HEADER_SIZE = 6
} }
} }

View file

@ -1,6 +1,6 @@
package com.futo.platformplayer.sync.internal package com.futo.platformplayer.sync.internal
class SyncStream(expectedSize: Int, val opcode: UByte) { class SyncStream(expectedSize: Int, val opcode: UByte, val subOpcode: UByte) {
companion object { companion object {
const val MAXIMUM_SIZE = 10_000_000 const val MAXIMUM_SIZE = 10_000_000
} }

View file

@ -327,8 +327,8 @@ abstract class FutoVideoPlayerBase : RelativeLayout {
return _chapters?.let { chaps -> chaps.find { pos.toDouble() / 1000 > it.timeStart && pos.toDouble() / 1000 < it.timeEnd && (toIgnore.isEmpty() || !toIgnore.contains(it)) } }; return _chapters?.let { chaps -> chaps.find { pos.toDouble() / 1000 > it.timeStart && pos.toDouble() / 1000 < it.timeEnd && (toIgnore.isEmpty() || !toIgnore.contains(it)) } };
} }
fun setSource(videoSource: IVideoSource?, audioSource: IAudioSource? = null, play: Boolean = false, keepSubtitles: Boolean = false) { fun setSource(videoSource: IVideoSource?, audioSource: IAudioSource? = null, play: Boolean = false, keepSubtitles: Boolean = false, resume: Boolean = false) {
swapSources(videoSource, audioSource,false, play, keepSubtitles); swapSources(videoSource, audioSource,resume, play, keepSubtitles);
} }
fun swapSources(videoSource: IVideoSource?, audioSource: IAudioSource?, resume: Boolean = true, play: Boolean = true, keepSubtitles: Boolean = false): Boolean { fun swapSources(videoSource: IVideoSource?, audioSource: IAudioSource?, resume: Boolean = true, play: Boolean = true, keepSubtitles: Boolean = false): Boolean {
var videoSourceUsed = videoSource; var videoSourceUsed = videoSource;

View file

@ -22,6 +22,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_back"
android:paddingRight="20dp" android:paddingRight="20dp"
app:srcCompat="@drawable/ic_back_thin_white_16dp" /> app:srcCompat="@drawable/ic_back_thin_white_16dp" />

View file

@ -22,6 +22,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_back"
android:paddingRight="20dp" android:paddingRight="20dp"
app:srcCompat="@drawable/ic_back_thin_white_16dp" /> app:srcCompat="@drawable/ic_back_thin_white_16dp" />

View file

@ -22,6 +22,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_back"
android:paddingRight="20dp" android:paddingRight="20dp"
app:srcCompat="@drawable/ic_back_thin_white_16dp" /> app:srcCompat="@drawable/ic_back_thin_white_16dp" />

View file

@ -10,6 +10,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_back_thin_white_16dp" app:srcCompat="@drawable/ic_back_thin_white_16dp"

View file

@ -14,6 +14,7 @@
android:id="@+id/button_close" android:id="@+id/button_close"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_close"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:padding="10dp" android:padding="10dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"

View file

@ -75,6 +75,7 @@
android:id="@+id/incognito_button" android:id="@+id/incognito_button"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_incognito_button"
android:src="@drawable/ic_disabled_visible_purple" android:src="@drawable/ic_disabled_visible_purple"
android:background="@drawable/background_button_round_black" android:background="@drawable/background_button_round_black"
android:scaleType="fitCenter" android:scaleType="fitCenter"

View file

@ -21,6 +21,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_back"
android:paddingRight="20dp" android:paddingRight="20dp"
app:srcCompat="@drawable/ic_back_thin_white_16dp" /> app:srcCompat="@drawable/ic_back_thin_white_16dp" />

View file

@ -9,6 +9,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_back_thin_white_16dp" app:srcCompat="@drawable/ic_back_thin_white_16dp"
@ -19,6 +20,7 @@
android:id="@+id/button_help" android:id="@+id/button_help"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_button_help"
app:srcCompat="@drawable/ic_help" app:srcCompat="@drawable/ic_help"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

View file

@ -10,6 +10,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -20,6 +21,8 @@
android:id="@+id/button_help" android:id="@+id/button_help"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_help"
app:srcCompat="@drawable/ic_help"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_help" /> app:srcCompat="@drawable/ic_help" />

View file

@ -9,6 +9,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_back_thin_white_16dp" app:srcCompat="@drawable/ic_back_thin_white_16dp"
@ -19,6 +20,7 @@
android:id="@+id/button_help" android:id="@+id/button_help"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_button_help"
app:srcCompat="@drawable/ic_help" app:srcCompat="@drawable/ic_help"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

View file

@ -9,6 +9,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_back_thin_white_16dp" app:srcCompat="@drawable/ic_back_thin_white_16dp"
@ -19,6 +20,7 @@
android:id="@+id/button_help" android:id="@+id/button_help"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_help"
app:srcCompat="@drawable/ic_help" app:srcCompat="@drawable/ic_help"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

View file

@ -10,6 +10,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_back_thin_white_16dp" app:srcCompat="@drawable/ic_back_thin_white_16dp"
@ -20,6 +21,7 @@
android:id="@+id/button_help" android:id="@+id/button_help"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_button_help"
app:srcCompat="@drawable/ic_help" app:srcCompat="@drawable/ic_help"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -28,6 +30,7 @@
android:id="@+id/image_polycentric" android:id="@+id/image_polycentric"
android:layout_height="80dp" android:layout_height="80dp"
android:layout_width="80dp" android:layout_width="80dp"
android:contentDescription="@string/cd_image_polycentric"
android:scaleType="centerCrop" android:scaleType="centerCrop"
app:shapeAppearanceOverlay="@style/roundedCorners_40dp" app:shapeAppearanceOverlay="@style/roundedCorners_40dp"
app:srcCompat="@drawable/placeholder_profile" app:srcCompat="@drawable/placeholder_profile"

View file

@ -10,6 +10,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_back_thin_white_16dp" app:srcCompat="@drawable/ic_back_thin_white_16dp"

View file

@ -24,6 +24,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_back"
android:paddingRight="20dp" android:paddingRight="20dp"
app:srcCompat="@drawable/ic_back_thin_white_16dp" /> app:srcCompat="@drawable/ic_back_thin_white_16dp" />

View file

@ -10,6 +10,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_back_thin_white_16dp" app:srcCompat="@drawable/ic_back_thin_white_16dp"

View file

@ -10,6 +10,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_back_thin_white_16dp" app:srcCompat="@drawable/ic_back_thin_white_16dp"

View file

@ -14,6 +14,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_back"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_back_thin_white_16dp" app:srcCompat="@drawable/ic_back_thin_white_16dp"

View file

@ -27,6 +27,7 @@
android:id="@+id/button_cancel" android:id="@+id/button_cancel"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_button_close"
app:srcCompat="@drawable/ic_close_thin" app:srcCompat="@drawable/ic_close_thin"
app:tint="#888888" app:tint="#888888"
android:layout_marginEnd="30dp" /> android:layout_marginEnd="30dp" />

View file

@ -97,6 +97,7 @@
android:id="@+id/button_scan_qr" android:id="@+id/button_scan_qr"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_scan_qr"
android:scaleType="centerCrop" android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_qr" app:srcCompat="@drawable/ic_qr"
app:tint="@color/primary" /> app:tint="@color/primary" />
@ -109,6 +110,7 @@
android:id="@+id/button_add" android:id="@+id/button_add"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_add"
android:scaleType="centerCrop" android:scaleType="centerCrop"
app:srcCompat="@drawable/ic_add" app:srcCompat="@drawable/ic_add"
app:tint="@color/primary" app:tint="@color/primary"

View file

@ -58,6 +58,7 @@
android:id="@+id/image_device" android:id="@+id/image_device"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" android:layout_height="25dp"
android:contentDescription="@string/cd_image_device"
app:srcCompat="@drawable/ic_chromecast" app:srcCompat="@drawable/ic_chromecast"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -197,6 +198,7 @@
android:id="@id/button_previous" android:id="@id/button_previous"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:contentDescription="@string/cd_button_previous"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:clickable="true" android:clickable="true"
android:padding="10dp" android:padding="10dp"
@ -206,6 +208,7 @@
android:id="@+id/button_play" android:id="@+id/button_play"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:contentDescription="@string/cd_button_play"
android:padding="20dp" android:padding="20dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
@ -215,6 +218,7 @@
android:id="@+id/button_pause" android:id="@+id/button_pause"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:contentDescription="@string/cd_button_pause"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
@ -224,6 +228,7 @@
android:id="@+id/button_stop" android:id="@+id/button_stop"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:contentDescription="@string/cd_button_stop"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:padding="5dp" android:padding="5dp"
android:clickable="true" android:clickable="true"
@ -233,6 +238,7 @@
android:id="@id/button_next" android:id="@id/button_next"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:contentDescription="@string/cd_button_next"
android:clickable="true" android:clickable="true"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:padding="10dp" android:padding="10dp"

View file

@ -23,6 +23,7 @@
android:id="@+id/update_spinner" android:id="@+id/update_spinner"
android:layout_width="100dp" android:layout_width="100dp"
android:layout_height="100dp" android:layout_height="100dp"
android:contentDescription="@string/cd_update_spinner"
app:srcCompat="@drawable/ic_update_animated" /> app:srcCompat="@drawable/ic_update_animated" />
<TextView <TextView

View file

@ -11,6 +11,7 @@
android:id="@+id/app_icon" android:id="@+id/app_icon"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:contentDescription="@string/cd_app_icon"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
@ -72,6 +73,7 @@
android:id="@+id/button_cast" android:id="@+id/button_cast"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_cast_button"
android:paddingStart="16dp" android:paddingStart="16dp"
android:paddingEnd="12dp" android:paddingEnd="12dp"
android:paddingTop="12dp" android:paddingTop="12dp"
@ -84,6 +86,7 @@
android:id="@+id/button_add" android:id="@+id/button_add"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_add"
android:paddingStart="5dp" android:paddingStart="5dp"
android:paddingEnd="12dp" android:paddingEnd="12dp"
android:paddingTop="7dp" android:paddingTop="7dp"

View file

@ -62,6 +62,7 @@
android:background="@drawable/rounded_outline" android:background="@drawable/rounded_outline"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:contentDescription="@string/cd_creator_thumbnail"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -103,6 +104,7 @@
android:id="@+id/button_sub_settings" android:id="@+id/button_sub_settings"
android:layout_width="30dp" android:layout_width="30dp"
android:layout_height="30dp" android:layout_height="30dp"
android:contentDescription="@string/cd_button_settings"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:layout_marginRight="10dp" android:layout_marginRight="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
@ -114,6 +116,7 @@
android:id="@+id/button_subscribe" android:id="@+id/button_subscribe"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_button_subscribe"
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"

View file

@ -17,6 +17,7 @@
android:id="@+id/image_channel_thumbnail" android:id="@+id/image_channel_thumbnail"
android:layout_width="80dp" android:layout_width="80dp"
android:layout_height="80dp" android:layout_height="80dp"
android:contentDescription="@string/cd_creator_thumbnail"
app:srcCompat="@drawable/ic_peertube" app:srcCompat="@drawable/ic_peertube"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"

View file

@ -48,6 +48,7 @@
android:id="@+id/button_clear_search" android:id="@+id/button_clear_search"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_clear_search"
android:paddingStart="18dp" android:paddingStart="18dp"
android:paddingEnd="18dp" android:paddingEnd="18dp"
android:layout_gravity="right|center_vertical" android:layout_gravity="right|center_vertical"

View file

@ -41,6 +41,7 @@
<ImageView <ImageView
android:layout_width="26dp" android:layout_width="26dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_search_icon"
app:srcCompat="@drawable/ic_search_thin" app:srcCompat="@drawable/ic_search_thin"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
@ -65,6 +66,7 @@
android:id="@+id/button_clear_search" android:id="@+id/button_clear_search"
android:layout_width="46dp" android:layout_width="46dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_clear_search"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:srcCompat="@drawable/ic_close_thin" app:srcCompat="@drawable/ic_close_thin"
app:tint="@color/gray_ac" app:tint="@color/gray_ac"

View file

@ -11,6 +11,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_back"
android:paddingLeft="16dp" android:paddingLeft="16dp"
android:paddingRight="8dp" android:paddingRight="8dp"
app:srcCompat="@drawable/ic_back_nav" /> app:srcCompat="@drawable/ic_back_nav" />

View file

@ -11,6 +11,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_back"
android:paddingLeft="16dp" android:paddingLeft="16dp"
android:paddingRight="8dp" android:paddingRight="8dp"
app:srcCompat="@drawable/ic_back_nav" /> app:srcCompat="@drawable/ic_back_nav" />
@ -34,6 +35,7 @@
android:id="@+id/button_cast" android:id="@+id/button_cast"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_cast_button"
android:paddingStart="4dp" android:paddingStart="4dp"
android:paddingEnd="4dp" android:paddingEnd="4dp"
android:paddingTop="9dp" android:paddingTop="9dp"

View file

@ -10,6 +10,7 @@
android:id="@+id/app_icon" android:id="@+id/app_icon"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:contentDescription="@string/cd_app_icon"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
@ -37,6 +38,7 @@
android:id="@+id/button_cast" android:id="@+id/button_cast"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_cast_button"
android:paddingStart="16dp" android:paddingStart="16dp"
android:paddingEnd="12dp" android:paddingEnd="12dp"
android:paddingTop="12dp" android:paddingTop="12dp"
@ -49,6 +51,7 @@
android:id="@+id/button_search" android:id="@+id/button_search"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_search"
android:paddingStart="5dp" android:paddingStart="5dp"
android:paddingEnd="12dp" android:paddingEnd="12dp"
android:paddingTop="11dp" android:paddingTop="11dp"

View file

@ -34,6 +34,7 @@
android:id="@+id/image_history" android:id="@+id/image_history"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_icon_history"
app:srcCompat="@drawable/ic_clock_white" app:srcCompat="@drawable/ic_clock_white"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -119,6 +120,7 @@
android:id="@+id/button_create_playlist" android:id="@+id/button_create_playlist"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_button_create_playlist"
app:srcCompat="@drawable/ic_add_white_16dp" app:srcCompat="@drawable/ic_add_white_16dp"
android:paddingEnd="15dp" android:paddingEnd="15dp"
android:paddingStart="15dp" android:paddingStart="15dp"

View file

@ -58,6 +58,7 @@
android:id="@+id/button_share" android:id="@+id/button_share"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_share"
android:background="@drawable/background_button_round" android:background="@drawable/background_button_round"
android:gravity="center" android:gravity="center"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"

View file

@ -13,6 +13,7 @@
android:id="@+id/button_back" android:id="@+id/button_back"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_back"
android:paddingLeft="16dp" android:paddingLeft="16dp"
android:paddingRight="16dp" android:paddingRight="16dp"
app:srcCompat="@drawable/ic_back_white_24dp" /> app:srcCompat="@drawable/ic_back_white_24dp" />
@ -27,6 +28,7 @@
android:id="@+id/edit_search" android:id="@+id/edit_search"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Search"
android:layout_weight="1" android:layout_weight="1"
android:inputType="text" android:inputType="text"
android:imeOptions="actionDone" android:imeOptions="actionDone"
@ -37,6 +39,7 @@
android:id="@+id/button_clear_search" android:id="@+id/button_clear_search"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_clear_search"
android:paddingStart="18dp" android:paddingStart="18dp"
android:paddingEnd="18dp" android:paddingEnd="18dp"
android:layout_gravity="right|center_vertical" android:layout_gravity="right|center_vertical"
@ -48,6 +51,7 @@
android:id="@+id/button_filter" android:id="@+id/button_filter"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_filter"
android:paddingStart="8dp" android:paddingStart="8dp"
android:paddingEnd="8dp" android:paddingEnd="8dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"

View file

@ -43,6 +43,7 @@
android:id="@+id/button_delete" android:id="@+id/button_delete"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_delete"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="0dp" android:layout_marginRight="0dp"
android:src="@drawable/ic_trash" android:src="@drawable/ic_trash"
@ -56,6 +57,7 @@
android:id="@+id/button_settings" android:id="@+id/button_settings"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_settings"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:src="@drawable/ic_settings" android:src="@drawable/ic_settings"
@ -69,6 +71,7 @@
android:id="@+id/image_group" android:id="@+id/image_group"
android:layout_width="110dp" android:layout_width="110dp"
android:layout_height="70dp" android:layout_height="70dp"
android:contentDescription="@string/cd_image_group"
android:adjustViewBounds="true" android:adjustViewBounds="true"
app:circularflow_defaultRadius="10dp" app:circularflow_defaultRadius="10dp"
android:layout_marginLeft="30dp" android:layout_marginLeft="30dp"
@ -90,6 +93,7 @@
<ImageButton <ImageButton
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_edit_image"
android:padding="5dp" android:padding="5dp"
android:clickable="false" android:clickable="false"
android:scaleType="fitCenter" android:scaleType="fitCenter"
@ -121,6 +125,7 @@
<ImageButton <ImageButton
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_button_edit"
android:padding="2dp" android:padding="2dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_marginBottom="-5dp" android:layout_marginBottom="-5dp"

View file

@ -58,6 +58,7 @@
android:id="@+id/button_share" android:id="@+id/button_share"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_share"
android:background="@drawable/background_button_round" android:background="@drawable/background_button_round"
android:gravity="center" android:gravity="center"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
@ -162,6 +163,7 @@
android:id="@+id/button_edit" android:id="@+id/button_edit"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_edit"
android:background="@drawable/background_button_round" android:background="@drawable/background_button_round"
android:gravity="center" android:gravity="center"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
@ -177,6 +179,7 @@
android:id="@+id/button_download" android:id="@+id/button_download"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_download"
android:background="@drawable/background_button_round" android:background="@drawable/background_button_round"
android:gravity="center" android:gravity="center"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"

View file

@ -36,7 +36,8 @@
<com.futo.platformplayer.views.others.CreatorThumbnail <com.futo.platformplayer.views.others.CreatorThumbnail
android:id="@+id/creator_thumbnail" android:id="@+id/creator_thumbnail"
android:layout_width="27dp" android:layout_width="27dp"
android:layout_height="27dp" /> android:layout_height="27dp"
android:contentDescription="@string/cd_creator_thumbnail" />
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -128,6 +129,7 @@
android:id="@+id/image_like_icon" android:id="@+id/image_like_icon"
android:layout_width="18dp" android:layout_width="18dp"
android:layout_height="18dp" android:layout_height="18dp"
android:contentDescription="@string/cd_image_like_icon"
app:srcCompat="@drawable/ic_thumb_up" /> app:srcCompat="@drawable/ic_thumb_up" />
<TextView <TextView
@ -144,6 +146,7 @@
android:id="@+id/image_dislike_icon" android:id="@+id/image_dislike_icon"
android:layout_width="18dp" android:layout_width="18dp"
android:layout_height="18dp" android:layout_height="18dp"
android:contentDescription="@string/cd_image_dislike_icon"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
app:srcCompat="@drawable/ic_thumb_down" /> app:srcCompat="@drawable/ic_thumb_down" />
@ -285,6 +288,7 @@
android:id="@+id/button_share" android:id="@+id/button_share"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:contentDescription="@string/cd_button_share"
android:background="@drawable/background_button_round" android:background="@drawable/background_button_round"
android:gravity="center" android:gravity="center"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"

View file

@ -103,6 +103,7 @@
android:id="@+id/minimize_play" android:id="@+id/minimize_play"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_minimize_play"
android:padding="10dp" android:padding="10dp"
android:clickable="true" android:clickable="true"
android:scaleType="fitCenter" android:scaleType="fitCenter"
@ -111,6 +112,7 @@
android:id="@+id/minimize_pause" android:id="@+id/minimize_pause"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_minimize_pause"
android:padding="5dp" android:padding="5dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
@ -119,6 +121,7 @@
android:id="@+id/minimize_close" android:id="@+id/minimize_close"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_minimize_close"
android:padding="5dp" android:padding="5dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:layout_marginStart="2dp" android:layout_marginStart="2dp"
@ -337,7 +340,8 @@
<com.futo.platformplayer.views.others.CreatorThumbnail <com.futo.platformplayer.views.others.CreatorThumbnail
android:id="@+id/creator_thumbnail" android:id="@+id/creator_thumbnail"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" /> android:layout_height="35dp"
android:contentDescription="@string/cd_creator_thumbnail" />
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -59,6 +59,7 @@
android:id="@+id/donation_amount" android:id="@+id/donation_amount"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_donation_amount"
android:gravity="center" android:gravity="center"
tools:text="$100" /> tools:text="$100" />
</LinearLayout> </LinearLayout>

View file

@ -100,6 +100,7 @@
android:id="@+id/image_like_icon" android:id="@+id/image_like_icon"
android:layout_width="18dp" android:layout_width="18dp"
android:layout_height="18dp" android:layout_height="18dp"
android:contentDescription="@string/cd_image_like_icon"
app:srcCompat="@drawable/ic_thumb_up" /> app:srcCompat="@drawable/ic_thumb_up" />
<TextView <TextView
@ -116,6 +117,7 @@
android:id="@+id/image_dislike_icon" android:id="@+id/image_dislike_icon"
android:layout_width="18dp" android:layout_width="18dp"
android:layout_height="18dp" android:layout_height="18dp"
android:contentDescription="@string/cd_image_dislike_icon"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
app:srcCompat="@drawable/ic_thumb_down" /> app:srcCompat="@drawable/ic_thumb_down" />
@ -134,6 +136,7 @@
android:id="@+id/button_replies" android:id="@+id/button_replies"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_button_replies"
app:pillIcon="@drawable/ic_forum" app:pillIcon="@drawable/ic_forum"
app:pillText="55 Replies" app:pillText="55 Replies"
android:layout_marginStart="15dp" /> android:layout_marginStart="15dp" />

View file

@ -91,6 +91,7 @@
android:id="@+id/button_replies" android:id="@+id/button_replies"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_button_replies"
app:pillIcon="@drawable/ic_forum" app:pillIcon="@drawable/ic_forum"
app:pillText="55 Replies" app:pillText="55 Replies"
android:layout_marginStart="15dp" /> android:layout_marginStart="15dp" />
@ -112,6 +113,7 @@
android:id="@+id/pill_text" android:id="@+id/pill_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_delete"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="13dp" android:textSize="13dp"
android:gravity="center_vertical" android:gravity="center_vertical"

View file

@ -56,6 +56,7 @@
android:id="@+id/button_subscribe" android:id="@+id/button_subscribe"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_button_subscribe"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/text_channel_metadata" app:layout_constraintTop_toBottomOf="@id/text_channel_metadata"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -65,6 +66,7 @@
android:id="@+id/platform_indicator" android:id="@+id/platform_indicator"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
android:contentDescription="@string/cd_platform_indicator"
android:layout_marginTop="18dp" android:layout_marginTop="18dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"

View file

@ -10,6 +10,7 @@
android:id="@+id/image_device" android:id="@+id/image_device"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" android:layout_height="25dp"
android:contentDescription="@string/cd_image_device"
app:srcCompat="@drawable/ic_chromecast" app:srcCompat="@drawable/ic_chromecast"
android:scaleType="fitCenter" android:scaleType="fitCenter"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -63,6 +64,7 @@
android:id="@+id/image_loader" android:id="@+id/image_loader"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" android:layout_height="25dp"
android:contentDescription="@string/cd_image_loader"
app:srcCompat="@drawable/ic_loader_animated" app:srcCompat="@drawable/ic_loader_animated"
android:layout_marginEnd="8dp"/> android:layout_marginEnd="8dp"/>

View file

@ -20,6 +20,7 @@
android:id="@+id/donation_author_image" android:id="@+id/donation_author_image"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_donation_author_image"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"

View file

@ -173,6 +173,7 @@
android:id="@+id/image_trash" android:id="@+id/image_trash"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_delete"
app:srcCompat="@drawable/ic_trash_18dp" app:srcCompat="@drawable/ic_trash_18dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:paddingTop="10dp" android:paddingTop="10dp"

View file

@ -45,7 +45,8 @@
<com.futo.platformplayer.views.platform.PlatformIndicator <com.futo.platformplayer.views.platform.PlatformIndicator
android:id="@+id/platform" android:id="@+id/platform"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" /> android:layout_height="25dp"
android:contentDescription="@string/cd_platform_indicator" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -194,6 +194,7 @@
android:id="@+id/creator_thumbnail" android:id="@+id/creator_thumbnail"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:contentDescription="@string/cd_creator_thumbnail"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
@ -272,6 +273,7 @@
android:id="@+id/thumbnail_platform" android:id="@+id/thumbnail_platform"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" android:layout_height="25dp"
android:contentDescription="@string/cd_platform_indicator"
android:scaleType="centerInside" android:scaleType="centerInside"
tools:src="@drawable/ic_peertube"/> tools:src="@drawable/ic_peertube"/>
</LinearLayout> </LinearLayout>

View file

@ -306,6 +306,7 @@
android:id="@+id/thumbnail_platform" android:id="@+id/thumbnail_platform"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_platform_indicator"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
android:layout_margin="4dp" /> android:layout_margin="4dp" />

View file

@ -14,6 +14,7 @@
android:id="@+id/image_drag_drop" android:id="@+id/image_drag_drop"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_drag_drop"
app:srcCompat="@drawable/ic_dragdrop_white" app:srcCompat="@drawable/ic_dragdrop_white"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:paddingTop="10dp" android:paddingTop="10dp"
@ -116,6 +117,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:scaleType="fitXY" android:scaleType="fitXY"
android:contentDescription="@string/cd_download_indicator"
app:srcCompat="@drawable/download_for_offline" /> app:srcCompat="@drawable/download_for_offline" />
</FrameLayout> </FrameLayout>
</FrameLayout> </FrameLayout>
@ -174,6 +176,7 @@
android:id="@+id/image_trash" android:id="@+id/image_trash"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_delete"
app:srcCompat="@drawable/ic_trash_18dp" app:srcCompat="@drawable/ic_trash_18dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:paddingTop="10dp" android:paddingTop="10dp"

View file

@ -41,6 +41,7 @@
android:id="@+id/thumbnail_platform" android:id="@+id/thumbnail_platform"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_platform_indicator"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_gravity="end" android:layout_gravity="end"

View file

@ -108,6 +108,7 @@
android:id="@+id/creator_thumbnail" android:id="@+id/creator_thumbnail"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:contentDescription="@string/cd_creator_thumbnail"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
@ -161,6 +162,7 @@
android:id="@+id/thumbnail_platform" android:id="@+id/thumbnail_platform"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" android:layout_height="25dp"
android:contentDescription="@string/cd_platform_indicator"
android:scaleType="centerInside" /> android:scaleType="centerInside" />
</LinearLayout> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -72,6 +72,7 @@
android:id="@+id/button_trash" android:id="@+id/button_trash"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_delete"
app:srcCompat="@drawable/ic_trash" app:srcCompat="@drawable/ic_trash"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"

View file

@ -90,6 +90,7 @@
android:id="@+id/platform_indicator" android:id="@+id/platform_indicator"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" android:layout_height="25dp"
android:contentDescription="@string/cd_platform_indicator"
android:scaleType="centerInside" android:scaleType="centerInside"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
app:layout_constraintTop_toTopOf="@id/image_author_thumbnail" app:layout_constraintTop_toTopOf="@id/image_author_thumbnail"
@ -157,6 +158,7 @@
android:id="@+id/image_like_icon" android:id="@+id/image_like_icon"
android:layout_width="18dp" android:layout_width="18dp"
android:layout_height="18dp" android:layout_height="18dp"
android:contentDescription="@string/cd_image_like_icon"
app:srcCompat="@drawable/ic_thumb_up" /> app:srcCompat="@drawable/ic_thumb_up" />
<TextView <TextView
@ -173,6 +175,7 @@
android:id="@+id/image_dislike_icon" android:id="@+id/image_dislike_icon"
android:layout_width="18dp" android:layout_width="18dp"
android:layout_height="18dp" android:layout_height="18dp"
android:contentDescription="@string/cd_image_dislike_icon"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
app:srcCompat="@drawable/ic_thumb_down" /> app:srcCompat="@drawable/ic_thumb_down" />
@ -202,6 +205,7 @@
android:id="@+id/image_comments" android:id="@+id/image_comments"
android:layout_width="18dp" android:layout_width="18dp"
android:layout_height="18dp" android:layout_height="18dp"
android:contentDescription="@string/Replies"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
app:srcCompat="@drawable/ic_forum" /> app:srcCompat="@drawable/ic_forum" />

View file

@ -90,6 +90,7 @@
android:id="@+id/platform_indicator" android:id="@+id/platform_indicator"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_platform_indicator"
android:scaleType="centerInside" android:scaleType="centerInside"
tools:src="@drawable/ic_peertube" tools:src="@drawable/ic_peertube"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"

View file

@ -24,6 +24,7 @@
android:id="@+id/image_source" android:id="@+id/image_source"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:contentDescription="@string/cd_platform_indicator"
app:srcCompat="@drawable/ic_peertube" app:srcCompat="@drawable/ic_peertube"
android:scaleType="fitCenter" /> android:scaleType="fitCenter" />

View file

@ -24,6 +24,7 @@
android:id="@+id/image_source" android:id="@+id/image_source"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:contentDescription="@string/cd_platform_indicator"
app:srcCompat="@drawable/ic_peertube" app:srcCompat="@drawable/ic_peertube"
android:scaleType="fitCenter" /> android:scaleType="fitCenter" />

View file

@ -15,6 +15,7 @@
android:id="@+id/image_drag_drop" android:id="@+id/image_drag_drop"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_drag_drop"
app:srcCompat="@drawable/ic_dragdrop_white" app:srcCompat="@drawable/ic_dragdrop_white"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:paddingTop="10dp" android:paddingTop="10dp"
@ -34,6 +35,7 @@
android:id="@+id/image_source" android:id="@+id/image_source"
android:layout_width="35dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:contentDescription="@string/cd_platform_indicator"
app:srcCompat="@drawable/ic_peertube" app:srcCompat="@drawable/ic_peertube"
android:scaleType="fitCenter" /> android:scaleType="fitCenter" />

View file

@ -14,6 +14,7 @@
android:id="@+id/creator_thumbnail" android:id="@+id/creator_thumbnail"
android:layout_width="46dp" android:layout_width="46dp"
android:layout_height="46dp" android:layout_height="46dp"
android:contentDescription="@string/cd_creator_thumbnail"
android:layout_marginStart="20dp"/> android:layout_marginStart="20dp"/>
<LinearLayout <LinearLayout
@ -42,7 +43,8 @@
<com.futo.platformplayer.views.platform.PlatformIndicator <com.futo.platformplayer.views.platform.PlatformIndicator
android:id="@+id/platform" android:id="@+id/platform"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" /> android:layout_height="25dp"
android:contentDescription="@string/cd_platform_indicator" />
<TextView <TextView
android:id="@+id/text_meta" android:id="@+id/text_meta"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -60,6 +62,7 @@
android:id="@+id/button_settings" android:id="@+id/button_settings"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_settings"
app:srcCompat="@drawable/ic_settings" app:srcCompat="@drawable/ic_settings"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:paddingStart="5dp" android:paddingStart="5dp"
@ -70,6 +73,7 @@
android:id="@+id/button_trash" android:id="@+id/button_trash"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_delete"
app:srcCompat="@drawable/ic_trash" app:srcCompat="@drawable/ic_trash"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:paddingStart="5dp" android:paddingStart="5dp"

View file

@ -13,6 +13,7 @@
android:id="@+id/thumb" android:id="@+id/thumb"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_drag_drop"
android:padding="12dp" android:padding="12dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -25,6 +26,7 @@
android:id="@+id/image" android:id="@+id/image"
android:layout_width="75dp" android:layout_width="75dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_image_group"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/thumb" app:layout_constraintLeft_toRightOf="@id/thumb"
@ -77,6 +79,7 @@
android:id="@+id/button_trash" android:id="@+id/button_trash"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_delete"
android:layout_marginRight="10dp" android:layout_marginRight="10dp"
android:padding="10dp" android:padding="10dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"

View file

@ -17,6 +17,7 @@
android:id="@+id/image_drag_drop" android:id="@+id/image_drag_drop"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_drag_drop"
app:srcCompat="@drawable/ic_dragdrop_white" app:srcCompat="@drawable/ic_dragdrop_white"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:paddingTop="10dp" android:paddingTop="10dp"

View file

@ -134,6 +134,7 @@
android:id="@+id/creator_thumbnail" android:id="@+id/creator_thumbnail"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:contentDescription="@string/cd_creator_thumbnail"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -205,6 +206,7 @@
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_download"
android:scaleType="fitXY" android:scaleType="fitXY"
app:srcCompat="@drawable/download_for_offline" /> app:srcCompat="@drawable/download_for_offline" />
</FrameLayout> </FrameLayout>
@ -213,6 +215,7 @@
android:id="@+id/thumbnail_platform" android:id="@+id/thumbnail_platform"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" android:layout_height="25dp"
android:contentDescription="@string/cd_platform_indicator"
android:scaleType="centerInside" android:scaleType="centerInside"
tools:src="@drawable/ic_peertube" /> tools:src="@drawable/ic_peertube" />
</LinearLayout> </LinearLayout>
@ -230,6 +233,7 @@
android:id="@+id/button_add_to_watch_later" android:id="@+id/button_add_to_watch_later"
android:layout_width="30dp" android:layout_width="30dp"
android:layout_height="30dp" android:layout_height="30dp"
android:contentDescription="@string/cd_button_add_to_watch_later"
android:layout_marginEnd="5dp" android:layout_marginEnd="5dp"
android:background="@drawable/edit_text_background" android:background="@drawable/edit_text_background"
app:srcCompat="@drawable/ic_clock_white" /> app:srcCompat="@drawable/ic_clock_white" />

View file

@ -40,6 +40,7 @@
android:id="@+id/thumbnail_platform_nested" android:id="@+id/thumbnail_platform_nested"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" android:layout_height="25dp"
android:contentDescription="@string/cd_platform_indicator"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
android:layout_margin="5dp" android:layout_margin="5dp"
@ -173,6 +174,7 @@
android:id="@+id/creator_thumbnail" android:id="@+id/creator_thumbnail"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:contentDescription="@string/cd_creator_thumbnail"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
@ -242,6 +244,7 @@
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_button_download"
android:scaleType="fitXY" android:scaleType="fitXY"
app:srcCompat="@drawable/download_for_offline" /> app:srcCompat="@drawable/download_for_offline" />
</FrameLayout> </FrameLayout>
@ -250,6 +253,7 @@
android:id="@+id/thumbnail_platform" android:id="@+id/thumbnail_platform"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp" android:layout_height="25dp"
android:contentDescription="@string/cd_platform_indicator"
android:scaleType="centerInside" android:scaleType="centerInside"
tools:src="@drawable/ic_peertube"/> tools:src="@drawable/ic_peertube"/>
</LinearLayout> </LinearLayout>
@ -267,6 +271,7 @@
android:id="@+id/button_add_to_watch_later" android:id="@+id/button_add_to_watch_later"
android:layout_width="30dp" android:layout_width="30dp"
android:layout_height="30dp" android:layout_height="30dp"
android:contentDescription="@string/cd_button_add_to_watch_later"
android:layout_marginEnd="5dp" android:layout_marginEnd="5dp"
android:background="@drawable/edit_text_background" android:background="@drawable/edit_text_background"
app:srcCompat="@drawable/ic_clock_white" /> app:srcCompat="@drawable/ic_clock_white" />

View file

@ -104,6 +104,7 @@
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_download_indicator"
android:scaleType="fitXY" android:scaleType="fitXY"
app:srcCompat="@drawable/download_for_offline" /> app:srcCompat="@drawable/download_for_offline" />
</FrameLayout> </FrameLayout>
@ -112,6 +113,7 @@
android:id="@+id/thumbnail_platform" android:id="@+id/thumbnail_platform"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_platform_indicator"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_gravity="end" android:layout_gravity="end"
@ -188,6 +190,7 @@
android:id="@+id/button_add_to_watch_later" android:id="@+id/button_add_to_watch_later"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="27dp" android:layout_height="27dp"
android:contentDescription="@string/cd_button_add_to_watch_later"
android:src="@drawable/ic_clock_white" android:src="@drawable/ic_clock_white"
android:paddingTop="7dp" android:paddingTop="7dp"
android:paddingBottom="6dp" android:paddingBottom="6dp"

View file

@ -104,6 +104,7 @@
<ImageView <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/cd_download_indicator"
android:scaleType="fitXY" android:scaleType="fitXY"
app:srcCompat="@drawable/download_for_offline" /> app:srcCompat="@drawable/download_for_offline" />
</FrameLayout> </FrameLayout>
@ -112,6 +113,7 @@
android:id="@+id/thumbnail_platform" android:id="@+id/thumbnail_platform"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_platform_indicator"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_gravity="end" android:layout_gravity="end"
@ -227,6 +229,7 @@
android:id="@+id/button_add_to_watch_later" android:id="@+id/button_add_to_watch_later"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="27dp" android:layout_height="27dp"
android:contentDescription="@string/cd_button_add_to_watch_later"
android:src="@drawable/ic_clock_white" android:src="@drawable/ic_clock_white"
android:paddingTop="7dp" android:paddingTop="7dp"
android:paddingBottom="6dp" android:paddingBottom="6dp"
@ -320,6 +323,7 @@
android:id="@+id/thumbnail_platform_nested" android:id="@+id/thumbnail_platform_nested"
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:contentDescription="@string/cd_platform_indicator"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
android:layout_margin="4dp" /> android:layout_margin="4dp" />

View file

@ -66,6 +66,7 @@
android:id="@+id/button_close" android:id="@+id/button_close"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_close"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:layout_margin="7dp" android:layout_margin="7dp"
@ -126,6 +127,7 @@
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_creator_thumbnail"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
android:layout_margin="20dp" android:layout_margin="20dp"
@ -159,6 +161,7 @@
android:id="@+id/donation_amount" android:id="@+id/donation_amount"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/cd_donation_amount"
android:gravity="center" android:gravity="center"
tools:text="$100" /> tools:text="$100" />
</LinearLayout> </LinearLayout>
@ -229,6 +232,7 @@
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_creator_thumbnail"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:layout_marginStart="-20dp" android:layout_marginStart="-20dp"
android:src="@drawable/placeholder_profile" /> android:src="@drawable/placeholder_profile" />

View file

@ -56,6 +56,7 @@
android:id="@+id/button_close" android:id="@+id/button_close"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_close"
android:padding="5dp" android:padding="5dp"
android:src="@drawable/ic_close" /> android:src="@drawable/ic_close" />
</LinearLayout> </LinearLayout>

View file

@ -25,6 +25,7 @@
android:id="@+id/thumbnail_player_unmute" android:id="@+id/thumbnail_player_unmute"
android:layout_width="34dp" android:layout_width="34dp"
android:layout_height="34dp" android:layout_height="34dp"
android:contentDescription="@string/cd_thumbnail_player_unmute"
android:padding="7dp" android:padding="7dp"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:background="@color/transparent" android:background="@color/transparent"

View file

@ -14,6 +14,7 @@
android:id="@+id/button_minimize" android:id="@+id/button_minimize"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_minimize"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="3dp" android:padding="3dp"
@ -33,6 +34,7 @@
android:id="@+id/button_autoplay" android:id="@+id/button_autoplay"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_autoplay"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -41,6 +43,7 @@
android:id="@+id/button_cast" android:id="@+id/button_cast"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_cast_button"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -49,6 +52,7 @@
android:id="@+id/button_rotate_lock" android:id="@+id/button_rotate_lock"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_rotate_lock"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -57,6 +61,7 @@
android:id="@+id/button_loop" android:id="@+id/button_loop"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_loop"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -65,6 +70,7 @@
android:id="@+id/button_settings" android:id="@+id/button_settings"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_settings"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -75,6 +81,7 @@
android:id="@+id/button_previous" android:id="@+id/button_previous"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:contentDescription="@string/cd_button_previous"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:clickable="true" android:clickable="true"
android:layout_marginRight="40dp" android:layout_marginRight="40dp"
@ -118,6 +125,7 @@
android:id="@+id/button_next" android:id="@+id/button_next"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:contentDescription="@string/cd_button_next"
android:clickable="true" android:clickable="true"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:padding="5dp" android:padding="5dp"
@ -131,6 +139,7 @@
android:id="@+id/button_fullscreen" android:id="@+id/button_fullscreen"
android:layout_width="55dp" android:layout_width="55dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_fullscreen"
android:clickable="true" android:clickable="true"
app:srcCompat="@drawable/ic_expand" app:srcCompat="@drawable/ic_expand"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"

View file

@ -13,6 +13,7 @@
android:id="@+id/button_minimize" android:id="@+id/button_minimize"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_minimize"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:scaleType="fitCenter" android:scaleType="fitCenter"
@ -61,6 +62,7 @@
android:id="@+id/button_autoplay" android:id="@+id/button_autoplay"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_autoplay"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -69,6 +71,7 @@
android:id="@+id/button_cast" android:id="@+id/button_cast"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_cast_button"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -77,6 +80,7 @@
android:id="@+id/button_rotate_lock" android:id="@+id/button_rotate_lock"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_rotate_lock"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -85,6 +89,7 @@
android:id="@+id/button_loop" android:id="@+id/button_loop"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_loop"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -93,6 +98,7 @@
android:id="@+id/button_settings" android:id="@+id/button_settings"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:contentDescription="@string/cd_button_settings"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:clickable="true" android:clickable="true"
android:padding="12dp" android:padding="12dp"
@ -103,6 +109,7 @@
android:id="@+id/button_previous" android:id="@+id/button_previous"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:contentDescription="@string/cd_button_previous"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:clickable="true" android:clickable="true"
android:layout_marginRight="40dp" android:layout_marginRight="40dp"
@ -146,6 +153,7 @@
android:id="@+id/button_next" android:id="@+id/button_next"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:contentDescription="@string/cd_button_next"
android:clickable="true" android:clickable="true"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:padding="5dp" android:padding="5dp"
@ -159,6 +167,7 @@
android:id="@+id/button_fullscreen" android:id="@+id/button_fullscreen"
android:layout_width="55dp" android:layout_width="55dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="@string/cd_button_fullscreen"
android:clickable="true" android:clickable="true"
app:srcCompat="@drawable/ic_expand" app:srcCompat="@drawable/ic_expand"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"

View file

@ -811,6 +811,64 @@
<string name="scroll_to_top">Scroll to top</string> <string name="scroll_to_top">Scroll to top</string>
<string name="disable_battery_optimization">Disable Battery Optimization</string> <string name="disable_battery_optimization">Disable Battery Optimization</string>
<string name="click_to_go_to_battery_optimization_settings_disabling_battery_optimization_will_prevent_the_os_from_killing_media_sessions">Click to go to battery optimization settings. Disabling battery optimization will prevent the OS from killing media sessions.</string> <string name="click_to_go_to_battery_optimization_settings_disabling_battery_optimization_will_prevent_the_os_from_killing_media_sessions">Click to go to battery optimization settings. Disabling battery optimization will prevent the OS from killing media sessions.</string>
<string name="cd_cast_button">Cast button</string>
<string name="cd_incognito_button">Incognito button</string>
<string name="cd_creator_thumbnail">Creator thumbnail</string>
<string name="cd_button_clear_search">Clear search</string>
<string name="cd_button_search">Search</string>
<string name="cd_search_icon">Search icon</string>
<string name="cd_button_back">Back button</string>
<string name="cd_app_icon">App icon</string>
<string name="cd_icon_history">History icon</string>
<string name="cd_button_create_playlist">Create playlist</string>
<string name="cd_button_share">Share</string>
<string name="cd_button_filter">Filter</string>
<string name="cd_button_delete">Delete</string>
<string name="cd_button_settings">Settings</string>
<string name="cd_image_group">Group image</string>
<string name="cd_button_edit">Edit</string>
<string name="cd_button_download">Download</string>
<string name="cd_minimize_close">Close</string>
<string name="cd_minimize_pause">Pause</string>
<string name="cd_minimize_play">Play</string>
<string name="cd_donation_amount">Donation amount</string>
<string name="cd_button_replies">Replies</string>
<string name="cd_image_like_icon">Like</string>
<string name="cd_image_dislike_icon">Dislike</string>
<string name="cd_button_subscribe">Subscribe</string>
<string name="cd_platform_indicator">Platform indicator</string>
<string name="cd_image_device">Device icon</string>
<string name="cd_image_loader">Loader</string>
<string name="cd_donation_author_image">Donation author's image</string>
<string name="cd_edit_image">Edit image</string>
<string name="cd_button_add">Add</string>
<string name="cd_download_indicator">Download indicator</string>
<string name="cd_drag_drop">Drag and drop</string>
<string name="cd_button_add_to_watch_later">Add to Watch Later</string>
<string name="cd_button_close">Close</string>
<string name="cd_thumbnail_player_unmute">Unmute</string>
<string name="cd_button_minimize">Minimize</string>
<string name="cd_button_rotate_lock">Lock rotation</string>
<string name="cd_button_loop">Loop</string>
<string name="cd_button_previous">Previous</string>
<string name="cd_button_next">Next</string>
<string name="cd_button_fullscreen">Fullscreen</string>
<string name="cd_button_autoplay">Autoplay</string>
<string name="cd_update_spinner">Update spinner</string>
<string name="cd_button_play">Play</string>
<string name="cd_button_pause">Pause</string>
<string name="cd_button_stop">Stop</string>
<string name="cd_button_scan_qr">Scan QR code</string>
<string name="cd_button_help">Help</string>
<string name="cd_image_polycentric">Change Polycentric profile picture</string>
<string name="cd_button_settings">Settings</string>
<string name="cd_button_settings">Settings</string>
<string name="cd_button_settings">Settings</string>
<string name="cd_button_settings">Settings</string>
<string name="cd_button_settings">Settings</string>
<string name="cd_button_settings">Settings</string>
<string name="cd_button_settings">Settings</string>
<string name="cd_button_settings">Settings</string>
<string-array name="home_screen_array"> <string-array name="home_screen_array">
<item>Recommendations</item> <item>Recommendations</item>
<item>Subscriptions</item> <item>Subscriptions</item>

@ -1 +1 @@
Subproject commit 58ea77229dcdb5c9ce8f1bd642baf29486d0bf21 Subproject commit 543a727d781fe5780fd0e8f20d53f6a53b285446

@ -1 +1 @@
Subproject commit 80c9b4d3b48739170b40b313be930329dcc59fe4 Subproject commit 0ce91be276681ab82d26f9471523beab6b2a0a00

View file

@ -524,8 +524,8 @@ class NoiseProtocolTest {
println("Initiator handshake complete") println("Initiator handshake complete")
handshakeLatch.countDown() // Handshake complete for initiator handshakeLatch.countDown() // Handshake complete for initiator
}, },
onData = { session, opcode, data -> onData = { session, opcode, subOpcode, data ->
println("Initiator received: Opcode $opcode, Data Length: ${data.remaining()}") println("Initiator received: Opcode: $opcode, SubOpcode: $subOpcode, Data Length: ${data.remaining()}")
when (data.remaining()) { when (data.remaining()) {
randomBytesExactlyOnePacket.remaining() -> { randomBytesExactlyOnePacket.remaining() -> {
@ -556,8 +556,8 @@ class NoiseProtocolTest {
println("Responder handshake complete") println("Responder handshake complete")
handshakeLatch.countDown() // Handshake complete for responder handshakeLatch.countDown() // Handshake complete for responder
}, },
onData = { session, opcode, data -> onData = { session, opcode, subOpcode, data ->
println("Responder received: Opcode $opcode, Data Length: ${data.remaining()}") println("Responder received: Opcode $opcode, SubOpcode $subOpcode, Data Length: ${data.remaining()}")
when (data.remaining()) { when (data.remaining()) {
randomBytesExactlyOnePacket.remaining() -> { randomBytesExactlyOnePacket.remaining() -> {
@ -590,12 +590,12 @@ class NoiseProtocolTest {
responderSession.send(SyncSocketSession.Opcode.PONG.value) responderSession.send(SyncSocketSession.Opcode.PONG.value)
// Test data transfer // Test data transfer
responderSession.send(SyncSocketSession.Opcode.NOTIFY_AUTHORIZED.value, randomBytesExactlyOnePacket) responderSession.send(SyncSocketSession.Opcode.DATA.value, 0u, randomBytesExactlyOnePacket)
initiatorSession.send(SyncSocketSession.Opcode.NOTIFY_AUTHORIZED.value, randomBytes) initiatorSession.send(SyncSocketSession.Opcode.DATA.value, 1u, randomBytes)
// Send large data to test stream handling // Send large data to test stream handling
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
responderSession.send(SyncSocketSession.Opcode.NOTIFY_AUTHORIZED.value, randomBytesBig) responderSession.send(SyncSocketSession.Opcode.DATA.value, 0u, randomBytesBig)
println("Sent 10MB in ${System.currentTimeMillis() - start}ms") println("Sent 10MB in ${System.currentTimeMillis() - start}ms")
// Wait for a brief period to simulate delay and allow communication // Wait for a brief period to simulate delay and allow communication

@ -1 +1 @@
Subproject commit 58ea77229dcdb5c9ce8f1bd642baf29486d0bf21 Subproject commit 543a727d781fe5780fd0e8f20d53f6a53b285446

@ -1 +1 @@
Subproject commit 80c9b4d3b48739170b40b313be930329dcc59fe4 Subproject commit 0ce91be276681ab82d26f9471523beab6b2a0a00