Skip to content

Commit

Permalink
add: app type filter flag in analytics
Browse files Browse the repository at this point in the history
  • Loading branch information
Hamza417 committed Jan 2, 2025
1 parent 2ee2549 commit d042cf4
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 7 deletions.
1 change: 1 addition & 0 deletions app/src/main/assets/html/changelogs.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ <h4>Improvements</h4>
<h4>Analytics</h4>

<ul>
<li>Added <b>Application Type</b> filter flag in <b>Analytics</b> panel.</li>
<li>Added new pie chart for <i>Installer of Apps</i> to show a graph for apps are installer
sources of apps.
</li>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package app.simple.inure.dialogs.analytics

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import app.simple.inure.R
import app.simple.inure.constants.SortConstant
import app.simple.inure.extensions.fragments.ScopedBottomSheetFragment
import app.simple.inure.preferences.AnalyticsPreferences
import com.google.android.material.chip.ChipGroup

class AnalyticsSort : ScopedBottomSheetFragment() {

private lateinit var applicationTypeChipGroup: ChipGroup

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.dialog_sort_analytics, container, false)

applicationTypeChipGroup = view.findViewById(R.id.application_type_chip_group)

return view
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

setApplicationType()

applicationTypeChipGroup.setOnCheckedStateChangeListener { _, checkedIds ->
for (id in checkedIds) {
when (id) {
R.id.both -> {
AnalyticsPreferences.setApplicationType(SortConstant.BOTH)
}
R.id.system -> {
AnalyticsPreferences.setApplicationType(SortConstant.SYSTEM)
}
R.id.user -> {
AnalyticsPreferences.setApplicationType(SortConstant.USER)
}
}
}
}
}

private fun setApplicationType() {
when (AnalyticsPreferences.getApplicationType()) {
SortConstant.BOTH -> applicationTypeChipGroup.check(R.id.both)
SortConstant.SYSTEM -> applicationTypeChipGroup.check(R.id.system)
SortConstant.USER -> applicationTypeChipGroup.check(R.id.user)
}
}

