Skip to content

Commit

Permalink
Merge branch 'LawnchairLauncher:15-dev' into trunk
Browse files Browse the repository at this point in the history
  • Loading branch information
Goooler authored Jan 16, 2025
2 parents 62b4f4f + 01b9914 commit 4971868
Show file tree
Hide file tree
Showing 32 changed files with 598 additions and 154 deletions.
10 changes: 5 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ plugins {
id 'app.cash.licensee' version "1.12.0"
id 'dev.rikka.tools.refine' version "4.4.0"
id 'org.gradle.android.cache-fix' version '3.0.1'
id 'com.diffplug.spotless' version '7.0.1'
id 'com.diffplug.spotless' version '7.0.2'
}


Expand Down Expand Up @@ -340,15 +340,15 @@ dependencies {
implementation 'androidx.profileinstaller:profileinstaller:1.4.1'
baselineProfile projects.baselineProfile

implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation "androidx.recyclerview:recyclerview:1.4.0"
implementation "androidx.preference:preference-ktx:1.2.1"

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.1'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0'
implementation 'com.github.ChickenHook:RestrictionBypass:2.2'
implementation 'dev.rikka.tools.refine:runtime:4.4.0'

implementation platform("androidx.compose:compose-bom:2024.12.01")
implementation platform("androidx.compose:compose-bom:2025.01.00")
implementation "androidx.compose.ui:ui"
implementation "androidx.compose.ui:ui-util"
debugImplementation "androidx.compose.ui:ui-tooling"
Expand All @@ -360,7 +360,7 @@ dependencies {
implementation "androidx.compose.runtime:runtime-livedata"
implementation 'androidx.compose.material3:material3'
implementation 'androidx.compose.material3:material3-window-size-class'
implementation "androidx.activity:activity-compose:1.9.3"
implementation "androidx.activity:activity-compose:1.10.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7"
implementation "androidx.navigation:navigation-compose:2.8.0"
implementation "androidx.constraintlayout:constraintlayout:2.2.0"
Expand All @@ -379,7 +379,7 @@ dependencies {
implementation "com.patrykmichalik.opto:domain:$optoVersion"
implementation "com.patrykmichalik.opto:core:$optoVersion"
implementation "com.patrykmichalik.opto:compose:$optoVersion"
implementation "androidx.datastore:datastore-preferences:1.1.1"
implementation "androidx.datastore:datastore-preferences:1.1.2"
def retrofitVersion = "2.11.0"
implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
implementation "com.squareup.retrofit2:converter-kotlinx-serialization:$retrofitVersion"
Expand Down
23 changes: 23 additions & 0 deletions lawnchair/res/layout/all_apps_folder_application.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ This file is part of Lawnchair Launcher.
~
~ Lawnchair Launcher is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ Lawnchair Launcher is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with Lawnchair Launcher. If not, see <https://www.gnu.org/licenses/>.
-->
<com.android.launcher3.BubbleTextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
style="@style/BaseIcon"
android:includeFontPadding="false"
launcher:iconDisplay="drawer_folder" />
36 changes: 36 additions & 0 deletions lawnchair/res/layout/all_apps_folder_icon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ This file is part of Lawnchair Launcher.
~
~ Lawnchair Launcher is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ Lawnchair Launcher is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with Lawnchair Launcher. If not, see <https://www.gnu.org/licenses/>.
-->
<com.android.launcher3.folder.FolderIcon
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:paddingLeft="@dimen/dynamic_grid_cell_padding_x"
android:paddingRight="@dimen/dynamic_grid_cell_padding_x"
android:focusable="true" >
<com.android.launcher3.BubbleTextView
style="@style/BaseIcon"
android:id="@+id/folder_icon_name"
android:focusable="false"
android:layout_gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:iconDisplay="all_apps"/>
</com.android.launcher3.folder.FolderIcon>
4 changes: 4 additions & 0 deletions lawnchair/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
General "words" used throughout Lawnchair
-->
<string name="others_category_label">Others</string>

<!-- Selection options -->
<string name="dynamic">Dynamic</string>
Expand Down Expand Up @@ -90,6 +91,9 @@

<string name="wallpapers">Wallpapers</string>

<string name="caddy_beta">Caddy (Beta)</string>
<string name="caddy">Caddy</string>

<!-- A11y description -->
<string name="accessibility_service_description">To lock your phone when performing a gesture, and to open Recents via gesture, Lawnchair requires accessibility access.\n\nLawnchair doesn\'t watch any user action, though the privilege to do so is required for all accessibility services. Lawnchair discards any event sent by the system.\n\nIn order to lock your phone, or to open Recents, Lawnchair uses the performGlobalAction Accessibility service.</string>

Expand Down
4 changes: 4 additions & 0 deletions lawnchair/src/app/lawnchair/LawnchairLauncher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import app.lawnchair.preferences2.PreferenceManager2
import app.lawnchair.root.RootHelperManager
import app.lawnchair.root.RootNotAvailableException
import app.lawnchair.theme.ThemeProvider
import app.lawnchair.ui.popup.LauncherOptionsPopup
import app.lawnchair.ui.popup.LawnchairShortcut
import app.lawnchair.util.getThemedIconPacksInstalled
import app.lawnchair.util.unsafeLazy
Expand Down Expand Up @@ -221,6 +222,9 @@ class LawnchairLauncher : QuickstepLauncher() {
hasBackGesture = handler !is GestureHandlerConfig.NoOp
}

LauncherOptionsPopup.restoreMissingPopupOptions(launcher)
LauncherOptionsPopup.migrateLegacyPreferences(launcher)

// Handle update from version 12 Alpha 4 to version 12 Alpha 5.
if (
prefs.themedIcons.get() &&
Expand Down
48 changes: 19 additions & 29 deletions lawnchair/src/app/lawnchair/allapps/AllAppsSearchInput.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ package app.lawnchair.allapps

import android.animation.ValueAnimator
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.RippleDrawable
import android.provider.SearchRecentSuggestions
import android.text.Selection
import android.text.SpannableStringBuilder
Expand All @@ -17,7 +15,6 @@ import android.view.KeyEvent
import android.view.View
import android.view.View.OnFocusChangeListener
import android.view.ViewTreeObserver
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.DecelerateInterpolator
import android.widget.FrameLayout
import android.widget.ImageButton
Expand Down Expand Up @@ -45,6 +42,7 @@ import app.lawnchair.search.algorithms.LawnchairSearchAlgorithm
import app.lawnchair.theme.drawable.DrawableTokens
import app.lawnchair.util.viewAttachedScope
import com.android.launcher3.Insettable
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener
import com.android.launcher3.LauncherState
import com.android.launcher3.R
import com.android.launcher3.Utilities
Expand All @@ -63,6 +61,7 @@ import kotlinx.coroutines.launch
class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
FrameLayout(context, attrs),
Insettable,
OnIDPChangeListener,
SearchUiManager,
SearchCallback<AdapterItem>,
AllAppsStore.OnUpdateListener,
Expand Down Expand Up @@ -96,11 +95,6 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
duration = 300
interpolator = DecelerateInterpolator()
}
private val rippleBackground = RippleDrawable(
ColorStateList.valueOf(Themes.getAttrColor(context, android.R.attr.colorControlHighlight)),
bg,
null,
)
private var bgVisible = true
private var bgAlpha = 1f
private val suggestionsRecent = SearchRecentSuggestions(launcher, LawnchairRecentSuggestionProvider.AUTHORITY, LawnchairRecentSuggestionProvider.MODE)
Expand All @@ -115,12 +109,8 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :

val wrapper = ViewCompat.requireViewById<View>(this, R.id.search_wrapper)
wrapper.background = bg
launcher.deviceProfile.let { dp ->
val padding = dp.desiredWorkspaceHorizontalMarginPx * 2 + dp.allAppsPadding.run { left + right * 2 }
initialPaddingLeft = padding
initialPaddingRight = padding
setPadding(padding, paddingTop, padding, paddingBottom)
}
setupPadding()
launcher.deviceProfile.inv.addOnChangeListener(this)
bgAlphaAnimator.addUpdateListener { updateBgAlpha() }

hint = ViewCompat.requireViewById(this, R.id.hint)
Expand Down Expand Up @@ -208,12 +198,10 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
input.setHint(R.string.all_apps_search_bar_hint)
}

triggerRippleEffect(true)
setBackgroundVisibility(false, 0f)
animateHintVisibility(true)
animatePadding(currentPaddingLeft / 2, currentPaddingRight / 2)
} else {
triggerRippleEffect(false)
setBackgroundVisibility(true, 1f)
animateHintVisibility(false)
if (prefs.searchResulRecentSuggestion.get()) {
Expand Down Expand Up @@ -249,6 +237,15 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
}
}

private fun setupPadding() {
launcher.deviceProfile.let { dp ->
val padding = dp.getAllAppsIconStartMargin(context)
initialPaddingLeft = padding
initialPaddingRight = padding
setPadding(padding, paddingTop, padding, paddingBottom)
}
}

private fun animateHintVisibility(visible: Boolean) {
val targetAlpha = if (visible) 1f else 0f
val duration = if (visible) 300L else 200L
Expand All @@ -268,19 +265,6 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
.start()
}

private fun triggerRippleEffect(expand: Boolean) {
rippleBackground.setHotspot(width / 2f, height / 2f)
ValueAnimator.ofFloat(if (expand) 1f else 0f, if (expand) 0f else 1f).apply {
duration = 500
interpolator = AccelerateDecelerateInterpolator()
addUpdateListener {
val alpha = it.animatedValue as Float
rippleBackground.alpha = (alpha * 255).toInt()
}
start()
}
}

private fun animatePadding(newPaddingLeft: Int, newPaddingRight: Int) {
val currentPaddingLeft = paddingLeft
val currentPaddingRight = paddingRight
Expand Down Expand Up @@ -447,4 +431,10 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
val fraction = bgAlphaAnimator.animatedFraction
bg.alpha = (Utilities.mapRange(fraction, 0f, bgAlpha) * 255).toInt()
}

override fun onIdpChanged(modelPropertiesChanged: Boolean) {
setupPadding()
invalidate()
requestLayout()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,35 @@ import android.content.Context
import android.util.Log
import androidx.lifecycle.lifecycleScope
import app.lawnchair.launcher
import app.lawnchair.preferences.PreferenceManager
import app.lawnchair.preferences2.PreferenceManager2
import app.lawnchair.util.categorizeApps
import com.android.launcher3.allapps.AllAppsStore
import com.android.launcher3.allapps.AlphabeticalAppsList
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem
import com.android.launcher3.allapps.PrivateProfileManager
import com.android.launcher3.allapps.WorkProfileManager
import com.android.launcher3.model.data.AppInfo
import com.android.launcher3.model.data.FolderInfo
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.views.ActivityContext
import com.patrykmichalik.opto.core.onEach
import java.util.function.Predicate

class LawnchairAlphabeticalAppsList<T>(
context: T,
private val context: T,
appsStore: AllAppsStore<T>,
workProfileManager: WorkProfileManager?,
privateProfileManager: PrivateProfileManager?,
) : AlphabeticalAppsList<T>(context, appsStore, workProfileManager, privateProfileManager)
where T : Context, T : ActivityContext {

private var hiddenApps: Set<String> = setOf()
private val prefs = PreferenceManager2.getInstance(context)

private val prefs2 = PreferenceManager2.getInstance(context)
private val prefs = PreferenceManager.getInstance(context)
init {
try {
prefs.hiddenApps.onEach(launchIn = context.launcher.lifecycleScope) {
prefs2.hiddenApps.onEach(launchIn = context.launcher.lifecycleScope) {
hiddenApps = it
onAppsUpdated()
}
Expand All @@ -45,4 +49,35 @@ class LawnchairAlphabeticalAppsList<T>(
}
onAppsUpdated()
}

override fun addAppsWithSections(appList: List<AppInfo?>?, startPosition: Int): Int {
if (appList.isNullOrEmpty()) return startPosition
val drawerListDefault = prefs.drawerList.get()
var position = startPosition

if (!drawerListDefault) {
val categorizedApps = categorizeApps(context, appList)

if (categorizedApps.isNotEmpty()) {
for ((category, apps) in categorizedApps) {
if (apps.size <= 1) {
val app = apps[0]
mAdapterItems.add(AdapterItem.asApp(app))
} else {
val folderInfo = FolderInfo()
folderInfo.title = category
for (app in apps) {
folderInfo.add(app)
}
mAdapterItems.add(AdapterItem.asFolder(folderInfo))
}
position++
}
}
} else {
position = super.addAppsWithSections(appList, startPosition)
}

return position
}
}
2 changes: 2 additions & 0 deletions lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class PreferenceManager private constructor(private val context: Context) :
val wallpaperBlur = IntPref("pref_wallpaperBlur", 25, recreate)
val wallpaperBlurFactorThreshold = FloatPref("pref_wallpaperBlurFactor", 3.0F, recreate)

val drawerList = BoolPref("pref_drawerList", true, recreate)

val recentsActionScreenshot = BoolPref("pref_recentsActionScreenshot", !isOnePlusStock)
val recentsActionShare = BoolPref("pref_recentsActionShare", isOnePlusStock)
val recentsActionLens = BoolPref("pref_recentsActionLens", true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,17 +97,17 @@ class LawnchairSearchAdapterProvider(
override fun getDecorator() = decorator

companion object {
private const val SEARCH_RESULT_ICON = (1 shl 8) or AllAppsGridAdapter.VIEW_TYPE_ICON
private const val SEARCH_RESULT_ICON_ROW = 1 shl 9
private const val SEARCH_RESULT_SMALL_ICON_ROW = 1 shl 10
private const val SEARCH_RESULT_DIVIDER = 1 shl 11
private const val SEARCH_TEXT_HEADER = 1 shl 12
private const val SEARCH_PEOPLE_TILE = 1 shl 13
private const val SEARCH_RESULT_FILE_TILE = 1 shl 14
private const val SEARCH_RESULT_SUGGESTION_TILE = 1 shl 15
private const val SEARCH_RESULT_SETTINGS_TILE = 1 shl 16
private const val SEARCH_RESULT_RECENT_TILE = 1 shl 17
private const val SEARCH_RESULT_CALCULATOR = 1 shl 18
private const val SEARCH_RESULT_ICON = (1 shl 10) or AllAppsGridAdapter.VIEW_TYPE_ICON
private const val SEARCH_RESULT_ICON_ROW = 1 shl 11
private const val SEARCH_RESULT_SMALL_ICON_ROW = 1 shl 12
private const val SEARCH_RESULT_DIVIDER = 1 shl 13
private const val SEARCH_TEXT_HEADER = 1 shl 14
private const val SEARCH_PEOPLE_TILE = 1 shl 15
private const val SEARCH_RESULT_FILE_TILE = 1 shl 16
private const val SEARCH_RESULT_SUGGESTION_TILE = 1 shl 17
private const val SEARCH_RESULT_SETTINGS_TILE = 1 shl 18
private const val SEARCH_RESULT_RECENT_TILE = 1 shl 19
private const val SEARCH_RESULT_CALCULATOR = 1 shl 20

val viewTypeMap = mapOf(
LayoutType.ICON_SINGLE_VERTICAL_TEXT to SEARCH_RESULT_ICON,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.util.Log
import androidx.core.net.toUri
import app.lawnchair.search.LawnchairRecentSuggestionProvider
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
Expand All @@ -29,7 +30,7 @@ suspend fun getRecentKeyword(context: Context, query: String, max: Int, callback
withContext(Dispatchers.IO) {
val contentResolver: ContentResolver = context.contentResolver
val uri: Uri =
Uri.parse("content://${LawnchairRecentSuggestionProvider.AUTHORITY}/suggestions")
"content://${LawnchairRecentSuggestionProvider.AUTHORITY}/suggestions".toUri()
val cursor: Cursor? = contentResolver.query(uri, null, null, null, null)
val recentKeywords = mutableListOf<RecentKeyword>()

Expand Down
Loading

0 comments on commit 4971868

Please sign in to comment.