From 27c82dd8b02c81115af67e7dfc79b1b3e1b80a2d Mon Sep 17 00:00:00 2001 From: Maksim Zoteev <39910552+F0x1d@users.noreply.github.com> Date: Tue, 5 Dec 2023 21:11:21 +0300 Subject: [PATCH] [feat]: update v1.5.2 * [build]: updated dependencies * [fix]: empty logs placeholder animation * [build]: bumped version to 1.5.2 * [refactor]: 1 second delay to show empty logs placeholder * [fix]: some crash idk * [feat]: show all logs since device boot * [fix]: first line dropping --- app/build.gradle | 4 +- .../12.json | 198 ++++++++++++++++++ .../com/f0x1d/logfox/database/AppDatabase.kt | 5 +- .../f0x1d/logfox/database/entity/AppCrash.kt | 17 +- .../java/com/f0x1d/logfox/di/RoomModule.kt | 3 +- .../repository/logging/CrashesRepository.kt | 58 ++--- .../repository/logging/LoggingRepository.kt | 13 +- .../logfox/ui/fragment/logs/LogsFragment.kt | 33 ++- .../settings/SettingsServiceFragment.kt | 10 + .../logfox/ui/viewholder/LogViewHolder.kt | 31 +-- .../ui/viewholder/base/BaseViewHolder.kt | 6 +- .../utils/preferences/AppPreferences.kt | 3 + .../f0x1d/logfox/viewmodel/LogsViewModel.kt | 4 +- app/src/main/res/layout/fragment_logs.xml | 1 - app/src/main/res/layout/placeholder_logs.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 3 +- app/src/main/res/xml/settings_service.xml | 8 + build.gradle | 4 +- 20 files changed, 338 insertions(+), 66 deletions(-) create mode 100644 app/schemas/com.f0x1d.logfox.database.AppDatabase/12.json diff --git a/app/build.gradle b/app/build.gradle index ea13890b..a784ecd3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { applicationId "com.f0x1d.logfox" minSdk 24 targetSdk 34 - versionCode 53 - versionName "1.5.1" + versionCode 54 + versionName "1.5.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/schemas/com.f0x1d.logfox.database.AppDatabase/12.json b/app/schemas/com.f0x1d.logfox.database.AppDatabase/12.json new file mode 100644 index 00000000..2f36e7ab --- /dev/null +++ b/app/schemas/com.f0x1d.logfox.database.AppDatabase/12.json @@ -0,0 +1,198 @@ +{ + "formatVersion": 1, + "database": { + "version": 12, + "identityHash": "6a7fde8f15f3c9a2f984798e872b69c2", + "entities": [ + { + "tableName": "AppCrash", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`app_name` TEXT, `package_name` TEXT NOT NULL, `crash_type` INTEGER NOT NULL, `date_and_time` INTEGER NOT NULL, `log` TEXT NOT NULL, `log_dump` TEXT, `log_dump_file` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", + "fields": [ + { + "fieldPath": "appName", + "columnName": "app_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "packageName", + "columnName": "package_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "crashType", + "columnName": "crash_type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dateAndTime", + "columnName": "date_and_time", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "log", + "columnName": "log", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "logDump", + "columnName": "log_dump", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "logDumpFile", + "columnName": "log_dump_file", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_AppCrash_date_and_time", + "unique": false, + "columnNames": [ + "date_and_time" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_AppCrash_date_and_time` ON `${TABLE_NAME}` (`date_and_time`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "LogRecording", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`title` TEXT NOT NULL, `date_and_time` INTEGER NOT NULL, `file` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", + "fields": [ + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateAndTime", + "columnName": "date_and_time", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "file", + "columnName": "file", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "UserFilter", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`including` INTEGER NOT NULL, `allowed_levels` TEXT NOT NULL, `uid` TEXT, `pid` TEXT, `tid` TEXT, `package_name` TEXT, `tag` TEXT, `content` TEXT, `enabled` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", + "fields": [ + { + "fieldPath": "including", + "columnName": "including", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "allowedLevels", + "columnName": "allowed_levels", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "uid", + "columnName": "uid", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "pid", + "columnName": "pid", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tid", + "columnName": "tid", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "packageName", + "columnName": "package_name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tag", + "columnName": "tag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6a7fde8f15f3c9a2f984798e872b69c2')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/f0x1d/logfox/database/AppDatabase.kt b/app/src/main/java/com/f0x1d/logfox/database/AppDatabase.kt index 3edda150..142d295a 100644 --- a/app/src/main/java/com/f0x1d/logfox/database/AppDatabase.kt +++ b/app/src/main/java/com/f0x1d/logfox/database/AppDatabase.kt @@ -15,7 +15,7 @@ import com.f0x1d.logfox.database.entity.LogRecordingDao import com.f0x1d.logfox.database.entity.UserFilter import com.f0x1d.logfox.database.entity.UserFilterDao -@Database(entities = [AppCrash::class, LogRecording::class, UserFilter::class], version = 11) +@Database(entities = [AppCrash::class, LogRecording::class, UserFilter::class], version = 12) @TypeConverters(CrashTypeConverter::class, AllowedLevelsConverter::class) abstract class AppDatabase: RoomDatabase() { @@ -51,6 +51,9 @@ abstract class AppDatabase: RoomDatabase() { val MIGRATION_10_11 = Migration(10, 11) { it.execSQL("ALTER TABLE AppCrash ADD COLUMN log_dump_file TEXT") } + val MIGRATION_11_12 = Migration(11, 12) { + it.execSQL("CREATE INDEX index_AppCrash_date_and_time ON AppCrash(date_and_time)") + } } abstract fun appCrashDao(): AppCrashDao diff --git a/app/src/main/java/com/f0x1d/logfox/database/entity/AppCrash.kt b/app/src/main/java/com/f0x1d/logfox/database/entity/AppCrash.kt index 45c1e2cf..42dd3d24 100644 --- a/app/src/main/java/com/f0x1d/logfox/database/entity/AppCrash.kt +++ b/app/src/main/java/com/f0x1d/logfox/database/entity/AppCrash.kt @@ -1,6 +1,14 @@ package com.f0x1d.logfox.database.entity -import androidx.room.* +import androidx.room.ColumnInfo +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Entity +import androidx.room.Insert +import androidx.room.PrimaryKey +import androidx.room.Query +import androidx.room.TypeConverter +import androidx.room.Update import kotlinx.coroutines.flow.Flow import java.io.File @@ -9,9 +17,9 @@ data class AppCrash( @ColumnInfo(name = "app_name") val appName: String?, @ColumnInfo(name = "package_name") val packageName: String, @ColumnInfo(name = "crash_type") val crashType: CrashType, - @ColumnInfo(name = "date_and_time") val dateAndTime: Long, + @ColumnInfo(name = "date_and_time", index = true) val dateAndTime: Long, @ColumnInfo(name = "log") val log: String, - @ColumnInfo(name = "log_dump") val logDump: String? = null, + @Deprecated("Use logDumpFile") @ColumnInfo(name = "log_dump") val logDump: String? = null, @ColumnInfo(name = "log_dump_file") val logDumpFile: String? = null, @PrimaryKey(autoGenerate = true) val id: Long = 0 ) { @@ -32,6 +40,9 @@ interface AppCrashDao { @Query("SELECT * FROM AppCrash WHERE package_name = :packageName") suspend fun getAllByPackageName(packageName: String): List + @Query("SELECT * FROM AppCrash WHERE date_and_time = :dateAndTime") + suspend fun getAllByDateAndTime(dateAndTime: Long): List + @Query("SELECT * FROM AppCrash WHERE id = :id") fun get(id: Long): Flow diff --git a/app/src/main/java/com/f0x1d/logfox/di/RoomModule.kt b/app/src/main/java/com/f0x1d/logfox/di/RoomModule.kt index 63d84f2c..f29f5667 100644 --- a/app/src/main/java/com/f0x1d/logfox/di/RoomModule.kt +++ b/app/src/main/java/com/f0x1d/logfox/di/RoomModule.kt @@ -27,6 +27,7 @@ object RoomModule { AppDatabase.MIGRATION_7_8, AppDatabase.MIGRATION_8_9, AppDatabase.MIGRATION_9_10, - AppDatabase.MIGRATION_10_11 + AppDatabase.MIGRATION_10_11, + AppDatabase.MIGRATION_11_12 ).build() } \ No newline at end of file diff --git a/app/src/main/java/com/f0x1d/logfox/repository/logging/CrashesRepository.kt b/app/src/main/java/com/f0x1d/logfox/repository/logging/CrashesRepository.kt index dad844b6..315118ec 100644 --- a/app/src/main/java/com/f0x1d/logfox/repository/logging/CrashesRepository.kt +++ b/app/src/main/java/com/f0x1d/logfox/repository/logging/CrashesRepository.kt @@ -31,7 +31,38 @@ class CrashesRepository @Inject constructor( if (!exists()) mkdirs() } - private val crashCollected: suspend (AppCrash) -> Unit = { + override val readers = listOf( + dumpCollector, + JavaCrashDetector(this::collectCrash), + JNICrashDetector(this::collectCrash), + ANRDetector(this::collectCrash) + ) + + override suspend fun setup() { + dumpCollector.capacity = appPreferences.logsDumpLinesCount + appPreferences.registerListener(this) + } + + override suspend fun stop() { + appPreferences.unregisterListener(this) + } + + fun deleteAllByPackageName(appCrash: AppCrash) = runOnAppScope { + database.appCrashDao().getAllByPackageName(appCrash.packageName).forEach { + it.deleteDumpFile() + context.cancelCrashNotificationFor(it) + } + + database.appCrashDao().deleteByPackageName(appCrash.packageName) + } + + private suspend fun collectCrash(it: AppCrash) { + database.appCrashDao().getAllByDateAndTime(it.dateAndTime).filter { crash -> + crash.packageName == it.packageName + }.also { + if (it.isNotEmpty()) return + } + val sendNotificationIfNeeded = { appCrash: AppCrash -> if (appPreferences.showingNotificationsFor(appCrash.crashType)) { context.sendErrorNotification(appCrash) @@ -64,31 +95,6 @@ class CrashesRepository @Inject constructor( ) } - override val readers = listOf( - dumpCollector, - JavaCrashDetector(crashCollected), - JNICrashDetector(crashCollected), - ANRDetector(crashCollected) - ) - - override suspend fun setup() { - dumpCollector.capacity = appPreferences.logsDumpLinesCount - appPreferences.registerListener(this) - } - - override suspend fun stop() { - appPreferences.unregisterListener(this) - } - - fun deleteAllByPackageName(appCrash: AppCrash) = runOnAppScope { - database.appCrashDao().getAllByPackageName(appCrash.packageName).forEach { - it.deleteDumpFile() - context.cancelCrashNotificationFor(it) - } - - database.appCrashDao().deleteByPackageName(appCrash.packageName) - } - override suspend fun updateInternal(item: AppCrash) = database.appCrashDao().update(item) override suspend fun deleteInternal(item: AppCrash) { diff --git a/app/src/main/java/com/f0x1d/logfox/repository/logging/LoggingRepository.kt b/app/src/main/java/com/f0x1d/logfox/repository/logging/LoggingRepository.kt index f5c057a5..54f2f0f7 100644 --- a/app/src/main/java/com/f0x1d/logfox/repository/logging/LoggingRepository.kt +++ b/app/src/main/java/com/f0x1d/logfox/repository/logging/LoggingRepository.kt @@ -38,7 +38,8 @@ class LoggingRepository @Inject constructor( ): BaseRepository(), SharedPreferences.OnSharedPreferenceChangeListener { companion object { - private val COMMAND = arrayOf("logcat" , "-v", "uid", "-v", "epoch", "-T", "1") + private val COMMAND = arrayOf("logcat" , "-v", "uid", "-v", "epoch") + private val SHOW_LOGS_FROM_NOW_FLAGS = arrayOf("-T", "1") } val logsFlow = MutableStateFlow(emptyList()) @@ -128,7 +129,13 @@ class LoggingRepository @Inject constructor( return@coroutineScope } - val process = loggingTerminal.execute(*COMMAND) + val command = COMMAND + when (appPreferences.showLogsFromAppLaunch) { + true -> SHOW_LOGS_FROM_NOW_FLAGS + + else -> emptyArray() + } + + val process = loggingTerminal.execute(*command) if (process == null) { fallbackToDefaultTerminal() return@coroutineScope @@ -156,7 +163,7 @@ class LoggingRepository @Inject constructor( try { process.output.bufferedReader().useLines { - var droppedFirst = false + var droppedFirst = !appPreferences.showLogsFromAppLaunch // avoiding getting the same line after logging restart because of // WARNING: -T 0 invalid, setting to 1 for (line in it) { diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/logs/LogsFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/logs/LogsFragment.kt index 72074f83..7d9f5e8c 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/logs/LogsFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/logs/LogsFragment.kt @@ -6,7 +6,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.OnBackPressedCallback -import androidx.core.view.isVisible import androidx.hilt.navigation.fragment.hiltNavGraphViewModels import androidx.lifecycle.asLiveData import androidx.navigation.fragment.findNavController @@ -25,6 +24,7 @@ import com.f0x1d.logfox.extensions.views.widgets.invalidateNavigationButton import com.f0x1d.logfox.extensions.views.widgets.setClickListenerOn import com.f0x1d.logfox.extensions.views.widgets.setupBackButtonForNavController import com.f0x1d.logfox.extensions.views.widgets.setupCloseButton +import com.f0x1d.logfox.model.LogLine import com.f0x1d.logfox.ui.fragment.base.BaseViewModelFragment import com.f0x1d.logfox.viewmodel.LogsViewModel import dagger.hilt.android.AndroidEntryPoint @@ -43,6 +43,7 @@ class LogsFragment: BaseViewModelFragment(), }) } private var changingState = false + private var changingPlaceholderVisibilityRunnable: Runnable? = null private val clearSelectionOnBackPressedCallback = object : OnBackPressedCallback(false) { override fun handleOnBackPressed() { @@ -98,9 +99,7 @@ class LogsFragment: BaseViewModelFragment(), } setClickListenerOn(R.id.clear_item) { viewModel.clearLogs() - - adapter.submitList(null) - viewModel.selectedItems.update { emptyList() } + updateLogsList(null) } setClickListenerOn(R.id.service_status_item) { requireContext().apply { @@ -176,12 +175,7 @@ class LogsFragment: BaseViewModelFragment(), } viewModel.logs.asLiveData().observe(viewLifecycleOwner) { - binding.placeholderLayout.root.isVisible = it.isEmpty() - - adapter.submitList(null) - adapter.submitList(it) { - scrollLogToBottom() - } + updateLogsList(it) } viewModel.paused.asLiveData().observe(viewLifecycleOwner) { paused -> @@ -248,6 +242,25 @@ class LogsFragment: BaseViewModelFragment(), else invalidateNavigationButton() } + private fun updateLogsList(items: List?) { + binding.placeholderLayout.root.apply { + if (items?.isEmpty() != false) { + animate() + .alpha(1f) + .setStartDelay(1000) + .setDuration(200) + } else { + animate().cancel() + alpha = 0f + } + } + + adapter.submitList(null) + adapter.submitList(items) { + scrollLogToBottom() + } + } + private fun scrollLogToBottom() { binding.logsRecycler.stopScroll() binding.logsRecycler.scrollToPosition(adapter.itemCount - 1) diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsServiceFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsServiceFragment.kt index 6e131d8e..dc858bfd 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsServiceFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsServiceFragment.kt @@ -76,6 +76,16 @@ class SettingsServiceFragment: BasePreferenceFragment() { return@setOnPreferenceChangeListener true } } + + findPreference("pref_show_logs_from_app_launch")?.apply { + setOnPreferenceChangeListener { preference, newValue -> + if (!(newValue as Boolean)) { + loggingRepository.restartLogging(updateTerminal = false) + } + + return@setOnPreferenceChangeListener true + } + } } private fun askAboutNewTerminalRestart() { diff --git a/app/src/main/java/com/f0x1d/logfox/ui/viewholder/LogViewHolder.kt b/app/src/main/java/com/f0x1d/logfox/ui/viewholder/LogViewHolder.kt index bf53ade3..718d4d43 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/viewholder/LogViewHolder.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/viewholder/LogViewHolder.kt @@ -39,28 +39,33 @@ class LogViewHolder( popupMenu.setForceShowIcon(true) binding.root.setOnClickListener { - if (adapter().selectedItems.isNotEmpty()) + val adapter = adapter() ?: return@setOnClickListener + + if (adapter.selectedItems.isNotEmpty()) selectItem() else expandOrCollapseItem() } binding.root.setOnLongClickListener { - if (adapter().selectedItems.isNotEmpty()) + val adapter = adapter() ?: return@setOnLongClickListener true + + if (adapter.selectedItems.isNotEmpty()) expandOrCollapseItem() else popupMenu.show() + return@setOnLongClickListener true } } override fun bindTo(data: LogLine) { - adapter().textSize.also { + adapter()?.textSize?.also { binding.logText.textSize = it binding.levelView.textSize = it } binding.logText.text = buildString { - adapter().logsFormat.apply { + adapter()?.logsFormat?.apply { if (date) append(dateTimeFormatter.formatDate(data.dateAndTime) + " ") if (time) append(dateTimeFormatter.formatTime(data.dateAndTime) + " ") if (uid) append(data.uid + " ") @@ -81,21 +86,23 @@ class LogViewHolder( popupMenu.dismiss() } - private fun selectItem() = adapter().selectedItems.apply { + private fun selectItem() = adapter()?.selectedItems?.apply { currentItem?.also { selectedItem(it, !any { logLine -> it.id == logLine.id }) } } - private fun expandOrCollapseItem() = adapter().expandedStates.apply { - currentItem?.also { - put(it.id, !getOrElse(it.id) { adapter().logsExpanded }) - changeExpandedAndSelected(it) + private fun expandOrCollapseItem() = adapter()?.apply { + expandedStates.apply { + currentItem?.also { + put(it.id, !getOrElse(it.id) { logsExpanded }) + changeExpandedAndSelected(it) + } } } - private fun changeExpandedAndSelected(logLine: LogLine) { - binding.logText.maxLines = if (adapter().expandedStates.getOrElse(logLine.id) { adapter().logsExpanded }) Int.MAX_VALUE else 1 - binding.container.isSelected = adapter().selectedItems.contains(logLine) + private fun changeExpandedAndSelected(logLine: LogLine) = adapter()?.apply { + binding.logText.maxLines = if (expandedStates.getOrElse(logLine.id) { logsExpanded }) Int.MAX_VALUE else 1 + binding.container.isSelected = selectedItems.contains(logLine) } } \ No newline at end of file diff --git a/app/src/main/java/com/f0x1d/logfox/ui/viewholder/base/BaseViewHolder.kt b/app/src/main/java/com/f0x1d/logfox/ui/viewholder/base/BaseViewHolder.kt index 8489dd42..a118ad87 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/viewholder/base/BaseViewHolder.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/viewholder/base/BaseViewHolder.kt @@ -6,13 +6,13 @@ import com.f0x1d.logfox.adapter.base.BaseListAdapter abstract class BaseViewHolder(protected val binding: D): RecyclerView.ViewHolder(binding.root) { - protected val baseAdapter get() = bindingAdapter as BaseListAdapter - protected val elements: List get() = baseAdapter.currentList + protected val baseAdapter get() = bindingAdapter as? BaseListAdapter + protected val elements: List get() = baseAdapter?.currentList ?: emptyList() protected val currentItem: T? get() = elements.getOrNull(bindingAdapterPosition) abstract fun bindTo(data: T) open fun recycle() {} open fun detach() {} - fun adapter() = bindingAdapter as R + fun adapter() = bindingAdapter as? R } \ No newline at end of file diff --git a/app/src/main/java/com/f0x1d/logfox/utils/preferences/AppPreferences.kt b/app/src/main/java/com/f0x1d/logfox/utils/preferences/AppPreferences.kt index e9e2ac96..5df188b9 100644 --- a/app/src/main/java/com/f0x1d/logfox/utils/preferences/AppPreferences.kt +++ b/app/src/main/java/com/f0x1d/logfox/utils/preferences/AppPreferences.kt @@ -80,6 +80,9 @@ class AppPreferences @Inject constructor( var startOnLaunch get() = get("pref_start_on_launch", true) set(value) { put("pref_start_on_launch", value) } + var showLogsFromAppLaunch + get() = get("pref_show_logs_from_app_launch", true) + set(value) { put("pref_show_logs_from_app_launch", value) } var selectedTerminalIndex get() = get("pref_selected_terminal_index", 0) set(value) { put("pref_selected_terminal_index", value) } diff --git a/app/src/main/java/com/f0x1d/logfox/viewmodel/LogsViewModel.kt b/app/src/main/java/com/f0x1d/logfox/viewmodel/LogsViewModel.kt index 0a17525d..4c848880 100644 --- a/app/src/main/java/com/f0x1d/logfox/viewmodel/LogsViewModel.kt +++ b/app/src/main/java/com/f0x1d/logfox/viewmodel/LogsViewModel.kt @@ -109,7 +109,9 @@ class LogsViewModel @Inject constructor( fun query(query: String?) = this.query.update { query } - fun clearLogs() = loggingRepository.clearLogs() + fun clearLogs() = loggingRepository.clearLogs().also { + selectedItems.update { emptyList() } + } fun restartLogging() = loggingRepository.restartLogging() diff --git a/app/src/main/res/layout/fragment_logs.xml b/app/src/main/res/layout/fragment_logs.xml index c792dc96..39964051 100644 --- a/app/src/main/res/layout/fragment_logs.xml +++ b/app/src/main/res/layout/fragment_logs.xml @@ -34,7 +34,6 @@ android:id="@+id/placeholder_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:visibility="gone" layout="@layout/placeholder_logs" app:layout_anchor="@id/logs_recycler" app:layout_anchorGravity="center" /> diff --git a/app/src/main/res/layout/placeholder_logs.xml b/app/src/main/res/layout/placeholder_logs.xml index 2047c65b..f02c7b43 100644 --- a/app/src/main/res/layout/placeholder_logs.xml +++ b/app/src/main/res/layout/placeholder_logs.xml @@ -2,6 +2,7 @@ Сейчас сбоев нет Сейчас записей нет Сейчас фильтров нет + Показывать только логи, появившиеся с момента запуска приложения \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index e2d10c06..b6db1372 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -133,4 +133,5 @@ 目前没有崩溃记录 目前没有录制 目前没有过滤器 + 只显示 app 启动后的日志 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e500c6de..51bba5a3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -134,7 +134,7 @@ Date format Time format Archives - Include device information with exported recordings and crashes + Include device information in exported recordings and crashes Logs dump lines are kept in RAM, so make sure not to overflow it with chosen count To recording There are currently no logs @@ -142,4 +142,5 @@ There are currently no crashes There are currently no recordings There are currently no filters + Show only logs which have appeared since the app launch \ No newline at end of file diff --git a/app/src/main/res/xml/settings_service.xml b/app/src/main/res/xml/settings_service.xml index cf09ab37..645a1088 100644 --- a/app/src/main/res/xml/settings_service.xml +++ b/app/src/main/res/xml/settings_service.xml @@ -46,6 +46,14 @@ app:singleLineTitle="false" app:widgetLayout="@layout/preference_material_switch" app:iconSpaceReserved="false" /> + +