diff --git a/app/src/main/java/io/github/sankalp/lunox/LauncherActivity.java b/app/src/main/java/io/github/sankalp/lunox/LauncherActivity.java index e4d99e2..47c4570 100644 --- a/app/src/main/java/io/github/sankalp/lunox/LauncherActivity.java +++ b/app/src/main/java/io/github/sankalp/lunox/LauncherActivity.java @@ -79,12 +79,14 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; +import io.github.sankalp.lunox.dialogs.AppSettingsPopup; import io.github.sankalp.lunox.dialogs.ColorSizeDialog; import io.github.sankalp.lunox.dialogs.FrozenAppsDialogs; import io.github.sankalp.lunox.dialogs.GlobalColorSizeDialog; import io.github.sankalp.lunox.dialogs.GlobalSettingsDialog; import io.github.sankalp.lunox.dialogs.HiddenAppsDialogs; import io.github.sankalp.lunox.dialogs.PaddingDialog; +import io.github.sankalp.lunox.dialogs.PermissionDialog; import io.github.sankalp.lunox.dialogs.RenameInputDialogs; import io.github.sankalp.lunox.model.Apps; import io.github.sankalp.lunox.model.Shortcut; @@ -564,13 +566,13 @@ public class LauncherActivity extends Activity implements View.OnClickListener, // If we have very few apps, try reloading in case permissions were granted loadApps(); } - + // Check if search box is visible and hide it if needed if (mSearchBox.getVisibility() == View.VISIBLE) { mSearchBox.setVisibility(View.GONE); mHomeLayout.setPadding(DbUtils.getPaddingLeft(), DbUtils.getPaddingTop(), DbUtils.getPaddingRight(), DbUtils.getPaddingBottom()); } - + // Reset search state searching = false; } @@ -605,88 +607,13 @@ public class LauncherActivity extends Activity implements View.OnClickListener, } private void showPopup(String activityName, AppTextView view) { - - Context context; - // set theme - // if theme wallpaper ie transparent then we have to show other theme - if (DbUtils.getTheme() == R.style.Wallpaper) - context = new ContextThemeWrapper(this, R.style.AppTheme); - else - context = new ContextThemeWrapper(this, DbUtils.getTheme()); - - PopupMenu popupMenu = new PopupMenu(context, view); - popupMenu.getMenuInflater().inflate(R.menu.menu, popupMenu.getMenu()); - - - int color = Color.parseColor("#E53935"); - - SpannableString s = new SpannableString(getString(R.string.hide)); - - s.setSpan(new ForegroundColorSpan(color), 0, s.length(), 0); - popupMenu.getMenu().findItem(R.id.menu_hide).setTitle(s); - - s = new SpannableString(getString(R.string.uninstall)); - s.setSpan(new ForegroundColorSpan(color), 0, s.length(), 0); - popupMenu.getMenu().findItem(R.id.menu_uninstall).setTitle(s); - - s = new SpannableString(getString(R.string.reset_to_default)); - s.setSpan(new ForegroundColorSpan(color), 0, s.length(), 0); - popupMenu.getMenu().findItem(R.id.menu_reset_to_default).setTitle(s); - - - // set proper item based on Db value - if (DbUtils.isAppFrozen(activityName)) { - popupMenu.getMenu().findItem(R.id.menu_freeze_size).setTitle(R.string.unfreeze_size); - } - - //disable some item for shortcut - // and change the uninstall to remove - if (view.isShortcut()) { - - SpannableString s1 = new SpannableString(getString(R.string.remove)); - s1.setSpan(new ForegroundColorSpan(Color.parseColor("#E53935")), 0, s1.length(), 0); - popupMenu.getMenu().findItem(R.id.menu_uninstall).setTitle(s1); - - popupMenu.getMenu().findItem(R.id.menu_hide).setVisible(false); - //renaming is also disabled; - // consider it later - popupMenu.getMenu().findItem(R.id.menu_rename).setVisible(false); - popupMenu.getMenu().findItem(R.id.menu_app_info).setVisible(false); - } - - popupMenu.setOnMenuItemClickListener(menuItem -> { - int id = menuItem.getItemId(); - if (id == R.id.menu_color) { - changeColorSize(activityName, view); - } else if (id == R.id.menu_rename) { - renameApp(activityName, view.getText().toString()); - } else if (id == R.id.menu_freeze_size) { - freezeAppSize(activityName); - } else if (id == R.id.menu_hide) { - hideApp(activityName); - } else if (id == R.id.menu_uninstall) { - if (view.isShortcut()) { - removeShortcut(view); - } else { - uninstallApp(activityName); - } - } else if (id == R.id.menu_app_info) { - showAppInfo(activityName); - } else if (id == R.id.menu_reset_to_default) { - resetApp(activityName); - } else if (id == R.id.menu_reset_color) { - resetAppColor(activityName); - } else { - return true; - } - return true; - }); - // not forget to show popup - popupMenu.show(); + // show app settings popup instead of popup menu + AppSettingsPopup popup = new AppSettingsPopup(this, activityName, view, this); + popup.showAsDropDown(view); } //reset the app color to default color; - private void resetAppColor(String activityName) { + public void resetAppColor(String activityName) { DbUtils.removeColor(activityName); boolean sortNeeded = (DbUtils.getSortsTypes() == SORT_BY_COLOR); addAppAfterReset(activityName, sortNeeded); @@ -723,7 +650,7 @@ public class LauncherActivity extends Activity implements View.OnClickListener, } // as method name suggest - private void freezeAppSize(String activityName) { + public void freezeAppSize(String activityName) { boolean b = DbUtils.isAppFrozen(activityName); for (Apps apps : mAppsList) { if (activityName.equalsIgnoreCase(apps.getActivityName())) { @@ -734,7 +661,7 @@ public class LauncherActivity extends Activity implements View.OnClickListener, } // as method name suggest - private void hideApp(String activityName) { + public void hideApp(String activityName) { for (Apps apps : mAppsList) { if (activityName.equalsIgnoreCase(apps.getActivityName())) { apps.setAppHidden(true); @@ -744,7 +671,7 @@ public class LauncherActivity extends Activity implements View.OnClickListener, } // show the app rename Dialog - private void renameApp(String activityName, String appName) { + public void renameApp(String activityName, String appName) { dialogs = new RenameInputDialogs(this, activityName, appName, this); Window window = dialogs.getWindow(); if (window != null) { @@ -771,20 +698,20 @@ public class LauncherActivity extends Activity implements View.OnClickListener, } // reset the app - private void resetApp(String activityName) { + public void resetApp(String activityName) { DbUtils.removeAppName(activityName); DbUtils.removeColor(activityName); DbUtils.removeSize(activityName); addAppAfterReset(activityName, true); } - private void showAppInfo(String activityName) { + public void showAppInfo(String activityName) { Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse("package:" + activityName.split("/")[0])); startActivity(intent); } - private void uninstallApp(String activityName) { + public void uninstallApp(String activityName) { Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); intent.setData(Uri.parse("package:" + activityName.split("/")[0])); intent.putExtra(Intent.EXTRA_RETURN_RESULT, true); @@ -792,7 +719,7 @@ public class LauncherActivity extends Activity implements View.OnClickListener, } //show dialog(i.e a color seek bar) for change color - private void changeColorSize(String activityName, TextView view) { + public void changeColorSize(String activityName, TextView view) { int color = DbUtils.getAppColor(activityName); if (color == DbUtils.NULL_TEXT_COLOR) { color = view.getCurrentTextColor(); @@ -1214,7 +1141,7 @@ public class LauncherActivity extends Activity implements View.OnClickListener, * * @param view shortcut view to be removed... */ - private void removeShortcut(AppTextView view) { + public void removeShortcut(AppTextView view) { // view.setVisibility(View.GONE); shortcutUtils.removeShortcut(new Shortcut(view.getText().toString(), view.getUri())); @@ -1224,13 +1151,13 @@ public class LauncherActivity extends Activity implements View.OnClickListener, @Override public void onSwipe(Gestures.Direction direction) { - if (direction == Gestures.Direction.SWIPE_RIGHT) { + if (direction == Gestures.Direction.SWIPE_UP) { searching = true; mSearchBox.setText(""); mSearchBox.setVisibility(View.VISIBLE); mSearchBox.requestFocus(); imm.showSoftInput(mSearchBox, InputMethodManager.SHOW_IMPLICIT); - } else if (direction == Gestures.Direction.SWIPE_LEFT) { + } else if (direction == Gestures.Direction.SWIPE_DOWN) { if (searching) { mSearchBox.setVisibility(View.GONE); imm.hideSoftInputFromWindow(mSearchBox.getWindowToken(), 0); @@ -1245,6 +1172,13 @@ public class LauncherActivity extends Activity implements View.OnClickListener, DeviceAdminManager.lockDevice(this); } + @Override + public void onLongPress() { + // Show launcher settings on long press in free space + dialogs = new GlobalSettingsDialog(this, this); + dialogs.show(); + } + static class SearchTask extends AsyncTask> { @Override protected void onPostExecute(ArrayList filteredApps) { @@ -1341,100 +1275,16 @@ public class LauncherActivity extends Activity implements View.OnClickListener, return; } - // Create a comprehensive permission request dialog - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("Welcome to Lunox! 🚀"); - builder.setMessage("To provide the best experience, Lunox needs a few permissions:\n\n" + - "📱 **Usage Access**: To show all your installed apps\n" + - "🔒 **Device Admin**: To manage app freezing and advanced features\n\n" + - "These permissions help Lunox work properly and show all your apps."); - - builder.setIcon(android.R.drawable.ic_dialog_info); - builder.setCancelable(false); - - builder.setPositiveButton("Grant Permissions", (dialog, which) -> { - requestPermissions(); - }); - - builder.setNegativeButton("Skip for Now", (dialog, which) -> { - DbUtils.setPermissionDialogShown(true); - }); - - AlertDialog dialog = builder.create(); - dialog.show(); + // Create the new permission dialog with proper theming + Context ctx; + if (DbUtils.getTheme() == R.style.Wallpaper) + ctx = new ContextThemeWrapper(this, R.style.AppTheme); + else + ctx = new ContextThemeWrapper(this, DbUtils.getTheme()); + + PermissionDialog permissionDialog = new PermissionDialog(ctx, this); + permissionDialog.show(); } - /** - * Request all necessary permissions - */ - private void requestPermissions() { - // Check and request Usage Access permission - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - AppOpsManager appOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE); - int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, - android.os.Process.myUid(), getPackageName()); - if (mode != AppOpsManager.MODE_ALLOWED) { - showUsageAccessDialog(); - } - } - - // Check and request Device Admin permission - if (!DeviceAdminManager.isDeviceAdminActive(this)) { - showDeviceAdminDialog(); - } - - DbUtils.setPermissionDialogShown(true); - } - /** - * Show dialog to guide user to enable usage access - */ - private void showUsageAccessDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("📱 Usage Access Required"); - builder.setMessage("To show all your installed apps, please enable 'Usage Access' for Lunox:\n\n" + - "1. Tap 'Open Settings'\n" + - "2. Find 'Lunox Dev' in the list\n" + - "3. Toggle 'Allow usage access' ON\n" + - "4. Return to Lunox\n\n" + - "This helps Lunox detect all your apps properly."); - - builder.setIcon(android.R.drawable.ic_menu_manage); - builder.setCancelable(false); - - builder.setPositiveButton("Open Settings", (dialog, which) -> { - Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS); - startActivity(intent); - }); - - builder.setNegativeButton("Later", null); - - AlertDialog dialog = builder.create(); - dialog.show(); - } - - /** - * Show dialog to guide user to enable device admin - */ - private void showDeviceAdminDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("🔒 Device Admin Required"); - builder.setMessage("Device Admin permission enables advanced features like:\n\n" + - "• App freezing functionality\n" + - "• Enhanced app management\n" + - "• Better system integration\n\n" + - "This permission is safe and only used for launcher features."); - - builder.setIcon(android.R.drawable.ic_lock_lock); - builder.setCancelable(false); - - builder.setPositiveButton("Enable Device Admin", (dialog, which) -> { - DeviceAdminManager.requestDeviceAdminPermission(this); - }); - - builder.setNegativeButton("Skip", null); - - AlertDialog dialog = builder.create(); - dialog.show(); - } } \ No newline at end of file diff --git a/app/src/main/java/io/github/sankalp/lunox/dialogs/AppSettingsPopup.java b/app/src/main/java/io/github/sankalp/lunox/dialogs/AppSettingsPopup.java new file mode 100644 index 0000000..03a09df --- /dev/null +++ b/app/src/main/java/io/github/sankalp/lunox/dialogs/AppSettingsPopup.java @@ -0,0 +1,152 @@ +/* + * Last Launcher + * Copyright (C) 2019 Shubham Tyagi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github.sankalp.lunox.dialogs; + +import android.content.Context; +import android.graphics.Color; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.PopupWindow; +import android.widget.TextView; + +import io.github.sankalp.lunox.LauncherActivity; +import io.github.sankalp.lunox.R; +import io.github.sankalp.lunox.utils.DbUtils; +import io.github.sankalp.lunox.views.textview.AppTextView; + +/** + * App settings popup that shows options for individual apps + */ +public class AppSettingsPopup extends PopupWindow implements View.OnClickListener { + + private final LauncherActivity launcherActivity; + private final Context context; + private final String activityName; + private final AppTextView appTextView; + private TextView freezeSize; + private TextView hideApp; + private TextView resetToDefault; + private TextView uninstallApp; + + public AppSettingsPopup(Context context, String activityName, AppTextView appTextView, LauncherActivity launcherActivity) { + super(context); + this.context = context; + this.activityName = activityName; + this.appTextView = appTextView; + this.launcherActivity = launcherActivity; + + initPopup(); + } + + private void initPopup() { + LayoutInflater inflater = LayoutInflater.from(context); + View contentView = inflater.inflate(R.layout.dialog_app_settings, null); + setContentView(contentView); + + // Set popup properties + setWidth(android.view.ViewGroup.LayoutParams.WRAP_CONTENT); + setHeight(android.view.ViewGroup.LayoutParams.WRAP_CONTENT); + setFocusable(true); + setOutsideTouchable(true); + + // Set background to match the dialog style with border + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + setBackgroundDrawable(context.getResources().getDrawable(R.drawable.popup_background, null)); + } else { + setBackgroundDrawable(context.getResources().getDrawable(R.drawable.popup_background)); + } + + // Set up click listeners + contentView.findViewById(R.id.app_settings_color).setOnClickListener(this); + contentView.findViewById(R.id.app_settings_rename).setOnClickListener(this); + + freezeSize = contentView.findViewById(R.id.app_settings_freeze_size); + freezeSize.setOnClickListener(this); + + contentView.findViewById(R.id.app_settings_app_info).setOnClickListener(this); + contentView.findViewById(R.id.app_settings_reset_color).setOnClickListener(this); + + hideApp = contentView.findViewById(R.id.app_settings_hide); + hideApp.setOnClickListener(this); + + resetToDefault = contentView.findViewById(R.id.app_settings_reset_to_default); + resetToDefault.setOnClickListener(this); + resetToDefault.setTextColor(Color.parseColor("#E53935")); + + uninstallApp = contentView.findViewById(R.id.app_settings_uninstall); + uninstallApp.setOnClickListener(this); + uninstallApp.setTextColor(Color.parseColor("#E53935")); + + // Set proper text based on DB value + if (DbUtils.isAppFrozen(activityName)) { + freezeSize.setText(R.string.unfreeze_size); + } else { + freezeSize.setText(R.string.freeze_size); + } + + // Handle shortcut-specific settings + if (appTextView.isShortcut()) { + uninstallApp.setText(R.string.remove); + hideApp.setVisibility(View.GONE); + contentView.findViewById(R.id.app_settings_rename).setVisibility(View.GONE); + contentView.findViewById(R.id.app_settings_app_info).setVisibility(View.GONE); + } else { + hideApp.setTextColor(Color.parseColor("#E53935")); + } + } + + public void showAsDropDown(View anchor) { + showAsDropDown(anchor, 0, 0, Gravity.START); + } + + @Override + public void onClick(View view) { + int id = view.getId(); + if (id == R.id.app_settings_color) { + launcherActivity.changeColorSize(activityName, appTextView); + dismiss(); + } else if (id == R.id.app_settings_rename) { + launcherActivity.renameApp(activityName, appTextView.getText().toString()); + dismiss(); + } else if (id == R.id.app_settings_freeze_size) { + launcherActivity.freezeAppSize(activityName); + dismiss(); + } else if (id == R.id.app_settings_app_info) { + launcherActivity.showAppInfo(activityName); + dismiss(); + } else if (id == R.id.app_settings_reset_color) { + launcherActivity.resetAppColor(activityName); + dismiss(); + } else if (id == R.id.app_settings_hide) { + launcherActivity.hideApp(activityName); + dismiss(); + } else if (id == R.id.app_settings_reset_to_default) { + launcherActivity.resetApp(activityName); + dismiss(); + } else if (id == R.id.app_settings_uninstall) { + if (appTextView.isShortcut()) { + launcherActivity.removeShortcut(appTextView); + } else { + launcherActivity.uninstallApp(activityName); + } + dismiss(); + } + } +} diff --git a/app/src/main/java/io/github/sankalp/lunox/dialogs/PermissionDialog.java b/app/src/main/java/io/github/sankalp/lunox/dialogs/PermissionDialog.java new file mode 100644 index 0000000..0c5a1a8 --- /dev/null +++ b/app/src/main/java/io/github/sankalp/lunox/dialogs/PermissionDialog.java @@ -0,0 +1,169 @@ +/* + * Last Launcher + * Copyright (C) 2019 Shubham Tyagi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github.sankalp.lunox.dialogs; + +import android.app.AppOpsManager; +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.provider.Settings; +import android.view.View; +import android.view.Window; +import android.widget.TextView; +import android.widget.Toast; + +import io.github.sankalp.lunox.LauncherActivity; +import io.github.sankalp.lunox.R; +import io.github.sankalp.lunox.utils.DbUtils; +import io.github.sankalp.lunox.utils.DeviceAdminManager; + +public class PermissionDialog extends Dialog implements View.OnClickListener { + + private final LauncherActivity context; + private TextView usageAccessButton; + private TextView deviceAdminButton; + private TextView continueButton; + + public PermissionDialog(Context context, LauncherActivity launcherActivity) { + super(context); + this.context = launcherActivity; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_NO_TITLE); + setContentView(R.layout.dialog_permission_setup); + setCancelable(false); + + // Initialize views + usageAccessButton = findViewById(R.id.permission_usage_access); + deviceAdminButton = findViewById(R.id.permission_device_admin); + continueButton = findViewById(R.id.permission_continue); + + // Set click listeners + usageAccessButton.setOnClickListener(this); + deviceAdminButton.setOnClickListener(this); + continueButton.setOnClickListener(this); + + // Update button states + updatePermissionStates(); + } + + @Override + public void onClick(View view) { + int id = view.getId(); + + if (id == R.id.permission_usage_access) { + openUsageAccessSettings(); + } else if (id == R.id.permission_device_admin) { + enableDeviceAdmin(); + } else if (id == R.id.permission_continue) { + continueToLauncher(); + } + } + + private void openUsageAccessSettings() { + try { + Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS); + context.startActivity(intent); + Toast.makeText(context, "Please enable Usage Access for Lunox", Toast.LENGTH_LONG).show(); + } catch (Exception e) { + // Fallback to general settings if specific intent fails + Intent intent = new Intent(Settings.ACTION_SETTINGS); + context.startActivity(intent); + Toast.makeText(context, "Please find and enable Usage Access for Lunox in Settings", Toast.LENGTH_LONG).show(); + } + } + + private void enableDeviceAdmin() { + try { + DeviceAdminManager.requestDeviceAdminPermission(context); + Toast.makeText(context, "Please enable Device Admin for Lunox", Toast.LENGTH_LONG).show(); + } catch (Exception e) { + Toast.makeText(context, "Unable to open Device Admin settings", Toast.LENGTH_SHORT).show(); + } + } + + private void continueToLauncher() { + // Mark permission dialog as shown + DbUtils.setPermissionDialogShown(true); + + // Check if at least one permission is granted + boolean hasUsageAccess = checkUsageAccessPermission(); + boolean hasDeviceAdmin = DeviceAdminManager.isDeviceAdminActive(context); + + if (hasUsageAccess || hasDeviceAdmin) { + dismiss(); + context.loadApps(); // Reload apps after permissions are granted + } else { + Toast.makeText(context, "Please grant at least one permission to continue", Toast.LENGTH_LONG).show(); + } + } + + private boolean checkUsageAccessPermission() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { + AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, + android.os.Process.myUid(), context.getPackageName()); + return mode == AppOpsManager.MODE_ALLOWED; + } + return true; // For older versions, assume permission is granted + } + + private void updatePermissionStates() { + // Update Usage Access button + boolean hasUsageAccess = checkUsageAccessPermission(); + if (hasUsageAccess) { + usageAccessButton.setText("Usage Access"); + usageAccessButton.setAlpha(0.7f); + } else { + usageAccessButton.setText("Enable Usage Access"); + usageAccessButton.setAlpha(1.0f); + } + + // Update Device Admin button + boolean hasDeviceAdmin = DeviceAdminManager.isDeviceAdminActive(context); + if (hasDeviceAdmin) { + deviceAdminButton.setText("Device Admin"); + deviceAdminButton.setAlpha(0.7f); + } else { + deviceAdminButton.setText("Enable Device Admin"); + deviceAdminButton.setAlpha(1.0f); + } + } + + @Override + protected void onStart() { + super.onStart(); + // Update permission states when dialog becomes visible + updatePermissionStates(); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (hasFocus) { + // Update permission states when user returns to the dialog + updatePermissionStates(); + } + } +} diff --git a/app/src/main/java/io/github/sankalp/lunox/utils/Gestures.java b/app/src/main/java/io/github/sankalp/lunox/utils/Gestures.java index 656570e..5e7497e 100644 --- a/app/src/main/java/io/github/sankalp/lunox/utils/Gestures.java +++ b/app/src/main/java/io/github/sankalp/lunox/utils/Gestures.java @@ -79,6 +79,11 @@ public class Gestures extends GestureDetector.SimpleOnGestureListener { return true; } + @Override + public void onLongPress(MotionEvent e) { + this.listener.onLongPress(); + } + public enum Direction { SWIPE_UP, SWIPE_DOWN, SWIPE_LEFT, SWIPE_RIGHT @@ -88,6 +93,8 @@ public class Gestures extends GestureDetector.SimpleOnGestureListener { void onSwipe(Direction direction); void onDoubleTap(); + + void onLongPress(); } } \ No newline at end of file diff --git a/app/src/main/res/drawable/popup_background.xml b/app/src/main/res/drawable/popup_background.xml new file mode 100644 index 0000000..f8a3461 --- /dev/null +++ b/app/src/main/res/drawable/popup_background.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_launcher.xml b/app/src/main/res/layout/activity_launcher.xml index 2d2e0cc..c1df462 100644 --- a/app/src/main/res/layout/activity_launcher.xml +++ b/app/src/main/res/layout/activity_launcher.xml @@ -1,10 +1,12 @@ diff --git a/app/src/main/res/layout/dialog_app_settings.xml b/app/src/main/res/layout/dialog_app_settings.xml new file mode 100644 index 0000000..4561238 --- /dev/null +++ b/app/src/main/res/layout/dialog_app_settings.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_permission_setup.xml b/app/src/main/res/layout/dialog_permission_setup.xml new file mode 100644 index 0000000..92fae87 --- /dev/null +++ b/app/src/main/res/layout/dialog_permission_setup.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ca9babf..7f2cfcf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -90,12 +90,17 @@ Recently first Restart Launcher - + Lunox Device Admin Required for double-tap to lock screen functionality Enable Device Admin Device Admin is required for lock screen functionality + + Welcome to Lunox! 🚀 + To provide the best launcher experience, Lunox needs these permissions:\n\nUsage Access - Display all your apps\nDevice Admin - Enable advanced features\n\nTap each permission below to enable it. + + Freezed Apps diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png index 1306ae7..94234fe 100644 Binary files a/fastlane/metadata/android/en-US/images/icon.png and b/fastlane/metadata/android/en-US/images/icon.png differ