Skip to content

Commit

Permalink
Merge pull request #58 from Khang-NT/release/0.7.1
Browse files Browse the repository at this point in the history
Release 0.7.1
  • Loading branch information
Khang-NT committed Feb 24, 2018
2 parents ee12a82 + 862996a commit 01ce691
Show file tree
Hide file tree
Showing 27 changed files with 947 additions and 406 deletions.
6 changes: 3 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ android {
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "0.7.0"
versionName "0.7.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

Expand Down Expand Up @@ -64,7 +64,7 @@ android {
}
}

final _versionCode = 20
final _versionCode = 21

flavorDimensions 'cpuArch'
productFlavors {
Expand Down Expand Up @@ -160,7 +160,7 @@ dependencies {
transitive = true
}

implementation 'com.liulishuo.filedownloader:library:1.6.9'
implementation 'com.liulishuo.filedownloader:library:1.7.1'

debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
Expand Down
37 changes: 37 additions & 0 deletions app/src/main/java/com/github/khangnt/mcp/MainApplication.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.github.khangnt.mcp

import android.app.Application
import android.os.StrictMode
import com.crashlytics.android.Crashlytics
import com.github.khangnt.mcp.util.IMMLeaks
import com.liulishuo.filedownloader.FileDownloader
import com.liulishuo.filedownloader.database.NoDatabaseImpl
import com.squareup.leakcanary.LeakCanary
import io.fabric.sdk.android.Fabric
import io.reactivex.exceptions.UndeliverableException
import io.reactivex.plugins.RxJavaPlugins
import timber.log.Timber

/**
Expand All @@ -18,6 +21,8 @@ class MainApplication: Application() {

override fun onCreate() {
super.onCreate()
setupStrictMode()

if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
Expand All @@ -40,6 +45,38 @@ class MainApplication: Application() {
} else {
Timber.plant(CrashlyticsTree())
}

setUpRxPlugins()
}

private fun setupStrictMode() {
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyFlashScreen()
.penaltyLog()
.build())
StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.detectActivityLeaks()
.penaltyLog()
.build())
} else {
// on release, don't detect any thing
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().build())
StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder().penaltyLog().build())
}
}

private fun setUpRxPlugins() {
RxJavaPlugins.setErrorHandler { throwable ->
Timber.d(throwable)
if (throwable is UndeliverableException) {
reportNonFatal(throwable.cause!!, "rx_undeliverable_exception")
} else {
reportNonFatal(throwable, "rx_undeliverable_exception")
}
}
}
}
17 changes: 15 additions & 2 deletions app/src/main/java/com/github/khangnt/mcp/PresetCommandInfo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.github.khangnt.mcp

import android.support.annotation.StringRes
import android.support.v4.app.Fragment
import com.github.khangnt.mcp.ui.presetcmd.aac.ConvertAacFragment
import com.github.khangnt.mcp.ui.presetcmd.flac.ConvertFlacFragment
import com.github.khangnt.mcp.ui.presetcmd.mp3.ConvertMp3Fragment

const val TYPE_AUDIO = 0
Expand All @@ -20,12 +22,23 @@ enum class PresetCommand(
val convertFragmentFactory: () -> Fragment
) {
CONVERT_MP3(
type = TYPE_AUDIO, shortName = "MP3", colors = colorArrayOf(0xffFC5C7D, 0xff6A82FB),
type = TYPE_AUDIO, shortName = "MP3", colors = colorArrayOf(0xffFC5C7D, 0xff6A82FB), // SublimeLight
titleRes = R.string.preset_command_convert_mp3_title,
descriptionRes = R.string.preset_command_convert_mp3_des,
convertFragmentFactory = ::ConvertMp3Fragment
),

CONVERT_AAC(
type = TYPE_AUDIO, shortName = "AAC", colors = colorArrayOf(0xff11998e, 0xff38ef7d), // Quepal
titleRes = R.string.preset_command_convert_aac_title,
descriptionRes = R.string.preset_command_convert_aac_des,
convertFragmentFactory = ::ConvertAacFragment
),
CONVERT_FLAC(
type = TYPE_AUDIO, shortName = "FLAC", colors = colorArrayOf(0xff74ebd5, 0xffACB6E5), // DigitalWater
titleRes = R.string.preset_command_convert_flac_title,
descriptionRes = R.string.preset_command_convert_flac_des,
convertFragmentFactory = ::ConvertFlacFragment
)
;
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,26 @@ import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context
import android.content.Intent
import android.os.Build
import android.support.v4.app.NotificationCompat
import com.github.khangnt.mcp.CONVERTER_NOTIFICATION_CHANNEL
import com.github.khangnt.mcp.R
import com.github.khangnt.mcp.ui.EXTRA_OPEN_JOB_MANAGER
import com.github.khangnt.mcp.ui.MainActivity

/**
* Created by Khang NT on 1/4/18.
* Email: khang.neon.1997@gmail.com
*/

class NotificationHelper(val appContext: Context) {
class NotificationHelper(private val appContext: Context) {
private val notificationManager =
appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

private val openJobManager by lazy {
PendingIntent.getActivity(appContext, 0,
Intent(appContext, MainActivity::class.java)
.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT or
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or
Intent.FLAG_ACTIVITY_SINGLE_TOP)
.putExtra(EXTRA_OPEN_JOB_MANAGER, true),
PendingIntent.FLAG_UPDATE_CURRENT)
val openJobManagerIntent = MainActivity.openJobManagerIntent(appContext)
PendingIntent.getActivity(appContext, 0, openJobManagerIntent, FLAG_UPDATE_CURRENT)
}

init {
Expand Down
13 changes: 11 additions & 2 deletions app/src/main/java/com/github/khangnt/mcp/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,21 @@ import java.lang.IllegalArgumentException
import java.util.concurrent.TimeUnit.DAYS
import java.util.concurrent.TimeUnit.MILLISECONDS

const val EXTRA_OPEN_JOB_MANAGER = "EXTRA:openJobManager"

private const val EXTRA_OPEN_JOB_MANAGER = "EXTRA:openJobManager"
private const val KEY_SELECTED_FRAGMENT = "MainActivity:selectedFragment"

class MainActivity : SingleFragmentActivity(), NavigationView.OnNavigationItemSelectedListener {

companion object {
fun openJobManagerIntent(context: Context): Intent {
return Intent(context, MainActivity::class.java)
.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT or
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or
Intent.FLAG_ACTIVITY_SINGLE_TOP)
.putExtra(EXTRA_OPEN_JOB_MANAGER, true)
}
}

private val jobStatusChangedReceiver = JobStatusChangedReceiver()
private var currentDrawerListener: DrawerLayout.DrawerListener? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private const val KET_START_UP_DIR = "FileBrowserFragment:start_up_directory"
private const val KEY_SELECTED_FILE_LIST = "FileBrowserFragment:selected_file_list"
private const val KEY_CURRENT_DIR = "FileBrowserFragment:current_dir"

class FileBrowserFragment : BaseFragment() {
class FileBrowserFragment : BaseFragment(), FileListFragment.CallbackDeclare {

companion object {
fun newInstance(
Expand Down Expand Up @@ -61,14 +61,6 @@ class FileBrowserFragment : BaseFragment() {
?: emptyList<String>()
selectedFiles.addAll(list.map { File(it) })
}

// re-attach callbacks
childFragmentManager.fragments.forEach { fragment ->
if (fragment is FileListFragment) {
fragment.onItemClickListener = onItemClickListener
fragment.checkedFilesRetriever = checkedFilesRetriever
}
}
}

override fun onCreateView(
Expand All @@ -95,40 +87,34 @@ class FileBrowserFragment : BaseFragment() {
val oldDir = currentDir
currentDir = dir
val existsFragment = childFragmentManager.findFragmentByTag(dir.absolutePath)
if (existsFragment != null) {
if (existsFragment is FileListFragment) { // implicit check !== null
childFragmentManager.popBackStack(dir.absolutePath, POP_BACK_STACK_INCLUSIVE)
} else {
val fragment = createFileListFragmentFor(dir)
val fragment = FileListFragment.newInstance(dir)
showFragment(oldDir, dir, fragment)
}

onDirChanged?.invoke(this, dir)
}
}

private fun createFileListFragmentFor(dir: File) = FileListFragment.newInstance(dir).also {
// set callbacks
it.onItemClickListener = onItemClickListener
it.checkedFilesRetriever = checkedFilesRetriever
}

private val onItemClickListener: OnItemClickListener = { _, clickItem ->
if (clickItem.isDirectory) {
goto(clickItem)
override fun onFileItemClick(fragment: FileListFragment, item: File): Boolean {
return if (item.isDirectory) {
goto(item)
false
} else if (selectedFiles.remove(clickItem)) {
} else if (selectedFiles.remove(item)) {
// discard select
onSelectedFilesChanged()
true
} else if (selectedFiles.size < maxFileCanSelect) {
// remember this file is selected
selectedFiles.add(clickItem)
selectedFiles.add(item)
onSelectedFilesChanged()
true
} else if (removeOldest && selectedFiles.isNotEmpty()) {
// exceed max file can select -> remove oldest file
selectedFiles.removeAt(0)
selectedFiles.add(clickItem)
selectedFiles.add(item)
onSelectedFilesChanged()
true
} else {
Expand All @@ -137,12 +123,10 @@ class FileBrowserFragment : BaseFragment() {
}
}

fun getSelectedFiles(): List<File> = selectedFilesReadOnly
override fun getCheckedFiles(): List<File> = selectedFilesReadOnly

fun getCurrentDir(): File? = currentDir

private val checkedFilesRetriever: CheckedFilesRetriever = { selectedFilesReadOnly }

private fun showFragment(oldDir: File?, dir: File, fileListFragment: FileListFragment) {
childFragmentManager.beginTransaction()
.replace(R.id.fileListContainer, fileListFragment, dir.absolutePath)
Expand All @@ -157,9 +141,8 @@ class FileBrowserFragment : BaseFragment() {
override fun onBackPressed(): Boolean {
val count = childFragmentManager.backStackEntryCount
if (count > 0) {
currentDir = File(childFragmentManager.getBackStackEntryAt(count - 1).name)
childFragmentManager.popBackStackImmediate()
onDirChanged?.invoke(this, currentDir!!)
// pop top stack
goto(File(childFragmentManager.getBackStackEntryAt(count - 1).name))
return true
}
return super.onBackPressed()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,14 @@ import kotlinx.android.synthetic.main.fragment_file_list.*
import timber.log.Timber
import java.io.File

typealias OnItemClickListener = (
fragment: FileListFragment,
item: File
) -> Boolean

typealias CheckedFilesRetriever = () -> List<File>

private const val KEY_PATH = "FileListFragment:path"

class FileListFragment : BaseFragment() {
interface CallbackDeclare {
fun onFileItemClick(fragment: FileListFragment, item: File): Boolean
fun getCheckedFiles(): List<File>
}

companion object {
fun newInstance(path: File): FileListFragment {
return FileListFragment().apply {
Expand All @@ -47,20 +45,14 @@ class FileListFragment : BaseFragment() {
private val path: File by lazy { File(arguments!!.getString(KEY_PATH)) }
private val createFolderItem = FileListModel(File("+folder"), TYPE_CREATE_FOLDER)

// retains instances
private lateinit var adapter: MixAdapter
private lateinit var recyclerViewGroupState: RecyclerViewGroupState

lateinit var onItemClickListener: OnItemClickListener
lateinit var checkedFilesRetriever: CheckedFilesRetriever

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true

if (!(::onItemClickListener.isInitialized && ::checkedFilesRetriever.isInitialized)) {
throw IllegalStateException("Must initialize onItemClickListener & checkedFilesRetriever")
}

adapter = MixAdapter.Builder("FileListFragment")
.register(FileListModel::class.java, { inflater, parent ->
FileListViewHolder(
Expand All @@ -73,18 +65,26 @@ class FileListFragment : BaseFragment() {
reloadData()
}

private fun getCallbackDeclaration(): CallbackDeclare {
return (parentFragment as? CallbackDeclare)
?: throw IllegalStateException(
"Parent fragment must implement FileListFragment.CallbackDeclare")
}

private val onClickListener = { model: FileListModel, _: Int ->
when (model.type) {
TYPE_FOLDER, TYPE_FILE -> {
if (onItemClickListener(this, model.path)) {
if (getCallbackDeclaration().onFileItemClick(this, model.path)) {
adapter.notifyDataSetChanged()
}
}
TYPE_CREATE_FOLDER -> showCreateFolderDialog()
}
}

private val checkStateFunc: (FileListModel) -> Boolean = { checkedFilesRetriever().contains(it.path) }
private val checkStateFunc: (FileListModel) -> Boolean = {
getCallbackDeclaration().getCheckedFiles().contains(it.path)
}

override fun onCreateView(
inflater: LayoutInflater,
Expand Down Expand Up @@ -127,7 +127,7 @@ class FileListFragment : BaseFragment() {

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (grantResults.any { it != PERMISSION_GRANTED }) {
if (grantResults.any { it != PERMISSION_GRANTED }) {
recyclerViewGroupState.error(getString(R.string.user_denied_permission))
} else {
reloadData()
Expand Down

0 comments on commit 01ce691

Please sign in to comment.