addressing pr comments

This commit is contained in:
Trevor
2025-10-01 13:11:59 -05:00
parent 25ab7aff92
commit 1abcc92a3b
6 changed files with 74 additions and 89 deletions
-2
View File
@@ -231,6 +231,4 @@ dependencies {
testImplementation "org.mockito:mockito-core:5.4.0"
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
//ffmpeg
implementation files('libs/ffmpeg-kit-full-6.0-2.aar')
}
Binary file not shown.
+1 -1
View File
@@ -30,7 +30,7 @@
android:largeHeap="true">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:authorities="@string/authority"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
@@ -13,8 +13,8 @@ import android.view.View
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.lifecycle.lifecycleScope
import com.futo.platformplayer.R
import com.futo.platformplayer.UIDialogs
@@ -42,10 +42,6 @@ import kotlinx.coroutines.withContext
import userpackage.Protocol
import userpackage.Protocol.ExportBundle
import userpackage.Protocol.URLInfo
import java.io.File
import java.io.FileWriter
import android.content.ContentValues
import android.provider.MediaStore
class PolycentricBackupActivity : AppCompatActivity() {
private lateinit var _buttonShare: BigButton;
@@ -57,6 +53,20 @@ class PolycentricBackupActivity : AppCompatActivity() {
private lateinit var _textQRHint: TextView;
private lateinit var _loader: View
private val _createDocumentLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) { uri ->
uri?.let { fileUri ->
try {
contentResolver.openOutputStream(fileUri)?.use { outputStream ->
outputStream.write(_exportBundle.toByteArray())
}
UIDialogs.toast(this, getString(R.string.profile_saved_successfully))
} catch (e: Exception) {
Logger.e(TAG, "Failed to write to document", e)
UIDialogs.toast(this, "Failed to save profile: ${e.message}")
}
}
}
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
}
@@ -149,7 +159,8 @@ class PolycentricBackupActivity : AppCompatActivity() {
};
_buttonExportFile.onClick.subscribe {
exportToFile()
val fileName = "polycentric_profile_${System.currentTimeMillis()}.txt"
_createDocumentLauncher.launch(fileName)
};
}
@@ -263,81 +274,6 @@ class PolycentricBackupActivity : AppCompatActivity() {
return "polycentric://" + data.toBase64Url()
}
private fun exportToFile() {
try {
val fileName = "polycentric_profile_${System.currentTimeMillis()}.txt"
val file = File(filesDir, fileName)
FileWriter(file).use { writer ->
writer.write(_exportBundle)
}
val uri = FileProvider.getUriForFile(
this,
"${packageName}.fileprovider",
file
)
// Show dialog with options
UIDialogs.showDialog(
this,
R.drawable.ic_download,
getString(R.string.export_profile),
getString(R.string.choose_export_option),
null,
-1,
UIDialogs.Action(getString(R.string.share), {
// Share the file
val shareIntent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_STREAM, uri)
putExtra(Intent.EXTRA_SUBJECT, "Polycentric Profile Export")
putExtra(Intent.EXTRA_TEXT, "Polycentric profile export file")
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(Intent.createChooser(shareIntent, getString(R.string.share_profile)))
}, UIDialogs.ActionStyle.NONE, true),
UIDialogs.Action(getString(R.string.save_to_device), {
// Save to device
saveToDevice(fileName)
}, UIDialogs.ActionStyle.NONE, true)
)
} catch (e: Exception) {
Logger.e(TAG, "Failed to export to file", e)
UIDialogs.toast(this, "Failed to export profile to file")
}
}
private fun saveToDevice(fileName: String) {
try {
// Use MediaStore API to save to Downloads folder
val contentValues = ContentValues().apply {
put(MediaStore.Downloads.DISPLAY_NAME, fileName)
put(MediaStore.Downloads.MIME_TYPE, "text/plain")
put(MediaStore.Downloads.IS_PENDING, 1)
}
val resolver = contentResolver
val uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
uri?.let { fileUri ->
resolver.openOutputStream(fileUri)?.use { outputStream ->
outputStream.write(_exportBundle.toByteArray())
}
contentValues.clear()
contentValues.put(MediaStore.Downloads.IS_PENDING, 0)
resolver.update(fileUri, contentValues, null, null)
UIDialogs.toast(this, getString(R.string.profile_saved_to_downloads))
} ?: run {
UIDialogs.toast(this, getString(R.string.failed_to_save_profile))
}
} catch (e: Exception) {
Logger.e(TAG, "Failed to save to device", e)
UIDialogs.toast(this, getString(R.string.failed_to_save_profile))
}
}
companion object {
private const val TAG = "PolycentricBackupActivity";
@@ -52,10 +52,46 @@ class PolycentricImportProfileActivity : AppCompatActivity() {
private val _filePickerLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
uri?.let { fileUri ->
try {
// Check file size before reading
val fileSize = contentResolver.openFileDescriptor(fileUri, "r")?.statSize ?: 0
val maxFileSize = 10 * 1024 * 1024 // 10MB limit
if (fileSize > maxFileSize) {
UIDialogs.toast(this, "File too large. Maximum size is 10MB.")
return@let
}
if (fileSize == 0L) {
UIDialogs.toast(this, "Selected file is empty.")
return@let
}
val content = contentResolver.openInputStream(fileUri)?.bufferedReader()?.readText()
content?.let { fileContent ->
import(fileContent.trim())
val trimmedContent = fileContent.trim()
// Check if content is empty after trimming
if (trimmedContent.isEmpty()) {
UIDialogs.toast(this, "Selected file contains no data.")
return@let
}
// Check if content looks like a valid polycentric URL
if (!trimmedContent.startsWith("polycentric://")) {
UIDialogs.toast(this, "Selected file does not contain a valid polycentric profile URL.")
return@let
}
import(trimmedContent)
} ?: run {
UIDialogs.toast(this, "Could not read file content.")
}
} catch (e: SecurityException) {
Logger.e(TAG, "Security exception reading file", e)
UIDialogs.toast(this, "Permission denied to read file.")
} catch (e: OutOfMemoryError) {
Logger.e(TAG, "Out of memory reading file", e)
UIDialogs.toast(this, "File too large to process.")
} catch (e: Exception) {
Logger.e(TAG, "Failed to read file", e)
UIDialogs.toast(this, "Failed to read file: ${e.message}")
@@ -32,7 +32,13 @@ class PolycentricModerationActivity : AppCompatActivity() {
setContentView(R.layout.activity_polycentric_moderation)
setNavigationBarColorAndIcons()
_moderationsManager = ModerationsManager.getInstance()
try {
_moderationsManager = ModerationsManager.getInstance()
} catch (e: IllegalStateException) {
// ModerationsManager not initialized, finish activity
finish()
return
}
_seekbarOffensive = findViewById(R.id.seekbar_offensive)
_seekbarExplicit = findViewById(R.id.seekbar_explicit)
@@ -44,7 +50,7 @@ class PolycentricModerationActivity : AppCompatActivity() {
_textExplicitValue = findViewById(R.id.text_explicit_value)
_textViolenceValue = findViewById(R.id.text_violence_value)
findViewById<ImageButton>(R.id.button_back).setOnClickListener {
findViewById<ImageButton>(R.id.button_back)?.setOnClickListener {
finish()
}
@@ -53,6 +59,8 @@ class PolycentricModerationActivity : AppCompatActivity() {
}
private fun loadSettings() {
if (isFinishing || isDestroyed) return
val levels = _moderationsManager.moderationLevels.value ?: mapOf()
val offensiveLevel = levels["hate"] ?: 2
@@ -71,6 +79,7 @@ class PolycentricModerationActivity : AppCompatActivity() {
private fun setupListeners() {
_seekbarOffensive.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (isFinishing || isDestroyed) return
updateDescriptionText(seekBar, _textOffensiveDesc, _textOffensiveValue, getOffensiveDescriptions())
if (fromUser) {
_moderationsManager.setModerationLevel("hate", progress)
@@ -83,6 +92,7 @@ class PolycentricModerationActivity : AppCompatActivity() {
_seekbarExplicit.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (isFinishing || isDestroyed) return
updateDescriptionText(seekBar, _textExplicitDesc, _textExplicitValue, getExplicitDescriptions())
if (fromUser) {
_moderationsManager.setModerationLevel("sexual", progress)
@@ -95,6 +105,7 @@ class PolycentricModerationActivity : AppCompatActivity() {
_seekbarViolence.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (isFinishing || isDestroyed) return
updateDescriptionText(seekBar, _textViolenceDesc, _textViolenceValue, getViolenceDescriptions())
if (fromUser) {
_moderationsManager.setModerationLevel("violence", progress)
@@ -107,9 +118,13 @@ class PolycentricModerationActivity : AppCompatActivity() {
}
private fun updateDescriptionText(seekBar: SeekBar?, textDesc: TextView, textValue: TextView, descriptions: Array<String>) {
if (isFinishing || isDestroyed) return
val progress = seekBar?.progress ?: 0
textDesc.text = descriptions[progress]
textValue.text = progress.toString()
if (progress in descriptions.indices) {
textDesc.text = descriptions[progress]
textValue.text = progress.toString()
}
}
private fun getOffensiveDescriptions(): Array<String> {