Add configurable upload parameter defaults with optional prompt

Users can now set default upload parameters (max downloads and expiry hours) in settings and choose whether to show the upload parameters dialog or use saved defaults directly.

Changes:
- Add upload preferences: default max downloads, default expiry hours, and ask before upload toggle
- Update SettingsScreen with new upload defaults section
- Modify UploadParamsDialog to initialize with saved defaults instead of hardcoded values
- Update DumpstateTab and GeneralUploadTab to check askBeforeUpload preference and bypass dialog when disabled
This commit is contained in:
2025-12-27 19:14:24 -05:00
parent d9052454fe
commit e60cdf9355
5 changed files with 219 additions and 8 deletions

View File

@@ -5,8 +5,10 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import com.mattintech.simplelogupload.util.PreferencesUtil
/**
* Dialog for entering upload parameters
@@ -19,8 +21,13 @@ fun UploadParamsDialog(
onDismiss: () -> Unit,
onConfirm: (Int, Int) -> Unit
) {
var maxDownloads by remember { mutableStateOf("5") }
var expiryHours by remember { mutableStateOf("24") }
val context = LocalContext.current
var maxDownloads by remember {
mutableStateOf(PreferencesUtil.getDefaultMaxDownloads(context).toString())
}
var expiryHours by remember {
mutableStateOf(PreferencesUtil.getDefaultExpiryHours(context).toString())
}
var maxDownloadsError by remember { mutableStateOf<String?>(null) }
var expiryHoursError by remember { mutableStateOf<String?>(null) }

View File

@@ -45,10 +45,21 @@ fun SettingsScreen(
var clientKey by remember {
mutableStateOf(PreferencesUtil.getClientKey(context))
}
var defaultMaxDownloads by remember {
mutableStateOf(PreferencesUtil.getDefaultMaxDownloads(context).toString())
}
var defaultExpiryHours by remember {
mutableStateOf(PreferencesUtil.getDefaultExpiryHours(context).toString())
}
var askBeforeUpload by remember {
mutableStateOf(PreferencesUtil.getAskBeforeUpload(context))
}
var serverAddressError by remember { mutableStateOf<String?>(null) }
var serverPortError by remember { mutableStateOf<String?>(null) }
var clientKeyError by remember { mutableStateOf<String?>(null) }
var maxDownloadsError by remember { mutableStateOf<String?>(null) }
var expiryHoursError by remember { mutableStateOf<String?>(null) }
// QR scanner launcher
val qrScannerLauncher = rememberLauncherForActivityResult(
@@ -108,6 +119,8 @@ fun SettingsScreen(
serverAddressError = null
serverPortError = null
clientKeyError = null
maxDownloadsError = null
expiryHoursError = null
var hasError = false
@@ -135,12 +148,29 @@ fun SettingsScreen(
hasError = true
}
// Validate max downloads
val maxDl = defaultMaxDownloads.toIntOrNull()
if (maxDl == null || maxDl < 0) {
maxDownloadsError = "Must be 0 or greater (0 = unlimited)"
hasError = true
}
// Validate expiry hours
val expiry = defaultExpiryHours.toIntOrNull()
if (expiry == null || expiry <= 0 || expiry > 24) {
expiryHoursError = "Must be between 1 and 24 hours"
hasError = true
}
if (hasError) return
// Save settings
PreferencesUtil.setServerAddress(context, serverAddress)
PreferencesUtil.setServerPort(context, serverPort.toInt())
PreferencesUtil.setClientKey(context, clientKey)
PreferencesUtil.setDefaultMaxDownloads(context, maxDl!!)
PreferencesUtil.setDefaultExpiryHours(context, expiry!!)
PreferencesUtil.setAskBeforeUpload(context, askBeforeUpload)
Toast.makeText(context, "Settings saved successfully!", Toast.LENGTH_SHORT).show()
onNavigateBack()
@@ -151,11 +181,16 @@ fun SettingsScreen(
serverAddress = PreferencesUtil.getServerAddress(context)
serverPort = PreferencesUtil.getServerPort(context).toString()
clientKey = PreferencesUtil.getClientKey(context)
defaultMaxDownloads = PreferencesUtil.getDefaultMaxDownloads(context).toString()
defaultExpiryHours = PreferencesUtil.getDefaultExpiryHours(context).toString()
askBeforeUpload = PreferencesUtil.getAskBeforeUpload(context)
// Clear errors
serverAddressError = null
serverPortError = null
clientKeyError = null
maxDownloadsError = null
expiryHoursError = null
Toast.makeText(context, "Settings reset", Toast.LENGTH_SHORT).show()
}
@@ -234,8 +269,88 @@ fun SettingsScreen(
singleLine = true
)
Spacer(modifier = Modifier.height(24.dp))
// Upload Defaults Section
Text(
text = "Upload Defaults",
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.primary
)
Spacer(modifier = Modifier.height(8.dp))
// Default Max Downloads
OutlinedTextField(
value = defaultMaxDownloads,
onValueChange = {
defaultMaxDownloads = it
maxDownloadsError = null
},
label = { Text("Default Maximum Downloads") },
placeholder = { Text("5") },
modifier = Modifier.fillMaxWidth(),
isError = maxDownloadsError != null,
supportingText = {
Text(maxDownloadsError ?: "Set to 0 for unlimited downloads")
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
singleLine = true
)
// Default Expiry Hours
OutlinedTextField(
value = defaultExpiryHours,
onValueChange = {
defaultExpiryHours = it
expiryHoursError = null
},
label = { Text("Default Expiry Time (hours)") },
placeholder = { Text("24") },
modifier = Modifier.fillMaxWidth(),
isError = expiryHoursError != null,
supportingText = {
Text(expiryHoursError ?: "Maximum 24 hours (1 day)")
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
singleLine = true
)
// Ask Before Upload Switch
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = "Ask Before Upload",
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = if (askBeforeUpload) "Show upload parameters dialog" else "Use default settings",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Switch(
checked = askBeforeUpload,
onCheckedChange = { askBeforeUpload = it }
)
}
}
Spacer(modifier = Modifier.height(24.dp))
// QR Scan Button
OutlinedButton(
onClick = {

View File

@@ -13,6 +13,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.mattintech.simplelogupload.ui.components.UploadParamsDialog
import com.mattintech.simplelogupload.ui.components.UploadResultDialog
import com.mattintech.simplelogupload.util.PreferencesUtil
import com.mattintech.simplelogupload.viewmodel.MainViewModel
import java.text.SimpleDateFormat
import java.util.*
@@ -138,7 +139,15 @@ fun DumpstateTab(
// Upload button
Button(
onClick = { viewModel.showUploadParamsDialog() },
onClick = {
if (PreferencesUtil.getAskBeforeUpload(context)) {
viewModel.showUploadParamsDialog()
} else {
val maxDownloads = PreferencesUtil.getDefaultMaxDownloads(context)
val expiryHours = PreferencesUtil.getDefaultExpiryHours(context)
viewModel.uploadSelectedDumpstates(maxDownloads, expiryHours)
}
},
modifier = Modifier.fillMaxWidth(),
enabled = !uiState.isLoading && uiState.selectedDumpstateIndices.isNotEmpty()
) {

View File

@@ -21,6 +21,7 @@ import androidx.compose.ui.unit.dp
import com.mattintech.simplelogupload.ui.components.UploadParamsDialog
import com.mattintech.simplelogupload.ui.components.UploadResultDialog
import com.mattintech.simplelogupload.util.PermissionUtil
import com.mattintech.simplelogupload.util.PreferencesUtil
import com.mattintech.simplelogupload.viewmodel.MainViewModel
/**
@@ -166,7 +167,17 @@ fun GeneralUploadTab(
Spacer(modifier = Modifier.height(16.dp))
Button(
onClick = { viewModel.showUploadParamsDialog() },
onClick = {
if (PreferencesUtil.getAskBeforeUpload(context)) {
viewModel.showUploadParamsDialog()
} else {
val maxDownloads = PreferencesUtil.getDefaultMaxDownloads(context)
val expiryHours = PreferencesUtil.getDefaultExpiryHours(context)
uiState.selectedFile?.let { file ->
viewModel.uploadFile(file, maxDownloads, expiryHours)
}
}
},
modifier = Modifier.fillMaxWidth(),
enabled = !uiState.isLoading
) {

View File

@@ -14,12 +14,18 @@ public class PreferencesUtil {
public static final String KEY_SERVER_PORT = "server_port";
public static final String KEY_CLIENT_KEY = "client_key";
public static final String KEY_SETUP_COMPLETED = "setup_completed";
public static final String KEY_DEFAULT_MAX_DOWNLOADS = "default_max_downloads";
public static final String KEY_DEFAULT_EXPIRY_HOURS = "default_expiry_hours";
public static final String KEY_ASK_BEFORE_UPLOAD = "ask_before_upload";
// Default values
private static final String DEFAULT_SERVER_ADDRESS = "";
private static final int DEFAULT_SERVER_PORT = 0;
private static final String DEFAULT_CLIENT_KEY = "";
private static final boolean DEFAULT_SETUP_COMPLETED = false;
private static final int DEFAULT_MAX_DOWNLOADS = 5;
private static final int DEFAULT_EXPIRY_HOURS = 24;
private static final boolean DEFAULT_ASK_BEFORE_UPLOAD = true;
/**
* Get the shared preferences instance
@@ -126,6 +132,9 @@ public class PreferencesUtil {
editor.putInt(KEY_SERVER_PORT, DEFAULT_SERVER_PORT);
editor.putString(KEY_CLIENT_KEY, DEFAULT_CLIENT_KEY);
editor.putBoolean(KEY_SETUP_COMPLETED, DEFAULT_SETUP_COMPLETED);
editor.putInt(KEY_DEFAULT_MAX_DOWNLOADS, DEFAULT_MAX_DOWNLOADS);
editor.putInt(KEY_DEFAULT_EXPIRY_HOURS, DEFAULT_EXPIRY_HOURS);
editor.putBoolean(KEY_ASK_BEFORE_UPLOAD, DEFAULT_ASK_BEFORE_UPLOAD);
editor.apply();
}
@@ -149,6 +158,66 @@ public class PreferencesUtil {
getPreferences(context).edit().putBoolean(KEY_SETUP_COMPLETED, completed).apply();
}
/**
* Get the default max downloads from preferences
*
* @param context The application context
* @return The default max downloads
*/
public static int getDefaultMaxDownloads(Context context) {
return getPreferences(context).getInt(KEY_DEFAULT_MAX_DOWNLOADS, DEFAULT_MAX_DOWNLOADS);
}
/**
* Set the default max downloads in preferences
*
* @param context The application context
* @param maxDownloads The default max downloads to save
*/
public static void setDefaultMaxDownloads(Context context, int maxDownloads) {
getPreferences(context).edit().putInt(KEY_DEFAULT_MAX_DOWNLOADS, maxDownloads).apply();
}
/**
* Get the default expiry hours from preferences
*
* @param context The application context
* @return The default expiry hours
*/
public static int getDefaultExpiryHours(Context context) {
return getPreferences(context).getInt(KEY_DEFAULT_EXPIRY_HOURS, DEFAULT_EXPIRY_HOURS);
}
/**
* Set the default expiry hours in preferences
*
* @param context The application context
* @param expiryHours The default expiry hours to save
*/
public static void setDefaultExpiryHours(Context context, int expiryHours) {
getPreferences(context).edit().putInt(KEY_DEFAULT_EXPIRY_HOURS, expiryHours).apply();
}
/**
* Get the ask before upload preference
*
* @param context The application context
* @return True if should ask before upload, false otherwise
*/
public static boolean getAskBeforeUpload(Context context) {
return getPreferences(context).getBoolean(KEY_ASK_BEFORE_UPLOAD, DEFAULT_ASK_BEFORE_UPLOAD);
}
/**
* Set the ask before upload preference
*
* @param context The application context
* @param askBeforeUpload True if should ask before upload, false otherwise
*/
public static void setAskBeforeUpload(Context context, boolean askBeforeUpload) {
getPreferences(context).edit().putBoolean(KEY_ASK_BEFORE_UPLOAD, askBeforeUpload).apply();
}
/**
* Check if all required server settings are configured
*