zusammenkopiert aus Teraplex und CodeGuard

This commit is contained in:
JG-Cody 2024-02-24 19:59:28 +01:00
parent 3d74d80b7a
commit c634995e41
54 changed files with 2844 additions and 30 deletions

View File

@ -7,11 +7,11 @@
<deviceKey> <deviceKey>
<Key> <Key>
<type value="VIRTUAL_DEVICE_PATH" /> <type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\Cody\.android\avd\for_Website.avd" /> <value value="C:\Users\Cody\.android\avd\Pixel_C_API_33.avd" />
</Key> </Key>
</deviceKey> </deviceKey>
</Target> </Target>
</targetSelectedWithDropDown> </targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-02-23T16:37:40.934381500Z" /> <timeTargetWasSelectedWithDropDown value="2024-02-24T17:39:55.956737900Z" />
</component> </component>
</project> </project>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">

View File

@ -46,6 +46,7 @@ dependencies {
implementation 'org.bouncycastle:bcprov-jdk15on:1.70' implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
implementation 'com.caverock:androidsvg-aar:1.4' implementation 'com.caverock:androidsvg-aar:1.4'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
implementation 'com.jcraft:jsch:0.1.55'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
} }

View File

@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.VIBRATE" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"

View File

@ -0,0 +1,103 @@
package com.example.onetap_ssh;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import androidx.fragment.app.DialogFragment;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import com.example.onetap_ssh.ui.tabs.TabsFragment;
public class AddButtonDialogSingle extends DialogFragment {
private EditText editText_command, editText_name, editText_button_name;
private AddButtonDialogListenerSingle listener;
private TabsFragment frag;
/**
*
* @param savedInstanceState
* @return
*/
@NotNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = requireActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.addbuttondialog_single, null);
editText_command = view.findViewById(R.id.dialogSingle_editText_command);
editText_name = view.findViewById(R.id.dialogheadline_editText_name);
editText_button_name = view.findViewById(R.id.dialogSingle_editText_buttonName);
builder.setView(view)
.setTitle("SINGLE BUTTON")
.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton(R.string.add, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String command = editText_command.getText().toString();
String name = editText_name.getText().toString();
String button = editText_button_name.getText().toString();
if(command.isEmpty()||button.isEmpty()||name.isEmpty()){
AlertDialog mDialog = new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.invalid))
.setMessage(getString(R.string.inputfields_cant_be_empty))
// 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(android.R.string.yes, null )
.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
return;
}
listener.applyTextsSingle(name,command,button);
}
});
AlertDialog mDialog = builder.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
return mDialog;
}
public void setFragment(TabsFragment frag)
{
this.frag = frag;
}
@Override
public void onAttach(@NotNull Context context) {
super.onAttach(context);
try {
listener = (AddButtonDialogListenerSingle) frag;
} catch (ClassCastException e) {
throw new ClassCastException(frag.toString() +
"must implement ExampleDialogListener");
}
}
public interface AddButtonDialogListenerSingle {
void applyTextsSingle(String name, String command, String button);
}
}

View File

@ -0,0 +1,96 @@
package com.example.onetap_ssh;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import androidx.fragment.app.DialogFragment;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import com.example.onetap_ssh.ui.tabs.TabsFragment;
public class AddButtonsDialogDouble extends DialogFragment {
private AddButtonsDialogListenerDouble listener;
private EditText editText_name, editText_command1, editText_button1, editText_command2, editText_button2;
private TabsFragment frag;
@NotNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = requireActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.addbuttonsdialog_double, null);
builder.setView(view)
.setTitle("ON/OFF BUTTON")
.setNegativeButton(getString(R.string.cancel), null)
.setPositiveButton(R.string.add, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String command1 = editText_command1.getText().toString();
String command2 = editText_command2.getText().toString();
String name = editText_name.getText().toString();
String button1 = editText_button1.getText().toString();
String button2 = editText_button2.getText().toString();
if(command1.isEmpty()||command2.isEmpty()||name.isEmpty()||button1.isEmpty()||button2.isEmpty()){
AlertDialog mDialog = new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.invalid))
.setMessage(getString(R.string.inputfields_cant_be_empty))
// 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(android.R.string.yes, null )
.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
return;
}
listener.applyTextsDouble(name,command1,command2,button1,button2);
}
});
editText_name = view.findViewById(R.id.dialogDouble_editText_name);
editText_command1 = view.findViewById(R.id.dialogDouble_editText_command1);
editText_command2 = view.findViewById(R.id.dialogDouble_editText_command2);
editText_button1 = view.findViewById(R.id.dialogDouble_editText_button1);
editText_button2 = view.findViewById(R.id.dialogDouble_editText_button2);
AlertDialog mDialog = builder.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
return mDialog;
}
public void setFragment(TabsFragment frag) {
this.frag = frag;
}
@Override
public void onAttach(@NotNull Context context) {
super.onAttach(context);
try {
listener = (AddButtonsDialogListenerDouble) frag;
} catch (ClassCastException ignored) {
}
}
public interface AddButtonsDialogListenerDouble {
void applyTextsDouble(String name, String command1, String command2, String button1, String button2);
}
}

View File

@ -0,0 +1,92 @@
package com.example.onetap_ssh;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import androidx.fragment.app.DialogFragment;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import com.example.onetap_ssh.ui.tabs.TabsFragment;
public class AddHeadlineDialog extends DialogFragment {
private AddHeadlineDialogListener listener;
private EditText editText_name;
private TabsFragment frag;
/**
*
* @param savedInstanceState
* @return
*/
@NotNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = requireActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.addheadlinedialog, null);
editText_name = view.findViewById(R.id.dialogheadline_editText_name);
builder.setView(view)
.setTitle(R.string.heading)
.setNegativeButton(R.string.cancel, (dialogInterface, i) -> {
})
.setPositiveButton(R.string.add, (dialogInterface, i) -> {
String headline = editText_name.getText().toString();
if(headline.isEmpty()){
AlertDialog mDialog = new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.invalid))
.setMessage(getString(R.string.inputfields_cant_be_empty))
// 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(android.R.string.yes, null )
.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
return;
}
listener.applyTextsHeadline(headline);
});
AlertDialog mDialog = builder.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
return mDialog;
}
public void setFragment(TabsFragment frag)
{
this.frag = frag;
}
@Override
public void onAttach(@NotNull Context context) {
super.onAttach(context);
try {
listener = (AddHeadlineDialogListener) frag;
} catch (ClassCastException e) {
throw new ClassCastException(frag.toString() +
"must implement ExampleDialogListener");
}
}
public interface AddHeadlineDialogListener {
void applyTextsHeadline(String headline);
}
}

View File

