Migrate to viewbinding and kotlin gradle scripts

- Replaced kotlinx sythetic with viewbinding
- Update build scripts to kotlin
- Intoduced version catalog, similar to Commons
- Updated kotlin from 1.7.10 to 1.9.0
- Updated Android Gradle Plugin to 8.1.0
This commit is contained in:
Ensar Sarajčić 2023-08-03 16:58:36 +02:00
parent a212b51e64
commit 89e76cc293
23 changed files with 462 additions and 353 deletions

View File

@ -1,74 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 34
defaultConfig {
applicationId "com.simplemobiletools.voicerecorder"
minSdkVersion 23
targetSdkVersion 34
versionCode 38
versionName "5.12.0"
setProperty("archivesBaseName", "voice-recorder")
vectorDrawables.useSupportLibrary = true
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (keystorePropertiesFile.exists()) {
signingConfig signingConfigs.release
}
}
}
flavorDimensions "variants"
productFlavors {
core {}
fdroid {}
prepaid {}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
dependencies {
implementation 'com.github.SimpleMobileTools:Simple-Commons:fad9b2cdb0'
implementation 'org.greenrobot:eventbus:3.3.1'
implementation 'com.github.Armen101:AudioRecordView:1.0.4'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.github.naman14:TAndroidLame:1.1'
implementation 'me.grantland:autofittextview:0.2.1'
}

100
app/build.gradle.kts Normal file
View File

@ -0,0 +1,100 @@
import java.io.FileInputStream
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.konan.properties.Properties
plugins {
alias(libs.plugins.android)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.ksp)
}
val keystorePropertiesFile: File = rootProject.file("keystore.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
android {
compileSdk = project.libs.versions.app.build.compileSDKVersion.get().toInt()
defaultConfig {
applicationId = libs.versions.app.version.appId.get()
minSdk = project.libs.versions.app.build.minimumSDK.get().toInt()
targetSdk = project.libs.versions.app.build.targetSDK.get().toInt()
versionName = project.libs.versions.app.version.versionName.get()
versionCode = project.libs.versions.app.version.versionCode.get().toInt()
setProperty("archivesBaseName", "voice-recorder")
vectorDrawables.useSupportLibrary = true
}
signingConfigs {
if (keystorePropertiesFile.exists()) {
register("release") {
keyAlias = keystoreProperties.getProperty("keyAlias")
keyPassword = keystoreProperties.getProperty("keyPassword")
storeFile = file(keystoreProperties.getProperty("storeFile"))
storePassword = keystoreProperties.getProperty("storePassword")
}
}
}
buildFeatures {
viewBinding = true
buildConfig = true
}
buildTypes {
debug {
applicationIdSuffix = ".debug"
}
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
if (keystorePropertiesFile.exists()) {
signingConfig = signingConfigs.getByName("release")
}
}
}
flavorDimensions.add("variants")
productFlavors {
register("core")
register("fdroid")
register("prepaid")
}
sourceSets {
getByName("main").java.srcDirs("src/main/kotlin")
}
compileOptions {
val currentJavaVersionFromLibs = JavaVersion.valueOf(libs.versions.app.build.javaVersion.get().toString())
sourceCompatibility = currentJavaVersionFromLibs
targetCompatibility = currentJavaVersionFromLibs
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = project.libs.versions.app.build.kotlinJVMTarget.get()
}
namespace = libs.versions.app.version.appId.get()
lint {
checkReleaseBuilds = false
abortOnError = false
}
}
dependencies {
implementation(libs.simple.tools.commons)
implementation(libs.eventbus)
implementation(libs.audiorecordview)
implementation(libs.androidx.documentfile)
implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.constraintlayout)
implementation(libs.tandroidlame)
implementation(libs.autofittextview)
}

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.simplemobiletools.voicerecorder"
android:installLocation="auto">
<uses-permission android:name="android.permission.WAKE_LOCK" />

View File

@ -3,8 +3,8 @@ package com.simplemobiletools.voicerecorder.activities
import android.content.Intent
import com.simplemobiletools.commons.dialogs.PermissionRequiredDialog
import com.simplemobiletools.commons.extensions.openNotificationSettings
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.services.RecorderService
import com.simplemobiletools.commons.R as CommonsR
class BackgroundRecordActivity : SimpleActivity() {
companion object {
@ -27,7 +27,7 @@ class BackgroundRecordActivity : SimpleActivity() {
}
}
} else {
PermissionRequiredDialog(this, R.string.allow_notifications_voice_recorder, { openNotificationSettings() })
PermissionRequiredDialog(this, CommonsR.string.allow_notifications_voice_recorder, { openNotificationSettings() })
}
}
}

View File

