Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ A simple open source audio note-taking 📝 Android application built to describ

<br />

***Find the latest apk here👇***
***Find the latest stable release here👇***

[![AudioNotes](https://github.com/certified84/AudioNote/blob/master/app/src/main/res/drawable/logo.png)](https://github.com/certified84/AudioNote/releases/tag/v0.1.1-beta00(11022022))
[![AudioNotes](https://github.com/certified84/AudioNote/blob/master/app/src/main/res/drawable/logo.png)](https://github.com/certified84/AudioNote/releases/tag/v0.1.3)

<br />

Expand Down Expand Up @@ -102,6 +102,11 @@ You need to have [Android Studio](https://developer.android.com/studio) to build

<br />

## Credit 🙌
Credit goes to [Shazomii's Notely](https://github.com/shazomii/Notely) for project inspiration

<br />

## Contribute 🤝
If you want to contribute to this app, you're always welcome!
See [Contributing Guidelines](https://github.com/certified84/AudioNote/blob/master/CONTRIBUTING.md).
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ android {
applicationId "com.certified.audionote"
minSdk 21
targetSdk 30
versionCode 3
versionName "v0.0.3-beta03(14022022)"
versionCode 4
versionName "0.1.4"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
Binary file modified app/release/app-release.apk
Binary file not shown.
4 changes: 2 additions & 2 deletions app/release/output-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 3,
"versionName": "v0.0.3-beta03(14022022)",
"versionCode": 4,
"versionName": "0.1.4",
"outputFile": "app-release.apk"
}
],
Expand Down
94 changes: 44 additions & 50 deletions app/src/main/java/com/certified/audionote/ui/EditNoteFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.certified.audionote.ui
import android.Manifest
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.content.Context
import android.media.MediaPlayer
import android.media.MediaRecorder
import android.os.Bundle
Expand All @@ -41,6 +42,7 @@ import com.certified.audionote.databinding.DialogEditReminderBinding
import com.certified.audionote.databinding.FragmentEditNoteBinding
import com.certified.audionote.model.Note
import com.certified.audionote.utils.*
import com.certified.audionote.utils.Extensions.showKeyboardFor
import com.certified.audionote.utils.Extensions.showToast
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
Expand Down Expand Up @@ -75,7 +77,6 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
private var mediaRecorder: MediaRecorder? = null
private var mediaPlayer: MediaPlayer? = null
private var file: File? = null
private val noteIsRequired = "The note title is required"
private var stopWatch: Stopwatch? = null
private var timer: Timer? = null

Expand Down Expand Up @@ -113,7 +114,7 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
openEditReminderDialog()
}
btnShare.setOnClickListener { shareNote(_note) }
btnDelete.setOnClickListener { launchDeleteNoteDialog() }
btnDelete.setOnClickListener { launchDeleteNoteDialog(requireContext()) }
btnRecord.setOnClickListener(this@EditNoteFragment)
fabSaveNote.setOnClickListener(this@EditNoteFragment)

Expand Down Expand Up @@ -149,11 +150,6 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
}

tvTitle.text = getString(R.string.edit_note)
etNoteTitle.apply {
// inputType = InputType.TYPE_NULL
keyListener = null
setOnClickListener { showToast("You can't edit the note title") }
}
btnRecord.setImageDrawable(
ResourcesCompat.getDrawable(
resources,
Expand All @@ -166,7 +162,11 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa

override fun onResume() {
super.onResume()

if (args.note.id == 0)
binding.etNoteTitle.apply {
requestFocus()
showKeyboardFor(requireContext())
}
updateStatusBarColor(binding.note!!.color)
}

Expand Down Expand Up @@ -248,7 +248,7 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
startAlarm(requireContext(), pickedDateTime!!.timeInMillis, note)
navController.navigate(R.id.action_editNoteFragment_to_homeFragment)
} else {
showToast(noteIsRequired)
showToast(requireContext().getString(R.string.title_required))
etNoteTitle.requestFocus()
}
}
Expand All @@ -257,30 +257,26 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
}

private fun onClickWhenIdIsZero(p0: View?) {
val context = requireContext()
binding.apply {
when (p0) {
btnRecord -> {
if (!isRecording) {
if (hasPermission(requireContext(), Manifest.permission.RECORD_AUDIO))
if (etNoteTitle.text.toString().isNotBlank())
btnRecord.setImageDrawable(
ResourcesCompat.getDrawable(
resources,
R.drawable.ic_mic_recording,
null
)
).run {
isRecording = true
startRecording()
}
else {
showToast(noteIsRequired)
etNoteTitle.requestFocus()
if (hasPermission(context, Manifest.permission.RECORD_AUDIO))
btnRecord.setImageDrawable(
ResourcesCompat.getDrawable(
resources,
R.drawable.ic_mic_recording,
null
)
).run {
isRecording = true
startRecording()
}
else
requestPermission(
requireActivity(),
"This permission is required to enable audio recording",
context.getString(R.string.permission_required),
MainActivity.RECORD_AUDIO_PERMISSION_CODE,
Manifest.permission.RECORD_AUDIO
)
Expand All @@ -299,17 +295,21 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
fabSaveNote -> {
if (etNoteTitle.text.toString().isNotBlank()) {
stopRecording()
if (_note.audioLength <= 0) {
showToast(context.getString(R.string.record_note_before_saving))
return
}
val note = _note.copy(
title = etNoteTitle.text.toString().trim(),
description = etNoteDescription.text.toString().trim()
)
viewModel.insertNote(note)
showToast("Note saved")
showToast(context.getString(R.string.note_saved))
if (pickedDateTime?.timeInMillis != null && pickedDateTime!!.timeInMillis <= currentDateTime.timeInMillis)
startAlarm(requireContext(), pickedDateTime!!.timeInMillis, note)
startAlarm(context, pickedDateTime!!.timeInMillis, note)
navController.navigate(R.id.action_editNoteFragment_to_homeFragment)
} else {
showToast(noteIsRequired)
showToast(context.getString(R.string.title_required))
etNoteTitle.requestFocus()
}
}
Expand Down Expand Up @@ -373,13 +373,13 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
bottomSheetDialog.show()
}

private fun launchDeleteNoteDialog() {
val materialDialog = MaterialAlertDialogBuilder(requireContext())
private fun launchDeleteNoteDialog(context: Context) {
val materialDialog = MaterialAlertDialogBuilder(context)
materialDialog.apply {
setTitle("Delete Note")
setMessage("Are you sure you want to delete ${_note.title}?")
setNegativeButton("No") { dialog, _ -> dialog?.dismiss() }
setPositiveButton("Yes") { _, _ ->
setTitle(context.getString(R.string.delete_note))
setMessage("${context.getString(R.string.confirm_deletion)} ${_note.title}?")
setNegativeButton(context.getString(R.string.no)) { dialog, _ -> dialog?.dismiss() }
setPositiveButton(context.getString(R.string.yes)) { _, _ ->
viewModel.deleteNote(_note)
lifecycleScope.launch(Dispatchers.IO) { file?.delete() }
navController.navigate(R.id.action_editNoteFragment_to_homeFragment)
Expand All @@ -390,9 +390,9 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa

private fun startRecording() {
val filePath = filePath(requireActivity())
val fileName = "${binding.etNoteTitle.text.toString().trim()}.3gp"
val fileName = "${System.currentTimeMillis()}.3gp"
_note.filePath = "$filePath/$fileName"
showToast("Started recording")
showToast(requireContext().getString(R.string.started_recording))

stopWatch = StopwatchBuilder()
.startFormat("MM:SS")
Expand All @@ -410,9 +410,8 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
prepare()
start()
stopWatch!!.start()
disableNoteTitleEdit()
} catch (e: IOException) {
showToast("An error occurred")
showToast(requireContext().getString(R.string.error_occurred))
}
}
}
Expand All @@ -429,11 +428,13 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
reset()
}
stopWatch = null
if (_note.audioLength <= 0)
return
val file = File(_note.filePath)
val fileByte = (file.readBytes().size.toDouble() / 1048576.00)
val fileSize = roundOffDecimal(fileByte).toString()
val fileSize = roundOffDecimal(fileByte)
_note.size = fileSize
showToast("Stopped recording")
showToast(requireContext().getString(R.string.stopped_recording))
}

private fun startPlayingRecording() {
Expand Down Expand Up @@ -462,18 +463,11 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
start()
}
timer!!.start()
showToast("Started playing recording")
showToast(requireContext().getString(R.string.started_playing_recording))
} catch (e: IOException) {
e.printStackTrace()
Log.d("TAG", "startPlayingRecording: ${e.localizedMessage}")
showToast("An error occurred")
}
}

private fun disableNoteTitleEdit() {
binding.etNoteTitle.apply {
keyListener = null
setOnClickListener { showToast("You can't edit the note title") }
showToast(requireContext().getString(R.string.error_occurred))
}
}

Expand All @@ -497,7 +491,7 @@ class EditNoteFragment : Fragment(), View.OnClickListener, DatePickerDialog.OnDa
stop()
}
timer = null
showToast("Stopped playing recording")
showToast(requireContext().getString(R.string.stopped_playing_recording))
}

private fun shareNote(note: Note) {
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/com/certified/audionote/utils/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@

package com.certified.audionote.utils

import android.app.Activity
import android.content.Context
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.datastore.preferences.preferencesDataStore
import androidx.fragment.app.Fragment
Expand All @@ -39,4 +42,14 @@ object Extensions {
}

val Context.dataStore by preferencesDataStore(name = "com.certified.audionotes.preferences")

fun View.hideKeyboardFrom(context: Context) {
val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(windowToken, 0)
}

fun View.showKeyboardFor(context: Context) {
val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(this, 0)
}
}
8 changes: 8 additions & 0 deletions app/src/main/java/com/certified/audionote/utils/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ fun main() {
val sec = time % 60
val minute = (time % 3600) / 60
println("Time: $time, Minute: $minute, Second: $sec")
// print(isEven(201))
}

fun isEven(number: Int): String {
return when (number % 2) {
0 -> "true"
else -> "false"
}
}
Loading