Initial commit.

This commit is contained in:
HeCodes2Much
2024-05-07 09:03:12 +01:00
commit 12d95a4db2
141 changed files with 9273 additions and 0 deletions

111
app/build.gradle.kts Normal file
View File

@@ -0,0 +1,111 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("kotlin-android")
id("kotlin-kapt")
id("kotlin-parcelize")
id("com.google.dagger.hilt.android")
id("dagger.hilt.android.plugin")
}
android {
namespace = "com.github.droidworksstudio.launcher"
compileSdk = 34
defaultConfig {
applicationId = "app.easy.launcher"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "0.0.1"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
getByName("debug") {
isMinifyEnabled = false
isShrinkResources = false
isDebuggable = true
applicationIdSuffix = ".debug"
proguardFiles (getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
resValue("string", "app_name", "EasyLauncher Debug")
}
getByName("release") {
isMinifyEnabled = false
isShrinkResources = false
proguardFiles (getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
resValue("string", "app_name", "EasyLauncher")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
buildFeatures {
viewBinding = true
}
applicationVariants.all {
if (buildType.name == "release") {
outputs.all {
val output = this as? com.android.build.gradle.internal.api.BaseVariantOutputImpl
if (output?.outputFileName?.endsWith(".apk") == true) {
output.outputFileName =
"${defaultConfig.applicationId}_v${defaultConfig.versionName}-Signed.apk"
}
}
}
if (buildType.name == "debug") {
outputs.all {
val output = this as? com.android.build.gradle.internal.api.BaseVariantOutputImpl
if (output?.outputFileName?.endsWith(".apk") == true) {
output.outputFileName =
"${defaultConfig.applicationId}_v${defaultConfig.versionName}-Debug.apk"
}
}
}
}
}
dependencies {
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")
implementation("androidx.navigation:navigation-ui-ktx:2.7.7")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
implementation("androidx.lifecycle:lifecycle-process:2.7.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("androidx.work:work-runtime-ktx:2.9.0")
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("androidx.viewpager2:viewpager2:1.1.0-rc01")
debugImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
//room
val roomVersion = "2.6.1"
implementation("androidx.room:room-runtime:$roomVersion")
implementation("androidx.room:room-ktx:$roomVersion")
//noinspection KaptUsageInsteadOfKsp
kapt("androidx.room:room-compiler:$roomVersion")
//hilt
val hiltVersion = "2.51.1"
implementation("com.google.dagger:hilt-android:$hiltVersion")
kapt("com.google.dagger:hilt-compiler:$hiltVersion")
//biometric
implementation("androidx.biometric:biometric-ktx:1.2.0-alpha05")
//color picker
implementation("net.mm2d.color-chooser:color-chooser:0.7.3")
}

21
app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<queries>
<intent>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent>
</queries>
<application
android:name=".Application"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/app_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.Launcher"
tools:targetApi="31">
<activity
android:name=".ui.activities.SettingsActivity"
android:exported="false" />
<activity
android:name=".ui.activities.LauncherActivity"
android:enabled="false"
android:excludeFromRecents="true"
android:exported="false"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".ui.activities.MainActivity"
android:configChanges="uiMode"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity=""
android:windowSoftInputMode="stateHidden"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.activities.FakeHomeActivity"
android:enabled="false"
android:launchMode="singleTask"
android:windowSoftInputMode="stateHidden"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".listener.DeviceAdmin"
android:permission="android.permission.BIND_DEVICE_ADMIN"
android:exported="false">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/policies" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
<service
android:name=".accessibility.MyAccessibilityService"
android:exported="false"
android:label="@string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service" />
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
</service>
</application>
</manifest>

View File

@@ -0,0 +1,12 @@
package com.github.droidworksstudio.launcher
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class Application: Application() {
override fun onCreate() {
super.onCreate()
}
}

View File

@@ -0,0 +1,46 @@
package com.github.droidworksstudio.launcher
object Constants {
const val PACKAGE_NAME = "com.github.droidworksstudio.launcher"
const val PREFS_FILENAME = "droidworksstudioLauncher.pref"
const val FIRST_LAUNCH = "FIRST_LAUNCH"
const val SHOW_DATE = "SHOW_DATE"
const val SHOW_TIME = "SHOW_TIME"
const val SHOW_DAILY_WORD = "SHOW_DAILY_WORD"
const val SHOW_BATTERY = "SHOW_BATTERY"
const val SHOW_STATUS_BAR = "SHOW_STATUS_BAR"
const val DOUBLE_TAP_LOCK = "DOUBLE_TAP_LOCK"
const val DATE_COLOR = "DATE_COLOR"
const val TIME_COLOR = "TIME_COLOR"
const val BATTERY_COLOR = "BATTERY_COLOR"
const val DAILY_WORD_COLOR = "DAILY_WORD_COLOR"
const val APP_COLOR = "APP_COLOR"
const val DATE_TEXT_SIZE = "DATE_TEXT_SIZE"
const val TIME_TEXT_SIZE = "TIME_TEXT_SIZE"
const val APP_TEXT_SIZE = "APP_TEXT_SIZE"
const val SHOW_APP_ICON = "SHOW_APP_ICON"
const val AUTOMATIC_KEYBOARD = "AUTOMATIC_KEYBOARD"
const val AUTOMATIC_OPEN_APP = "AUTOMATIC_OPEN_APP"
const val HOME_DATE_ALIGNMENT = "HOME_DATE_ALIGNMENT"
const val HOME_TIME_ALIGNMENT = "HOME_TIME_ALIGNMENT"
const val HOME_APP_ALIGNMENT = "HOME_APP_ALIGNMENT"
const val HOME_DAILY_WORD_ALIGNMENT = "HOME_DAILY_WORD_ALIGNMENT"
const val HOME_DRAW_ALIGNMENT = "HOME_DRAW_ALIGNMENT"
const val HOME_BATTERY_ALIGNMENT = "HOME_BATTERY_ALIGNMENT"
const val NOTIFICATION_SERVICE = "statusbar"
const val NOTIFICATION_MANAGER = "android.app.StatusBarManager"
const val NOTIFICATION_METHOD = "expandNotificationsPanel"
const val QUICKSETTINGS_SERVICE = "statusbar"
const val QUICKSETTINGS_MANAGER = "android.app.StatusBarManager"
const val QUICKSETTINGS_METHOD = "expandSettingsPanel"
const val REQUEST_CODE_ENABLE_ADMIN = 123
}

View File

@@ -0,0 +1,48 @@
package com.github.droidworksstudio.launcher.accessibility
import android.accessibilityservice.AccessibilityService
import android.accessibilityservice.AccessibilityServiceInfo
import android.content.Intent
import android.os.Build
import android.view.accessibility.AccessibilityEvent
import androidx.annotation.RequiresApi
import java.lang.ref.WeakReference
class MyAccessibilityService : AccessibilityService() {
private var info: AccessibilityServiceInfo = AccessibilityServiceInfo()
override fun onServiceConnected() {
mInstance = WeakReference(this)
info.apply {
eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED or AccessibilityEvent.TYPE_VIEW_FOCUSED
feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC
notificationTimeout = 100
}
this.serviceInfo = info
}
override fun onUnbind(intent: Intent?): Boolean {
mInstance = WeakReference(null)
return super.onUnbind(intent)
}
override fun onInterrupt() {}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {}
@RequiresApi(Build.VERSION_CODES.P)
fun lockScreen(): Boolean = performGlobalAction(GLOBAL_ACTION_LOCK_SCREEN)
companion object {
private var mInstance: WeakReference<MyAccessibilityService> = WeakReference(null)
fun instance(): MyAccessibilityService? {
return mInstance.get()
}
}
}

View File

@@ -0,0 +1,12 @@
package com.github.droidworksstudio.launcher.data
import androidx.room.Database
import androidx.room.RoomDatabase
import com.github.droidworksstudio.launcher.data.dao.AppInfoDAO
import com.github.droidworksstudio.launcher.data.entities.AppInfo
@Database(entities = [AppInfo::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun appDao(): AppInfoDAO
}

View File

@@ -0,0 +1,76 @@
package com.github.droidworksstudio.launcher.data.dao
import android.util.Log
import androidx.room.*
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import kotlinx.coroutines.flow.Flow
@Dao
interface AppInfoDAO {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(app: AppInfo)
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertAll(apps: List<AppInfo>)
@Update
suspend fun update(app: AppInfo)
@Delete
suspend fun delete(app: AppInfo)
@Query("SELECT * FROM app ORDER BY app_name ASC")
fun getAllApps(): List<AppInfo>
@Query("SELECT * FROM app ORDER BY app_name ASC")
fun getAllAppsFlow(): Flow<List<AppInfo>>
@Query("SELECT * FROM app WHERE is_hidden = 0 ORDER BY app_name ASC")
fun getDrawAppsFlow(): Flow<List<AppInfo>>
@Query("SELECT * FROM app WHERE is_favorite = 1 ORDER BY app_order ASC, id ASC")
fun getFavoriteAppsFlow(): Flow<List<AppInfo>>
@Query("SELECT * FROM app WHERE is_hidden = 1 ORDER BY id ASC")
fun getHiddenAppsFlow(): Flow<List<AppInfo>>
@Query("SELECT * FROM app WHERE is_lock = 1 ORDER BY app_order ASC")
fun getLockAppsFlow(): Flow<List<AppInfo>>
@Query("SELECT * FROM app WHERE app_name LIKE :query AND is_hidden = 0")
fun searchApps(query: String?): Flow<List<AppInfo>>
@Update
fun updateAppInfo(appInfo: AppInfo)
@Update
suspend fun updateAppOrder(appInfo: List<AppInfo>)
@Transaction
suspend fun updateAppName(appInfo: AppInfo, newAppName: String) {
appInfo.appName = newAppName
update(appInfo)
Log.d("Tag", "${appInfo.appName} : Repo Order: ${appInfo.appOrder}")
}
@Transaction
suspend fun updateAppHidden(appInfo: AppInfo, appHidden: Boolean) {
appInfo.hidden = appHidden
update(appInfo)
Log.d("Tag", "${appInfo.appName} : Repo Order: ${appInfo.hidden}")
}
@Transaction
suspend fun updateLockApp(appInfo: AppInfo, appLock: Boolean) {
appInfo.lock = appLock
update(appInfo)
Log.d("Tag", "${appInfo.appName} : Repo Order: ${appInfo.lock}")
}
@Query("SELECT MAX(`app_order`) FROM app")
fun getMaxOrder(): Int
@Query("SELECT * FROM app WHERE is_favorite = 1")
fun getFavoriteAppInfo(): List<AppInfo>
@Query("SELECT * FROM app WHERE package_name = :packageName")
suspend fun getAppByPackageName(packageName: String): AppInfo?
}

View File

@@ -0,0 +1,34 @@
package com.github.droidworksstudio.launcher.data.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "app")
data class AppInfo(
@PrimaryKey(autoGenerate = true)
@field:ColumnInfo(name = "id")
var id: Int = 0,
@field:ColumnInfo(name = "app_name")
var appName: String,
@field:ColumnInfo(name = "package_name")
var packageName: String,
@field:ColumnInfo(name = "is_favorite")
var favorite: Boolean,
@field:ColumnInfo(name = "is_hidden")
var hidden: Boolean,
@ColumnInfo(name = "is_lock")
var lock: Boolean,
@ColumnInfo(name = "create_time")
var createTime: String = "",
@ColumnInfo(name = "app_order")
var appOrder: Int = -1
)

View File

@@ -0,0 +1,65 @@
package com.github.droidworksstudio.launcher.di
import android.content.Context
import android.content.pm.PackageManager
import androidx.room.Room
import com.github.droidworksstudio.launcher.data.AppDatabase
import com.github.droidworksstudio.launcher.data.dao.AppInfoDAO
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.BottomDialogHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.scopes.ViewModelScoped
@Module
@InstallIn(ViewModelComponent::class)
object DatabaseModule {
@Provides
@ViewModelScoped
fun provideLocalDatabase(
@ApplicationContext context: Context
): AppDatabase =
Room.databaseBuilder(
context,
AppDatabase::class.java,
"app_database"
).build()
@Provides
@ViewModelScoped
fun provideAppDao(appDatabase: AppDatabase): AppInfoDAO = appDatabase.appDao()
@Provides
@ViewModelScoped
fun providePackageManager(@ApplicationContext context: Context): PackageManager {
return context.packageManager
}
@Provides
@ViewModelScoped
fun providePreferenceHelper(@ApplicationContext context: Context): PreferenceHelper {
return PreferenceHelper(context)
}
@Provides
@ViewModelScoped
fun provideContext(@ApplicationContext context: Context): Context {
return context
}
@Provides
@ViewModelScoped
fun provideAppHelper(): AppHelper {
return AppHelper()
}
@Provides
@ViewModelScoped
fun provideBottomDialogHelper(): BottomDialogHelper {
return BottomDialogHelper()
}
}

View File

@@ -0,0 +1,249 @@
package com.github.droidworksstudio.launcher.helper
import android.annotation.SuppressLint
import android.app.SearchManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.net.Uri
import android.os.Build
import android.provider.AlarmClock
import android.provider.CalendarContract
import android.provider.Settings
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.Window
import android.view.WindowInsets
import android.view.inputmethod.InputMethodManager
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.widget.LinearLayoutCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.github.droidworksstudio.launcher.Constants
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.accessibility.MyAccessibilityService
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.ui.activities.FakeHomeActivity
import javax.inject.Inject
class AppHelper @Inject constructor() {
fun resetDefaultLauncher(context: Context) {
try {
val packageManager = context.packageManager
val componentName = ComponentName(context, FakeHomeActivity::class.java)
packageManager.setComponentEnabledSetting(
componentName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
val selector = Intent(Intent.ACTION_MAIN)
selector.addCategory(Intent.CATEGORY_HOME)
context.startActivity(selector)
packageManager.setComponentEnabledSetting(
componentName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
} catch (e: Exception) {
e.printStackTrace()
}
}
@SuppressLint("WrongConstant", "PrivateApi")
fun expandNotificationDrawer(context: Context) {
try {
val statusBarService = context.getSystemService(Constants.NOTIFICATION_SERVICE)
val statusBarManager = Class.forName(Constants.NOTIFICATION_MANAGER)
val method = statusBarManager.getMethod(Constants.NOTIFICATION_METHOD)
method.invoke(statusBarService)
} catch (exception: Exception) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// initActionService(context)?.openNotifications()
// }
exception.printStackTrace()
}
}
@SuppressLint("WrongConstant", "PrivateApi")
private fun expandQuickSettings(context: Context) {
try {
val statusBarService = context.getSystemService(Constants.QUICKSETTINGS_SERVICE)
val statusBarManager = Class.forName(Constants.QUICKSETTINGS_MANAGER)
val method = statusBarManager.getMethod(Constants.QUICKSETTINGS_METHOD)
method.invoke(statusBarService)
} catch (exception: Exception) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// initActionService(context)?.openQuickSettings()
// }
exception.printStackTrace()
}
}
fun searchView(context: Context) {
val intent = Intent(Intent.ACTION_WEB_SEARCH)
intent.putExtra(SearchManager.QUERY, "")
context.startActivity(intent)
}
fun dayNightMod(context: Context, view: View) {
when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> {
view.setBackgroundColor(context.resources.getColor(R.color.whiteTrans25))
}
Configuration.UI_MODE_NIGHT_NO -> {
view.setBackgroundColor(context.resources.getColor(R.color.blackTrans50))
}
}
}
fun updateUI(view: View, gravity: Int, selectColor: Int, textSize: Float, isVisible: Boolean) {
val layoutParams = view.layoutParams as LinearLayoutCompat.LayoutParams
layoutParams.gravity = gravity
view.layoutParams = layoutParams
if (view is TextView) {
view.setTextColor(selectColor)
view.textSize = textSize
view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
view.isClickable = if (isVisible) view.isClickable else !view.isClickable
}
}
fun launchApp(context: Context, appInfo: AppInfo) {
val intent = context.packageManager.getLaunchIntentForPackage(appInfo.packageName)
if (intent != null) {
context.startActivity(intent)
} else {
showToast(context, "Failed to open the application")
}
}
fun launchClock(context: Context) {
try {
val intent = Intent(AlarmClock.ACTION_SHOW_ALARMS)
context.startActivity(intent)
} catch (e: Exception) {
Log.e("launchClock", "Error launching clock app: ${e.message}")
}
}
fun launchCalendar(context: Context) {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = CalendarContract.CONTENT_URI
try {
context.startActivity(intent)
} catch (e: Exception) {
val pickerIntent = Intent(Intent.ACTION_MAIN)
pickerIntent.addCategory(Intent.CATEGORY_APP_CALENDAR)
try {
context.startActivity(pickerIntent)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
fun unInstallApp(context: Context, appInfo: AppInfo) {
val intent = Intent(Intent.ACTION_DELETE)
intent.data = Uri.parse("package:${appInfo.packageName}")
context.startActivity(intent)
}
fun appInfo(context: Context, appInfo: AppInfo) {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.fromParts("package", appInfo.packageName, null)
context.startActivity(intent)
}
fun gravityToString(gravity: Int): String? {
return when (gravity) {
Gravity.CENTER -> "CENTER"
Gravity.START -> "LEFT"
Gravity.END -> "RIGHT"
Gravity.TOP -> "TOP"
Gravity.BOTTOM -> "BOTTOM"
else -> null
}
}
fun getGravityFromSelectedItem(selectedItem: String): Int {
return when (selectedItem) {
"Left" -> Gravity.START
"Center" -> Gravity.CENTER
"Right" -> Gravity.END
else -> Gravity.START
}
}
fun showToast(context: Context,message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
fun showStatusBar(window: Window) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.insetsController?.show(WindowInsets.Type.statusBars())
} else
@Suppress("DEPRECATION", "InlinedApi")
window.decorView.apply {
systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}
}
fun hideStatusBar(window: Window) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
window.insetsController?.hide(WindowInsets.Type.statusBars())
else {
@Suppress("DEPRECATION")
window.decorView.apply {
systemUiVisibility =
View.SYSTEM_UI_FLAG_IMMERSIVE or View.SYSTEM_UI_FLAG_FULLSCREEN
}
}
}
fun showSoftKeyboard(context: Context, view: View) {
if (view.requestFocus()) {
val inputMethodManager: InputMethodManager =
context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
}
}
fun hideKeyboard(context: Context, view: View) {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
fun View.hideKeyboard() {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(this.windowToken, 0)
}
fun enableAppAsAccessibilityService(context: Context, accessibilityState: Boolean) {
val myAccessibilityService = MyAccessibilityService.instance()
val state: String = if (myAccessibilityService != null) {
context.getString(R.string.accessibility_settings_disable)
}else{
context.getString(R.string.accessibility_settings_enable)
}
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(R.string.accessibility_settings_title)
builder.setMessage(R.string.accessibility_service_desc)
builder.setPositiveButton(state) { _, _ ->
val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
context.startActivity(intent)
}
.setNegativeButton(android.R.string.cancel) { dialog, _ -> dialog.dismiss() }
.show()
}
}

View File

@@ -0,0 +1,34 @@
package com.github.droidworksstudio.launcher.helper
import android.app.Dialog
import android.graphics.Color
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.view.WindowManager
import javax.inject.Inject
class BottomDialogHelper @Inject constructor() {
fun setupDialogStyle(dialog: Dialog?) {
val window = dialog?.window
if (window != null) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.statusBarColor = Color.TRANSPARENT
}
}
fun getColorText(color: Int): SpannableString {
val colorText = "#${Integer.toHexString(color)}"
val spannableString = SpannableString(colorText)
spannableString.setSpan(
ForegroundColorSpan(color),
0,
colorText.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
return spannableString
}
}

View File

@@ -0,0 +1,52 @@
package com.github.droidworksstudio.launcher.helper
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import javax.inject.Inject
class FingerprintHelper @Inject constructor(private val fragment: Fragment) {
private lateinit var callback: Callback
interface Callback {
fun onAuthenticationSucceeded(appInfo: AppInfo)
fun onAuthenticationFailed()
fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?)
}
fun startFingerprintAuth(appInfo: AppInfo, callback: Callback) {
this.callback = callback
val authenticationCallback = object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
callback.onAuthenticationSucceeded(appInfo)
}
override fun onAuthenticationFailed() {
callback.onAuthenticationFailed()
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence) {
callback.onAuthenticationError(errorCode, errorMessage)
}
}
val executor = ContextCompat.getMainExecutor(fragment.requireContext())
val biometricPrompt = BiometricPrompt(fragment, executor, authenticationCallback)
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle(fragment.getString(R.string.authentication_title))
.setNegativeButtonText(fragment.getString(R.string.authentication_cancel))
.build()
val canAuthenticate = BiometricManager.from(fragment.requireContext())
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
if (canAuthenticate == BiometricManager.BIOMETRIC_SUCCESS) {
biometricPrompt.authenticate(promptInfo)
}
}
}

View File

@@ -0,0 +1,99 @@
package com.github.droidworksstudio.launcher.helper
import android.content.Context
import android.content.SharedPreferences
import android.view.Gravity
import com.github.droidworksstudio.launcher.Constants
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
class PreferenceHelper @Inject constructor(@ApplicationContext context: Context) {
private val prefs: SharedPreferences = context.getSharedPreferences(Constants.PREFS_FILENAME, 0)
var firstLaunch: Boolean
get() = prefs.getBoolean(Constants.FIRST_LAUNCH, true)
set(value) = prefs.edit().putBoolean(Constants.FIRST_LAUNCH, value).apply()
var showStatusBar: Boolean
get() = prefs.getBoolean(Constants.SHOW_STATUS_BAR, true)
set(value) = prefs.edit().putBoolean(Constants.SHOW_STATUS_BAR, value).apply()
var showTime: Boolean
get() = prefs.getBoolean(Constants.SHOW_TIME, true)
set(value) = prefs.edit().putBoolean(Constants.SHOW_TIME, value).apply()
var showDate: Boolean
get() = prefs.getBoolean(Constants.SHOW_DATE, true)
set(value) = prefs.edit().putBoolean(Constants.SHOW_DATE, value).apply()
var showBattery: Boolean
get() = prefs.getBoolean(Constants.SHOW_BATTERY, true)
set(value) = prefs.edit().putBoolean(Constants.SHOW_BATTERY, value).apply()
var showDailyWord: Boolean
get() = prefs.getBoolean(Constants.SHOW_DAILY_WORD, true)
set(value) = prefs.edit().putBoolean(Constants.SHOW_DAILY_WORD, value).apply()
var dateColor: Int
get() = prefs.getInt(Constants.DATE_COLOR, 0xFFFFFFFF.toInt())
set(value) = prefs.edit().putInt(Constants.DATE_COLOR, value).apply()
var timeColor: Int
get() = prefs.getInt(Constants.TIME_COLOR, 0xFFFFFFFF.toInt())
set(value) = prefs.edit().putInt(Constants.TIME_COLOR, value).apply()
var batteryColor: Int
get() = prefs.getInt(Constants.BATTERY_COLOR, 0xFFFFFFFF.toInt())
set(value) = prefs.edit().putInt(Constants.BATTERY_COLOR, value).apply()
var dailyWordColor: Int
get() = prefs.getInt(Constants.DAILY_WORD_COLOR, 0xFFFFFFFF.toInt())
set(value) = prefs.edit().putInt(Constants.DAILY_WORD_COLOR, value).apply()
var appColor: Int
get() = prefs.getInt(Constants.APP_COLOR, 0xFFFFFFFF.toInt())
set(value) = prefs.edit().putInt(Constants.APP_COLOR, value).apply()
var showAppIcon: Boolean
get() = prefs.getBoolean(Constants.SHOW_APP_ICON, true)
set(value) = prefs.edit().putBoolean(Constants.SHOW_APP_ICON, value).apply()
var automaticKeyboard: Boolean
get() = prefs.getBoolean(Constants.AUTOMATIC_KEYBOARD, true)
set(value) = prefs.edit().putBoolean(Constants.AUTOMATIC_KEYBOARD, value).apply()
var automaticOpenApp: Boolean
get() = prefs.getBoolean(Constants.AUTOMATIC_OPEN_APP, false)
set(value) = prefs.edit().putBoolean(Constants.AUTOMATIC_OPEN_APP, value).apply()
var homeAppAlignment: Int
get() = prefs.getInt(Constants.HOME_APP_ALIGNMENT, Gravity.START)
set(value) = prefs.edit().putInt(Constants.HOME_APP_ALIGNMENT, value).apply()
var homeDateAlignment: Int
get() = prefs.getInt(Constants.HOME_DATE_ALIGNMENT, Gravity.START)
set(value) = prefs.edit().putInt(Constants.HOME_DATE_ALIGNMENT, value).apply()
var homeTimeAlignment: Int
get() = prefs.getInt(Constants.HOME_TIME_ALIGNMENT, Gravity.START)
set(value) = prefs.edit().putInt(Constants.HOME_TIME_ALIGNMENT, value).apply()
var homeDailyWordAlignment: Int
get() = prefs.getInt(Constants.HOME_DAILY_WORD_ALIGNMENT, Gravity.START)
set(value) = prefs.edit().putInt(Constants.HOME_DAILY_WORD_ALIGNMENT,value).apply()
var dateTextSize: Float
get() = prefs.getFloat(Constants.DATE_TEXT_SIZE, 32f)
set(value) = prefs.edit().putFloat(Constants.DATE_TEXT_SIZE, value).apply()
var timeTextSize: Float
get() = prefs.getFloat(Constants.TIME_TEXT_SIZE, 48f)
set(value) = prefs.edit().putFloat(Constants.TIME_TEXT_SIZE, value).apply()
var appTextSize: Float
get() = prefs.getFloat(Constants.APP_TEXT_SIZE, 24f)
set(value) = prefs.edit().putFloat(Constants.APP_TEXT_SIZE, value).apply()
var tapLockScreen: Boolean
get() = prefs.getBoolean(Constants.DOUBLE_TAP_LOCK, false)
set(value) = prefs.edit().putBoolean(Constants.DOUBLE_TAP_LOCK, value).apply()
}

View File

@@ -0,0 +1,18 @@
package com.github.droidworksstudio.launcher.listener
import android.app.admin.DeviceAdminReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast
class DeviceAdmin : DeviceAdminReceiver() {
override fun onEnabled(context: Context, intent: Intent) {
super.onEnabled(context, intent)
Toast.makeText(context, "Enabled", Toast.LENGTH_SHORT).show()
}
override fun onDisabled(context: Context, intent: Intent) {
super.onDisabled(context, intent)
Toast.makeText(context, "Disabled", Toast.LENGTH_SHORT).show()
}
}

View File

@@ -0,0 +1,22 @@
package com.github.droidworksstudio.launcher.listener
import com.github.droidworksstudio.launcher.data.entities.AppInfo
class OnItemClickedListener {
interface OnAppsClickedListener{
fun onAppClicked(appInfo: AppInfo)
}
interface OnAppLongClickedListener{
fun onAppLongClicked(appInfo: AppInfo)
}
interface BottomSheetDismissListener {
fun onBottomSheetDismissed()
}
interface OnAppStateClickListener{
fun onAppStateClicked(appInfo: AppInfo)
}
}

View File

@@ -0,0 +1,8 @@
package com.github.droidworksstudio.launcher.listener
class OnItemMoveListener {
interface OnItemActionListener {
fun onViewMoved(oldPosition: Int, newPosition: Int): Boolean
fun onViewSwiped(position: Int)
}
}

View File

@@ -0,0 +1,83 @@
package com.github.droidworksstudio.launcher.listener
import android.annotation.SuppressLint
import android.content.Context
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
internal open class OnSwipeTouchListener(c: Context?) : View.OnTouchListener {
private var longPressOn = false
private val gestureDetector: GestureDetector
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
if (motionEvent.action == MotionEvent.ACTION_UP)
longPressOn = false
return gestureDetector.onTouchEvent(motionEvent)
}
private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
private val swipeThreshold: Int = 100
private val swipeVelocityThreshold: Int = 100
override fun onDown(e: MotionEvent): Boolean {
return true
}
override fun onDoubleTap(e: MotionEvent): Boolean {
onDoubleClick()
return super.onDoubleTap(e)
}
override fun onLongPress(e: MotionEvent) {
longPressOn = true
val scope = CoroutineScope(Dispatchers.Main)
scope.launch {
if (longPressOn) {
onLongClick()
}
}
super.onLongPress(e)
}
override fun onFling(
e1: MotionEvent?,
event1: MotionEvent,
velocityX: Float,
velocityY: Float
): Boolean {
try {
val diffY = event1.y - event1.y
val diffX = event1.x - event1.x
if (kotlin.math.abs(diffX) > kotlin.math.abs(diffY)) {
if (kotlin.math.abs(diffX) > swipeThreshold && kotlin.math.abs(velocityX) > swipeVelocityThreshold) {
if (diffX > 0) onSwipeRight() else onSwipeLeft()
}
} else {
if (kotlin.math.abs(diffY) > swipeThreshold && kotlin.math.abs(velocityY) > swipeVelocityThreshold) {
if (diffY < 0) onSwipeUp() else onSwipeDown()
}
}
} catch (exception: Exception) {
exception.printStackTrace()
}
return false
}
}
open fun onSwipeRight() {}
open fun onSwipeLeft() {}
open fun onSwipeUp() {}
open fun onSwipeDown() {}
open fun onLongClick() {}
open fun onDoubleClick() {}
init {
gestureDetector = GestureDetector(c, GestureListener())
}
}

View File

@@ -0,0 +1,7 @@
package com.github.droidworksstudio.launcher.listener
interface ScrollEventListener {
fun onTopReached()
fun onBottomReached()
fun onScroll(isTopReached: Boolean, isBottomReached: Boolean)
}

View File

@@ -0,0 +1,179 @@
package com.github.droidworksstudio.launcher.repository
import android.content.Context
import android.content.pm.LauncherApps
import android.content.pm.PackageManager
import android.os.UserManager
import android.util.Log
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 javax.inject.Inject
class AppInfoRepository @Inject constructor(
private val appDao: AppInfoDAO
) {
@Inject
lateinit var packageManager: PackageManager
fun getDrawApps(): Flow<List<AppInfo>> {
return appDao.getDrawAppsFlow()
}
fun getFavoriteApps(): Flow<List<AppInfo>> {
return appDao.getFavoriteAppsFlow()
}
fun getHiddenApps(): Flow<List<AppInfo>> {
return appDao.getHiddenAppsFlow()
}
suspend fun updateInfo(appInfo: AppInfo) {
appDao.update(appInfo)
}
suspend fun updateAppOrder(appInfoList: List<AppInfo>) {
withContext(Dispatchers.IO) {
appDao.updateAppOrder(appInfoList)
}
}
fun searchNote(query: String?): Flow<List<AppInfo>> {
return appDao.searchApps(query)
}
suspend fun updateFavoriteAppInfo(appInfo: AppInfo) = withContext(Dispatchers.IO) {
if (appInfo.favorite) {
val maxOrder = appDao.getMaxOrder()
val newOrder = maxOrder + 1
appInfo.appOrder = newOrder
appDao.updateAppInfo(appInfo)
Log.d("Tag", "${appInfo.appName} : DAO Order: ${appInfo.appOrder}")
Log.d("Tag", "${appInfo.appName} : DAO Favorite: ${appInfo.favorite}")
} else {
appInfo.appOrder = -1
appDao.updateAppInfo(appInfo)
Log.d("Tag", "${appInfo.appName} : DAO Order Remove: ${appInfo.appOrder}")
Log.d("Tag", "${appInfo.appName} : DAO Favorite Remove: ${appInfo.favorite}")
}
val favoriteAppInfos = appDao.getFavoriteAppInfo().sortedBy { it.appOrder }
for ((index, info) in favoriteAppInfos.withIndex()) {
info.appOrder = index
appDao.updateAppInfo(info)
}
}
suspend fun updateAppName(appInfo: AppInfo, newAppName: String) = withContext(Dispatchers.IO) {
appInfo.appName = newAppName
appDao.updateAppName(appInfo, newAppName)
}
suspend fun updateAppHidden(appInfo: AppInfo, appHidden: Boolean) =
withContext(Dispatchers.IO) {
appInfo.hidden = appHidden
appDao.updateAppHidden(appInfo, appHidden)
}
suspend fun updateAppLock(appInfo: AppInfo, appLock: Boolean) = withContext(Dispatchers.IO) {
appInfo.lock = appLock
appDao.updateLockApp(appInfo, appLock)
}
private suspend fun getInstalledPackages(): Set<String> = withContext(Dispatchers.IO) {
val packages = HashSet<String>()
val apps = packageManager.getInstalledApplications(PackageManager.GET_META_DATA)
for (app in apps) {
packages.add(app.packageName)
}
packages
}
suspend fun initInstalledAppInfo(context: Context): List<AppInfo> = withContext(Dispatchers.IO) {
val appList: MutableList<AppInfo> = mutableListOf()
val allApps = appDao.getAllAppsFlow().firstOrNull()
val existingPackageNames = allApps?.map { it.packageName } ?: emptyList()
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
val launcherApps =
context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
val excludedPackageName = Constants.PACKAGE_NAME
val newAppList: List<AppInfo> = userManager.userProfiles
.flatMap { profile ->
launcherApps.getActivityList(null, profile)
.mapNotNull { app ->
val packageName = app.applicationInfo.packageName
if (packageName !in existingPackageNames && packageName != excludedPackageName) {
AppInfo(
appName = app.label.toString(),
packageName = packageName,
favorite = false,
hidden = false,
lock = false
)
} else {
val existingApp = getAppByPackageName(packageName)
existingApp?.let { appList.add(it) }
existingApp
}
}
}
appDao.insertAll(newAppList.sortedBy { it.appName })
Log.d("Tag", "State: ${newAppList.sortedBy { it.appName }}")
val deletedApps = allApps?.filter { it.packageName !in existingPackageNames }
deletedApps?.forEach { appDao.delete(it) }
appList.sortBy { it.appName }
appList
}
suspend fun compareInstalledApp(): List<AppInfo> = withContext(Dispatchers.IO) {
val installedPackages = getInstalledPackages()
val uninstalledApps = mutableListOf<AppInfo>()
val allApps = appDao.getAllApps()
val newApps = mutableListOf<AppInfo>()
for (app in allApps) {
val packageName = app.packageName
if (!installedPackages.contains(packageName)) {
appDao.delete(app)
uninstalledApps.add(app)
}
}
val newPackageNames = installedPackages.filterNot { packageName ->
allApps.any { app -> app.packageName == packageName }
}
for (packageName in newPackageNames) {
val app = appDao.getAppByPackageName(packageName)
app?.let {
newApps.add(app)
}
}
appDao.insertAll(newApps)
uninstalledApps
}
private suspend fun getAppByPackageName(packageName: String): AppInfo? {
return appDao.getAppByPackageName(packageName)
}
}

View File

@@ -0,0 +1,12 @@
package com.github.droidworksstudio.launcher.ui.activities
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.github.droidworksstudio.launcher.R
class FakeHomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fake_home)
}
}

