Complete app redesign
- Switched to AndroidX namespace - Switched from Fragments to Activities - Automatically detects USB drives on (dis)connection - UX is simpler, less taps are needed
This commit is contained in:
parent
309434ebae
commit
53dc07490c
45 changed files with 1072 additions and 1017 deletions
|
@ -12,7 +12,7 @@ android {
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
@ -26,11 +26,11 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation 'com.android.support:appcompat-v7:28.0.0-rc01'
|
implementation 'androidx.appcompat:appcompat:1.0.0-rc02'
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
|
||||||
implementation 'com.android.support:design:28.0.0-rc01'
|
implementation 'com.google.android.material:material:1.0.0-rc01'
|
||||||
implementation 'com.android.support:recyclerview-v7:28.0.0-rc01'
|
implementation 'androidx.recyclerview:recyclerview:1.0.0-rc02'
|
||||||
implementation 'com.android.support:gridlayout-v7:28.0.0-rc01'
|
implementation 'androidx.gridlayout:gridlayout:1.0.0-rc02'
|
||||||
api 'com.google.guava:guava:26.0-android'
|
api 'com.google.guava:guava:26.0-android'
|
||||||
|
|
||||||
implementation 'com.github.codekidX:storage-chooser:2.0.4.2'
|
implementation 'com.github.codekidX:storage-chooser:2.0.4.2'
|
||||||
|
@ -39,7 +39,9 @@ dependencies {
|
||||||
implementation project(':dmg2img')
|
implementation project(':dmg2img')
|
||||||
|
|
||||||
|
|
||||||
|
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||||
|
implementation 'com.android.support:design:28.0.0-rc01'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
|
||||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.depau.etchdroid
|
package eu.depau.etchdroid
|
||||||
|
|
||||||
import android.support.test.InstrumentationRegistry
|
import androidx.test.InstrumentationRegistry
|
||||||
import android.support.test.runner.AndroidJUnit4
|
import androidx.test.runner.AndroidJUnit4
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="eu.depau.etchdroid">
|
package="eu.depau.etchdroid">
|
||||||
|
|
||||||
|
<uses-feature android:name="android.hardware.usb.host" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
|
@ -12,17 +14,41 @@
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme"
|
||||||
|
tools:ignore="GoogleAppIndexingWarning">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.MainActivity"
|
android:name=".activities.StartActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/AppTheme.NoActionBar">
|
android:theme="@style/MaterialAppTheme">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name=".activities.LicensesActivity"
|
||||||
|
android:label="@string/licenses"
|
||||||
|
android:theme="@style/MaterialAppTheme">
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.UsbDrivePickerActivity"
|
||||||
|
android:label="@string/title_activity_usb_drive_picker"
|
||||||
|
android:parentActivityName=".activities.StartActivity"
|
||||||
|
android:theme="@style/MaterialAppTheme">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value="eu.depau.etchdroid.activities.StartActivity"/>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.ConfirmationActivity"
|
||||||
|
android:label="@string/title_activity_confirmation"
|
||||||
|
android:parentActivityName=".activities.UsbDrivePickerActivity"
|
||||||
|
android:theme="@style/MaterialAppTheme">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value="eu.depau.etchdroid.activities.UsbDrivePickerActivity"/>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".services.UsbApiImgWriteService"
|
android:name=".services.UsbApiImgWriteService"
|
||||||
|
@ -30,9 +56,6 @@
|
||||||
<service
|
<service
|
||||||
android:name=".services.UsbApiDmgWriteService"
|
android:name=".services.UsbApiDmgWriteService"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<activity android:name=".activities.LicensesActivity">
|
|
||||||
</activity>
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -3,18 +3,11 @@ package eu.depau.etchdroid
|
||||||
import android.hardware.usb.UsbDevice
|
import android.hardware.usb.UsbDevice
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.github.mjdev.libaums.UsbMassStorageDevice
|
import com.github.mjdev.libaums.UsbMassStorageDevice
|
||||||
import eu.depau.etchdroid.fragments.WizardFragment
|
|
||||||
import eu.depau.etchdroid.enums.FlashMethod
|
import eu.depau.etchdroid.enums.FlashMethod
|
||||||
import eu.depau.etchdroid.enums.ImageLocation
|
|
||||||
import eu.depau.etchdroid.enums.WizardStep
|
|
||||||
import eu.depau.etchdroid.img_types.Image
|
import eu.depau.etchdroid.img_types.Image
|
||||||
|
|
||||||
object StateKeeper {
|
object StateKeeper {
|
||||||
var wizardStep: WizardStep = WizardStep.SELECT_FLASH_METHOD
|
|
||||||
var currentFragment: WizardFragment? = null
|
|
||||||
var flashMethod: FlashMethod? = null
|
var flashMethod: FlashMethod? = null
|
||||||
var imageLocation: ImageLocation? = ImageLocation.LOCAL
|
|
||||||
var streamingWrite: Boolean = false
|
|
||||||
var imageFile: Uri? = null
|
var imageFile: Uri? = null
|
||||||
var imageRepr: Image? = null
|
var imageRepr: Image? = null
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package eu.depau.etchdroid.activities
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import eu.depau.etchdroid.R
|
||||||
|
|
||||||
|
abstract class ActivityBase: AppCompatActivity() {
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
|
menuInflater.inflate(R.menu.menu_main, menu)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
// Handle action bar item clicks here. The action bar will
|
||||||
|
// automatically handle clicks on the Home/Up button, so long
|
||||||
|
// as you specify a parent activity in AndroidManifest.xml.
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.action_licenses -> {
|
||||||
|
val intent = Intent(this, LicensesActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
package eu.depau.etchdroid.activities
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import eu.depau.etchdroid.R
|
||||||
|
import eu.depau.etchdroid.StateKeeper
|
||||||
|
import eu.depau.etchdroid.adapters.PartitionTableRecyclerViewAdapter
|
||||||
|
import eu.depau.etchdroid.enums.FlashMethod
|
||||||
|
import eu.depau.etchdroid.img_types.DMGImage
|
||||||
|
import eu.depau.etchdroid.kotlin_exts.*
|
||||||
|
import eu.depau.etchdroid.services.UsbApiDmgWriteService
|
||||||
|
import eu.depau.etchdroid.services.UsbApiImgWriteService
|
||||||
|
|
||||||
|
import kotlinx.android.synthetic.main.activity_confirmation.*
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class ConfirmationActivity : ActivityBase() {
|
||||||
|
var canContinue: Boolean = false
|
||||||
|
var issuesFound: Boolean = false
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_confirmation)
|
||||||
|
actionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
|
displayDetails()
|
||||||
|
displayImageLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun displayDetails() {
|
||||||
|
confirm_sel_method.text = when (StateKeeper.flashMethod) {
|
||||||
|
FlashMethod.FLASH_API -> getString(R.string.flash_dd_usb_api)
|
||||||
|
FlashMethod.FLASH_DMG_API -> getString(R.string.flash_dmg_api)
|
||||||
|
FlashMethod.FLASH_UNETBOOTIN -> getString(R.string.flash_unetbootin)
|
||||||
|
FlashMethod.FLASH_WOEUSB -> getString(R.string.flash_woeusb)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm_sel_image.text = StateKeeper.imageFile?.getFileName(this)
|
||||||
|
|
||||||
|
if (confirm_sel_image.text == null)
|
||||||
|
confirm_sel_image.text = getString(R.string.unknown_filename)
|
||||||
|
|
||||||
|
val imgSize = StateKeeper.imageFile?.getFileSize(this)
|
||||||
|
confirm_sel_image_size.text = imgSize?.toHRSize()
|
||||||
|
|
||||||
|
confirm_sel_usbdev.text = StateKeeper.usbDevice?.name
|
||||||
|
|
||||||
|
for (trial in 0..1) {
|
||||||
|
try {
|
||||||
|
StateKeeper.usbMassStorageDevice!!.init()
|
||||||
|
val blockDev = StateKeeper.usbMassStorageDevice?.blockDevice
|
||||||
|
|
||||||
|
if (blockDev != null) {
|
||||||
|
val devSize = (blockDev.size.toLong() * blockDev.blockSize.toLong())
|
||||||
|
confirm_sel_usbdev_size.text = devSize.toHRSize()
|
||||||
|
|
||||||
|
if (imgSize!! > devSize)
|
||||||
|
confirm_extra_info.text = getString(R.string.image_bigger_than_usb)
|
||||||
|
else {
|
||||||
|
var text =
|
||||||
|
if (StateKeeper.flashMethod == FlashMethod.FLASH_DMG_API)
|
||||||
|
getString(R.string.no_image_size_check_dmg) + "\n"
|
||||||
|
else
|
||||||
|
""
|
||||||
|
text += getString(R.string.tap_next_to_write)
|
||||||
|
confirm_extra_info.text = text
|
||||||
|
canContinue = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
confirm_extra_info.text = getString(R.string.cant_read_usbdev)
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
if (trial == 0) {
|
||||||
|
StateKeeper.usbMassStorageDevice!!.close()
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
confirm_extra_info.text = getString(R.string.could_not_access_usb_error)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun displayImageLayout() {
|
||||||
|
val uri = StateKeeper.imageFile ?: return
|
||||||
|
val text = uri.getFileName(this)
|
||||||
|
|
||||||
|
if (StateKeeper.flashMethod == FlashMethod.FLASH_DMG_API) {
|
||||||
|
StateKeeper.imageRepr = DMGImage(uri, this)
|
||||||
|
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) getString(R.string.partition_table_title) else ""
|
||||||
|
part_table_header_side.text = imgRepr.tableType?.getString(this) ?: ""
|
||||||
|
issuesFound = false
|
||||||
|
|
||||||
|
val viewAdapter = PartitionTableRecyclerViewAdapter(imgRepr.partitionTable!!)
|
||||||
|
part_table_recycler.apply {
|
||||||
|
setHasFixedSize(true)
|
||||||
|
layoutManager = LinearLayoutManager(context)
|
||||||
|
adapter = viewAdapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun nextStep() {
|
||||||
|
if (!canContinue) {
|
||||||
|
confirm_fab.snackbar(getString(R.string.cannot_write))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
toast(getString(R.string.check_notification_progress), Toast.LENGTH_LONG)
|
||||||
|
|
||||||
|
val intent: Intent = when (StateKeeper.flashMethod) {
|
||||||
|
FlashMethod.FLASH_API -> Intent(this, UsbApiImgWriteService::class.java)
|
||||||
|
FlashMethod.FLASH_DMG_API -> Intent(this, UsbApiDmgWriteService::class.java)
|
||||||
|
else -> null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
intent.setDataAndType(StateKeeper.imageFile, "application/octet-stream")
|
||||||
|
intent.putExtra("usbDevice", StateKeeper.usbDevice)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||||
|
startForegroundService(intent)
|
||||||
|
else
|
||||||
|
startService(intent)
|
||||||
|
|
||||||
|
moveTaskToBack(true);
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun onButtonClicked(view: View) {
|
||||||
|
when (view.id) {
|
||||||
|
R.id.confirm_fab -> nextStep()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,10 +3,9 @@ package eu.depau.etchdroid.activities
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v7.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import android.support.v7.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import android.support.v7.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import android.util.Log
|
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import eu.depau.etchdroid.R
|
import eu.depau.etchdroid.R
|
||||||
|
@ -41,8 +40,6 @@ class LicensesActivity : AppCompatActivity() {
|
||||||
setContentView(R.layout.activity_licenses)
|
setContentView(R.layout.activity_licenses)
|
||||||
updateLicenses()
|
updateLicenses()
|
||||||
|
|
||||||
title = getString(R.string.licenses)
|
|
||||||
|
|
||||||
// Enable back button in action bar
|
// Enable back button in action bar
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
package eu.depau.etchdroid.activities
|
|
||||||
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.hardware.usb.UsbDevice
|
|
||||||
import android.hardware.usb.UsbManager
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuItem
|
|
||||||
import eu.depau.etchdroid.R
|
|
||||||
import eu.depau.etchdroid.StateKeeper
|
|
||||||
import eu.depau.etchdroid.fragments.WizardFragment
|
|
||||||
import eu.depau.etchdroid.fragments.FlashMethodFragment
|
|
||||||
import eu.depau.etchdroid.fragments.UsbDriveFragment
|
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
|
||||||
|
|
||||||
class MainActivity : WizardActivity() {
|
|
||||||
val TAG = "MainActivity"
|
|
||||||
val ACTION_USB_PERMISSION = "eu.depau.etchdroid.USB_PERMISSION"
|
|
||||||
lateinit var mUsbPermissionIntent: PendingIntent
|
|
||||||
|
|
||||||
private val mUsbReceiver = object : BroadcastReceiver() {
|
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
|
||||||
if (intent.action == ACTION_USB_PERMISSION) {
|
|
||||||
synchronized(this) {
|
|
||||||
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
|
|
||||||
|
|
||||||
val result = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
|
|
||||||
if (result)
|
|
||||||
device?.apply {
|
|
||||||
StateKeeper.usbDevice = this
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StateKeeper.currentFragment is UsbDriveFragment)
|
|
||||||
(StateKeeper.currentFragment as UsbDriveFragment).onUsbPermissionResult(device, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_main)
|
|
||||||
setSupportActionBar(toolbar)
|
|
||||||
fab.setOnClickListener(::nextStep)
|
|
||||||
|
|
||||||
// Create new fragment and transaction
|
|
||||||
val fragment = FlashMethodFragment()
|
|
||||||
val transaction = supportFragmentManager.beginTransaction()
|
|
||||||
transaction.replace(R.id.fragment_layout, fragment)
|
|
||||||
transaction.commit()
|
|
||||||
fragment.onFragmentAdded(this)
|
|
||||||
|
|
||||||
val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
|
|
||||||
mUsbPermissionIntent = PendingIntent.getBroadcast(this, 0, Intent(ACTION_USB_PERMISSION), 0)
|
|
||||||
val filter = IntentFilter(ACTION_USB_PERMISSION)
|
|
||||||
registerReceiver(mUsbReceiver, filter)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
|
|
||||||
unregisterReceiver(mUsbReceiver)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun goToNewFragment(fragment: WizardFragment) {
|
|
||||||
StateKeeper.currentFragment?.onFragmentRemoving(this)
|
|
||||||
|
|
||||||
val transaction = supportFragmentManager.beginTransaction()
|
|
||||||
transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)
|
|
||||||
transaction.replace(R.id.fragment_layout, fragment)
|
|
||||||
transaction.addToBackStack(null)
|
|
||||||
transaction.commit()
|
|
||||||
|
|
||||||
fragment.onFragmentAdded(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
|
||||||
menuInflater.inflate(R.menu.menu_main, menu)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
// Handle action bar item clicks here. The action bar will
|
|
||||||
// automatically handle clicks on the Home/Up button, so long
|
|
||||||
// as you specify a parent activity in AndroidManifest.xml.
|
|
||||||
return when (item.itemId) {
|
|
||||||
R.id.action_licenses -> {
|
|
||||||
val intent = Intent(this, LicensesActivity::class.java)
|
|
||||||
startActivity(intent)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
else -> super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
128
app/src/main/java/eu/depau/etchdroid/activities/StartActivity.kt
Normal file
128
app/src/main/java/eu/depau/etchdroid/activities/StartActivity.kt
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
package eu.depau.etchdroid.activities
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Environment
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.codekidlabs.storagechooser.StorageChooser
|
||||||
|
import eu.depau.etchdroid.R
|
||||||
|
import eu.depau.etchdroid.StateKeeper
|
||||||
|
import eu.depau.etchdroid.enums.FlashMethod
|
||||||
|
import eu.depau.etchdroid.kotlin_exts.snackbar
|
||||||
|
import kotlinx.android.synthetic.main.activity_start.*
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class StartActivity : ActivityBase() {
|
||||||
|
val TAG = "StartActivity"
|
||||||
|
val READ_REQUEST_CODE = 42
|
||||||
|
val READ_EXTERNAL_STORAGE_PERMISSION = 29
|
||||||
|
var delayedButtonClicked: View? = null
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_start)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onButtonClicked(view: View) {
|
||||||
|
StateKeeper.flashMethod = when (view.id) {
|
||||||
|
R.id.btn_image_raw -> FlashMethod.FLASH_API
|
||||||
|
R.id.btn_image_dmg -> FlashMethod.FLASH_DMG_API
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
when (StateKeeper.flashMethod) {
|
||||||
|
FlashMethod.FLASH_API -> {
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
intent.setType("*/*");
|
||||||
|
startActivityForResult(intent, READ_REQUEST_CODE)
|
||||||
|
}
|
||||||
|
FlashMethod.FLASH_DMG_API -> {
|
||||||
|
if (checkAndRequestStorageReadPerm()) {
|
||||||
|
val sdcard = Environment.getExternalStorageDirectory().absolutePath
|
||||||
|
|
||||||
|
val chooser = StorageChooser.Builder()
|
||||||
|
.withActivity(this)
|
||||||
|
.withFragmentManager(fragmentManager)
|
||||||
|
.withMemoryBar(true)
|
||||||
|
.allowCustomPath(true)
|
||||||
|
.setType(StorageChooser.FILE_PICKER)
|
||||||
|
.customFilter(arrayListOf("dmg"))
|
||||||
|
.build()
|
||||||
|
chooser.show()
|
||||||
|
chooser.setOnSelectListener {
|
||||||
|
StateKeeper.imageFile = Uri.fromFile(File(it))
|
||||||
|
nextStep()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
delayedButtonClicked = view
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FlashMethod.FLASH_UNETBOOTIN -> {
|
||||||
|
}
|
||||||
|
FlashMethod.FLASH_WOEUSB -> {
|
||||||
|
}
|
||||||
|
null -> {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAndRequestStorageReadPerm(): Boolean {
|
||||||
|
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
|
||||||
|
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE)) {
|
||||||
|
btn_image_dmg.snackbar("Storage permission is required to read DMG images")
|
||||||
|
} else {
|
||||||
|
ActivityCompat.requestPermissions(this,
|
||||||
|
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
|
||||||
|
READ_EXTERNAL_STORAGE_PERMISSION)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Permission granted
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||||
|
when (requestCode) {
|
||||||
|
READ_EXTERNAL_STORAGE_PERMISSION -> {
|
||||||
|
if (delayedButtonClicked != null)
|
||||||
|
onButtonClicked(delayedButtonClicked!!)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
||||||
|
// The document selected by the user won't be returned in the intent.
|
||||||
|
// Instead, a URI to that document will be contained in the return intent
|
||||||
|
// provided to this method as a parameter.
|
||||||
|
// Pull that URI using resultData.getData().
|
||||||
|
var uri: Uri? = null
|
||||||
|
if (data != null) {
|
||||||
|
uri = data.getData()
|
||||||
|
StateKeeper.imageFile = uri
|
||||||
|
|
||||||
|
nextStep()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun nextStep() {
|
||||||
|
val intent = Intent(this, UsbDrivePickerActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
package eu.depau.etchdroid.activities
|
||||||
|
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.hardware.usb.UsbDevice
|
||||||
|
import android.hardware.usb.UsbManager
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
import com.github.mjdev.libaums.UsbMassStorageDevice
|
||||||
|
import eu.depau.etchdroid.R
|
||||||
|
import eu.depau.etchdroid.StateKeeper
|
||||||
|
import eu.depau.etchdroid.adapters.UsbDrivesRecyclerViewAdapter
|
||||||
|
import eu.depau.etchdroid.kotlin_exts.name
|
||||||
|
import eu.depau.etchdroid.kotlin_exts.snackbar
|
||||||
|
import eu.depau.etchdroid.utils.ClickListener
|
||||||
|
import eu.depau.etchdroid.utils.EmptyRecyclerView
|
||||||
|
import eu.depau.etchdroid.utils.RecyclerViewTouchListener
|
||||||
|
import kotlinx.android.synthetic.main.activity_usb_drive_picker.*
|
||||||
|
|
||||||
|
class UsbDrivePickerActivity : ActivityBase(), SwipeRefreshLayout.OnRefreshListener {
|
||||||
|
val USB_PERMISSION = "eu.depau.etchdroid.USB_PERMISSION"
|
||||||
|
lateinit var mUsbPermissionIntent: PendingIntent
|
||||||
|
|
||||||
|
private lateinit var recyclerView: EmptyRecyclerView
|
||||||
|
private lateinit var viewAdapter: UsbDrivesRecyclerViewAdapter
|
||||||
|
private lateinit var viewManager: RecyclerView.LayoutManager
|
||||||
|
private lateinit var refreshLayout: SwipeRefreshLayout
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_usb_drive_picker)
|
||||||
|
actionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
|
mUsbPermissionIntent = PendingIntent.getBroadcast(this, 0, Intent(USB_PERMISSION), 0)
|
||||||
|
val usbPermissionFilter = IntentFilter(USB_PERMISSION)
|
||||||
|
val usbAttachedFilter = IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED)
|
||||||
|
val usbDetachedFilter = IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED)
|
||||||
|
|
||||||
|
registerReceiver(mUsbReceiver, usbPermissionFilter)
|
||||||
|
registerReceiver(mUsbReceiver, usbAttachedFilter)
|
||||||
|
registerReceiver(mUsbReceiver, usbDetachedFilter)
|
||||||
|
|
||||||
|
refreshLayout = usbdevs_swiperefreshlayout
|
||||||
|
refreshLayout.setOnRefreshListener(this)
|
||||||
|
refreshLayout.post {
|
||||||
|
refreshLayout.isRefreshing = true
|
||||||
|
loadUsbDevices()
|
||||||
|
}
|
||||||
|
|
||||||
|
viewManager = LinearLayoutManager(this)
|
||||||
|
recyclerView = usbdevs_recycler_view
|
||||||
|
recyclerView.emptyView = usbdevs_recycler_empty_view
|
||||||
|
|
||||||
|
recyclerView.addOnItemTouchListener(RecyclerViewTouchListener(this, recyclerView, object : ClickListener {
|
||||||
|
override fun onClick(view: View, position: Int) {
|
||||||
|
val device = viewAdapter.get(position)
|
||||||
|
val manager = getSystemService(Context.USB_SERVICE) as UsbManager
|
||||||
|
manager.requestPermission(device.usbDevice, mUsbPermissionIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onLongClick(view: View, position: Int) {}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
unregisterReceiver(mUsbReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.usb_devices_menu, menu)
|
||||||
|
return super.onCreateOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onContextItemSelected(item: MenuItem): Boolean {
|
||||||
|
return when (item.itemId) {
|
||||||
|
R.id.action_refresh -> {
|
||||||
|
loadUsbDevices()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRefresh() {
|
||||||
|
loadUsbDevices()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val mUsbReceiver = object : BroadcastReceiver() {
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
when (intent.action) {
|
||||||
|
USB_PERMISSION -> synchronized(this) {
|
||||||
|
val device: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)
|
||||||
|
|
||||||
|
val result = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
|
||||||
|
if (result)
|
||||||
|
device?.apply {
|
||||||
|
StateKeeper.usbDevice = this
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
if (device != null) {
|
||||||
|
recyclerView.snackbar(getString(R.string.usb_perm_denied) + device.name)
|
||||||
|
} else {
|
||||||
|
recyclerView.snackbar(getString(R.string.usb_perm_denied_noname))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
StateKeeper.usbDevice = device
|
||||||
|
StateKeeper.usbMassStorageDevice = UsbMassStorageDevice.getMassStorageDevices(context).find { it.usbDevice == device }
|
||||||
|
|
||||||
|
nextStep()
|
||||||
|
}
|
||||||
|
UsbManager.ACTION_USB_DEVICE_ATTACHED, UsbManager.ACTION_USB_DEVICE_DETACHED -> loadUsbDevices()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadUsbDevices() {
|
||||||
|
try {
|
||||||
|
viewAdapter = UsbDrivesRecyclerViewAdapter(UsbMassStorageDevice.getMassStorageDevices(this))
|
||||||
|
|
||||||
|
recyclerView.apply {
|
||||||
|
setHasFixedSize(true)
|
||||||
|
layoutManager = viewManager
|
||||||
|
adapter = viewAdapter
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
refreshLayout.isRefreshing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun nextStep() {
|
||||||
|
val intent = Intent(this, ConfirmationActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,35 +0,0 @@
|
||||||
package eu.depau.etchdroid.activities
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.support.v7.app.AppCompatActivity
|
|
||||||
import android.view.View
|
|
||||||
import eu.depau.etchdroid.StateKeeper
|
|
||||||
import eu.depau.etchdroid.fragments.WizardFragment
|
|
||||||
|
|
||||||
abstract class WizardActivity : AppCompatActivity() {
|
|
||||||
abstract fun goToNewFragment(fragment: WizardFragment)
|
|
||||||
|
|
||||||
open fun onCheckBoxClicked(view: View) {
|
|
||||||
StateKeeper.currentFragment?.onCheckBoxClicked(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun onButtonClicked(view: View) {
|
|
||||||
StateKeeper.currentFragment?.onButtonClicked(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun onRadioButtonClicked(view: View) {
|
|
||||||
StateKeeper.currentFragment?.onRadioButtonClicked(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun nextStep(view: View) {
|
|
||||||
StateKeeper.currentFragment?.nextStep(view)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
|
||||||
StateKeeper.currentFragment?.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
||||||
StateKeeper.currentFragment?.onActivityResult(requestCode, resultCode, data)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.depau.etchdroid.adapters
|
package eu.depau.etchdroid.adapters
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.support.v7.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.depau.etchdroid.adapters
|
package eu.depau.etchdroid.adapters
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
|
|
@ -2,7 +2,7 @@ package eu.depau.etchdroid.adapters
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.support.v7.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
package eu.depau.etchdroid.fragments
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import eu.depau.etchdroid.R
|
|
||||||
import eu.depau.etchdroid.StateKeeper
|
|
||||||
import eu.depau.etchdroid.enums.FlashMethod
|
|
||||||
import eu.depau.etchdroid.enums.WizardStep
|
|
||||||
import eu.depau.etchdroid.kotlin_exts.*
|
|
||||||
import eu.depau.etchdroid.services.UsbApiDmgWriteService
|
|
||||||
import eu.depau.etchdroid.services.UsbApiImgWriteService
|
|
||||||
import kotlinx.android.synthetic.main.fragment_confirminfo.view.*
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder fragment containing a simple view.
|
|
||||||
*/
|
|
||||||
class ConfirmInfoFragment : WizardFragment() {
|
|
||||||
val TAG = "ConfirmInfoFragment"
|
|
||||||
var canContinue = false
|
|
||||||
|
|
||||||
override fun nextStep(view: View?) {
|
|
||||||
if (!canContinue) {
|
|
||||||
view?.snackbar("Cannot write image to USB drive")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
context?.toast("Check notification for progress")
|
|
||||||
|
|
||||||
val intent: Intent = when (StateKeeper.flashMethod) {
|
|
||||||
FlashMethod.FLASH_API -> Intent(activity, UsbApiImgWriteService::class.java)
|
|
||||||
FlashMethod.FLASH_DMG_API -> Intent(activity, UsbApiDmgWriteService::class.java)
|
|
||||||
else -> null!!
|
|
||||||
}
|
|
||||||
|
|
||||||
intent.setDataAndType(StateKeeper.imageFile, "application/octet-stream")
|
|
||||||
intent.putExtra("usbDevice", StateKeeper.usbDevice)
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
|
||||||
activity!!.startForegroundService(intent)
|
|
||||||
else
|
|
||||||
activity!!.startService(intent)
|
|
||||||
|
|
||||||
activity!!.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?): View? {
|
|
||||||
StateKeeper.currentFragment = this
|
|
||||||
StateKeeper.wizardStep = WizardStep.CONFIRM
|
|
||||||
|
|
||||||
val view = inflater.inflate(R.layout.fragment_confirminfo, container, false)
|
|
||||||
|
|
||||||
view.confirm_sel_method.text = when (StateKeeper.flashMethod) {
|
|
||||||
FlashMethod.FLASH_API -> getString(R.string.flash_dd_usb_api)
|
|
||||||
FlashMethod.FLASH_DMG_API -> getString(R.string.flash_dmg_api)
|
|
||||||
FlashMethod.FLASH_UNETBOOTIN -> getString(R.string.flash_unetbootin)
|
|
||||||
FlashMethod.FLASH_WOEUSB -> getString(R.string.flash_woeusb)
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
view.confirm_sel_image.text = StateKeeper.imageFile?.getFileName(context!!)
|
|
||||||
|
|
||||||
if (view.confirm_sel_image.text == null)
|
|
||||||
view.confirm_sel_image.text = getString(R.string.unknown_filename)
|
|
||||||
|
|
||||||
val imgSize = StateKeeper.imageFile?.getFileSize(context!!)
|
|
||||||
view.confirm_sel_image_size.text = imgSize?.toHRSize()
|
|
||||||
|
|
||||||
view.confirm_sel_usbdev.text = StateKeeper.usbDevice?.name
|
|
||||||
|
|
||||||
for (trial in 0..1) {
|
|
||||||
try {
|
|
||||||
StateKeeper.usbMassStorageDevice!!.init()
|
|
||||||
val blockDev = StateKeeper.usbMassStorageDevice?.blockDevice
|
|
||||||
|
|
||||||
if (blockDev != null) {
|
|
||||||
val devSize = (blockDev.size.toLong() * blockDev.blockSize.toLong())
|
|
||||||
view.confirm_sel_usbdev_size.text = devSize.toHRSize()
|
|
||||||
|
|
||||||
if (imgSize!! > devSize)
|
|
||||||
view.confirm_extra_info.text = getString(R.string.image_bigger_than_usb)
|
|
||||||
else {
|
|
||||||
var text =
|
|
||||||
if (StateKeeper.flashMethod == FlashMethod.FLASH_DMG_API)
|
|
||||||
getString(R.string.no_image_size_check_dmg) + "\n"
|
|
||||||
else
|
|
||||||
""
|
|
||||||
text += getString(R.string.tap_next_to_write)
|
|
||||||
view.confirm_extra_info.text = text
|
|
||||||
canContinue = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
view.confirm_extra_info.text = getString(R.string.cant_read_usbdev)
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
|
||||||
if (trial == 0) {
|
|
||||||
StateKeeper.usbMassStorageDevice!!.close()
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
view.confirm_extra_info.text = "Could not access USB device. Maybe you ran the app previously and it crashed? Remove and reinsert the USB drive, then restart the app."
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
package eu.depau.etchdroid.fragments
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import eu.depau.etchdroid.R
|
|
||||||
import eu.depau.etchdroid.StateKeeper
|
|
||||||
import eu.depau.etchdroid.activities.WizardActivity
|
|
||||||
import eu.depau.etchdroid.kotlin_exts.snackbar
|
|
||||||
import eu.depau.etchdroid.enums.FlashMethod
|
|
||||||
import eu.depau.etchdroid.enums.WizardStep
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder fragment containing a simple view.
|
|
||||||
*/
|
|
||||||
class FlashMethodFragment : WizardFragment() {
|
|
||||||
override fun nextStep(view: View?) {
|
|
||||||
if (StateKeeper.flashMethod == null)
|
|
||||||
view?.snackbar(getString(R.string.please_select_writing_method))
|
|
||||||
else
|
|
||||||
(activity as WizardActivity).goToNewFragment(ImageLocationFragment())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?): View? {
|
|
||||||
StateKeeper.currentFragment = this
|
|
||||||
StateKeeper.wizardStep = WizardStep.SELECT_FLASH_METHOD
|
|
||||||
|
|
||||||
return inflater.inflate(R.layout.fragment_select_flash_method, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRadioButtonClicked(view: View) {
|
|
||||||
StateKeeper.flashMethod = when (view.id) {
|
|
||||||
R.id.flash_dmg_api_radio -> FlashMethod.FLASH_DMG_API
|
|
||||||
R.id.flash_usb_api_radio -> FlashMethod.FLASH_API
|
|
||||||
R.id.flash_unetbootin_radio -> FlashMethod.FLASH_UNETBOOTIN
|
|
||||||
R.id.flash_woeusb_radio -> FlashMethod.FLASH_WOEUSB
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,211 +0,0 @@
|
||||||
package eu.depau.etchdroid.fragments
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.net.Uri
|
|
||||||
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
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import com.codekidlabs.storagechooser.StorageChooser
|
|
||||||
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.enums.FlashMethod
|
|
||||||
import eu.depau.etchdroid.enums.ImageLocation
|
|
||||||
import eu.depau.etchdroid.enums.WizardStep
|
|
||||||
import eu.depau.etchdroid.img_types.DMGImage
|
|
||||||
import eu.depau.etchdroid.kotlin_exts.getFileName
|
|
||||||
import eu.depau.etchdroid.kotlin_exts.snackbar
|
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
|
||||||
import kotlinx.android.synthetic.main.fragment_select_location.*
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder fragment containing a simple view.
|
|
||||||
*/
|
|
||||||
class ImageLocationFragment : WizardFragment() {
|
|
||||||
val READ_REQUEST_CODE = 42
|
|
||||||
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)
|
|
||||||
return false
|
|
||||||
if (StateKeeper.flashMethod != FlashMethod.FLASH_DMG_API && StateKeeper.flashMethod != FlashMethod.FLASH_API)
|
|
||||||
return false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRadioButtonClicked(view: View) {
|
|
||||||
StateKeeper.imageLocation = ImageLocation.LOCAL
|
|
||||||
activity?.fab?.show()
|
|
||||||
pick_file_btn?.isEnabled = StateKeeper.imageLocation == ImageLocation.LOCAL
|
|
||||||
loadImageChanges(activity as WizardActivity)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onButtonClicked(view: View) {
|
|
||||||
if (view.id == R.id.pick_file_btn) {
|
|
||||||
when (StateKeeper.flashMethod) {
|
|
||||||
FlashMethod.FLASH_API -> {
|
|
||||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
|
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
|
||||||
intent.setType("*/*");
|
|
||||||
activity?.startActivityForResult(intent, READ_REQUEST_CODE)
|
|
||||||
}
|
|
||||||
FlashMethod.FLASH_DMG_API -> {
|
|
||||||
if (checkAndRequestStorageReadPerm()) {
|
|
||||||
val sdcard = Environment.getExternalStorageDirectory().absolutePath
|
|
||||||
|
|
||||||
|
|
||||||
val chooser = StorageChooser.Builder()
|
|
||||||
.withActivity(activity)
|
|
||||||
.withFragmentManager(activity!!.fragmentManager)
|
|
||||||
.withMemoryBar(true)
|
|
||||||
.allowCustomPath(true)
|
|
||||||
.setType(StorageChooser.FILE_PICKER)
|
|
||||||
.customFilter(arrayListOf("dmg"))
|
|
||||||
.build()
|
|
||||||
chooser.show()
|
|
||||||
chooser.setOnSelectListener {
|
|
||||||
StateKeeper.imageFile = Uri.fromFile(File(it))
|
|
||||||
loadImageChanges(activity as WizardActivity)
|
|
||||||
|
|
||||||
activity?.fab?.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FlashMethod.FLASH_UNETBOOTIN -> {
|
|
||||||
}
|
|
||||||
FlashMethod.FLASH_WOEUSB -> {
|
|
||||||
}
|
|
||||||
null -> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkAndRequestStorageReadPerm(): Boolean {
|
|
||||||
if ((ContextCompat.checkSelfPermission(activity!!, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
|
|
||||||
if (ActivityCompat.shouldShowRequestPermissionRationale(activity!!,
|
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE)) {
|
|
||||||
view!!.snackbar("Storage permission is required to read DMG images")
|
|
||||||
} else {
|
|
||||||
ActivityCompat.requestPermissions(activity!!,
|
|
||||||
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
|
|
||||||
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Permission granted
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
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.imageFile == null) {
|
|
||||||
view?.snackbar(getString(R.string.provide_image_file))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
(activity as WizardActivity).goToNewFragment(UsbDriveFragment())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
|
||||||
when (requestCode) {
|
|
||||||
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE -> {
|
|
||||||
onButtonClicked(pick_file_btn)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
activity?.fab?.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?): View? {
|
|
||||||
StateKeeper.currentFragment = this
|
|
||||||
StateKeeper.wizardStep = WizardStep.SELECT_LOCATION
|
|
||||||
|
|
||||||
return inflater.inflate(R.layout.fragment_select_location, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadImageChanges(context: WizardActivity) {
|
|
||||||
val button = pick_file_btn
|
|
||||||
val uri = StateKeeper.imageFile ?: return
|
|
||||||
|
|
||||||
val text = uri.getFileName(context)
|
|
||||||
|
|
||||||
if (text != null)
|
|
||||||
button.text = text
|
|
||||||
else
|
|
||||||
button.text = getString(R.string.pick_a_file)
|
|
||||||
|
|
||||||
if (StateKeeper.flashMethod == FlashMethod.FLASH_DMG_API) {
|
|
||||||
StateKeeper.imageRepr = DMGImage(uri, context)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
||||||
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
|
|
||||||
// The document selected by the user won't be returned in the intent.
|
|
||||||
// Instead, a URI to that document will be contained in the return intent
|
|
||||||
// provided to this method as a parameter.
|
|
||||||
// Pull that URI using resultData.getData().
|
|
||||||
var uri: Uri? = null
|
|
||||||
if (data != null) {
|
|
||||||
uri = data.getData()
|
|
||||||
Log.d(TAG, "Uri: " + uri!!.toString())
|
|
||||||
StateKeeper.imageFile = uri
|
|
||||||
loadImageChanges(activity as WizardActivity)
|
|
||||||
|
|
||||||
activity?.fab?.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,139 +0,0 @@
|
||||||
package eu.depau.etchdroid.fragments
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.hardware.usb.UsbDevice
|
|
||||||
import android.hardware.usb.UsbManager
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.support.v4.widget.SwipeRefreshLayout
|
|
||||||
import android.support.v7.widget.LinearLayoutManager
|
|
||||||
import android.support.v7.widget.RecyclerView
|
|
||||||
import android.view.*
|
|
||||||
import com.github.mjdev.libaums.UsbMassStorageDevice
|
|
||||||
import eu.depau.etchdroid.R
|
|
||||||
import eu.depau.etchdroid.StateKeeper
|
|
||||||
import eu.depau.etchdroid.utils.ClickListener
|
|
||||||
import eu.depau.etchdroid.activities.WizardActivity
|
|
||||||
import eu.depau.etchdroid.activities.MainActivity
|
|
||||||
import eu.depau.etchdroid.adapters.UsbDrivesRecyclerViewAdapter
|
|
||||||
import eu.depau.etchdroid.kotlin_exts.name
|
|
||||||
import eu.depau.etchdroid.kotlin_exts.snackbar
|
|
||||||
import eu.depau.etchdroid.enums.WizardStep
|
|
||||||
import eu.depau.etchdroid.utils.RecyclerViewTouchListener
|
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
|
||||||
import kotlinx.android.synthetic.main.fragment_select_usb_drive.view.*
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder fragment containing a simple view.
|
|
||||||
*/
|
|
||||||
class UsbDriveFragment : WizardFragment(), SwipeRefreshLayout.OnRefreshListener {
|
|
||||||
val TAG = "UsbDriveFragment"
|
|
||||||
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
|
||||||
private lateinit var viewAdapter: UsbDrivesRecyclerViewAdapter
|
|
||||||
private lateinit var viewManager: RecyclerView.LayoutManager
|
|
||||||
private lateinit var refreshLayout: SwipeRefreshLayout
|
|
||||||
|
|
||||||
|
|
||||||
override fun onRefresh() {
|
|
||||||
loadUsbDevices()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun nextStep(view: View?) {
|
|
||||||
(activity as WizardActivity).goToNewFragment(ConfirmInfoFragment())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?): View? {
|
|
||||||
StateKeeper.currentFragment = this
|
|
||||||
StateKeeper.wizardStep = WizardStep.SELECT_USB_DRIVE
|
|
||||||
|
|
||||||
val view = inflater.inflate(R.layout.fragment_select_usb_drive, container, false)
|
|
||||||
|
|
||||||
refreshLayout = view.usbdevs_refresh_layout
|
|
||||||
refreshLayout.setOnRefreshListener(this)
|
|
||||||
refreshLayout.post {
|
|
||||||
refreshLayout.isRefreshing = true
|
|
||||||
loadUsbDevices()
|
|
||||||
}
|
|
||||||
|
|
||||||
viewManager = LinearLayoutManager(activity)
|
|
||||||
recyclerView = view.usbdevs_recycler_view
|
|
||||||
|
|
||||||
recyclerView.addOnItemTouchListener(RecyclerViewTouchListener(activity!!, recyclerView, object : ClickListener {
|
|
||||||
override fun onClick(view: View, position: Int) {
|
|
||||||
val device = viewAdapter.get(position)
|
|
||||||
val manager = activity!!.getSystemService(Context.USB_SERVICE) as UsbManager
|
|
||||||
manager.requestPermission(device.usbDevice, (activity as MainActivity).mUsbPermissionIntent)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLongClick(view: View, position: Int) {}
|
|
||||||
}))
|
|
||||||
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setHasOptionsMenu(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadUsbDevices() {
|
|
||||||
try {
|
|
||||||
viewAdapter = UsbDrivesRecyclerViewAdapter(UsbMassStorageDevice.getMassStorageDevices(activity))
|
|
||||||
|
|
||||||
recyclerView.apply {
|
|
||||||
setHasFixedSize(true)
|
|
||||||
layoutManager = viewManager
|
|
||||||
adapter = viewAdapter
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
refreshLayout.isRefreshing = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFragmentAdded(activity: WizardActivity) {
|
|
||||||
activity.fab.hide()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFragmentRemoving(activity: WizardActivity) {
|
|
||||||
activity.fab.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
|
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
|
||||||
menuInflater.inflate(R.menu.usb_devices_menu, menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
// Handle action bar item clicks here. The action bar will
|
|
||||||
// automatically handle clicks on the Home/Up button, so long
|
|
||||||
// as you specify a parent activity in AndroidManifest.xml.
|
|
||||||
return when (item.itemId) {
|
|
||||||
R.id.action_refresh -> {
|
|
||||||
loadUsbDevices()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onUsbPermissionResult(usbDevice: UsbDevice?, granted: Boolean) {
|
|
||||||
if (!granted) {
|
|
||||||
if (usbDevice != null) {
|
|
||||||
recyclerView.snackbar(getString(R.string.usb_perm_denied) + usbDevice.name)
|
|
||||||
} else {
|
|
||||||
recyclerView.snackbar(getString(R.string.usb_perm_denied_noname))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
StateKeeper.usbDevice = usbDevice
|
|
||||||
StateKeeper.usbMassStorageDevice = UsbMassStorageDevice.getMassStorageDevices(activity).find { it.usbDevice == usbDevice }
|
|
||||||
|
|
||||||
nextStep(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package eu.depau.etchdroid.fragments
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.support.v4.app.Fragment
|
|
||||||
import android.view.View
|
|
||||||
import eu.depau.etchdroid.activities.WizardActivity
|
|
||||||
|
|
||||||
abstract class WizardFragment() : Fragment() {
|
|
||||||
private lateinit var wizardActivity: WizardActivity
|
|
||||||
|
|
||||||
abstract fun nextStep(view: View?)
|
|
||||||
|
|
||||||
open fun onFragmentAdded(activity: WizardActivity) {}
|
|
||||||
open fun onFragmentRemoving(activity: WizardActivity) {}
|
|
||||||
open fun onRadioButtonClicked(view: View) {}
|
|
||||||
open fun onCheckBoxClicked(view: View) {}
|
|
||||||
open override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {}
|
|
||||||
open fun onButtonClicked(view: View) {}
|
|
||||||
open override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.depau.etchdroid.kotlin_exts
|
package eu.depau.etchdroid.kotlin_exts
|
||||||
|
|
||||||
import android.support.design.widget.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
|
||||||
fun View.snackbar(message: CharSequence, duration: Int = Snackbar.LENGTH_LONG) {
|
fun View.snackbar(message: CharSequence, duration: Int = Snackbar.LENGTH_LONG) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.support.v4.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import eu.depau.etchdroid.R
|
import eu.depau.etchdroid.R
|
||||||
import eu.depau.etchdroid.kotlin_exts.toHRSize
|
import eu.depau.etchdroid.kotlin_exts.toHRSize
|
||||||
import eu.depau.etchdroid.kotlin_exts.toHRTime
|
import eu.depau.etchdroid.kotlin_exts.toHRTime
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package eu.depau.etchdroid.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
||||||
|
class EmptyRecyclerView : RecyclerView {
|
||||||
|
var emptyView: View? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
checkIfEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val observer: RecyclerView.AdapterDataObserver = object : RecyclerView.AdapterDataObserver() {
|
||||||
|
override fun onChanged() {
|
||||||
|
super.onChanged()
|
||||||
|
checkIfEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: Context) : super(context)
|
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
|
||||||
|
|
||||||
|
internal fun checkIfEmpty() {
|
||||||
|
if (emptyView != null)
|
||||||
|
emptyView!!.visibility = if (adapter?.itemCount ?: 0 > 0) View.GONE else View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setAdapter(adapter: RecyclerView.Adapter<*>?) {
|
||||||
|
val oldAdapter = this.adapter
|
||||||
|
oldAdapter?.unregisterAdapterDataObserver(observer)
|
||||||
|
super.setAdapter(adapter)
|
||||||
|
adapter?.registerAdapterDataObserver(observer)
|
||||||
|
checkIfEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
package eu.depau.etchdroid.utils
|
package eu.depau.etchdroid.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v7.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import android.view.GestureDetector
|
import android.view.GestureDetector
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
|
|
||||||
|
|
34
app/src/main/res/drawable/ic_beta.xml
Normal file
34
app/src/main/res/drawable/ic_beta.xml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="64dp"
|
||||||
|
android:height="64dp"
|
||||||
|
android:viewportWidth="64"
|
||||||
|
android:viewportHeight="64">
|
||||||
|
<path
|
||||||
|
android:pathData="m0,0 l64,64L64,34.6L29.4,0Z"
|
||||||
|
android:strokeAlpha="1"
|
||||||
|
android:strokeWidth="3.24922633"
|
||||||
|
android:fillColor="#c62828"
|
||||||
|
android:strokeColor="#00000000"
|
||||||
|
android:fillAlpha="1"
|
||||||
|
android:strokeLineCap="square"/>
|
||||||
|
<path
|
||||||
|
android:pathData="m29.8847,6.8837l3.1187,3.1187q0.6608,0.6608 0.9275,1.5072 0.2782,0.8579 0.1043,1.7043 -0.1739,0.8463 -0.7884,1.4608 -0.6145,0.6145 -1.3796,0.7536 -0.7536,0.1507 -1.484,-0.1159l-0.0696,0.0696q0.4058,0.8463 0.2782,1.739 -0.1159,0.9043 -0.8,1.5883 -0.684,0.684 -1.5767,0.8579 -0.8811,0.1855 -1.7854,-0.1159 -0.8811,-0.3014 -1.5883,-1.0086l-3.2578,-3.2578zM29.4674,13.4225q0.5565,0.5565 1.2405,0.5449 0.6956,0 1.1478,-0.4522 0.4522,-0.4522 0.4522,-1.1246 0.0232,-0.6724 -0.5101,-1.2057l-1.8086,-1.8086l-2.2839,2.2839zM26.0473,17.2368q0.5913,0.5913 1.3101,0.5681 0.7304,-0.0116 1.2173,-0.4985 0.4985,-0.4985 0.4869,-1.2289 0.0116,-0.7304 -0.6029,-1.3449l-1.9129,-1.9129l-2.4578,2.4578z"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:strokeColor="#00000000"
|
||||||
|
android:fillAlpha="1"/>
|
||||||
|
<path
|
||||||
|
android:pathData="m37.176,14.175l5.0432,5.0432l-1.2405,1.2405l-3.7447,-3.7447l-2.2955,2.2955l3.3737,3.3737l-1.2289,1.2289l-3.3737,-3.3737l-2.2955,2.2955l3.7447,3.7447l-1.2405,1.2405l-5.0432,-5.0432z"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:strokeColor="#00000000"
|
||||||
|
android:fillAlpha="1"/>
|
||||||
|
<path
|
||||||
|
android:pathData="m44.2738,23.7538l-2.3187,-2.3187l1.2405,-1.2405l5.9359,5.9359l-1.2405,1.2405l-2.3187,-2.3187l-7.0605,7.0605l-1.2985,-1.2985z"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:strokeColor="#00000000"
|
||||||
|
android:fillAlpha="1"/>
|
||||||
|
<path
|
||||||
|
android:pathData="m51.972,28.9709l1.484,1.484l-5.1823,11.4197l-1.4376,-1.4376l1.3796,-2.8636l-3.3505,-3.3505l-2.8752,1.368l-1.4376,-1.4376zM48.9808,35.9271 L50.5692,32.5765 51.2068,31.2897l-0.0696,-0.0696l-1.2869,0.6376 -3.3505,1.5883z"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:strokeColor="#00000000"
|
||||||
|
android:fillAlpha="1"/>
|
||||||
|
</vector>
|
16
app/src/main/res/drawable/ic_dmg.xml
Normal file
16
app/src/main/res/drawable/ic_dmg.xml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<vector android:height="96dp" android:viewportHeight="512"
|
||||||
|
android:viewportWidth="512" android:width="96dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillAlpha="0.3" android:fillColor="#FF000000"
|
||||||
|
android:pathData="m170.667,341.333h256v-256h-256z"
|
||||||
|
android:strokeAlpha="0.3" android:strokeWidth="21.33333206"/>
|
||||||
|
<path android:fillColor="#FF000000"
|
||||||
|
android:pathData="m426.667,42.667h-256c-23.467,0 -42.667,19.2 -42.667,42.667v256C128,364.8 147.2,384 170.667,384h256c23.467,0 42.667,-19.2 42.667,-42.667v-256c0,-23.467 -19.2,-42.667 -42.667,-42.667zM426.667,341.333h-256v-256h256z" android:strokeWidth="21.33333206"/>
|
||||||
|
<path android:fillColor="#FF000000"
|
||||||
|
android:pathData="M85.333,128L42.667,128v298.667c0,23.467 19.2,42.667 42.667,42.667L384,469.333L384,426.667L85.333,426.667Z" android:strokeWidth="21.33333206"/>
|
||||||
|
<path android:fillColor="#000000"
|
||||||
|
android:pathData="m277.992,209.953l11.969,0l0,41.891l17.953,0l0,-42.011l11.969,0L319.883,263.814l17.953,0L337.837,203.969C337.837,197.386 332.451,192 325.868,192l-53.86,0C265.424,192 260.038,197.386 260.038,203.969L260.038,263.814l17.953,0z" android:strokeWidth="0.83333331"/>
|
||||||
|
<path android:fillAlpha="1" android:fillColor="#000000"
|
||||||
|
android:pathData="M394.169,191.68L358.263,191.68c-7.181,0 -11.969,5.985 -11.969,11.969l0,47.876c0,5.984 4.788,11.969 11.969,11.969l35.907,0c7.181,0 11.969,-5.985 11.969,-11.969l0,-23.938l-17.953,0l0,17.953l-23.938,0l0,-35.907l41.891,0L406.139,203.649c0,-5.984 -4.788,-11.969 -11.969,-11.969z" android:strokeWidth="0.83333331"/>
|
||||||
|
<path android:fillColor="#000000"
|
||||||
|
android:pathData="M233.098,192L191.195,192L191.195,263.814l41.903,0c10.24,0 17.92,-7.815 17.92,-17.92L251.017,209.92c0,-10.105 -7.68,-17.92 -17.92,-17.92zM233.098,245.894L209.115,245.894L209.115,209.92l23.983,0z" android:strokeWidth="0.93808633"/>
|
||||||
|
</vector>
|
13
app/src/main/res/drawable/ic_raw.xml
Normal file
13
app/src/main/res/drawable/ic_raw.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<vector android:height="96dp" android:viewportHeight="512"
|
||||||
|
android:viewportWidth="512" android:width="96dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillAlpha="0.3" android:fillColor="#FF000000"
|
||||||
|
android:pathData="M171.1,340.9L427.3,340.9L427.3,84.7L171.1,84.7Z" android:strokeAlpha="0.3"/>
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M427.3,42L171.1,42C147.615,42 128.4,61.215 128.4,84.7l0,256.2c0,23.485 19.215,42.7 42.7,42.7l256.2,0c23.485,0 42.7,-19.215 42.7,-42.7L470,84.7C470,61.215 450.785,42 427.3,42ZM427.3,340.9L171.1,340.9L171.1,84.7l256.2,0z"/>
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M85.7,127.4L43,127.4l0,298.9c0,23.485 19.215,42.7 42.7,42.7L384.6,469L384.6,426.3L85.7,426.3Z"/>
|
||||||
|
<path android:fillColor="#FF000000"
|
||||||
|
android:pathData="M253.711,221.384L253.711,209.384c0,-10.247 -7.82,-17.932 -17.932,-17.932L193.847,191.451L193.847,263.316l17.932,0l0,-24l13.753,0l10.247,24l17.932,0l-10.786,-25.213c5.932,-2.966 10.786,-9.573 10.786,-16.719zM235.779,221.384L211.779,221.384L211.779,209.384l24,0z" android:strokeWidth="0.63151968"/>
|
||||||
|
<path android:fillColor="#FF000000"
|
||||||
|
android:pathData="m280.71,245.35l23.955,0l0,17.966l17.966,0L322.631,203.429c0,-6.588 -5.39,-11.977 -11.977,-11.977l-35.932,0c-6.588,0 -11.977,5.39 -11.977,11.977L262.744,263.316l17.966,0zM280.71,209.418l23.955,0L304.665,227.384l-23.955,0z" android:strokeWidth="0.56099999"/>
|
||||||
|
<path android:fillColor="#FF000000"
|
||||||
|
android:pathData="m332.835,191.451l0,59.935c0,6.546 5.383,11.929 11.929,11.929l47.861,0c6.546,0 11.929,-5.383 11.929,-11.929L404.553,191.451L389.57,191.451L389.57,245.422L376.186,245.422L376.186,203.38l-14.984,0l0,42.187l-13.529,0L347.673,191.451Z" android:strokeWidth="0.68137652"/>
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_twotone_save_alt_24px.xml
Normal file
9
app/src/main/res/drawable/ic_twotone_save_alt_24px.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M19,12v7H5v-7H3v7c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2v-7H19zM13,12.67l2.59,-2.58L17,11.5l-5,5l-5,-5l1.41,-1.41L11,12.67V3h2V12.67z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_usb_black_200dp.xml
Normal file
5
app/src/main/res/drawable/ic_usb_black_200dp.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:alpha="0.4" android:height="200dp"
|
||||||
|
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||||
|
android:width="200dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M15,7v4h1v2h-3V5h2l-3,-4 -3,4h2v8H8v-2.07c0.7,-0.37 1.2,-1.08 1.2,-1.93 0,-1.21 -0.99,-2.2 -2.2,-2.2 -1.21,0 -2.2,0.99 -2.2,2.2 0,0.85 0.5,1.56 1.2,1.93V13c0,1.11 0.89,2 2,2h3v3.05c-0.71,0.37 -1.2,1.1 -1.2,1.95 0,1.22 0.99,2.2 2.2,2.2 1.21,0 2.2,-0.98 2.2,-2.2 0,-0.85 -0.49,-1.58 -1.2,-1.95V15h3c1.11,0 2,-0.89 2,-2v-2h1V7h-4z"/>
|
||||||
|
</vector>
|
219
app/src/main/res/layout/activity_confirmation.xml
Normal file
219
app/src/main/res/layout/activity_confirmation.xml
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/linearLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".activities.ConfirmationActivity">
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/nestedScrollView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/relativeLayout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/row_padding"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/row_padding"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirm_sel_method_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:text="@string/selected_method"
|
||||||
|
android:textColor="@color/name"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirm_sel_method"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/confirm_sel_method_title"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/row_padding"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/row_padding"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirm_sel_image_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:text="@string/selected_image"
|
||||||
|
android:textColor="@color/name"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirm_sel_image"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/confirm_sel_image_title"/>
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirm_sel_image_size"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:textColor="@color/info"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/relativeLayout2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/row_padding"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/row_padding"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirm_sel_usbdev_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:text="@string/selected_usbdev"
|
||||||
|
android:textColor="@color/name"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirm_sel_usbdev"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/confirm_sel_usbdev_title"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirm_sel_usbdev_size"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:textColor="@color/info"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/row_padding"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/row_padding"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/confirm_extra_info"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:textColor="@color/name"
|
||||||
|
android:textSize="16sp"/>
|
||||||
|
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/part_table_header"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/row_padding"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/row_padding"
|
||||||
|
android:textColor="@color/name"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/part_table_header_side"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/row_padding"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/row_padding"
|
||||||
|
android:textColor="@color/info"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/part_table_recycler"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/row_padding"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingBottom="@dimen/row_padding"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/relativeLayout2"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/confirm_fab"
|
||||||
|
style="@style/Widget.MaterialComponents.FloatingActionButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="@dimen/fab_margin"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:onClick="onButtonClicked"
|
||||||
|
app:srcCompat="@drawable/ic_twotone_save_alt_24px"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.constraint.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
@ -7,11 +7,11 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".activities.LicensesActivity">
|
tools:context=".activities.LicensesActivity">
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/licenses_recycler_view"
|
android:id="@+id/licenses_recycler_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scrollbars="vertical"/>
|
android:scrollbars="vertical"/>
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,34 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<android.support.design.widget.CoordinatorLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".activities.MainActivity">
|
|
||||||
|
|
||||||
<android.support.design.widget.AppBarLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:theme="@style/AppTheme.AppBarOverlay">
|
|
||||||
|
|
||||||
<android.support.v7.widget.Toolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
android:background="?attr/colorPrimary"
|
|
||||||
app:popupTheme="@style/AppTheme.PopupOverlay"/>
|
|
||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
|
||||||
|
|
||||||
<include layout="@layout/wizard_fragment_layout"/>
|
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
|
||||||
android:id="@+id/fab"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:layout_margin="@dimen/fab_margin"
|
|
||||||
app:srcCompat="@drawable/ic_navigate_next_black_24dp"/>
|
|
||||||
|
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
|
151
app/src/main/res/layout/activity_start.xml
Normal file
151
app/src/main/res/layout/activity_start.xml
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".activities.StartActivity">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".fragments.FlashMethodFragment"
|
||||||
|
tools:showIn="@layout/activity_start">
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:layout_marginLeft="@dimen/card_margin"
|
||||||
|
android:layout_marginTop="@dimen/card_margin"
|
||||||
|
android:layout_marginRight="@dimen/card_margin"
|
||||||
|
android:minHeight="200dp">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/btn_image_raw"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:onClick="onButtonClicked">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.0"
|
||||||
|
app:srcCompat="@drawable/ic_raw"/>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/imageView"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.502">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/write_image_or_iso"
|
||||||
|
android:textColor="@color/name"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView2"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/textView"
|
||||||
|
android:text="@string/raw_image_desc"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:layout_marginLeft="@dimen/card_margin"
|
||||||
|
android:layout_marginTop="@dimen/card_margin"
|
||||||
|
android:layout_marginRight="@dimen/card_margin"
|
||||||
|
android:layout_marginBottom="@dimen/card_margin"
|
||||||
|
android:minHeight="200dp">
|
||||||
|
<!--
|
||||||
|
android:background="?attr/selectableItemBackground"-->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/btn_image_dmg"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:onClick="onButtonClicked">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.0"
|
||||||
|
app:srcCompat="@drawable/ic_dmg"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView3"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="-2dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/ic_beta"/>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginEnd="36dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/imageView2"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView4"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/write_apple_dmg"
|
||||||
|
android:textColor="@color/name"
|
||||||
|
android:textStyle="bold"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textView5"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/textView4"
|
||||||
|
android:text="@string/dmg_image_desc"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
42
app/src/main/res/layout/activity_usb_drive_picker.xml
Normal file
42
app/src/main/res/layout/activity_usb_drive_picker.xml
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/usbdevs_swiperefreshlayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".activities.UsbDrivePickerActivity">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<eu.depau.etchdroid.utils.EmptyRecyclerView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/usbdevs_recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scrollbars="vertical"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/usbdevs_recycler_empty_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:text="@string/no_usb_drives_detected"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:drawableTop="@drawable/ic_usb_black_200dp"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
|
@ -1,144 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
tools:context=".fragments.ConfirmInfoFragment">
|
|
||||||
<!--tools:showIn="@layout/activity_main"-->
|
|
||||||
|
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingBottom="@dimen/row_padding"
|
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingTop="@dimen/row_padding">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/confirm_sel_method_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:text="@string/selected_method"
|
|
||||||
android:textColor="@color/name"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/confirm_sel_method"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/confirm_sel_method_title"/>
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingBottom="@dimen/row_padding"
|
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingTop="@dimen/row_padding">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/confirm_sel_image_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:text="@string/selected_image"
|
|
||||||
android:textColor="@color/name"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/confirm_sel_image"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/confirm_sel_image_title"/>
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/confirm_sel_image_size"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:textColor="@color/info"/>
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingBottom="@dimen/row_padding"
|
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingTop="@dimen/row_padding">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/confirm_sel_usbdev_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:text="@string/selected_usbdev"
|
|
||||||
android:textColor="@color/name"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/confirm_sel_usbdev"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/confirm_sel_usbdev_title"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/confirm_sel_usbdev_size"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:textColor="@color/info"/>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingBottom="@dimen/row_padding"
|
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingTop="@dimen/row_padding">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/confirm_extra_info"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:textColor="@color/name"
|
|
||||||
android:textSize="16sp"/>
|
|
||||||
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -1,46 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
tools:context=".fragments.FlashMethodFragment"
|
|
||||||
tools:showIn="@layout/activity_main">
|
|
||||||
|
|
||||||
<RadioGroup
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<RadioButton
|
|
||||||
android:id="@+id/flash_usb_api_radio"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:onClick="onRadioButtonClicked"
|
|
||||||
android:text="@string/flash_dd_usb_api"/>
|
|
||||||
|
|
||||||
<RadioButton
|
|
||||||
android:id="@+id/flash_dmg_api_radio"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:onClick="onRadioButtonClicked"
|
|
||||||
android:text="@string/flash_dmg_api"/>
|
|
||||||
|
|
||||||
<RadioButton
|
|
||||||
android:id="@+id/flash_unetbootin_radio"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:enabled="false"
|
|
||||||
android:onClick="onRadioButtonClicked"
|
|
||||||
android:text="@string/flash_unetbootin"/>
|
|
||||||
|
|
||||||
<RadioButton
|
|
||||||
android:id="@+id/flash_woeusb_radio"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:enabled="false"
|
|
||||||
android:onClick="onRadioButtonClicked"
|
|
||||||
android:text="@string/flash_woeusb"/>
|
|
||||||
|
|
||||||
</RadioGroup>
|
|
||||||
</LinearLayout>
|
|
|
@ -1,59 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
tools:context=".fragments.FlashMethodFragment">
|
|
||||||
|
|
||||||
<RadioGroup
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/pick_file_btn"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:onClick="onButtonClicked"
|
|
||||||
android:text="@string/pick_a_file"/>
|
|
||||||
|
|
||||||
</RadioGroup>
|
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:paddingBottom="@dimen/row_padding"
|
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingTop="@dimen/row_padding">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/part_table_header"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="@dimen/grid_padding"
|
|
||||||
android:textColor="@color/name"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/part_table_header_side"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="@dimen/grid_padding"
|
|
||||||
android:textColor="@color/info"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
|
||||||
android:id="@+id/part_table_recycler"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -1,16 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<android.support.v4.widget.SwipeRefreshLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/usbdevs_refresh_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/usbdevs_recycler_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:scrollbars="vertical"/>
|
|
||||||
|
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>
|
|
|
@ -1,7 +1,7 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context="eu.depau.etchdroid.activities.MainActivity">
|
tools:context="eu.depau.etchdroid.activities.StartActivity">
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_licenses"
|
android:id="@+id/action_licenses"
|
||||||
android:orderInCategory="100"
|
android:orderInCategory="100"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="colorPrimary">#3F51B5</color>
|
<color name="colorPrimary">#4caf50</color>
|
||||||
<color name="colorPrimaryDark">#303F9F</color>
|
<color name="colorPrimaryDark">#087f23</color>
|
||||||
<color name="colorAccent">#FF4081</color>
|
<color name="colorAccent">#4caf50</color>
|
||||||
<color name="info">#999999</color>
|
<color name="info">#999999</color>
|
||||||
<color name="name">#222222</color>
|
<color name="name">#222222</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
<dimen name="row_padding">10dp</dimen>
|
<dimen name="row_padding">10dp</dimen>
|
||||||
<dimen name="grid_padding">5dp</dimen>
|
<dimen name="grid_padding">5dp</dimen>
|
||||||
|
<dimen name="card_margin">12dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<string name="please_select_writing_method">Please select writing method</string>
|
<string name="please_select_writing_method">Please select writing method</string>
|
||||||
<string name="image_bigger_than_usb">Image is bigger than the USB drive, so it can\'t be written</string>
|
<string name="image_bigger_than_usb">Image is bigger than the USB drive, so it can\'t be written</string>
|
||||||
<string name="cant_read_usbdev">Cannot read USB device</string>
|
<string name="cant_read_usbdev">Cannot read USB device</string>
|
||||||
<string name="tap_next_to_write">Tap Next to write the image to the USB drive</string>
|
<string name="tap_next_to_write">Tap Write to write the image to the USB drive</string>
|
||||||
<string name="notchan_writestatus_title">USB write status</string>
|
<string name="notchan_writestatus_title">USB write status</string>
|
||||||
<string name="notchan_writestatus_desc">Used to display the status of images being written to USB drives</string>
|
<string name="notchan_writestatus_desc">Used to display the status of images being written to USB drives</string>
|
||||||
<string name="notif_initializing">Initializing...</string>
|
<string name="notif_initializing">Initializing...</string>
|
||||||
|
@ -81,4 +81,15 @@
|
||||||
<string name="license_custom">Custom</string>
|
<string name="license_custom">Custom</string>
|
||||||
<string name="licenses">Licenses</string>
|
<string name="licenses">Licenses</string>
|
||||||
<string name="dmg2img_license_desc">Converts compressed Apple® DMG images</string>
|
<string name="dmg2img_license_desc">Converts compressed Apple® DMG images</string>
|
||||||
|
<string name="title_activity_usb_drive_picker">Select USB drive</string>
|
||||||
|
<string name="title_activity_confirmation">Ready to write</string>
|
||||||
|
<string name="cannot_write">Cannot write image to USB drive</string>
|
||||||
|
<string name="check_notification_progress">Check notification for progress</string>
|
||||||
|
<string name="partition_table_title">Partition table:</string>
|
||||||
|
<string name="could_not_access_usb_error">Could not access USB device. Maybe you ran the app previously and it crashed? Remove and reinsert the USB drive, then restart the app.</string>
|
||||||
|
<string name="write_image_or_iso">Write raw image or ISO</string>
|
||||||
|
<string name="raw_image_desc">Good for GNU/Linux distribution ISOs and disk images created on Windows or Linux</string>
|
||||||
|
<string name="write_apple_dmg">Write Apple® DMG image</string>
|
||||||
|
<string name="dmg_image_desc">Restore an image created with macOS Disk Utility</string>
|
||||||
|
<string name="no_usb_drives_detected">No USB drives detected</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="AppTheme" parent="Base.Theme.AppCompat.Light.DarkActionBar">
|
<style name="MaterialAppTheme" parent="Base.Theme.AppCompat.Light.DarkActionBar">
|
||||||
<!-- Customize your theme here. -->
|
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
@ -10,13 +9,14 @@
|
||||||
<item name="floatingActionButtonStyle">@style/Widget.Design.FloatingActionButton</item>
|
<item name="floatingActionButtonStyle">@style/Widget.Design.FloatingActionButton</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.NoActionBar">
|
|
||||||
|
<style name="MaterialAppTheme.NoActionBar">
|
||||||
<item name="windowActionBar">false</item>
|
<item name="windowActionBar">false</item>
|
||||||
<item name="windowNoTitle">true</item>
|
<item name="windowNoTitle">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
|
|
||||||
|
|
||||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
|
<style name="MaterialAppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
|
||||||
|
|
||||||
|
<style name="MaterialAppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
|
||||||
</resources>
|
</resources>
|
|
@ -1,13 +1,13 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.2.50'
|
ext.kotlin_version = '1.2.51'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.1.4'
|
classpath 'com.android.tools.build:gradle:3.2.0-rc02'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
|
||||||
// For libaums
|
// For libaums
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
# Specifies the JVM arguments used for the daemon process.
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
# The setting is particularly useful for tweaking memory settings.
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
android.enableJetifier=true
|
||||||
|
android.useAndroidX=true
|
||||||
org.gradle.jvmargs=-Xmx1536m
|
org.gradle.jvmargs=-Xmx1536m
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
||||||
#Sat Aug 11 18:29:21 CEST 2018
|
#Thu Aug 30 23:16:18 CEST 2018
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||||
|
|
Loading…
Reference in a new issue