From 4ee420c965a6b0f1b6728fb93a7113ebb10009fd Mon Sep 17 00:00:00 2001 From: Davide Depau Date: Fri, 17 Aug 2018 02:43:58 +0200 Subject: [PATCH] Show DMG partition table in image picker screen --- app/build.gradle | 1 + .../java/eu/depau/etchdroid/StateKeeper.kt | 2 +- .../PartitionTableRecyclerViewAdapter.kt | 76 +++++++++++++++++++ .../depau/etchdroid/enums/FilesystemType.kt | 35 ++++++++- .../etchdroid/enums/PartitionTableType.kt | 22 +++++- .../fragments/ImageLocationFragment.kt | 54 +++++++++---- .../main/res/layout/fragment_confirminfo.xml | 16 ++-- .../res/layout/fragment_select_location.xml | 73 +++++++++--------- .../main/res/layout/part_data_keyvalue.xml | 26 +++++++ app/src/main/res/layout/partition_row.xml | 31 ++++++++ app/src/main/res/layout/usb_device_row.xml | 4 +- app/src/main/res/values/dimens.xml | 3 +- app/src/main/res/values/strings.xml | 44 ++++++++++- app/src/main/res/values/styles.xml | 4 +- 14 files changed, 325 insertions(+), 66 deletions(-) create mode 100644 app/src/main/java/eu/depau/etchdroid/adapters/PartitionTableRecyclerViewAdapter.kt create mode 100644 app/src/main/res/layout/part_data_keyvalue.xml create mode 100644 app/src/main/res/layout/partition_row.xml diff --git a/app/build.gradle b/app/build.gradle index c8245d4..b2ebfeb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,6 +30,7 @@ dependencies { implementation 'com.android.support.constraint:constraint-layout:1.1.2' implementation 'com.android.support:design:28.0.0-rc01' implementation 'com.android.support:recyclerview-v7:28.0.0-rc01' + implementation 'com.android.support:gridlayout-v7:28.0.0-rc01' implementation 'com.github.isabsent:filepicker:1.1.01' // implementation 'com.github.mjdev:libaums:0.5.5' diff --git a/app/src/main/java/eu/depau/etchdroid/StateKeeper.kt b/app/src/main/java/eu/depau/etchdroid/StateKeeper.kt index 412799a..69d85fd 100644 --- a/app/src/main/java/eu/depau/etchdroid/StateKeeper.kt +++ b/app/src/main/java/eu/depau/etchdroid/StateKeeper.kt @@ -13,7 +13,7 @@ object StateKeeper { var wizardStep: WizardStep = WizardStep.SELECT_FLASH_METHOD var currentFragment: WizardFragment? = null var flashMethod: FlashMethod? = null - var imageLocation: ImageLocation? = null + var imageLocation: ImageLocation? = ImageLocation.LOCAL var streamingWrite: Boolean = false var imageFile: Uri? = null var imageRepr: Image? = null diff --git a/app/src/main/java/eu/depau/etchdroid/adapters/PartitionTableRecyclerViewAdapter.kt b/app/src/main/java/eu/depau/etchdroid/adapters/PartitionTableRecyclerViewAdapter.kt new file mode 100644 index 0000000..8b7d9aa --- /dev/null +++ b/app/src/main/java/eu/depau/etchdroid/adapters/PartitionTableRecyclerViewAdapter.kt @@ -0,0 +1,76 @@ +package eu.depau.etchdroid.adapters + +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import eu.depau.etchdroid.R +import eu.depau.etchdroid.kotlin_exts.toHRSize +import eu.depau.etchdroid.utils.Partition +import kotlinx.android.synthetic.main.part_data_keyvalue.view.* +import kotlinx.android.synthetic.main.partition_row.view.* + +class PartitionTableRecyclerViewAdapter(private val dataset: List) : RecyclerView.Adapter() { + + class ViewHolder(val layout: LinearLayout) : RecyclerView.ViewHolder(layout) + + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): + ViewHolder { + + val layout = LayoutInflater.from(parent.context) + .inflate(R.layout.partition_row, parent, false) as LinearLayout + return ViewHolder(layout) + } + + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val part = dataset[position] + val layout = holder.layout + val li = LayoutInflater.from(layout.context) + var kv: LinearLayout + + layout.part_number.text = "${part.number}" + + layout.part_data_grid.removeAllViewsInLayout() + + if (part.partLabel != null) { + kv = li.inflate(R.layout.part_data_keyvalue, layout.part_data_grid, false) as LinearLayout + kv.key.text = layout.context.getString(R.string.part_label) + kv.value.text = part.partLabel + layout.part_data_grid.addView(kv) + } + if (part.fsLabel != null) { + kv = li.inflate(R.layout.part_data_keyvalue, layout.part_data_grid, false) as LinearLayout + kv.key.text = layout.context.getString(R.string.fs_label) + kv.value.text = part.fsLabel + layout.part_data_grid.addView(kv) + } + if (part.fsType != null) { + kv = li.inflate(R.layout.part_data_keyvalue, layout.part_data_grid, false) as LinearLayout + kv.key.text = layout.context.getString(R.string.fs_type) + kv.value.text = part.fsType.getString(layout.context) + layout.part_data_grid.addView(kv) + } + if (part.fsLabel != null) { + kv = li.inflate(R.layout.part_data_keyvalue, layout.part_data_grid, false) as LinearLayout + kv.key.text = layout.context.getString(R.string.fs_label) + kv.value.text = part.fsLabel + layout.part_data_grid.addView(kv) + } + if (part.size != null) { + kv = li.inflate(R.layout.part_data_keyvalue, layout.part_data_grid, false) as LinearLayout + kv.key.text = layout.context.getString(R.string.part_size) + kv.value.text = part.size.toHRSize() + layout.part_data_grid.addView(kv) + } + } + + + override fun getItemCount(): Int = dataset.size + + + fun get(position: Int): Partition { + return dataset[position] + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/depau/etchdroid/enums/FilesystemType.kt b/app/src/main/java/eu/depau/etchdroid/enums/FilesystemType.kt index b1b066c..43349dd 100644 --- a/app/src/main/java/eu/depau/etchdroid/enums/FilesystemType.kt +++ b/app/src/main/java/eu/depau/etchdroid/enums/FilesystemType.kt @@ -1,5 +1,8 @@ package eu.depau.etchdroid.enums +import android.content.Context +import eu.depau.etchdroid.R + enum class FilesystemType { // Microsoft FAT12, @@ -35,5 +38,35 @@ enum class FilesystemType { FREE, UNFORMATTED, - UNKNOWN + UNKNOWN; + + fun getString(context: Context): String { + return when(this) { + FilesystemType.FAT12 -> context.getString(R.string.fs_fat12) + FilesystemType.FAT16 -> context.getString(R.string.fs_fat16) + FilesystemType.FAT32 -> context.getString(R.string.fs_fat32) + FilesystemType.EXFAT -> context.getString(R.string.fs_exfat) + FilesystemType.NTFS -> context.getString(R.string.fs_ntfs) + FilesystemType.REFS -> context.getString(R.string.fs_refs) + FilesystemType.HFS -> context.getString(R.string.fs_hfs) + FilesystemType.HFSPLUS -> context.getString(R.string.fs_hfsplus) + FilesystemType.APFS -> context.getString(R.string.fs_apfs) + FilesystemType.APT_DATA -> context.getString(R.string.fs_apt_data) + FilesystemType.ISO9660 -> context.getString(R.string.fs_iso9660) + FilesystemType.EXT2 -> context.getString(R.string.fs_ext2) + FilesystemType.EXT3 -> context.getString(R.string.fs_ext3) + FilesystemType.EXT4 -> context.getString(R.string.fs_ext4) + FilesystemType.BTRFS -> context.getString(R.string.fs_btrfs) + FilesystemType.F2FS -> context.getString(R.string.fs_f2fs) + FilesystemType.LUKS -> context.getString(R.string.fs_luks) + FilesystemType.LINUX_SWAP -> context.getString(R.string.fs_linux_swap) + FilesystemType.LINUX_LVM_PV -> context.getString(R.string.fs_linux_lvm_pv) + FilesystemType.UFS -> context.getString(R.string.fs_ufs) + FilesystemType.XFS -> context.getString(R.string.fs_xfs) + FilesystemType.ZFS -> context.getString(R.string.fs_zfs) + FilesystemType.FREE -> context.getString(R.string.fs_free) + FilesystemType.UNFORMATTED -> context.getString(R.string.fs_unformatted) + FilesystemType.UNKNOWN -> context.getString(R.string.fs_unknown) + } + } } \ No newline at end of file diff --git a/app/src/main/java/eu/depau/etchdroid/enums/PartitionTableType.kt b/app/src/main/java/eu/depau/etchdroid/enums/PartitionTableType.kt index 20676be..d687bfe 100644 --- a/app/src/main/java/eu/depau/etchdroid/enums/PartitionTableType.kt +++ b/app/src/main/java/eu/depau/etchdroid/enums/PartitionTableType.kt @@ -1,5 +1,8 @@ package eu.depau.etchdroid.enums +import android.content.Context +import eu.depau.etchdroid.R + enum class PartitionTableType { AIX, AMIGA, @@ -10,5 +13,20 @@ enum class PartitionTableType { MAC, MSDOS, PC98, - SUN -} \ No newline at end of file + SUN; + + fun getString(context: Context): String { + return when(this) { + PartitionTableType.AIX -> context.getString(R.string.ptt_aix) + PartitionTableType.AMIGA -> context.getString(R.string.ptt_amiga) + PartitionTableType.BSD -> context.getString(R.string.ptt_bsd) + PartitionTableType.DVH -> context.getString(R.string.ptt_dvh) + PartitionTableType.GPT -> context.getString(R.string.ptt_gpt) + PartitionTableType.LOOP -> context.getString(R.string.ptt_loop) + PartitionTableType.MAC -> context.getString(R.string.ptt_mac) + PartitionTableType.MSDOS -> context.getString(R.string.ptt_msdos) + PartitionTableType.PC98 -> context.getString(R.string.ptt_pc98) + PartitionTableType.SUN -> context.getString(R.string.ptt_sun) + } + } +} diff --git a/app/src/main/java/eu/depau/etchdroid/fragments/ImageLocationFragment.kt b/app/src/main/java/eu/depau/etchdroid/fragments/ImageLocationFragment.kt index 72620cf..107e21f 100644 --- a/app/src/main/java/eu/depau/etchdroid/fragments/ImageLocationFragment.kt +++ b/app/src/main/java/eu/depau/etchdroid/fragments/ImageLocationFragment.kt @@ -9,6 +9,7 @@ import android.os.Bundle import android.os.Environment import android.support.v4.app.ActivityCompat import android.support.v4.content.ContextCompat +import android.support.v7.widget.LinearLayoutManager import android.util.Log import android.view.LayoutInflater import android.view.View @@ -17,6 +18,7 @@ import com.github.isabsent.filepicker.SimpleFilePickerDialog import eu.depau.etchdroid.R import eu.depau.etchdroid.StateKeeper import eu.depau.etchdroid.activities.WizardActivity +import eu.depau.etchdroid.adapters.PartitionTableRecyclerViewAdapter import eu.depau.etchdroid.kotlin_exts.getFileName import eu.depau.etchdroid.kotlin_exts.snackbar import eu.depau.etchdroid.enums.FlashMethod @@ -37,6 +39,7 @@ class ImageLocationFragment : WizardFragment(), SimpleFilePickerDialog.Interacti val MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 29 val TAG = "ImageLocationFragment" val PICKER_DIALOG_TAG = "eu.depau.etchdroid.filepicker.DIALOG_TAG" + var issuesFound = false fun isStreamingAvailable(): Boolean { if (StateKeeper.imageLocation != ImageLocation.REMOTE) @@ -46,7 +49,7 @@ class ImageLocationFragment : WizardFragment(), SimpleFilePickerDialog.Interacti return true } - fun setStreamingCheckBoxAvailability(context: WizardActivity) { +/* fun setStreamingCheckBoxAvailability(context: WizardActivity) { val checkBox = streaming_write_checkbox if (checkBox == null) @@ -59,28 +62,29 @@ class ImageLocationFragment : WizardFragment(), SimpleFilePickerDialog.Interacti checkBox.isEnabled = enabled onCheckBoxClicked(checkBox) } - } + }*/ - override fun onCheckBoxClicked(view: View) { +/* override fun onCheckBoxClicked(view: View) { super.onCheckBoxClicked(view) if (view.id == R.id.streaming_write_checkbox) StateKeeper.streamingWrite = view.isActivated && view.isEnabled - } + }*/ override fun onRadioButtonClicked(view: View) { - StateKeeper.imageLocation = when (view.id) { + StateKeeper.imageLocation = ImageLocation.LOCAL + /*when (view.id) { R.id.download_img_radio -> ImageLocation.REMOTE R.id.use_local_img_radio -> ImageLocation.LOCAL else -> null - } + }*/ fab?.show() pick_file_btn?.isEnabled = StateKeeper.imageLocation == ImageLocation.LOCAL - img_url_textview?.isEnabled = StateKeeper.imageLocation == ImageLocation.REMOTE +// img_url_textview?.isEnabled = StateKeeper.imageLocation == ImageLocation.REMOTE - setStreamingCheckBoxAvailability(activity as WizardActivity) +// setStreamingCheckBoxAvailability(activity as WizardActivity) loadImageChanges(activity as WizardActivity) } @@ -127,12 +131,17 @@ class ImageLocationFragment : WizardFragment(), SimpleFilePickerDialog.Interacti } override fun nextStep(view: View?) { + if (issuesFound) { + view?.snackbar(getString(R.string.issues_found_expl)) + return + } + if (StateKeeper.imageLocation == null) { view?.snackbar(getString(R.string.select_image_location)) return } - if (StateKeeper.imageLocation == ImageLocation.REMOTE) { +/* if (StateKeeper.imageLocation == ImageLocation.REMOTE) { try { StateKeeper.imageFile = getRemoteImageUri(activity as WizardActivity) } catch (e: RuntimeException) { @@ -140,7 +149,7 @@ class ImageLocationFragment : WizardFragment(), SimpleFilePickerDialog.Interacti view?.snackbar(getString(R.string.provided_url_invalid)) return } - } + }*/ if (StateKeeper.imageFile == null) { view?.snackbar(getString(R.string.provide_image_file)) @@ -185,7 +194,7 @@ class ImageLocationFragment : WizardFragment(), SimpleFilePickerDialog.Interacti override fun onFragmentAdded(activity: WizardActivity) { super.onFragmentAdded(activity) - setStreamingCheckBoxAvailability(activity) +// setStreamingCheckBoxAvailability(activity) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, @@ -196,10 +205,10 @@ class ImageLocationFragment : WizardFragment(), SimpleFilePickerDialog.Interacti return inflater.inflate(R.layout.fragment_select_location, container, false) } - fun getRemoteImageUri(context: WizardActivity): Uri { +/* fun getRemoteImageUri(context: WizardActivity): Uri { val text = img_url_textview.text.toString() return Uri.parse(text) - } + }*/ fun loadImageChanges(context: WizardActivity) { val button = pick_file_btn @@ -214,7 +223,24 @@ class ImageLocationFragment : WizardFragment(), SimpleFilePickerDialog.Interacti if (StateKeeper.flashMethod == FlashMethod.FLASH_DMG_API) { StateKeeper.imageRepr = DMGImage(uri, context) - Log.d(TAG, (StateKeeper.imageRepr as DMGImage).partitionTable.toString()) + val imgRepr = StateKeeper.imageRepr as DMGImage + + if (imgRepr.tableType == null && (imgRepr.partitionTable == null || imgRepr.partitionTable?.size == 0)) { + part_table_header.text = getString(R.string.image_is_not_dmg) + issuesFound = true + return + } else { + part_table_header.text = if (imgRepr.tableType != null) "Partition table:" else "" + part_table_header_side.text = imgRepr.tableType?.getString(context) ?: "" + issuesFound = false + + val viewAdapter = PartitionTableRecyclerViewAdapter(imgRepr.partitionTable!!) + part_table_recycler.apply { + setHasFixedSize(true) + layoutManager = LinearLayoutManager(activity) + adapter = viewAdapter + } + } } } diff --git a/app/src/main/res/layout/fragment_confirminfo.xml b/app/src/main/res/layout/fragment_confirminfo.xml index 32e3805..286b885 100644 --- a/app/src/main/res/layout/fragment_confirminfo.xml +++ b/app/src/main/res/layout/fragment_confirminfo.xml @@ -16,10 +16,10 @@ android:clickable="true" android:focusable="true" android:orientation="vertical" - android:paddingBottom="@dimen/row_padding_vertical" + android:paddingBottom="@dimen/row_padding" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" - android:paddingTop="@dimen/row_padding_vertical"> + android:paddingTop="@dimen/row_padding"> + android:paddingTop="@dimen/row_padding"> + android:paddingTop="@dimen/row_padding"> + android:paddingTop="@dimen/row_padding"> + tools:context=".fragments.FlashMethodFragment"> - -