@ -1,9 +1,13 @@
package com.example.onetap_ssh; package com.example.onetap_ssh;
import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast; import android.widget.Toast;
@ -13,6 +17,8 @@ import com.example.onetap_ssh.util.SettingsUtil;
public class IntroActivity extends BaseActivity { public class IntroActivity extends BaseActivity {
public static boolean show_logoanimation = false;
private ActivityIntroBinding binding; private ActivityIntroBinding binding;
private MediaPlayer mMediaPlayer; private MediaPlayer mMediaPlayer;
@ -46,6 +52,26 @@ public class IntroActivity extends BaseActivity {
}); });
setContentView(binding.getRoot()); setContentView(binding.getRoot());
SharedPreferences p = getSharedPreferences("appsettings", Activity.MODE_PRIVATE);
show_logoanimation = p.getBoolean("Logoanimation", true);
if (show_logoanimation) {
setContentView(R.layout.activity_intro);
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
//Do something after 4000ms
Intent m = new Intent(getApplicationContext(), MainActivity.class);
m.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(m);
}
}, 4000);
} else {
Intent m = new Intent(getApplicationContext(), MainActivity.class);
m.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(m);
}
} }
public void openMainActivity() { public void openMainActivity() {

View File

@ -1,12 +1,24 @@
package com.example.onetap_ssh; package com.example.onetap_ssh;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.os.Bundle; import android.os.Bundle;
import android.os.Vibrator;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.Menu; import android.view.Menu;
import android.view.LayoutInflater;
import com.example.onetap_ssh.fragment.AboutFragment; import com.example.onetap_ssh.fragment.AboutFragment;
import com.example.onetap_ssh.fragment.SettingsFragment; import com.example.onetap_ssh.fragment.SettingsFragment;
import com.example.onetap_ssh.ui.tabs.TabsFragment;
import com.example.onetap_ssh.util.DialogUtil; import com.example.onetap_ssh.util.DialogUtil;
import com.example.onetap_ssh.util.NavigationUtil; import com.example.onetap_ssh.util.NavigationUtil;
import com.example.onetap_ssh.util.SettingsUtil; import com.example.onetap_ssh.util.SettingsUtil;
@ -15,16 +27,27 @@ import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView; import com.google.android.material.navigation.NavigationView;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.core.view.GravityCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI; import androidx.navigation.ui.NavigationUI;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;
import com.example.onetap_ssh.databinding.ActivityMainBinding; import com.example.onetap_ssh.databinding.ActivityMainBinding;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
@ -33,9 +56,13 @@ public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding; private ActivityMainBinding binding;
private boolean fullyLaunched; private boolean fullyLaunched;
public static boolean button_vibration = false;
private boolean lockOnStop = true; private boolean lockOnStop = true;
public static boolean editmode = false;
int lastID = 6969;
Map<String, MenuItem> tabitems = new HashMap<>();
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -51,7 +78,7 @@ public class MainActivity extends AppCompatActivity {
.setAction("Action", null).show(); .setAction("Action", null).show();
} }
}); });
DrawerLayout drawer = binding.appBackground; DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = binding.navView; NavigationView navigationView = binding.navView;
// Passing each menu ID as a set of Ids because each // Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations. // menu should be considered as top level destinations.
@ -59,13 +86,127 @@ public class MainActivity extends AppCompatActivity {
R.id.nav_home, R.id.nav_settings, R.id.nav_about) R.id.nav_home, R.id.nav_settings, R.id.nav_about)
.setOpenableLayout(drawer) .setOpenableLayout(drawer)
.build(); .build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration); NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController); NavigationUI.setupWithNavController(navigationView, navController);
SharedPreferences p = getSharedPreferences("appsettings", Activity.MODE_PRIVATE);
button_vibration = p.getBoolean("Vibration", false );
IntroActivity.show_logoanimation = p.getBoolean("Logoanimation", true );
launchApp(); launchApp();
navigationView.getMenu().getItem(4).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);
}
SharedPreferences p = getSharedPreferences("appsettings", MODE_PRIVATE);
String tabsString = p.getString("tabs", null);
List<String> tabs = new ArrayList<String>();
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();
}
}
List<String> selectedTabs = new ArrayList<>();
String[] tabsarray = tabs.toArray(new String[0]);
AlertDialog.Builder mBuilder = new AlertDialog.Builder(MainActivity.this);
mBuilder.setTitle(R.string.menu_remove);
mBuilder.setMultiChoiceItems(tabsarray, null, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i, boolean isChecked) {
String selectedItem = tabsarray[i];
if (isChecked) {
selectedTabs.add(selectedItem);
} else {
selectedTabs.remove(selectedItem);
}
}
});
mBuilder.setPositiveButton(getString(R.string.remove), 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);
}
tabs.removeAll(selectedTabs);
SharedPreferences.Editor editor = p.edit();
editor.putString("tabs", new JSONArray(tabs).toString());
for (String tab : selectedTabs) {
editor.remove("listItems." + tab);
editor.apply();
navigationView.getMenu().removeItem(tabitems.get(tab).getItemId());
tabitems.remove(tab);
dialogInterface.dismiss();
}
}
});
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;
}
});
String tabsString = p.getString("tabs", null);
List<String> 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();
}
}
for (String tab : tabs) {
MenuItem item = navigationView.getMenu().add(R.id.dynamicgroup, lastID++, 3, tab);
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.drawer_layout);
mDrawerLayout.closeDrawer(GravityCompat.START);
Objects.requireNonNull(getSupportActionBar()).setTitle(tab);
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(tab)).commit();
return true;
}
});
tabitems.put(tab, item);
}
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present. // Inflate the menu; this adds items to the action bar if it is present.
@ -75,7 +216,7 @@ public class MainActivity extends AppCompatActivity {
@Override @Override
public boolean onSupportNavigateUp() { public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main); NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration) return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp(); || super.onSupportNavigateUp();
} }
@ -119,4 +260,37 @@ public class MainActivity extends AppCompatActivity {
Fragment fragment = NavigationUtil.getCurrentFragment(this); Fragment fragment = NavigationUtil.getCurrentFragment(this);
} }
public static Bitmap scaleCenterCrop(Bitmap source, int newHeight,
int newWidth) {
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
float xScale = (float) newWidth / sourceWidth;
float yScale = (float) newHeight / sourceHeight;
float scale = Math.max(xScale, yScale);
// Now get the size of the source bitmap when scaled
float scaledWidth = scale * sourceWidth;
float scaledHeight = scale * sourceHeight;
float left = (newWidth - scaledWidth) / 2;
float top = (newHeight - scaledHeight) / 2;
RectF targetRect = new RectF(left, top, left + scaledWidth, top
+ scaledHeight);//from ww w .j a va 2s. co m
Bitmap dest = Bitmap.createBitmap(newWidth, newHeight,
source.getConfig());
Canvas canvas = new Canvas(dest);
canvas.drawBitmap(source, null, targetRect, null);
return dest;
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
} }

View File

