Skip to content

Commit 4971868

Browse files
authored
Merge branch 'LawnchairLauncher:15-dev' into trunk
2 parents 62b4f4f + 01b9914 commit 4971868

32 files changed

+598
-154
lines changed

build.gradle

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ plugins {
1616
id 'app.cash.licensee' version "1.12.0"
1717
id 'dev.rikka.tools.refine' version "4.4.0"
1818
id 'org.gradle.android.cache-fix' version '3.0.1'
19-
id 'com.diffplug.spotless' version '7.0.1'
19+
id 'com.diffplug.spotless' version '7.0.2'
2020
}
2121

2222

@@ -340,15 +340,15 @@ dependencies {
340340
implementation 'androidx.profileinstaller:profileinstaller:1.4.1'
341341
baselineProfile projects.baselineProfile
342342

343-
implementation "androidx.recyclerview:recyclerview:1.3.2"
343+
implementation "androidx.recyclerview:recyclerview:1.4.0"
344344
implementation "androidx.preference:preference-ktx:1.2.1"
345345

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

351-
implementation platform("androidx.compose:compose-bom:2024.12.01")
351+
implementation platform("androidx.compose:compose-bom:2025.01.00")
352352
implementation "androidx.compose.ui:ui"
353353
implementation "androidx.compose.ui:ui-util"
354354
debugImplementation "androidx.compose.ui:ui-tooling"
@@ -360,7 +360,7 @@ dependencies {
360360
implementation "androidx.compose.runtime:runtime-livedata"
361361
implementation 'androidx.compose.material3:material3'
362362
implementation 'androidx.compose.material3:material3-window-size-class'
363-
implementation "androidx.activity:activity-compose:1.9.3"
363+
implementation "androidx.activity:activity-compose:1.10.0"
364364
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7"
365365
implementation "androidx.navigation:navigation-compose:2.8.0"
366366
implementation "androidx.constraintlayout:constraintlayout:2.2.0"
@@ -379,7 +379,7 @@ dependencies {
379379
implementation "com.patrykmichalik.opto:domain:$optoVersion"
380380
implementation "com.patrykmichalik.opto:core:$optoVersion"
381381
implementation "com.patrykmichalik.opto:compose:$optoVersion"
382-
implementation "androidx.datastore:datastore-preferences:1.1.1"
382+
implementation "androidx.datastore:datastore-preferences:1.1.2"
383383
def retrofitVersion = "2.11.0"
384384
implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
385385
implementation "com.squareup.retrofit2:converter-kotlinx-serialization:$retrofitVersion"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ This file is part of Lawnchair Launcher.
4+
~
5+
~ Lawnchair Launcher is free software: you can redistribute it and/or modify
6+
~ it under the terms of the GNU General Public License as published by
7+
~ the Free Software Foundation, either version 3 of the License, or
8+
~ (at your option) any later version.
9+
~
10+
~ Lawnchair Launcher is distributed in the hope that it will be useful,
11+
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
~ GNU General Public License for more details.
14+
~
15+
~ You should have received a copy of the GNU General Public License
16+
~ along with Lawnchair Launcher. If not, see <https://www.gnu.org/licenses/>.
17+
-->
18+
<com.android.launcher3.BubbleTextView
19+
xmlns:android="http://schemas.android.com/apk/res/android"
20+
xmlns:launcher="http://schemas.android.com/apk/res-auto"
21+
style="@style/BaseIcon"
22+
android:includeFontPadding="false"
23+
launcher:iconDisplay="drawer_folder" />
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ This file is part of Lawnchair Launcher.
4+
~
5+
~ Lawnchair Launcher is free software: you can redistribute it and/or modify
6+
~ it under the terms of the GNU General Public License as published by
7+
~ the Free Software Foundation, either version 3 of the License, or
8+
~ (at your option) any later version.
9+
~
10+
~ Lawnchair Launcher is distributed in the hope that it will be useful,
11+
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
~ GNU General Public License for more details.
14+
~
15+
~ You should have received a copy of the GNU General Public License
16+
~ along with Lawnchair Launcher. If not, see <https://www.gnu.org/licenses/>.
17+
-->
18+
<com.android.launcher3.folder.FolderIcon
19+
xmlns:android="http://schemas.android.com/apk/res/android"
20+
xmlns:app="http://schemas.android.com/apk/res-auto"
21+
android:layout_width="match_parent"
22+
android:layout_height="wrap_content"
23+
android:layout_gravity="center"
24+
android:orientation="vertical"
25+
android:paddingLeft="@dimen/dynamic_grid_cell_padding_x"
26+
android:paddingRight="@dimen/dynamic_grid_cell_padding_x"
27+
android:focusable="true" >
28+
<com.android.launcher3.BubbleTextView
29+
style="@style/BaseIcon"
30+
android:id="@+id/folder_icon_name"
31+
android:focusable="false"
32+
android:layout_gravity="top"
33+
android:layout_width="match_parent"
34+
android:layout_height="wrap_content"
35+
app:iconDisplay="all_apps"/>
36+
</com.android.launcher3.folder.FolderIcon>

lawnchair/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
General "words" used throughout Lawnchair
6060
6161
-->
62+
<string name="others_category_label">Others</string>
6263

6364
<!-- Selection options -->
6465
<string name="dynamic">Dynamic</string>
@@ -90,6 +91,9 @@
9091

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

94+
<string name="caddy_beta">Caddy (Beta)</string>
95+
<string name="caddy">Caddy</string>
96+
9397
<!-- A11y description -->
9498
<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>
9599

lawnchair/src/app/lawnchair/LawnchairLauncher.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import app.lawnchair.preferences2.PreferenceManager2
4545
import app.lawnchair.root.RootHelperManager
4646
import app.lawnchair.root.RootNotAvailableException
4747
import app.lawnchair.theme.ThemeProvider
48+
import app.lawnchair.ui.popup.LauncherOptionsPopup
4849
import app.lawnchair.ui.popup.LawnchairShortcut
4950
import app.lawnchair.util.getThemedIconPacksInstalled
5051
import app.lawnchair.util.unsafeLazy
@@ -221,6 +222,9 @@ class LawnchairLauncher : QuickstepLauncher() {
221222
hasBackGesture = handler !is GestureHandlerConfig.NoOp
222223
}
223224

225+
LauncherOptionsPopup.restoreMissingPopupOptions(launcher)
226+
LauncherOptionsPopup.migrateLegacyPreferences(launcher)
227+
224228
// Handle update from version 12 Alpha 4 to version 12 Alpha 5.
225229
if (
226230
prefs.themedIcons.get() &&

lawnchair/src/app/lawnchair/allapps/AllAppsSearchInput.kt

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ package app.lawnchair.allapps
22

33
import android.animation.ValueAnimator
44
import android.content.Context
5-
import android.content.res.ColorStateList
65
import android.graphics.Color
76
import android.graphics.Rect
8-
import android.graphics.drawable.RippleDrawable
97
import android.provider.SearchRecentSuggestions
108
import android.text.Selection
119
import android.text.SpannableStringBuilder
@@ -17,7 +15,6 @@ import android.view.KeyEvent
1715
import android.view.View
1816
import android.view.View.OnFocusChangeListener
1917
import android.view.ViewTreeObserver
20-
import android.view.animation.AccelerateDecelerateInterpolator
2118
import android.view.animation.DecelerateInterpolator
2219
import android.widget.FrameLayout
2320
import android.widget.ImageButton
@@ -45,6 +42,7 @@ import app.lawnchair.search.algorithms.LawnchairSearchAlgorithm
4542
import app.lawnchair.theme.drawable.DrawableTokens
4643
import app.lawnchair.util.viewAttachedScope
4744
import com.android.launcher3.Insettable
45+
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener
4846
import com.android.launcher3.LauncherState
4947
import com.android.launcher3.R
5048
import com.android.launcher3.Utilities
@@ -63,6 +61,7 @@ import kotlinx.coroutines.launch
6361
class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
6462
FrameLayout(context, attrs),
6563
Insettable,
64+
OnIDPChangeListener,
6665
SearchUiManager,
6766
SearchCallback<AdapterItem>,
6867
AllAppsStore.OnUpdateListener,
@@ -96,11 +95,6 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
9695
duration = 300
9796
interpolator = DecelerateInterpolator()
9897
}
99-
private val rippleBackground = RippleDrawable(
100-
ColorStateList.valueOf(Themes.getAttrColor(context, android.R.attr.colorControlHighlight)),
101-
bg,
102-
null,
103-
)
10498
private var bgVisible = true
10599
private var bgAlpha = 1f
106100
private val suggestionsRecent = SearchRecentSuggestions(launcher, LawnchairRecentSuggestionProvider.AUTHORITY, LawnchairRecentSuggestionProvider.MODE)
@@ -115,12 +109,8 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
115109

116110
val wrapper = ViewCompat.requireViewById<View>(this, R.id.search_wrapper)
117111
wrapper.background = bg
118-
launcher.deviceProfile.let { dp ->
119-
val padding = dp.desiredWorkspaceHorizontalMarginPx * 2 + dp.allAppsPadding.run { left + right * 2 }
120-
initialPaddingLeft = padding
121-
initialPaddingRight = padding
122-
setPadding(padding, paddingTop, padding, paddingBottom)
123-
}
112+
setupPadding()
113+
launcher.deviceProfile.inv.addOnChangeListener(this)
124114
bgAlphaAnimator.addUpdateListener { updateBgAlpha() }
125115

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

211-
triggerRippleEffect(true)
212201
setBackgroundVisibility(false, 0f)
213202
animateHintVisibility(true)
214203
animatePadding(currentPaddingLeft / 2, currentPaddingRight / 2)
215204
} else {
216-
triggerRippleEffect(false)
217205
setBackgroundVisibility(true, 1f)
218206
animateHintVisibility(false)
219207
if (prefs.searchResulRecentSuggestion.get()) {
@@ -249,6 +237,15 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
249237
}
250238
}
251239

240+
private fun setupPadding() {
241+
launcher.deviceProfile.let { dp ->
242+
val padding = dp.getAllAppsIconStartMargin(context)
243+
initialPaddingLeft = padding
244+
initialPaddingRight = padding
245+
setPadding(padding, paddingTop, padding, paddingBottom)
246+
}
247+
}
248+
252249
private fun animateHintVisibility(visible: Boolean) {
253250
val targetAlpha = if (visible) 1f else 0f
254251
val duration = if (visible) 300L else 200L
@@ -268,19 +265,6 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
268265
.start()
269266
}
270267

271-
private fun triggerRippleEffect(expand: Boolean) {
272-
rippleBackground.setHotspot(width / 2f, height / 2f)
273-
ValueAnimator.ofFloat(if (expand) 1f else 0f, if (expand) 0f else 1f).apply {
274-
duration = 500
275-
interpolator = AccelerateDecelerateInterpolator()
276-
addUpdateListener {
277-
val alpha = it.animatedValue as Float
278-
rippleBackground.alpha = (alpha * 255).toInt()
279-
}
280-
start()
281-
}
282-
}
283-
284268
private fun animatePadding(newPaddingLeft: Int, newPaddingRight: Int) {
285269
val currentPaddingLeft = paddingLeft
286270
val currentPaddingRight = paddingRight
@@ -447,4 +431,10 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
447431
val fraction = bgAlphaAnimator.animatedFraction
448432
bg.alpha = (Utilities.mapRange(fraction, 0f, bgAlpha) * 255).toInt()
449433
}
434+
435+
override fun onIdpChanged(modelPropertiesChanged: Boolean) {
436+
setupPadding()
437+
invalidate()
438+
requestLayout()
439+
}
450440
}

lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.kt

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,35 @@ import android.content.Context
44
import android.util.Log
55
import androidx.lifecycle.lifecycleScope
66
import app.lawnchair.launcher
7+
import app.lawnchair.preferences.PreferenceManager
78
import app.lawnchair.preferences2.PreferenceManager2
9+
import app.lawnchair.util.categorizeApps
810
import com.android.launcher3.allapps.AllAppsStore
911
import com.android.launcher3.allapps.AlphabeticalAppsList
12+
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem
1013
import com.android.launcher3.allapps.PrivateProfileManager
1114
import com.android.launcher3.allapps.WorkProfileManager
1215
import com.android.launcher3.model.data.AppInfo
16+
import com.android.launcher3.model.data.FolderInfo
1317
import com.android.launcher3.model.data.ItemInfo
1418
import com.android.launcher3.views.ActivityContext
1519
import com.patrykmichalik.opto.core.onEach
1620
import java.util.function.Predicate
1721

1822
class LawnchairAlphabeticalAppsList<T>(
19-
context: T,
23+
private val context: T,
2024
appsStore: AllAppsStore<T>,
2125
workProfileManager: WorkProfileManager?,
2226
privateProfileManager: PrivateProfileManager?,
2327
) : AlphabeticalAppsList<T>(context, appsStore, workProfileManager, privateProfileManager)
2428
where T : Context, T : ActivityContext {
2529

2630
private var hiddenApps: Set<String> = setOf()
27-
private val prefs = PreferenceManager2.getInstance(context)
28-
31+
private val prefs2 = PreferenceManager2.getInstance(context)
32+
private val prefs = PreferenceManager.getInstance(context)
2933
init {
3034
try {
31-
prefs.hiddenApps.onEach(launchIn = context.launcher.lifecycleScope) {
35+
prefs2.hiddenApps.onEach(launchIn = context.launcher.lifecycleScope) {
3236
hiddenApps = it
3337
onAppsUpdated()
3438
}
@@ -45,4 +49,35 @@ class LawnchairAlphabeticalAppsList<T>(
4549
}
4650
onAppsUpdated()
4751
}
52+
53+
override fun addAppsWithSections(appList: List<AppInfo?>?, startPosition: Int): Int {
54+
if (appList.isNullOrEmpty()) return startPosition
55+
val drawerListDefault = prefs.drawerList.get()
56+
var position = startPosition
57+
58+
if (!drawerListDefault) {
59+
val categorizedApps = categorizeApps(context, appList)
60+
61+
if (categorizedApps.isNotEmpty()) {
62+
for ((category, apps) in categorizedApps) {
63+
if (apps.size <= 1) {
64+
val app = apps[0]
65+
mAdapterItems.add(AdapterItem.asApp(app))
66+
} else {
67+
val folderInfo = FolderInfo()
68+
folderInfo.title = category
69+
for (app in apps) {
70+
folderInfo.add(app)
71+
}
72+
mAdapterItems.add(AdapterItem.asFolder(folderInfo))
73+
}
74+
position++
75+
}
76+
}
77+
} else {
78+
position = super.addAppsWithSections(appList, startPosition)
79+
}
80+
81+
return position
82+
}
4883
}

lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ class PreferenceManager private constructor(private val context: Context) :
115115
val wallpaperBlur = IntPref("pref_wallpaperBlur", 25, recreate)
116116
val wallpaperBlurFactorThreshold = FloatPref("pref_wallpaperBlurFactor", 3.0F, recreate)
117117

118+
val drawerList = BoolPref("pref_drawerList", true, recreate)
119+
118120
val recentsActionScreenshot = BoolPref("pref_recentsActionScreenshot", !isOnePlusStock)
119121
val recentsActionShare = BoolPref("pref_recentsActionShare", isOnePlusStock)
120122
val recentsActionLens = BoolPref("pref_recentsActionLens", true)

lawnchair/src/app/lawnchair/search/LawnchairSearchAdapterProvider.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,17 @@ class LawnchairSearchAdapterProvider(
9797
override fun getDecorator() = decorator
9898

9999
companion object {
100-
private const val SEARCH_RESULT_ICON = (1 shl 8) or AllAppsGridAdapter.VIEW_TYPE_ICON
101-
private const val SEARCH_RESULT_ICON_ROW = 1 shl 9
102-
private const val SEARCH_RESULT_SMALL_ICON_ROW = 1 shl 10
103-
private const val SEARCH_RESULT_DIVIDER = 1 shl 11
104-
private const val SEARCH_TEXT_HEADER = 1 shl 12
105-
private const val SEARCH_PEOPLE_TILE = 1 shl 13
106-
private const val SEARCH_RESULT_FILE_TILE = 1 shl 14
107-
private const val SEARCH_RESULT_SUGGESTION_TILE = 1 shl 15
108-
private const val SEARCH_RESULT_SETTINGS_TILE = 1 shl 16
109-
private const val SEARCH_RESULT_RECENT_TILE = 1 shl 17
110-
private const val SEARCH_RESULT_CALCULATOR = 1 shl 18
100+
private const val SEARCH_RESULT_ICON = (1 shl 10) or AllAppsGridAdapter.VIEW_TYPE_ICON
101+
private const val SEARCH_RESULT_ICON_ROW = 1 shl 11
102+
private const val SEARCH_RESULT_SMALL_ICON_ROW = 1 shl 12
103+
private const val SEARCH_RESULT_DIVIDER = 1 shl 13
104+
private const val SEARCH_TEXT_HEADER = 1 shl 14
105+
private const val SEARCH_PEOPLE_TILE = 1 shl 15
106+
private const val SEARCH_RESULT_FILE_TILE = 1 shl 16
107+
private const val SEARCH_RESULT_SUGGESTION_TILE = 1 shl 17
108+
private const val SEARCH_RESULT_SETTINGS_TILE = 1 shl 18
109+
private const val SEARCH_RESULT_RECENT_TILE = 1 shl 19
110+
private const val SEARCH_RESULT_CALCULATOR = 1 shl 20
111111

112112
val viewTypeMap = mapOf(
113113
LayoutType.ICON_SINGLE_VERTICAL_TEXT to SEARCH_RESULT_ICON,

lawnchair/src/app/lawnchair/search/algorithms/data/History.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.content.Context
55
import android.database.Cursor
66
import android.net.Uri
77
import android.util.Log
8+
import androidx.core.net.toUri
89
import app.lawnchair.search.LawnchairRecentSuggestionProvider
910
import kotlinx.coroutines.Dispatchers
1011
import kotlinx.coroutines.withContext
@@ -29,7 +30,7 @@ suspend fun getRecentKeyword(context: Context, query: String, max: Int, callback
2930
withContext(Dispatchers.IO) {
3031
val contentResolver: ContentResolver = context.contentResolver
3132
val uri: Uri =
32-
Uri.parse("content://${LawnchairRecentSuggestionProvider.AUTHORITY}/suggestions")
33+
"content://${LawnchairRecentSuggestionProvider.AUTHORITY}/suggestions".toUri()
3334
val cursor: Cursor? = contentResolver.query(uri, null, null, null, null)
3435
val recentKeywords = mutableListOf<RecentKeyword>()
3536

0 commit comments

Comments
 (0)