View File

@@ -0,0 +1,12 @@
package com.github.droidworksstudio.launcher.ui.activities
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.github.droidworksstudio.launcher.R
class LauncherActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_mock)
}
}

View File

@@ -0,0 +1,149 @@
package com.github.droidworksstudio.launcher.ui.activities
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.ActivityMainBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.ui.drawer.DrawFragment
import com.github.droidworksstudio.launcher.ui.viewpager.ViewPagerAdapter
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding
private val viewModel: AppViewModel by viewModels()
private val preferenceViewModel: PreferenceViewModel by viewModels()
private lateinit var navController: NavController
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var appHelper: AppHelper
private val viewPagerAdapter: ViewPagerAdapter by lazy { ViewPagerAdapter(supportFragmentManager, lifecycle) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
initializeDependencies()
setupNavController()
setupViewPagerAdapter()
}
private fun initializeDependencies() {
preferenceViewModel.setShowStatusBar(preferenceHelper.showStatusBar)
preferenceViewModel.setFirstLaunch(preferenceHelper.firstLaunch)
window.addFlags(FLAG_LAYOUT_NO_LIMITS)
}
private fun setupDataBase() {
lifecycleScope.launch {
viewModel.initializeInstalledAppInfo(this@MainActivity)
}
//GlobalScope.launch { }
preferenceHelper.firstLaunch = false
}
private fun observeUI() {
preferenceViewModel.setShowStatusBar(preferenceHelper.showStatusBar)
preferenceViewModel.showStatusBarLiveData.observe(this) {
if (it) appHelper.showStatusBar(this.window)
else appHelper.hideStatusBar(this.window) }
}
private fun setupNavController() {
navController = findNavController(R.id.nav_host_fragment_content_main)
appBarConfiguration = AppBarConfiguration(navController.graph)
//setupActionBarWithNavController(navController, appBarConfiguration)
}
private fun setupViewPagerAdapter() {
binding.pager.apply {
adapter = viewPagerAdapter
offscreenPageLimit = 1
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_content_main)
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
override fun onResume() {
super.onResume()
setupDataBase()
observeUI()
}
override fun onStop() {
backToHomeScreen()
super.onStop()
}
override fun onUserLeaveHint() {
backToHomeScreen()
super.onUserLeaveHint()
}
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
val currentItem = binding.pager.currentItem
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment_content_main) as NavHostFragment
val currentFragment = navHostFragment.childFragmentManager.fragments[0]
if (currentFragment is DrawFragment) {
@Suppress("DEPRECATION")
super.onBackPressed()
} else {
binding.pager.currentItem = currentItem - 1
}
}
private fun backToHomeScreen() {
if (navController.currentDestination?.id != R.id.HomeFragment)
navController.popBackStack(R.id.HomeFragment, false)
}
}

