Skip to content

Commit

Permalink
Recordings with titles
Browse files Browse the repository at this point in the history
  • Loading branch information
F0x1d committed Nov 14, 2022
1 parent 071f0f3 commit 46ade16
Show file tree
Hide file tree
Showing 29 changed files with 235 additions and 65 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
applicationId "com.f0x1d.logfox"
minSdk 21
targetSdk 33
versionCode 21
versionName "1.2.0"
versionCode 22
versionName "1.2.1"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
4 changes: 0 additions & 4 deletions app/src/main/java/com/f0x1d/logfox/adapter/CrashesAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import com.f0x1d.logfox.ui.viewholder.CrashViewHolder

class CrashesAdapter(private val click: (AppCrash) -> Unit, private val delete: (AppCrash) -> Unit): BaseAdapter<AppCrash, ItemCrashBinding>() {

init {
setHasStableIds(true)
}

override fun createHolder(layoutInflater: LayoutInflater, parent: ViewGroup) = CrashViewHolder(
ItemCrashBinding.inflate(layoutInflater, parent, false),
click,
Expand Down
4 changes: 0 additions & 4 deletions app/src/main/java/com/f0x1d/logfox/adapter/FiltersAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ class FiltersAdapter(private val click: (UserFilter) -> Unit,
private val delete: (UserFilter) -> Unit,
private val checked: (UserFilter, Boolean) -> Unit): BaseAdapter<UserFilter, ItemFilterBinding>() {

init {
setHasStableIds(true)
}

override fun createHolder(layoutInflater: LayoutInflater, parent: ViewGroup) = FilterViewHolder(
ItemFilterBinding.inflate(layoutInflater, parent, false),
click,
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/f0x1d/logfox/adapter/LogsAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class LogsAdapter: BaseAdapter<LogLine, ItemLogBinding>() {
notifyItemRangeChanged(0, itemCount)
}

init {
setHasStableIds(false)
}

override fun createHolder(layoutInflater: LayoutInflater, parent: ViewGroup) = LogViewHolder(
ItemLogBinding.inflate(layoutInflater, parent, false)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import com.f0x1d.logfox.ui.viewholder.RecordingViewHolder

class RecordingsAdapter(private val click: (LogRecording) -> Unit, private val delete: (LogRecording) -> Unit): BaseAdapter<LogRecording, ItemRecordingBinding>() {

init {
setHasStableIds(true)
}

override fun createHolder(layoutInflater: LayoutInflater, parent: ViewGroup) = RecordingViewHolder(
ItemRecordingBinding.inflate(layoutInflater, parent, false),
click,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ abstract class BaseAdapter<T, D : ViewBinding>: RecyclerView.Adapter<BaseViewHol

protected var recyclerView: RecyclerView? = null

init {
setHasStableIds(true)
}

abstract fun createHolder(layoutInflater: LayoutInflater, parent: ViewGroup): BaseViewHolder<T, D>

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createHolder(
Expand Down
10 changes: 9 additions & 1 deletion app/src/main/java/com/f0x1d/logfox/database/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.f0x1d.logfox.LogFoxApp
import com.f0x1d.logfox.R

@Database(entities = [AppCrash::class, LogRecording::class, UserFilter::class], version = 6)
@Database(entities = [AppCrash::class, LogRecording::class, UserFilter::class], version = 7)
@TypeConverters(CrashTypeConverter::class, AllowedLevelsConverter::class)
abstract class AppDatabase: RoomDatabase() {

Expand All @@ -33,6 +35,12 @@ abstract class AppDatabase: RoomDatabase() {
database.execSQL("CREATE TABLE LogRecording(id INTEGER PRIMARY KEY ASC AUTOINCREMENT NOT NULL, date_and_time INTEGER NOT NULL, file TEXT NOT NULL)")
}
}
val MIGRATION_6_7 = object : Migration(6, 7) {
override fun migrate(database: SupportSQLiteDatabase) {
val recordingString = LogFoxApp.instance.getString(R.string.recording)
database.execSQL("ALTER TABLE LogRecording ADD COLUMN title TEXT NOT NULL DEFAULT '${recordingString}'")
}
}
}

abstract fun appCrashDao(): AppCrashDao
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/java/com/f0x1d/logfox/database/LogRecording.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import kotlinx.coroutines.flow.Flow
import java.io.File

@Entity
data class LogRecording(@ColumnInfo(name = "date_and_time") val dateAndTime: Long,
data class LogRecording(@ColumnInfo(name = "title") val title: String,
@ColumnInfo(name = "date_and_time") val dateAndTime: Long,
@ColumnInfo(name = "file") val file: String,
@PrimaryKey(autoGenerate = true) val id: Long = 0) {

Expand All @@ -24,6 +25,9 @@ interface LogRecordingDao {
@Insert
fun insert(logRecording: LogRecording): Long

@Update
fun update(logRecording: LogRecording)

@Delete
fun delete(logRecording: LogRecording)

Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/com/f0x1d/logfox/di/RoomModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ object RoomModule {
AppDatabase.MIGRATION_2_3,
AppDatabase.MIGRATION_3_4,
AppDatabase.MIGRATION_4_5,
AppDatabase.MIGRATION_5_6
AppDatabase.MIGRATION_5_6,
AppDatabase.MIGRATION_6_7
).build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ fun View.applyBottomInsets(view: View) = applyInsets(view) { insets ->
}
}

fun View.applyInsets(view: View, block: View.(Insets) -> Unit) {
fun View.applyInsets(view: View, block: View.(Insets) -> Unit) = com.f0x1d.logfox.extensions.applyInsets(view) {
block.invoke(this, it)
}

fun applyInsets(view: View, block: (Insets) -> Unit) {
ViewCompat.setOnApplyWindowInsetsListener(view) { _, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())

block.invoke(this, insets)
block.invoke(insets)

windowInsets
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,27 @@ package com.f0x1d.logfox.extensions

import android.net.Uri
import androidx.lifecycle.viewModelScope
import com.f0x1d.logfox.utils.exportCrashToZip
import com.f0x1d.logfox.utils.exportLogToZip
import com.f0x1d.logfox.viewmodel.base.BaseFlowProxyViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.OutputStream

inline fun <T, R> BaseFlowProxyViewModel<T, R>.logToZip(uri: Uri, crossinline block: R.() -> String) {
inline fun <T, R> BaseFlowProxyViewModel<T, R>.logToZip(uri: Uri, crossinline block: R.() -> String) = toZip(uri) {
exportLogToZip(ctx, block.invoke(it))
}

inline fun <T, R> BaseFlowProxyViewModel<T, R>.crashToZip(uri: Uri, crossinline block: R.() -> String) = toZip(uri) {
exportCrashToZip(ctx, block.invoke(it))
}

inline fun <T, R> BaseFlowProxyViewModel<T, R>.toZip(uri: Uri, crossinline block: OutputStream.(R) -> Unit) {
viewModelScope.launch(Dispatchers.IO) {
data.value?.apply {
ctx.contentResolver.openOutputStream(uri)?.exportLogToZip(ctx, block.invoke(this))
ctx.contentResolver.openOutputStream(uri)?.also {
block.invoke(it, this)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.f0x1d.logfox.repository.logging

import android.content.Context
import com.f0x1d.logfox.R
import com.f0x1d.logfox.database.AppDatabase
import com.f0x1d.logfox.database.LogRecording
import com.f0x1d.logfox.extensions.exportFormatted
Expand Down Expand Up @@ -118,7 +119,9 @@ class RecordingsRepository @Inject constructor(@ApplicationContext private val c
writeLogsToFile()

recordingsFlow.updateList {
val logRecording = LogRecording(recordingTime, recordingFile!!.absolutePath).run {
val title = "${context.getString(R.string.recording)} ${recordingsFlow.value.size + 1}"

val logRecording = LogRecording(title, recordingTime, recordingFile!!.absolutePath).run {
copy(id = database.logRecordingDao().insert(this))
}

Expand All @@ -133,6 +136,17 @@ class RecordingsRepository @Inject constructor(@ApplicationContext private val c
}
}

fun updateTitle(logRecording: LogRecording, newTitle: String) {
onAppScope {
recordingsFlow.updateList {
val newValue = logRecording.copy(title = newTitle).also {
database.logRecordingDao().update(it)
}
set(indexOfFirst { it.id == newValue.id }, newValue)
}
}
}

fun deleteRecording(logRecording: LogRecording) {
onAppScope {
recordingsFlow.updateList {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class CrashDetailsActivity: BaseViewModelActivity<CrashDetailsViewModel, Activit
}

private val zipCrashLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("application/zip")) {
viewModel.logToZip(it ?: return@registerForActivityResult) { log }
viewModel.crashToZip(it ?: return@registerForActivityResult) { log }
}
private val navArgs by navArgs<CrashDetailsActivityArgs>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import com.f0x1d.logfox.extensions.logToZip
import com.f0x1d.logfox.extensions.shareFileIntent
import com.f0x1d.logfox.extensions.toLocaleString
import com.f0x1d.logfox.ui.dialog.base.BaseViewModelBottomSheet
import com.f0x1d.logfox.utils.OneTimeAction
import com.f0x1d.logfox.utils.view.PauseTextWatcher
import com.f0x1d.logfox.utils.viewModelFactory
import com.f0x1d.logfox.viewmodel.recordings.RecordingViewModel
import com.f0x1d.logfox.viewmodel.recordings.RecordingViewModelAssistedFactory
Expand All @@ -33,7 +35,7 @@ class RecordingBottomSheet: BaseViewModelBottomSheet<RecordingViewModel, SheetRe
}

private val zipLogLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("application/zip")) {
viewModel.logToZip(it ?: return@registerForActivityResult) { File(file).readText() }
viewModel.logToZip(it ?: return@registerForActivityResult) { file }
}
private val logExportLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) {
viewModel.exportFile(it ?: return@registerForActivityResult)
Expand All @@ -45,10 +47,24 @@ class RecordingBottomSheet: BaseViewModelBottomSheet<RecordingViewModel, SheetRe
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val pauseTextWatcher = PauseTextWatcher {
viewModel.updateTitle(it.toString())
}.also {
binding.title.addTextChangedListener(it)
}

val setTextAction = OneTimeAction()

viewModel.data.observe(viewLifecycleOwner) { logRecording ->
if (logRecording == null) return@observe

binding.title.text = logRecording.dateAndTime.toLocaleString()
setTextAction.doIfNotDone {
pauseTextWatcher.paused {
binding.title.setText(logRecording.title)
}
}

binding.timeText.text = logRecording.dateAndTime.toLocaleString()

binding.exportLayout.setOnClickListener {
logExportLauncher.launch("${logRecording.dateAndTime.exportFormatted}.txt")
Expand Down
18 changes: 13 additions & 5 deletions app/src/main/java/com/f0x1d/logfox/ui/fragment/FiltersFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels
import androidx.hilt.navigation.fragment.hiltNavGraphViewModels
Expand All @@ -17,6 +19,7 @@ import com.f0x1d.logfox.databinding.FragmentFiltersBinding
import com.f0x1d.logfox.extensions.applyInsets
import com.f0x1d.logfox.extensions.setClickListenerOn
import com.f0x1d.logfox.ui.fragment.base.BaseViewModelFragment
import com.f0x1d.logfox.utils.dpToPx
import com.f0x1d.logfox.viewmodel.LogsViewModel
import com.f0x1d.logfox.viewmodel.filters.FiltersViewModel
import dagger.hilt.android.AndroidEntryPoint
Expand Down Expand Up @@ -47,16 +50,17 @@ class FiltersFragment: BaseViewModelFragment<FiltersViewModel, FragmentFiltersBi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

binding.filtersRecycler.applyInsets(view) { insets ->
updatePadding(bottom = insets.bottom)
applyInsets(view) { insets ->
binding.addFab.updateLayoutParams<MarginLayoutParams> {
bottomMargin = 10.dpToPx.toInt() + insets.bottom
}

binding.filtersRecycler.updatePadding(bottom = 71.dpToPx.toInt() + insets.bottom)
}

binding.toolbar.setOnClickListener { findNavController().popBackStack() }
binding.toolbar.inflateMenu(R.menu.filters_menu)
binding.toolbar.menu.apply {
setClickListenerOn(R.id.create_item) {
findNavController().navigate(FiltersFragmentDirections.actionFiltersFragmentToFilterBottomSheet())
}
setClickListenerOn(R.id.clear_item) {
viewModel.clearAll()
}
Expand All @@ -71,6 +75,10 @@ class FiltersFragment: BaseViewModelFragment<FiltersViewModel, FragmentFiltersBi
binding.filtersRecycler.layoutManager = LinearLayoutManager(requireContext())
binding.filtersRecycler.adapter = adapter

binding.addFab.setOnClickListener {
findNavController().navigate(FiltersFragmentDirections.actionFiltersFragmentToFilterBottomSheet())
}

viewModel.data.observe(viewLifecycleOwner) {
adapter.elements = it ?: return@observe
logsViewModel.recollect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class RecordingsFragment: BaseViewModelFragment<RecordingsViewModel, FragmentRec
binding.pauseFab.setOnClickListener { viewModel.togglePauseResume() }

binding.recordingsRecycler.layoutManager = LinearLayoutManager(requireContext())
binding.recordingsRecycler.addItemDecoration(RecyclerViewDivider(requireContext(), 10.dpToPx.toInt(), 10.dpToPx.toInt()))
binding.recordingsRecycler.addItemDecoration(RecyclerViewDivider(requireContext(), 80.dpToPx.toInt(), 10.dpToPx.toInt()))
binding.recordingsRecycler.adapter = adapter

viewModel.data.observe(viewLifecycleOwner) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class RecordingViewHolder(binding: ItemRecordingBinding,
}

override fun bindTo(data: LogRecording) {
binding.recordingText.text = data.dateAndTime.toLocaleString()
binding.title.text = data.title
binding.dateText.text = data.dateAndTime.toLocaleString()
}
}
26 changes: 24 additions & 2 deletions app/src/main/java/com/f0x1d/logfox/utils/ExportImportUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.components.SingletonComponent
import java.io.File
import java.io.FileInputStream
import java.io.InputStream
import java.io.OutputStream
import java.util.zip.ZipEntry
Expand All @@ -32,11 +34,19 @@ fun OutputStream.exportFilters(context: Context, filters: List<UserFilter>) {
close()
}

fun OutputStream.exportLogToZip(context: Context, log: String) {
fun OutputStream.exportCrashToZip(context: Context, log: String) = exportToZip(context) {
putZipEntry("log.txt", log.encodeToByteArray())
}

fun OutputStream.exportLogToZip(context: Context, logFile: String) = exportToZip(context) {
putZipEntry("log.txt", File(logFile))
}

private fun OutputStream.exportToZip(context: Context, block: ZipOutputStream.() -> Unit) {
val device = EntryPointAccessors.fromApplication(context, ExportImportUtilsEntryPoint::class.java).device()

ZipOutputStream(this).apply {
putZipEntry("log.txt", log.encodeToByteArray())
block.invoke(this)
putZipEntry("device.txt", device.toString().encodeToByteArray())

close()
Expand All @@ -53,6 +63,18 @@ private fun ZipOutputStream.putZipEntry(name: String, content: ByteArray) {
closeEntry()
}

private fun ZipOutputStream.putZipEntry(name: String, file: File) {
val entry = ZipEntry(name)
putNextEntry(entry)

with(FileInputStream(file)) {
copyTo(this@putZipEntry)
close()
}

closeEntry()
}

@EntryPoint
@InstallIn(SingletonComponent::class)
interface ExportImportUtilsEntryPoint {
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/com/f0x1d/logfox/utils/OneTimeAction.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.f0x1d.logfox.utils

class OneTimeAction {

private var done = false

fun doIfNotDone(action: () -> Unit) {
if (!done) {
action.invoke()
done = true
}
}
}
Loading

0 comments on commit 46ade16

Please sign in to comment.