diff --git a/app/src/main/java/io/github/subhamtyagi/lastlauncher/LauncherActivity.java b/app/src/main/java/io/github/subhamtyagi/lastlauncher/LauncherActivity.java index f95f1c80..13d0678a 100644 --- a/app/src/main/java/io/github/subhamtyagi/lastlauncher/LauncherActivity.java +++ b/app/src/main/java/io/github/subhamtyagi/lastlauncher/LauncherActivity.java @@ -45,6 +45,7 @@ import android.text.style.ForegroundColorSpan; import android.util.ArrayMap; import android.view.ContextThemeWrapper; +import android.view.DragEvent; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -74,6 +75,7 @@ import java.util.ListIterator; import java.util.Locale; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import io.github.subhamtyagi.lastlauncher.dialogs.ColorSizeDialog; import io.github.subhamtyagi.lastlauncher.dialogs.FrozenAppsDialogs; @@ -132,11 +134,13 @@ @SuppressLint("NonConstantResourceId") public class LauncherActivity extends Activity implements View.OnClickListener, View.OnLongClickListener, + View.OnDragListener, + View.OnTouchListener, Gestures.OnSwipeListener { //region Field declarations - public static List mAppsList; + public final static List mAppsList = Collections.synchronizedList(new ArrayList<>()); // home layout private static FlowLayout mHomeLayout; // when search bar appears this will be true and show search result @@ -333,8 +337,6 @@ public void loadApps() { // Log.d(TAG, "loadApps: install shortcut sizes::" + installedShortcut); final int appsCount = activities.size(); - mAppsList = Collections.synchronizedList(new ArrayList<>(appsCount + installedShortcut)); - // get the most used apps // a list of app that are popular on f-droid and some of my apps List oftenApps = Utils.getOftenAppsList(); @@ -494,6 +496,8 @@ private AppTextView getCustomView() { AppTextView textView = new AppTextView(this); textView.setOnClickListener(this); textView.setOnLongClickListener(this); + textView.setOnTouchListener(this); + textView.setOnDragListener(this); textView.setPadding(10, 0, 4, -2); textView.setTypeface(mTypeface); return textView; @@ -1225,6 +1229,162 @@ private void removeShortcut(AppTextView view) { loadApps(); } + private int mCurrentDropTargetColor = 0; + private CharSequence mLastDropTarget = ""; + + @Override + public boolean onDrag(View v, DragEvent event) { + AppTextView dropTarget = (AppTextView) v; + AppTextView draggedItem = (AppTextView) event.getLocalState(); + + switch (event.getAction()) { + case DragEvent.ACTION_DRAG_STARTED: + if (mCurrentDropTargetColor == 0) { + mCurrentDropTargetColor = draggedItem.getCurrentTextColor(); + } + break; + + case DragEvent.ACTION_DRAG_ENTERED: + if (dropTarget.getText() != mLastDropTarget) { + mLastDropTarget = dropTarget.getText(); + + String dropActivityName = (String) dropTarget.getTag(); + int currentTextColor; + + if (dropTarget.getText() == draggedItem.getText()) { + currentTextColor = mCurrentDropTargetColor; + } else { + Apps appBeforeDropTarget = null; + Apps dropTargetApp = null; + + synchronized (mAppsList) { + for (Apps apps : mAppsList) { + if (dropActivityName.equalsIgnoreCase(apps.getActivityName())) { + dropTargetApp = apps; + break; + } + + appBeforeDropTarget = apps; + } + } + + if (dropTargetApp == null) { + return true; + } + + int appBeforeDropTargetColor = appBeforeDropTarget == null ? 0 : appBeforeDropTarget.getColor(); + float[] appBeforeDropTargetHsv = new float[3]; + int dropTargetColor = dropTargetApp.getColor(); + float[] dropTargetHsv = new float[3]; + + Color.colorToHSV(appBeforeDropTargetColor, appBeforeDropTargetHsv); + Color.colorToHSV(dropTargetColor, dropTargetHsv); + + float[] newHsv = new float[3]; + + newHsv[0] = (appBeforeDropTargetHsv[0] + dropTargetHsv[0]) / 2; + newHsv[1] = (appBeforeDropTargetHsv[1] + dropTargetHsv[1]) / 2; + newHsv[2] = (appBeforeDropTargetHsv[2] + dropTargetHsv[2]) / 2; + + currentTextColor = Color.HSVToColor((Color.alpha(appBeforeDropTargetColor) + Color.alpha(dropTargetColor)) / 2, newHsv); + } + + setColorOfDraggedView(draggedItem, currentTextColor); + } + break; + + case DragEvent.ACTION_DROP: + if (dropTarget.getText() == draggedItem.getText()) { + draggedItem.setTextColor(mCurrentDropTargetColor); + mCurrentDropTargetColor = 0; + } else { + DbUtils.putAppColor((String) draggedItem.getTag(), draggedItem.getCurrentTextColor()); + sortApps(DbUtils.getSortsTypes()); + } + break; + + case DragEvent.ACTION_DRAG_EXITED: + setColorOfDraggedView(draggedItem, mCurrentDropTargetColor); + break; + } + + return true; + } + + private void setColorOfDraggedView(AppTextView draggedItem, int currentTextColor) { + draggedItem.setTextColor(currentTextColor); + + String draggedActivityName = (String) draggedItem.getTag(); + + synchronized (mAppsList) { + for (Apps apps : mAppsList) { + if (draggedActivityName.equalsIgnoreCase(apps.getActivityName())) { + apps.setColor(currentTextColor); + break; + } + } + } + } + + private long touchDownTime = 0; + private float x = 0; + private float y = 0; + private final AtomicBoolean touchActionTriggered = new AtomicBoolean(false); + + @Override + public boolean onTouch(View v, MotionEvent event) { + int sortType = DbUtils.getSortsTypes(); + + if (!DbUtils.getEnableAppsDragging() || sortType != SORT_BY_COLOR) { + return false; + } + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + touchDownTime = System.currentTimeMillis(); + x = event.getX(); + y = event.getY(); + touchActionTriggered.set(false); + + new Thread(() -> { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // ignored + } + + if (touchActionTriggered.compareAndSet(false, true)) { + runOnUiThread(() -> onLongClick(v)); + } + }).start(); + + return true; + + case MotionEvent.ACTION_MOVE: + int historySize = event.getHistorySize(); + + if (historySize > 0 && + (Math.abs(x - event.getX()) > 5 || Math.abs(y - event.getY()) > 5)) { + if (touchActionTriggered.compareAndSet(false, true)) { + v.startDrag(null, new View.DragShadowBuilder(v), v, 0); + } + } + + return true; + + case MotionEvent.ACTION_UP: + touchActionTriggered.set(true); + + if (System.currentTimeMillis() - touchDownTime < 500) { + v.performClick(); + } + + return true; + } + + return false; + } + @Override public void onSwipe(Gestures.Direction direction) { if (direction == Gestures.Direction.SWIPE_RIGHT) { diff --git a/app/src/main/java/io/github/subhamtyagi/lastlauncher/dialogs/FrozenAppsDialogs.java b/app/src/main/java/io/github/subhamtyagi/lastlauncher/dialogs/FrozenAppsDialogs.java index 2d4fc49f..52f9b8a3 100644 --- a/app/src/main/java/io/github/subhamtyagi/lastlauncher/dialogs/FrozenAppsDialogs.java +++ b/app/src/main/java/io/github/subhamtyagi/lastlauncher/dialogs/FrozenAppsDialogs.java @@ -28,6 +28,7 @@ import android.widget.PopupMenu; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import io.github.subhamtyagi.lastlauncher.R; @@ -94,6 +95,7 @@ public int updateFrozenList() { } } } + Collections.sort(frozenApps, (o1, o2) -> o1.getAppName().compareToIgnoreCase(o2.getAppName())); return frozenApps.size(); } diff --git a/app/src/main/java/io/github/subhamtyagi/lastlauncher/dialogs/GlobalSettingsDialog.java b/app/src/main/java/io/github/subhamtyagi/lastlauncher/dialogs/GlobalSettingsDialog.java index bcd0c7d2..b5eab0be 100644 --- a/app/src/main/java/io/github/subhamtyagi/lastlauncher/dialogs/GlobalSettingsDialog.java +++ b/app/src/main/java/io/github/subhamtyagi/lastlauncher/dialogs/GlobalSettingsDialog.java @@ -57,6 +57,7 @@ public class GlobalSettingsDialog extends Dialog implements View.OnClickListener private final LauncherActivity launcherActivity; private final Context context; private TextView freezeSize; + private TextView dragApps; public GlobalSettingsDialog(Context context, LauncherActivity launcherActivity) { super(context); @@ -88,9 +89,11 @@ protected void onCreate(Bundle savedInstanceState) { findViewById(R.id.settings_padding).setOnClickListener(this); findViewById(R.id.settings_color_size).setOnClickListener(this); findViewById(R.id.settings_sort_app_by).setOnClickListener(this); - findViewById(R.id.settings_sort_app_reverse).setOnClickListener(this); findViewById(R.id.settings_restart_launcher).setOnClickListener(this); + dragApps = findViewById(R.id.drag_apps); + dragApps.setOnClickListener(this); + //TODO: remove this var TextView colorSniffer = findViewById(R.id.settings_color_sniffer); colorSniffer.setOnClickListener(this); @@ -105,13 +108,18 @@ protected void onCreate(Bundle savedInstanceState) { findViewById(R.id.settings_frozen_apps).setOnClickListener(this); findViewById(R.id.settings_hidden_apps).setOnClickListener(this); - //reflect the DB value if (DbUtils.isSizeFrozen()) { freezeSize.setText(R.string.unfreeze_app_size); - } else + } else { freezeSize.setText(R.string.freeze_apps_size); + } + if (DbUtils.getEnableAppsDragging()) { + dragApps.setText(R.string.disable_apps_dragging); + } else { + dragApps.setText(R.string.enable_apps_dragging); + } } @Override @@ -133,10 +141,6 @@ public void onClick(View view) { sortApps(view); break; } - case R.id.settings_sort_app_reverse: { - sortAppsReverseOrder(); - break; - } case R.id.settings_color_size: { showColorAndSizeDialog(); break; @@ -169,6 +173,9 @@ public void onClick(View view) { case R.id.settings_restart_launcher: launcherActivity.recreate(); break; + case R.id.drag_apps: + toggleAppsDragging(); + break; } } @@ -214,6 +221,9 @@ private void sortApps(View view) { case R.id.menu_sort_by_recent_use: launcherActivity.sortApps(Constants.SORT_BY_RECENT_OPEN); break; + case R.id.settings_sort_app_reverse: + sortAppsReverseOrder(); + break; } return true; }); @@ -262,6 +272,17 @@ private void setFlowLayoutAlignment(View view) { } + private void toggleAppsDragging() { + boolean appsDraggingEnabled = DbUtils.getEnableAppsDragging(); + DbUtils.setEnableAppsDragging(!appsDraggingEnabled); + + if (!appsDraggingEnabled) { + dragApps.setText(R.string.disable_apps_dragging); + } else { + dragApps.setText(R.string.enable_apps_dragging); + } + } + private void randomColor() { boolean rColor = !DbUtils.isRandomColor(); DbUtils.randomColor(rColor); @@ -303,8 +324,9 @@ private void freezeAppsSize() { DbUtils.freezeSize(!b); if (!b) { freezeSize.setText(R.string.unfreeze_app_size); - } else + } else { freezeSize.setText(R.string.freeze_apps_size); + } } private void frozenApps() { diff --git a/app/src/main/java/io/github/subhamtyagi/lastlauncher/utils/DbUtils.java b/app/src/main/java/io/github/subhamtyagi/lastlauncher/utils/DbUtils.java index e64cb5c1..bc60f610 100644 --- a/app/src/main/java/io/github/subhamtyagi/lastlauncher/utils/DbUtils.java +++ b/app/src/main/java/io/github/subhamtyagi/lastlauncher/utils/DbUtils.java @@ -62,6 +62,7 @@ public class DbUtils { private static final String APPS_COLORS_DEFAULT = "apps_color_default"; private static final String APPS_SORTS_TYPE = "apps_sorts_types"; private static final String APPS_SORTS_REVERSE_ORDER = "apps_sorts_reverse_order"; + private static final String ENABLE_APPS_DRAGGING = "enable_apps_dragging"; public static void init(Context context) { @@ -397,6 +398,14 @@ public static void setAppSortReverseOrder(boolean reverseOrder) { SpUtils.getInstance().putBoolean(APPS_SORTS_REVERSE_ORDER, reverseOrder); } + public static boolean getEnableAppsDragging() { + return SpUtils.getInstance().getBoolean(ENABLE_APPS_DRAGGING, false); + } + + public static void setEnableAppsDragging(boolean enableAppsDragging) { + SpUtils.getInstance().putBoolean(ENABLE_APPS_DRAGGING, enableAppsDragging); + } + // a simple ciphered counter: "opening counter" is a private thing // rest is on device security private static String codeCount(int count) { diff --git a/app/src/main/java/io/github/subhamtyagi/lastlauncher/views/colorseekbar/ColorSeekBar.java b/app/src/main/java/io/github/subhamtyagi/lastlauncher/views/colorseekbar/ColorSeekBar.java index 150ea7b7..0c2f1af0 100644 --- a/app/src/main/java/io/github/subhamtyagi/lastlauncher/views/colorseekbar/ColorSeekBar.java +++ b/app/src/main/java/io/github/subhamtyagi/lastlauncher/views/colorseekbar/ColorSeekBar.java @@ -500,7 +500,7 @@ public int getColor() { } /** - * Set color,the mCachedColors must contains the specified color, if not ,invoke setColorBarPosition(0); + * Set color,the mCachedColors must contains the specified color, if not take the nearest * * @param color */ @@ -508,6 +508,23 @@ public void setColor(int color) { int withoutAlphaColor = Color.rgb(Color.red(color), Color.green(color), Color.blue(color)); if (mInit) { int value = mCachedColors.indexOf(withoutAlphaColor); + + if (value == -1) { + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + + float[] cachedHsv = new float[3]; + + for (int i = 7; i < mCachedColors.size(); i++) { + Color.colorToHSV(mCachedColors.get(i), cachedHsv); + + if (cachedHsv[0] < hsv[0]) { + value = i; + break; + } + } + } + setAlphaValue(Color.alpha(color)); setColorBarPosition(value); diff --git a/app/src/main/res/layout/dialog_global_settings.xml b/app/src/main/res/layout/dialog_global_settings.xml index 0719cc19..3eb33fe8 100644 --- a/app/src/main/res/layout/dialog_global_settings.xml +++ b/app/src/main/res/layout/dialog_global_settings.xml @@ -155,16 +155,15 @@ android:foregroundGravity="center_vertical|center_horizontal" /> - + - + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 253edc1e..0494cb8f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -91,4 +91,6 @@ Recently first Restart Launcher + Enable Dragging + Disable Dragging \ No newline at end of file