View File

@@ -0,0 +1,71 @@
package com.github.droidworksstudio.launcher.ui.activities
import android.os.Bundle
import android.view.WindowManager
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.ActivitySettingsBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class SettingsActivity : AppCompatActivity() {
private lateinit var binding: ActivitySettingsBinding
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var navController: NavController
private val preferenceViewModel: PreferenceViewModel by viewModels()
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var appHelper: AppHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
navController = findNavController(R.id.nav_host_fragment_content_settings)
appBarConfiguration = AppBarConfiguration(navController.graph)
initializeDependencies()
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_content_settings)
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
private fun initializeDependencies() {
preferenceViewModel.setShowStatusBar(preferenceHelper.showStatusBar)
}
private fun observeUI(){
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
preferenceViewModel.setShowStatusBar(preferenceHelper.showStatusBar)
preferenceViewModel.showStatusBarLiveData.observe(this) {
if (it) appHelper.showStatusBar(this.window)
else appHelper.hideStatusBar(this.window) }
}
override fun onResume() {
super.onResume()
observeUI()
}
}

View File

@@ -0,0 +1,173 @@
package com.github.droidworksstudio.launcher.ui.bottomsheetdialog
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.fragment.app.viewModels
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.BottomsheetdialogAlignmentSettingsBinding
import com.github.droidworksstudio.launcher.databinding.BottomsheetdialogColorSettingsBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.BottomDialogHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class AlignmentBottomSheetDialogFragment(context: Context) : BottomSheetDialogFragment() {
private var _binding: BottomsheetdialogAlignmentSettingsBinding? = null
private val binding get() = _binding!!
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var appHelper: AppHelper
@Inject
lateinit var bottomDialogHelper: BottomDialogHelper
private val preferenceViewModel: PreferenceViewModel by viewModels()
private var selectedAlignment: String = ""
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = BottomsheetdialogAlignmentSettingsBinding.inflate(inflater, container, false)
return binding.root
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
observeClickListener()
}
private fun initView() {
bottomDialogHelper.setupDialogStyle(dialog)
binding.selectDateTextSize.apply {
text = appHelper.gravityToString(preferenceHelper.homeDateAlignment)
}
binding.selectTimeTextSize.apply {
text = appHelper.gravityToString(preferenceHelper.homeTimeAlignment)
}
binding.selectAppTextSize.apply {
text = appHelper.gravityToString(preferenceHelper.homeAppAlignment)
}
}
private fun observeClickListener(){
binding.bottomAlignmentDateView.setOnClickListener {
selectedAlignment = REQUEST_KEY_DATE_ALIGNMENT
showListDialog(selectedAlignment)
}
binding.bottomAlignmentTimeView.setOnClickListener {
selectedAlignment = REQUEST_KEY_TIME_ALIGNMENT
showListDialog(selectedAlignment)
}
binding.bottomAlignmentAppView.setOnClickListener {
selectedAlignment = REQUEST_KEY_APP_ALIGNMENT
showListDialog(selectedAlignment)
}
}
private fun showListDialog(selectedAlignment: String) {
val items = resources.getStringArray(R.array.alignment_options)
val dialog = MaterialAlertDialogBuilder(requireContext())
dialog.setTitle(DIALOG_TITLE)
dialog.setItems(items) { _, which ->
val selectedItem = items[which]
val gravity = appHelper.getGravityFromSelectedItem(selectedItem)
when (selectedAlignment) {
REQUEST_KEY_APP_ALIGNMENT -> {
setAlignment(
selectedAlignment,
selectedItem,
gravity,
binding.selectAppTextSize
)
}
REQUEST_KEY_TIME_ALIGNMENT -> {
setAlignment(
selectedAlignment,
selectedItem,
gravity,
binding.selectTimeTextSize
)
}
REQUEST_KEY_DATE_ALIGNMENT -> {
setAlignment(
selectedAlignment,
selectedItem,
gravity,
binding.selectDateTextSize
)
}
}
}
dialog.show()
}
private fun setAlignment(
alignmentType: String,
selectedItem: String,
gravity: Int,
textView: TextView
) {
val alignmentPreference: (Int) -> Unit
val alignmentGetter: () -> Int
when (alignmentType) {
REQUEST_KEY_APP_ALIGNMENT -> {
alignmentPreference = { preferenceViewModel.setHomeAppAlignment(it) }
alignmentGetter = { preferenceHelper.homeAppAlignment }
}
REQUEST_KEY_TIME_ALIGNMENT -> {
alignmentPreference = { preferenceViewModel.setHomeTimeAppAlignment(it) }
alignmentGetter = { preferenceHelper.homeTimeAlignment }
}
REQUEST_KEY_DATE_ALIGNMENT -> {
alignmentPreference = { preferenceViewModel.setHomeDateAlignment(it) }
alignmentGetter = { preferenceHelper.homeDateAlignment }
}
else -> return
}
alignmentPreference(gravity)
textView.text = appHelper.gravityToString(alignmentGetter())
}
companion object {
private const val DIALOG_TITLE = "Select Alignment"
private const val REQUEST_KEY_DATE_ALIGNMENT = "REQUEST_KEY_DATE_ALIGNMENT"
private const val REQUEST_KEY_TIME_ALIGNMENT = "REQUEST_KEY_TIME_ALIGNMENT"
private const val REQUEST_KEY_APP_ALIGNMENT = "REQUEST_KEY_APP_ALIGNMENT"
}
}

View File

@@ -0,0 +1,188 @@
package com.github.droidworksstudio.launcher.ui.bottomsheetdialog
import android.os.Build
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.BottomsheetDialogBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.BottomDialogHelper
import com.github.droidworksstudio.launcher.helper.FingerprintHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class AppInfoBottomSheetFragment(private val appInfo: AppInfo) : BottomSheetDialogFragment(),
FingerprintHelper.Callback {
private var _binding: BottomsheetDialogBinding? = null
private val binding get() = _binding!!
private val viewModel: AppViewModel by viewModels()
@Inject
lateinit var appHelper: AppHelper
@Inject
lateinit var bottomDialogHelper: BottomDialogHelper
@Inject
lateinit var fingerHelper: FingerprintHelper
private var appStateClickListener: OnItemClickedListener.OnAppStateClickListener? = null
private var dismissListener: OnItemClickedListener.BottomSheetDismissListener? = null
fun setOnAppStateClickListener(listener: OnItemClickedListener.OnAppStateClickListener) {
appStateClickListener = listener
}
fun setOnBottomSheetDismissedListener(listener: OnItemClickedListener.BottomSheetDismissListener) {
dismissListener = listener
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = BottomsheetDialogBinding.inflate(inflater, container, false)
return binding.root
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
observeClickListener()
}
private fun initView() {
bottomDialogHelper.setupDialogStyle(dialog)
binding.run {
bottomSheetFavHidden.text = getString(if (!appInfo.favorite) R.string.bottom_dialog_add_to_home else R.string.bottom_dialog_remove_from_home)
bottomSheetHidden.text = getString(if (!appInfo.hidden) R.string.bottom_dialog_add_to_hidden else R.string.bottom_dialog_remove_to_hidden)
bottomSheetLock.text = getString(if (!appInfo.lock) R.string.bottom_dialog_add_to_lock else R.string.bottom_dialog_remove_to_unlock)
bottomSheetRename.setText(appInfo.appName)
bottomSheetOrder.text = appInfo.appOrder.toString()
}
}
@RequiresApi(Build.VERSION_CODES.O)
private fun observeClickListener() {
val packageName = appInfo.packageName
val packageManager = context?.packageManager
val applicationInfo = packageManager?.getApplicationInfo(packageName, 0)
val appName = applicationInfo?.let { packageManager.getApplicationLabel(it).toString() }
binding.bottomSheetFavHidden.setOnClickListener {
appStateClickListener?.onAppStateClicked(appInfo)
appInfo.favorite = !appInfo.favorite
viewModel.updateAppInfoFavorite(appInfo)
Log.d("Tag", "${appInfo.appName} : Bottom Favorite: ${appInfo.favorite}")
Log.d("Tag", "${appInfo.appName} : Bottom Order: ${appInfo.appOrder}")
dismiss()
}
binding.bottomSheetRename.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
appInfo.appName = s.toString()
if (s.isNullOrEmpty()) {
viewModel.updateAppInfoAppName(appInfo, appName.toString())
} else {
viewModel.updateAppInfoAppName(appInfo, s.toString())
}
}
override fun afterTextChanged(s: Editable?) {
if (s.isNullOrEmpty()) {
binding.bottomSheetRename.setHintTextColor(ContextCompat.getColor(requireContext(), R.color.white))
binding.bottomSheetRename.hint = appName
appInfo.appName = appName ?: ""
} else {
appInfo.appName = s.toString()
}
}
})
binding.bottomSheetRenameDone.setOnClickListener {
appStateClickListener?.onAppStateClicked(appInfo)
viewModel.updateAppInfoAppName(appInfo, appInfo.appName)
dismiss()
Log.d("Tag", "${appInfo.appName} Bottom State: ${appInfo.appName}")
}
binding.bottomSheetHidden.setOnClickListener {
appStateClickListener?.onAppStateClicked(appInfo)
appInfo.hidden = !appInfo.hidden
viewModel.updateAppHidden(appInfo, appInfo.hidden)
dismiss()
}
binding.bottomSheetLock.setOnClickListener {
if (appInfo.lock) {
fingerHelper.startFingerprintAuth(appInfo, this)
}
else {
appInfo.lock = true
viewModel.updateAppLock(appInfo, appInfo.lock)
dismiss()
}
}
binding.bottomSheetUninstall.setOnClickListener {
appStateClickListener?.onAppStateClicked(appInfo)
appHelper.unInstallApp(requireContext(), appInfo)
dismiss()
}
binding.bottomSheetInfo.setOnClickListener {
appHelper.appInfo(requireContext(), appInfo)
dismiss()
}
}
override fun onAuthenticationSucceeded(appInfo: AppInfo) {
appInfo.lock = false
viewModel.updateAppLock(appInfo, appInfo.lock)
dismiss()
appHelper.showToast(requireContext(), getString(R.string.authentication_succeeded))
}
override fun onAuthenticationFailed() {
appHelper.showToast(requireContext(), getString(R.string.authentication_failed))
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
appHelper.showToast(requireContext(), getString(R.string.authentication_error))
}
}

View File

