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">
-
-
-