Implement bottom row docking

This commit is contained in:
Ensar Sarajčić 2023-07-19 17:26:36 +02:00
parent 1c67a8f097
commit 05c9644037
7 changed files with 71 additions and 24 deletions

View file

@ -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) {

View file

@ -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))
}
}
}
}
}

View file

@ -208,6 +208,7 @@ class AllAppsFragment(context: Context, attributeSet: AttributeSet) : MyFragment
"",
"",
null,
false,
appLauncher.drawable
)

View file

@ -266,6 +266,7 @@ class WidgetsFragment(context: Context, attributeSet: AttributeSet) : MyFragment
"",
"",
null,
false,
appWidget.widgetPreviewImage,
appWidget.providerInfo,
appWidget.activityInfo,

View file

@ -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)

View file

@ -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"
}

View file

@ -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<Int>?) {
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)
}