diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 69999da..43e74a8 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -1,17 +1,23 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index ae388c2..0897082 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,16 +4,15 @@ diff --git a/app/src/main/java/com/example/onetap_ssh/MainActivity.java b/app/src/main/java/com/example/onetap_ssh/MainActivity.java index 79ac54b..f0a4168 100644 --- a/app/src/main/java/com/example/onetap_ssh/MainActivity.java +++ b/app/src/main/java/com/example/onetap_ssh/MainActivity.java @@ -17,6 +17,10 @@ import android.view.MenuItem; import android.view.View; import android.view.Menu; import android.view.LayoutInflater; +import android.widget.CompoundButton; +import android.widget.EditText; +import android.widget.Switch; +import android.widget.Toast; import com.example.onetap_ssh.fragment.AboutFragment; import com.example.onetap_ssh.fragment.SettingsFragment; @@ -28,6 +32,7 @@ import com.example.onetap_ssh.util.ThemeUtil; import com.google.android.material.snackbar.Snackbar; import com.google.android.material.navigation.NavigationView; +import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.core.view.GravityCompat; import androidx.fragment.app.Fragment; @@ -67,19 +72,12 @@ public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + ThemeUtil.loadBackground(this); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); - setSupportActionBar(binding.appBarMain.toolbar); - binding.appBarMain.fab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show(); - } - }); - DrawerLayout drawer = findViewById(R.id.drawer_layout); + + DrawerLayout drawer = findViewById(R.id.app_background); NavigationView navigationView = binding.navView; // Passing each menu ID as a set of Ids because each // menu should be considered as top level destinations. @@ -92,7 +90,168 @@ public class MainActivity extends BaseActivity { NavigationUI.setupWithNavController(navigationView, navController); SharedPreferences p = getSharedPreferences("appsettings", Activity.MODE_PRIVATE); button_vibration = p.getBoolean("Vibration", false ); + ((Switch) navigationView.getMenu().getItem(2).getActionView().findViewById(R.id.switch_editmode)).setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (button_vibration) { + Vibrator vr = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + assert vr != null; + vr.vibrate(100); + } + + editmode = isChecked; + Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment); + NavHostFragment nhf = (NavHostFragment) currentFragment; + assert nhf != null; + Fragment childfragment = nhf.getChildFragmentManager().getFragments().get(0); + if (childfragment instanceof TabsFragment) { + try { + ((TabsFragment) childfragment).load(); + } catch (JSONException e) { + e.printStackTrace(); + } + + } + navigationView.getMenu().getItem(3).setVisible(editmode); + navigationView.getMenu().getItem(4).setVisible(editmode); + } + }); + navigationView.getMenu().getItem(3).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + if (button_vibration) { + Vibrator vr = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + assert vr != null; + vr.vibrate(100); + } + AlertDialog.Builder mBuilder = new AlertDialog.Builder(MainActivity.this); + + + LayoutInflater inflater = getLayoutInflater(); + View view = inflater.inflate(R.layout.addtabdialog, null); + EditText editText_name = view.findViewById(R.id.dialogtab_editText_name); + + + mBuilder.setView(view) + .setTitle(R.string.menu_add); + mBuilder.setPositiveButton(R.string.add, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (button_vibration) { + Vibrator vr = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + assert vr != null; + vr.vibrate(100); + } + String tabname = editText_name.getText().toString().trim(); + + SharedPreferences p = getSharedPreferences("appsettings", MODE_PRIVATE); + String tabsString = p.getString("tabs", null); + List tabs = new ArrayList(); + if (tabsString != null) { + try { + JSONArray tabsArray = new JSONArray(tabsString); + for (int i = 0; i < tabsArray.length(); i++) { + tabs.add(tabsArray.getString(i)); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + if (tabs.contains(tabname)) { + + AlertDialog mDialog = new AlertDialog.Builder(MainActivity.this) + .setTitle(getString(R.string.tabname)) + .setMessage(getString(R.string.tabname_already_exist)) + + // Specifying a listener allows you to take an action before dismissing the dialog. + // The dialog is automatically dismissed when a dialog button is clicked. + .setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (button_vibration) { + Vibrator vr = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + assert vr != null; + vr.vibrate(100); + } + } + }).create(); + Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round); + mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id + mDialog.show(); + return; + } + if (tabname.isEmpty()) { + + AlertDialog mDialog = new AlertDialog.Builder(MainActivity.this) + .setTitle(getString(R.string.tabname)) + .setMessage(getString(R.string.invalid)) + + // Specifying a listener allows you to take an action before dismissing the dialog. + // The dialog is automatically dismissed when a dialog button is clicked. + .setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (button_vibration) { + Vibrator vr = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + assert vr != null; + vr.vibrate(100); + } + } + }).create(); + Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round); + mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id + mDialog.show(); + return; + } + MenuItem item = navigationView.getMenu().add(R.id.dynamicgroup, lastID++, 3, tabname); + item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + if (button_vibration) { + Vibrator vr = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + assert vr != null; + vr.vibrate(100); + } + DrawerLayout mDrawerLayout; + mDrawerLayout = (DrawerLayout) findViewById(R.id.app_background); + mDrawerLayout.closeDrawer(GravityCompat.START); + Objects.requireNonNull(getSupportActionBar()).setTitle(tabname); + Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment); + NavHostFragment nhf = (NavHostFragment) currentFragment; + assert nhf != null; + nhf.getChildFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new TabsFragment(tabname)).commit(); + return true; + } + }); + tabitems.put(tabname, item); + + + tabs.add(tabname); + SharedPreferences.Editor editor = p.edit(); + editor.putString("tabs", new JSONArray(tabs).toString()); + editor.apply(); + + } + }); + mBuilder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (button_vibration) { + Vibrator vr = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + assert vr != null; + vr.vibrate(100); + } + + } + }); + AlertDialog mDialog = mBuilder.create(); + Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round); + mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id + mDialog.show(); + return true; + } + }); //launchApp(); navigationView.getMenu().getItem(4).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @@ -193,7 +352,7 @@ public class MainActivity extends BaseActivity { vr.vibrate(100); } DrawerLayout mDrawerLayout; - mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); + mDrawerLayout = (DrawerLayout) findViewById(R.id.app_background); mDrawerLayout.closeDrawer(GravityCompat.START); Objects.requireNonNull(getSupportActionBar()).setTitle(tab); Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment); @@ -221,6 +380,7 @@ public class MainActivity extends BaseActivity { return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp(); } + public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long @@ -350,4 +510,9 @@ public class MainActivity extends BaseActivity { super.recreate(); } + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/onetap_ssh/MovableFloatingActionButton.java b/app/src/main/java/com/example/onetap_ssh/MovableFloatingActionButton.java new file mode 100644 index 0000000..465563e --- /dev/null +++ b/app/src/main/java/com/example/onetap_ssh/MovableFloatingActionButton.java @@ -0,0 +1,129 @@ +package com.example.onetap_ssh; + + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.OvershootInterpolator; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; + +public class MovableFloatingActionButton extends FloatingActionButton implements View.OnTouchListener { + CustomClickListener customClickListener; + + private final static float CLICK_DRAG_TOLERANCE = 10; // Often, there will be a slight, unintentional, drag when the user taps the FAB, so we need to account for this. + + private float downRawX, downRawY; + private float dX, dY; + + int viewWidth; + int viewHeight; + + int parentWidth; + int parentHeight; + + float newX; + float newY; + + public MovableFloatingActionButton(Context context) { + super(context); + init(); + } + + public MovableFloatingActionButton(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public MovableFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private void init() { + setOnTouchListener(this); + } + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + + ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams(); + + int action = motionEvent.getAction(); + if (action == MotionEvent.ACTION_DOWN) { + + downRawX = motionEvent.getRawX(); + downRawY = motionEvent.getRawY(); + dX = view.getX() - downRawX; + dY = view.getY() - downRawY; + + return false; // not Consumed for ripple effect + + } else if (action == MotionEvent.ACTION_MOVE) { + + viewWidth = view.getWidth(); + viewHeight = view.getHeight(); + + View viewParent = (View) view.getParent(); + parentWidth = viewParent.getWidth(); + parentHeight = viewParent.getHeight(); + + newX = motionEvent.getRawX() + dX; + newX = Math.max(layoutParams.leftMargin, newX); // Don't allow the FAB past the left hand side of the parent + newX = Math.min(parentWidth - viewWidth - layoutParams.rightMargin, newX); // Don't allow the FAB past the right hand side of the parent + + newY = motionEvent.getRawY() + dY; + newY = Math.max(layoutParams.topMargin, newY); // Don't allow the FAB past the top of the parent + newY = Math.min(parentHeight - viewHeight - layoutParams.bottomMargin, newY); // Don't allow the FAB past the bottom of the parent + + view.animate() + .x(newX) + .y(newY) + .setDuration(0) + .start(); + + return true; // Consumed + + } else if (action == MotionEvent.ACTION_UP) { + + float upRawX = motionEvent.getRawX(); + float upRawY = motionEvent.getRawY(); + + float upDX = upRawX - downRawX; + float upDY = upRawY - downRawY; + + if (newX > ((parentWidth - viewWidth - layoutParams.rightMargin) / 2)) { + newX = parentWidth - viewWidth - layoutParams.rightMargin; + } else { + newX = layoutParams.leftMargin; + } + + view.animate() + .x(newX) + .y(newY) + .setInterpolator(new OvershootInterpolator()) + .setDuration(600) + .start(); + + if (Math.abs(upDX) < CLICK_DRAG_TOLERANCE && Math.abs(upDY) < CLICK_DRAG_TOLERANCE) { // A click + if (customClickListener != null) { + customClickListener.onClick(view); + } + return false;// not Consumed for ripple effect + } else { // A drag + return false; // not Consumed for ripple effect + } + + } else { + return super.onTouchEvent(motionEvent); + } + + } + + public interface CustomClickListener { + void onClick(View view); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/onetap_ssh/ui/home/HomeFragment.java b/app/src/main/java/com/example/onetap_ssh/ui/home/HomeFragment.java index b8a324c..c77c9c0 100644 --- a/app/src/main/java/com/example/onetap_ssh/ui/home/HomeFragment.java +++ b/app/src/main/java/com/example/onetap_ssh/ui/home/HomeFragment.java @@ -66,12 +66,7 @@ public class HomeFragment extends Fragment { View root = inflater.inflate(R.layout.fragment_home, container, false); SharedPreferences p = requireContext().getSharedPreferences("appsettings", Activity.MODE_PRIVATE); String Background = p.getString("Background", null); - if (Background != null) { - ImageView I = root.findViewById(R.id.Background); - byte[] BA = Base64.decode(Background, Base64.DEFAULT); - I.setImageDrawable(new BitmapDrawable(getResources(), MainActivity.scaleCenterCrop(BitmapFactory.decodeByteArray(BA, 0, BA.length), MainActivity.getScreenHeight(), MainActivity.getScreenWidth()))); - I.setScaleType(ImageView.ScaleType.CENTER_CROP); - } + final TextView textView = root.findViewById(R.id.text_home); final TextView login_data = root.findViewById(R.id.login_data); if (user == null || ip == null) { diff --git a/app/src/main/java/com/example/onetap_ssh/ui/tabs/TabsFragment.java b/app/src/main/java/com/example/onetap_ssh/ui/tabs/TabsFragment.java index 62661a7..ff30b19 100644 --- a/app/src/main/java/com/example/onetap_ssh/ui/tabs/TabsFragment.java +++ b/app/src/main/java/com/example/onetap_ssh/ui/tabs/TabsFragment.java @@ -66,12 +66,7 @@ public class TabsFragment extends Fragment implements AddButtonDialogSingle.AddB View root = inflater.inflate(R.layout.fragment_tabs, container, false); SharedPreferences p = requireContext().getSharedPreferences("appsettings", Activity.MODE_PRIVATE); String Background = p.getString("Background", null); - if (Background != null) { - ImageView I = root.findViewById(R.id.Background); - byte[] BA = Base64.decode(Background, Base64.DEFAULT); - I.setImageDrawable(new BitmapDrawable(getResources(), MainActivity.scaleCenterCrop(BitmapFactory.decodeByteArray(BA, 0, BA.length), MainActivity.getScreenHeight(), MainActivity.getScreenWidth()))); - I.setScaleType(ImageView.ScaleType.CENTER_CROP); - } + listView = root.findViewById(R.id.listView); diff --git a/app/src/main/res/drawable/onetap_ssh.png b/app/src/main/res/drawable/onetap_ssh.png new file mode 100644 index 0000000..720903d Binary files /dev/null and b/app/src/main/res/drawable/onetap_ssh.png differ diff --git a/app/src/main/res/drawable/sidemenu.xml b/app/src/main/res/drawable/sidemenu.xml new file mode 100644 index 0000000..de8bbf2 --- /dev/null +++ b/app/src/main/res/drawable/sidemenu.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 76c7a47..0792bff 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,7 +5,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" - android:id="@+id/drawer_layout" + + android:id="@+id/app_background" tools:openDrawer="start"> + app:menu="@menu/activity_main_drawer" + android:background="@drawable/sidemenu"/> \ No newline at end of file diff --git a/app/src/main/res/layout/app_bar_main.xml b/app/src/main/res/layout/app_bar_main.xml index 1900dbe..f405a07 100644 --- a/app/src/main/res/layout/app_bar_main.xml +++ b/app/src/main/res/layout/app_bar_main.xml @@ -20,13 +20,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/doublebutton.xml b/app/src/main/res/layout/doublebutton.xml index ce932f8..87c6829 100644 --- a/app/src/main/res/layout/doublebutton.xml +++ b/app/src/main/res/layout/doublebutton.xml @@ -8,7 +8,7 @@ android:orientation="horizontal"> -