Skip to content

Commit

Permalink
Feat: Added work profile support with icon.
Browse files Browse the repository at this point in the history
Signed-off-by: HeCodes2Much <wayne6324@gmail.com>
  • Loading branch information
CreativeCodeCat committed May 28, 2024
1 parent bbe9c98 commit e61a989
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import android.graphics.drawable.AdaptiveIconDrawable
import android.net.Uri
import android.os.Build
import android.os.UserHandle
import android.os.UserManager
import android.provider.AlarmClock
import android.provider.CalendarContract
import android.provider.Settings
Expand Down Expand Up @@ -297,6 +298,16 @@ fun Context.searchCustomSearchEngine(searchQuery: String? = null): Boolean {
return true
}

fun Context.isWorkProfileEnabled(): Boolean {
val userManager = getSystemService(Context.USER_SERVICE) as? UserManager
return if (userManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val profiles = userManager.userProfiles
profiles.size > 1
} else {
false
}
}

fun Context.backupSharedPreferences(backupFileName: String) {
val sharedPreferences: SharedPreferences =
this.getSharedPreferences(Constants.PREFS_FILENAME, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface AppInfoDAO {
suspend fun update(app: AppInfo)

@Delete
suspend fun delete(app: AppInfo)
fun delete(app: AppInfo)

@Query("SELECT * FROM app ORDER BY app_name COLLATE NOCASE ASC")
fun getAllApps(): List<AppInfo>
Expand Down Expand Up @@ -73,9 +73,12 @@ interface AppInfoDAO {
@Query("SELECT * FROM app WHERE is_favorite = 1")
fun getFavoriteAppInfo(): List<AppInfo>

@Query("SELECT * FROM app WHERE package_name = :packageName")
@Query("SELECT * FROM app WHERE package_name = :packageName AND is_work = 0")
suspend fun getAppByPackageName(packageName: String): AppInfo?

@Query("SELECT * FROM app WHERE package_name = :packageName AND is_work = 1")
suspend fun getAppByPackageNameWork(packageName: String): AppInfo?

private fun logUpdate(message: String, appInfo: AppInfo) {
// You can replace this with a logging library like Timber for more advanced logging capabilities.
Log.d(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ data class AppInfo(
@ColumnInfo(name = "is_lock")
var lock: Boolean,

@ColumnInfo(name = "is_work")
var work: Boolean,

@ColumnInfo(name = "create_time")
var createTime: String = "",
var createTime: String,

@ColumnInfo(name = "app_order")
var appOrder: Int = -1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ internal open class OnSwipeTouchListener(c: Context?) : OnTouchListener {
if (diffY < 0) onSwipeUp() else onSwipeDown()
}
}
} catch (exception: Exception) {
exception.printStackTrace()
} catch (exception: NullPointerException) {
return false
}
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@ package com.github.droidworksstudio.launcher.repository
import android.content.Context
import android.content.pm.LauncherApps
import android.content.pm.PackageManager
import android.os.Build
import android.os.UserHandle
import android.os.UserManager
import android.util.Log
import androidx.annotation.RequiresApi
import com.github.droidworksstudio.launcher.Constants
import com.github.droidworksstudio.launcher.data.dao.AppInfoDAO
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.withContext
import java.lang.reflect.Method
import java.time.LocalDateTime
import javax.inject.Inject


class AppInfoRepository @Inject constructor(
private val appDao: AppInfoDAO
private val appDao: AppInfoDAO,
) {

@Inject
Expand Down Expand Up @@ -98,7 +103,9 @@ class AppInfoRepository @Inject constructor(
packages
}

suspend fun initInstalledAppInfo(context: Context): List<AppInfo> = withContext(Dispatchers.IO) {
@RequiresApi(Build.VERSION_CODES.O)
suspend fun initInstalledAppInfo(context: Context): List<AppInfo> =
withContext(Dispatchers.IO) {
val appList: MutableList<AppInfo> = mutableListOf()

val allApps = appDao.getAllAppsFlow().firstOrNull()
Expand All @@ -109,29 +116,69 @@ class AppInfoRepository @Inject constructor(
val launcherApps =
context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps

val excludedPackageNames = mutableListOf(Constants.PACKAGE_NAME,Constants.PACKAGE_NAME_DEBUG)
val excludedPackageNames =
mutableListOf(Constants.PACKAGE_NAME, Constants.PACKAGE_NAME_DEBUG)

val getIdentifierMethod: Method =
UserHandle::class.java.getDeclaredMethod("getIdentifier")

val newAppList: List<AppInfo> = userManager.userProfiles
.flatMap { profile ->
launcherApps.getActivityList(null, profile)
.mapNotNull { app ->
val packageName = app.applicationInfo.packageName
if (packageName !in existingPackageNames && packageName !in excludedPackageNames) {
AppInfo(
appName = app.label.toString(),
packageName = packageName,
favorite = false,
hidden = false,
lock = false
)
} else {
val existingApp = getAppByPackageName(packageName)
existingApp?.let { appList.add(it) }
existingApp
}
// Invoke the getIdentifier method on the UserHandle instance
val userId = getIdentifierMethod.invoke(profile) as Int

when (userId) {
0 -> {
// Handle the case when profile is UserHandle{0}
launcherApps.getActivityList(null, profile)
.mapNotNull { app ->
val packageName = app.applicationInfo.packageName
val currentDateTime = LocalDateTime.now()
if (packageName !in existingPackageNames && packageName !in excludedPackageNames) {
AppInfo(
appName = app.label.toString(),
packageName = packageName,
favorite = false,
hidden = false,
lock = false,
createTime = currentDateTime.toString(),
work = false,
)
} else {
val existingApp = getAppByPackageName(packageName)
existingApp?.let { appList.add(it) }
existingApp
}
}
}

else -> {
// Handle other profiles
launcherApps.getActivityList(null, profile)
.mapNotNull { app ->
val packageName = app.applicationInfo.packageName
val currentDateTime = LocalDateTime.now()
if (packageName !in existingPackageNames && packageName !in excludedPackageNames) {
AppInfo(
appName = app.label.toString(),
packageName = packageName,
favorite = false,
hidden = false,
lock = false,
createTime = currentDateTime.toString(),
work = true,
)
} else {
val existingApp = getAppByPackageNameWork(packageName)
existingApp?.let { appList.add(it) }
existingApp
}
}
}
}
}


appDao.insertAll(newAppList.sortedBy { it.appName })
Log.d("Tag", "State: ${newAppList.sortedBy { it.appName }}")

Expand All @@ -142,6 +189,7 @@ class AppInfoRepository @Inject constructor(
appList
}

@RequiresApi(Build.VERSION_CODES.R)
suspend fun compareInstalledApp(): List<AppInfo> = withContext(Dispatchers.IO) {
val installedPackages = getInstalledPackages()
val uninstalledApps = mutableListOf<AppInfo>()
Expand Down Expand Up @@ -176,4 +224,8 @@ class AppInfoRepository @Inject constructor(
private suspend fun getAppByPackageName(packageName: String): AppInfo? {
return appDao.getAppByPackageName(packageName)
}

private suspend fun getAppByPackageNameWork(packageName: String): AppInfo? {
return appDao.getAppByPackageNameWork(packageName)
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
package com.github.droidworksstudio.launcher.ui.activities

import android.annotation.SuppressLint
import android.app.admin.DevicePolicyManager
import android.content.Intent
import android.content.pm.ActivityInfo
import android.os.Build
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
import android.widget.Toast
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
Expand All @@ -19,7 +17,6 @@ import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import com.github.droidworksstudio.ktx.isTablet
import com.github.droidworksstudio.launcher.Constants
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.ActivityMainBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
Expand Down Expand Up @@ -68,6 +65,7 @@ class MainActivity : AppCompatActivity() {

}

@RequiresApi(Build.VERSION_CODES.R)
private fun setupDataBase() {
lifecycleScope.launch {
viewModel.initializeInstalledAppInfo(this@MainActivity)
Expand Down Expand Up @@ -118,6 +116,7 @@ class MainActivity : AppCompatActivity() {
|| super.onSupportNavigateUp()
}

@RequiresApi(Build.VERSION_CODES.R)
override fun onResume() {
super.onResume()
backToHomeScreen()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ class DrawAdapter(
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

val appInfo = getItem(position)
(holder as DrawViewHolder).bind(appInfo)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.droidworksstudio.launcher.ui.drawer

import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.text.Spannable
import android.text.SpannableString
Expand All @@ -10,6 +11,7 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
Expand Down Expand Up @@ -64,7 +66,13 @@ class DrawFragment : Fragment(),

private val viewModel: AppViewModel by viewModels()

private val drawAdapter: DrawAdapter by lazy { DrawAdapter(this, this, preferenceHelper) }
private val drawAdapter: DrawAdapter by lazy {
DrawAdapter(
this,
this,
preferenceHelper
)
}

private lateinit var context: Context
override fun onCreateView(
Expand Down Expand Up @@ -98,6 +106,7 @@ class DrawFragment : Fragment(),
}
}

@RequiresApi(Build.VERSION_CODES.R)
private fun observeDrawerApps() {
viewModel.compareInstalledAppInfo()

Expand Down Expand Up @@ -242,12 +251,14 @@ class DrawFragment : Fragment(),
binding.searchViewText.hideKeyboard()
}

@RequiresApi(Build.VERSION_CODES.R)
override fun onResume() {
super.onResume()
observeDrawerApps()
if (preferenceHelper.automaticKeyboard) binding.searchViewText.showKeyboard()
}

@RequiresApi(Build.VERSION_CODES.R)
override fun onStart() {
super.onStart()
observeDrawerApps()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package com.github.droidworksstudio.launcher.ui.drawer

import android.util.Log
import android.view.Gravity
import android.view.View
import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.ktx.dpToPx
import com.github.droidworksstudio.ktx.isWorkProfileEnabled
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemDrawBinding
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
Expand All @@ -14,7 +20,9 @@ class DrawViewHolder(
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener,
private val preferenceHelper: PreferenceHelper
) :

RecyclerView.ViewHolder(binding.root) {

fun bind(appInfo: AppInfo) {
binding.apply {
val layoutParams = LinearLayoutCompat.LayoutParams(
Expand All @@ -30,7 +38,28 @@ class DrawViewHolder(
appDrawName.text = appInfo.appName
appDrawName.setTextColor(preferenceHelper.appColor)
appDrawName.textSize = preferenceHelper.appTextSize
Log.d("Tag", "Draw Adapter: ${appInfo.appName + appInfo.id}")
Log.d("Tag", "Draw Adapter: ${appInfo.appName + appInfo.id} | ${appInfo.work}")
val icon = AppCompatResources.getDrawable(appDrawName.context, R.drawable.work_profile)
val px = preferenceHelper.appTextSize.toInt().dpToPx()
icon?.setBounds(0, 0, px, px)
if (appInfo.work) {
val appLabelGravity = preferenceHelper.homeAppAlignment

if (appLabelGravity == Gravity.START) {
appDrawName.setCompoundDrawables(icon, null, null, null)
} else {
appDrawName.setCompoundDrawables(null, null, icon, null)
}
appDrawName.compoundDrawablePadding = 20
if (!appDrawName.context.isWorkProfileEnabled()) {
appDrawName.visibility = View.GONE
}
} else {

// If appInfo.work is false, remove the drawable
appDrawName.setCompoundDrawables(null, null, null, null)
appDrawName.compoundDrawablePadding = 0
}
}

itemView.setOnClickListener {
Expand Down
Loading

0 comments on commit e61a989

Please sign in to comment.