companion object {
const val TAG = "AnalyticsSort"

fun newInstance(): AnalyticsSort {
val args = Bundle()
val fragment = AnalyticsSort()
fragment.arguments = args
return fragment
}

fun FragmentManager.showAnalyticsSort() {
newInstance().show(this, TAG)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package app.simple.inure.preferences

import app.simple.inure.constants.SortConstant

object AnalyticsPreferences {

const val SDK_VALUE = "analytics_sdk_value"
const val PIE_HOLE_RADIUS = "pie_hole_radius"
const val APPLICATION_TYPE = "application_type_analytics"

// ---------------------------------------------------------------------------------------------------------- //

Expand All @@ -25,4 +28,13 @@ object AnalyticsPreferences {
return SharedPreferences.getSharedPreferences().getFloat(PIE_HOLE_RADIUS, 50F)
}

// ---------------------------------------------------------------------------------------------------------- //

fun setApplicationType(value: String) {
SharedPreferences.getSharedPreferences().edit().putString(APPLICATION_TYPE, value).apply()
}

fun getApplicationType(): String {
return SharedPreferences.getSharedPreferences().getString(APPLICATION_TYPE, SortConstant.BOTH)!!
}
}
39 changes: 37 additions & 2 deletions app/src/main/java/app/simple/inure/ui/panels/Analytics.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import app.simple.inure.R
import app.simple.inure.adapters.analytics.AdapterInstallerLegend
import app.simple.inure.adapters.analytics.AdapterLegend
import app.simple.inure.constants.BottomMenuConstants
import app.simple.inure.constants.SortConstant
import app.simple.inure.decorations.padding.PaddingAwareNestedScrollView
import app.simple.inure.decorations.theme.ThemePieChart
import app.simple.inure.decorations.typeface.TypeFaceTextView
import app.simple.inure.decorations.views.LegendRecyclerView
import app.simple.inure.dialogs.analytics.AnalyticsMenu
import app.simple.inure.dialogs.analytics.AnalyticsSort.Companion.showAnalyticsSort
import app.simple.inure.extensions.fragments.ScopedFragment
import app.simple.inure.popups.charts.PopupChartEntry
import app.simple.inure.popups.charts.PopupInstallerChartEntry
Expand All @@ -39,6 +41,7 @@ import com.github.mikephil.charting.utils.ColorTemplate
class Analytics : ScopedFragment() {

private lateinit var scrollView: PaddingAwareNestedScrollView
private lateinit var filterStyle: TypeFaceTextView
private lateinit var minSdkHeading: TypeFaceTextView
private lateinit var minimumOsPie: ThemePieChart
private lateinit var targetOsPie: ThemePieChart
Expand All @@ -60,6 +63,7 @@ class Analytics : ScopedFragment() {
val view = inflater.inflate(R.layout.fragment_analytics, container, false)

scrollView = view.findViewById(R.id.scroll_view)
filterStyle = view.findViewById(R.id.filter_style)
minSdkHeading = view.findViewById(R.id.min_sdk_heading)
minimumOsPie = view.findViewById(R.id.minimum_os_pie)
targetOsPie = view.findViewById(R.id.target_os_pie)
Expand All @@ -80,10 +84,12 @@ class Analytics : ScopedFragment() {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

setFilterStyle()
startPostponedEnterTransition()

bottomRightCornerMenu?.initBottomMenuWithScrollView(
BottomMenuConstants.getGenericBottomMenuItems(), scrollView) { id, _ ->
BottomMenuConstants.getAllAppsBottomMenuItems(), scrollView) { id, _ ->
when (id) {
R.drawable.ic_settings -> {
AnalyticsMenu.newInstance()
Expand All @@ -96,6 +102,9 @@ class Analytics : ScopedFragment() {
showLoader(manualOverride = true)
analyticsViewModel.refreshPackageData()
}
R.drawable.ic_filter -> {
childFragmentManager.showAnalyticsSort()
}
}
}

Expand Down Expand Up @@ -232,7 +241,8 @@ class Analytics : ScopedFragment() {
}
})

packageTypeAdapter = AdapterLegend(it.first, ColorTemplate.PASTEL_COLORS.toMutableList().toArrayList()) { pieEntry, longPressed ->
packageTypeAdapter = AdapterLegend(
it.first, ColorTemplate.PASTEL_COLORS.toMutableList().toArrayList()) { pieEntry, longPressed ->
if (longPressed) {
packageTypePie.highlightValue(Highlight(
it.first.indexOf(pieEntry).toFloat(),
Expand Down Expand Up @@ -301,12 +311,37 @@ class Analytics : ScopedFragment() {
}
}

private fun setFilterStyle() {
filterStyle.text = when (AnalyticsPreferences.getApplicationType()) {
SortConstant.USER -> {
getString(R.string.user)
}
SortConstant.SYSTEM -> {
getString(R.string.system)
}
SortConstant.BOTH -> {
with(StringBuilder()) {
append(getString(R.string.user))
append(" | ")
append(getString(R.string.system))
}
}
else -> {
getString(R.string.unknown)
}
}
}

override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
super.onSharedPreferenceChanged(sharedPreferences, key)
when (key) {
AnalyticsPreferences.SDK_VALUE -> {
analyticsViewModel.refreshPackageData()
}
AnalyticsPreferences.APPLICATION_TYPE -> {
analyticsViewModel.refreshPackageData()
setFilterStyle()
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app.simple.inure.viewmodels.panels

import android.app.Application
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.os.Build
import androidx.annotation.RequiresApi
Expand All @@ -12,13 +13,15 @@ import app.simple.inure.apk.utils.PackageUtils.getInstallerPackageName
import app.simple.inure.apk.utils.PackageUtils.safeApplicationInfo
import app.simple.inure.constants.Colors
import app.simple.inure.constants.InstallerColors
import app.simple.inure.constants.SortConstant
import app.simple.inure.extensions.viewmodels.PackageUtilsViewModel
import app.simple.inure.preferences.AnalyticsPreferences
import app.simple.inure.util.ConditionUtils.isNotZero
import app.simple.inure.util.SDKUtils
import com.github.mikephil.charting.data.PieEntry
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.stream.Collectors

class AnalyticsViewModel(application: Application) : PackageUtilsViewModel(application) {

Expand Down Expand Up @@ -177,13 +180,31 @@ class AnalyticsViewModel(application: Application) : PackageUtilsViewModel(appli
}

override fun onAppsLoaded(apps: ArrayList<PackageInfo>) {
val filteredApps = filterAppsByType(apps)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
loadMinimumOsData(apps)
loadMinimumOsData(filteredApps)
}

loadTargetOsData(apps)
loadPackageTypeData(apps)
loadInstallerData(apps)
loadTargetOsData(filteredApps)
loadPackageTypeData(filteredApps)
loadInstallerData(filteredApps)
}

private fun filterAppsByType(apps: ArrayList<PackageInfo>): ArrayList<PackageInfo> {
return when (AnalyticsPreferences.getApplicationType()) {
SortConstant.SYSTEM -> {
apps.parallelStream().filter { packageInfo ->
packageInfo.safeApplicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0
}.collect(Collectors.toList()) as ArrayList<PackageInfo>
}
SortConstant.USER -> {
apps.parallelStream().filter { packageInfo ->
packageInfo.safeApplicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0
}.collect(Collectors.toList()) as ArrayList<PackageInfo>
}
else -> apps
}
}

override fun onAppUninstalled(packageName: String?) {
Expand Down
58 changes: 58 additions & 0 deletions app/src/main/res/layout/dialog_sort_analytics.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false">

<app.simple.inure.decorations.corners.DynamicCornerLinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@android:color/transparent"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_margin="@dimen/dialog_padding"
android:orientation="vertical"
android:padding="@dimen/dialog_padding">

<app.simple.inure.decorations.typeface.TypeFaceTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/application_type"
android:textSize="@dimen/preferences_title_text_size"
android:layout_marginTop="5dp"
app:appFontStyle="bold"
app:textColorStyle="primary" />

<com.google.android.material.chip.ChipGroup
android:id="@+id/application_type_chip_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:chipSpacingHorizontal="5dp"
app:chipSpacingVertical="@dimen/chip_vertical_spacing"
app:selectionRequired="true"
app:singleSelection="true">

<app.simple.inure.decorations.views.Chip
android:id="@+id/both"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/both" />

<app.simple.inure.decorations.views.Chip
android:id="@+id/system"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/system" />

<app.simple.inure.decorations.views.Chip
android:id="@+id/user"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/user" />

</com.google.android.material.chip.ChipGroup>

</app.simple.inure.decorations.corners.DynamicCornerLinearLayout>
</FrameLayout>
14 changes: 13 additions & 1 deletion app/src/main/res/layout/fragment_analytics.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,21 @@
app:appFontStyle="light"
app:textColorStyle="heading" />


</LinearLayout>

<app.simple.inure.decorations.typeface.TypeFaceTextView
android:id="@+id/filter_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:drawablePadding="@dimen/popup_padding"
android:layout_marginHorizontal="@dimen/panel_item_padding"
android:textSize="@dimen/info_text_small"
app:appFontStyle="regular"
app:drawableStartCompat="@drawable/ic_filter_16dp"
app:drawableTintStyle="secondary"
app:textColorStyle="tertiary" />

<app.simple.inure.decorations.typeface.TypeFaceTextView
android:id="@+id/min_sdk_heading"
android:layout_width="match_parent"
Expand Down

0 comments on commit d042cf4

Please sign in to comment.