@@ -0,0 +1,168 @@
package com.github.droidworksstudio.launcher.ui.bottomsheetdialog
import android.content.Context
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.fragment.app.viewModels
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.github.droidworksstudio.launcher.databinding.BottomsheetdialogColorSettingsBinding
import com.github.droidworksstudio.launcher.helper.BottomDialogHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import dagger.hilt.android.AndroidEntryPoint
import net.mm2d.color.chooser.ColorChooserDialog
import javax.inject.Inject
@AndroidEntryPoint
class ColorBottomSheetDialogFragment(context: Context) : BottomSheetDialogFragment() {
private var _binding: BottomsheetdialogColorSettingsBinding? = null
private val binding get() = _binding!!
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var bottomDialogHelper: BottomDialogHelper
private val preferenceViewModel: PreferenceViewModel by viewModels()
private var color: Int = Color.WHITE
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = BottomsheetdialogColorSettingsBinding.inflate(inflater, container, false)
return binding.root
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
observeClickListener()
}
private fun initView(){
bottomDialogHelper.setupDialogStyle(dialog)
binding.selectDateTextColor.apply {
text = bottomDialogHelper.getColorText(preferenceHelper.dateColor)
setTextColor(preferenceHelper.dateColor)
}
binding.selectTimeTextColor.apply {
text = bottomDialogHelper.getColorText(preferenceHelper.timeColor)
setTextColor(preferenceHelper.timeColor)
}
binding.selectAppTextColor.apply {
text = bottomDialogHelper.getColorText(preferenceHelper.appColor)
setTextColor(preferenceHelper.appColor)
}
binding.selectBatteryTextColor.apply {
text = bottomDialogHelper.getColorText(preferenceHelper.batteryColor)
setTextColor(preferenceHelper.batteryColor)
}
}
private fun observeClickListener(){
binding.bottomColorDateView.setOnClickListener {
showColorPickerDialog(
binding.selectDateTextColor,
REQUEST_KEY_DATE_COLOR,
preferenceHelper.dateColor
)
}
binding.bottomColorTimeView.setOnClickListener {
showColorPickerDialog(
binding.selectTimeTextColor,
REQUEST_KEY_TIME_COLOR,
preferenceHelper.timeColor
)
}
binding.bottomColorAppView.setOnClickListener {
showColorPickerDialog(
binding.selectAppTextColor,
REQUEST_KEY_APP_COLOR,
preferenceHelper.appColor
)
}
binding.bottomColorBatteryView.setOnClickListener {
showColorPickerDialog(
binding.selectBatteryTextColor,
REQUEST_KEY_BATTERY_COLOR,
preferenceHelper.batteryColor
)
}
}
private fun showColorPickerDialog(view: View, requestCode: String, color: Int) {
ColorChooserDialog.show(
this, requestCode, color, true, tabs = intArrayOf(
ColorChooserDialog.TAB_HSV,
ColorChooserDialog.TAB_PALETTE
)
)
ColorChooserDialog.registerListener(this, requestCode, { pickedColor ->
this.color = pickedColor
(view as TextView).apply {
//text = getColorText(pickedColor)
text = bottomDialogHelper.getColorText(pickedColor)
setTextColor(pickedColor)
}
when (requestCode) {
REQUEST_KEY_DAILY_WORD_COLOR -> {
preferenceViewModel.setDailyWordColor(pickedColor)
Log.d("Tag", "Settings Daily Color: ${Integer.toHexString(pickedColor)}")
}
REQUEST_KEY_BATTERY_COLOR -> {
preferenceViewModel.setBatteryColor(pickedColor)
Log.d("Tag", "Settings Battery Color: ${Integer.toHexString(pickedColor)}")
}
REQUEST_KEY_APP_COLOR -> {
preferenceViewModel.setAppColor(pickedColor)
Log.d("Tag", "Settings Daily Color: ${Integer.toHexString(pickedColor)}")
}
REQUEST_KEY_DATE_COLOR -> {
preferenceViewModel.setDateColor(pickedColor)
Log.d("Tag", "Settings Date Color: ${Integer.toHexString(pickedColor)}")
}
REQUEST_KEY_TIME_COLOR -> {
preferenceViewModel.setTimeColor(pickedColor)
Log.d("Tag", "Settings Time Color: ${Integer.toHexString(color)}")
}
}
}) {
Toast.makeText(context, "onCancel", Toast.LENGTH_SHORT).show()
}
}
companion object {
private const val REQUEST_KEY_DATE_COLOR = "REQUEST_DATE_COLOR"
private const val REQUEST_KEY_TIME_COLOR = "REQUEST_TIME_COLOR"
private const val REQUEST_KEY_DAILY_WORD_COLOR = "REQUEST_DAILY_WORD_COLOR"
private const val REQUEST_KEY_APP_COLOR = "REQUEST_APP_COLOR"
private const val REQUEST_KEY_BATTERY_COLOR = "REQUEST_BATTERY_COLOR"
}
}

View File

@@ -0,0 +1,83 @@
package com.github.droidworksstudio.launcher.ui.bottomsheetdialog
import android.content.Context
import android.content.DialogInterface
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.fragment.app.viewModels
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.github.droidworksstudio.launcher.databinding.BottomsheetdialogTextSettingsBinding
import com.github.droidworksstudio.launcher.helper.BottomDialogHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class TextBottomSheetDialogFragment(context: Context) : BottomSheetDialogFragment() {
private var _binding: BottomsheetdialogTextSettingsBinding? = null
private val binding get() = _binding!!
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var bottomDialogHelper: BottomDialogHelper
private val preferenceViewModel: PreferenceViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = BottomsheetdialogTextSettingsBinding.inflate(inflater, container, false)
return binding.root
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
}
private fun initView(){
bottomDialogHelper.setupDialogStyle(dialog)
binding.selectDateTextSize.setText(preferenceHelper.dateTextSize.toString())
binding.selectTimeTextSize.setText(preferenceHelper.timeTextSize.toString())
binding.selectAppTextSize.setText(preferenceHelper.appTextSize.toString())
}
private fun observeValueChange(){
val dateValue = binding.selectDateTextSize.text.toString()
val timeValue = binding.selectTimeTextSize.text.toString()
val appValue = binding.selectAppTextSize.text.toString()
val dateFloatValue = parseFloatValue(dateValue, preferenceHelper.dateTextSize)
val timeFloatValue = parseFloatValue(timeValue, preferenceHelper.timeTextSize)
val appFloatValue = parseFloatValue(appValue, preferenceHelper.appTextSize)
dismiss()
preferenceViewModel.setDateTextSize(dateFloatValue)
preferenceViewModel.setTimeTextSize(timeFloatValue)
preferenceViewModel.setAppTextSize(appFloatValue)
}
private fun parseFloatValue(text: String, defaultValue: Float): Float {
if (text.isEmpty() || text == "0") {
return defaultValue
}
return text.toFloat()
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
observeValueChange()
}
}

View File

@@ -0,0 +1,47 @@
package com.github.droidworksstudio.launcher.ui.drawer
import android.annotation.SuppressLint
import android.view.LayoutInflater
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemDrawBinding
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
class DrawAdapter(private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener) :
ListAdapter<AppInfo, RecyclerView.ViewHolder>(DiffCallback()) {
override fun onCreateViewHolder(
parent: android.view.ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
val binding = ItemDrawBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return DrawViewHolder(binding, onAppClickedListener, onAppLongClickedListener)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val appInfo = getItem(position)
(holder as DrawViewHolder).bind(appInfo)
}
class DiffCallback : DiffUtil.ItemCallback<AppInfo>() {
override fun areItemsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem == newItem
}
@SuppressLint("NotifyDataSetChanged")
fun updateDataWithStateFlow(newData: List<AppInfo>) {
submitList(newData.toMutableList())
notifyDataSetChanged()
}
}

View File

@@ -0,0 +1,193 @@
package com.github.droidworksstudio.launcher.ui.drawer
import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.FragmentDrawBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.FingerprintHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AppInfoBottomSheetFragment
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
/**
* A simple [Fragment] subclass as the second destination in the navigation.
*/
@AndroidEntryPoint
class DrawFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
OnItemClickedListener.OnAppLongClickedListener,
OnItemClickedListener.BottomSheetDismissListener,
OnItemClickedListener.OnAppStateClickListener,
FingerprintHelper.Callback{
private var _binding: FragmentDrawBinding? = null
private val binding get() = _binding!!
private val viewModel: AppViewModel by viewModels()
private val drawAdapter: DrawAdapter by lazy { DrawAdapter(this, this) }
@Inject
lateinit var appHelper: AppHelper
@Inject
lateinit var fingerHelper: FingerprintHelper
private lateinit var context: Context
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentDrawBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
appHelper.dayNightMod(requireContext(), binding.drawBackground)
super.onViewCreated(view, savedInstanceState)
context = requireContext()
setupRecyclerView()
setupSearch()
observeClickListener()
}
private fun setupRecyclerView() {
binding.drawAdapter.apply {
adapter = drawAdapter
layoutManager = StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL)
setHasFixedSize(false)
}
}
private fun observeDrawerApps() {
viewModel.compareInstalledAppInfo()
viewLifecycleOwner.lifecycleScope.launchWhenCreated {
viewModel.drawApps.collect{
drawAdapter.submitList(it)
drawAdapter.updateDataWithStateFlow(it)
}
}
}
private fun setupSearch() {
binding.searchView1.addTextChangedListener(object: TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
// Do Nothing
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
searchApp(s.toString())
}
override fun afterTextChanged(s: Editable?) {
// Do Nothing
}
})
}
private fun observeClickListener(){
binding.drawSearchButton.setOnClickListener {appHelper.showSoftKeyboard(context, binding.searchView1)}
}
private fun searchApp(query: String?) {
val searchQuery = "%$query%"
viewLifecycleOwner.lifecycle.coroutineScope.launchWhenCreated {
viewModel.searchAppInfo(searchQuery).collect { drawAdapter.submitList(it) }
}
}
private fun showSelectedApp(appInfo: AppInfo) {
binding.searchView1.text?.clear()
val bottomSheetFragment = AppInfoBottomSheetFragment(appInfo)
bottomSheetFragment.setOnBottomSheetDismissedListener(this)
bottomSheetFragment.setOnAppStateClickListener(this)
bottomSheetFragment.show(parentFragmentManager, "BottomSheetDialog")
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onPause() {
super.onPause()
binding.searchView1.text?.clear()
}
override fun onResume() {
super.onResume()
observeDrawerApps()
binding.drawAdapter.scrollToPosition(0)
appHelper.hideKeyboard(context, binding.searchView1)
}
override fun onStop() {
super.onStop()
}
override fun onAppClicked(appInfo: AppInfo) {
observeBioAuthCheck(appInfo)
}
override fun onAppLongClicked(appInfo: AppInfo) {
showSelectedApp(appInfo)
}
override fun onBottomSheetDismissed() {
}
override fun onAppStateClicked(appInfo: AppInfo) {
viewModel.update(appInfo)
Log.d("Tag", "${appInfo.appName} : Draw Favorite: ${appInfo.favorite}")
}
private fun observeBioAuthCheck(appInfo: AppInfo) {
if (!appInfo.lock) {
appHelper.launchApp(context, appInfo)
} else {
fingerHelper.startFingerprintAuth(appInfo,this)
}
}
override fun onAuthenticationSucceeded(appInfo: AppInfo) {
Toast.makeText(context, getString(R.string.authentication_succeeded), Toast.LENGTH_SHORT)
.show()
appHelper.launchApp(context, appInfo)
}
override fun onAuthenticationFailed() {
Toast.makeText(context, getString(R.string.authentication_failed), Toast.LENGTH_SHORT)
.show()
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
Toast.makeText(context, getString(R.string.authentication_error), Toast.LENGTH_SHORT)
.show()
}
}

View File

@@ -0,0 +1,29 @@
package com.github.droidworksstudio.launcher.ui.drawer
import android.util.Log
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemDrawBinding
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
class DrawViewHolder(private val binding: ItemDrawBinding,
private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener) :
RecyclerView.ViewHolder(binding.root) {
fun bind(appInfo: AppInfo) {
binding.apply {
appDrawName.text = appInfo.appName
Log.d("Tag", "Draw Adapter: ${appInfo.appName + appInfo.id}")
}
itemView.setOnClickListener {
onAppClickedListener.onAppClicked(appInfo)
}
itemView.setOnLongClickListener {
onAppLongClickedListener.onAppLongClicked(appInfo)
true
}
}
}

View File

@@ -0,0 +1,60 @@
package com.github.droidworksstudio.launcher.ui.favorite
import android.util.Log
import android.view.LayoutInflater
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemFavoriteBinding
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.listener.OnItemMoveListener
class FavoriteAdapter(private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
) : ListAdapter<AppInfo, RecyclerView.ViewHolder>(DiffCallback()) ,OnItemMoveListener.OnItemActionListener{
private lateinit var touchHelper: ItemTouchHelper
override fun onCreateViewHolder(
parent: android.view.ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
val binding = ItemFavoriteBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return FavoriteViewHolder(binding, onAppClickedListener, touchHelper)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val currentItem = getItem(position)
when (holder) {
is FavoriteViewHolder -> {
holder.bind(currentItem)
}
}
}
class DiffCallback : androidx.recyclerview.widget.DiffUtil.ItemCallback<AppInfo>() {
override fun areItemsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem == newItem
}
fun setItemTouchHelper(touchHelper: ItemTouchHelper) {
this.touchHelper = touchHelper
}
override fun onViewMoved(oldPosition: Int, newPosition: Int): Boolean {
Log.d("Tag", "List Adapter$newPosition")
return false
}
override fun onViewSwiped(position: Int) {
Log.d("Tag", "onViewMoved")
}
}

View File

@@ -0,0 +1,227 @@
package com.github.droidworksstudio.launcher.ui.favorite
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.FragmentFavoriteBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.FingerprintHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.listener.OnItemMoveListener
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AppInfoBottomSheetFragment
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import java.util.Collections
import javax.inject.Inject
@AndroidEntryPoint
class FavoriteFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
OnItemClickedListener.BottomSheetDismissListener,
OnItemClickedListener.OnAppStateClickListener,
FingerprintHelper.Callback,OnItemMoveListener.OnItemActionListener{
private var _binding: FragmentFavoriteBinding? = null
private val binding get() = _binding!!
private val viewModel: AppViewModel by viewModels()
private lateinit var context: Context
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var fingerHelper: FingerprintHelper
@Inject
lateinit var appHelper: AppHelper
private val favoriteAdapter: FavoriteAdapter by lazy { FavoriteAdapter(this) }
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentFavoriteBinding.inflate(inflater, container, false)
return binding.root
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@SuppressLint("ClickableViewAccessibility")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
appHelper.dayNightMod(requireContext(), binding.favoriteView)
super.onViewCreated(view, savedInstanceState)
context = requireContext()
setupRecyclerView()
observeFavorite()
observeHomeAppOrder()
}
private fun setupRecyclerView() {
binding.favoriteAdapter.apply {
adapter = favoriteAdapter
layoutManager = StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL)
setHasFixedSize(false)
}
}
private fun handleDragAndDrop(oldPosition: Int, newPosition: Int) {
val items = favoriteAdapter.currentList.toMutableList()
Collections.swap(items, oldPosition, newPosition)
items.forEachIndexed { index, appInfo ->
appInfo.appOrder = index
}
viewLifecycleOwner.lifecycleScope.launch {
viewModel.updateAppOrder(items)
}
}
private fun observeHomeAppOrder() {
//binding.favoriteAdapter.adapter = favoriteAdapter
val listener: OnItemMoveListener.OnItemActionListener = favoriteAdapter
val simpleItemTouchCallback = object : ItemTouchHelper.Callback() {
override fun onChildDraw(
canvas: Canvas, recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder, dX: Float,
dY: Float, actionState: Int, isCurrentlyActive: Boolean
) {
if (isCurrentlyActive) {
viewHolder.itemView.alpha = 0.5f
} else {
viewHolder.itemView.alpha = 1f
}
super.onChildDraw(
canvas, recyclerView, viewHolder,
dX, dY,
actionState, isCurrentlyActive
)
}
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
val swipeFlags = 0
return makeMovementFlags(dragFlags, swipeFlags)
}
override fun onMove(
recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val oldPosition = viewHolder.bindingAdapterPosition
val newPosition = target.bindingAdapterPosition
handleDragAndDrop(oldPosition, newPosition)
return listener.onViewMoved(
viewHolder.bindingAdapterPosition,
target.bindingAdapterPosition
)
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
listener.onViewSwiped(viewHolder.adapterPosition)
}
override fun isLongPressDragEnabled() = false
}
val itemTouchHelper = ItemTouchHelper(simpleItemTouchCallback)
favoriteAdapter.setItemTouchHelper(itemTouchHelper)
itemTouchHelper.attachToRecyclerView(binding.favoriteAdapter)
}
private fun observeFavorite() {
viewModel.compareInstalledAppInfo()
viewLifecycleOwner.lifecycleScope.launch {
viewModel.favoriteApps.collect {
favoriteAdapter.submitList(it)
}
}
}
private fun observeBioAuthCheck(appInfo: AppInfo) {
if (!appInfo.lock) {
appHelper.launchApp(context, appInfo)
} else {
fingerHelper.startFingerprintAuth(appInfo, this)
}
}
private fun showSelectedApp(appInfo: AppInfo) {
val bottomSheetFragment = AppInfoBottomSheetFragment(appInfo)
bottomSheetFragment.setOnBottomSheetDismissedListener(this)
bottomSheetFragment.setOnAppStateClickListener(this)
bottomSheetFragment.show(parentFragmentManager, "BottomSheetDialog")
}
override fun onBottomSheetDismissed() {
TODO("Not yet implemented")
}
override fun onAppStateClicked(appInfo: AppInfo) {
viewModel.update(appInfo)
}
override fun onAppClicked(appInfo: AppInfo) {
observeBioAuthCheck(appInfo)
}
override fun onAuthenticationSucceeded(appInfo: AppInfo) {
Toast.makeText(context, getString(R.string.authentication_succeeded), Toast.LENGTH_SHORT)
.show()
appHelper.launchApp(context, appInfo)
}
override fun onAuthenticationFailed() {
Toast.makeText(context, getString(R.string.authentication_failed), Toast.LENGTH_SHORT)
.show()
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
Toast.makeText(context, getString(R.string.authentication_error), Toast.LENGTH_SHORT)
.show()
}
override fun onViewMoved(oldPosition: Int, newPosition: Int): Boolean {
return true
}
override fun onViewSwiped(position: Int) {
TODO("Not yet implemented")
}
}

