summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorZeapo <mohamed@zenadi.com>2014-07-27 03:33:08 +0100
committerZeapo <mohamed@zenadi.com>2014-07-27 03:33:08 +0100
commitc75fd77fdf39328e41a2e23c26583ab745df44a3 (patch)
tree7afff75e12814185501521a6c3d9315ec87ce65c /app
parent784a474efb93f5c45fd24ed63ecfdd6f198ba51d (diff)
Implemented the List view, a lot of work to do..
Diffstat (limited to 'app')
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/GitClone.java64
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/PasswordFragment.java155
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/ToCloneOrNot.java110
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/pwdstore.java79
-rw-r--r--app/src/main/res/drawable-xxhdpi/rectangle.xml23
-rw-r--r--app/src/main/res/layout/activity_pwdstore.xml7
-rw-r--r--app/src/main/res/layout/fragment_password_grid.xml20
-rw-r--r--app/src/main/res/layout/fragment_password_list.xml15
-rw-r--r--app/src/main/res/layout/fragment_to_clone_or_not.xml37
-rw-r--r--app/src/main/res/layout/password_row_layout.xml13
-rw-r--r--app/src/main/res/menu/pwdstore.xml5
-rw-r--r--app/src/main/res/values/strings.xml4
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>