@ -0,0 +1,58 @@
package com.example.onetap_ssh;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.InputStream;
public class SSH_connection {
public static void executeRemoteCommand(String ip, String user, String password, String command) throws Exception {
new Thread(() -> {
String command1 = command;
try {
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
JSch jsch = new JSch();
Session session = jsch.getSession(user, ip, 22);
session.setPassword(password);
session.setConfig(config);
session.connect();
System.out.println("Connected");
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command1);
channel.setInputStream(null);
((ChannelExec) channel).setErrStream(System.err);
InputStream in = channel.getInputStream();
channel.connect();
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0) break;
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
System.out.println("exit-status: " + channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ignored) {
}
}
channel.disconnect();
session.disconnect();
System.out.println("DONE");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}

View File

@ -1,37 +1,372 @@
package com.example.onetap_ssh.ui.home; package com.example.onetap_ssh.ui.home;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.Vibrator;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.util.Base64;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.example.onetap_ssh.databinding.FragmentHomeBinding; import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.util.Objects;
import com.example.onetap_ssh.MainActivity;
import com.example.onetap_ssh.R;
import com.example.onetap_ssh.SSH_connection;
import com.example.onetap_ssh.ui.terminal.Terminal;
public class HomeFragment extends Fragment { public class HomeFragment extends Fragment {
private FragmentHomeBinding binding; public static String user, password, ip;
public static EditText ipInput;
public static EditText userInput;
public static EditText passwordInput;
boolean isPasswordVisible = false;
Button reboot_Button;
Button shutdown_Button;
Button loginButton;
Button logoutButton;
ImageView togglepassword;
ImageView backgroundoverlay_bottom;
@SuppressLint("ClickableViewAccessibility")
public View onCreateView(@NonNull LayoutInflater inflater, public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) { ViewGroup container, Bundle savedInstanceState) {
HomeViewModel homeViewModel = SharedPreferences prefs = requireContext().getSharedPreferences("appsettings", Context.MODE_PRIVATE);
new ViewModelProvider(this).get(HomeViewModel.class); user = prefs.getString("user", null);
password = prefs.getString("password", null);
ip = prefs.getString("ip", null);
binding = FragmentHomeBinding.inflate(inflater, container, false); View root = inflater.inflate(R.layout.fragment_home, container, false);
View root = binding.getRoot(); 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) {
login_data.setText(R.string.please_login);
} else {
login_data.setText(getString(R.string.sie_sind_als_angemeldet).replace("{IP}", ip).replace("{USERNAME}", user));
}
userInput = (EditText) root.findViewById(R.id.loginuserInput);
passwordInput = (EditText) root.findViewById(R.id.loginpasswordInput);
ipInput = (EditText) root.findViewById(R.id.ipInput);
loginButton = (Button) root.findViewById(R.id.loginButton);
reboot_Button = (Button) root.findViewById(R.id.reboot);
shutdown_Button = (Button) root.findViewById(R.id.shutdown);
togglepassword = (ImageView) root.findViewById(R.id.togglepassword);
SharedPreferences t = requireContext().getSharedPreferences("appsettings", Context.MODE_PRIVATE);
if (user == null || ip == null) {
loginButton.setVisibility(View.VISIBLE);
togglepassword.setVisibility(View.VISIBLE);
reboot_Button.setVisibility(View.GONE);
shutdown_Button.setVisibility(View.GONE);
} else {
loginButton.setVisibility(View.INVISIBLE);
togglepassword.setVisibility(View.INVISIBLE);
ipInput.setVisibility(View.GONE);
userInput.setVisibility(View.GONE);
passwordInput.setVisibility(View.GONE);
reboot_Button.setVisibility(View.VISIBLE);
shutdown_Button.setVisibility(View.VISIBLE);
}
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().getSystemService(Context.VIBRATOR_SERVICE);
assert vr != null;
vr.vibrate(100);
}
if (userInput.getText().toString().trim().length() == 0 || ipInput.getText().toString().trim().length() == 0 || passwordInput.getText().toString().trim().length() == 0) {
AlertDialog mDialog = new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.invalid))
.setMessage(getString(R.string.inputfields_cant_be_empty))
// 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 (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().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();
} else {
user = userInput.getText().toString();
password = passwordInput.getText().toString();
ip = ipInput.getText().toString();
new Thread(new Runnable() {
@Override
public void run() {
try {
JSch jsch = new JSch();
Session session;
session = jsch.getSession(user, ip, 22);
session.setPassword(password);
session.setUserInfo(new Terminal.MyUserInfo() {
@Override
public String getPassword() {
return super.getPassword();
}
});
session.setConfig("StrictHostKeyChecking", "no");
System.out.println("CONNECT");
session.connect(30000);
Channel channel = session.openChannel("shell");
channel.connect(3 * 1000);
session.disconnect();
System.out.println("DISCONNECT");
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getContext(), R.string.connecting, Toast.LENGTH_SHORT).show();
SharedPreferences p = requireContext().getSharedPreferences("appsettings", Context.MODE_PRIVATE);
p.edit().putString("user", user).putString("password", password).putString("ip", ip).apply();
if (user == null || ip == null) {
login_data.setText("");
reboot_Button.setVisibility(View.GONE);
shutdown_Button.setVisibility(View.GONE);
backgroundoverlay_bottom.setVisibility(View.INVISIBLE);
} else {
login_data.setText(getString(R.string.sie_sind_als_angemeldet).replace("{IP}", ip).replace("{USERNAME}", user));
logoutButton.setVisibility(View.VISIBLE);
loginButton.setVisibility(View.INVISIBLE);
togglepassword.setVisibility(View.INVISIBLE);
ipInput.setVisibility(View.GONE);
userInput.setVisibility(View.GONE);
passwordInput.setVisibility(View.GONE);
reboot_Button.setVisibility(View.VISIBLE);
shutdown_Button.setVisibility(View.VISIBLE);
backgroundoverlay_bottom.setVisibility(View.VISIBLE);
}
}
});
} catch (Exception e) {
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
e.printStackTrace();
AlertDialog mDialog = new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.unable_to_connect))
.setMessage(getString(R.string.try_again))
// 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 (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().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();
}
});
}
}
}).start();
}
}
});
logoutButton = (Button) root.findViewById(R.id.logoutButton);
if (user == null || ip == null) {
logoutButton.setVisibility(View.INVISIBLE);
ipInput.setVisibility(View.VISIBLE);
userInput.setVisibility(View.VISIBLE);
passwordInput.setVisibility(View.VISIBLE);
reboot_Button.setVisibility(View.GONE);
shutdown_Button.setVisibility(View.GONE);
backgroundoverlay_bottom.setVisibility(View.INVISIBLE);
} else {
logoutButton.setVisibility(View.VISIBLE);
reboot_Button.setVisibility(View.VISIBLE);
shutdown_Button.setVisibility(View.VISIBLE);
backgroundoverlay_bottom.setVisibility(View.VISIBLE);
}
logoutButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().getSystemService(Context.VIBRATOR_SERVICE);
assert vr != null;
vr.vibrate(100);
}
requireContext().getSharedPreferences("appsettings", Context.MODE_PRIVATE).edit().remove("ip").remove("user").remove("password").apply();
startActivity(requireActivity().getIntent());
requireActivity().finish();
}
});
reboot_Button = (Button) root.findViewById(R.id.reboot);
reboot_Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().getSystemService(Context.VIBRATOR_SERVICE);
assert vr != null;
vr.vibrate(100);
}
AlertDialog mDialog = new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.restart_server))
.setMessage(getString(R.string.are_you_sure))
// 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.yes), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().getSystemService(Context.VIBRATOR_SERVICE);
assert vr != null;
vr.vibrate(100);
}
try {
Toast.makeText(getContext(), R.string.rebooting, Toast.LENGTH_SHORT).show();
SSH_connection.executeRemoteCommand(ip, user, password, "reboot");
} catch (Exception ignored) {
}
// Continue with delete operation
}
})
// A null listener allows the button to dismiss the dialog and take no further action.
.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().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();
}
});
shutdown_Button = (Button) root.findViewById(R.id.shutdown);
shutdown_Button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().getSystemService(Context.VIBRATOR_SERVICE);
assert vr != null;
vr.vibrate(100);
}
AlertDialog mDialog = new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.shutdown_server))
.setMessage(getString(R.string.are_you_sure))
// 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(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().getSystemService(Context.VIBRATOR_SERVICE);
assert vr != null;
vr.vibrate(100);
}
try {
Toast.makeText(getContext(), R.string.shutting_down, Toast.LENGTH_SHORT).show();
SSH_connection.executeRemoteCommand(ip, user, password, "shutdown now");
} catch (Exception ignored) {
}
// Continue with delete operation
}
})
// A null listener allows the button to dismiss the dialog and take no further action.
.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().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();
}
});
if (togglepassword.getVisibility() == View.VISIBLE) {
togglepassword.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (isPasswordVisible) {
passwordInput.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
isPasswordVisible = false;
} else {
passwordInput.setTransformationMethod(PasswordTransformationMethod.getInstance());
isPasswordVisible = true;
}
return false;
}
});
}
final TextView textView = binding.textHome;
homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
return root; return root;
} }
@Override }
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

View File