View File

@@ -0,0 +1,39 @@
package com.github.droidworksstudio.launcher.ui.favorite
import android.annotation.SuppressLint
import android.util.Log
import android.view.MotionEvent
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemFavoriteBinding
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
@SuppressLint("ClickableViewAccessibility")
class FavoriteViewHolder(private val binding: ItemFavoriteBinding,
private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val touchHelper: ItemTouchHelper,
) :
RecyclerView.ViewHolder(binding.root){
init {
binding.appFavoriteDragIcon.setOnTouchListener { _, event ->
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
touchHelper.startDrag(this)
}
false
}
}
fun bind(appInfo: AppInfo) {
binding.apply {
appFavoriteName.text = appInfo.appName
//appFavoriteDragIcon.visibility = View.GONE
Log.d("Tag", "Draw Adapter: ${appInfo.appName}")
}
itemView.setOnClickListener {
onAppClickedListener.onAppClicked(appInfo)
}
}
}

View File

@@ -0,0 +1,53 @@
package com.github.droidworksstudio.launcher.ui.hidden
import android.util.Log
import android.view.LayoutInflater
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemHiddenBinding
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
class HiddenAdapter(
private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener
) : ListAdapter<AppInfo, RecyclerView.ViewHolder>(DiffCallback()) {
override fun onCreateViewHolder(
parent: android.view.ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
val binding = ItemHiddenBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return HiddenViewHolder(binding, onAppClickedListener, onAppLongClickedListener)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
getItem(position)
when (holder) {
is HiddenViewHolder -> {
val appInfo = getItem(position) as AppInfo
holder.bind(appInfo)
}
}
}
class DiffCallback : DiffUtil.ItemCallback<AppInfo>() {
override fun areItemsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem == newItem
}
fun updateData(newData: List<AppInfo>) {
notifyItemChanged(newData.size)
submitList(newData)
Log.d("Tag", "Collected Hidden Adapter : $newData")
}
}

View File

@@ -0,0 +1,151 @@
package com.github.droidworksstudio.launcher.ui.hidden
import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.FragmentHiddenBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.FingerprintHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AppInfoBottomSheetFragment
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class HiddenFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
OnItemClickedListener.OnAppLongClickedListener,
OnItemClickedListener.BottomSheetDismissListener,
OnItemClickedListener.OnAppStateClickListener,
FingerprintHelper.Callback{
private var _binding: FragmentHiddenBinding? = null
private val binding get() = _binding!!
private val hiddenAdapter: HiddenAdapter by lazy { HiddenAdapter(this, this) }
private val viewModel: AppViewModel by viewModels()
private lateinit var context: Context
@Inject
lateinit var fingerHelper: FingerprintHelper
@Inject
lateinit var appHelper: AppHelper
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHiddenBinding.inflate(inflater, container, false)
return binding.root
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@SuppressLint("ClickableViewAccessibility")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
appHelper.dayNightMod(requireContext(), binding.hiddenView)
super.onViewCreated(view, savedInstanceState)
context = requireContext()
setupRecyclerView()
observeHiddenApps()
}
private fun setupRecyclerView() {
binding.hiddenAdapter.apply {
adapter = hiddenAdapter
layoutManager = StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL)
setHasFixedSize(false)
}
}
private fun observeHiddenApps() {
viewModel.compareInstalledAppInfo()
viewLifecycleOwner.lifecycleScope.launchWhenCreated {
viewModel.hiddenApps.collect {
hiddenAdapter.updateData(it)
}
}
}
private fun observeBioAuthCheck(appInfo: AppInfo) {
if (!appInfo.lock) {
appHelper.launchApp(context, appInfo)
} else {
fingerHelper.startFingerprintAuth(appInfo,this)
}
}
private fun showSelectedApp(appInfo: AppInfo) {
val bottomSheetFragment = AppInfoBottomSheetFragment(appInfo)
bottomSheetFragment.setOnBottomSheetDismissedListener(this)
bottomSheetFragment.setOnAppStateClickListener(this)
bottomSheetFragment.show(parentFragmentManager, "BottomSheetDialog")
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onPause() {
super.onPause()
binding.hiddenAdapter.scrollToPosition(0)
}
@SuppressLint("NotifyDataSetChanged")
override fun onResume() {
super.onResume()
observeHiddenApps()
}
override fun onAppLongClicked(appInfo: AppInfo) {
showSelectedApp(appInfo)
}
override fun onBottomSheetDismissed() {
TODO("Not yet implemented")
}
override fun onAppStateClicked(appInfo: AppInfo) {
viewModel.update(appInfo)
}
override fun onAppClicked(appInfo: AppInfo) {
observeBioAuthCheck(appInfo)
}
override fun onAuthenticationSucceeded(appInfo: AppInfo) {
Toast.makeText(context, getString(R.string.authentication_succeeded), Toast.LENGTH_SHORT)
.show()
appHelper.launchApp(context, appInfo)
}
override fun onAuthenticationFailed() {
Toast.makeText(context, getString(R.string.authentication_failed), Toast.LENGTH_SHORT)
.show()
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
Toast.makeText(context, getString(R.string.authentication_error), Toast.LENGTH_SHORT)
.show()
}
}

View File

@@ -0,0 +1,28 @@
package com.github.droidworksstudio.launcher.ui.hidden
import android.util.Log
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemHiddenBinding
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
class HiddenViewHolder(private val binding: ItemHiddenBinding,
private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener) :
RecyclerView.ViewHolder(binding.root) {
fun bind(appInfo: AppInfo) {
binding.apply {
appHiddenName.text = appInfo.appName
Log.d("Tag", "Draw Adapter: ${appInfo.appName}")
}
itemView.setOnClickListener {
onAppClickedListener.onAppClicked(appInfo)
}
itemView.setOnLongClickListener {
onAppLongClickedListener.onAppLongClicked(appInfo)
true
}
}
}

View File

@@ -0,0 +1,54 @@
package com.github.droidworksstudio.launcher.ui.home
import android.annotation.SuppressLint
import android.view.LayoutInflater
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemHomeBinding
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import javax.inject.Inject
class HomeAdapter @Inject constructor(private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener,
private val preferenceHelperProvider: PreferenceHelper
) :
ListAdapter<AppInfo,RecyclerView.ViewHolder>(DiffCallback()) {
override fun onCreateViewHolder(
parent: android.view.ViewGroup,
viewType: Int
): RecyclerView.ViewHolder {
val binding = ItemHomeBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
val preferenceHelper = preferenceHelperProvider
return HomeViewHolder(binding, onAppClickedListener, onAppLongClickedListener, preferenceHelper)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val appInfo = getItem(position)
(holder as HomeViewHolder).bind(appInfo)
}
class DiffCallback : DiffUtil.ItemCallback<AppInfo>() {
override fun areItemsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: AppInfo, newItem: AppInfo) =
oldItem == newItem
}
@SuppressLint("NotifyDataSetChanged")
fun updateDataWithStateFlow(newData: List<AppInfo>) {
submitList(newData.toMutableList())
notifyDataSetChanged()
}
}

View File

@@ -0,0 +1,291 @@
package com.github.droidworksstudio.launcher.ui.home
import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build
import android.os.Bundle
import android.text.format.DateFormat
import android.util.Log
import android.view.*
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.accessibility.MyAccessibilityService
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.FragmentHomeBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.FingerprintHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
import com.github.droidworksstudio.launcher.ui.activities.SettingsActivity
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AppInfoBottomSheetFragment
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flowOn
import java.util.Locale
import javax.inject.Inject
/**
* A simple [Fragment] subclass as the default destination in the navigation.
*/
@AndroidEntryPoint
class HomeFragment : Fragment(), OnItemClickedListener.OnAppsClickedListener,
OnItemClickedListener.OnAppLongClickedListener,
OnItemClickedListener.BottomSheetDismissListener,
OnItemClickedListener.OnAppStateClickListener,
FingerprintHelper.Callback, ScrollEventListener {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var appHelper: AppHelper
@Inject
lateinit var fingerHelper: FingerprintHelper
private val viewModel: AppViewModel by viewModels()
private val preferenceViewModel: PreferenceViewModel by viewModels()
private val homeAdapter: HomeAdapter by lazy { HomeAdapter(this, this, preferenceHelper) }
private lateinit var batteryReceiver: BroadcastReceiver
private lateinit var context: Context
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@SuppressLint("ClickableViewAccessibility")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initializeInjectedDependencies()
setupBattery()
setupRecyclerView()
observeUserInterfaceSettings()
}
@SuppressLint("ClickableViewAccessibility")
private fun initializeInjectedDependencies() {
context = requireContext()
binding.nestScrollView.scrollEventListener = this
binding.nestScrollView.registerRecyclerView(binding.appListAdapter, this)
preferenceViewModel.setShowTime(preferenceHelper.showTime)
preferenceViewModel.setShowDate(preferenceHelper.showDate)
preferenceViewModel.setShowDailyWord(preferenceHelper.showDailyWord)
binding.mainView.setOnTouchListener(getSwipeGestureListener(context))
binding.clock.setOnClickListener { appHelper.launchClock(context) }
binding.date.setOnClickListener { appHelper.launchCalendar(context) }
}
private fun setupBattery() {
batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
val batteryLevel = level * 100 / scale.toFloat()
val batteryLevelText = getString(R.string.battery_level, batteryLevel.toString())
binding.battery.text = batteryLevelText
}
}
val batteryIntentFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
requireActivity().registerReceiver(batteryReceiver, batteryIntentFilter)
}
private fun setupRecyclerView() {
val marginTopInPixels = 128
val params: ViewGroup.MarginLayoutParams = binding.appListAdapter.layoutParams as ViewGroup.MarginLayoutParams
params.topMargin = marginTopInPixels
binding.appListAdapter.layoutParams = params
binding.appListAdapter.apply {
adapter = homeAdapter
setHasFixedSize(false)
layoutManager = StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL)
//itemAnimator = false
isNestedScrollingEnabled = false
}
}
private fun observeFavoriteAppList() {
viewModel.compareInstalledAppInfo()
viewLifecycleOwner.lifecycleScope.launchWhenCreated {
viewModel.favoriteApps.flowOn(Dispatchers.Main).collect {
homeAdapter.submitList(it)
homeAdapter.updateDataWithStateFlow(it)
}
}
}
private fun observeUserInterfaceSettings() {
preferenceViewModel.setShowTime(preferenceHelper.showTime)
preferenceViewModel.setShowDate(preferenceHelper.showDate)
preferenceViewModel.setShowDailyWord(preferenceHelper.showDailyWord)
preferenceViewModel.setShowBattery(preferenceHelper.showBattery)
preferenceViewModel.showTimeLiveData.observe(viewLifecycleOwner) {
Log.d("Tag", "ShowTime Home: $it")
//updateViewVisibility(binding.clock, showTime)
appHelper.updateUI(binding.clock,
preferenceHelper.homeTimeAlignment,
preferenceHelper.timeColor,
preferenceHelper.timeTextSize,
preferenceHelper.showTime
)
}
preferenceViewModel.showDateLiveData.observe(viewLifecycleOwner) {
appHelper.updateUI(binding.date,
preferenceHelper.homeDateAlignment,
preferenceHelper.dateColor,
preferenceHelper.timeTextSize,
preferenceHelper.showDate
)
}
preferenceViewModel.showBatteryLiveData.observe(viewLifecycleOwner){
//binding.battery.setTextColor(preferenceHelper.batteryColor)
appHelper.updateUI(binding.battery, Gravity.END,
preferenceHelper.batteryColor,
preferenceHelper.timeTextSize,
preferenceHelper.showBattery
)
}
preferenceViewModel.showDailyWordLiveData.observe(viewLifecycleOwner) {
// updateViewVisibility(binding.word, showDailyWord)
// appHelper.updateUI(binding.word, preferenceHelper.homeDailyWordAlignment, preferenceHelper.dailyWordColor, preferenceHelper.showDailyWord)
}
val is24HourFormat = DateFormat.is24HourFormat(requireContext())
val localLocale = Locale.getDefault()
val best12 = DateFormat.getBestDateTimePattern(localLocale, "hmma")
val best24 = DateFormat.getBestDateTimePattern(localLocale, "HHmm")
val timePattern = if (is24HourFormat) best24 else best12
binding.clock.format12Hour = timePattern
binding.clock.format24Hour = timePattern
val datePattern = DateFormat.getBestDateTimePattern(localLocale, "eeeddMMM")
binding.date.format12Hour = datePattern
binding.date.format24Hour = datePattern
}
private fun observeBioAuthCheck(appInfo: AppInfo) {
if (!appInfo.lock) appHelper.launchApp(context, appInfo) else fingerHelper.startFingerprintAuth(appInfo, this)
}
private fun showSelectedApp(appInfo: AppInfo) {
val bottomSheetFragment = AppInfoBottomSheetFragment(appInfo)
bottomSheetFragment.setOnBottomSheetDismissedListener(this)
bottomSheetFragment.setOnAppStateClickListener(this)
bottomSheetFragment.show(parentFragmentManager, "BottomSheetDialog")
}
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
override fun onLongClick() {
super.onLongClick()
val intent = Intent(requireActivity(), SettingsActivity::class.java)
requireActivity().startActivity(intent)
return
}
@RequiresApi(Build.VERSION_CODES.P)
override fun onDoubleClick() {
super.onDoubleClick()
if(preferenceHelper.tapLockScreen) { MyAccessibilityService.instance()?.lockScreen() } else { return }
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
requireActivity().unregisterReceiver(batteryReceiver)
}
override fun onPause() {
super.onPause()
}
override fun onResume() {
super.onResume()
observeUserInterfaceSettings()
observeFavoriteAppList()
}
override fun onAppClicked(appInfo: AppInfo) {
observeBioAuthCheck(appInfo)
}
override fun onAppLongClicked(appInfo: AppInfo) {
showSelectedApp(appInfo)
Log.d("Tag", "Home LiveData Favorite : ${appInfo.favorite}")
}
override fun onBottomSheetDismissed() {
}
override fun onAppStateClicked(appInfo: AppInfo) {
viewModel.update(appInfo)
Log.d("Tag", "${appInfo.appName} : Home Favorite: ${appInfo.favorite}")
}
override fun onAuthenticationSucceeded(appInfo: AppInfo) {
appHelper.launchApp(context, appInfo)
appHelper.showToast(context, getString(R.string.authentication_succeeded))
}
override fun onAuthenticationFailed() {
appHelper.showToast(context, getString(R.string.authentication_failed))
}
override fun onAuthenticationError(errorCode: Int, errorMessage: CharSequence?) {
appHelper.showToast(context, getString(R.string.authentication_error))
}
override fun onTopReached() {
appHelper.expandNotificationDrawer(context)
}
override fun onBottomReached() {
appHelper.searchView(context)
}
override fun onScroll(isTopReached: Boolean, isBottomReached: Boolean) {
Log.d("Tag", "onScroll")
}
}

