Skip to content

Commit 7b1b083

Browse files
authored
Merge pull request #140 from esensar/fix/crashes
Fix various crashes and general issues
2 parents f46b6fc + 681e509 commit 7b1b083

File tree

5 files changed

+127
-53
lines changed

5 files changed

+127
-53
lines changed

app/src/main/kotlin/com/simplemobiletools/launcher/activities/MainActivity.kt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import android.content.Intent
1313
import android.content.pm.ActivityInfo
1414
import android.content.pm.LauncherApps
1515
import android.content.pm.PackageManager
16-
import android.content.pm.ShortcutInfo
1716
import android.content.res.Configuration
1817
import android.graphics.Bitmap
1918
import android.graphics.Color
@@ -52,6 +51,7 @@ import com.simplemobiletools.launcher.interfaces.ItemMenuListener
5251
import com.simplemobiletools.launcher.models.AppLauncher
5352
import com.simplemobiletools.launcher.models.HiddenIcon
5453
import com.simplemobiletools.launcher.models.HomeScreenGridItem
54+
import kotlinx.collections.immutable.toImmutableList
5555
import kotlin.math.abs
5656

5757
class MainActivity : SimpleActivity(), FlingListener {
@@ -234,11 +234,12 @@ class MainActivity : SimpleActivity(), FlingListener {
234234
if (resultCode == Activity.RESULT_OK && resultData != null) {
235235
val launcherApps = applicationContext.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
236236
val item = launcherApps.getPinItemRequest(resultData)
237-
item.accept()
238-
val shortcutId = item.shortcutInfo?.id!!
239-
val label = item.shortcutInfo.getLabel()
240-
val icon = launcherApps.getShortcutBadgedIconDrawable(item.shortcutInfo!!, resources.displayMetrics.densityDpi)
241-
mActionOnAddShortcut?.invoke(shortcutId, label, icon)
237+
if (item.accept()) {
238+
val shortcutId = item.shortcutInfo?.id!!
239+
val label = item.shortcutInfo.getLabel()
240+
val icon = launcherApps.getShortcutBadgedIconDrawable(item.shortcutInfo!!, resources.displayMetrics.densityDpi)
241+
mActionOnAddShortcut?.invoke(shortcutId, label, icon)
242+
}
242243
}
243244
}
244245
}
@@ -404,9 +405,9 @@ class MainActivity : SimpleActivity(), FlingListener {
404405

405406
private fun findFirstEmptyCell(): Pair<Int, Rect> {
406407
val gridItems = homeScreenGridItemsDB.getAllItems() as ArrayList<HomeScreenGridItem>
407-
val maxPage = gridItems.map { it.page }.max()
408+
val maxPage = gridItems.maxOf { it.page }
408409
val occupiedCells = ArrayList<Triple<Int, Int, Int>>()
409-
gridItems.forEach { item ->
410+
gridItems.toImmutableList().filter { it.parentId == null }.forEach { item ->
410411
for (xCell in item.left..item.right) {
411412
for (yCell in item.top..item.bottom) {
412413
occupiedCells.add(Triple(item.page, xCell, yCell))

app/src/main/kotlin/com/simplemobiletools/launcher/fragments/WidgetsFragment.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,12 @@ class WidgetsFragment(context: Context, attributeSet: AttributeSet) : MyFragment
5555
binding.widgetsList.scrollToPosition(0)
5656
setupViews()
5757

58-
val appWidgets = (binding.widgetsList.adapter as WidgetsAdapter).widgetListItems
59-
setupAdapter(appWidgets)
58+
val appWidgets = (binding.widgetsList.adapter as? WidgetsAdapter)?.widgetListItems
59+
if (appWidgets != null) {
60+
setupAdapter(appWidgets)
61+
} else {
62+
getAppWidgets()
63+
}
6064
}
6165

6266
override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {

app/src/main/kotlin/com/simplemobiletools/launcher/views/HomeScreenGrid.kt

Lines changed: 100 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import android.view.animation.OvershootInterpolator
2626
import android.widget.RelativeLayout
2727
import androidx.core.graphics.drawable.toBitmap
2828
import androidx.core.graphics.drawable.toDrawable
29+
import androidx.core.graphics.toRect
2930
import androidx.core.graphics.withScale
3031
import androidx.core.graphics.withTranslation
3132
import androidx.core.view.ViewCompat
@@ -42,6 +43,7 @@ import com.simplemobiletools.launcher.extensions.getDrawableForPackageName
4243
import com.simplemobiletools.launcher.extensions.homeScreenGridItemsDB
4344
import com.simplemobiletools.launcher.helpers.*
4445
import com.simplemobiletools.launcher.models.HomeScreenGridItem
46+
import kotlinx.collections.immutable.toImmutableList
4547
import kotlin.math.*
4648

4749
class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : RelativeLayout(context, attrs, defStyle) {
@@ -87,6 +89,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
8789
pageChangeStarted = {
8890
widgetViews.forEach { it.resetTouches() }
8991
closeFolder()
92+
accessibilityHelper.invalidateRoot()
9093
}
9194
)
9295

@@ -105,12 +108,13 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
105108
val appWidgetHost = MyAppWidgetHost(context, WIDGET_HOST_ID)
106109
private val appWidgetManager = AppWidgetManager.getInstance(context)
107110

111+
private val accessibilityHelper = HomeScreenGridTouchHelper(this)
108112
var itemClickListener: ((HomeScreenGridItem) -> Unit)? = null
109113
var itemLongClickListener: ((HomeScreenGridItem) -> Unit)? = null
110114

111115

112116
init {
113-
ViewCompat.setAccessibilityDelegate(this, HomeScreenGridTouchHelper(this))
117+
ViewCompat.setAccessibilityDelegate(this, accessibilityHelper)
114118

115119
textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
116120
color = Color.WHITE
@@ -179,7 +183,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
179183
ensureBackgroundThread {
180184
val providers = appWidgetManager.installedProviders
181185
gridItems = context.homeScreenGridItemsDB.getAllItems() as ArrayList<HomeScreenGridItem>
182-
gridItems.forEach { item ->
186+
gridItems.toImmutableList().forEach { item ->
183187
if (item.type == ITEM_TYPE_ICON) {
184188
item.drawable = context.getDrawableForPackageName(item.packageName)
185189
} else if (item.type == ITEM_TYPE_FOLDER) {
@@ -241,6 +245,13 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
241245
ensureBackgroundThread {
242246
if (item.id != null) {
243247
context.homeScreenGridItemsDB.deleteById(item.id!!)
248+
if (item.parentId != null) {
249+
gridItems.filter { it.parentId == item.parentId && it.left > item.left && it.id != item.id }.forEach {
250+
it.left -= 1
251+
}
252+
253+
context.homeScreenGridItemsDB.shiftFolderItems(item.parentId!!, item.left, -1, item.id)
254+
}
244255
}
245256

246257
if (item.type == ITEM_TYPE_WIDGET) {
@@ -682,9 +693,20 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
682693
draggedItem!!.activityInfo
683694
)
684695

696+
fun finalizeFolderOrder(newItem: HomeScreenGridItem) {
697+
if (newParentId != null && gridItems.any { it.parentId == newParentId && it.left == newItem.left }) {
698+
gridItems.filter { it.parentId == newParentId && it.left >= newItem.left && it.id != newItem.id}.forEach {
699+
it.left += 1
700+
}
701+
702+
context.homeScreenGridItemsDB.shiftFolderItems(newParentId, newItem.left - 1, +1, newItem.id)
703+
}
704+
}
705+
685706
if (newHomeScreenGridItem.type == ITEM_TYPE_ICON) {
686707
ensureBackgroundThread {
687708
storeAndShowGridItem(newHomeScreenGridItem)
709+
finalizeFolderOrder(newHomeScreenGridItem)
688710
}
689711
} else if (newHomeScreenGridItem.type == ITEM_TYPE_SHORTCUT) {
690712
(context as? MainActivity)?.handleShorcutCreation(newHomeScreenGridItem.activityInfo!!) { shortcutId, label, icon ->
@@ -694,19 +716,10 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
694716
newHomeScreenGridItem.icon = icon.toBitmap()
695717
newHomeScreenGridItem.drawable = icon
696718
storeAndShowGridItem(newHomeScreenGridItem)
719+
finalizeFolderOrder(newHomeScreenGridItem)
697720
}
698721
}
699722
}
700-
701-
ensureBackgroundThread {
702-
if (newParentId != null && gridItems.any { it.parentId == newParentId && it.left == finalXIndex }) {
703-
gridItems.filter { it.parentId == newParentId && it.left >= finalXIndex }.forEach {
704-
it.left += 1
705-
}
706-
707-
context.homeScreenGridItemsDB.shiftFolderItems(newParentId, left - 1, +1)
708-
}
709-
}
710723
}
711724

712725
draggedItem = null
@@ -1052,7 +1065,6 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
10521065

10531066
items.forEach { item ->
10541067
val itemRect = folder.getItemRect(item)
1055-
// canvas.drawRect(itemRect, contrastTextPaint)
10561068
canvas.drawItemInCell(item, itemRect)
10571069
}
10581070
}
@@ -1098,8 +1110,9 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
10981110
// show the app icon itself at dragging, move it above the finger a bit to make it visible
10991111
val drawableX = (draggedItemCurrentCoords.first - iconSize / 1.5f).toInt()
11001112
val drawableY = (draggedItemCurrentCoords.second - iconSize / 1.2f).toInt()
1101-
draggedItem!!.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
1102-
draggedItem!!.drawable!!.draw(canvas)
1113+
val newDrawable = draggedItem!!.drawable?.constantState?.newDrawable()?.mutate()
1114+
newDrawable?.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
1115+
newDrawable?.draw(canvas)
11031116
} else if (draggedItem!!.type == ITEM_TYPE_WIDGET) {
11041117
// at first draw we are loading the widget from the database at some exact spot, not dragging it
11051118
if (!isFirstDraw) {
@@ -1119,18 +1132,19 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
11191132
}
11201133

11211134
// show the widget preview itself at dragging
1122-
val drawable = draggedItem!!.drawable!!
1123-
val aspectRatio = drawable.minimumHeight / drawable.minimumWidth.toFloat()
1124-
val drawableX = (draggedItemCurrentCoords.first - drawable.minimumWidth / 2f).toInt()
1125-
val drawableY = (draggedItemCurrentCoords.second - drawable.minimumHeight / 3f).toInt()
1126-
val drawableWidth = draggedItem!!.getWidthInCells() * cellWidth - iconMargin * (draggedItem!!.getWidthInCells() - 1)
1127-
drawable.setBounds(
1128-
drawableX,
1129-
drawableY,
1130-
drawableX + drawableWidth,
1131-
(drawableY + drawableWidth * aspectRatio).toInt()
1132-
)
1133-
drawable.draw(canvas)
1135+
draggedItem!!.drawable?.also { drawable ->
1136+
val aspectRatio = drawable.minimumHeight / drawable.minimumWidth.toFloat()
1137+
val drawableX = (draggedItemCurrentCoords.first - drawable.minimumWidth / 2f).toInt()
1138+
val drawableY = (draggedItemCurrentCoords.second - drawable.minimumHeight / 3f).toInt()
1139+
val drawableWidth = draggedItem!!.getWidthInCells() * cellWidth - iconMargin * (draggedItem!!.getWidthInCells() - 1)
1140+
drawable.setBounds(
1141+
drawableX,
1142+
drawableY,
1143+
drawableX + drawableWidth,
1144+
(drawableY + drawableWidth * aspectRatio).toInt()
1145+
)
1146+
drawable.draw(canvas)
1147+
}
11341148
}
11351149
}
11361150
}
@@ -1299,23 +1313,53 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
12991313
}
13001314

13011315
override fun getVisibleVirtualViews(virtualViewIds: MutableList<Int>?) {
1302-
val sorted = gridItems.sortedBy {
1303-
it.getDockAdjustedTop(rowCount) * 100 + it.left
1316+
val sorted = gridItems.filter { it.visibleOnCurrentPage() || (currentlyOpenFolder != null && it.parentId == currentlyOpenFolder?.item?.id) }.sortedBy {
1317+
(if (it.parentId == null) it.getDockAdjustedTop(rowCount) else 1) * 100 + it.left
13041318
}
13051319
sorted.forEachIndexed { index, homeScreenGridItem ->
13061320
virtualViewIds?.add(index, homeScreenGridItem.id?.toInt() ?: index)
13071321
}
13081322
}
13091323

13101324
override fun onPopulateNodeForVirtualView(virtualViewId: Int, node: AccessibilityNodeInfoCompat) {
1325+
val viewLocation = IntArray(2)
1326+
getLocationOnScreen(viewLocation)
1327+
1328+
// home screen
1329+
if (virtualViewId == -1) {
1330+
node.text = context.getString(R.string.app_name)
1331+
val viewBounds = Rect(left, top, right, bottom)
1332+
val onScreenBounds = Rect(viewBounds)
1333+
onScreenBounds.offset(viewLocation[0], viewLocation[1])
1334+
node.setBoundsInScreen(onScreenBounds)
1335+
node.setBoundsInParent(viewBounds)
1336+
1337+
node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK)
1338+
node.addAction(AccessibilityNodeInfoCompat.ACTION_LONG_CLICK)
1339+
node.setParent(this@HomeScreenGrid)
1340+
}
1341+
13111342
val item = gridItems.firstOrNull { it.id?.toInt() == virtualViewId } ?: throw IllegalArgumentException("Unknown id")
13121343

1313-
node.text = item.title
1344+
node.text = if (item.type == ITEM_TYPE_WIDGET) {
1345+
item.providerInfo?.loadLabel(context.packageManager) ?: item.title
1346+
} else {
1347+
item.title
1348+
}
13141349

1315-
val viewLocation = IntArray(2)
1316-
getLocationOnScreen(viewLocation)
1350+
val viewBounds = if (item == currentlyOpenFolder?.item) {
1351+
currentlyOpenFolder?.getDrawingRect()?.toRect()
1352+
} else if (item.type == ITEM_TYPE_WIDGET) {
1353+
val widgetPos = calculateWidgetPos(item.getTopLeft())
1354+
val left = widgetPos.x
1355+
val top = widgetPos.y
1356+
val right = left + item.getWidthInCells() * cellWidth
1357+
val bottom = top + item.getHeightInCells() * cellHeight
13171358

1318-
val viewBounds = getClickableRect(item)
1359+
Rect(left, top, right, bottom)
1360+
} else {
1361+
getClickableRect(item)
1362+
}
13191363
val onScreenBounds = Rect(viewBounds)
13201364
onScreenBounds.offset(viewLocation[0], viewLocation[1])
13211365
node.setBoundsInScreen(onScreenBounds)
@@ -1330,7 +1374,11 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
13301374
val item = gridItems.firstOrNull { it.id?.toInt() == virtualViewId } ?: throw IllegalArgumentException("Unknown id")
13311375
when (action) {
13321376
AccessibilityNodeInfoCompat.ACTION_CLICK -> itemClickListener?.apply {
1333-
invoke(item)
1377+
if (item == currentlyOpenFolder?.item) {
1378+
closeFolder(true)
1379+
} else {
1380+
invoke(item)
1381+
}
13341382
return true
13351383
}
13361384

@@ -1391,6 +1439,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
13911439
} else if (currentlyOpenFolder?.item?.id != folder.id) {
13921440
closeFolder()
13931441
}
1442+
accessibilityHelper.invalidateRoot()
13941443
}
13951444

13961445
fun closeFolder(redraw: Boolean = false) {
@@ -1399,6 +1448,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
13991448
if (redraw) {
14001449
redrawGrid()
14011450
}
1451+
accessibilityHelper.invalidateRoot()
14021452
}
14031453
}
14041454

@@ -1409,7 +1459,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
14091459
val drawable = if (item.type == ITEM_TYPE_FOLDER) {
14101460
item.toFolder().generateDrawable()
14111461
} else {
1412-
item.drawable!!
1462+
item.drawable?.constantState?.newDrawable()?.mutate()
14131463
}
14141464

14151465
if (item.docked) {
@@ -1458,7 +1508,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
14581508

14591509
private fun HomeScreenGridItem.visibleOnCurrentPage() = (pager.isItemOnCurrentPage(this) || docked) && parentId == null
14601510

1461-
private fun HomeScreenGridItem.isSingleCellType() = (drawable != null && type == ITEM_TYPE_ICON || type == ITEM_TYPE_SHORTCUT || type == ITEM_TYPE_FOLDER)
1511+
private fun HomeScreenGridItem.isSingleCellType() = (type == ITEM_TYPE_ICON || type == ITEM_TYPE_SHORTCUT || type == ITEM_TYPE_FOLDER)
14621512

14631513
private fun HomeScreenGridItem.toFolder(animateOpening: Boolean = false) = HomeScreenFolder(this, animateOpening)
14641514

@@ -1502,13 +1552,18 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
15021552
return null
15031553
}
15041554

1555+
val items = getItems()
1556+
val itemsCount = getItems().count()
1557+
1558+
if (itemsCount == 0) {
1559+
return null
1560+
}
1561+
15051562
val bitmap = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888)
15061563
val canvas = Canvas(bitmap)
15071564
val circlePath = Path().apply { addCircle((iconSize / 2).toFloat(), (iconSize / 2).toFloat(), (iconSize / 2).toFloat(), Path.Direction.CCW) }
15081565
canvas.clipPath(circlePath)
15091566
canvas.drawPaint(folderIconBackgroundPaint)
1510-
val items = getItems()
1511-
val itemsCount = getItems().count()
15121567
val folderColumnCount = ceil(sqrt(itemsCount.toDouble())).roundToInt()
15131568
val folderRowCount = ceil(itemsCount.toFloat() / folderColumnCount).roundToInt()
15141569
val scaledCellSize = (iconSize.toFloat() / folderColumnCount)
@@ -1519,8 +1574,9 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
15191574
val (row, column) = getItemPosition(it)
15201575
val drawableX = (scaledGap + column * scaledIconSize + column * scaledGap).toInt()
15211576
val drawableY = (extraYMargin + scaledGap + row * scaledIconSize + row * scaledGap).toInt()
1522-
it.drawable?.setBounds(drawableX, drawableY, drawableX + scaledIconSize.toInt(), drawableY + scaledIconSize.toInt())
1523-
it.drawable?.draw(canvas)
1577+
val newDrawable = it.drawable?.constantState?.newDrawable()?.mutate()
1578+
newDrawable?.setBounds(drawableX, drawableY, drawableX + scaledIconSize.toInt(), drawableY + scaledIconSize.toInt())
1579+
newDrawable?.draw(canvas)
15241580
}
15251581
canvas.drawPath(circlePath, folderIconBorderPaint)
15261582
return BitmapDrawable(resources, bitmap)
@@ -1572,6 +1628,10 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
15721628

15731629
fun getItemsGridCenters(): List<Triple<Int, Int, Int>> {
15741630
val count = getItems().count()
1631+
if (count == 0) {
1632+
return emptyList()
1633+
}
1634+
15751635
val columnsCount = ceil(sqrt(count.toDouble())).roundToInt()
15761636
val rowsCount = ceil(count.toFloat() / columnsCount).roundToInt()
15771637
val folderItemsRect = getItemsDrawingRect()

0 commit comments

Comments
 (0)