diff --git a/app/src/main/java/foundation/e/blisslauncher/core/database/DatabaseManager.java b/app/src/main/java/foundation/e/blisslauncher/core/database/DatabaseManager.java index 9819fbc7959655341ac801911c6833df4f66adb2..4c890cfd3f1c843672f97ad4b65cdf6449330dcd 100644 --- a/app/src/main/java/foundation/e/blisslauncher/core/database/DatabaseManager.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/database/DatabaseManager.java @@ -4,9 +4,13 @@ import android.content.Context; import android.widget.GridLayout; import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Set; import foundation.e.blisslauncher.core.customviews.BlissFrameLayout; +import foundation.e.blisslauncher.core.database.daos.WidgetDao; import foundation.e.blisslauncher.core.database.model.FolderItem; import foundation.e.blisslauncher.core.database.model.LauncherItem; import foundation.e.blisslauncher.core.database.model.WidgetItem; @@ -117,17 +121,38 @@ public class DatabaseManager { new_component_name); } - public Single getHeightOfWidget(int id) { - return Single.defer(() -> Single.just(LauncherDB.getDatabase(mContext).widgetDao().getHeight(id))); + public void insertWidget(WidgetItem widgetItem) { + mAppExecutors.diskIO().execute( + () -> LauncherDB.getDatabase(mContext).widgetDao().insert(widgetItem)); } - public void saveWidget(int id, int height) { - WidgetItem widgetItem = new WidgetItem(id, height); + public void saveWidgetHeight(int id, int height) { mAppExecutors.diskIO().execute( - () -> LauncherDB.getDatabase(mContext).widgetDao().insert(widgetItem)); + () -> LauncherDB.getDatabase(mContext).widgetDao().updateHeight(id, height)); } public void removeWidget(int id) { mAppExecutors.diskIO().execute(() -> LauncherDB.getDatabase(mContext).widgetDao().delete(id)); } + + public Single> getWidgets(int[] widgetIds) { + return Single.defer(() -> { + Set missingIds = new HashSet<>(); + for (int widgetId : widgetIds) { + missingIds.add(widgetId); + } + WidgetDao widgetDao = LauncherDB.getDatabase(mContext).widgetDao(); + List widgets = widgetDao.getAll(); + for (WidgetItem widget : widgets) { + missingIds.remove(widget.id); + } + for (int id : missingIds) { + WidgetItem item = new WidgetItem(id); + widgets.add(item); + widgetDao.insert(item); + } + widgets.sort(Comparator.comparingInt(widget -> widget.order).thenComparingInt(widget -> widget.id)); + return Single.just(widgets); + }); + } } diff --git a/app/src/main/java/foundation/e/blisslauncher/core/database/LauncherDB.java b/app/src/main/java/foundation/e/blisslauncher/core/database/LauncherDB.java index 477e022ca28d44ef933fba4bac41e7178b1c86d6..6c6b7700ba9e49c28bdeaf7b4076e78e457e4165 100644 --- a/app/src/main/java/foundation/e/blisslauncher/core/database/LauncherDB.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/database/LauncherDB.java @@ -17,7 +17,11 @@ import foundation.e.blisslauncher.core.database.daos.WidgetDao; import foundation.e.blisslauncher.core.database.model.LauncherItem; import foundation.e.blisslauncher.core.database.model.WidgetItem; -@Database(entities = {LauncherItem.class, WidgetItem.class}, version = 4, exportSchema = false) +@Database( + entities = {LauncherItem.class, WidgetItem.class}, + version = 5, + exportSchema = false +) @TypeConverters({CharSequenceConverter.class}) public abstract class LauncherDB extends RoomDatabase { @@ -37,6 +41,14 @@ public abstract class LauncherDB extends RoomDatabase { private static final Migration MIGRATION_4_5 = new Migration(4, 5) { @Override public void migrate(@NonNull SupportSQLiteDatabase database) { + database.execSQL("ALTER TABLE `widget_items` RENAME TO `widget_items_old`"); + database.execSQL("CREATE TABLE IF NOT EXISTS `widget_items` (" + + "`id` INTEGER NOT NULL, " + + "`height` INTEGER NOT NULL DEFAULT 0, " + + "`order` INTEGER NOT NULL DEFAULT 99999, " + + "PRIMARY KEY(`id`))"); + database.execSQL("INSERT INTO `widget_items` (`id`, `height`) SELECT `id`, `height` FROM `widget_items_old`"); + database.execSQL("DROP TABLE `widget_items_old`"); } }; @@ -46,7 +58,7 @@ public abstract class LauncherDB extends RoomDatabase { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), LauncherDB.class, "launcher_db") - .addMigrations(MIGRATION_3_4) + .addMigrations(MIGRATION_3_4, MIGRATION_4_5) .build(); } } diff --git a/app/src/main/java/foundation/e/blisslauncher/core/database/daos/WidgetDao.java b/app/src/main/java/foundation/e/blisslauncher/core/database/daos/WidgetDao.java index e23172c2e47e09d0544da1d0c76999f3a7d68dbe..f85fbff6aeab103b85add48bf605b5f1a581b691 100644 --- a/app/src/main/java/foundation/e/blisslauncher/core/database/daos/WidgetDao.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/database/daos/WidgetDao.java @@ -15,9 +15,15 @@ public interface WidgetDao { @Insert(onConflict = OnConflictStrategy.REPLACE) long insert(WidgetItem widgetItem); + @Query("UPDATE widget_items SET height = :height WHERE id = :id") + void updateHeight(int id, int height); + @Query("SELECT height FROM widget_items WHERE id = :id") int getHeight(int id); + @Query("SELECT * FROM widget_items") + List getAll(); + @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(List widgetItems); diff --git a/app/src/main/java/foundation/e/blisslauncher/core/database/model/WidgetItem.java b/app/src/main/java/foundation/e/blisslauncher/core/database/model/WidgetItem.java index 28de71e054c76f08a3147360554bad7f50e00bfb..645d142d08e8ae0ed7e6a962e7b325cc8524b091 100644 --- a/app/src/main/java/foundation/e/blisslauncher/core/database/model/WidgetItem.java +++ b/app/src/main/java/foundation/e/blisslauncher/core/database/model/WidgetItem.java @@ -1,22 +1,28 @@ package foundation.e.blisslauncher.core.database.model; - +import androidx.room.ColumnInfo; import androidx.room.Entity; import androidx.room.PrimaryKey; @Entity(tableName = "widget_items") public class WidgetItem { + public static final int DEFAULT_ORDER = 99999; + @PrimaryKey public int id; - public int height; - public WidgetItem(){ + @ColumnInfo(defaultValue = "0") + public int height = 0; + + @ColumnInfo(defaultValue = "99999") + public int order = DEFAULT_ORDER; + + public WidgetItem() { } - public WidgetItem(int id, int height){ + public WidgetItem(int id) { this.id = id; - this.height = height; } } diff --git a/app/src/main/java/foundation/e/blisslauncher/features/launcher/LauncherActivity.java b/app/src/main/java/foundation/e/blisslauncher/features/launcher/LauncherActivity.java index 0f0e1fb30b8f9bab46de54517a5ef6bdbb7eca69..afe87b4362420def88a352ad9c6331e914e77181 100755 --- a/app/src/main/java/foundation/e/blisslauncher/features/launcher/LauncherActivity.java +++ b/app/src/main/java/foundation/e/blisslauncher/features/launcher/LauncherActivity.java @@ -75,7 +75,6 @@ import androidx.viewpager.widget.ViewPager; import com.jakewharton.rxbinding3.widget.RxTextView; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; @@ -115,6 +114,7 @@ import foundation.e.blisslauncher.core.database.model.CalendarIcon; import foundation.e.blisslauncher.core.database.model.FolderItem; import foundation.e.blisslauncher.core.database.model.LauncherItem; import foundation.e.blisslauncher.core.database.model.ShortcutItem; +import foundation.e.blisslauncher.core.database.model.WidgetItem; import foundation.e.blisslauncher.core.events.AppAddEvent; import foundation.e.blisslauncher.core.events.AppChangeEvent; import foundation.e.blisslauncher.core.events.AppRemoveEvent; @@ -413,6 +413,9 @@ public class LauncherActivity extends AppCompatActivity implements mAppWidgetHost.deleteAppWidgetId(appWidgetId); return false; } + WidgetItem widgetItem = new WidgetItem(appWidgetId); + widgetItem.order = 0; + DatabaseManager.getManager(this).insertWidget(widgetItem); return true; } @@ -482,6 +485,7 @@ public class LauncherActivity extends AppCompatActivity implements while (widgetView != null) { widgetView = WidgetViewBuilder.create(this, widgetView); addWidgetToContainer(widgetView); + DatabaseManager.getManager(this).insertWidget(new WidgetItem(widgetView.getAppWidgetId())); widgetView = widgetManager.dequeAddWidgetView(); } } @@ -1471,29 +1475,31 @@ public class LauncherActivity extends AppCompatActivity implements // [[END]] int[] widgetIds = mAppWidgetHost.getAppWidgetIds(); - Arrays.sort(widgetIds); - for (int id : widgetIds) { - AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(id); - if (appWidgetInfo != null) { - RoundedWidgetView hostView = (RoundedWidgetView) mAppWidgetHost.createView( - getApplicationContext(), id, - appWidgetInfo); - hostView.setAppWidget(id, appWidgetInfo); - getCompositeDisposable().add(DatabaseManager.getManager(this).getHeightOfWidget(id) - .subscribeOn(Schedulers.from(AppExecutors.getInstance().diskIO())) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(height -> { - RoundedWidgetView widgetView = WidgetViewBuilder.create(this, hostView); - if (height != 0) { - int minHeight = hostView.getAppWidgetInfo().minResizeHeight; - int maxHeight = mDeviceProfile.availableHeightPx * 3 / 4; - int normalisedDifference = (maxHeight - minHeight) / 100; - int newHeight = minHeight + (normalisedDifference * height); - widgetView.getLayoutParams().height = newHeight; - } - addWidgetToContainer(widgetView); - }, Throwable::printStackTrace)); + getCompositeDisposable().add(DatabaseManager.getManager(this).getWidgets(widgetIds) + .subscribeOn(Schedulers.from(AppExecutors.getInstance().diskIO())) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::bindWidgets)); + } + + private void bindWidgets(List widgets) { + for (WidgetItem widget : widgets) { + AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(widget.id); + if (appWidgetInfo == null) continue; + + RoundedWidgetView hostView = (RoundedWidgetView) mAppWidgetHost.createView( + getApplicationContext(), widget.id, + appWidgetInfo); + hostView.setAppWidget(widget.id, appWidgetInfo); + + RoundedWidgetView widgetView = WidgetViewBuilder.create(this, hostView); + if (widgetView == null) continue; + if (widget.height != 0) { + int minHeight = hostView.getAppWidgetInfo().minResizeHeight; + int maxHeight = mDeviceProfile.availableHeightPx * 3 / 4; + int normalisedDifference = (maxHeight - minHeight) / 100; + widgetView.getLayoutParams().height = minHeight + (normalisedDifference * widget.height); } + addWidgetToContainer(widgetView); } } @@ -3343,7 +3349,7 @@ public class LauncherActivity extends AppCompatActivity implements @Override public void onStopTrackingTouch(SeekBar seekBar) { - DatabaseManager.getManager(LauncherActivity.this).saveWidget( + DatabaseManager.getManager(LauncherActivity.this).saveWidgetHeight( activeRoundedWidgetView.getAppWidgetId(), seekBar.getProgress()); } }); diff --git a/app/src/main/java/foundation/e/blisslauncher/features/widgets/WidgetsActivity.java b/app/src/main/java/foundation/e/blisslauncher/features/widgets/WidgetsActivity.java index a0ea7d1c2d2ba73c2c1be3bb55e8d7c131644591..ee10dc7a81ae7eb5a7bba2e2ccd856df537b8b9a 100644 --- a/app/src/main/java/foundation/e/blisslauncher/features/widgets/WidgetsActivity.java +++ b/app/src/main/java/foundation/e/blisslauncher/features/widgets/WidgetsActivity.java @@ -14,13 +14,18 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import foundation.e.blisslauncher.BlissLauncher; import foundation.e.blisslauncher.R; import foundation.e.blisslauncher.core.customviews.RoundedWidgetView; import foundation.e.blisslauncher.core.customviews.WidgetHost; +import foundation.e.blisslauncher.core.database.DatabaseManager; +import foundation.e.blisslauncher.core.database.model.WidgetItem; +import foundation.e.blisslauncher.core.executors.AppExecutors; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; public class WidgetsActivity extends Activity implements AddedWidgetsAdapter.OnActionClickListener { @@ -29,6 +34,8 @@ public class WidgetsActivity extends Activity implements AddedWidgetsAdapter.OnA private AppWidgetManager mAppWidgetManager; private WidgetHost mAppWidgetHost; + private final CompositeDisposable mCompositeDisposable = new CompositeDisposable(); + private static final int REQUEST_PICK_APPWIDGET = 455; private static final int REQUEST_CREATE_APPWIDGET = 189; @@ -60,15 +67,27 @@ public class WidgetsActivity extends Activity implements AddedWidgetsAdapter.OnA }); } + @Override + protected void onDestroy() { + super.onDestroy(); + mCompositeDisposable.dispose(); + } + private void refreshRecyclerView() { - List widgets = new ArrayList<>(); int[] widgetIds = mAppWidgetHost.getAppWidgetIds(); - Arrays.sort(widgetIds); - for (int id : widgetIds) { - AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(id); + mCompositeDisposable.add(DatabaseManager.getManager(this).getWidgets(widgetIds) + .subscribeOn(Schedulers.from(AppExecutors.getInstance().diskIO())) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(this::setWidgetItems)); + } + + private void setWidgetItems(List widgetItems) { + List widgets = new ArrayList<>(); + for (WidgetItem item : widgetItems) { + AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(item.id); if (appWidgetInfo != null) { Widget widget = new Widget(); - widget.id = id; + widget.id = item.id; widget.info = appWidgetInfo; widgets.add(widget); }