View File

@@ -0,0 +1,45 @@
package com.github.droidworksstudio.launcher.ui.home
import android.util.Log
import android.view.View
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.databinding.ItemHomeBinding
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
import javax.inject.Inject
class HomeViewHolder @Inject constructor(
private val binding: ItemHomeBinding,
private val onAppClickedListener: OnItemClickedListener.OnAppsClickedListener,
private val onAppLongClickedListener: OnItemClickedListener.OnAppLongClickedListener,
private val preferenceHelper: PreferenceHelper
) : RecyclerView.ViewHolder(binding.root) {
fun bind(appInfo: AppInfo) {
binding.apply {
val layoutParams = LinearLayoutCompat.LayoutParams(
LinearLayoutCompat.LayoutParams.WRAP_CONTENT,
LinearLayoutCompat.LayoutParams.WRAP_CONTENT
).apply {
gravity = preferenceHelper.homeAppAlignment
}
appHomeName.layoutParams = layoutParams
appHomeName.text = appInfo.appName
appHomeName.setTextColor(preferenceHelper.appColor)
appHomeName.textSize = preferenceHelper.appTextSize
Log.d("Tag", "Home Adapter Color: ${preferenceHelper.appColor}")
appHomeIcon.visibility = View.GONE
}
itemView.setOnClickListener { onAppClickedListener.onAppClicked(appInfo) }
itemView.setOnLongClickListener {
onAppLongClickedListener.onAppLongClicked(appInfo)
true
}
}
}

View File

@@ -0,0 +1,144 @@
package com.github.droidworksstudio.launcher.ui.settings
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.FragmentSettingsBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.AlignmentBottomSheetDialogFragment
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.ColorBottomSheetDialogFragment
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.TextBottomSheetDialogFragment
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class SettingsFragment : Fragment(), ScrollEventListener {
private var _binding: FragmentSettingsBinding? = null
private val binding get() = _binding!!
//private val viewModel: AppViewModel by viewModels()
private val preferenceViewModel: PreferenceViewModel by viewModels()
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var appHelper: AppHelper
private lateinit var navController: NavController
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
_binding = FragmentSettingsBinding.inflate(inflater, container, false)
_binding = binding
return binding.root
}
// Called after the fragment view is created
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// Set according to the system theme mode
appHelper.dayNightMod(requireContext(), binding.nestScrollView)
super.onViewCreated(view, savedInstanceState)
initializeInjectedDependencies()
observeClickListener()
}
private fun initializeInjectedDependencies() {
navController = findNavController()
binding.nestScrollView.scrollEventListener = this
// Set initial values and listeners for switches
binding.statueBarSwitchCompat.isChecked = preferenceHelper.showStatusBar
binding.timeSwitchCompat.isChecked = preferenceHelper.showTime
binding.dateSwitchCompat.isChecked = preferenceHelper.showDate
binding.batterySwitchCompat.isChecked = preferenceHelper.showBattery
binding.gesturesLockSwitchCompat1.isChecked = preferenceHelper.tapLockScreen
}
private fun observeClickListener() {
setupSwitchListeners()
// Click listener for reset default launcher
binding.setLauncherSelector.setOnClickListener {
appHelper.resetDefaultLauncher(requireContext())
}
binding.favoriteText.setOnClickListener {
findNavController().navigate(R.id.action_SettingsFragment_to_FavoriteFragment)
}
binding.hiddenText.setOnClickListener {
findNavController().navigate(R.id.action_SettingsFragment_to_HiddenFragment)
}
binding.setAppWallpaper.setOnClickListener {
val intent = Intent(Intent.ACTION_SET_WALLPAPER)
startActivity(Intent.createChooser(intent, "Select Wallpaper"))
}
binding.selectAppearanceTextSize.setOnClickListener {
val bottomSheetFragment = TextBottomSheetDialogFragment(this.requireContext())
bottomSheetFragment.show(parentFragmentManager, "BottomSheetDialog")
}
binding.selectAppearanceAlignment.setOnClickListener {
val bottomSheetFragment = AlignmentBottomSheetDialogFragment(this.requireContext())
bottomSheetFragment.show(parentFragmentManager, "BottomSheetDialog")
}
binding.selectAppearanceColor.setOnClickListener {
val bottomSheetFragment = ColorBottomSheetDialogFragment(this.requireContext())
bottomSheetFragment.show(parentFragmentManager, "BottomSheetDialog")
}
}
private fun setupSwitchListeners() {
binding.statueBarSwitchCompat.setOnCheckedChangeListener { _, isChecked ->
preferenceViewModel.setShowStatusBar(isChecked)
}
binding.timeSwitchCompat.setOnCheckedChangeListener { _, isChecked ->
preferenceViewModel.setShowTime(isChecked)
}
binding.dateSwitchCompat.setOnCheckedChangeListener { _, isChecked ->
preferenceViewModel.setShowDate(isChecked)
}
binding.batterySwitchCompat.setOnCheckedChangeListener { _, isChecked ->
preferenceViewModel.setShowBattery(isChecked)
}
binding.gesturesLockSwitchCompat1.setOnCheckedChangeListener { _, isChecked ->
appHelper.enableAppAsAccessibilityService(requireContext(), preferenceHelper.tapLockScreen)
preferenceViewModel.setDoubleTapLock(isChecked)
}
}
override fun onTopReached() {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
override fun onBottomReached() {
Log.d("Tag", "onBottomReached")
}
override fun onScroll(isTopReached: Boolean, isBottomReached: Boolean) {
Log.d("Tag", "onScroll")
}
}

View File

@@ -0,0 +1,27 @@
package com.github.droidworksstudio.launcher.ui.viewpager
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.github.droidworksstudio.launcher.ui.drawer.DrawFragment
import com.github.droidworksstudio.launcher.ui.home.HomeFragment
class ViewPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
FragmentStateAdapter(fragmentManager, lifecycle) {
private val fragments: ArrayList<Fragment> = arrayListOf(
HomeFragment(),
DrawFragment(),
)
override fun getItemCount(): Int {
return fragments.size
}
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
}

View File

@@ -0,0 +1,106 @@
package com.github.droidworksstudio.launcher.view
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.ViewConfiguration
import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
class GestureNestedScrollView(context: Context, attrs: AttributeSet) : NestedScrollView(context, attrs){
private var startY: Float = 0f
private var startTouchY: Float = 0f
private var isTopReached: Boolean = false
private var isBottomReached: Boolean = false
private var isScrollingUp: Boolean = false
private var isPullingDown: Boolean = false
private var isPullingUp: Boolean = false
var scrollEventListener: ScrollEventListener? = null
init {
isNestedScrollingEnabled = true
}
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
when (ev.action) {
MotionEvent.ACTION_DOWN -> {
startY = ev.y
startTouchY = ev.y
isScrollingUp = false
isPullingDown = false
isPullingUp = false
}
MotionEvent.ACTION_MOVE -> {
val deltaY = ev.y - startY
isTopReached = !canScrollVertically(-1)
isBottomReached = !canScrollVertically(1)
isScrollingUp = deltaY < 0 && isTopReached
val distanceY = ev.y - startTouchY
val threshold = ViewConfiguration.get(context).scaledTouchSlop.toFloat()
isPullingDown = distanceY > threshold && isTopReached
isPullingUp = distanceY < -threshold && isBottomReached
}
}
return super.onInterceptTouchEvent(ev)
}
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(ev: MotionEvent): Boolean {
when (ev.action) {
MotionEvent.ACTION_DOWN -> {
startY = ev.y
startTouchY = ev.y
isScrollingUp = false
isPullingDown = false
isPullingUp = false
}
MotionEvent.ACTION_MOVE -> {
val deltaY = ev.y - startY
isTopReached = !canScrollVertically(-1)
isBottomReached = !canScrollVertically(1)
isScrollingUp = deltaY < 0 && isTopReached
val distanceY = ev.y - startTouchY
val threshold = 200
isPullingDown = distanceY > threshold && isTopReached
isPullingUp = distanceY < -threshold && isBottomReached
}
MotionEvent.ACTION_UP -> {
startY = 0f
if (isPullingDown) {
scrollEventListener?.onTopReached()
return true
} else if (isPullingUp) {
scrollEventListener?.onBottomReached()
return true
}
}
}
return super.onTouchEvent(ev)
}
fun isTopReached(): Boolean {
return !canScrollVertically(-1)
// return isTopReached && isScrollingUp
}
fun isBottomReached(): Boolean {
return !canScrollVertically(1)
// return isBottomReached && !isScrollingUp
}
fun registerRecyclerView(recyclerView: RecyclerView, eventListener: ScrollEventListener) {
scrollEventListener = eventListener
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
scrollEventListener?.onScroll(isTopReached(), isBottomReached())
}
})
}
}

View File

@@ -0,0 +1,68 @@
package com.github.droidworksstudio.launcher.viewmodel
import android.content.Context
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.github.droidworksstudio.launcher.data.entities.AppInfo
import com.github.droidworksstudio.launcher.repository.AppInfoRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
@HiltViewModel
class AppViewModel @Inject constructor(
private val appInfoRepository: AppInfoRepository
) : ViewModel() {
val drawApps: Flow<List<AppInfo>> = appInfoRepository.getDrawApps().conflate()
val favoriteApps: Flow<List<AppInfo>> = appInfoRepository.getFavoriteApps().conflate()
val hiddenApps: Flow<List<AppInfo>> = appInfoRepository.getHiddenApps().conflate()
fun initializeInstalledAppInfo(context: Context) {
viewModelScope.launch {
appInfoRepository.initInstalledAppInfo(context)
}
}
fun updateAppInfoFavorite(appInfo: AppInfo) {
viewModelScope.launch {
appInfoRepository.updateFavoriteAppInfo(appInfo)
Log.d("Tag", "ViewModel Home Order : ${appInfo.appOrder}")
}
}
fun updateAppInfoAppName(appInfo: AppInfo, newAppName: String) {
viewModelScope.launch {
appInfoRepository.updateAppName(appInfo, newAppName)
Log.d("Tag", "ViewModel Home Name : ${appInfo.appName}")
}
}
fun updateAppHidden(appInfo: AppInfo, appHidden: Boolean) {
viewModelScope.launch {
appInfoRepository.updateAppHidden(appInfo, appHidden)
}
}
fun updateAppLock(appInfo: AppInfo, appLock: Boolean) {
viewModelScope.launch {
appInfoRepository.updateAppLock(appInfo, appLock)
}
}
fun compareInstalledAppInfo() {
viewModelScope.launch {
appInfoRepository.compareInstalledApp()
}
}
suspend fun updateAppOrder(appInfoList: List<AppInfo>) {
withContext(Dispatchers.IO) {
appInfoRepository.updateAppOrder(appInfoList)
}
}
fun update(appInfo: AppInfo) {
viewModelScope.launch {
appInfoRepository.updateInfo(appInfo)
}
}
fun searchAppInfo(query: String?) = appInfoRepository.searchNote(query)
}

View File

@@ -0,0 +1,122 @@
package com.github.droidworksstudio.launcher.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class PreferenceViewModel @Inject constructor(
private val preferenceHelper: PreferenceHelper)
: ViewModel() {
val firstLaunchLiveData: MutableLiveData<Boolean> = MutableLiveData()
val showStatusBarLiveData: MutableLiveData<Boolean> = MutableLiveData()
val showTimeLiveData: MutableLiveData<Boolean> = MutableLiveData()
val showDateLiveData: MutableLiveData<Boolean> = MutableLiveData()
val showDailyWordLiveData: MutableLiveData<Boolean> = MutableLiveData()
val showBatteryLiveData: MutableLiveData<Boolean> = MutableLiveData()
val homeAppAlignmentLiveData: MutableLiveData<Int> = MutableLiveData()
val homeDateAlignmentLiveData: MutableLiveData<Int> = MutableLiveData()
val homeTimeAlignmentLiveData: MutableLiveData<Int> = MutableLiveData()
val dateColorLiveData: MutableLiveData<Int> = MutableLiveData()
val timeColorLiveData: MutableLiveData<Int> = MutableLiveData()
val batteryColorLiveData: MutableLiveData<Int> = MutableLiveData()
val dailyWordColorLiveData: MutableLiveData<Int> = MutableLiveData()
val appColorLiveData: MutableLiveData<Int> = MutableLiveData()
val dateTextSizeLiveData: MutableLiveData<Float> = MutableLiveData()
val timeTextSizeLiveData: MutableLiveData<Float> = MutableLiveData()
val appTextSizeLiveData: MutableLiveData<Float> = MutableLiveData()
val tapLockScreenLiveData: MutableLiveData<Boolean> = MutableLiveData()
fun setFirstLaunch(firstLaunch: Boolean) {
preferenceHelper.firstLaunch = firstLaunch
firstLaunchLiveData.postValue(preferenceHelper.firstLaunch)
}
fun setShowStatusBar(showStatusBar: Boolean) {
preferenceHelper.showStatusBar = showStatusBar
showStatusBarLiveData.postValue(preferenceHelper.showStatusBar)
}
fun setShowTime(showTime: Boolean) {
preferenceHelper.showTime = showTime
showTimeLiveData.postValue(preferenceHelper.showTime)
}
fun setShowDate(showDate: Boolean) {
preferenceHelper.showDate = showDate
showDateLiveData.postValue(preferenceHelper.showDate)
}
fun setShowBattery(showBattery: Boolean){
preferenceHelper.showBattery = showBattery
showBatteryLiveData.postValue(preferenceHelper.showBattery)
}
fun setShowDailyWord(showDailyWord: Boolean) {
preferenceHelper.showDailyWord = showDailyWord
showDailyWordLiveData.postValue(preferenceHelper.showDailyWord)
}
fun setDailyWordColor(dailyWordColor: Int) {
preferenceHelper.dailyWordColor = dailyWordColor
dailyWordColorLiveData.postValue(preferenceHelper.dailyWordColor)
}
fun setAppColor(appColor: Int) {
preferenceHelper.appColor = appColor
appColorLiveData.postValue(preferenceHelper.appColor)
}
fun setDateColor(dateColor: Int) {
preferenceHelper.dateColor = dateColor
dateColorLiveData.postValue(preferenceHelper.dateColor)
}
fun setTimeColor(timeColor: Int) {
preferenceHelper.timeColor = timeColor
timeColorLiveData.postValue(preferenceHelper.timeColor)
}
fun setBatteryColor(batteryColor: Int){
preferenceHelper.batteryColor = batteryColor
batteryColorLiveData.postValue(preferenceHelper.batteryColor)
}
fun setHomeAppAlignment(homeAppAlignment: Int) {
preferenceHelper.homeAppAlignment = homeAppAlignment
homeAppAlignmentLiveData.postValue(preferenceHelper.homeAppAlignment)
}
fun setHomeDateAlignment(homeDateAlignment: Int) {
preferenceHelper.homeDateAlignment = homeDateAlignment
homeDateAlignmentLiveData.postValue(preferenceHelper.homeDateAlignment)
}
fun setHomeTimeAppAlignment(homeTimeAlignment: Int) {
preferenceHelper.homeTimeAlignment = homeTimeAlignment
homeTimeAlignmentLiveData.postValue(preferenceHelper.homeTimeAlignment)
}
fun setDateTextSize(dateTextSize: Float) {
preferenceHelper.dateTextSize = dateTextSize
dateTextSizeLiveData.postValue(preferenceHelper.dateTextSize)
}
fun setTimeTextSize(timeTextSize: Float) {
preferenceHelper.timeTextSize = timeTextSize
timeTextSizeLiveData.postValue(preferenceHelper.timeTextSize)
}
fun setAppTextSize(appTextSize: Float) {
preferenceHelper.appTextSize = appTextSize
appTextSizeLiveData.postValue(preferenceHelper.appTextSize)
}
fun setDoubleTapLock(tapLockScreen: Boolean){
preferenceHelper.tapLockScreen = tapLockScreen
tapLockScreenLiveData.postValue((preferenceHelper.tapLockScreen))
}
}