@ -12,30 +12,33 @@ import com.simplemobiletools.commons.models.FAQItem
import com.simplemobiletools.voicerecorder.BuildConfig
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.adapters.ViewPagerAdapter
import com.simplemobiletools.voicerecorder.databinding.ActivityMainBinding
import com.simplemobiletools.voicerecorder.extensions.checkRecycleBinItems
import com.simplemobiletools.voicerecorder.extensions.config
import com.simplemobiletools.voicerecorder.helpers.STOP_AMPLITUDE_UPDATE
import com.simplemobiletools.voicerecorder.models.Events
import com.simplemobiletools.voicerecorder.services.RecorderService
import kotlinx.android.synthetic.main.activity_main.*
import me.grantland.widget.AutofitHelper
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import com.simplemobiletools.commons.R as CommonsR
class MainActivity : SimpleActivity() {
private var bus: EventBus? = null
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
appLaunched(BuildConfig.APPLICATION_ID)
setupOptionsMenu()
refreshMenuItems()
updateMaterialActivityViews(main_coordinator, main_holder, useTransparentNavigation = false, useTopSearchMenu = true)
updateMaterialActivityViews(binding.mainCoordinator, binding.mainHolder, useTransparentNavigation = false, useTopSearchMenu = true)
if (checkAppSideloading()) {
return
@ -49,7 +52,7 @@ class MainActivity : SimpleActivity() {
if (it) {
tryInitVoiceRecorder()
} else {
toast(R.string.no_audio_permissions)
toast(CommonsR.string.no_audio_permissions)
finish()
}
}
@ -78,7 +81,7 @@ class MainActivity : SimpleActivity() {
override fun onPause() {
super.onPause()
config.lastUsedViewPagerPage = view_pager.currentItem
config.lastUsedViewPagerPage = binding.viewPager.currentItem
}
override fun onDestroy() {
@ -96,8 +99,8 @@ class MainActivity : SimpleActivity() {
}
override fun onBackPressed() {
if (main_menu.isSearchOpen) {
main_menu.closeSearch()
if (binding.mainMenu.isSearchOpen) {
binding.mainMenu.closeSearch()
} else if (isThirdPartyIntent()) {
setResult(Activity.RESULT_CANCELED, null)
super.onBackPressed()
@ -107,27 +110,27 @@ class MainActivity : SimpleActivity() {
}
private fun refreshMenuItems() {
main_menu.getToolbar().menu.apply {
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
binding.mainMenu.getToolbar().menu.apply {
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(CommonsR.bool.hide_google_relations)
}
}
private fun setupOptionsMenu() {
main_menu.getToolbar().inflateMenu(R.menu.menu)
main_menu.toggleHideOnScroll(false)
main_menu.setupMenu()
binding.mainMenu.getToolbar().inflateMenu(R.menu.menu)
binding.mainMenu.toggleHideOnScroll(false)
binding.mainMenu.setupMenu()
main_menu.onSearchOpenListener = {
if (view_pager.currentItem == 0) {
view_pager.currentItem = 1
binding.mainMenu.onSearchOpenListener = {
if (binding.viewPager.currentItem == 0) {
binding.viewPager.currentItem = 1
}
}
main_menu.onSearchTextChangedListener = { text ->
binding.mainMenu.onSearchTextChangedListener = { text ->
getPagerAdapter()?.searchTextChanged(text)
}
main_menu.getToolbar().setOnMenuItemClickListener { menuItem ->
binding.mainMenu.getToolbar().setOnMenuItemClickListener { menuItem ->
when (menuItem.itemId) {
R.id.more_apps_from_us -> launchMoreAppsFromUsIntent()
R.id.settings -> launchSettings()
@ -140,7 +143,7 @@ class MainActivity : SimpleActivity() {
private fun updateMenuColors() {
updateStatusbarColor(getProperBackgroundColor())
main_menu.updateColors()
binding.mainMenu.updateColors()
}
private fun tryInitVoiceRecorder() {
@ -158,66 +161,66 @@ class MainActivity : SimpleActivity() {
}
private fun setupViewPager() {
main_tabs_holder.removeAllTabs()
var tabDrawables = arrayOf(R.drawable.ic_microphone_vector, R.drawable.ic_headset_vector)
binding.mainTabsHolder.removeAllTabs()
var tabDrawables = arrayOf(CommonsR.drawable.ic_microphone_vector, R.drawable.ic_headset_vector)
var tabLabels = arrayOf(R.string.recorder, R.string.player)
if (config.useRecycleBin) {
tabDrawables += R.drawable.ic_delete_vector
tabLabels += R.string.recycle_bin
tabDrawables += CommonsR.drawable.ic_delete_vector
tabLabels += CommonsR.string.recycle_bin
}
tabDrawables.forEachIndexed { i, drawableId ->
main_tabs_holder.newTab().setCustomView(R.layout.bottom_tablayout_item).apply {
customView?.findViewById<ImageView>(R.id.tab_item_icon)?.setImageDrawable(getDrawable(drawableId))
customView?.findViewById<TextView>(R.id.tab_item_label)?.setText(tabLabels[i])
AutofitHelper.create(customView?.findViewById(R.id.tab_item_label))
main_tabs_holder.addTab(this)
binding.mainTabsHolder.newTab().setCustomView(CommonsR.layout.bottom_tablayout_item).apply {
customView?.findViewById<ImageView>(CommonsR.id.tab_item_icon)?.setImageDrawable(getDrawable(drawableId))
customView?.findViewById<TextView>(CommonsR.id.tab_item_label)?.setText(tabLabels[i])
AutofitHelper.create(customView?.findViewById(CommonsR.id.tab_item_label))
binding.mainTabsHolder.addTab(this)
}
}
main_tabs_holder.onTabSelectionChanged(
binding.mainTabsHolder.onTabSelectionChanged(
tabUnselectedAction = {
updateBottomTabItemColors(it.customView, false)
if (it.position == 1 || it.position == 2) {
main_menu.closeSearch()
binding.mainMenu.closeSearch()
}
},
tabSelectedAction = {
view_pager.currentItem = it.position
binding.viewPager.currentItem = it.position
updateBottomTabItemColors(it.customView, true)
}
)
view_pager.adapter = ViewPagerAdapter(this, config.useRecycleBin)
view_pager.offscreenPageLimit = 2
view_pager.onPageChangeListener {
main_tabs_holder.getTabAt(it)?.select()
(view_pager.adapter as ViewPagerAdapter).finishActMode()
binding.viewPager.adapter = ViewPagerAdapter(this, config.useRecycleBin)
binding.viewPager.offscreenPageLimit = 2
binding.viewPager.onPageChangeListener {
binding.mainTabsHolder.getTabAt(it)?.select()
(binding.viewPager.adapter as ViewPagerAdapter).finishActMode()
}
if (isThirdPartyIntent()) {
view_pager.currentItem = 0
binding.viewPager.currentItem = 0
} else {
view_pager.currentItem = config.lastUsedViewPagerPage
main_tabs_holder.getTabAt(config.lastUsedViewPagerPage)?.select()
binding.viewPager.currentItem = config.lastUsedViewPagerPage
binding.mainTabsHolder.getTabAt(config.lastUsedViewPagerPage)?.select()
}
}
private fun setupTabColors() {
val activeView = main_tabs_holder.getTabAt(view_pager.currentItem)?.customView
val inactiveView = main_tabs_holder.getTabAt(getInactiveTabIndex())?.customView
val activeView = binding.mainTabsHolder.getTabAt(binding.viewPager.currentItem)?.customView
val inactiveView = binding.mainTabsHolder.getTabAt(getInactiveTabIndex())?.customView
updateBottomTabItemColors(activeView, true)
updateBottomTabItemColors(inactiveView, false)
main_tabs_holder.getTabAt(view_pager.currentItem)?.select()
binding.mainTabsHolder.getTabAt(binding.viewPager.currentItem)?.select()
val bottomBarColor = getBottomNavigationBackgroundColor()
main_tabs_holder.setBackgroundColor(bottomBarColor)
binding.mainTabsHolder.setBackgroundColor(bottomBarColor)
updateNavigationBarColor(bottomBarColor)
}
private fun getInactiveTabIndex() = if (view_pager.currentItem == 0) 1 else 0
private fun getInactiveTabIndex() = if (binding.viewPager.currentItem == 0) 1 else 0
private fun getPagerAdapter() = (view_pager.adapter as? ViewPagerAdapter)
private fun getPagerAdapter() = (binding.viewPager.adapter as? ViewPagerAdapter)
private fun launchSettings() {
hideKeyboard()
@ -229,12 +232,12 @@ class MainActivity : SimpleActivity() {
val faqItems = arrayListOf(
FAQItem(R.string.faq_1_title, R.string.faq_1_text),
FAQItem(R.string.faq_9_title_commons, R.string.faq_9_text_commons)
FAQItem(CommonsR.string.faq_9_title_commons, CommonsR.string.faq_9_text_commons)
)
if (!resources.getBoolean(R.bool.hide_google_relations)) {
faqItems.add(FAQItem(R.string.faq_2_title_commons, R.string.faq_2_text_commons))
faqItems.add(FAQItem(R.string.faq_6_title_commons, R.string.faq_6_text_commons))
if (!resources.getBoolean(CommonsR.bool.hide_google_relations)) {
faqItems.add(FAQItem(CommonsR.string.faq_2_title_commons, CommonsR.string.faq_2_text_commons))
faqItems.add(FAQItem(CommonsR.string.faq_6_title_commons, CommonsR.string.faq_6_text_commons))
}
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)

View File

@ -8,6 +8,7 @@ import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.databinding.ActivitySettingsBinding
import com.simplemobiletools.voicerecorder.extensions.config
import com.simplemobiletools.voicerecorder.extensions.emptyTheRecycleBin
import com.simplemobiletools.voicerecorder.extensions.getAllRecordings
@ -16,26 +17,28 @@ import com.simplemobiletools.voicerecorder.helpers.EXTENSION_M4A
import com.simplemobiletools.voicerecorder.helpers.EXTENSION_MP3
import com.simplemobiletools.voicerecorder.helpers.EXTENSION_OGG
import com.simplemobiletools.voicerecorder.models.Events
import kotlinx.android.synthetic.main.activity_settings.*
import org.greenrobot.eventbus.EventBus
import java.util.Locale
import kotlin.system.exitProcess
import com.simplemobiletools.commons.R as CommonsR
class SettingsActivity : SimpleActivity() {
private var recycleBinContentSize = 0
private lateinit var binding: ActivitySettingsBinding
override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
updateMaterialActivityViews(settings_coordinator, settings_holder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar)
updateMaterialActivityViews(binding.settingsCoordinator, binding.settingsHolder, useTransparentNavigation = true, useTopSearchMenu = false)
setupMaterialScrollListener(binding.settingsNestedScrollview, binding.settingsToolbar)
}
override fun onResume() {
super.onResume()
setupToolbar(settings_toolbar, NavigationIcon.Arrow)
setupToolbar(binding.settingsToolbar, NavigationIcon.Arrow)
setupPurchaseThankYou()
setupCustomizeColors()
@ -51,29 +54,29 @@ class SettingsActivity : SimpleActivity() {
setupRecordAfterLaunch()
setupUseRecycleBin()
setupEmptyRecycleBin()
updateTextColors(settings_nested_scrollview)
updateTextColors(binding.settingsNestedScrollview)
arrayOf(settings_color_customization_section_label, settings_general_settings_label, settings_recycle_bin_label).forEach {
arrayOf(binding.settingsColorCustomizationLabel, binding.settingsGeneralSettingsLabel, binding.settingsRecycleBinLabel).forEach {
it.setTextColor(getProperPrimaryColor())
}
}
private fun setupPurchaseThankYou() {
settings_purchase_thank_you_holder.beGoneIf(isOrWasThankYouInstalled())
settings_purchase_thank_you_holder.setOnClickListener {
binding.settingsPurchaseThankYouHolder.beGoneIf(isOrWasThankYouInstalled())
binding.settingsPurchaseThankYouHolder.setOnClickListener {
launchPurchaseThankYouIntent()
}
}
private fun setupCustomizeColors() {
settings_color_customization_label.text = getCustomizeColorsString()
settings_color_customization_holder.setOnClickListener {
binding.settingsColorCustomizationLabel.text = getCustomizeColorsString()
binding.settingsColorCustomizationHolder.setOnClickListener {
handleCustomizeColorsClick()
}
}
private fun setupCustomizeWidgetColors() {
settings_widget_color_customization_holder.setOnClickListener {
binding.settingsWidgetColorCustomizationHolder.setOnClickListener {
Intent(this, WidgetRecordDisplayConfigureActivity::class.java).apply {
putExtra(IS_CUSTOMIZING_COLORS, true)
startActivity(this)
@ -82,41 +85,41 @@ class SettingsActivity : SimpleActivity() {
}
private fun setupUseEnglish() {
settings_use_english_holder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
settings_use_english.isChecked = config.useEnglish
settings_use_english_holder.setOnClickListener {
settings_use_english.toggle()
config.useEnglish = settings_use_english.isChecked
binding.settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus())
binding.settingsUseEnglish.isChecked = config.useEnglish
binding.settingsUseEnglishHolder.setOnClickListener {
binding.settingsUseEnglish.toggle()
config.useEnglish = binding.settingsUseEnglish.isChecked
exitProcess(0)
}
}
private fun setupLanguage() {
settings_language.text = Locale.getDefault().displayLanguage
settings_language_holder.beVisibleIf(isTiramisuPlus())
settings_language_holder.setOnClickListener {
binding.settingsLanguage.text = Locale.getDefault().displayLanguage
binding.settingsLanguageHolder.beVisibleIf(isTiramisuPlus())
binding.settingsLanguageHolder.setOnClickListener {
launchChangeAppLanguageIntent()
}
}
private fun setupChangeDateTimeFormat() {
settings_change_date_time_format_holder.setOnClickListener {
binding.settingsChangeDateTimeFormatHolder.setOnClickListener {
ChangeDateTimeFormatDialog(this) {}
}
}
private fun setupHideNotification() {
settings_hide_notification.isChecked = config.hideNotification
settings_hide_notification_holder.setOnClickListener {
settings_hide_notification.toggle()
config.hideNotification = settings_hide_notification.isChecked
binding.settingsHideNotification.isChecked = config.hideNotification
binding.settingsHideNotificationHolder.setOnClickListener {
binding.settingsHideNotification.toggle()
config.hideNotification = binding.settingsHideNotification.isChecked
}
}
private fun setupSaveRecordingsFolder() {
settings_save_recordings_label.text = addLockedLabelIfNeeded(R.string.save_recordings_in)
settings_save_recordings.text = humanizePath(config.saveRecordingsFolder)
settings_save_recordings_holder.setOnClickListener {
binding.settingsSaveRecordingsLabel.text = addLockedLabelIfNeeded(R.string.save_recordings_in)
binding.settingsSaveRecordings.text = humanizePath(config.saveRecordingsFolder)
binding.settingsAudioSourceHolder.setOnClickListener {
if (isOrWasThankYouInstalled()) {
FilePickerDialog(this, config.saveRecordingsFolder, false, showFAB = true) {
val path = it
@ -131,7 +134,7 @@ class SettingsActivity : SimpleActivity() {
}
config.saveRecordingsFolder = path
settings_save_recordings.text = humanizePath(config.saveRecordingsFolder)
binding.settingsSaveRecordings.text = humanizePath(config.saveRecordingsFolder)
}
}
}
@ -142,8 +145,8 @@ class SettingsActivity : SimpleActivity() {
}
private fun setupExtension() {
settings_extension.text = config.getExtensionText()
settings_extension_holder.setOnClickListener {
binding.settingsExtension.text = config.getExtensionText()
binding.settingsExtensionHolder.setOnClickListener {
val items = arrayListOf(
RadioItem(EXTENSION_M4A, getString(R.string.m4a)),
RadioItem(EXTENSION_MP3, getString(R.string.mp3))
@ -155,19 +158,19 @@ class SettingsActivity : SimpleActivity() {
RadioGroupDialog(this@SettingsActivity, items, config.extension) {
config.extension = it as Int
settings_extension.text = config.getExtensionText()
binding.settingsExtension.text = config.getExtensionText()
}
}
}
private fun setupBitrate() {
settings_bitrate.text = getBitrateText(config.bitrate)
settings_bitrate_holder.setOnClickListener {
binding.settingsBitrate.text = getBitrateText(config.bitrate)
binding.settingsBitrateHolder.setOnClickListener {
val items = BITRATES.map { RadioItem(it, getBitrateText(it)) } as ArrayList
RadioGroupDialog(this@SettingsActivity, items, config.bitrate) {
config.bitrate = it as Int
settings_bitrate.text = getBitrateText(config.bitrate)
binding.settingsBitrate.text = getBitrateText(config.bitrate)
}
}
}
@ -175,25 +178,25 @@ class SettingsActivity : SimpleActivity() {
private fun getBitrateText(value: Int): String = getString(R.string.bitrate_value).format(value / 1000)
private fun setupRecordAfterLaunch() {
settings_record_after_launch.isChecked = config.recordAfterLaunch
settings_record_after_launch_holder.setOnClickListener {
settings_record_after_launch.toggle()
config.recordAfterLaunch = settings_record_after_launch.isChecked
binding.settingsRecordAfterLaunch.isChecked = config.recordAfterLaunch
binding.settingsRecordAfterLaunchHolder.setOnClickListener {
binding.settingsRecordAfterLaunch.toggle()
config.recordAfterLaunch = binding.settingsRecordAfterLaunch.isChecked
}
}
private fun setupUseRecycleBin() {
updateRecycleBinButtons()
settings_use_recycle_bin.isChecked = config.useRecycleBin
settings_use_recycle_bin_holder.setOnClickListener {
settings_use_recycle_bin.toggle()
config.useRecycleBin = settings_use_recycle_bin.isChecked
binding.settingsUseRecycleBin.isChecked = config.useRecycleBin
binding.settingsUseRecycleBinHolder.setOnClickListener {
binding.settingsUseRecycleBin.toggle()
config.useRecycleBin = binding.settingsUseRecycleBin.isChecked
updateRecycleBinButtons()
}
}
private fun updateRecycleBinButtons() {
settings_empty_recycle_bin_holder.beVisibleIf(config.useRecycleBin)
binding.settingsEmptyRecycleBinHolder.beVisibleIf(config.useRecycleBin)
}
private fun setupEmptyRecycleBin() {
@ -206,18 +209,18 @@ class SettingsActivity : SimpleActivity() {
}
runOnUiThread {
settings_empty_recycle_bin_size.text = recycleBinContentSize.formatSize()
binding.settingsEmptyRecycleBinSize.text = recycleBinContentSize.formatSize()
}
}
settings_empty_recycle_bin_holder.setOnClickListener {
binding.settingsEmptyRecycleBinHolder.setOnClickListener {
if (recycleBinContentSize == 0) {
toast(R.string.recycle_bin_empty)
toast(CommonsR.string.recycle_bin_empty)
} else {
ConfirmationDialog(this, "", R.string.empty_recycle_bin_confirmation, R.string.yes, R.string.no) {
ConfirmationDialog(this, "", CommonsR.string.empty_recycle_bin_confirmation, CommonsR.string.yes, CommonsR.string.no) {
emptyTheRecycleBin()
recycleBinContentSize = 0
settings_empty_recycle_bin_size.text = 0.formatSize()
binding.settingsEmptyRecycleBinSize.text = 0.formatSize()
EventBus.getDefault().post(Events.RecordingTrashUpdated())
}
}
@ -225,13 +228,13 @@ class SettingsActivity : SimpleActivity() {
}
private fun setupAudioSource() {
settings_audio_source.text = config.getAudioSourceText(config.audioSource)
settings_audio_source_holder.setOnClickListener {
binding.settingsAudioSource.text = config.getAudioSourceText(config.audioSource)
binding.settingsAudioSourceHolder.setOnClickListener {
val items = getAudioSources().map { RadioItem(it, config.getAudioSourceText(it)) } as ArrayList
RadioGroupDialog(this@SettingsActivity, items, config.audioSource) {
config.audioSource = it as Int
settings_audio_source.text = config.getAudioSourceText(config.audioSource)
binding.settingsAudioSource.text = config.getAudioSourceText(config.audioSource)
}
}
}

View File

@ -12,9 +12,10 @@ import com.simplemobiletools.commons.dialogs.FeatureLockedDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.databinding.WidgetRecordDisplayConfigBinding
import com.simplemobiletools.voicerecorder.extensions.config
import com.simplemobiletools.voicerecorder.helpers.MyWidgetRecordDisplayProvider
import kotlinx.android.synthetic.main.widget_record_display_config.*
import com.simplemobiletools.commons.R as CommonsR
class WidgetRecordDisplayConfigureActivity : SimpleActivity() {
private var mWidgetAlpha = 0f
@ -22,12 +23,14 @@ class WidgetRecordDisplayConfigureActivity : SimpleActivity() {
private var mWidgetColor = 0
private var mWidgetColorWithoutTransparency = 0
private var mFeatureLockedDialog: FeatureLockedDialog? = null
private lateinit var binding: WidgetRecordDisplayConfigBinding
public override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false
super.onCreate(savedInstanceState)
setResult(Activity.RESULT_CANCELED)
setContentView(R.layout.widget_record_display_config)
binding = WidgetRecordDisplayConfigBinding.inflate(layoutInflater)
setContentView(binding.root)
initVariables()
val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false
@ -37,11 +40,11 @@ class WidgetRecordDisplayConfigureActivity : SimpleActivity() {
finish()
}
config_save.setOnClickListener { saveConfig() }
config_widget_color.setOnClickListener { pickBackgroundColor() }
binding.configSave.setOnClickListener { saveConfig() }
binding.configWidgetColor.setOnClickListener { pickBackgroundColor() }
val primaryColor = getProperPrimaryColor()
config_widget_seekbar.setColors(getProperTextColor(), primaryColor, primaryColor)
binding.configWidgetSeekbar.setColors(getProperTextColor(), primaryColor, primaryColor)
if (!isCustomizingColors && !isOrWasThankYouInstalled()) {
mFeatureLockedDialog = FeatureLockedDialog(this) {
@ -51,8 +54,8 @@ class WidgetRecordDisplayConfigureActivity : SimpleActivity() {
}
}
config_save.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
config_save.setTextColor(getProperPrimaryColor().getContrastColor())
binding.configSave.backgroundTintList = ColorStateList.valueOf(getProperPrimaryColor())
binding.configSave.setTextColor(getProperPrimaryColor().getContrastColor())
}
override fun onResume() {
@ -67,14 +70,14 @@ class WidgetRecordDisplayConfigureActivity : SimpleActivity() {
private fun initVariables() {
mWidgetColor = config.widgetBgColor
if (mWidgetColor == resources.getColor(R.color.default_widget_bg_color) && config.isUsingSystemTheme) {
mWidgetColor = resources.getColor(R.color.you_primary_color, theme)
mWidgetColor = resources.getColor(CommonsR.color.you_primary_color, theme)
}
mWidgetAlpha = Color.alpha(mWidgetColor) / 255.toFloat()
mWidgetColorWithoutTransparency = Color.rgb(Color.red(mWidgetColor), Color.green(mWidgetColor), Color.blue(mWidgetColor))
config_widget_seekbar.setOnSeekBarChangeListener(seekbarChangeListener)
config_widget_seekbar.progress = (mWidgetAlpha * 100).toInt()
binding.configWidgetSeekbar.setOnSeekBarChangeListener(seekbarChangeListener)
binding.configWidgetSeekbar.progress = (mWidgetAlpha * 100).toInt()
updateColors()
}
@ -107,8 +110,8 @@ class WidgetRecordDisplayConfigureActivity : SimpleActivity() {
private fun updateColors() {
mWidgetColor = mWidgetColorWithoutTransparency.adjustAlpha(mWidgetAlpha)
config_widget_color.setFillWithStroke(mWidgetColor, mWidgetColor)
config_image.background.mutate().applyColorFilter(mWidgetColor)
binding.configWidgetColor.setFillWithStroke(mWidgetColor, mWidgetColor)
binding.configImage.background.mutate().applyColorFilter(mWidgetColor)
}
private val seekbarChangeListener = object : SeekBar.OnSeekBarChangeListener {

View File

@ -12,6 +12,7 @@ import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.voicerecorder.BuildConfig
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.activities.SimpleActivity
import com.simplemobiletools.voicerecorder.databinding.ItemRecordingBinding
import com.simplemobiletools.voicerecorder.dialogs.DeleteConfirmationDialog
import com.simplemobiletools.voicerecorder.dialogs.RenameRecordingDialog
import com.simplemobiletools.voicerecorder.extensions.config
@ -21,8 +22,8 @@ import com.simplemobiletools.voicerecorder.helpers.getAudioFileContentUri
import com.simplemobiletools.voicerecorder.interfaces.RefreshRecordingsListener
import com.simplemobiletools.voicerecorder.models.Events
import com.simplemobiletools.voicerecorder.models.Recording
import kotlinx.android.synthetic.main.item_recording.view.*
import org.greenrobot.eventbus.EventBus
import com.simplemobiletools.commons.R as CommonsR
class RecordingsAdapter(
activity: SimpleActivity,
@ -74,7 +75,9 @@ class RecordingsAdapter(
override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_recording, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return createViewHolder(ItemRecordingBinding.inflate(layoutInflater, parent, false).root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val recording = recordings[position]
@ -136,7 +139,7 @@ class RecordingsAdapter(
}
val baseString = if (activity.config.useRecycleBin) {
R.string.move_to_recycle_bin_confirmation
CommonsR.string.move_to_recycle_bin_confirmation
} else {
R.string.delete_recordings_confirmation
}
@ -215,30 +218,30 @@ class RecordingsAdapter(
private fun getSelectedItems() = recordings.filter { selectedKeys.contains(it.id) } as ArrayList<Recording>
private fun setupView(view: View, recording: Recording) {
view.apply {
setupViewBackground(activity)
recording_frame?.isSelected = selectedKeys.contains(recording.id)
ItemRecordingBinding.bind(view).apply {
root.setupViewBackground(activity)
recordingFrame.isSelected = selectedKeys.contains(recording.id)
arrayListOf<TextView>(recording_title, recording_date, recording_duration, recording_size).forEach {
arrayListOf<TextView>(recordingTitle, recordingDate, recordingDuration, recordingSize).forEach {
it.setTextColor(textColor)
}
if (recording.id == currRecordingId) {
recording_title.setTextColor(context.getProperPrimaryColor())
recordingTitle.setTextColor(root.context.getProperPrimaryColor())
}
recording_title.text = recording.title
recording_date.text = recording.timestamp.formatDate(context)
recording_duration.text = recording.duration.getFormattedDuration()
recording_size.text = recording.size.formatSize()
recordingTitle.text = recording.title
recordingDate.text = recording.timestamp.formatDate(root.context)
recordingDuration.text = recording.duration.getFormattedDuration()
recordingSize.text = recording.size.formatSize()
overflow_menu_icon.drawable.apply {
overflowMenuIcon.drawable.apply {
mutate()
setTint(activity.getProperTextColor())
}
overflow_menu_icon.setOnClickListener {
showPopupMenu(overflow_menu_anchor, recording)
overflowMenuIcon.setOnClickListener {
showPopupMenu(overflowMenuAnchor, recording)
}
}
}

View File

@ -11,13 +11,14 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.activities.SimpleActivity
import com.simplemobiletools.voicerecorder.databinding.ItemRecordingBinding
import com.simplemobiletools.voicerecorder.extensions.deleteRecordings
import com.simplemobiletools.voicerecorder.extensions.restoreRecordings
import com.simplemobiletools.voicerecorder.interfaces.RefreshRecordingsListener
import com.simplemobiletools.voicerecorder.models.Events
import com.simplemobiletools.voicerecorder.models.Recording
import kotlinx.android.synthetic.main.item_recording.view.*
import org.greenrobot.eventbus.EventBus
import com.simplemobiletools.commons.R as CommonsR
class TrashAdapter(
activity: SimpleActivity,
@ -59,7 +60,9 @@ class TrashAdapter(
override fun onActionModeDestroyed() {}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_recording, parent)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return createViewHolder(ItemRecordingBinding.inflate(layoutInflater, parent, false).root)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val recording = recordings[position]
@ -147,26 +150,26 @@ class TrashAdapter(
private fun getSelectedItems() = recordings.filter { selectedKeys.contains(it.id) } as ArrayList<Recording>
private fun setupView(view: View, recording: Recording) {
view.apply {
setupViewBackground(activity)
recording_frame?.isSelected = selectedKeys.contains(recording.id)
ItemRecordingBinding.bind(view).apply {
root.setupViewBackground(activity)
recordingFrame.isSelected = selectedKeys.contains(recording.id)
arrayListOf<TextView>(recording_title, recording_date, recording_duration, recording_size).forEach {
arrayListOf<TextView>(recordingTitle, recordingDate, recordingDuration, recordingSize).forEach {
it.setTextColor(textColor)
}
recording_title.text = recording.title
recording_date.text = recording.timestamp.formatDate(context)
recording_duration.text = recording.duration.getFormattedDuration()
recording_size.text = recording.size.formatSize()
recordingTitle.text = recording.title
recordingDate.text = recording.timestamp.formatDate(root.context)
recordingDuration.text = recording.duration.getFormattedDuration()
recordingSize.text = recording.size.formatSize()
overflow_menu_icon.drawable.apply {
overflowMenuIcon.drawable.apply {
mutate()
setTint(activity.getProperTextColor())
}
overflow_menu_icon.setOnClickListener {
showPopupMenu(overflow_menu_anchor, recording)
overflowMenuIcon.setOnClickListener {
showPopupMenu(overflowMenuAnchor, recording)
}
}
}
@ -186,7 +189,7 @@ class TrashAdapter(
PopupMenu(contextTheme, view, Gravity.END).apply {
inflate(getActionMenuId())
menu.findItem(R.id.cab_select_all).isVisible = false
menu.findItem(R.id.cab_restore).title = resources.getString(R.string.restore_this_file)
menu.findItem(R.id.cab_restore).title = resources.getString(CommonsR.string.restore_this_file)
setOnMenuItemClickListener { item ->
val recordingId = recording.id
when (item.itemId) {

View File

@ -53,7 +53,7 @@ class ViewPagerAdapter(private val activity: SimpleActivity, val showRecycleBin:
}
fun finishActMode() {
(mFragments[1] as? PlayerFragment)?.finishActMode()
(mFragments[1] as? PlayerFragment)?.finishActMode()
if (showRecycleBin) {
(mFragments[2] as? TrashFragment)?.finishActMode()
}

View File

@ -5,9 +5,8 @@ import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.voicerecorder.R
import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.delete_remember_title
import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.skip_the_recycle_bin_checkbox
import com.simplemobiletools.voicerecorder.databinding.DialogDeleteConfirmationBinding
import com.simplemobiletools.commons.R as CommonsR
class DeleteConfirmationDialog(
private val activity: Activity,
@ -17,14 +16,15 @@ class DeleteConfirmationDialog(
) {
private var dialog: AlertDialog? = null
val view = activity.layoutInflater.inflate(R.layout.dialog_delete_confirmation, null)!!
val binding = DialogDeleteConfirmationBinding.inflate(activity.layoutInflater)
val view = binding.root
init {
view.delete_remember_title.text = message
view.skip_the_recycle_bin_checkbox.beGoneIf(!showSkipRecycleBinOption)
binding.deleteRememberTitle.text = message
binding.skipTheRecycleBinCheckbox.beGoneIf(!showSkipRecycleBinOption)
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.yes) { _, _ -> dialogConfirmed() }
.setNegativeButton(R.string.no, null)
.setPositiveButton(CommonsR.string.yes) { _, _ -> dialogConfirmed() }
.setNegativeButton(CommonsR.string.no, null)
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
dialog = alertDialog
@ -34,6 +34,6 @@ class DeleteConfirmationDialog(
private fun dialogConfirmed() {
dialog?.dismiss()
callback(view.skip_the_recycle_bin_checkbox.isChecked)
callback(binding.skipTheRecycleBinCheckbox.isChecked)
}
}

View File

@ -7,36 +7,37 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isRPlus
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.databinding.DialogRenameRecordingBinding
import com.simplemobiletools.voicerecorder.extensions.config
import com.simplemobiletools.voicerecorder.helpers.getAudioFileContentUri
import com.simplemobiletools.voicerecorder.models.Events
import com.simplemobiletools.voicerecorder.models.Recording
import kotlinx.android.synthetic.main.dialog_rename_recording.view.*
import org.greenrobot.eventbus.EventBus
import java.io.File
import com.simplemobiletools.commons.R as CommonsR
class RenameRecordingDialog(val activity: BaseSimpleActivity, val recording: Recording, val callback: () -> Unit) {
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_rename_recording, null).apply {
rename_recording_title.setText(recording.title.substringBeforeLast('.'))
val binding = DialogRenameRecordingBinding.inflate(activity.layoutInflater).apply {
renameRecordingTitle.setText(recording.title.substringBeforeLast('.'))
}
val view = binding.root
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(CommonsR.string.ok, null)
.setNegativeButton(CommonsR.string.cancel, null)
.apply {
activity.setupDialogStuff(view, this, R.string.rename) { alertDialog ->
alertDialog.showKeyboard(view.rename_recording_title)
activity.setupDialogStuff(view, this, CommonsR.string.rename) { alertDialog ->
alertDialog.showKeyboard(binding.renameRecordingTitle)
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
val newTitle = view.rename_recording_title.value
val newTitle = binding.renameRecordingTitle.value
if (newTitle.isEmpty()) {
activity.toast(R.string.empty_name)
activity.toast(CommonsR.string.empty_name)
return@setOnClickListener
}
if (!newTitle.isAValidFilename()) {
activity.toast(R.string.invalid_name)
activity.toast(CommonsR.string.invalid_name)
return@setOnClickListener
}

View File

@ -16,19 +16,20 @@ import com.simplemobiletools.commons.helpers.isQPlus
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.activities.SimpleActivity
import com.simplemobiletools.voicerecorder.adapters.RecordingsAdapter
import com.simplemobiletools.voicerecorder.databinding.FragmentPlayerBinding
import com.simplemobiletools.voicerecorder.extensions.config
import com.simplemobiletools.voicerecorder.extensions.getAllRecordings
import com.simplemobiletools.voicerecorder.helpers.getAudioFileContentUri
import com.simplemobiletools.voicerecorder.interfaces.RefreshRecordingsListener
import com.simplemobiletools.voicerecorder.models.Events
import com.simplemobiletools.voicerecorder.models.Recording
import kotlinx.android.synthetic.main.fragment_player.view.*
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.Stack
import java.util.Timer
import java.util.TimerTask
import com.simplemobiletools.commons.R as CommonsR
class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshRecordingsListener {
private val FAST_FORWARD_SKIP_MS = 10000
@ -42,6 +43,12 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
private var prevSavePath = ""
private var prevRecycleBinState = context.config.useRecycleBin
private var playOnPreparation = true
private lateinit var binding: FragmentPlayerBinding
override fun onFinishInflate() {
super.onFinishInflate()
binding = FragmentPlayerBinding.bind(this)
}
override fun onResume() {
setupColors()
@ -78,23 +85,23 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
}
private fun setupViews() {
play_pause_btn.setOnClickListener {
if (playedRecordingIDs.empty() || player_progressbar.max == 0) {
next_btn.callOnClick()
binding.playPauseBtn.setOnClickListener {
if (playedRecordingIDs.empty() || binding.playerProgressbar.max == 0) {
binding.nextBtn.callOnClick()
} else {
togglePlayPause()
}
}
player_progress_current.setOnClickListener {
binding.playerProgressCurrent.setOnClickListener {
skip(false)
}
player_progress_max.setOnClickListener {
binding.playerProgressMax.setOnClickListener {
skip(true)
}
previous_btn.setOnClickListener {
binding.previousBtn.setOnClickListener {
if (playedRecordingIDs.isEmpty()) {
return@setOnClickListener
}
@ -110,14 +117,14 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
playRecording(prevRecording, true)
}
player_title.setOnLongClickListener {
if (player_title.value.isNotEmpty()) {
context.copyToClipboard(player_title.value)
binding.playerTitle.setOnLongClickListener {
if (binding.playerTitle.value.isNotEmpty()) {
context.copyToClipboard(binding.playerTitle.value)
}
true
}
next_btn.setOnClickListener {
binding.nextBtn.setOnClickListener {
val adapter = getRecordingsAdapter()
if (adapter == null || adapter.recordings.isEmpty()) {
return@setOnClickListener
@ -137,8 +144,8 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
}
private fun setupAdapter(recordings: ArrayList<Recording>) {
recordings_fastscroller.beVisibleIf(recordings.isNotEmpty())
recordings_placeholder.beVisibleIf(recordings.isEmpty())
binding.recordingsFastscroller.beVisibleIf(recordings.isNotEmpty())
binding.recordingsPlaceholder.beVisibleIf(recordings.isEmpty())
if (recordings.isEmpty()) {
val stringId = if (lastSearchQuery.isEmpty()) {
if (isQPlus()) {
@ -147,27 +154,27 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
R.string.no_recordings_in_folder_found
}
} else {
R.string.no_items_found
CommonsR.string.no_items_found
}
recordings_placeholder.text = context.getString(stringId)
binding.recordingsPlaceholder.text = context.getString(stringId)
resetProgress(null)
player?.stop()
}
val adapter = getRecordingsAdapter()
if (adapter == null) {
RecordingsAdapter(context as SimpleActivity, recordings, this, recordings_list) {
RecordingsAdapter(context as SimpleActivity, recordings, this, binding.recordingsList) {
playRecording(it as Recording, true)
if (playedRecordingIDs.isEmpty() || playedRecordingIDs.peek() != it.id) {
playedRecordingIDs.push(it.id)
}
}.apply {
recordings_list.adapter = this
binding.recordingsList.adapter = this
}
if (context.areSystemAnimationsEnabled) {
recordings_list.scheduleLayoutAnimation()
binding.recordingsList.scheduleLayoutAnimation()
}
} else {
adapter.updateItems(recordings)
@ -187,9 +194,9 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
setOnCompletionListener {
progressTimer.cancel()
player_progressbar.progress = player_progressbar.max
player_progress_current.text = player_progress_max.text
play_pause_btn.setImageDrawable(getToggleButtonIcon(false))
binding.playerProgressbar.progress = binding.playerProgressbar.max
binding.playerProgressCurrent.text = binding.playerProgressMax.text
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
}
setOnPreparedListener {
@ -205,7 +212,7 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
override fun playRecording(recording: Recording, playOnPrepared: Boolean) {
resetProgress(recording)
(recordings_list.adapter as RecordingsAdapter).updateCurrentRecording(recording.id)
(binding.recordingsList.adapter as RecordingsAdapter).updateCurrentRecording(recording.id)
playOnPreparation = playOnPrepared
player!!.apply {
@ -239,12 +246,12 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
}
}
play_pause_btn.setImageDrawable(getToggleButtonIcon(playOnPreparation))
player_progressbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(playOnPreparation))
binding.playerProgressbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser && !playedRecordingIDs.isEmpty()) {
player?.seekTo(progress * 1000)
player_progress_current.text = progress.getFormattedDuration()
binding.playerProgressCurrent.text = progress.getFormattedDuration()
resumePlayback()
}
}
@ -267,22 +274,22 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
if (player != null) {
val progress = Math.round(player!!.currentPosition / 1000.toDouble()).toInt()
updateCurrentProgress(progress)
player_progressbar.progress = progress
binding.playerProgressbar.progress = progress
}
}
}
}
private fun updateCurrentProgress(seconds: Int) {
player_progress_current.text = seconds.getFormattedDuration()
binding.playerProgressCurrent.text = seconds.getFormattedDuration()
}
private fun resetProgress(recording: Recording?) {
updateCurrentProgress(0)
player_progressbar.progress = 0
player_progressbar.max = recording?.duration ?: 0
player_title.text = recording?.title ?: ""
player_progress_max.text = (recording?.duration ?: 0).getFormattedDuration()
binding.playerProgressbar.progress = 0
binding.playerProgressbar.max = recording?.duration ?: 0
binding.playerTitle.text = recording?.title ?: ""
binding.playerProgressMax.text = (recording?.duration ?: 0).getFormattedDuration()
}
fun onSearchTextChanged(text: String) {
@ -301,18 +308,18 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
private fun pausePlayback() {
player?.pause()
play_pause_btn.setImageDrawable(getToggleButtonIcon(false))
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
progressTimer.cancel()
}
private fun resumePlayback() {
player?.start()
play_pause_btn.setImageDrawable(getToggleButtonIcon(true))
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(true))
setupProgressTimer()
}
private fun getToggleButtonIcon(isPlaying: Boolean): Drawable {
val drawable = if (isPlaying) R.drawable.ic_pause_vector else R.drawable.ic_play_vector
val drawable = if (isPlaying) CommonsR.drawable.ic_pause_vector else CommonsR.drawable.ic_play_vector
return resources.getColoredDrawableWithColor(drawable, context.getProperPrimaryColor().getContrastColor())
}
@ -333,7 +340,7 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
private fun getIsPlaying() = player?.isPlaying == true
private fun getRecordingsAdapter() = recordings_list.adapter as? RecordingsAdapter
private fun getRecordingsAdapter() = binding.recordingsList.adapter as? RecordingsAdapter
private fun storePrevState() {
prevSavePath = context!!.config.saveRecordingsFolder
@ -342,16 +349,16 @@ class PlayerFragment(context: Context, attributeSet: AttributeSet) : MyViewPager
private fun setupColors() {
val properPrimaryColor = context.getProperPrimaryColor()
recordings_fastscroller.updateColors(properPrimaryColor)
context.updateTextColors(player_holder)
binding.recordingsFastscroller.updateColors(properPrimaryColor)
context.updateTextColors(binding.playerHolder)
val textColor = context.getProperTextColor()
arrayListOf(previous_btn, next_btn).forEach {
arrayListOf(binding.previousBtn, binding.nextBtn).forEach {
it.applyColorFilter(textColor)
}
play_pause_btn.background.applyColorFilter(properPrimaryColor)
play_pause_btn.setImageDrawable(getToggleButtonIcon(false))
binding.playPauseBtn.background.applyColorFilter(properPrimaryColor)
binding.playPauseBtn.setImageDrawable(getToggleButtonIcon(false))
}
fun finishActMode() = getRecordingsAdapter()?.finishActMode()

View File

@ -10,24 +10,27 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity
import com.simplemobiletools.commons.dialogs.PermissionRequiredDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.isNougatPlus
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.databinding.FragmentRecorderBinding
import com.simplemobiletools.voicerecorder.helpers.*
import com.simplemobiletools.voicerecorder.models.Events
import com.simplemobiletools.voicerecorder.services.RecorderService
import kotlinx.android.synthetic.main.fragment_recorder.view.recorder_visualizer
import kotlinx.android.synthetic.main.fragment_recorder.view.recording_duration
import kotlinx.android.synthetic.main.fragment_recorder.view.toggle_pause_button
import kotlinx.android.synthetic.main.fragment_recorder.view.toggle_recording_button
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.Timer
import java.util.TimerTask
import com.simplemobiletools.commons.R as CommonsR
class RecorderFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
private var status = RECORDING_STOPPED
private var pauseBlinkTimer = Timer()
private var bus: EventBus? = null
private lateinit var binding: FragmentRecorderBinding
override fun onFinishInflate() {
super.onFinishInflate()
binding = FragmentRecorderBinding.bind(this)
}
override fun onResume() {
setupColors()
@ -46,24 +49,24 @@ class RecorderFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
override fun onAttachedToWindow() {
super.onAttachedToWindow()
setupColors()
recorder_visualizer.recreate()
binding.recorderVisualizer.recreate()
bus = EventBus.getDefault()
bus!!.register(this)
updateRecordingDuration(0)
toggle_recording_button.setOnClickListener {
binding.toggleRecordingButton.setOnClickListener {
(context as? BaseSimpleActivity)?.handleNotificationPermission { granted ->
if (granted) {
toggleRecording()
} else {
PermissionRequiredDialog(context as BaseSimpleActivity, R.string.allow_notifications_voice_recorder, {
PermissionRequiredDialog(context as BaseSimpleActivity, CommonsR.string.allow_notifications_voice_recorder, {
(context as BaseSimpleActivity).openNotificationSettings()
})
}
}
}
toggle_pause_button.setOnClickListener {
binding.togglePauseButton.setOnClickListener {
Intent(context, RecorderService::class.java).apply {
action = TOGGLE_PAUSE
context.startService(this)
@ -81,26 +84,27 @@ class RecorderFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
private fun setupColors() {
val properPrimaryColor = context.getProperPrimaryColor()
toggle_recording_button.apply {
binding.toggleRecordingButton.apply {
setImageDrawable(getToggleButtonIcon())
background.applyColorFilter(properPrimaryColor)
}
toggle_pause_button.apply {
setImageDrawable(resources.getColoredDrawableWithColor(R.drawable.ic_pause_vector, properPrimaryColor.getContrastColor()))
binding.togglePauseButton.apply {
setImageDrawable(resources.getColoredDrawableWithColor(CommonsR.drawable.ic_pause_vector, properPrimaryColor.getContrastColor()))
background.applyColorFilter(properPrimaryColor)
}
recorder_visualizer.chunkColor = properPrimaryColor
recording_duration.setTextColor(context.getProperTextColor())
binding.recorderVisualizer.chunkColor = properPrimaryColor
binding.recordingDuration.setTextColor(context.getProperTextColor())
}
private fun updateRecordingDuration(duration: Int) {
recording_duration.text = duration.getFormattedDuration()
binding.recordingDuration.text = duration.getFormattedDuration()
}
private fun getToggleButtonIcon(): Drawable {
val drawable = if (status == RECORDING_RUNNING || status == RECORDING_PAUSED) R.drawable.ic_stop_vector else R.drawable.ic_microphone_vector
val drawable =
if (status == RECORDING_RUNNING || status == RECORDING_PAUSED) CommonsR.drawable.ic_stop_vector else CommonsR.drawable.ic_microphone_vector
return resources.getColoredDrawableWithColor(drawable, context.getProperPrimaryColor().getContrastColor())
}
@ -111,12 +115,12 @@ class RecorderFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
RECORDING_RUNNING
}
toggle_recording_button.setImageDrawable(getToggleButtonIcon())
binding.toggleRecordingButton.setImageDrawable(getToggleButtonIcon())
if (status == RECORDING_RUNNING) {
startRecording()
} else {
toggle_pause_button.beGone()
binding.togglePauseButton.beGone()
stopRecording()
}
}
@ -125,7 +129,7 @@ class RecorderFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
Intent(context, RecorderService::class.java).apply {
context.startService(this)
}
recorder_visualizer.recreate()
binding.recorderVisualizer.recreate()
}
private fun stopRecording() {
@ -139,15 +143,15 @@ class RecorderFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
if (status == RECORDING_PAUSED) {
// update just the alpha so that it will always be clickable
Handler(Looper.getMainLooper()).post {
toggle_pause_button.alpha = if (toggle_pause_button.alpha == 0f) 1f else 0f
binding.togglePauseButton.alpha = if (binding.togglePauseButton.alpha == 0f) 1f else 0f
}
}
}
}
private fun refreshView() {
toggle_recording_button.setImageDrawable(getToggleButtonIcon())
toggle_pause_button.beVisibleIf(status != RECORDING_STOPPED && isNougatPlus())
binding.toggleRecordingButton.setImageDrawable(getToggleButtonIcon())
binding.togglePauseButton.beVisibleIf(status != RECORDING_STOPPED && isNougatPlus())
pauseBlinkTimer.cancel()
if (status == RECORDING_PAUSED) {
@ -156,7 +160,7 @@ class RecorderFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
}
if (status == RECORDING_RUNNING) {
toggle_pause_button.alpha = 1f
binding.togglePauseButton.alpha = 1f
}
}
@ -175,7 +179,7 @@ class RecorderFragment(context: Context, attributeSet: AttributeSet) : MyViewPag
fun gotAmplitudeEvent(event: Events.RecordingAmplitude) {
val amplitude = event.amplitude
if (status == RECORDING_RUNNING) {
recorder_visualizer.update(amplitude)
binding.recorderVisualizer.update(amplitude)
}
}
}

View File

@ -3,27 +3,30 @@ package com.simplemobiletools.voicerecorder.fragments
import android.content.Context
import android.util.AttributeSet
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.activities.SimpleActivity
import com.simplemobiletools.voicerecorder.adapters.TrashAdapter
import com.simplemobiletools.voicerecorder.databinding.FragmentTrashBinding
import com.simplemobiletools.voicerecorder.extensions.config
import com.simplemobiletools.voicerecorder.extensions.getAllRecordings
import com.simplemobiletools.voicerecorder.interfaces.RefreshRecordingsListener
import com.simplemobiletools.voicerecorder.models.Events
import com.simplemobiletools.voicerecorder.models.Recording
import kotlinx.android.synthetic.main.fragment_trash.view.trash_fastscroller
import kotlinx.android.synthetic.main.fragment_trash.view.trash_holder
import kotlinx.android.synthetic.main.fragment_trash.view.trash_list
import kotlinx.android.synthetic.main.fragment_trash.view.trash_placeholder
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import com.simplemobiletools.commons.R as CommonsR
class TrashFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshRecordingsListener {
private var itemsIgnoringSearch = ArrayList<Recording>()
private var lastSearchQuery = ""
private var bus: EventBus? = null
private var prevSavePath = ""
private lateinit var binding: FragmentTrashBinding
override fun onFinishInflate() {
super.onFinishInflate()
binding = FragmentTrashBinding.bind(this)
}
override fun onResume() {
setupColors()
@ -60,26 +63,26 @@ class TrashFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerF
override fun playRecording(recording: Recording, playOnPrepared: Boolean) {}
private fun setupAdapter(recordings: ArrayList<Recording>) {
trash_fastscroller.beVisibleIf(recordings.isNotEmpty())
trash_placeholder.beVisibleIf(recordings.isEmpty())
binding.trashFastscroller.beVisibleIf(recordings.isNotEmpty())
binding.trashPlaceholder.beVisibleIf(recordings.isEmpty())
if (recordings.isEmpty()) {
val stringId = if (lastSearchQuery.isEmpty()) {
R.string.recycle_bin_empty
CommonsR.string.recycle_bin_empty
} else {
R.string.no_items_found
CommonsR.string.no_items_found
}
trash_placeholder.text = context.getString(stringId)
binding.trashPlaceholder.text = context.getString(stringId)
}
val adapter = getRecordingsAdapter()
if (adapter == null) {
TrashAdapter(context as SimpleActivity, recordings, this, trash_list).apply {
trash_list.adapter = this
TrashAdapter(context as SimpleActivity, recordings, this, binding.trashList).apply {
binding.trashList.adapter = this
}
if (context.areSystemAnimationsEnabled) {
trash_list.scheduleLayoutAnimation()
binding.trashList.scheduleLayoutAnimation()
}
} else {
adapter.updateItems(recordings)
@ -98,7 +101,7 @@ class TrashFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerF
setupAdapter(filtered)
}
private fun getRecordingsAdapter() = trash_list.adapter as? TrashAdapter
private fun getRecordingsAdapter() = binding.trashList.adapter as? TrashAdapter
private fun storePrevPath() {
prevSavePath = context!!.config.saveRecordingsFolder
@ -106,8 +109,8 @@ class TrashFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerF
private fun setupColors() {
val properPrimaryColor = context.getProperPrimaryColor()
trash_fastscroller.updateColors(properPrimaryColor)
context.updateTextColors(trash_holder)
binding.trashFastscroller.updateColors(properPrimaryColor)
context.updateTextColors(binding.trashHolder)
}
fun finishActMode() = getRecordingsAdapter()?.finishActMode()

View File

@ -14,6 +14,7 @@ import com.simplemobiletools.voicerecorder.R
import com.simplemobiletools.voicerecorder.activities.BackgroundRecordActivity
import com.simplemobiletools.voicerecorder.extensions.config
import com.simplemobiletools.voicerecorder.extensions.drawableToBitmap
import com.simplemobiletools.commons.R as CommonsR
class MyWidgetRecordDisplayProvider : AppWidgetProvider() {
private val OPEN_APP_INTENT_ID = 1
@ -57,7 +58,7 @@ class MyWidgetRecordDisplayProvider : AppWidgetProvider() {
}
private fun getColoredIcon(context: Context, color: Int, alpha: Int): Bitmap {
val drawable = context.resources.getColoredDrawableWithColor(R.drawable.ic_microphone_vector, color, alpha)
val drawable = context.resources.getColoredDrawableWithColor(CommonsR.drawable.ic_microphone_vector, color, alpha)
return context.drawableToBitmap(drawable)
}
}

View File

@ -30,6 +30,7 @@ import com.simplemobiletools.voicerecorder.recorder.Recorder
import org.greenrobot.eventbus.EventBus
import java.io.File
import java.util.*
import com.simplemobiletools.commons.R as CommonsR
class RecorderService : Service() {
companion object {
@ -195,7 +196,7 @@ class RecorderService : Service() {
val newUri = contentResolver.insert(audioCollection, newSongDetails)
if (newUri == null) {
toast(R.string.unknown_error_occurred)
toast(CommonsR.string.unknown_error_occurred)
return
}
@ -257,7 +258,7 @@ class RecorderService : Service() {
}
var priority = Notification.PRIORITY_DEFAULT
var icon = R.drawable.ic_microphone_vector
var icon = CommonsR.drawable.ic_microphone_vector
var title = label
var visibility = NotificationCompat.VISIBILITY_PUBLIC
var text = getString(R.string.recording)

View File

@ -1,29 +0,0 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

5
build.gradle.kts Normal file
View File

@ -0,0 +1,5 @@
plugins {
alias(libs.plugins.android).apply(false)
alias(libs.plugins.kotlinAndroid).apply(false)
alias(libs.plugins.ksp).apply(false)
}

61
gradle/libs.versions.toml Normal file
View File

@ -0,0 +1,61 @@
[versions]
#jetbrains
kotlin = "1.9.0"
#KSP
ksp = "1.9.0-1.0.12"
#AndroidX
androidx-constraintlayout = "2.1.4"
androidx-documentfile = "1.0.1"
androidx-swiperefreshlayout = "1.1.0"
#Eventbus
eventbus = "3.3.1"
#Room
room = "2.6.0-alpha02"
#Simple tools
simple-commons = "c5a32fb1f3"
#AudioRecordView
audiorecordview = "1.0.4"
#TAndroidLame
tandroidlame = "1.1"
#AutofitTextView
autofittextview = "0.2.1"
#Gradle
gradlePlugins-agp = "8.1.0"
#build
app-build-compileSDKVersion = "34"
app-build-targetSDK = "34"
app-build-minimumSDK = "23"
app-build-javaVersion = "VERSION_17"
app-build-kotlinJVMTarget = "17"
#versioning
app-version-appId = "com.simplemobiletools.voicerecorder"
app-version-versionCode = "38"
app-version-versionName = "5.12.0"
[libraries]
#AndroidX
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" }
androidx-documentfile = { module = "androidx.documentfile:documentfile", version.ref = "androidx-documentfile" }
androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version.ref = "androidx-swiperefreshlayout" }
#Room
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
#Simple Mobile Tools
simple-tools-commons = { module = "com.github.SimpleMobileTools:Simple-Commons", version.ref = "simple-commons" }
#EventBus
eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbus" }
#AudioRecordView
audiorecordview = { module = "com.github.Armen101:AudioRecordView", version.ref = "audiorecordview" }
#TAndroidLame
tandroidlame = { module = "com.github.naman14:TAndroidLame", version.ref = "tandroidlame" }
#AutofitTextView
autofittextview = { module = "me.grantland:autofittextview", version.ref = "autofittextview" }
[bundles]
room = [
"androidx-room-ktx",
"androidx-room-runtime",
]
[plugins]
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip

View File

@ -1 +0,0 @@
include ':app'

16
settings.gradle.kts Normal file
View File

@ -0,0 +1,16 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { setUrl("https://jitpack.io") }
}
}
include(":app")