@ -0,0 +1,37 @@
package com.example.onetap_ssh.ui.tabs;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Vibrator;
import android.view.View;
import com.example.onetap_ssh.MainActivity;
import com.example.onetap_ssh.SSH_connection;
public class CommandExecutor implements View.OnClickListener {
private final String command;
public CommandExecutor(String command) {
this.command = command;
}
@Override
public void onClick(View v) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) v.getContext().getSystemService(Context.VIBRATOR_SERVICE);
assert vr != null;
vr.vibrate(100);
}
SharedPreferences prefs = v.getContext().getSharedPreferences("appsettings", Context.MODE_PRIVATE);
String user = prefs.getString("user", null);
String password = prefs.getString("password", null);
String ip = prefs.getString("ip", null);
if (user == null||ip == null||password == null){
return;
}
try {
SSH_connection.executeRemoteCommand(ip, user, password, command);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,9 @@
package com.example.onetap_ssh.ui.tabs;
import android.view.View;
public interface IViewHolder {
abstract public String getCommand();
abstract public View[] getViews();
}

View File

@ -0,0 +1,396 @@
package com.example.onetap_ssh.ui.tabs;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;
import com.example.onetap_ssh.AddButtonsDialogDouble;
import com.example.onetap_ssh.MainActivity;
import com.example.onetap_ssh.R;
public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ListItemViewHolder> {
private AddButtonsDialogDouble.AddButtonsDialogListenerDouble listener;
private EditText editText_name, editText_command, editText_command1, editText_button1, editText_command2, editText_button2, editText_button_name;
private TabsFragment frag;
public static final int
SINGLEBUTTON = 0,
DOUBLEBUTTON = 1,
HEADLINE = 2,
SPACE = 3;
private final LayoutInflater inflater;
private final String tabname;
private final ArrayList<ListItem> objects;
private final Context context;
public ListAdapter(Context context, ArrayList<ListItem> objects, String tabname) {
this.inflater = LayoutInflater.from(context);
this.tabname = tabname;
this.objects = objects;
this.context = context;
}
@NonNull
@NotNull
@Override
public ListItemViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
return new ListItemViewHolder(createView(viewType, parent));
}
@Override
public void onBindViewHolder(@NonNull @NotNull ListItemViewHolder holder, int position) {
bindView(holder.getItemView(), objects.get(position));
}
public int getItemViewType(int position) {
return objects.get(position).getType();
}
@Override
public int getItemCount() {
return objects.size();
}
public void add(ListItem item) {
objects.add(item);
notifyDataSetChanged();
}
public void remove(ListItem item) {
int position = objects.indexOf(item);
objects.remove(item);
notifyItemRemoved(position);
}
public void remove(int position) {
objects.remove(position);
notifyItemRemoved(position);
}
public void swap(int idx1, int idx2) {
Collections.swap(objects, idx1, idx2);
notifyItemMoved(idx1, idx2);
}
public void clear() {
objects.clear();
notifyDataSetChanged();
}
public ArrayList<ListItem> getObjects() {
return objects;
}
public View createView(int listViewItemType, ViewGroup parent) {
switch(listViewItemType) {
case SINGLEBUTTON:
{
return inflater.inflate(R.layout.singlebutton, parent, false);
}
case DOUBLEBUTTON:
{
return inflater.inflate(R.layout.doublebutton, parent, false);
}
case SPACE:
{
return inflater.inflate(R.layout.space, parent, false);
}
case HEADLINE:
{
return inflater.inflate(R.layout.headline, parent, false);
}
}
return null;
}
public void bindView(View view, ListItem item) {
String[] strings = item.getStrings();
ImageView Remove = view.findViewById(R.id.image_remove);
ImageView Edit = view.findViewById(R.id.image_edit);
if (MainActivity.editmode) {
Remove.setVisibility(View.VISIBLE);
Edit.setVisibility(View.VISIBLE);
}
else {
Remove.setVisibility(View.GONE);
Edit.setVisibility(View.GONE);
}
Remove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
remove(item);
try {
TabsFragment.save(tabname, context, ListAdapter.this);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Edit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (item.getType()) {
case SINGLEBUTTON: {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(v.getContext());
View view = inflater.inflate(R.layout.addbuttondialog_single, null);
editText_command = view.findViewById(R.id.dialogSingle_editText_command);
editText_command.setText(strings[1]);
editText_name = view.findViewById(R.id.dialogheadline_editText_name);
editText_name.setText(strings[0]);
editText_button_name = view.findViewById(R.id.dialogSingle_editText_buttonName);
editText_button_name.setText(strings[2]);
mBuilder.setView(view)
.setTitle("SINGLE BUTTON")
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton(R.string.add, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String command = editText_command.getText().toString();
String name = editText_name.getText().toString();
String button = editText_button_name.getText().toString();
if(command.isEmpty()||button.isEmpty()||name.isEmpty()){
AlertDialog mDialog = new AlertDialog.Builder(v.getContext())
.setTitle(R.string.invalid)
.setMessage(R.string.inputfields_cant_be_empty)
// 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(android.R.string.yes, null )
.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
return;
}
ListItemSingle item_tmp = (ListItemSingle) item;
item_tmp.setButtonName(button);
item_tmp.setCommand(command);
item_tmp.setName(name);
notifyDataSetChanged();
try {
TabsFragment.save(tabname, context, ListAdapter.this);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
AlertDialog mDialog = mBuilder.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
break;
}
case DOUBLEBUTTON: {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(v.getContext());
View view = inflater.inflate(R.layout.addbuttonsdialog_double, null);
mBuilder.setView(view)
.setTitle("ON/OFF BUTTON")
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.add, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String command1 = editText_command1.getText().toString();
String command2 = editText_command2.getText().toString();
String name = editText_name.getText().toString();
String button1 = editText_button1.getText().toString();
String button2 = editText_button2.getText().toString();
if (command1.isEmpty() || command2.isEmpty() || name.isEmpty() || button1.isEmpty() || button2.isEmpty()) {
AlertDialog mDialog = new AlertDialog.Builder(v.getContext())
.setTitle(R.string.invalid)
.setMessage(R.string.inputfields_cant_be_empty)
// 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(android.R.string.yes, null)
.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
return;
}
ListItemDouble item_tmp = (ListItemDouble) item;
item_tmp.setButton1(button1);
item_tmp.setButton2(button2);
item_tmp.setCommand1(command1);
item_tmp.setCommand2(command2);
item_tmp.setName(name);
notifyDataSetChanged();
try {
TabsFragment.save(tabname, context, ListAdapter.this);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
editText_name = view.findViewById(R.id.dialogDouble_editText_name);
editText_name.setText(strings[0]);
editText_command1 = view.findViewById(R.id.dialogDouble_editText_command1);
editText_command1.setText(strings[1]);
editText_command2 = view.findViewById(R.id.dialogDouble_editText_command2);
editText_command2.setText(strings[2]);
editText_button1 = view.findViewById(R.id.dialogDouble_editText_button1);
editText_button1.setText(strings[3]);
editText_button2 = view.findViewById(R.id.dialogDouble_editText_button2);
editText_button2.setText(strings[4]);
AlertDialog mDialog = mBuilder.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
break;
}
case HEADLINE: {
AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
View view = inflater.inflate(R.layout.addheadlinedialog, null);
editText_name = view.findViewById(R.id.dialogheadline_editText_name);
editText_name.setText(strings[0]);
builder.setView(view)
.setTitle(R.string.heading)
.setNegativeButton(R.string.cancel, (dialogInterface, i) -> {
})
.setPositiveButton(R.string.add, (dialogInterface, i) -> {
String headline = editText_name.getText().toString();
if(headline.isEmpty()){
AlertDialog mDialog = new AlertDialog.Builder(v.getContext())
.setTitle(R.string.invalid)
.setMessage(R.string.inputfields_cant_be_empty)
// 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(android.R.string.yes, null )
.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
return;
}
ListItemHeadline item_tmp = (ListItemHeadline) item;
item_tmp.setName(headline);
notifyDataSetChanged();
try {
TabsFragment.save(tabname, context, ListAdapter.this);
} catch (JSONException e) {
e.printStackTrace();
}
});
AlertDialog mDialog = builder.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
break;
}
}
}});
switch(item.getType()) {
case SINGLEBUTTON:
{
Button bRun = view.findViewById(R.id.singleButton_button);
Button text = view.findViewById(R.id.singleButton_text);
bRun.setText(strings[2]);
bRun.setOnClickListener(new CommandExecutor(strings[1]));
text.setText(strings[0]);
break;
}
case DOUBLEBUTTON:
{
Button bLeft = (Button) view.findViewById(R.id.doubleButton_bLeft);
Button bRight = (Button) view.findViewById(R.id.doubleButton_bRight);
Button text = (Button) view.findViewById(R.id.doubleButton_text);
bLeft.setText(strings[3]);
bRight.setText(strings[4]);
bLeft.setOnClickListener(new CommandExecutor(strings[1]));
bRight.setOnClickListener(new CommandExecutor(strings[2]));
text.setText(strings[0]);
break;
}
case SPACE:
{
// NOP
break;
}
case HEADLINE:
{
Button text = (Button) view.findViewById(R.id.headline_text);
text.setText(strings[0]);
break;
}
}
}
public static class ListItemViewHolder extends RecyclerView.ViewHolder {
private View itemView;
public ListItemViewHolder(@NonNull @NotNull View itemView) {
super(itemView);
this.itemView = itemView;
}
public void setItemView(View itemView) {
this.itemView = itemView;
}
public View getItemView() {
return itemView;
}
}
}

View File

@ -0,0 +1,58 @@
package com.example.onetap_ssh.ui.tabs;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public abstract class ListItem {
private int type;
public ListItem(int type) {
this.type = type;
}
public JSONObject toJson() throws JSONException {
JSONObject toJson = new JSONObject();
toJson.put("type", type);
JSONArray a = new JSONArray();
for(String s : getStrings()) {
a.put(s);
}
toJson.put("strings", a);
return toJson;
}
abstract public String[] getStrings();
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public static ListItem fromJson(JSONObject object) throws JSONException {
JSONArray Strings = object.getJSONArray("strings");
switch (object.getInt("type")){
case ListAdapter.SINGLEBUTTON:{
return new ListItemSingle(Strings.getString(0), Strings.getString(1), Strings.getString(2));
}
case ListAdapter.DOUBLEBUTTON:{
return new ListItemDouble(Strings.getString(0), Strings.getString(1), Strings.getString(2), Strings.getString(3), Strings.getString(4));
}
case ListAdapter.HEADLINE:{
return new ListItemHeadline(Strings.getString(0));
}
case ListAdapter.SPACE:{
return new ListItemSpace();
}
default: {
throw new RuntimeException("UNGÜLTIGER OBJEKTTYP");
}
}
}
}

View File

@ -0,0 +1,60 @@
package com.example.onetap_ssh.ui.tabs;
public class ListItemDouble extends ListItem{
private String name, command1, command2,button1, button2;
public ListItemDouble( String name, String command1, String command2, String button1, String button2) {
super( ListAdapter.DOUBLEBUTTON);
this.name = name;
this.command1 = command1;
this.command2 = command2;
this.button1 = button1;
this.button2 = button2;
}
public void setName(String name)
{
this.name = name;
}
public void setCommand1(String command1)
{
this.command1 = command1;
}
public void setCommand2(String command2)
{
this.command2 = command2;
}
public void setButton1(String button1)
{
this.button1 = button1;
}
public void setButton2(String button2)
{
this.button2 = button2;
}
public String getName()
{
return name;
}
public String getCommand1()
{
return command1;
}
public String getCommand2()
{
return command2;
}
public String getButton1()
{
return button1;
}
public String getButton2()
{
return button2;
}
@Override
public String[] getStrings() {
String[] s = {name, command1, command2, button1, button2};
return s;
}
}

View File

@ -0,0 +1,24 @@
package com.example.onetap_ssh.ui.tabs;
public class ListItemHeadline extends ListItem{
private String name;
public ListItemHeadline(String name) {
super( ListAdapter.HEADLINE);
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName()
{
return this.name;
}
@Override
public String[] getStrings() {
String[] s = {name};
return s;
}
}

View File

@ -0,0 +1,33 @@
package com.example.onetap_ssh.ui.tabs;
public class ListItemSingle extends ListItem{
String buttonName;
String command;
String name;
public ListItemSingle(String name,String command,String buttonName ) {
super(ListAdapter.SINGLEBUTTON);
this.name = name;
this.buttonName = buttonName;
this.command = command;
}
public void setName(String name)
{
this.name = name;
}
public void setButtonName(String buttonName)
{
this.buttonName = buttonName;
}
public void setCommand(String command)
{
this.command = command;
}
@Override
public String[] getStrings() {
String[] s = {name, command, buttonName};
return s;
}
}

View File

@ -0,0 +1,16 @@
package com.example.onetap_ssh.ui.tabs;
public class ListItemSpace extends ListItem {
public ListItemSpace() {
super(ListAdapter.SPACE);
}
@Override
public String[] getStrings() {
String[] s = {};
return s;
}
}

View File

@ -0,0 +1,272 @@
package com.example.onetap_ssh.ui.tabs;
import static android.content.Context.MODE_PRIVATE;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.Base64;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Objects;
import com.example.onetap_ssh.AddButtonDialogSingle;
import com.example.onetap_ssh.AddButtonsDialogDouble;
import com.example.onetap_ssh.AddHeadlineDialog;
import com.example.onetap_ssh.MainActivity;
import com.example.onetap_ssh.R;
public class TabsFragment extends Fragment implements AddButtonDialogSingle.AddButtonDialogListenerSingle, AddButtonsDialogDouble.AddButtonsDialogListenerDouble, AddHeadlineDialog.AddHeadlineDialogListener {
String[] commands = {"Hello1", "Hello2", "Hello3", "Hello4", "Hello5"};
int[] type = {0, 1, 0, 0, 1};
RecyclerView listView;
ListAdapter listAdapter;
FloatingActionButton addfab;
ArrayList<ListItem> items;
String tabname;
public TabsFragment(String tabname) {
this.tabname = tabname;
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
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);
items = new ArrayList<ListItem>();
listAdapter = new ListAdapter(getContext(), items, tabname);
listView.setLayoutManager(new LinearLayoutManager(getContext()));
listView.setAdapter(listAdapter);
ItemTouchHelper h = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(@NonNull @NotNull RecyclerView recyclerView, @NonNull @NotNull RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(@NonNull @NotNull RecyclerView recyclerView, @NonNull @NotNull RecyclerView.ViewHolder viewHolder, @NonNull @NotNull RecyclerView.ViewHolder target) {
//listAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
listAdapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
try {
save();
} catch (JSONException e) {
e.printStackTrace();
}
return true;
}
@Override
public void onSwiped(@NonNull @NotNull RecyclerView.ViewHolder viewHolder, int direction) {
listAdapter.remove(viewHolder.getAdapterPosition());
try {
save();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public boolean isLongPressDragEnabled() {
return MainActivity.editmode;
}
@Override
public boolean isItemViewSwipeEnabled() {
return MainActivity.editmode;
}
});
h.attachToRecyclerView(listView);
addfab = root.findViewById(R.id.fab);
if (MainActivity.editmode) {
addfab.setVisibility(View.VISIBLE);
} else {
addfab.setVisibility(View.GONE);
}
addfab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showChooseElement();
}
});
try {
load();
} catch (JSONException e) {
e.printStackTrace();
}
return root;
}
private void showChooseElement() {
final String[] listItems = {getString(R.string.single_button), getString(R.string.double_button), getString(R.string.heading), getString(R.string.space)};
AlertDialog.Builder mBuilder = new AlertDialog.Builder(getActivity());
mBuilder.setTitle(getString(R.string.choose_element));
mBuilder.setSingleChoiceItems(listItems, -1, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (i == 0) {
openDialog1();
} else if (i == 1) {
openDialog2();
} else if (i == 2) {
openDialog3();
} else if (i == 3) {
listAdapter.add(new ListItemSpace());
try {
save();
} catch (JSONException e) {
e.printStackTrace();
}
}
dialogInterface.dismiss();
}
});
AlertDialog mDialog = mBuilder.create();
Objects.requireNonNull(mDialog.getWindow()).setBackgroundDrawableResource(R.drawable.button_round);
mDialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //style id
mDialog.show();
}
public void openDialog1() {
AddButtonDialogSingle addButtonDialogSingle = new AddButtonDialogSingle();
addButtonDialogSingle.setFragment(this);
addButtonDialogSingle.show(requireActivity().getSupportFragmentManager(), getString(R.string.single_button));
}
public void openDialog2() {
AddButtonsDialogDouble addButtonsDialogDouble = new AddButtonsDialogDouble();
addButtonsDialogDouble.setFragment(this);
addButtonsDialogDouble.show(requireActivity().getSupportFragmentManager(), getString(R.string.double_button));
}
public void openDialog3() {
AddHeadlineDialog addHeadlineDialog = new AddHeadlineDialog();
addHeadlineDialog.setFragment(this);
addHeadlineDialog.show(requireActivity().getSupportFragmentManager(), getString(R.string.heading));
}
@Override
public void applyTextsSingle(String name, String command, String button) {
//items.add(new ListItemSingle(0,name,command,button));
listAdapter.add(new ListItemSingle(name, command, button));
try {
save();
} catch (JSONException e) {
e.printStackTrace();
}
}
public static int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
@Override
public void applyTextsDouble(String name, String command1, String command2, String button1, String button2) {
listAdapter.add(new ListItemDouble(name, command1, command2, button1, button2));
try {
save();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void applyTextsHeadline(String headline) {
listAdapter.add(new ListItemHeadline(headline));
try {
save();
} catch (JSONException e) {
e.printStackTrace();
}
}
public void load() throws JSONException {
if (MainActivity.editmode) {
addfab.setVisibility(View.VISIBLE);
} else {
addfab.setVisibility(View.GONE);
}
listAdapter.clear();
SharedPreferences p = requireContext().getSharedPreferences("appsettings", Activity.MODE_PRIVATE);
String listItems = p.getString("listItems." + tabname, "[]");
JSONArray listItems2 = new JSONArray(listItems);
for (int i = 0; i < listItems2.length(); i++) {
JSONObject item = listItems2.getJSONObject(i);
listAdapter.add(ListItem.fromJson(item));
}
}
public static void save(String tabname, Context context, ListAdapter listAdapter) throws JSONException {
JSONArray listItems2 = new JSONArray();
for (ListItem Item : listAdapter.getObjects()) {
listItems2.put(Item.toJson());
}
SharedPreferences.Editor editor = context.getSharedPreferences("appsettings", MODE_PRIVATE).edit();
editor.putString("listItems." + tabname, listItems2.toString());
editor.apply();
}
public void save() throws JSONException {
save(tabname, requireContext(), listAdapter);
}
}

View File

@ -0,0 +1,25 @@
package com.example.onetap_ssh.ui.tabs;
import android.view.View;
import android.widget.Button;
public class ViewHolderDoubleButton implements IViewHolder{
String commandL;
Button bLeft, bRight;
@Override
public String getCommand() {
return commandL;
}
public Button getbLeft() {
return bLeft;
}
public Button getbRight(){return bRight;}
@Override
public View[] getViews()
{
return new View[]{getbLeft(),getbRight()};
}
}

View File

@ -0,0 +1,25 @@
package com.example.onetap_ssh.ui.tabs;
import android.view.View;
import android.widget.Button;
public class ViewHolderSingleButton implements IViewHolder {
String command;
Button bRun;
@Override
public String getCommand() {
return command;
}
public Button getbRun() {
return bRun;
}
@Override
public View[] getViews()
{
return new View[]{getbRun(),};
}
}

View File

@ -0,0 +1,120 @@
package com.example.onetap_ssh.ui.terminal;
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/**
* This program enables you to connect to sshd server and get the shell prompt.
* $ CLASSPATH=.:../build javac Shell.java
* $ CLASSPATH=.:../build java Shell
* You will be asked username, hostname and passwd.
* If everything works fine, you will get the shell prompt. Output may
* be ugly because of lacks of terminal-emulation, but you can issue commands.
*/
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UIKeyboardInteractive;
import com.jcraft.jsch.UserInfo;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import com.example.onetap_ssh.ui.home.HomeFragment;
public class Terminal {
private Session session;
private JSch jsch;
private ByteArrayOutputStream Output;
private PipedOutputStream Input;
public Terminal() {
try {
JSch jsch = new JSch();
session = jsch.getSession(HomeFragment.user, HomeFragment.ip, 22);
session.setPassword(HomeFragment.password);
session.setUserInfo(new MyUserInfo() {
@Override
public String getPassword() {
return super.getPassword();
}
});
session.setConfig("StrictHostKeyChecking", "no");
session.connect(30000);
Channel channel = session.openChannel("shell");
Input = new PipedOutputStream();
channel.setInputStream(new PipedInputStream(Input));
Output = new ByteArrayOutputStream();
channel.setOutputStream(Output);
channel.connect(3 * 1000);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String getTerminalOutput() {
return new String(Output.toByteArray()).replaceAll("\u001B\\[[;\\d]*m", "");
}
public void sendTerminalCommand(String terminalcommand) {
try {
Input.write((terminalcommand + "\n").getBytes());
Input.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void closeTerminal() {
session.disconnect();
}
public static abstract class MyUserInfo
implements UserInfo, UIKeyboardInteractive {
public String getPassword() {
return null;
}
public boolean promptYesNo(String str) {
return false;
}
public String getPassphrase() {
return null;
}
public boolean promptPassphrase(String message) {
return false;
}
public boolean promptPassword(String message) {
return false;
}
public void showMessage(String message) {
}
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo) {
return null;
}
}
}

View File

@ -0,0 +1,168 @@
package com.example.onetap_ssh.ui.terminal;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Vibrator;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import java.util.Objects;
import com.example.onetap_ssh.MainActivity;
import com.example.onetap_ssh.R;
public class TerminalFragment extends Fragment {
public static boolean atBottom = false;
public static String command;
Button send_button;
EditText terminal_edit_text;
TextView terminal_textView;
Terminal terminal;
ScrollView scrollView;
public static String user, password, ip;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_terminal, container, false);
SharedPreferences prefs = requireContext().getSharedPreferences("appsettings", Context.MODE_PRIVATE);
user = prefs.getString("user", null);
password = prefs.getString("password", null);
ip = prefs.getString("ip", null);
if (user == null || ip == null || password == null) {
AlertDialog mDialog = new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.unable_to_connect))
.setMessage(getString(R.string.please_login))
// 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 (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().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();
} else {
scrollView = (ScrollView) root.findViewById((R.id.scrollView));
terminal_edit_text = (EditText) root.findViewById(R.id.terminal_edit_text);
send_button = (Button) root.findViewById(R.id.send_button);
send_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (MainActivity.button_vibration) {
Vibrator vr = (Vibrator) requireContext().getSystemService(Context.VIBRATOR_SERVICE);
assert vr != null;
vr.vibrate(100);
}
if (terminal != null) {
terminal.sendTerminalCommand(terminal_edit_text.getText().toString());
if (atBottom) {
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(View.FOCUS_DOWN);
}
}, 500);
}}
}
});
terminal_textView = (TextView) root.findViewById(R.id.terminal_textView);
new Thread() {
public void run() {
try {
terminal = new Terminal();
} catch (Exception e) {
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getContext(), R.string.unable_to_connect, Toast.LENGTH_SHORT).show();
}
});
return;
}
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getContext(), R.string.connected, Toast.LENGTH_SHORT).show();
}
});
while (terminal != null) {
if (getActivity() == null) {
return;
}
try {
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
atBottom = scrollView.getChildAt(0).getBottom() <= (scrollView.getHeight() + scrollView.getScrollY());
terminal_textView.setText(terminal.getTerminalOutput());
System.out.println(atBottom);
terminal_textView.invalidate();
scrollView.invalidate();
//scrollView.fullScroll(View.FOCUS_DOWN);
}
});
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
return root;
}
@Override
public void onDestroy() {
if (terminal != null) {
terminal.closeTerminal();
}
super.onDestroy();
}
}

