Commit 9b74e296 authored by Amit Kumar's avatar Amit Kumar
Browse files

Merge branch 'dev' with version 1.1.0

parents 7705271f c763de52
Pipeline #13321 passed with stage
in 4 minutes and 22 seconds
......@@ -3,8 +3,8 @@ apply plugin: 'io.fabric'
// Manifest version information!
def versionMajor = 1
def versionMinor = 0
def versionPatch = 2
def versionMinor = 1
def versionPatch = 0
android {
compileSdkVersion rootProject.ext.compileSdkVersion
......
......@@ -44,6 +44,7 @@
android:name=".features.launcher.LauncherActivity"
android:clearTaskOnLaunch="true"
android:launchMode="singleTask"
android:resumeWhilePausing="true"
android:screenOrientation="nosensor"
android:stateNotNeeded="true"
android:theme="@style/HomeScreenTheme"
......
......@@ -19,8 +19,6 @@ public class BlissLauncher extends Application {
private static WidgetHost sAppWidgetHost;
private static AppWidgetManager sAppWidgetManager;
private static int sLongPressTimeout = 300;
private static final String TAG = "BlissLauncher";
@Override
......@@ -92,6 +90,6 @@ public class BlissLauncher extends Application {
}
public static long getLongPressTimeout() {
return sLongPressTimeout;
return 500;
}
}
......@@ -5,11 +5,9 @@ import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ImageView;
import foundation.e.blisslauncher.BlissLauncher;
import foundation.e.blisslauncher.R;
public class AppWidgetResizeFrame extends FrameLayout {
......@@ -58,6 +56,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
private Context mContext;
private static final String TAG = "AppWidgetResizeFrame";
public AppWidgetResizeFrame(@NonNull Context context, RoundedWidgetView widgetView) {
super(context);
......@@ -72,101 +72,6 @@ public class AppWidgetResizeFrame extends FrameLayout {
setBackgroundResource(R.drawable.widget_resize_frame);
setPadding(0, 0, 0, 0);
LayoutParams lp;
mTopHandle = new ImageView(context);
mTopHandle.setImageResource(R.drawable.widget_resize_handle_top);
lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.CENTER_HORIZONTAL | Gravity.TOP);
addView(mTopHandle, lp);
mBottomHandle = new ImageView(context);
mBottomHandle.setImageResource(R.drawable.widget_resize_handle_bottom);
lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
addView(mBottomHandle, lp);
Rect p = AppWidgetHostView.getDefaultPaddingForWidget(context,
widgetView.getAppWidgetInfo().provider, null);
mWidgetPaddingTop = p.top;
mWidgetPaddingBottom = p.bottom;
if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
mTopHandle.setVisibility(GONE);
mBottomHandle.setVisibility(GONE);
}
final float density = context.getResources().getDisplayMetrics().density;
mBackgroundPadding = (int) Math.ceil(density * BACKGROUND_PADDING);
mTouchTargetWidth = 2 * mBackgroundPadding;
}
public boolean beginResizeIfPointInRegion(int x, int y) {
boolean horizontalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0;
boolean verticalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0;
mTopBorderActive = (y < mTouchTargetWidth + mTopTouchRegionAdjustment) && verticalActive;
mBottomBorderActive = (y > getHeight() - mTouchTargetWidth + mBottomTouchRegionAdjustment)
&& verticalActive;
boolean anyBordersActive = mTopBorderActive || mBottomBorderActive;
mBaselineWidth = getMeasuredWidth();
mBaselineHeight = getMeasuredHeight();
mBaselineX = getLeft();
mBaselineY = getTop();
if (anyBordersActive) {
mTopHandle.setAlpha(mTopBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
mBottomHandle.setAlpha(mBottomBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
}
return anyBordersActive;
}
/**
* Here we bound the deltas such that the frame cannot be stretched beyond the extents
* of the CellLayout, and such that the frame's borders can't cross.
*/
public void updateDeltas(int deltaX, int deltaY) {
if (mTopBorderActive) {
mDeltaY = Math.max(-mBaselineY, deltaY);
mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY);
} else if (mBottomBorderActive) {
mDeltaY = Math.min(BlissLauncher.getApplication(
mContext).getDeviceProfile().availableHeightPx - (mBaselineY + mBaselineHeight),
deltaY);
mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY);
}
}
public void visualizeResizeForDelta(int deltaX, int deltaY) {
visualizeResizeForDelta(deltaX, deltaY, false);
}
/**
* Based on the deltas, we resize the frame, and, if needed, we resize the widget.
*/
private void visualizeResizeForDelta(int deltaX, int deltaY, boolean onDismiss) {
updateDeltas(deltaX, deltaY);
/* DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
if (mTopBorderActive) {
lp.y = mBaselineY + mDeltaY;
lp.height = mBaselineHeight - mDeltaY;
} else if (mBottomBorderActive) {
lp.height = mBaselineHeight + mDeltaY;
}
resizeWidgetIfNeeded(onDismiss);*/
requestLayout();
}
/**
* This is the final step of the resize. Here we save the new widget size and position
* to LauncherModel and animate the resize frame.
*/
public void commitResize() {
//resizeWidgetIfNeeded(true);
requestLayout();
//setLayoutParams(mRoundedWidgetView.getLayoutParams());
}
}
......@@ -4,8 +4,14 @@ import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import foundation.e.blisslauncher.R;
import foundation.e.blisslauncher.features.widgets.CheckLongPressHelper;
......@@ -15,10 +21,18 @@ public class RoundedWidgetView extends AppWidgetHostView {
private final Path stencilPath = new Path();
private float cornerRadius;
private CheckLongPressHelper mLongPressHelper;
private Context mContext;
private static final String TAG = "RoundedWidgetView";
private ImageView resizeBorder;
private OnTouchListener _onTouchListener;
private OnLongClickListener _longClick;
private long _down;
private boolean mChildrenFocused;
public RoundedWidgetView(Context context) {
super(context);
this.mContext = context;
this.cornerRadius = context.getResources().getDimensionPixelSize(R.dimen.corner_radius);
mLongPressHelper = new CheckLongPressHelper(this);
}
......@@ -44,6 +58,11 @@ public class RoundedWidgetView extends AppWidgetHostView {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "onInterceptTouchEvent() called with: ev = [" + ev.getAction() + "]");
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mLongPressHelper.cancelLongPress();
}
// Consume any touch events for ourselves after longpress is triggered
if (mLongPressHelper.hasPerformedLongPress()) {
......@@ -60,6 +79,9 @@ public class RoundedWidgetView extends AppWidgetHostView {
}
case MotionEvent.ACTION_UP:
mLongPressHelper.cancelLongPress();
break;
case MotionEvent.ACTION_CANCEL:
mLongPressHelper.cancelLongPress();
break;
......@@ -67,6 +89,7 @@ public class RoundedWidgetView extends AppWidgetHostView {
// Otherwise continue letting touch events fall through to children
return false;
}
@Override
......@@ -78,6 +101,55 @@ public class RoundedWidgetView extends AppWidgetHostView {
@Override
public int getDescendantFocusability() {
return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
return mChildrenFocused ? ViewGroup.FOCUS_BEFORE_DESCENDANTS
: ViewGroup.FOCUS_BLOCK_DESCENDANTS;
}
@Override
protected void onFocusChanged(boolean gainFocus, int direction,
@Nullable Rect previouslyFocusedRect) {
if (gainFocus) {
mChildrenFocused = false;
dispatchChildFocus(false);
}
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
}
@Override
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
dispatchChildFocus(mChildrenFocused && focused != null);
if (focused != null) {
focused.setFocusableInTouchMode(false);
}
}
@Override
public boolean dispatchUnhandledMove(View focused, int direction) {
return mChildrenFocused;
}
private void dispatchChildFocus(boolean childIsFocused) {
// The host view's background changes when selected, to indicate the focus is inside.
setSelected(childIsFocused);
}
public void addBorder() {
if (resizeBorder != null) {
removeBorder();
}
resizeBorder = new ImageView(mContext);
resizeBorder.setImageResource(R.drawable.widget_resize_frame);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
resizeBorder.setLayoutParams(layoutParams);
addView(resizeBorder);
}
public void removeBorder() {
if (resizeBorder != null) {
removeView(resizeBorder);
resizeBorder = null;
}
}
}
......@@ -8,8 +8,10 @@ import java.util.List;
import foundation.e.blisslauncher.core.customviews.BlissFrameLayout;
import foundation.e.blisslauncher.core.database.model.FolderItem;
import foundation.e.blisslauncher.core.database.model.LauncherItem;
import foundation.e.blisslauncher.core.database.model.WidgetItem;
import foundation.e.blisslauncher.core.executors.AppExecutors;
import foundation.e.blisslauncher.core.utils.Constants;
import io.reactivex.Single;
public class DatabaseManager {
......@@ -107,4 +109,18 @@ public class DatabaseManager {
LauncherDB.getDatabase(mContext).launcherDao().updateComponent(old_component_name,
new_component_name);
}
public Single<Integer> getHeightOfWidget(int id){
return Single.defer(() -> Single.just(LauncherDB.getDatabase(mContext).widgetDao().getHeight(id)));
}
public void saveWidget(int id, int height){
WidgetItem widgetItem = new WidgetItem(id, height);
mAppExecutors.diskIO().execute(
() -> LauncherDB.getDatabase(mContext).widgetDao().insert(widgetItem));
}
public void removeWidget(int id){
mAppExecutors.diskIO().execute(() -> LauncherDB.getDatabase(mContext).widgetDao().delete(id));
}
}
package foundation.e.blisslauncher.core.database;
import android.arch.persistence.db.SupportSQLiteDatabase;
import android.arch.persistence.room.Database;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.arch.persistence.room.TypeConverters;
import android.arch.persistence.room.migration.Migration;
import android.content.Context;
import foundation.e.blisslauncher.core.database.converters.CharSequenceConverter;
import foundation.e.blisslauncher.core.database.daos.LauncherDao;
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}, version = 3, exportSchema = false)
@Database(entities = {LauncherItem.class, WidgetItem.class}, version = 4, exportSchema = false)
@TypeConverters({CharSequenceConverter.class})
public abstract class LauncherDB extends RoomDatabase {
public abstract LauncherDao launcherDao();
public abstract WidgetDao widgetDao();
private static volatile LauncherDB INSTANCE;
private static final Migration MIGRATION_3_4 = new Migration(3, 4) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS `widget_items` (`id` INTEGER NOT NULL, `height` INTEGER NOT NULL, PRIMARY KEY(`id`))");
}
};
public static LauncherDB getDatabase(Context context){
if (INSTANCE == null) {
synchronized (LauncherDB.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
LauncherDB.class, "launcher_db")
.addMigrations(MIGRATION_3_4)
.build();
}
}
......
package foundation.e.blisslauncher.core.database;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.GridLayout;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;
public class Storage {
private final String TAG = "BLISS_STORAGE";
private final SharedPreferences prefs;
public Storage(Context context) {
prefs = context.getSharedPreferences("launcher_layout", Context.MODE_PRIVATE);
}
/**
* Loop through all the child elements of all the pages, and the dock, to create a JSON
* document, which is then stored in the shared-preferences.
*/
public void save(final List<GridLayout> pages, final GridLayout dock) {
AsyncTask.execute(() -> {
JSONObject data = new JSONObject();
JSONArray pagesData = new JSONArray();
JSONArray dockData = new JSONArray();
try {
for (int i = 0; i < pages.size(); i++) {
stuffData(pagesData, pages.get(i));
}
stuffData(dockData, dock);
data.put("pages", pagesData);
data.put("dock", dockData);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("LAYOUT", data.toString(4));
editor.putBoolean("LAYOUT_PRESENT", true);
editor.apply();
} catch(Exception e) {
Log.e(TAG, "Couldn't save layout " + e);
}
});
}
/**
* Reads the tags of the View networkItems of a single page to populate a JSONArray
* @param storageArray array in which data is stored
* @param layout Layout which is stored
* @throws Exception if any json i/o exception
*/
private void stuffData(JSONArray storageArray, ViewGroup layout) throws Exception {
//TODO:
/*JSONArray apps = new JSONArray();
for (int j = 0; j < layout.getChildCount(); j++) {
List<Object> tags = (List<Object>) layout.getChildAt(j).getTag();
AppItem appItem = (AppItem) tags.get(2);
JSONObject appData = new JSONObject();
appData.put("index", j);
appData.put("packageName", appItem.getPackageName());
appData.put("isFolder", appItem.isFolder());
appData.put("componentName", appItem.getComponentName());
if(appItem.isFolder()) {
appData.put("folderID", appItem.getFolderID());
appData.put("folderName", appItem.getLabel());
JSONArray subAppPackageNames = new JSONArray();
for(int k=0;k<appItem.getSubApps().size();k++) {
subAppPackageNames.put(appItem.getSubApps().get(k).getPackageName());
}
appData.put("subApps", subAppPackageNames);
}
apps.put(appData);
}
storageArray.put(apps);*/
}
/**
* Converts the JSON data stored as a string back into valid JSON objects
* @return stored data of launcher
*/
public StorageData load() {
StorageData storageData = new StorageData();
try {
JSONObject jsonData = new JSONObject(prefs.getString("LAYOUT", ""));
storageData.pages = jsonData.getJSONArray("pages");
storageData.dock = jsonData.getJSONArray("dock");
} catch (JSONException e) {
Log.e(TAG, "Could not load data " + e);
}
return storageData;
}
/**
* @return true if the shared preferences contains a previously stored layout
*/
public boolean isLayoutPresent() {
return prefs.getBoolean("LAYOUT_PRESENT", false);
}
/**
* A class that simplifies access to the stored JSON data.
*/
public static class StorageData {
public JSONArray pages;
public JSONArray dock;
private String TAG = "BLISS_STORAGE_DATA";
public int getNPages() {
return pages.length();
}
public int getNDocked() {
try {
return dock.getJSONArray(0).length();
} catch (JSONException e) {
Log.e(TAG, "Couldn't count dock networkItems.");
return 0;
}
}
}
public boolean isWallpaperShown() {
return prefs.getBoolean("WALLPAPER_SHOWN", false);
}
public void setWallpaperShown() {
prefs.edit().putBoolean("WALLPAPER_SHOWN", true).apply();
}
}
package foundation.e.blisslauncher.core.database.daos;
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.OnConflictStrategy;
import android.arch.persistence.room.Query;
import java.util.List;
import foundation.e.blisslauncher.core.database.model.WidgetItem;
@Dao
public interface WidgetDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insert(WidgetItem widgetItem);
@Query("SELECT height FROM widget_items WHERE id = :id")
int getHeight(int id);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<WidgetItem> widgetItems);
@Query("DELETE FROM widget_items WHERE id = :id")
void delete(int id);
}
......@@ -46,7 +46,6 @@ public class LauncherItem {
* {@link Constants#ITEM_TYPE_SHORTCUT}
* {@link Constants#ITEM_TYPE_FOLDER}
*/
@NonNull
@ColumnInfo(name = "item_type")
public int itemType;
......
package foundation.e.blisslauncher.core.database.model;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;
@Entity(tableName = "widget_items")
public class WidgetItem {
@PrimaryKey
public int id;
public int height;
public WidgetItem(){
}
public WidgetItem(int id, int height){
this.id = id;
this.height = height;
}
}
......@@ -168,8 +168,8 @@ public class AppProvider {
mAppsRepository = AppsRepository.getAppsRepository();
}
public static AppProvider getInstance(Context context){
if(sInstance == null){
public static AppProvider getInstance(Context context) {
if (sInstance == null) {
sInstance = new AppProvider(context);
sInstance.reload();
}
......@@ -265,7 +265,8 @@ public class AppProvider {
mLauncherItems.add(applicationItem);
} else {
FolderItem folderItem =
(FolderItem) mLauncherItems.get(foldersIndex.get(applicationItem.container));
(FolderItem) mLauncherItems.get(
foldersIndex.get(applicationItem.container));
if (folderItem.items == null) {
folderItem.items = new ArrayList<>();
}
......@@ -289,7 +290,8 @@ public class AppProvider {
mLauncherItems.add(shortcutItem);
} else {
FolderItem folderItem =
(FolderItem) mLauncherItems.get(foldersIndex.