diff options
author | Zeapo <mohamed@zenadi.com> | 2014-07-27 03:33:08 +0100 |
---|---|---|
committer | Zeapo <mohamed@zenadi.com> | 2014-07-27 03:33:08 +0100 |
commit | c75fd77fdf39328e41a2e23c26583ab745df44a3 (patch) | |
tree | 7afff75e12814185501521a6c3d9315ec87ce65c | |
parent | 784a474efb93f5c45fd24ed63ecfdd6f198ba51d (diff) |
Implemented the List view, a lot of work to do..
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/GitClone.java | 64 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java | 155 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/ToCloneOrNot.java | 110 | ||||
-rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/pwdstore.java | 79 | ||||
-rw-r--r-- | app/src/main/res/drawable-xxhdpi/rectangle.xml | 23 | ||||
-rw-r--r-- | app/src/main/res/layout/activity_pwdstore.xml | 7 | ||||
-rw-r--r-- | app/src/main/res/layout/fragment_password_grid.xml | 20 | ||||
-rw-r--r-- | app/src/main/res/layout/fragment_password_list.xml | 15 | ||||
-rw-r--r-- | app/src/main/res/layout/fragment_to_clone_or_not.xml | 37 | ||||
-rw-r--r-- | app/src/main/res/layout/password_row_layout.xml | 13 | ||||
-rw-r--r-- | app/src/main/res/menu/pwdstore.xml | 5 | ||||
-rw-r--r-- | app/src/main/res/values/strings.xml | 4 |
12 files changed, 490 insertions, 42 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/GitClone.java b/app/src/main/java/com/zeapo/pwdstore/GitClone.java index a7c817c5..cab56e96 100644 --- a/app/src/main/java/com/zeapo/pwdstore/GitClone.java +++ b/app/src/main/java/com/zeapo/pwdstore/GitClone.java @@ -325,33 +325,43 @@ public class GitClone extends Activity { if (connectionMode.equalsIgnoreCase("ssh-key")) { } else { - final EditText password = new EditText(activity); - password.setHint("Password"); - password.setWidth(LinearLayout.LayoutParams.MATCH_PARENT); - password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); - - new AlertDialog.Builder(activity) - .setTitle("Authenticate") - .setMessage("Please provide the password for this repository") - .setView(password) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - - SshSessionFactory.setInstance(new GitConfigSessionFactory()); - - CloneCommand cmd = Git.cloneRepository(). - setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password.getText().toString())). - setCloneAllBranches(true). - setDirectory(localDir). - setURI(hostname); - - new CloneTask(activity).execute(cmd); - } - }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - // Do nothing. - } - }).show(); + if (protocol.equals("ssh://")) { + + final EditText password = new EditText(activity); + password.setHint("Password"); + password.setWidth(LinearLayout.LayoutParams.MATCH_PARENT); + password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); + + new AlertDialog.Builder(activity) + .setTitle("Authenticate") + .setMessage("Please provide the password for this repository") + .setView(password) + .setPositiveButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + + SshSessionFactory.setInstance(new GitConfigSessionFactory()); + + CloneCommand cmd = Git.cloneRepository(). + setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password.getText().toString())). + setCloneAllBranches(true). + setDirectory(localDir). + setURI(hostname); + + new CloneTask(activity).execute(cmd); + } + }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + // Do nothing. + } + }).show(); + } else { + CloneCommand cmd = Git.cloneRepository(). + setCloneAllBranches(true). + setDirectory(localDir). + setURI(hostname); + + new CloneTask(activity).execute(cmd); + } } } diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java new file mode 100644 index 00000000..462324db --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java @@ -0,0 +1,155 @@ +package com.zeapo.pwdstore; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ListAdapter; +import android.widget.RelativeLayout; +import android.widget.TextView; + + +import com.zeapo.pwdstore.dummy.DummyContent; + +import java.util.List; + +/** + * A fragment representing a list of Items. + * <p /> + * Large screen devices (such as tablets) are supported by replacing the ListView + * with a GridView. + * <p /> + * Activities containing this fragment MUST implement the {@link Callbacks} + * interface. + */ +public class PasswordFragment extends Fragment implements AbsListView.OnItemClickListener { + + private OnFragmentInteractionListener mListener; + + /** + * The fragment's ListView/GridView. + */ + private AbsListView mListView; + + /** + * The Adapter which will be used to populate the ListView/GridView with + * Views. + */ + private ListAdapter mAdapter; + + // TODO: Rename and change types of parameters + public static PasswordFragment newInstance(String param1, String param2) { + PasswordFragment fragment = new PasswordFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + /** + * Mandatory empty constructor for the fragment manager to instantiate the + * fragment (e.g. upon screen orientation changes). + */ + public PasswordFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (getArguments() != null) { + } + String[] values = new String[] { "NOT", "YET", "IMPLEMENTED" }; + + // TODO: Change Adapter to display your content + mAdapter = new MySimpleArrayAdapter(getActivity(), values); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_password, container, false); + + // Set the adapter + mListView = (AbsListView) view.findViewById(android.R.id.list); + ((AdapterView<ListAdapter>) mListView).setAdapter(mAdapter); + + // Set OnItemClickListener so we can be notified on item clicks + mListView.setOnItemClickListener(this); + + return view; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + mListener = (OnFragmentInteractionListener) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement OnFragmentInteractionListener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + if (null != mListener) { + // Notify the active callbacks interface (the activity, if the + // fragment is attached to one) that an item has been selected. +// mListener.onFragmentInteraction(DummyContent.ITEMS.get(position).id); + } + } + + /** + * The default content for this Fragment has a TextView that is shown when + * the list is empty. If you would like to change the text, call this method + * to supply the text it should use. + */ + public void setEmptyText(CharSequence emptyText) { + View emptyView = mListView.getEmptyView(); + + if (emptyText instanceof TextView) { + ((TextView) emptyView).setText(emptyText); + } + } + + public interface OnFragmentInteractionListener { + // TODO: Update argument type and name + public void onFragmentInteraction(String id); + } + + + public class MySimpleArrayAdapter extends ArrayAdapter<String> { + private final Context context; + private final String[] values; + + public MySimpleArrayAdapter(Context context, String[] values) { + super(context, R.layout.password_row_layout, values); + this.context = context; + this.values = values; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rowView = inflater.inflate(R.layout.password_row_layout, parent, false); + TextView textView = (TextView) rowView.findViewById(R.id.label); + textView.setText(values[position]); + + return rowView; + } + } +} diff --git a/app/src/main/java/com/zeapo/pwdstore/ToCloneOrNot.java b/app/src/main/java/com/zeapo/pwdstore/ToCloneOrNot.java new file mode 100644 index 00000000..dd1ebda1 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/ToCloneOrNot.java @@ -0,0 +1,110 @@ +package com.zeapo.pwdstore; + +import android.app.Activity; +import android.net.Uri; +import android.os.Bundle; +import android.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + + + +/** + * A simple {@link Fragment} subclass. + * Activities that contain this fragment must implement the + * {@link ToCloneOrNot.OnFragmentInteractionListener} interface + * to handle interaction events. + * Use the {@link ToCloneOrNot#newInstance} factory method to + * create an instance of this fragment. + * + */ +public class ToCloneOrNot extends Fragment { + // TODO: Rename parameter arguments, choose names that match + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER + private static final String ARG_PARAM1 = "param1"; + private static final String ARG_PARAM2 = "param2"; + + // TODO: Rename and change types of parameters + private String mParam1; + private String mParam2; + + private OnFragmentInteractionListener mListener; + + /** + * Use this factory method to create a new instance of + * this fragment using the provided parameters. + * + * @param param1 Parameter 1. + * @param param2 Parameter 2. + * @return A new instance of fragment ToCloneOrNot. + */ + // TODO: Rename and change types and number of parameters + public static ToCloneOrNot newInstance(String param1, String param2) { + ToCloneOrNot fragment = new ToCloneOrNot(); + Bundle args = new Bundle(); + args.putString(ARG_PARAM1, param1); + args.putString(ARG_PARAM2, param2); + fragment.setArguments(args); + return fragment; + } + public ToCloneOrNot() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mParam1 = getArguments().getString(ARG_PARAM1); + mParam2 = getArguments().getString(ARG_PARAM2); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.fragment_to_clone_or_not, container, false); + } + + // TODO: Rename method, update argument and hook method into UI event + public void onButtonPressed(Uri uri) { + if (mListener != null) { + mListener.onFragmentInteraction(uri); + } + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + mListener = (OnFragmentInteractionListener) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement OnFragmentInteractionListener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + /** + * This interface must be implemented by activities that contain this + * fragment to allow an interaction in this fragment to be communicated + * to the activity and potentially other fragments contained in that + * activity. + * <p> + * See the Android Training lesson <a href= + * "http://developer.android.com/training/basics/fragments/communicating.html" + * >Communicating with Other Fragments</a> for more information. + */ + public interface OnFragmentInteractionListener { + // TODO: Update argument type and name + public void onFragmentInteraction(Uri uri); + } + +} diff --git a/app/src/main/java/com/zeapo/pwdstore/pwdstore.java b/app/src/main/java/com/zeapo/pwdstore/pwdstore.java index 54e1605b..52071957 100644 --- a/app/src/main/java/com/zeapo/pwdstore/pwdstore.java +++ b/app/src/main/java/com/zeapo/pwdstore/pwdstore.java @@ -1,26 +1,48 @@ package com.zeapo.pwdstore; import android.app.Activity; +import android.app.FragmentManager; +import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; import android.hardware.display.DisplayManager; +import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.TextView; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.filefilter.DirectoryFileFilter; +import org.apache.commons.io.filefilter.FileFilterUtils; +import org.apache.commons.io.filefilter.NotFileFilter; +import org.apache.commons.io.filefilter.TrueFileFilter; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.RepositoryBuilder; +import org.eclipse.jgit.storage.file.FileRepositoryBuilder; + +import java.io.File; +import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.util.Collection; -public class pwdstore extends Activity { +public class pwdstore extends Activity implements ToCloneOrNot.OnFragmentInteractionListener, PasswordFragment.OnFragmentInteractionListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_pwdstore); - System.out.println("HEE"); + } + + @Override + public void onResume(){ + super.onResume(); + // re-check that there was no change with the repository state + checkLocalRepository(); } @@ -36,16 +58,57 @@ public class pwdstore extends Activity { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. - int id = item.getItemId(); - if (id == R.id.clone_setting) { - getClone(); - return true; - } +// int id = item.getItemId(); +// if (id == R.id.clone_setting) { +// getClone(); +// return true; +// } return super.onOptionsItemSelected(item); } - public void getClone(){ + public void getClone(View view){ Intent intent = new Intent(this, GitClone.class); startActivity(intent); } + + @Override + public void onFragmentInteraction(Uri uri) { + + } + + @Override + public void onFragmentInteraction(String id) { + + } + + private void checkLocalRepository() { + int status = 0; + final File localDir = new File(getCacheDir() + "/store"); + + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + + if (localDir.exists()) { + File[] folders = localDir.listFiles((FileFilter) FileFilterUtils.directoryFileFilter()); + status = folders.length; + } + + // either the repo is empty or it was not correctly cloned + switch (status) { + case 0: + ToCloneOrNot cloneFrag = new ToCloneOrNot(); + fragmentTransaction.replace(R.id.main_layout, cloneFrag); + fragmentTransaction.commit(); + break; + case 1: + // empty + break; + default: + PasswordFragment passFrag = new PasswordFragment(); + fragmentTransaction.replace(R.id.main_layout, passFrag); + fragmentTransaction.commit(); + } + } + } diff --git a/app/src/main/res/drawable-xxhdpi/rectangle.xml b/app/src/main/res/drawable-xxhdpi/rectangle.xml new file mode 100644 index 00000000..67e169df --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/rectangle.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape android:shape="rectangle" + android:dither="true"> + <corners android:radius="2dp"/> + <solid android:color="#ccc" /> + </shape> + </item> + + <item android:bottom="2dp"> + <shape android:shape="rectangle" android:dither="true"> + <corners android:radius="2dp" /> + <solid android:color="@android:color/white" /> + + <padding android:bottom="8dp" + android:left="8dp" + android:right="8dp" + android:top="8dp" /> + </shape> + </item> +</layer-list>
\ No newline at end of file diff --git a/app/src/main/res/layout/activity_pwdstore.xml b/app/src/main/res/layout/activity_pwdstore.xml index a59ed394..0060cb78 100644 --- a/app/src/main/res/layout/activity_pwdstore.xml +++ b/app/src/main/res/layout/activity_pwdstore.xml @@ -6,6 +6,13 @@ android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" + android:background="#eee" tools:context=".pwdstore"> + <LinearLayout + android:id="@+id/main_layout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"></LinearLayout> + </RelativeLayout> diff --git a/app/src/main/res/layout/fragment_password_grid.xml b/app/src/main/res/layout/fragment_password_grid.xml new file mode 100644 index 00000000..b23aa4d3 --- /dev/null +++ b/app/src/main/res/layout/fragment_password_grid.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context="com.zeapo.pwdstore.PasswordFragment"> + + <GridView + android:id="@android:id/list" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:numColumns="2" /> + + <TextView + android:id="@android:id/empty" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" /> + +</FrameLayout> diff --git a/app/src/main/res/layout/fragment_password_list.xml b/app/src/main/res/layout/fragment_password_list.xml new file mode 100644 index 00000000..9ee68056 --- /dev/null +++ b/app/src/main/res/layout/fragment_password_list.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context="com.zeapo.pwdstore.PasswordFragment"> + + <ListView + android:id="@android:id/list" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:dividerHeight="8dp" + android:divider="@android:color/transparent"/> + +</FrameLayout> diff --git a/app/src/main/res/layout/fragment_to_clone_or_not.xml b/app/src/main/res/layout/fragment_to_clone_or_not.xml new file mode 100644 index 00000000..c11f3567 --- /dev/null +++ b/app/src/main/res/layout/fragment_to_clone_or_not.xml @@ -0,0 +1,37 @@ +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#eee" + tools:context="com.zeapo.pwdstore.ToCloneOrNot"> + + <LinearLayout + android:id="@+id/myRectangleView" + android:layout_width="200dp" + android:layout_height="wrap_content" + android:background="@drawable/rectangle" + android:layout_gravity="center" + android:orientation="vertical"> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:text="You have no git repository for the password store."/> + <Button + android:id="@+id/main_clone_button" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="8dp" + android:background="@android:color/holo_green_light" + android:onClick="getClone" + android:text="Clone!"/> + <Button + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:background="@android:color/holo_red_light" + android:text="Initialize!"/> + </LinearLayout> + +</FrameLayout> diff --git a/app/src/main/res/layout/password_row_layout.xml b/app/src/main/res/layout/password_row_layout.xml new file mode 100644 index 00000000..4a562f76 --- /dev/null +++ b/app/src/main/res/layout/password_row_layout.xml @@ -0,0 +1,13 @@ +<?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:id="@+id/pass_row_layout" + android:background="@drawable/rectangle"> + <TextView + android:id="@+id/label" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="8dp"/> + +</LinearLayout> diff --git a/app/src/main/res/menu/pwdstore.xml b/app/src/main/res/menu/pwdstore.xml index 749cabdd..7dc96cff 100644 --- a/app/src/main/res/menu/pwdstore.xml +++ b/app/src/main/res/menu/pwdstore.xml @@ -1,9 +1,4 @@ <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context=".pwdstore" > - <item android:id="@+id/clone_setting" - android:title="@string/clone_settings" - android:orderInCategory="100" - android:showAsAction="ifRoom|withText" - android:icon="@android:drawable/stat_sys_download"/> </menu> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 50acf7e6..c348f3aa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,7 +6,6 @@ <string name="clone_settings">Clone</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> - <string name="dialog_delete_title">Directory already exist</string> <string name="dialog_delete_msg">Target directory already exist. Current version support only a single store. Do you want to delete the current password store directory?</string> <string name="dialog_delete">Delete directory</string> @@ -16,11 +15,12 @@ <item>username/password</item> <item>ssh-key</item> </string-array> - <string-array name="clone_protocols"> <item>ssh://</item> <item>https://</item> <item>http://</item> </string-array> + <string name="hello_blank_fragment">Hello blank fragment</string> + </resources> |