View File

@ -40,7 +40,7 @@ public class NavigationUtil {
FragmentManager manager = activity.getSupportFragmentManager(); FragmentManager manager = activity.getSupportFragmentManager();
manager.beginTransaction() manager.beginTransaction()
.setReorderingAllowed(true) .setReorderingAllowed(true)
.add(R.id.nav_host_fragment_content_main, overlay) .add(R.id.nav_host_fragment, overlay)
.runOnCommit(() -> updateActivity(activity, overlay)) .runOnCommit(() -> updateActivity(activity, overlay))
.commit(); .commit();
} }
@ -70,7 +70,7 @@ public class NavigationUtil {
private static void navigate(FragmentManager manager, Fragment fragment, Runnable onCommit) { private static void navigate(FragmentManager manager, Fragment fragment, Runnable onCommit) {
manager.beginTransaction() manager.beginTransaction()
.setReorderingAllowed(true) .setReorderingAllowed(true)
.replace(R.id.nav_host_fragment_content_main, fragment) .replace(R.id.nav_host_fragment, fragment)
.runOnCommit(onCommit) .runOnCommit(onCommit)
.commit(); .commit();
} }
@ -80,7 +80,7 @@ public class NavigationUtil {
} }
public static Fragment getCurrentFragment(FragmentManager manager) { public static Fragment getCurrentFragment(FragmentManager manager) {
return manager.findFragmentById(R.id.nav_host_fragment_content_main); return manager.findFragmentById(R.id.nav_host_fragment);
} }
} }

