Skip to content

Commit

Permalink
import / export
Browse files Browse the repository at this point in the history
  • Loading branch information
Duron27 committed Oct 15, 2024
1 parent 8e782a5 commit 04f4e21
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 6 deletions.
Empty file modified app/src/main/java/org/openmw/EngineActivity.kt
100755 → 100644
Empty file.
41 changes: 38 additions & 3 deletions app/src/main/java/org/openmw/SettingScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
Expand All @@ -23,16 +24,21 @@ import org.openmw.navigation.MyFloatingActionButton
import org.openmw.navigation.MyTopBar
import org.openmw.utils.ExpandableBox
import org.openmw.utils.ReadAndDisplayIniValues
import org.openmw.utils.exportFilesAndDirectories
import org.openmw.utils.importFilesAndDirectories

@ExperimentalMaterial3Api
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable
fun SettingScreen(context: Context, navigateToHome: () -> Unit) {
val transparentBlack = Color(alpha = 0.6f, red = 0f, green = 0f, blue = 0f)
var showDialog = remember { mutableStateOf(false) }

Scaffold(
topBar = {
MyTopBar(context)
}, content = @Composable {
},
content = @Composable {
BouncingBackground()
Box(
modifier = Modifier
Expand All @@ -44,13 +50,42 @@ fun SettingScreen(context: Context, navigateToHome: () -> Unit) {
.padding(top = 40.dp, bottom = 60.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally

) {
ReadAndDisplayIniValues()
ExpandableBox(expanded = remember { mutableStateOf(false) })

Button(onClick = { exportFilesAndDirectories(context) }) {
Text(text = "Backup all saves, config files and screenshots", color = Color.White)
}

Button(onClick = { showDialog.value = true }) {
Text(text = "Restore all saves, config files and screenshots", color = Color.White)
}
}

if (showDialog.value) {
AlertDialog(
onDismissRequest = { showDialog.value = false },
title = { Text("Confirm Import") },
text = { Text("Are you sure you want to restore all saves, config files, and screenshots?") },
confirmButton = {
Button(onClick = {
importFilesAndDirectories(context)
showDialog.value = false
}) {
Text("Yes")
}
},
dismissButton = {
Button(onClick = { showDialog.value = false }) {
Text("No")
}
}
)
}
}
}, bottomBar = {
},
bottomBar = {
BottomAppBar(
containerColor = transparentBlack,
actions = {
Expand Down
11 changes: 8 additions & 3 deletions app/src/main/java/org/openmw/navigation/TopBottomBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,15 @@ fun MyFloatingActionButton(context: Context) {

FloatingActionButton(
onClick = {
val intent = Intent(context, EngineActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val uri = getGameFilesUri(context)
if (uri != null && uri.contains("Morrowind")) {
val intent = Intent(context, EngineActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(intent)
} else {
Toast.makeText(context, "Morrowind folder not found. Please select game files.", Toast.LENGTH_LONG).show()
}
context.startActivity(intent)
},
containerColor = Color(alpha = 0.6f, red = 0f, green = 0f, blue = 0f),
elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation()
Expand Down
123 changes: 123 additions & 0 deletions app/src/main/java/org/openmw/utils/ImportExport.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,18 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import org.openmw.Constants
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.InputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

@Composable
fun CfgImport() {
Expand Down Expand Up @@ -103,3 +112,117 @@ fun copyFile(context: Context, uri: Uri, destinationFile: File) {
}
}
}

fun zipFilesAndDirectories(rootDirectory: File, files: List<File>, directories: List<File>, zipFile: File) {
ZipOutputStream(BufferedOutputStream(FileOutputStream(zipFile))).use { out ->
val addedEntries = mutableSetOf<String>()

// Add files to the zip
files.forEach { file ->
FileInputStream(file).use { fi ->
BufferedInputStream(fi).use { origin ->
val entryName = file.relativeTo(rootDirectory).path
if (addedEntries.add(entryName)) {
val entry = ZipEntry(entryName)
out.putNextEntry(entry)
origin.copyTo(out, 1024)
out.closeEntry()
}
}
}
}

// Add directories to the zip
directories.forEach { dir ->
dir.walkTopDown().forEach { file ->
val entryName = file.relativeTo(rootDirectory).path
if (file.isDirectory && !addedEntries.contains(entryName)) {
out.putNextEntry(ZipEntry("$entryName/"))
addedEntries.add(entryName)
out.closeEntry()
} else if (file.isFile) {
FileInputStream(file).use { fi ->
BufferedInputStream(fi).use { origin ->
if (addedEntries.add(entryName)) {
val entry = ZipEntry(entryName)
out.putNextEntry(entry)
origin.copyTo(out, 1024)
out.closeEntry()
}
}
}
}
}
}
}
}

fun exportFilesAndDirectories(context: Context) {
val downloadFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val dateFormat = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault())
val date = dateFormat.format(Date())
val zipFile = File(downloadFolder, "openmw_$date.zip")
val rootDirectory = File(Constants.USER_FILE_STORAGE)

try {
val filesToZip = listOf(
File("${Constants.USER_FILE_STORAGE}/config/openmw.cfg"),
File("${Constants.USER_FILE_STORAGE}/config/settings.cfg"),
File("${Constants.USER_FILE_STORAGE}/config/shaders.yaml")
)
val directoriesToZip = listOf(
File("${Constants.USER_FILE_STORAGE}/saves"),
File("${Constants.USER_FILE_STORAGE}/screenshots")
)
zipFilesAndDirectories(rootDirectory, filesToZip, directoriesToZip, zipFile)
Toast.makeText(context, "Files and directories zipped and exported to Downloads", Toast.LENGTH_SHORT).show()
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(context, "Export failed: ${e.message}", Toast.LENGTH_SHORT).show()
}
}

fun unzipFiles(zipFile: File, targetDirectory: File) {
ZipInputStream(FileInputStream(zipFile)).use { zis ->
var entry: ZipEntry?
while (zis.nextEntry.also { entry = it } != null) {
val newFile = File(targetDirectory, entry!!.name)
// Create directories for subfolders
if (entry!!.isDirectory) {
newFile.mkdirs()
} else {
// Extract files
FileOutputStream(newFile).use { fos ->
val buffer = ByteArray(1024)
var len: Int
while (zis.read(buffer).also { len = it } > 0) {
fos.write(buffer, 0, len)
}
}
}
zis.closeEntry()
}
}
}

fun importFilesAndDirectories(context: Context) {
val downloadFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val targetDirectory = File(Constants.USER_FILE_STORAGE)

try {
val newestZipFile = downloadFolder.listFiles { _, name ->
name.startsWith("openmw_") && name.endsWith(".zip")
}?.maxByOrNull { it.lastModified() }

if (newestZipFile != null) {
unzipFiles(newestZipFile, targetDirectory)
Toast.makeText(context, "Files and directories imported successfully", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "No zip files found for import", Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(context, "Import failed: ${e.message}", Toast.LENGTH_SHORT).show()
}
}

0 comments on commit 04f4e21

Please sign in to comment.