Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05d682601a | ||
|
|
02b4862294 | ||
|
|
bb822736ab | ||
|
|
591527750d | ||
|
|
5f6f169d3e |
@@ -19,6 +19,8 @@ decisions, physical device testing, and final behaviour are still manually revie
|
|||||||
You can choose which event types to record, set app-specific allow/block lists,
|
You can choose which event types to record, set app-specific allow/block lists,
|
||||||
and suppress routine progress or timer updates. The log view can be tailored,
|
and suppress routine progress or timer updates. The log view can be tailored,
|
||||||
expanded for long entries, and exported as CSV, aligned text, or an HTML ZIP.
|
expanded for long entries, and exported as CSV, aligned text, or an HTML ZIP.
|
||||||
|
Only the HTML ZIP includes saved notification images; CSV and aligned text use
|
||||||
|
an `[image]` marker instead.
|
||||||
|
|
||||||
## Privacy
|
## Privacy
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import androidx.fragment.app.Fragment
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.color.MaterialColors
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.switchmaterial.SwitchMaterial
|
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
import se.ajpanton.notificationlog.capture.SeenApps
|
import se.ajpanton.notificationlog.capture.SeenApps
|
||||||
@@ -293,13 +292,13 @@ class FilterAppsFragment : Fragment(R.layout.fragment_event_settings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
holder.filter.contentDescription = "Edit logging events for ${app.label}"
|
holder.filter.contentDescription = "Edit logging events for ${app.label}"
|
||||||
holder.filter.imageTintList = ColorStateList.valueOf(
|
val colors = if (app.hasEventOverride) {
|
||||||
MaterialColors.getColor(
|
R.color.app_filter_override_background to R.color.app_filter_override_icon
|
||||||
holder.filter,
|
} else {
|
||||||
if (app.hasEventOverride) com.google.android.material.R.attr.colorPrimary
|
R.color.app_filter_inherited_background to R.color.app_filter_inherited_icon
|
||||||
else com.google.android.material.R.attr.colorOnSurface,
|
}
|
||||||
),
|
holder.filter.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(holder.filter.context, colors.first))
|
||||||
)
|
holder.filter.imageTintList = ColorStateList.valueOf(ContextCompat.getColor(holder.filter.context, colors.second))
|
||||||
holder.filter.setOnClickListener { onEventFilterClicked(app) }
|
holder.filter.setOnClickListener { onEventFilterClicked(app) }
|
||||||
}
|
}
|
||||||
if (holder is SectionTitleHolder && item is AppListItem.SectionTitle) {
|
if (holder is SectionTitleHolder && item is AppListItem.SectionTitle) {
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class LogDisplayFragment : Fragment(R.layout.fragment_log_display) {
|
|||||||
): LinearLayout = LinearLayout(requireContext()).apply {
|
): LinearLayout = LinearLayout(requireContext()).apply {
|
||||||
orientation = LinearLayout.VERTICAL
|
orientation = LinearLayout.VERTICAL
|
||||||
setPadding(dp(TIMESTAMP_CONTROLS_INDENT_DP), 0, 0, 0)
|
setPadding(dp(TIMESTAMP_CONTROLS_INDENT_DP), 0, 0, 0)
|
||||||
addDropdown("Timestamp timezone", listOf("Current local timezone", "UTC", "Local timezone when event happened"), TimestampZone.entries.indexOf(currentSettings().timestampZone)) { position ->
|
addDropdown("Timestamp timezone", listOf("Local timezone when event happened", "Current local timezone", "UTC"), TimestampZone.entries.indexOf(currentSettings().timestampZone)) { position ->
|
||||||
val updated = currentSettings().copy(timestampZone = TimestampZone.entries[position])
|
val updated = currentSettings().copy(timestampZone = TimestampZone.entries[position])
|
||||||
saveSettings(updated)
|
saveSettings(updated)
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,8 @@ class LogDisplayFragment : Fragment(R.layout.fragment_log_display) {
|
|||||||
|
|
||||||
private fun LinearLayout.addDropdown(label: String, values: List<String>, selected: Int, onSelected: (Int) -> Unit) {
|
private fun LinearLayout.addDropdown(label: String, values: List<String>, selected: Int, onSelected: (Int) -> Unit) {
|
||||||
addView(TextView(context).apply { text = label })
|
addView(TextView(context).apply { text = label })
|
||||||
addView(Spinner(context).apply {
|
addView(Spinner(context, Spinner.MODE_DROPDOWN).apply {
|
||||||
|
setPopupBackgroundDrawable(context.getDrawable(R.drawable.dropdown_popup_background))
|
||||||
adapter = ArrayAdapter(context, android.R.layout.simple_spinner_dropdown_item, values)
|
adapter = ArrayAdapter(context, android.R.layout.simple_spinner_dropdown_item, values)
|
||||||
setSelection(selected)
|
setSelection(selected)
|
||||||
onItemSelectedListener = object : android.widget.AdapterView.OnItemSelectedListener {
|
onItemSelectedListener = object : android.widget.AdapterView.OnItemSelectedListener {
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
|||||||
|
|
||||||
private fun chooseExportFormat() {
|
private fun chooseExportFormat() {
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
.setItems(arrayOf("CSV", "Formatted text", "HTML ZIP")) { _, which ->
|
.setItems(arrayOf("CSV (no images)", "Formatted text (no images)", "HTML ZIP")) { _, which ->
|
||||||
pendingExport = ExportFormat.entries[which]
|
pendingExport = ExportFormat.entries[which]
|
||||||
createDocument.launch("notification-log.${pendingExport!!.extension}")
|
createDocument.launch("notification-log.${pendingExport!!.extension}")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package se.ajpanton.notificationlog.settings
|
package se.ajpanton.notificationlog.settings
|
||||||
|
|
||||||
enum class LogField { TIMESTAMP, APP_NAME, PACKAGE_NAME, ACTION, CONTENTS }
|
enum class LogField { TIMESTAMP, APP_NAME, PACKAGE_NAME, ACTION, CONTENTS }
|
||||||
enum class TimestampZone { LOCAL_NOW, UTC, EVENT_LOCAL }
|
enum class TimestampZone { EVENT_LOCAL, LOCAL_NOW, UTC }
|
||||||
enum class TimestampDateFormat { SYSTEM_DEFAULT, YEAR_MONTH_DAY, DAY_MONTH_YEAR, MONTH_DAY_YEAR }
|
enum class TimestampDateFormat { SYSTEM_DEFAULT, YEAR_MONTH_DAY, DAY_MONTH_YEAR, MONTH_DAY_YEAR }
|
||||||
enum class TimestampClockFormat { SYSTEM_DEFAULT, HOUR_24, HOUR_12 }
|
enum class TimestampClockFormat { SYSTEM_DEFAULT, HOUR_24, HOUR_12 }
|
||||||
enum class DisplayEvent { APPEARING, DISAPPEARING, EDITS }
|
enum class DisplayEvent { APPEARING, DISAPPEARING, EDITS }
|
||||||
@@ -9,7 +9,7 @@ enum class DisplayEvent { APPEARING, DISAPPEARING, EDITS }
|
|||||||
data class LogViewSettings(
|
data class LogViewSettings(
|
||||||
val visibleFields: Set<LogField> = setOf(LogField.TIMESTAMP, LogField.APP_NAME, LogField.ACTION, LogField.CONTENTS),
|
val visibleFields: Set<LogField> = setOf(LogField.TIMESTAMP, LogField.APP_NAME, LogField.ACTION, LogField.CONTENTS),
|
||||||
val order: List<LogField> = LogField.entries,
|
val order: List<LogField> = LogField.entries,
|
||||||
val timestampZone: TimestampZone = TimestampZone.LOCAL_NOW,
|
val timestampZone: TimestampZone = TimestampZone.EVENT_LOCAL,
|
||||||
val timestampDateFormat: TimestampDateFormat = TimestampDateFormat.SYSTEM_DEFAULT,
|
val timestampDateFormat: TimestampDateFormat = TimestampDateFormat.SYSTEM_DEFAULT,
|
||||||
val timestampClockFormat: TimestampClockFormat = TimestampClockFormat.SYSTEM_DEFAULT,
|
val timestampClockFormat: TimestampClockFormat = TimestampClockFormat.SYSTEM_DEFAULT,
|
||||||
val visibleEvents: Set<DisplayEvent> = DisplayEvent.entries.toSet(),
|
val visibleEvents: Set<DisplayEvent> = DisplayEvent.entries.toSet(),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class LogViewSettingsStore(context: Context) {
|
|||||||
visibleFields = prefs.getStringSet("visible", LogViewSettings().visibleFields.map { it.name }.toSet())!!
|
visibleFields = prefs.getStringSet("visible", LogViewSettings().visibleFields.map { it.name }.toSet())!!
|
||||||
.map(LogField::valueOf).toSet(),
|
.map(LogField::valueOf).toSet(),
|
||||||
order = prefs.getString("order", null)?.split(',')?.map(LogField::valueOf) ?: LogField.entries,
|
order = prefs.getString("order", null)?.split(',')?.map(LogField::valueOf) ?: LogField.entries,
|
||||||
timestampZone = TimestampZone.valueOf(prefs.getString("zone", TimestampZone.LOCAL_NOW.name)!!),
|
timestampZone = TimestampZone.valueOf(prefs.getString("zone", TimestampZone.EVENT_LOCAL.name)!!),
|
||||||
timestampDateFormat = TimestampDateFormat.valueOf(prefs.getString("date_format", TimestampDateFormat.SYSTEM_DEFAULT.name)!!),
|
timestampDateFormat = TimestampDateFormat.valueOf(prefs.getString("date_format", TimestampDateFormat.SYSTEM_DEFAULT.name)!!),
|
||||||
timestampClockFormat = TimestampClockFormat.valueOf(prefs.getString("clock_format", TimestampClockFormat.SYSTEM_DEFAULT.name)!!),
|
timestampClockFormat = TimestampClockFormat.valueOf(prefs.getString("clock_format", TimestampClockFormat.SYSTEM_DEFAULT.name)!!),
|
||||||
visibleEvents = prefs.getStringSet("visible_events", DisplayEvent.entries.map { it.name }.toSet())!!
|
visibleEvents = prefs.getStringSet("visible_events", DisplayEvent.entries.map { it.name }.toSet())!!
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@color/dropdown_popup_background" />
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@color/dropdown_popup_outline" />
|
||||||
|
</shape>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="24dp"
|
||||||
android:text="Storage limits" />
|
android:text="Storage limits (MiB)" />
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/log_limit_mib"
|
android:id="@+id/log_limit_mib"
|
||||||
|
|||||||
@@ -9,4 +9,10 @@
|
|||||||
<color name="on_surface">#E3E2E9</color>
|
<color name="on_surface">#E3E2E9</color>
|
||||||
<color name="window_background">#121318</color>
|
<color name="window_background">#121318</color>
|
||||||
<color name="log_row_separator">#8F8D96</color>
|
<color name="log_row_separator">#8F8D96</color>
|
||||||
|
<color name="dropdown_popup_background">#25262D</color>
|
||||||
|
<color name="dropdown_popup_outline">#C7C5CF</color>
|
||||||
|
<color name="app_filter_inherited_background">#2D2E34</color>
|
||||||
|
<color name="app_filter_inherited_icon">#000000</color>
|
||||||
|
<color name="app_filter_override_background">#4A4B53</color>
|
||||||
|
<color name="app_filter_override_icon">#B8CCFF</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -9,4 +9,10 @@
|
|||||||
<color name="on_surface">#1B1B21</color>
|
<color name="on_surface">#1B1B21</color>
|
||||||
<color name="window_background">#FBF8FF</color>
|
<color name="window_background">#FBF8FF</color>
|
||||||
<color name="log_row_separator">#A5A2AB</color>
|
<color name="log_row_separator">#A5A2AB</color>
|
||||||
|
<color name="dropdown_popup_background">#FFFFFF</color>
|
||||||
|
<color name="dropdown_popup_outline">#64646C</color>
|
||||||
|
<color name="app_filter_inherited_background">#DFDFE5</color>
|
||||||
|
<color name="app_filter_inherited_icon">#FFFFFF</color>
|
||||||
|
<color name="app_filter_override_background">#D0D0D8</color>
|
||||||
|
<color name="app_filter_override_icon">#34588E</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
version=0.2
|
version=1.0
|
||||||
|
|||||||
Reference in New Issue
Block a user