View File

@@ -0,0 +1,25 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
android:height="1024sp"
android:width="1024sp"
android:viewportHeight="1024"
android:viewportWidth="1024">
<path android:fillAlpha="0.098039"
android:fillColor="#FF000000"
android:pathData="m969.7,351.3q-8.6,-20.9 -19.4,-40.8c-4.1,-7.6 -8.4,-15.1 -12.9,-22.4 -19.5,-31.7 -43.4,-61.7 -71.6,-89.8 -92.2,-92.2 -203.4,-138.3 -333.8,-138.3s-241.6,46.1 -333.8,138.3 -138.3,203.4 -138.3,333.8 46.1,241.6 138.3,333.8 203.4,138.2 333.8,138.2 241.6,-46 333.8,-138.2c50.8,-50.8 87.6,-107.4 110.3,-169.8 18.5,-50.8 27.9,-105.5 27.9,-164.1 0,-44.9 -5.4,-87.6 -16.4,-127.9 -1.3,-4.6 -2.5,-9.1 -3.9,-13.6 -4.1,-13.3 -8.8,-26.4 -14.1,-39.2z"/>
<path android:fillColor="#e85479"
android:pathData="m982.1,517q0,-2.5 0,-4.9c0,-130.4 -46,-241.6 -138.2,-333.8 -91.9,-91.8 -202.9,-137.9 -332.8,-138.2v475h2v2z"/>
<path android:fillColor="#00c0e6"
android:pathData="m511.1,40.1c-0.3,0 -0.6,0 -1,0 -130.4,0 -241.6,46 -333.8,138.2s-138.2,203.4 -138.2,333.8v3h473z"/>
<path android:fillColor="#ebc240"
android:pathData="m513.1,517v-2h-2,-473c0.7,129.1 46.8,239.4 138.2,330.8 92.2,92.2 203.4,138.2 333.8,138.2h1,2z"/>
<path android:fillColor="#55da97"
android:pathData="m513.1,517v467c129.1,-0.8 239.4,-46.8 330.8,-138.2 90.9,-91 137.1,-200.6 138.2,-328.9z"/>
<path android:fillColor="#fff"
android:pathData="m862.5,528.8q0.3,-8.3 0.3,-16.8c0,-96.8 -34.3,-179.6 -102.7,-248 -68.5,-68.4 -151.2,-102.7 -248.1,-102.7s-179.6,34.3 -248,102.7 -102.7,151.1 -102.7,248 34.3,179.6 102.7,248.1c68.4,68.4 151.1,102.7 248,102.7 31.4,0 61.3,-3.6 89.8,-10.8 59.2,-15 112,-45.7 158.3,-91.9 64.4,-64.4 98.6,-141.4 102.3,-231.3z"/>
<path android:fillAlpha="0.098039"
android:fillColor="#FF000000"
android:pathData="m760.1,760.1q94.7,-94.8 102.1,-225.7l-177.1,-177.1 -56,34.5 -163.9,-4.6 -72.1,11.1v202.7l-44.5,68 192.7,192.7 0,0c21,-1.6 41.2,-4.8 60.5,-9.8 59.2,-15 112,-45.7 158.3,-91.9z"/>
<path android:fillColor="#96a6a6"
android:pathData="m692.5,387c0,-33.1 -26.8,-60 -60,-60 -33.1,0 -60,26.9 -60,60 0,29.2 20.9,53.5 48.2,59 -28.4,4.8 -50,29.4 -50,59.2 0,33.2 26.8,60 60,60 33.1,0 60,-26.8 60,-60 0,-29 -20.7,-53.3 -48.2,-58.8 28.4,-4.8 50,-29.5 50,-59.3zM629.5,685c33.2,0 60,-26.8 60,-60 0,-33.1 -26.8,-60 -60,-60 -33.1,0 -60,26.9 -60,60 0,33.2 26.9,60 60,60zM392.7,327.3c-33.1,0 -60,26.9 -60,60 0,16.6 5.9,30.7 17.6,42.4 11.5,11.5 25.4,17.4 41.6,17.5 -16.3,0.2 -30.1,6.1 -41.6,17.5 -11.7,11.7 -17.6,25.9 -17.6,42.4 0,33.2 26.9,60 60,60 29.3,0 53.7,-21 59,-48.9 5.4,28 29.8,48.9 59,48.9q24.9,0 42.4,-17.6 17.6,-17.5 17.6,-42.4c0,-29 -20.7,-53.3 -48.3,-58.9 28.5,-4.8 50.1,-29.4 50.1,-59.2 0,-33.1 -26.8,-60 -60,-60 -33.1,0 -60,26.9 -60,60 0,29.2 20.9,53.5 48.2,59 -24.9,4.2 -44.5,23.6 -49.1,48.2 -2.1,-11.9 -7.6,-22.4 -16.6,-31.4 -11.4,-11.5 -25.4,-17.4 -41.7,-17.5 16.3,-0.2 30.2,-6.1 41.7,-17.5 11.7,-11.7 17.5,-25.8 17.5,-42.4 0,-33.1 -26.8,-60 -60,-60zM569.5,627.2c0,-33.1 -26.9,-60 -60,-60 -29.3,0 -53.8,21.1 -59,48.8 -5.3,-27.8 -29.7,-48.8 -59,-48.8 -33.1,0 -60,26.9 -60,60 0,33.2 26.9,60 60,60 29.3,0 53.6,-20.9 59,-48.8 5.5,28 29.9,48.8 59,48.8 33.2,0 60,-26.8 60,-60z"/>
</vector>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:shape="rectangle">
<solid android:color="@android:color/white"/>
<corners
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:shape="rectangle">
<solid android:color="#333333"/>
<corners
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
</shape>

View File

@@ -0,0 +1,4 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="16dp" />
<solid android:color="?android:colorBackground" />
</shape>

View File

@@ -0,0 +1,5 @@
<vector android:height="16dp" android:tint="@android:color/darker_gray"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#33000000"/>
<stroke android:width="0dp"
android:color="@android:color/black"/>
<corners android:radius="12dp" />
</shape>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_switch_track_off" android:state_checked="false" />
<item android:drawable="@drawable/shape_switch_track_on" android:state_checked="true" />
</selector>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size
android:width="24dp"
android:height="24dp" />
<solid android:color="@color/white" />
<stroke
android:width="6dp"
android:color="#00ffffff"/>
</shape>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:height="20dp"/>
<size android:width="50dp"/>
<corners android:radius="20dp"/>
<gradient
android:endColor="#DCDCDC"
android:startColor="#B6B6B6" />
</shape>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:height="20dp"/>
<size android:width="50dp"/>
<corners android:radius="20dp"/>
<gradient
android:endColor="#56AFE2"
android:startColor="#56AFE2" />
</shape>

View File

@@ -0,0 +1,7 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activities.FakeHomeActivity">
</merge>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activities.MainActivity">
<fragment
android:id="@+id/nav_host_fragment_content_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent" />
<!--include layout="@layout/content_main"-->
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activities.LauncherActivity">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activities.SettingsActivity">
<include layout="@layout/content_settings"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:id="@+id/dialog_background">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/transparent"
android:layout_margin="12dp">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="12dp"
android:textSize="@dimen/text_super_large"
android:id="@+id/alignment_title"
style="@style/TextDefaultStyle">
</androidx.appcompat.widget.AppCompatTextView>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="12dp"
android:textSize="@dimen/text_large"
android:text="@string/bottom_alignment_star"
android:id="@+id/alignment_star"
style="@style/TextDefaultStyle">
</androidx.appcompat.widget.AppCompatTextView>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="12dp"
android:textSize="@dimen/text_large"
android:text="@string/bottom_alignment_center"
android:id="@+id/alignment_center"
style="@style/TextDefaultStyle">
</androidx.appcompat.widget.AppCompatTextView>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="12dp"
android:textSize="@dimen/text_large"
android:text="@string/bottom_alignment_end"
android:id="@+id/alignment_end"
style="@style/TextDefaultStyle">
</androidx.appcompat.widget.AppCompatTextView>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottom_sheet0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:orientation="horizontal"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/bottom_sheet_rename"
style="@style/TextDefaultStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="@string/bottom_dialog_app_rename"
android:textSize="@dimen/bottom_dialog_text_large"></androidx.appcompat.widget.AppCompatEditText>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/bottom_sheet_rename_done"
style="@style/TextDefaultStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:gravity="center"
android:text="Save"
android:textSize="@dimen/bottom_dialog_text_small" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:orientation="horizontal"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/bottom_sheet_fav_hidden"
style="@style/TextDefaultStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bottom_dialog_remove_from_home"
android:textSize="@dimen/bottom_dialog_text_large">
</androidx.appcompat.widget.AppCompatTextView>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:orientation="horizontal"
android:visibility="gone"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/bottom_sheet_order"
style="@style/TextDefaultStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bottom_dialog_order_home_apps"
android:textSize="@dimen/bottom_dialog_text_large">
</androidx.appcompat.widget.AppCompatTextView>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:orientation="horizontal"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/bottom_sheet_hidden"
style="@style/TextDefaultStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bottom_dialog_add_to_hidden"
android:textSize="@dimen/bottom_dialog_text_large">
</androidx.appcompat.widget.AppCompatTextView>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:orientation="horizontal"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/bottom_sheet_lock"
style="@style/TextDefaultStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bottom_dialog_add_to_lock"
android:textSize="@dimen/bottom_dialog_text_large">
</androidx.appcompat.widget.AppCompatTextView>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:orientation="horizontal"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/bottom_sheet_uninstall"
style="@style/TextDefaultStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bottom_dialog_app_uninstall"
android:textSize="@dimen/bottom_dialog_text_large">
</androidx.appcompat.widget.AppCompatTextView>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottom_sheet4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:orientation="horizontal"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/bottom_sheet_info"
style="@style/TextDefaultStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/bottom_dialog_app_info"
android:textSize="@dimen/bottom_dialog_text_large">
</androidx.appcompat.widget.AppCompatTextView>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:text="@string/appearance_bottom_dialog_alignment_title"
android:textAlignment="textStart"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottom_alignment_date_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_date_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:background="@android:color/transparent"
android:gravity="left|center"
android:inputType="number"
android:text="@string/appearance_bottom_dialog_desc_date"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_date_text_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottom_alignment_time_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_time_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:text="@string/appearance_bottom_dialog_desc_time"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_time_text_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottom_alignment_app_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_app_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:text="@string/appearance_bottom_dialog_desc_app"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_app_text_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:text="@string/appearance_bottom_dialog_text_color_title"
android:textAlignment="textStart"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottom_color_date_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_date_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:background="@android:color/transparent"
android:gravity="left|center"
android:inputType="number"
android:text="@string/appearance_bottom_dialog_desc_date"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_date_text_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottom_color_time_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_time_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:text="@string/appearance_bottom_dialog_desc_time"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_time_text_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottom_color_app_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_app_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:text="@string/appearance_bottom_dialog_desc_app"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_app_text_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:gravity="left|center"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/bottom_color_battery_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_battery_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:text="@string/appearance_bottom_dialog_desc_battery"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_battery_text_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:gravity="left|center"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/textSizeSave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:text="@string/settings_appearance_text_size_title"
android:textAlignment="textStart"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_date_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:background="@android:color/transparent"
android:gravity="left|center"
android:inputType="number"
android:text="@string/appearance_bottom_dialog_desc_date"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/select_date_text_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_time_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:text="@string/appearance_bottom_dialog_desc_time"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/select_time_text_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/select_app_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:text="@string/appearance_bottom_dialog_desc_app"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/select_app_text_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:gravity="left|center"
android:background="@android:color/transparent"
android:textSize="@dimen/text_large"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<fragment
android:id="@+id/nav_host_fragment_content_settings"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/settings_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/draw_background"
tools:context=".ui.drawer.DrawFragment">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginVertical="32dp"
android:layout_marginHorizontal="20dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/searchViewContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginVertical="16dp"
android:clickable="true"
android:focusable="true">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/search_view1"
android:layout_width="match_parent"
android:layout_height="64dp"
android:hint="search"
android:textSize="@dimen/text_super_large"
android:textStyle="normal"
android:background="@android:color/transparent"
android:inputType="text"
style="@style/TextDefaultStyle">
</androidx.appcompat.widget.AppCompatEditText>
<!--androidx.appcompat.widget.SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"/-->
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/drawAdapter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/draw_search_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.FloatingActionButton"
android:clickable="true"
app:backgroundTint="@color/search_button_background"
android:src="?android:attr/actionModeWebSearchDrawable"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_margin="32dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/favorite_view"
tools:context=".ui.favorite.FavoriteFragment">
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:clickable="true"
android:focusable="true"
android:layout_height="match_parent"
android:layout_marginVertical="32dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/topTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="Home App Order"
android:textSize="@dimen/text_super_large"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
style="@style/TextDefaultStyle"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/favoriteAdapter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="92dp"
app:layout_constraintTop_toBottomOf="@id/topTextView"
/>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/hidden_view"
tools:context=".ui.favorite.FavoriteFragment">
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:clickable="true"
android:focusable="true"
android:layout_height="match_parent"
android:layout_marginVertical="32dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/topTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="Hidden App"
android:textSize="@dimen/text_super_large"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/hiddenAdapter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="92dp"
app:layout_constraintTop_toBottomOf="@id/topTextView"
/>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical"
android:longClickable="true"
tools:context=".ui.home.HomeFragment">
<com.github.droidworksstudio.launcher.view.GestureNestedScrollView
android:id="@+id/nestScrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:clipChildren="false"
android:clipToPadding="false"
android:fadingEdgeLength="48dp"
android:overScrollMode="never"
android:requiresFadingEdge="vertical"
android:scrollbars="none">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/mainView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="32dp"
android:orientation="vertical">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/battery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="Battery"
android:textSize="16sp"
style="@style/TextDefaultStyle"/>
<TextClock
android:id="@+id/clock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginVertical="16dp"
android:fontFamily="sans-serif-light"
android:format12Hour="h:mm"
android:textSize="48sp"
tools:text="02:34"
style="@style/TextDefaultStyle"/>
<TextClock
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="8dp"
android:format12Hour="EEE, dd MMM"
android:format24Hour="EEE, dd MMM"
android:gravity="start"
android:paddingHorizontal="2dp"
android:textSize="32sp"
tools:text="Thu, 30 Dec"
style="@style/TextDefaultStyle"/>
<!--TextView
android:id="@+id/word"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/settings_appearance_daily_word_default"
android:textSize="32sp"
android:visibility="gone"
android:layout_marginBottom="42dp" /-->
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/appListAdapter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
</com.github.droidworksstudio.launcher.view.GestureNestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,421 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.settings.SettingsFragment">
<com.github.droidworksstudio.launcher.view.GestureNestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nestScrollView"
android:clipChildren="false"
android:clipToPadding="false"
android:fadingEdgeLength="48dp"
android:overScrollMode="never"
android:requiresFadingEdge="vertical"
android:scrollbars="none">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginVertical="32dp"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="48dp"
android:text="@string/settings_name"
android:textSize="@dimen/text_super_large"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/set_launcher_selector"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="18dp"
android:text="@string/action_settings_default"
android:textSize="@dimen/text_large"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/settings_title_home_display_preferences"
android:textSize="@dimen/text_super_large"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/statue_bar_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_statue_bar"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/statue_bar_switchCompat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="0.7"
android:scaleY="0.8"
android:thumb="@drawable/shape_switch_thumb"
app:track="@drawable/selector_switch"
tools:ignore="DuplicateSpeakableTextCheck,TouchTargetSizeCheck" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/date_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_date"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/date_switchCompat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="0.7"
android:scaleY="0.8"
android:thumb="@drawable/shape_switch_thumb"
app:track="@drawable/selector_switch"
tools:ignore="TouchTargetSizeCheck" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/time_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_time"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/time_switchCompat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="0.7"
android:scaleY="0.8"
android:thumb="@drawable/shape_switch_thumb"
app:track="@drawable/selector_switch"
tools:ignore="TouchTargetSizeCheck" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/battery_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_battery"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/battery_switchCompat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="0.7"
android:scaleY="0.8"
android:thumb="@drawable/shape_switch_thumb"
app:track="@drawable/selector_switch"
tools:ignore="TouchTargetSizeCheck" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/settings_title_home_appearance_preferences"
android:textSize="@dimen/text_super_large"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/select_appearance_text_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_text_size_title"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/select_appearance_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_color_title"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/select_appearance_alignment"
android:layout_width="match_parent"
android:layout_height="28dp"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
tools:ignore="MissingConstraints,TextSizeCheck">
<androidx.appcompat.widget.AppCompatTextView
style="@style/TextDefaultStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_alignment_title"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/set_app_wallpaper"
android:layout_width="match_parent"
android:layout_height="28dp"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
tools:ignore="MissingConstraints,TextSizeCheck">
<androidx.appcompat.widget.AppCompatTextView
style="@style/TextDefaultStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_wallpaper"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/settings_title_app_manager"
android:textSize="@dimen/text_super_large"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/favorite_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_manager_favorite"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="28dp"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="20dp"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/hidden_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_manager_hidden"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/settings_title_gestures"
android:textSize="@dimen/text_super_large"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/gestures_lock_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_double_tap_lock"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/gestures_lock_switchCompat1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:thumb="@drawable/shape_switch_thumb"
app:track="@drawable/selector_switch"
android:scaleY="0.8"
android:scaleX="0.7"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/settings_title_others"
android:textSize="@dimen/text_super_large"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</com.github.droidworksstudio.launcher.view.GestureNestedScrollView>
</FrameLayout>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginVertical="16dp"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/appDraw_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginVertical="16dp"
android:textSize="@dimen/text_super_large"
android:textStyle="normal"
style="@style/TextDefaultStyle"
android:layout_gravity="start"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/appFavorite_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:layout_weight="1"
android:gravity="left|center"
android:textSize="24sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/appFavorite_drag_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:layout_marginHorizontal="16dp"
android:background="@drawable/icon_favorite_order" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/appHidden_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:layout_weight="1"
android:gravity="left|center"
android:textSize="24sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/appHome_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:layout_marginEnd="16dp"
android:visibility="visible"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/appHome_name"
android:layout_width="match_parent"
android:layout_height="48dp"
android:textSize="24sp"
style="@style/TextDefaultStyle"
android:gravity="center"/>
<!--TextView
android:id="@+id/package_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textAlignment="center"
android:visibility="gone"/-->
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,10 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.github.droidworksstudio.launcher.ui.activities.MainActivity">
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@id/HomeFragment">
<fragment
android:id="@+id/HomeFragment"
android:name="com.github.droidworksstudio.launcher.ui.home.HomeFragment"
android:label="@string/home_fragment_label"
tools:layout="@layout/fragment_home">
<action
android:id="@+id/action_HomeFragment_to_DrawFragment"
app:destination="@id/DrawFragment" />
<action
android:id="@+id/action_HomeFragment_to_SettingsFragment"
app:destination="@id/SettingsFragment" />
<action
android:id="@+id/action_HomeFragment_to_FavoriteFragment"
app:destination="@id/FavoriteFragment" />
</fragment>
<fragment
android:id="@+id/DrawFragment"
android:name="com.github.droidworksstudio.launcher.ui.drawer.DrawFragment"
android:label="@string/draw_fragment_label"
tools:layout="@layout/fragment_draw">
</fragment>
</navigation>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@id/SettingsFragment">
<fragment
android:id="@+id/SettingsFragment"
android:name="com.github.droidworksstudio.launcher.ui.settings.SettingsFragment"
android:label="@string/home_fragment_label"
tools:layout="@layout/fragment_settings">
<action
android:id="@+id/action_SettingsFragment_to_FavoriteFragment"
app:destination="@id/FavoriteFragment" />
<action
android:id="@+id/action_SettingsFragment_to_HiddenFragment"
app:destination="@id/HiddenFragment" />
</fragment>
<fragment
android:id="@+id/FavoriteFragment"
android:name="com.github.droidworksstudio.launcher.ui.favorite.FavoriteFragment"
android:label="@string/draw_fragment_label"
tools:layout="@layout/fragment_favorite">
</fragment>
<fragment
android:id="@+id/HiddenFragment"
android:name="com.github.droidworksstudio.launcher.ui.hidden.HiddenFragment"
android:label="@string/draw_fragment_label"
tools:layout="@layout/fragment_favorite">
</fragment>
</navigation>

