Skip to content

Commit

Permalink
Merge pull request #143 from TeamAmaze/feature
Browse files Browse the repository at this point in the history
Bugfixes for audio player, subtitles dialog picker
  • Loading branch information
VishalNehra authored Dec 10, 2023
2 parents 51dc6ca + 1218864 commit dbae481
Show file tree
Hide file tree
Showing 45 changed files with 1,137 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import com.amaze.fileutilities.utilis.ObtainableServiceBinder
import com.amaze.fileutilities.utilis.PreferencesConstants
import com.amaze.fileutilities.utilis.Utils
import com.amaze.fileutilities.utilis.getAppCommonSharedPreferences
import com.amaze.fileutilities.utilis.startServiceSafely
import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem
Expand Down Expand Up @@ -89,7 +90,7 @@ class AudioPlayerService : Service(), ServiceOperationCallback, OnPlayerRepeatin
intent.putParcelableArrayListExtra(ARG_URI_LIST, ArrayList(uriList))
}
intent.action = action
context.startService(intent)
context.startServiceSafely(intent, ARG_URI_LIST)
}

fun sendCancelBroadcast(context: Context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ public class M3UWriter {

public static File write(File dir, MediaFileInfo.Playlist playlist, List<MediaFileInfo> songs)
throws IOException {
if (!dir.exists()) // noinspection ResultOfMethodCallIgnored
dir.mkdirs();
if (!dir.exists()) {
// noinspection ResultOfMethodCallIgnored
dir.mkdirs();
}
File file = new File(dir, playlist.getName().concat("." + EXTENSION));

if (songs.size() > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import com.amaze.fileutilities.utilis.share.getShareIntents
import com.amaze.fileutilities.utilis.share.showEditImageDialog
import com.amaze.fileutilities.utilis.share.showShareDialog
import com.amaze.fileutilities.utilis.showFade
import com.amaze.fileutilities.utilis.showToastOnBottom
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
Expand Down Expand Up @@ -314,13 +315,14 @@ class EditImageActivity :

private fun addFilterViews() {
loadedBitmap?.let {
val resizedBitmap = Bitmap.createScaledBitmap(loadedBitmap!!, 100, 100, false)
supportedFilters.forEach {
photoFilter ->
val filterItem = layoutInflater.inflate(R.layout.row_filter_view, null)
val photoEditorView = filterItem.findViewById<PhotoEditorView>(R.id.imgFilterView)
val txtFilterName = filterItem.findViewById<TextView>(R.id.txtFilterName)
txtFilterName.text = photoFilter.name.replace("_", " ")
photoEditorView.source.setImageBitmap(loadedBitmap)
photoEditorView.source.setImageBitmap(resizedBitmap)
try {
photoEditorView.setFilterEffect(photoFilter)
} catch (e: Exception) {
Expand Down Expand Up @@ -620,7 +622,12 @@ class EditImageActivity :
}

override fun onFilterSelected(photoFilter: PhotoFilter?) {
mPhotoEditor?.setFilterEffect(photoFilter)
try {
mPhotoEditor?.setFilterEffect(photoFilter)
} catch (e: Exception) {
log.error("failed to apply filter on bitmap")
this.showToastOnBottom(getString(R.string.operation_failed))
}
}

override fun onToolSelected(toolType: ToolType?) {
Expand Down
38 changes: 35 additions & 3 deletions app/src/main/java/com/amaze/fileutilities/utilis/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package com.amaze.fileutilities.utilis

import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.res.Resources
import android.database.Cursor
Expand All @@ -30,6 +31,7 @@ import android.net.Uri
import android.os.Build
import android.os.Environment
import android.os.ParcelFileDescriptor
import android.os.TransactionTooLargeException
import android.provider.MediaStore
import android.util.DisplayMetrics
import android.view.Gravity
Expand All @@ -42,9 +44,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.documentfile.provider.DocumentFile
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.files.FileFilter
import com.afollestad.materialdialogs.files.fileChooser
import com.afollestad.materialdialogs.files.folderChooser
import com.amaze.fileutilities.audio_player.AudioPlayerService
import com.amaze.fileutilities.home_page.database.BlurAnalysis
import com.amaze.fileutilities.home_page.database.BlurAnalysisDao
import com.amaze.fileutilities.home_page.database.ImageAnalysis
Expand All @@ -59,6 +59,9 @@ import com.amaze.fileutilities.home_page.database.SimilarImagesAnalysis
import com.amaze.fileutilities.home_page.database.SimilarImagesAnalysisDao
import com.amaze.fileutilities.home_page.database.SimilarImagesAnalysisMetadata
import com.amaze.fileutilities.home_page.database.SimilarImagesAnalysisMetadataDao
import com.amaze.fileutilities.utilis.dialog_picker.FileFilter
import com.amaze.fileutilities.utilis.dialog_picker.fileChooser
import com.amaze.fileutilities.utilis.dialog_picker.folderChooser
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -451,6 +454,35 @@ fun Context.getAppCommonSharedPreferences(): SharedPreferences {
)
}

fun Context.startServiceSafely(intent: Intent, extraName: String) {
try {
this.startService(intent)
} catch (ttle: TransactionTooLargeException) {
// decrease by 10% and try recursively
val intentUriList: ArrayList<Uri>? = intent.getParcelableArrayListExtra(extraName)
intentUriList?.let {
if (intentUriList.isNotEmpty()) {
log.warn("failed to start service with extras size ${intentUriList.size}", ttle)
val uri = it.take(intentUriList.size - (intentUriList.size / 10))
if (uri.isNotEmpty()) {
log.warn("trying to start with new size ${uri.size}")
intent.putParcelableArrayListExtra(
AudioPlayerService.ARG_URI_LIST,
ArrayList(uri)
)
startServiceSafely(intent, extraName)
} else {
log.error("couldn't start service safely, returning...", ttle)
return
}
} else {
log.error("couldn't start service safely, returning...", ttle)
return
}
}
}
}

fun ImageAnalysis.invalidate(dao: ImageAnalysisDao): Boolean {
val file = File(filePath)
return if (!file.exists()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2021-2023 Arpit Khurana <arpitkh96@gmail.com>, Vishal Nehra <vishalmeham2@gmail.com>,
* Emmanuel Messulam<emmanuelbendavid@gmail.com>, Raymond Lai <airwave209gt at gmail.com> and Contributors.
*
* This file is part of Amaze File Utilities.
*
* Amaze File Utilities is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/**
* Designed and developed by Aidan Follestad (@afollestad)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.amaze.fileutilities.utilis.dialog_picker

import android.content.Context
import java.io.File

internal fun Context.getExternalFilesDir(): File? {
return this.getExternalFilesDir(null)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
* Copyright (C) 2021-2023 Arpit Khurana <arpitkh96@gmail.com>, Vishal Nehra <vishalmeham2@gmail.com>,
* Emmanuel Messulam<emmanuelbendavid@gmail.com>, Raymond Lai <airwave209gt at gmail.com> and Contributors.
*
* This file is part of Amaze File Utilities.
*
* Amaze File Utilities is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/**
* Designed and developed by Aidan Follestad (@afollestad)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

@file:Suppress("unused")

package com.amaze.fileutilities.utilis.dialog_picker

import android.annotation.SuppressLint
import android.content.Context
import android.text.InputFilter
import android.widget.EditText
import android.widget.TextView
import androidx.annotation.CheckResult
import androidx.annotation.StringRes
import androidx.recyclerview.widget.LinearLayoutManager
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.WhichButton.POSITIVE
import com.afollestad.materialdialogs.actions.setActionButtonEnabled
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import com.afollestad.materialdialogs.files.R
import com.afollestad.materialdialogs.input.getInputField
import com.afollestad.materialdialogs.input.input
import com.afollestad.materialdialogs.internal.list.DialogRecyclerView
import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
import java.io.File

typealias FileFilter = ((File) -> Boolean)?
typealias FileCallback = ((dialog: MaterialDialog, file: File) -> Unit)?

/** Gets the selected file for the current file chooser dialog. */
@CheckResult
fun MaterialDialog.selectedFile(): File? {
val customView = getCustomView()
val list: DialogRecyclerView = customView.findViewById(R.id.list)
return (list.adapter as? FileChooserAdapter)?.selectedFile
}

/**
* Shows a dialog that lets the user select a local file.
*
* @param initialDirectory The directory that is listed initially, defaults to external storage.
* @param filter A filter to apply when listing files, defaults to only show non-hidden files.
* @param waitForPositiveButton When true, the callback isn't invoked until the user selects a
* file and taps on the positive action button. Defaults to true if the dialog has buttons.
* @param emptyTextRes A string resource displayed on the empty view shown when a directory is
* empty. Defaults to "This folder's empty!".
* @param selection A callback invoked when a file is selected.
*/
@SuppressLint("CheckResult")
fun MaterialDialog.fileChooser(
context: Context,
initialDirectory: File? = context.getExternalFilesDir(),
filter: FileFilter = null,
waitForPositiveButton: Boolean = true,
emptyTextRes: Int = R.string.files_default_empty_text,
allowFolderCreation: Boolean = false,
@StringRes folderCreationLabel: Int? = null,
selection: FileCallback = null
): MaterialDialog {
var actualFilter: FileFilter = filter

if (allowFolderCreation) {
// we already have permissions at app startup
// check(hasWriteStoragePermission()) {
// "You must have the WRITE_EXTERNAL_STORAGE permission first."
// }
if (filter == null) {
actualFilter = { !it.isHidden && it.canWrite() }
}
} else {
// we already have permissions at app startup
// check(hasWriteStoragePermission()) {
// "You must have the WRITE_EXTERNAL_STORAGE permission first."
// }
if (filter == null) {
actualFilter = { !it.isHidden && it.canRead() }
}
}

check(initialDirectory != null) {
"The initial directory is null."
}

customView(R.layout.md_file_chooser_base, noVerticalPadding = true)
setActionButtonEnabled(POSITIVE, false)

val customView = getCustomView()
val list: DialogRecyclerView = customView.findViewById(R.id.list)
val emptyText: TextView = customView.findViewById(R.id.empty_text)
emptyText.setText(emptyTextRes)
emptyText.maybeSetTextColor(windowContext, R.attr.md_color_content)

list.attach(this)
list.layoutManager = LinearLayoutManager(windowContext)
val adapter = FileChooserAdapter(
dialog = this,
initialFolder = initialDirectory,
waitForPositiveButton = waitForPositiveButton,
emptyView = emptyText,
onlyFolders = false,
filter = actualFilter,
allowFolderCreation = allowFolderCreation,
folderCreationLabel = folderCreationLabel,
callback = selection
)
list.adapter = adapter

if (waitForPositiveButton && selection != null) {
setActionButtonEnabled(POSITIVE, false)
positiveButton {
val selectedFile = adapter.selectedFile
if (selectedFile != null) {
selection.invoke(this, selectedFile)
}
}
}

return this
}

internal fun MaterialDialog.showNewFolderCreator(
parent: File,
@StringRes folderCreationLabel: Int?,
onCreation: () -> Unit
) {
val dialog = MaterialDialog(windowContext).show {
title(folderCreationLabel ?: R.string.files_new_folder)
input(hintRes = R.string.files_new_folder_hint) { _, input ->
File(parent, input.toString().trim()).mkdir()
onCreation()
}
}
dialog.getInputField()
.blockReservedCharacters()
}

private fun EditText.blockReservedCharacters() {
filters += InputFilter { source, _, _, _, _, _ ->
if (source.isEmpty()) {
return@InputFilter null
}
val last = source[source.length - 1]
val reservedChars = "?:\"*|/\\<>"
if (reservedChars.indexOf(last) > -1) {
source.subSequence(0, source.length - 1)
} else {
null
}
}
}
Loading

0 comments on commit dbae481

Please sign in to comment.