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,9 +95,11 @@ 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) {
synchronized(_socketSessions) { synchronized(_socketSessions) {
@ -117,8 +120,9 @@ 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()})") try {
Logger.i(TAG, "Handle packet (opcode: ${opcode}, subOpcode: ${subOpcode}, data.length: ${data.remaining()})")
when (opcode) { when (opcode) {
Opcode.NOTIFY_AUTHORIZED.value -> { Opcode.NOTIFY_AUTHORIZED.value -> {
@ -136,10 +140,14 @@ class SyncSession : IAuthorizable {
return return
} }
Logger.i(TAG, "Received ${opcode} (${data.remaining()} bytes)") 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 //TODO: Abstract this out
try { when (subOpcode) {
when (opcode) {
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