View File

@@ -0,0 +1 @@
<resources></resources>

View File

@@ -0,0 +1,83 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Launcher" parent="Theme.MaterialComponents.NoActionBar">
<item name="android:windowDisablePreview">true</item>
<!-- Primary brand color. -->
<item name="colorPrimary">@color/teal_700</item>
<item name="colorPrimaryVariant">@color/teal_200</item>
<item name="colorOnPrimary">?attr/color</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/white</item>
<item name="colorSurface">@color/black</item>
<item name="primaryTextShadowColor">@color/whiteTrans50</item>
<item name="primaryShadeDarkColor">@color/blackTrans25</item>
<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges
</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:colorEdgeEffect">@android:color/transparent</item>
<item name="android:fitsSystemWindows">false</item>
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowLightStatusBar">false</item>
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<!-- <item name="android:enforceStatusBarContrast">false</item>-->
<item name="android:enforceNavigationBarContrast" tools:targetApi="q">false</item>
<!-- custom bottom_dialog -->
<item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item>
<!-- custom dialog -->
<item name="materialAlertDialogTheme">@style/CustomAlertDialog</item>
</style>
<!-- Base application theme. -->
<style name="AppBottomSheetDialogTheme" parent="Theme.Design.BottomSheetDialog">
<item name="bottomSheetStyle">@style/AppModalStyle</item>
</style>
<style name="AppModalStyle" parent="Theme.Design.BottomSheetDialog">
<item name="android:background">@drawable/bottom_dialog_style_night</item>
</style>
<style name="CustomAlertDialog" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="shapeAppearanceOverlay">@style/RoundedCorners</item>
</style>
<style name="RoundedCorners">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">16dp</item>
</style>
<style name="TextDefaultStyle" parent="@android:style/TextAppearance.Large">
<item name="android:shadowColor">?attr/primaryTextShadowColor</item>
<item name="android:shadowDx">1</item>
<item name="android:shadowDy">1</item>
<item name="android:shadowRadius">2</item>
</style>
</resources>

View File

@@ -0,0 +1 @@
<resources></resources>

View File

@@ -0,0 +1 @@
<resources></resources>

View File

@@ -0,0 +1,8 @@
<resources>
<declare-styleable name="FullscreenAttrs">
<attr name="fullscreenBackgroundColor" format="color" />
<attr name="fullscreenTextColor" format="color" />
<attr name="primaryTextShadowColor" format="color" />
<attr name="primaryShadeDarkColor" format="color" />
</declare-styleable>
</resources>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="search_view_hint">#FFFFFFFF</color>
<color name="search_button_background">#56A1E6</color>
<color name="dialog_background">#333333</color>
<!-- Black -->
<color name="black">#000000</color>
<color name="blackTrans10">#1A000000</color>
<color name="blackTrans25">#30000000</color>
<color name="blackTrans50">#80000000</color>
<color name="blackTrans80">#CC000000</color>
<color name="blackTrans90">#E6000000</color>
<!-- White -->
<color name="white">#FFFFFF</color>
<color name="whiteTrans10">#1AFFFFFF</color>
<color name="whiteTrans25">#30FFFFFF</color>
<color name="whiteTrans50">#65FFFFFF</color>
<color name="whiteTrans80">#CCFFFFFF</color>
<color name="whiteTrans90">#E6FFFFFF</color>
</resources>

View File

@@ -0,0 +1,9 @@
<resources>
<dimen name="bottom_dialog_text_small" >14sp</dimen>
<dimen name="bottom_dialog_text_large" >18sp</dimen>
<dimen name="text_large" >18sp</dimen>
<dimen name="text_super_large" >24sp</dimen>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="action_HomeFragment_to_SettingsFragment" type="id" />
</resources>

View File

@@ -0,0 +1,104 @@
<resources>
<string name="action_settings">Settings</string>
<string name="action_settings_default">Set as default launcher</string>
<!-- Strings used for fragments for navigation -->
<string name="home_fragment_label">Home Fragment</string>
<string name="draw_fragment_label">Draw Fragment</string>
<string name="battery_level">%s%%</string>
<string name="bottom_dialog_app_rename">Rename</string>
<string name="bottom_dialog_add_to_home">Add to Home Screen</string>
<string name="bottom_dialog_order_home_apps">Order Home Apps</string>
<string name="bottom_dialog_remove_from_home">Remove from Home Screen</string>
<string name="bottom_dialog_add_to_hidden">Hidden App</string>
<string name="bottom_dialog_remove_to_hidden">Remove Hidden App</string>
<string name="bottom_dialog_add_to_lock">Lock App</string>
<string name="bottom_dialog_remove_to_unlock">Unlock App</string>
<string name="bottom_dialog_app_info">App Info</string>
<string name="bottom_dialog_app_uninstall">Uninstall App</string>
<string name="settings_name">Launcher Settings</string>
<string name="settings_home">Home</string>
<string name="settings_title_home_display_preferences">Display</string>
<string name="settings_title_home_appearance_preferences">Appearance</string>
<string name="settings_title_date_style">Date Style</string>
<string name="settings_title_time_style">Time Style</string>
<string name="settings_title_app_manager">App Manage</string>
<string name="settings_title_gestures">Gestures</string>
<string name="settings_title_others">Others</string>
<string name="settings_appearance_statue_bar">Show Statue Bar</string>
<string name="settings_appearance_date">Show Date</string>
<string name="settings_appearance_time">Show Time</string>
<string name="settings_appearance_battery">Show Battery</string>
<string name="settings_appearance_daily_word">Show Daily Word</string>
<string name="settings_appearance_daily_word_default">Keep Going</string>
<string name="settings_appearance_color_title">Color</string>
<string name="settings_appearance_text_size_title">Size</string>
<string name="settings_appearance_alignment_title">Alignment</string>
<string name="settings_appearance_date_color">Select Date Color</string>
<string name="settings_appearance_time_color">Select Time Color</string>
<string name="settings_appearance_battery_color">Select Battery Color</string>
<string name="settings_appearance_daily_word_color">Select Daily Word Color</string>
<string name="settings_appearance_app_display_color">Select App Color</string>
<string name="settings_appearance_date_size_title">Date Size : </string>
<string name="settings_appearance_time_size_title">Time Size : </string>
<string name="settings_appearance_app_size_title">App Size : </string>
<string name="appearance_bottom_dialog_text_size_title">Size</string>
<string name="appearance_bottom_dialog_text_color_title">Color</string>
<string name="appearance_bottom_dialog_alignment_title">Alignment</string>
<string name="appearance_bottom_dialog_desc_date">Date\u0020:\u0020</string>
<string name="appearance_bottom_dialog_desc_time">Time\u0020:\u0020 </string>
<string name="appearance_bottom_dialog_desc_app">App\u0020:\u0020</string>
<string name="appearance_bottom_dialog_desc_battery">Battery\u0020:\u0020 </string>
<string name="settings_appearance_wallpaper">Custom Wallpaper</string>
<string name="settings_appearance_home_date_alignment">Date Alignment</string>
<string name="settings_appearance_home_time_alignment">Time Alignment</string>
<string name="settings_appearance_home_app_alignment">Home App Alignment</string>
<string name="settings_manager_favorite">Favorite Apps</string>
<string name="settings_manager_hidden">Hidden Apps</string>
<string name="settings_double_tap_lock">Double tap to lock</string>
<string name="settings_select_wallpaper">Select Wallpaper</string>
<string name="authentication_title">Authentication</string>
<string name="authentication_subtitle">Please login to get access</string>
<string name="authentication_cancel">Authentication Cancel</string>
<string name="authentication_succeeded">Authentication Succeeded</string>
<string name="authentication_failed">Authentication Failed</string>
<string name="authentication_error">Authentication Error</string>
<string name="bottom_alignment_star">Star</string>
<string name="bottom_alignment_center">Center</string>
<string name="bottom_alignment_end">End</string>
<string name="accessibility_settings_title">Accessibility Settings</string>
<string name="accessibility_settings_enable">Enable</string>
<string name="accessibility_settings_disable">Disable</string>
<string name="accessibility_service_desc">Please turn on accessibility service to use double tap to lock feature in Aster Launcher.\n\nThis permission
is used only to turn off your screen.Our accessibility service does not collect or share any data.</string>
<string name="receiver_name">Lock - screen locker</string>
<!-- Message displayed to the user by system during authorization-->
<!-- Small description inside Device Administrator Setting -->
<string name="receiver_desc">Allows to lock the screen</string>
<string name="admin_permission_message">Aster launcher promises to use lock screen permission responsibly.Aster launcher does not collect or share any data.</string>
<!-- TODO: Remove or change this placeholder text -->
<string-array name="alignment_options">
<item>Left</item>
<item>Center</item>
<item>Right</item>
</string-array>
</resources>

View File

@@ -0,0 +1,82 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Launcher" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:windowDisablePreview">true</item>
<!-- Primary brand color. -->
<item name="colorPrimary">@color/teal_700</item>
<item name="colorPrimaryVariant">@color/teal_200</item>
<item name="colorOnPrimary">?attr/color</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<item name="colorSurface">@color/white</item>
<item name="primaryTextShadowColor">@color/whiteTrans50</item>
<item name="primaryShadeDarkColor">@color/blackTrans25</item>
<item name="android:forceDarkAllowed" tools:targetApi="q">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges
</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:colorEdgeEffect">@android:color/transparent</item>
<item name="android:fitsSystemWindows">false</item>
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<!-- <item name="android:enforceStatusBarContrast">false</item>-->
<item name="android:enforceNavigationBarContrast" tools:targetApi="q">false</item>
<!-- custom bottom_dialog -->
<item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item>
<!-- custom dialog -->
<item name="materialAlertDialogTheme">@style/CustomAlertDialog</item>
</style>
<!-- Base application theme. -->
<style name="AppBottomSheetDialogTheme"
parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/AppModalStyle</item>
</style>
<style name="AppModalStyle" parent="Theme.Design.Light.BottomSheetDialog">
<item name="android:background">@drawable/bottom_dialog_style</item>
</style>
<style name="CustomAlertDialog" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="shapeAppearanceOverlay">@style/RoundedCorners</item>
</style>
<style name="RoundedCorners">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">16dp</item>
</style>
<style name="TextDefaultStyle" parent="@android:style/TextAppearance.Large">
<item name="android:shadowColor">?attr/primaryTextShadowColor</item>
<item name="android:shadowDx">1</item>
<item name="android:shadowDy">1</item>
<item name="android:shadowRadius">2</item>
</style>
</resources>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeViewClicked" android:accessibilityFeedbackType="feedbackVisual" android:accessibilityFlags="flagDefault" android:canRetrieveWindowContent="true" android:description="@string/accessibility_service_desc" android:notificationTimeout="10" android:packageNames="com.github.droidworksstudio.launcher.debug, com.github.droidworksstudio.launcher" android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity" />

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<device-admin>
<uses-policies><force-lock /></uses-policies>
</device-admin>