diff --git a/app/src/main/kotlin/com/simplemobiletools/launcher/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/launcher/activities/MainActivity.kt index 23e911b..f0d4661 100644 --- a/app/src/main/kotlin/com/simplemobiletools/launcher/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/launcher/activities/MainActivity.kt @@ -148,6 +148,7 @@ class MainActivity : SimpleActivity(), FlingListener { "", shortcutId, icon.toBitmap(), + false, icon ) @@ -764,7 +765,7 @@ class MainActivity : SimpleActivity(), FlingListener { val defaultDialerPackage = (getSystemService(Context.TELECOM_SERVICE) as TelecomManager).defaultDialerPackage appLaunchers.firstOrNull { it.packageName == defaultDialerPackage }?.apply { val dialerIcon = - HomeScreenGridItem(null, 0, config.homeRowCount - 1, 0, config.homeRowCount - 1, 0, defaultDialerPackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null) + HomeScreenGridItem(null, 0, config.homeRowCount - 1, 0, config.homeRowCount - 1, 0, defaultDialerPackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null, true) homeScreenGridItems.add(dialerIcon) } } catch (e: Exception) { @@ -774,7 +775,7 @@ class MainActivity : SimpleActivity(), FlingListener { val defaultSMSMessengerPackage = Telephony.Sms.getDefaultSmsPackage(this) appLaunchers.firstOrNull { it.packageName == defaultSMSMessengerPackage }?.apply { val SMSMessengerIcon = - HomeScreenGridItem(null, 1, config.homeRowCount - 1, 1, config.homeRowCount - 1, 0, defaultSMSMessengerPackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null) + HomeScreenGridItem(null, 1, config.homeRowCount - 1, 1, config.homeRowCount - 1, 0, defaultSMSMessengerPackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null, true) homeScreenGridItems.add(SMSMessengerIcon) } } catch (e: Exception) { @@ -786,7 +787,7 @@ class MainActivity : SimpleActivity(), FlingListener { val defaultBrowserPackage = resolveInfo!!.activityInfo.packageName appLaunchers.firstOrNull { it.packageName == defaultBrowserPackage }?.apply { val browserIcon = - HomeScreenGridItem(null, 2, config.homeRowCount - 1, 2, config.homeRowCount - 1, 0, defaultBrowserPackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null) + HomeScreenGridItem(null, 2, config.homeRowCount - 1, 2, config.homeRowCount - 1, 0, defaultBrowserPackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null, true) homeScreenGridItems.add(browserIcon) } } catch (e: Exception) { @@ -797,7 +798,7 @@ class MainActivity : SimpleActivity(), FlingListener { val storePackage = potentialStores.firstOrNull { isPackageInstalled(it) && appLaunchers.map { it.packageName }.contains(it) } if (storePackage != null) { appLaunchers.firstOrNull { it.packageName == storePackage }?.apply { - val storeIcon = HomeScreenGridItem(null, 3, config.homeRowCount - 1, 3, config.homeRowCount - 1, 0, storePackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null) + val storeIcon = HomeScreenGridItem(null, 3, config.homeRowCount - 1, 3, config.homeRowCount - 1, 0, storePackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null, true) homeScreenGridItems.add(storeIcon) } } @@ -810,7 +811,7 @@ class MainActivity : SimpleActivity(), FlingListener { val defaultCameraPackage = resolveInfo!!.activityInfo.packageName appLaunchers.firstOrNull { it.packageName == defaultCameraPackage }?.apply { val cameraIcon = - HomeScreenGridItem(null, 4, config.homeRowCount - 1, 4, config.homeRowCount - 1, 0, defaultCameraPackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null) + HomeScreenGridItem(null, 4, config.homeRowCount - 1, 4, config.homeRowCount - 1, 0, defaultCameraPackage, "", title, ITEM_TYPE_ICON, "", -1, "", "", null, true) homeScreenGridItems.add(cameraIcon) } } catch (e: Exception) { diff --git a/app/src/main/kotlin/com/simplemobiletools/launcher/databases/AppsDatabase.kt b/app/src/main/kotlin/com/simplemobiletools/launcher/databases/AppsDatabase.kt index f6e85d9..e655487 100644 --- a/app/src/main/kotlin/com/simplemobiletools/launcher/databases/AppsDatabase.kt +++ b/app/src/main/kotlin/com/simplemobiletools/launcher/databases/AppsDatabase.kt @@ -7,6 +7,7 @@ import androidx.room.RoomDatabase import androidx.room.TypeConverters import androidx.room.migration.Migration import androidx.sqlite.db.SupportSQLiteDatabase +import com.simplemobiletools.launcher.extensions.config import com.simplemobiletools.launcher.helpers.Converters import com.simplemobiletools.launcher.interfaces.AppLaunchersDao import com.simplemobiletools.launcher.interfaces.HiddenIconsDao @@ -15,7 +16,7 @@ import com.simplemobiletools.launcher.models.AppLauncher import com.simplemobiletools.launcher.models.HiddenIcon import com.simplemobiletools.launcher.models.HomeScreenGridItem -@Database(entities = [AppLauncher::class, HomeScreenGridItem::class, HiddenIcon::class], version = 5) +@Database(entities = [AppLauncher::class, HomeScreenGridItem::class, HiddenIcon::class], version = 6) @TypeConverters(Converters::class) abstract class AppsDatabase : RoomDatabase() { @@ -37,6 +38,7 @@ abstract class AppsDatabase : RoomDatabase() { .addMigrations(MIGRATION_2_3) .addMigrations(MIGRATION_3_4) .addMigrations(MIGRATION_4_5) + .addMigrations(MIGRATION_5_6.withContext(context)) .build() } } @@ -71,5 +73,14 @@ abstract class AppsDatabase : RoomDatabase() { database.execSQL("ALTER TABLE home_screen_grid_items ADD COLUMN page INTEGER NOT NULL DEFAULT 0") } } + + private val MIGRATION_5_6 = object { + fun withContext(context: Context) = object : Migration(5, 6) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE home_screen_grid_items ADD COLUMN docked INTEGER NOT NULL DEFAULT 0") + database.execSQL("UPDATE home_screen_grid_items SET docked = 1 WHERE page = 0 AND type != 1 AND top = ?", arrayOf(context.config.homeRowCount - 1)) + } + } + } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/launcher/fragments/AllAppsFragment.kt b/app/src/main/kotlin/com/simplemobiletools/launcher/fragments/AllAppsFragment.kt index d4b4214..ff2bf46 100644 --- a/app/src/main/kotlin/com/simplemobiletools/launcher/fragments/AllAppsFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/launcher/fragments/AllAppsFragment.kt @@ -208,6 +208,7 @@ class AllAppsFragment(context: Context, attributeSet: AttributeSet) : MyFragment "", "", null, + false, appLauncher.drawable ) diff --git a/app/src/main/kotlin/com/simplemobiletools/launcher/fragments/WidgetsFragment.kt b/app/src/main/kotlin/com/simplemobiletools/launcher/fragments/WidgetsFragment.kt index 07b5afc..1053144 100644 --- a/app/src/main/kotlin/com/simplemobiletools/launcher/fragments/WidgetsFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/launcher/fragments/WidgetsFragment.kt @@ -266,6 +266,7 @@ class WidgetsFragment(context: Context, attributeSet: AttributeSet) : MyFragment "", "", null, + false, appWidget.widgetPreviewImage, appWidget.providerInfo, appWidget.activityInfo, diff --git a/app/src/main/kotlin/com/simplemobiletools/launcher/interfaces/HomeScreenGridItemsDao.kt b/app/src/main/kotlin/com/simplemobiletools/launcher/interfaces/HomeScreenGridItemsDao.kt index 7abd805..592e895 100644 --- a/app/src/main/kotlin/com/simplemobiletools/launcher/interfaces/HomeScreenGridItemsDao.kt +++ b/app/src/main/kotlin/com/simplemobiletools/launcher/interfaces/HomeScreenGridItemsDao.kt @@ -23,8 +23,8 @@ interface HomeScreenGridItemsDao { @Query("UPDATE home_screen_grid_items SET title = :title WHERE id = :id") fun updateItemTitle(title: String, id: Long): Int - @Query("UPDATE home_screen_grid_items SET `left` = :left, `top` = :top, `right` = :right, `bottom` = :bottom, `page` = :page WHERE id = :id") - fun updateItemPosition(left: Int, top: Int, right: Int, bottom: Int, page: Int, id: Long) + @Query("UPDATE home_screen_grid_items SET `left` = :left, `top` = :top, `right` = :right, `bottom` = :bottom, `page` = :page, `docked` = :docked WHERE id = :id") + fun updateItemPosition(left: Int, top: Int, right: Int, bottom: Int, page: Int, docked: Boolean, id: Long) @Query("DELETE FROM home_screen_grid_items WHERE id = :id") fun deleteById(id: Long) diff --git a/app/src/main/kotlin/com/simplemobiletools/launcher/models/HomeScreenGridItem.kt b/app/src/main/kotlin/com/simplemobiletools/launcher/models/HomeScreenGridItem.kt index 0d4b38c..c87acab 100644 --- a/app/src/main/kotlin/com/simplemobiletools/launcher/models/HomeScreenGridItem.kt +++ b/app/src/main/kotlin/com/simplemobiletools/launcher/models/HomeScreenGridItem.kt @@ -25,6 +25,7 @@ data class HomeScreenGridItem( @ColumnInfo(name = "intent") var intent: String, // used at static and dynamic shortcuts on click @ColumnInfo(name = "shortcut_id") var shortcutId: String, // used at pinned shortcuts at startLauncher call @ColumnInfo(name = "icon") var icon: Bitmap? = null, // store images of pinned shortcuts, those cannot be retrieved after creating + @ColumnInfo(name = "docked") var docked: Boolean = false, // special flag, meaning that page, top and bottom don't matter for this item, it is always at the bottom of the screen @Ignore var drawable: Drawable? = null, @Ignore var providerInfo: AppWidgetProviderInfo? = null, // used at widgets @@ -32,7 +33,7 @@ data class HomeScreenGridItem( @Ignore var widthCells: Int = 1, @Ignore var heightCells: Int = 1 ) { - constructor() : this(null, -1, -1, -1, -1, 0, "", "", "", ITEM_TYPE_ICON, "", -1, "", "", null, null, null, null, 1, 1) + constructor() : this(null, -1, -1, -1, -1, 0, "", "", "", ITEM_TYPE_ICON, "", -1, "", "", null, false, null, null, null, 1, 1) fun getWidthInCells() = if (right == -1 || left == -1) { widthCells @@ -46,5 +47,21 @@ data class HomeScreenGridItem( bottom - top + 1 } + fun getDockAdjustedTop(rowCount: Int): Int { + return if (!docked) { + top + } else { + rowCount - 1 + } + } + + fun getDockAdjustedBottom(rowCount: Int): Int { + return if (!docked) { + bottom + } else { + rowCount - 1 + } + } + fun getItemIdentifier() = "$packageName/$activityName" } diff --git a/app/src/main/kotlin/com/simplemobiletools/launcher/views/HomeScreenGrid.kt b/app/src/main/kotlin/com/simplemobiletools/launcher/views/HomeScreenGrid.kt index 2d68305..9f9a666 100644 --- a/app/src/main/kotlin/com/simplemobiletools/launcher/views/HomeScreenGrid.kt +++ b/app/src/main/kotlin/com/simplemobiletools/launcher/views/HomeScreenGrid.kt @@ -272,7 +272,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel } updateWidgetPositionAndSize(widgetView, item) ensureBackgroundThread { - context.homeScreenGridItemsDB.updateItemPosition(item.left, item.top, item.right, item.bottom, item.page, item.id!!) + context.homeScreenGridItemsDB.updateItemPosition(item.left, item.top, item.right, item.bottom, item.page, false, item.id!!) } } @@ -311,9 +311,9 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel // check if the destination cell is empty var areAllCellsEmpty = true val wantedCell = Pair(xIndex, yIndex) - gridItems.filter { it.page == currentPage }.forEach { item -> + gridItems.filter { it.page == currentPage || it.docked }.forEach { item -> for (xCell in item.left..item.right) { - for (yCell in item.top..item.bottom) { + for (yCell in item.getDockAdjustedTop(rowCount)..item.getDockAdjustedBottom(rowCount)) { val cell = Pair(xCell, yCell) val isAnyCellOccupied = wantedCell == cell if (isAnyCellOccupied) { @@ -335,9 +335,10 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel right = xIndex bottom = yIndex page = currentPage + docked = yIndex == rowCount - 1 ensureBackgroundThread { - context.homeScreenGridItemsDB.updateItemPosition(left, top, right, bottom, page, id!!) + context.homeScreenGridItemsDB.updateItemPosition(left, top, right, bottom, page, docked, id!!) } } redrawIcons = true @@ -359,6 +360,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel "", "", draggedItem!!.icon, + yIndex == rowCount - 1, draggedItem!!.drawable, draggedItem!!.providerInfo, draggedItem!!.activityInfo @@ -416,9 +418,9 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel } var areAllCellsEmpty = true - gridItems.filter { it.id != draggedItem?.id && it.page == currentPage }.forEach { item -> + gridItems.filter { it.id != draggedItem?.id && (it.page == currentPage || it.docked) }.forEach { item -> for (xCell in item.left..item.right) { - for (yCell in item.top..item.bottom) { + for (yCell in item.getDockAdjustedTop(rowCount)..item.getDockAdjustedBottom(rowCount)) { val cell = Pair(xCell, yCell) val isAnyCellOccupied = widgetTargetCells.contains(cell) if (isAnyCellOccupied) { @@ -454,6 +456,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel widgetItem.right, widgetItem.bottom, currentPage, + false, widgetItem.id!! ) val widgetView = widgetViews.firstOrNull { it.tag == widgetItem.widgetId } @@ -636,8 +639,8 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel if (item.id != draggedItem?.id) { val drawableX = cellXCoords[item.left] + iconMargin + extraXMargin + sideMargins.left + (width * xFactor).toInt() - if (item.top == rowCount - 1) { - val drawableY = cellYCoords[item.top] + cellHeight - iconMargin - iconSize + sideMargins.top + if (item.docked) { + val drawableY = cellYCoords[rowCount - 1] + cellHeight - iconMargin - iconSize + sideMargins.top item.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize) } else { @@ -665,15 +668,26 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel } } - gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT) && it.page == currentPage }.forEach { item -> + gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT) && it.page == currentPage && !it.docked }.forEach { item -> if (item.outOfBounds()) { return@forEach } handleDrawing(item, currentXFactor) } + gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT) && it.docked }.forEach { item -> + if (item.outOfBounds()) { + return@forEach + } + + handleDrawing(item, 0f) + } if (pageChangeAnimLeftPercentage > 0f && pageChangeAnimLeftPercentage < 1f) { - gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT) && it.page == lastPage }.forEach { item -> + gridItems.filter { (it.drawable != null && it.type == ITEM_TYPE_ICON || it.type == ITEM_TYPE_SHORTCUT) && it.page == lastPage && !it.docked }.forEach { item -> + if (item.outOfBounds()) { + return@forEach + } + handleDrawing(item, lastXFactor) } } @@ -799,8 +813,8 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel } val clickableLeft = cellXCoords[item.left] + sideMargins.left + extraXMargin - val clickableTop = if (item.top == rowCount - 1) { - cellYCoords[item.top] + cellHeight - iconSize - iconMargin + val clickableTop = if (item.docked) { + cellYCoords[item.getDockAdjustedTop(rowCount)] + cellHeight - iconSize - iconMargin } else { cellYCoords[item.top] - iconMargin + extraYMargin } + sideMargins.top @@ -833,7 +847,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel } fun isClickingGridItem(x: Int, y: Int): HomeScreenGridItem? { - for (gridItem in gridItems.filter { it.page == currentPage }) { + for (gridItem in gridItems.filter { it.page == currentPage || it.docked }) { if (gridItem.outOfBounds()) { continue } @@ -867,7 +881,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel } private fun HomeScreenGridItem.outOfBounds(): Boolean { - return (left >= cellXCoords.size || right >= cellXCoords.size || top >= cellYCoords.size || bottom >= cellYCoords.size) + return (left >= cellXCoords.size || right >= cellXCoords.size || (!docked && (top >= cellYCoords.size - 1 || bottom >= cellYCoords.size - 1))) } private inner class HomeScreenGridTouchHelper(host: View) : ExploreByTouchHelper(host) { @@ -882,7 +896,9 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel } override fun getVisibleVirtualViews(virtualViewIds: MutableList?) { - val sorted = gridItems.sortedBy { it.top * 100 + it.left } + val sorted = gridItems.sortedBy { + it.getDockAdjustedTop(rowCount) * 100 + it.left + } sorted.forEachIndexed { index, homeScreenGridItem -> virtualViewIds?.add(index, homeScreenGridItem.id?.toInt() ?: index) }