diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/di/AppModule.kt b/app/src/main/java/dev/arkbuilders/arkmemo/di/AppModule.kt index 9768d55..56d2a27 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/di/AppModule.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/di/AppModule.kt @@ -11,11 +11,11 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) object AppModule { - @Provides @Singleton - fun provideApplicationContext(@ApplicationContext context: Context): Context { + fun provideApplicationContext( + @ApplicationContext context: Context, + ): Context { return context } - -} \ No newline at end of file +} diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/models/GraphicNote.kt b/app/src/main/java/dev/arkbuilders/arkmemo/models/GraphicNote.kt index 8e6f47f..ddafa1a 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/models/GraphicNote.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/models/GraphicNote.kt @@ -16,6 +16,5 @@ data class GraphicNote( @IgnoredOnParcel override var resource: Resource? = null, override var pendingForDelete: Boolean = false, - var thumb: Bitmap? = null - + var thumb: Bitmap? = null, ) : Note, Parcelable diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/repo/graphics/GraphicNotesRepo.kt b/app/src/main/java/dev/arkbuilders/arkmemo/repo/graphics/GraphicNotesRepo.kt index 1f4c31b..c1d0302 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/repo/graphics/GraphicNotesRepo.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/repo/graphics/GraphicNotesRepo.kt @@ -13,8 +13,6 @@ import dev.arkbuilders.arklib.data.index.Resource import dev.arkbuilders.arkmemo.R import dev.arkbuilders.arkmemo.di.IO_DISPATCHER import dev.arkbuilders.arkmemo.graphics.ColorCode -import dev.arkbuilders.arkmemo.models.GraphicNote -import dev.arkbuilders.arkmemo.preferences.MemoPreferences import dev.arkbuilders.arkmemo.graphics.SVG import dev.arkbuilders.arkmemo.models.GraphicNote import dev.arkbuilders.arkmemo.models.SaveNoteResult @@ -38,26 +36,27 @@ import kotlin.io.path.fileSize import kotlin.io.path.getLastModifiedTime import kotlin.io.path.name -class GraphicNotesRepo @Inject constructor( - private val memoPreferences: MemoPreferences, - @Named(IO_DISPATCHER) private val iODispatcher: CoroutineDispatcher, - private val helper: NotesRepoHelper, - @ApplicationContext private val context: Context -): NotesRepo { - - private lateinit var root: Path - - private val displayMetrics by lazy { Resources.getSystem().displayMetrics } - private val screenWidth by lazy { displayMetrics.widthPixels } - private val screenHeight by lazy { displayMetrics.heightPixels - 150.dpToPx() } - private val thumbViewWidth by lazy { context.resources.getDimension(R.dimen.graphic_thumb_width) } - - private val thumbDirectory by lazy { context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) } - - override suspend fun init() { - helper.init() - root = memoPreferences.getNotesStorage() - } +class GraphicNotesRepo + @Inject + constructor( + private val memoPreferences: MemoPreferences, + @Named(IO_DISPATCHER) private val iODispatcher: CoroutineDispatcher, + private val helper: NotesRepoHelper, + @ApplicationContext private val context: Context, + ) : NotesRepo { + private lateinit var root: Path + + private val displayMetrics by lazy { Resources.getSystem().displayMetrics } + private val screenWidth by lazy { displayMetrics.widthPixels } + private val screenHeight by lazy { displayMetrics.heightPixels - 150.dpToPx() } + private val thumbViewWidth by lazy { context.resources.getDimension(R.dimen.graphic_thumb_width) } + + private val thumbDirectory by lazy { context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) } + + override suspend fun init() { + helper.init() + root = memoPreferences.getNotesStorage() + } override suspend fun save( note: GraphicNote, @@ -130,78 +129,81 @@ class GraphicNotesRepo @Inject constructor( modified = path.getLastModifiedTime(), ) - val userNoteProperties = helper.readProperties(id, "") - val bitmap = exportBitmapFromSvg(fileName = id.toString(), svg = svg) - - GraphicNote( - title = userNoteProperties.title, - description = userNoteProperties.description, - svg = svg, - resource = resource, - thumb = bitmap - ) - - }.filter { graphicNote -> graphicNote.svg != null } - } - - private fun exportBitmapFromSvg(fileName: String, svg: SVG?): Bitmap? { - - // Check if thumb bitmap already exists - val file = File(thumbDirectory, "$fileName.png") - try { - if (file.exists()) { - return BitmapFactory.decodeFile(file.absolutePath) + val userNoteProperties = helper.readProperties(id, "") + val bitmap = exportBitmapFromSvg(fileName = id.toString(), svg = svg) + + GraphicNote( + title = userNoteProperties.title, + description = userNoteProperties.description, + svg = svg, + resource = resource, + thumb = bitmap, + ) + }.filter { graphicNote -> graphicNote.svg != null } } - } catch (e: Exception) { - e.printStackTrace() - } - // If thumb doesn't exist, create a bitmap and a canvas for offscreen drawing - val bitmap = Bitmap.createBitmap( - thumbViewWidth.toInt(), thumbViewWidth.toInt(), Bitmap.Config.ARGB_8888 - ) - val canvas = Canvas(bitmap) + private fun exportBitmapFromSvg( + fileName: String, + svg: SVG?, + ): Bitmap? { + // Check if thumb bitmap already exists + val file = File(thumbDirectory, "$fileName.png") + try { + if (file.exists()) { + return BitmapFactory.decodeFile(file.absolutePath) + } + } catch (e: Exception) { + e.printStackTrace() + } - canvas.drawColor(ColorCode.lightYellow) - svg?.getPaths()?.forEach { path -> + // If thumb doesn't exist, create a bitmap and a canvas for offscreen drawing + val bitmap = + Bitmap.createBitmap( + thumbViewWidth.toInt(), + thumbViewWidth.toInt(), + Bitmap.Config.ARGB_8888, + ) + val canvas = Canvas(bitmap) - canvas.save() + canvas.drawColor(ColorCode.lightYellow) + svg?.getPaths()?.forEach { path -> - // Scale factor to fit the SVG path into the view - val scaleX = thumbViewWidth / screenWidth - val scaleY = thumbViewWidth / screenHeight + canvas.save() - // Find the smallest scale to maintain the aspect ratio - val scale = minOf(scaleX, scaleY) + // Scale factor to fit the SVG path into the view + val scaleX = thumbViewWidth / screenWidth + val scaleY = thumbViewWidth / screenHeight - // Center the path in the view - val dx = (thumbViewWidth - screenWidth * scale) / 2f - val dy = (thumbViewWidth - screenHeight * scale) / 2f + // Find the smallest scale to maintain the aspect ratio + val scale = minOf(scaleX, scaleY) - // Apply scaling and translation to center the path - canvas.translate(dx, dy) - canvas.scale(scale, scale) + // Center the path in the view + val dx = (thumbViewWidth - screenWidth * scale) / 2f + val dy = (thumbViewWidth - screenHeight * scale) / 2f - canvas.drawPath(path.path, path.paint) - canvas.restore() - } ?: let { - return null - } + // Apply scaling and translation to center the path + canvas.translate(dx, dy) + canvas.scale(scale, scale) - // Save the bitmap to a file - try { + canvas.drawPath(path.path, path.paint) + canvas.restore() + } ?: let { + return null + } - // Open an output stream and write the bitmap to the file - FileOutputStream(file).use { outputStream -> - bitmap.compress(Bitmap.CompressFormat.PNG, 80, outputStream) // Save as PNG + // Save the bitmap to a file + try { + // Open an output stream and write the bitmap to the file + FileOutputStream(file).use { outputStream -> + bitmap.compress(Bitmap.CompressFormat.PNG, 80, outputStream) // Save as PNG + } + return bitmap + } catch (e: IOException) { + e.printStackTrace() + return null } - return bitmap - } catch (e: IOException) { - e.printStackTrace() - return null } } -} private const val GRAPHICS_REPO = "GraphicNotesRepo" private const val SVG_EXT = "svg" diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/ui/adapters/NotesListAdapter.kt b/app/src/main/java/dev/arkbuilders/arkmemo/ui/adapters/NotesListAdapter.kt index f3a743d..68abf9d 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/ui/adapters/NotesListAdapter.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/ui/adapters/NotesListAdapter.kt @@ -33,8 +33,7 @@ import dev.arkbuilders.arkmemo.utils.visible class NotesListAdapter( private var notes: MutableList, private val onPlayPauseClick: (path: String, pos: Int?, stopCallback: ((pos: Int) -> Unit)?) -> Unit, -): RecyclerView.Adapter() { - +) : RecyclerView.Adapter() { private lateinit var activity: MainActivity lateinit var observeItemSideEffect: () -> ArkMediaPlayerSideEffect @@ -116,23 +115,26 @@ class NotesListAdapter( } } } else if (note is GraphicNote) { - holder.ivGraphicThumb.background = BitmapDrawable( - holder.itemView.context.resources, note.thumb - ) + holder.ivGraphicThumb.background = + BitmapDrawable( + holder.itemView.context.resources, note.thumb, + ) holder.ivGraphicThumb.visible() - holder.ivGraphicThumb.shapeAppearanceModel = ShapeAppearanceModel.builder() - .setBottomLeftCornerSize(0f) - .setTopLeftCornerSize(0f) - .setTopRightCorner(CornerFamily.ROUNDED, cornerRadius) - .setBottomRightCorner(CornerFamily.ROUNDED, cornerRadius) - .build() + holder.ivGraphicThumb.shapeAppearanceModel = + ShapeAppearanceModel.builder() + .setBottomLeftCornerSize(0f) + .setTopLeftCornerSize(0f) + .setTopRightCorner(CornerFamily.ROUNDED, cornerRadius) + .setBottomRightCorner(CornerFamily.ROUNDED, cornerRadius) + .build() } if (note.pendingForDelete) { holder.tvDelete.visible() if (note is GraphicNote) { - holder.ivGraphicThumb.shapeAppearanceModel = ShapeAppearanceModel.builder() - .setAllCorners(CornerFamily.ROUNDED, 0f).build() + holder.ivGraphicThumb.shapeAppearanceModel = + ShapeAppearanceModel.builder() + .setAllCorners(CornerFamily.ROUNDED, 0f).build() } } else { holder.tvDelete.gone() diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/EditGraphicNotesFragment.kt b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/EditGraphicNotesFragment.kt index bb733d7..45d2279 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/EditGraphicNotesFragment.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/EditGraphicNotesFragment.kt @@ -67,7 +67,6 @@ class EditGraphicNotesFragment : BaseEditNoteFragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) notesViewModel.init {} - observeSaveResult(notesViewModel.getSaveNoteResultLiveData()) arguments?.getParcelableCompat(GRAPHICAL_NOTE_KEY, GraphicNote::class.java)?.let { note = it graphicNotesViewModel.onNoteOpened(note) @@ -140,6 +139,7 @@ class EditGraphicNotesFragment : BaseEditNoteFragment() { binding.editTextDescription.setText(this.note.description) initBottomControls() observeDrawEvent() + observeSaveResult(notesViewModel.getSaveNoteResultLiveData()) } private fun observeDrawEvent() { diff --git a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/NotesFragment.kt b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/NotesFragment.kt index f263f3a..53798ac 100644 --- a/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/NotesFragment.kt +++ b/app/src/main/java/dev/arkbuilders/arkmemo/ui/fragments/NotesFragment.kt @@ -202,13 +202,14 @@ class NotesFragment : BaseFragment() { private fun onNotesLoaded(notes: List) { binding.pbLoading.gone() if (notesAdapter == null) { - notesAdapter = NotesListAdapter( - notes.toMutableList(), - onPlayPauseClick = { path, pos, onStop -> - playingAudioPath = path - if (playingAudioPosition >= 0) { - refreshNoteItem(playingAudioPosition) - } + notesAdapter = + NotesListAdapter( + notes.toMutableList(), + onPlayPauseClick = { path, pos, onStop -> + playingAudioPath = path + if (playingAudioPosition >= 0) { + refreshNoteItem(playingAudioPosition) + } if (playingAudioPosition >= 0 && playingAudioPosition != pos) { // Another Voice note is being played compared to the previously played one @@ -224,10 +225,9 @@ class NotesFragment : BaseFragment() { mItemTouchHelper?.attachToRecyclerView(null) } - arkMediaPlayerViewModel.onPlayOrPauseClick(path, pos, onStop) - } - ) - + arkMediaPlayerViewModel.onPlayOrPauseClick(path, pos, onStop) + }, + ) } else { notesAdapter?.setNotes(notes) }