View File

@ -48,7 +48,7 @@ public class ThemeUtil {
if(!SettingsUtil.isThemedBackgroundEnabled(activity)) return; if(!SettingsUtil.isThemedBackgroundEnabled(activity)) return;
int background = getBackground(activity); int background = getBackground(activity);
View v = activity.findViewById(R.id.app_background); View v = activity.findViewById(R.id.drawer_layout);
if(v != null) { if(v != null) {
v.setBackgroundResource(background); v.setBackgroundResource(background);
} }

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/overshoot_interpolator"
android:shareInterpolator="true" >
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="300"/>
<scale
android:fromXScale="0.8"
android:toXScale="1.0"
android:fromYScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="300"/>
<translate
android:fromXDelta="0%"
android:toXDelta="0%"
android:fromYDelta="-10%"
android:toYDelta="0%"
android:duration="300"/>
<rotate
android:fromDegrees="10"
android:toDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="300"/>
</set>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/anticipate_interpolator"
android:shareInterpolator="true" >
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="300"/>
<scale
android:fromXScale="1.0"
android:toXScale="0.8"
android:fromYScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="300"/>
<translate
android:fromXDelta="0%"
android:toXDelta="0%"
android:fromYDelta="0%"
android:toYDelta="-10%"
android:duration="300"/>
<rotate
android:fromDegrees="0"
android:toDegrees="-10"
android:pivotX="50%"
android:pivotY="50%"
android:duration="300"/>
</set>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="0dp"
android:color="#FFFFFF" />
<gradient
android:angle="180"
android:endColor="?attr/colorPrimary"
android:startColor="?attr/colorSecondary" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />
</shape>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:width="0dp"
android:color="#FFFFFF"/>
<solid
android:color="?attr/colorBackgroundFloating"
android:alpha="0.0"/>
<corners
android:bottomLeftRadius="20dp"
android:bottomRightRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp" />
</shape>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="0dp"
android:color="#FFFFFF" />
<gradient
android:angle="0"
android:endColor="?attr/colorPrimary"
android:startColor="?attr/colorSecondary" />
<corners
android:bottomLeftRadius="20dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="20dp"
android:topRightRadius="0dp" />
</shape>
</item>
<item
android:bottom="2dp"
android:left="0dp"
android:right="0dp"
android:top="0dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="0dp"
android:color="#FFFFFF" />
<gradient
android:angle="180"
android:endColor="?attr/colorOnBackground"
android:startColor="?attr/colorOnBackground" />
<corners
android:bottomLeftRadius="20dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="20dp"
android:topRightRadius="0dp" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="0dp"
android:color="#FFFFFF" />
<gradient
android:angle="180"
android:endColor="?attr/colorPrimary"
android:startColor="?attr/colorPrimary" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />
</shape>
</item>
<item
android:bottom="2dp"
android:left="0dp"
android:right="0dp"
android:top="0dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="0dp"
android:color="#FFFFFF" />
<gradient
android:angle="180"
android:endColor="?attr/colorOnBackground"
android:startColor="?attr/colorOnBackground" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="0dp"
android:color="#FFFFFF" />
<gradient
android:angle="180"
android:endColor="?attr/colorPrimary"
android:startColor="?attr/colorSecondary" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="20dp"
android:topLeftRadius="0dp"
android:topRightRadius="20dp" />
</shape>
</item>
<item
android:bottom="2dp"
android:left="0dp"
android:right="0dp"
android:top="0dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="0dp"
android:color="#FFFFFF" />
<gradient
android:angle="180"
android:endColor="?attr/colorOnBackground"
android:startColor="?attr/colorOnBackground" />
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="20dp"
android:topLeftRadius="0dp"
android:topRightRadius="20dp" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12 19,6.41z"
android:fillColor="#000000"/>
</vector>

View File

@ -4,7 +4,8 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="#000000"> android:background="#000000"
android:id="@+id/drawer_layout">
<VideoView <VideoView
android:id="@+id/videoView" android:id="@+id/videoView"

View File

@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
android:id="@+id/app_background" android:id="@+id/drawer_layout"
tools:openDrawer="start"> tools:openDrawer="start">
<include <include

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical" >
<EditText
android:id="@+id/dialogheadline_editText_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/name"
android:inputType="textPersonName" />
<EditText
android:id="@+id/dialogSingle_editText_buttonName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/button"
android:inputType="textPersonName" />
<EditText
android:id="@+id/dialogSingle_editText_command"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/command"
android:inputType="textPersonName" />
</LinearLayout>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation = "vertical"
android:padding="16dp">
<EditText
android:id="@+id/dialogDouble_editText_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/name"
android:inputType="textPersonName" />
<EditText
android:id="@+id/dialogDouble_editText_command1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/command1"
android:inputType="textPersonName" />
<EditText
android:id="@+id/dialogDouble_editText_button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/button1"
android:inputType="textPersonName" />
<EditText
android:id="@+id/dialogDouble_editText_command2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/command2"
android:inputType="textPersonName" />
<EditText
android:id="@+id/dialogDouble_editText_button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/button2"
android:inputType="textPersonName" />
</LinearLayout>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical" >
<EditText
android:id="@+id/dialogheadline_editText_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/heading"
android:inputType="textPersonName" />
</LinearLayout>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical" >
<EditText
android:id="@+id/dialogtab_editText_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/tabname"
android:inputType="textPersonName" />
</LinearLayout>

View File

@ -8,7 +8,7 @@
tools:showIn="@layout/app_bar_main"> tools:showIn="@layout/app_bar_main">
<fragment <fragment
android:id="@+id/nav_host_fragment_content_main" android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/line1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/doubleButton_bLeft"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/button_left"
android:text="Button1"
app:backgroundTint="@null" />
<Button
android:id="@+id/doubleButton_text"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/button_middle"
android:text="Button1"
app:backgroundTint="@null" />
<Button
android:id="@+id/doubleButton_bRight"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/button_right"
android:text="Button2"
app:backgroundTint="@null" />
<ImageView
android:id="@+id/image_edit"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_margin="5dp"
android:layout_weight="0"
app:srcCompat="@drawable/mode_edit_black_24dp"
app:tint="?attr/colorOnPrimary"
tools:ignore="VectorDrawableCompat">
</ImageView>
<ImageView
android:id="@+id/image_remove"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_margin="5dp"
app:srcCompat="@drawable/clear_black_24dp"
app:tint="?attr/colorOnPrimary"
tools:ignore="VectorDrawableCompat">
</ImageView>
</LinearLayout>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical" >
<EditText
android:id="@+id/dialogexport_editText_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/filename"
android:inputType="textPersonName" />
</LinearLayout>

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/fragment_tabs"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/Background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80FFFFFF"
android:scaleType="centerCrop"
android:src="@drawable/background_red_blue" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="65dp"
android:visibility="visible"
android:divider="@null"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:dividerHeight="0dp"
/>
</FrameLayout>

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragment_terminal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
tools:context=".ui.terminal.TerminalFragment">
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="10dp"
android:scrollbars="horizontal|vertical"
app:layout_constraintBottom_toTopOf="@+id/divider2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/terminal_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="serif-monospace"
android:text="TextView"
android:textColor="#FFFFFF" />
</LinearLayout>
</HorizontalScrollView>
</ScrollView>
<View
android:id="@+id/divider2"
android:layout_width="0dp"
android:layout_height="2dp"
android:layout_marginBottom="10dp"
android:background="@drawable/background_full"
app:layout_constraintBottom_toTopOf="@+id/terminal_edit_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="@+id/terminal_edit_text"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginStart="10dp"
android:layout_marginBottom="10dp"
android:ems="10"
android:fontFamily="serif-monospace"
android:hint="@string/command"
android:imeOptions="actionDone"
android:inputType="text"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/send_button"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/send_button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp"
android:background="@drawable/button_right"
android:text="@string/send"
app:backgroundTint="@null"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/headline_text"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_marginTop="5dp"
android:layout_weight="1"
android:background="@drawable/backgroundoverlay"
android:insetLeft="25dp"
android:insetRight="25dp"
android:text="TEXT"
app:backgroundTint="@null" />
<ImageView
android:id="@+id/image_edit"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_margin="5dp"
android:layout_weight="0"
android:visibility="visible"
app:srcCompat="@drawable/mode_edit_black_24dp"
app:tint="?attr/colorOnPrimary"
tools:ignore="VectorDrawableCompat">
</ImageView>
<ImageView
android:id="@+id/image_remove"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_margin="5dp"
android:visibility="visible"
app:srcCompat="@drawable/clear_black_24dp"
app:tint="?attr/colorOnPrimary"
tools:ignore="VectorDrawableCompat">
</ImageView>
</LinearLayout>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/singleButton_text"
android:layout_width="10dp"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_marginTop="5dp"
android:layout_weight="2"
android:background="@drawable/button_middle"
android:text="TEXT"
app:backgroundTint="@null" />
<Button
android:id="@+id/singleButton_button"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@drawable/button_right"
android:text="Button2"
app:backgroundTint="@null" />
<ImageView
android:id="@+id/image_edit"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_margin="5dp"
android:layout_weight="0"
android:visibility="visible"
app:srcCompat="@drawable/mode_edit_black_24dp"
app:tint="?attr/colorOnPrimary"
tools:ignore="VectorDrawableCompat">
</ImageView>
<ImageView
android:id="@+id/image_remove"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_margin="5dp"
android:layout_weight="0"
android:visibility="visible"
app:srcCompat="@drawable/clear_black_24dp"
app:tint="?attr/colorOnPrimary"
tools:ignore="VectorDrawableCompat">
</ImageView>
</LinearLayout>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Space
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1" />
<ImageView
android:id="@+id/image_edit"
android:layout_width="00dp"
android:layout_height="00dp"
android:layout_gravity="center"
android:layout_margin="5dp"
android:layout_weight="0"
android:visibility="gone"
app:srcCompat="@drawable/mode_edit_black_24dp"
app:tint="?attr/colorOnPrimary"
tools:ignore="VectorDrawableCompat">
</ImageView>
<ImageView
android:id="@+id/image_remove"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:layout_margin="5dp"
android:visibility="visible"
app:srcCompat="@drawable/clear_black_24dp"
app:tint="?attr/colorOnPrimary"
tools:ignore="VectorDrawableCompat">
</ImageView>
</LinearLayout>

View File

@ -19,6 +19,7 @@
android:title="@string/menu_terminal" /> android:title="@string/menu_terminal" />
</group> </group>
<group <group
android:id="@+id/Down" android:id="@+id/Down"

View File

@ -5,6 +5,17 @@
android:id="@+id/mobile_navigation" android:id="@+id/mobile_navigation"
app:startDestination="@+id/nav_home"> app:startDestination="@+id/nav_home">
<fragment
android:id="@+id/nav_tabs"
android:name="com.example.onetap_ssh.ui.tabs.TabsFragment"
android:label="@string/menu_tabs"
tools:layout="@layout/fragment_tabs" />
<fragment
android:id="@+id/nav_terminal"
android:name="com.example.onetap_ssh.ui.terminal.TerminalFragment"
android:label="@string/menu_terminal"
tools:layout="@layout/fragment_terminal" />
<fragment <fragment
android:id="@+id/nav_home" android:id="@+id/nav_home"
android:name="com.example.onetap_ssh.ui.home.HomeFragment" android:name="com.example.onetap_ssh.ui.home.HomeFragment"

Binary file not shown.

View File

@ -11,4 +11,8 @@
<item name="colorTheme1">@color/color_blue</item> <item name="colorTheme1">@color/color_blue</item>
<item name="colorTheme2">@color/color_light_green</item> <item name="colorTheme2">@color/color_light_green</item>
</style> </style>
<style name="DialogAnimation">
<item name="android:windowEnterAnimation">@anim/dialog_in</item>
<item name="android:windowExitAnimation">@anim/dialog_out</item>
</style>
</resources> </resources>

View File

@ -82,4 +82,8 @@
<item name="colorTheme1">@color/color_blue</item> <item name="colorTheme1">@color/color_blue</item>
<item name="colorTheme2">@color/color_light_green</item> <item name="colorTheme2">@color/color_light_green</item>
</style> </style>
<style name="DialogAnimation">
<item name="android:windowEnterAnimation">@anim/dialog_in</item>
<item name="android:windowExitAnimation">@anim/dialog_out</item>
</style>
</resources> </resources>