Bladeren bron

Merge branch 'master' into newui

Iñigo Valentin 9 jaren geleden
bovenliggende
commit
eb9b2fdf88

+ 2 - 1
README.md

@@ -12,12 +12,13 @@ This features wil be only available during the city festivals.
 * Check out the festival schedule, showing events all around the city, and indicating their location.
 * Check out the schedule for the members of Gasteizko Margolariak, indicating the location of every event and activity...
 * ... but, since we are not known for our puntuality, check out the location of Gasteizko Margolariak in real time.
+* Approximate distanc eto important event around the city.
 
 
 ### Features for the rest of the year ###
 
 * Check out and be notified of all activities organized by gasteizzko margolariak.
-* View nd comment our blog.
+* View and comment our blog.
 * View and comment our gallery.
 
 

+ 3 - 2
app/src/main/java/com/ivalentin/margolariak/ActivityFutureLayout.java

@@ -82,7 +82,7 @@ public class ActivityFutureLayout extends Fragment implements OnMapReadyCallback
         final Cursor cursor;
 		String lang = GM.getLang();
 
-        cursor = db.rawQuery("SELECT id, title_" + lang+ " AS title, text_" + lang + " AS text, date, city, price FROM activity WHERE id = " + id + ";", null);
+        cursor = db.rawQuery("SELECT id, title_" + lang+ " AS title, text_" + lang + " AS text, date, city, price, permalink FROM activity WHERE id = " + id + ";", null);
         cursor.moveToFirst();
 
         //Get display elements
@@ -102,6 +102,7 @@ public class ActivityFutureLayout extends Fragment implements OnMapReadyCallback
         //Set fields
         tvTitle.setText(cursor.getString(1));
         ((MainActivity) getActivity()).setSectionTitle(cursor.getString(1));
+		((MainActivity) getActivity()).setShareLink(String.format(getString(R.string.share_with_title), cursor.getString(1)), GM.SHARE.ACTIVITIES + cursor.getString(6));
 		if (Build.VERSION.SDK_INT >= 19) {
 			wvText.setLayerType(View.LAYER_TYPE_HARDWARE, null);
 		}
@@ -291,7 +292,7 @@ public class ActivityFutureLayout extends Fragment implements OnMapReadyCallback
 
             //Set time
             try{
-                if (cursor.getString(5).length() == 0) {
+                if (cursor.getString(5) == null || cursor.getString(5).length() == 0) {
                     tvTime.setText(timeFormat.format(dateFormat.parse(cursor.getString(4))));
                 }
                 else {

+ 1 - 1
app/src/main/java/com/ivalentin/margolariak/ActivityLayout.java

@@ -195,7 +195,7 @@ public class ActivityLayout extends Fragment{
                 text = Html.fromHtml(cursorPast.getString(4)).toString();
             }
             else {
-                if (cursorPast.getString(5).length() < 1) {
+                if (cursorPast.getString(5) == null || cursorPast.getString(5).length() < 1) {
                     text = Html.fromHtml(cursorPast.getString(4)).toString();
                 } else {
                     text = Html.fromHtml(cursorPast.getString(5)).toString();

+ 5 - 9
app/src/main/java/com/ivalentin/margolariak/ActivityPastLayout.java

@@ -50,7 +50,7 @@ public class ActivityPastLayout extends Fragment {
         SQLiteDatabase db = SQLiteDatabase.openDatabase(getActivity().getDatabasePath(GM.DB.NAME).getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
         final Cursor cursor;
         String lang = GM.getLang();
-        cursor = db.rawQuery("SELECT id, title_" + lang+ " AS title, text_" + lang + " AS text, date, city, after_" + lang + " AS after FROM activity WHERE id = " + id + ";", null);
+        cursor = db.rawQuery("SELECT id, title_" + lang+ " AS title, text_" + lang + " AS text, date, city, after_" + lang + " AS after, permalink FROM activity WHERE id = " + id + ";", null);
         cursor.moveToFirst();
 
         //Get display elements
@@ -75,15 +75,11 @@ public class ActivityPastLayout extends Fragment {
         //Set fields
         tvTitle.setText(cursor.getString(1));
         ((MainActivity) getActivity()).setSectionTitle(cursor.getString(1));
-        if (cursor.getString(5) != null) {
-            if (cursor.getString(5).length() < 1) {
-                wvText.loadDataWithBaseURL(null, cursor.getString(2), "text/html", "utf-8", null);
-            } else {
-                wvText.loadDataWithBaseURL(null, cursor.getString(5), "text/html", "utf-8", null);
-            }
-        }
-        else{
+        ((MainActivity) getActivity()).setShareLink(String.format(getString(R.string.share_with_title), cursor.getString(1)), GM.SHARE.ACTIVITIES + cursor.getString(6));
+        if (cursor.getString(5) == null || cursor.getString(5).length() < 1) {
             wvText.loadDataWithBaseURL(null, cursor.getString(2), "text/html", "utf-8", null);
+        } else {
+            wvText.loadDataWithBaseURL(null, cursor.getString(5), "text/html", "utf-8", null);
         }
         tvDate.setText(GM.formatDate(cursor.getString(3) + " 00:00:00", lang, false));
         tvCity.setText(cursor.getString(4));

+ 8 - 2
app/src/main/java/com/ivalentin/margolariak/AlbumLayout.java

@@ -52,7 +52,7 @@ public class AlbumLayout extends Fragment {
         SQLiteDatabase db = SQLiteDatabase.openDatabase(getActivity().getDatabasePath(GM.DB.NAME).getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
         final Cursor cursor;
 		String lang = GM.getLang();
-        cursor = db.rawQuery("SELECT id, title_" + lang + " AS title, description_" + lang + " AS description FROM album WHERE id = " + id + ";", null);
+        cursor = db.rawQuery("SELECT id, title_" + lang + " AS title, description_" + lang + " AS description, permalink FROM album WHERE id = " + id + ";", null);
         cursor.moveToFirst();
 
         //Set album elements
@@ -67,8 +67,12 @@ public class AlbumLayout extends Fragment {
 		}
 
         tvTitle.setText(cursor.getString(1));
+		((MainActivity) getActivity()).setSectionTitle(cursor.getString(1));
+		((MainActivity) getActivity()).setShareLink(String.format(getString(R.string.share_with_title), cursor.getString(1)), GM.SHARE.GALLERY + cursor.getString(3));
+
 		final String albumName = cursor.getString(1);
-        if (cursor.getString(2).length() < 1){
+		final String albumPerm = cursor.getString(3);
+        if (cursor.getString(2) == null || cursor.getString(2).length() < 1){
             tvDescription.setVisibility(View.GONE);
         }
         else {
@@ -95,6 +99,7 @@ public class AlbumLayout extends Fragment {
 
             //Set title
             TextView tvTitleLeft = (TextView) entry.findViewById(R.id.tv_row_album_title_left);
+
 			if (imageCursor.getString(1) != null && imageCursor.getString(1).length() > 0) {
 				tvTitleLeft.setText(imageCursor.getString(1));
 			}
@@ -148,6 +153,7 @@ public class AlbumLayout extends Fragment {
 				int id = Integer.parseInt(((TextView) v.findViewById(R.id.tv_row_album_hidden_left)).getText().toString());
 				bundle.putInt("photo", id);
 				bundle.putString("albumName", albumName);
+				bundle.putString("albumPerm", albumPerm);
 				fragment.setArguments(bundle);
 
 				FragmentManager fm = AlbumLayout.this.getActivity().getFragmentManager();

+ 90 - 2
app/src/main/java/com/ivalentin/margolariak/GM.java

@@ -23,8 +23,16 @@ final class GM {
 	 */
 	final class DB {
 
+		/**
+		 * Name of the database.
+		 */
 		static final String NAME = "gm";
 
+		/**
+		 * Initial version of the database.
+		 */
+		static final int INITIAL_VERSION = 0;
+
 		/**
 		 * Column types
 		 */
@@ -605,9 +613,19 @@ final class GM {
 			static final String PREVIOUS_APP_VERSION = "previous_app_version";
 
 			/**
-			 * Key of the data to store if ther is a festival season..
+			 * Key of the data to store if ther is a festival season.
 			 */
 			static final String LABLANCA = "lablanca";
+
+			/**
+			 * Key that indicates if comments can be posted.
+			 */
+			static final String COMMENTS = "comments";
+
+			/**
+			 * Key that indicates if photos can be uploaded.
+			 */
+			static final String PHOTOS = "photos";
 		}
 
 		/**
@@ -630,6 +648,16 @@ final class GM {
 			 * Default value for the data that indicates if it's festival season.
 			 */
 			static final boolean LABLANCA = false;
+
+			/**
+			 * Default value for the key that indicates if comments can be posted.
+			 */
+			static final boolean COMMENTS = false;
+
+			/**
+			 * Default value for the key that indicates if photos can be uploaded.
+			 */
+			static final boolean PHOTOS = false;
 		}
 	}
 
@@ -689,7 +717,7 @@ final class GM {
 		/**
 		 * URL of the server.
 		 */
-		static final String SERVER = "http://margolariak.com";
+		static final String SERVER = "https://margolariak.com";
 	}
 
 	/**
@@ -865,6 +893,55 @@ final class GM {
 				static final String FORMAT = "json";
 			}
 		}
+
+		/**
+		 * Utilities for the COMMENT V1 API.
+		 */
+		static final class COMMENT {
+
+			/**
+			 * Path to the API.
+			 */
+			static final String PATH = "/API/v1/comment.php";
+
+			/**
+			 * Keys fotr the API parameters.
+			 */
+			static final class KEY {
+
+				/**
+				 * Key for the client identifier.
+				 */
+				static final String CLIENT = "client";
+
+				/**
+				 * Key for the user identifier.
+				 */
+				static final String USER = "user";
+
+				/**
+				 * Key for the action to perform with the API ("sync" or "version").
+				 */
+				static final String TARGET = "target";
+
+				/**
+				 * Key to indicate the format of the data for the API to send.
+				 */
+				static final String ID = "id";
+
+				/**
+				 * Key to indicate the comment's username.
+				 */
+				static final String USERNAME = "username";
+
+				/**
+				 * Key to indicate the text.
+				 */
+				static final String TEXT = "text";
+
+			}
+		}
+
 	}
 
 	/**
@@ -1096,6 +1173,17 @@ final class GM {
 		static final int ENTRY_MARGIN = 8;
 	}
 
+	/**
+	 * URLs to be shared.
+	 */
+	static final class SHARE {
+		static final String HOME = "http://www.margolariak.com";
+		static final String LABLANCA = HOME + "/lablanca/";
+		static final String ACTIVITIES = HOME + "/actividades/";
+		static final String BLOG = HOME + "/blog/";
+		static final String GALLERY = HOME + "/galeria/";
+	}
+
 	/**
 	 * Gets the language code for sql queries.
 	 * Only three values can be returned: es, eu, en.

+ 2 - 2
app/src/main/java/com/ivalentin/margolariak/HomeLayout.java

@@ -433,7 +433,7 @@ public class HomeLayout extends Fragment implements LocationListener {
 
 				//Set image
 				String image = cursor.getString(1);
-				if (image.length() > 0){
+				if (image != null && image.length() > 0){
 
 					//Check if image exists
 					File f;
@@ -655,7 +655,7 @@ public class HomeLayout extends Fragment implements LocationListener {
 
 			//Set text
 			String text;
-			if (cursor.getString(6).length() < 1) {
+			if (cursor.getString(6) == null || cursor.getString(6).length() < 1) {
 				text = Html.fromHtml(cursor.getString(4)).toString();
 			} else {
 				text = Html.fromHtml(cursor.getString(6)).toString();

+ 1 - 1
app/src/main/java/com/ivalentin/margolariak/LablancaLayout.java

@@ -77,7 +77,7 @@ public class LablancaLayout extends Fragment {
 		//Set image
 		ImageView headerImage = (ImageView) view.findViewById(R.id.iv_lablanca_header);
 		String image = cursor.getString(1);
-		if (image.length() > 0){
+		if (image != null && image.length() > 0){
 
 			//Check if image exists
 			File f;

+ 77 - 4
app/src/main/java/com/ivalentin/margolariak/MainActivity.java

@@ -77,6 +77,34 @@ public class MainActivity extends Activity {
 	 */
 	private GoogleApiClient client;
 
+	// Shareable URL
+	private String shareURL = GM.SHARE.HOME;
+	private String shareTitle = "";
+
+	/**
+	 * Sets the displayed section url and localized title.
+	 * Thy can be retrieved later with getShareLink() to share the URL.
+	 *
+	 * @param title The title of the displayed section.
+	 * @param url The URL of the current section.
+	 *
+	 * @see MainActivity#getShareLink();
+	 */
+	public void setShareLink(String title, String url){
+		shareTitle = title;
+		shareURL = url;
+	}
+
+	/**
+	 * Returns the url of the current sections and a title.
+	 * To be used with the share option.
+	 *
+	 * @return String array. Index 0 has the title of the section. Index 1 has the URL.
+	 */
+	public String[] getShareLink(){
+		return(new String[]{shareTitle, shareURL});
+	}
+
 	/**
 	 * Enables o disables the location section.
 	 *
@@ -99,13 +127,30 @@ public class MainActivity extends Activity {
 		}
 	}
 
-	//Not referenced in code.
+	/**
+	 * Opens and closes the app menu.
+	 * Not referenced in code.
+	 *
+	 * @param v Menu view.
+	 */
 	public void showMenu(View v) {
 		PopupMenu popup = new PopupMenu(this, v);
 		MenuInflater inflater = popup.getMenuInflater();
 		inflater.inflate(R.menu.menu, popup.getMenu());
 
 		popup.getMenu().getItem(0).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+			@Override
+			public boolean onMenuItemClick(MenuItem item) {
+				Intent sendIntent = new Intent();
+				sendIntent.setAction(Intent.ACTION_SEND);
+				sendIntent.putExtra(Intent.EXTRA_TEXT, getShareLink()[0] + "\n\n" + getShareLink()[1] + "\n\n");
+				sendIntent.setType("text/plain");
+				startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.share_with)));
+				return true;
+			}
+		});
+
+		popup.getMenu().getItem(1).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
 			@Override
 			public boolean onMenuItemClick(MenuItem item) {
 				Intent intent = new Intent(MainActivity.this, AboutActivity.class);
@@ -114,7 +159,7 @@ public class MainActivity extends Activity {
 			}
 		});
 
-		popup.getMenu().getItem(1).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+		popup.getMenu().getItem(2).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
 			@Override
 			public boolean onMenuItemClick(MenuItem item) {
 				Intent intent = new Intent(MainActivity.this, SponsorActivity.class);
@@ -123,7 +168,7 @@ public class MainActivity extends Activity {
 			}
 		});
 
-		popup.getMenu().getItem(2).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+		popup.getMenu().getItem(3).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
 			@Override
 			public boolean onMenuItemClick(MenuItem item) {
 				Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
@@ -146,6 +191,8 @@ public class MainActivity extends Activity {
 		FragmentTransaction ft = fm.beginTransaction();
 		Fragment fragment = null;
 		String title = "";
+		String shareURL = GM.SHARE.HOME;
+		String shareTitle = getString(R.string.share_home);
 		Bundle bundle = new Bundle();
 
 		//Get measures in dp
@@ -164,6 +211,8 @@ public class MainActivity extends Activity {
 			case GM.SECTION.HOME:
 				fragment = new HomeLayout();
 				title = getString(R.string.menu_home);
+				shareURL = GM.SHARE.HOME;
+				shareTitle = getString(R.string.share_home);
 				menuText[0].setTypeface(null, Typeface.BOLD);
 				menuImage[0].getLayoutParams().height = dp7;
 				break;
@@ -171,6 +220,8 @@ public class MainActivity extends Activity {
 			case GM.SECTION.LOCATION:
 				fragment = new LocationLayout();
 				title = getString(R.string.menu_location);
+				shareURL = GM.SHARE.HOME;
+				shareTitle = getString(R.string.share_home);
 				menuText[1].setTypeface(null, Typeface.BOLD);
 				menuImage[1].getLayoutParams().height = dp7;
 				break;
@@ -184,6 +235,8 @@ public class MainActivity extends Activity {
 					fragment = new LablancaNoFestivalsLayout();
 				}
 				title = getString(R.string.menu_lablanca);
+				shareURL = GM.SHARE.LABLANCA;
+				shareTitle = getString(R.string.share_lablanca);
 				menuText[2].setTypeface(null, Typeface.BOLD);
 				menuImage[2].getLayoutParams().height = dp7;
 				break;
@@ -193,6 +246,8 @@ public class MainActivity extends Activity {
 				bundle.putInt(GM.SCHEDULE.KEY, GM.SCHEDULE.MARGOLARIAK);
 				fragment.setArguments(bundle);
 				title = getString(R.string.menu_lablanca_schedule);
+				shareURL = GM.SHARE.LABLANCA;
+				shareTitle = getString(R.string.share_lablanca);
 				menuText[2].setTypeface(null, Typeface.BOLD);
 				menuImage[2].getLayoutParams().height = dp7;
 				break;
@@ -202,6 +257,8 @@ public class MainActivity extends Activity {
 				bundle.putInt(GM.SCHEDULE.KEY, GM.SCHEDULE.MARGOLARIAK);
 				fragment.setArguments(bundle);
 				title = getString(R.string.menu_lablanca_gm_schedule);
+				shareURL = GM.SHARE.LABLANCA;
+				shareTitle = getString(R.string.share_lablanca);
 				menuText[2].setTypeface(null, Typeface.BOLD);
 				menuImage[2].getLayoutParams().height = dp7;
 				break;
@@ -209,6 +266,8 @@ public class MainActivity extends Activity {
 			case GM.SECTION.ACTIVITIES:
 				fragment = new ActivityLayout();
 				title = getString(R.string.menu_activities);
+				shareURL = GM.SHARE.ACTIVITIES;
+				shareTitle = getString(R.string.share_activities);
 				menuText[3].setTypeface(null, Typeface.BOLD);
 				menuImage[3].getLayoutParams().height = dp7;
 				break;
@@ -216,6 +275,8 @@ public class MainActivity extends Activity {
 			case GM.SECTION.BLOG:
 				fragment = new BlogLayout();
 				title = getString(R.string.menu_blog);
+				shareURL = GM.SHARE.BLOG;
+				shareTitle = getString(R.string.share_blog);
 				menuText[4].setTypeface(null, Typeface.BOLD);
 				menuImage[4].getLayoutParams().height = dp7;
 				break;
@@ -223,6 +284,8 @@ public class MainActivity extends Activity {
 			case GM.SECTION.GALLERY:
 				fragment = new GalleryLayout();
 				title = getString(R.string.menu_blog);
+				shareURL = GM.SHARE.GALLERY;
+				shareTitle = getString(R.string.share_gallery);
 				menuText[5].setTypeface(null, Typeface.BOLD);
 				menuImage[5].getLayoutParams().height = dp7;
 				break;
@@ -233,6 +296,8 @@ public class MainActivity extends Activity {
 		//ft.addToBackStack(title);
 		ft.commit();
 		setSectionTitle(title);
+		//Set the shareable url
+		setShareLink(shareTitle, shareURL);
 	}
 
 	/**
@@ -360,7 +425,7 @@ public class MainActivity extends Activity {
 		});
 
 		//Get preferences
-		SharedPreferences sharedData = getSharedPreferences(GM.PREFERENCES.PREFERNCES, Context.MODE_PRIVATE);
+		SharedPreferences sharedData = getSharedPreferences(GM.DATA.DATA, Context.MODE_PRIVATE);
 		SharedPreferences.Editor dataEditor = sharedData.edit();
 
 		//If the user code is not set, generate one
@@ -632,6 +697,14 @@ public class MainActivity extends Activity {
 		new Sync(this, pbSync, ivSync).execute();
 	}
 
+	/**
+	 * Asks the activity to performa a sync.
+	 * Intended to be called from any screen.
+	 */
+	public void bgSync(){
+		new Sync(this).execute();
+	}
+
 	/**
 	 * Perform an initial sync before the app can be used.
 	 * A dialog will block the UI.

+ 6 - 2
app/src/main/java/com/ivalentin/margolariak/PhotoLayout.java

@@ -37,6 +37,7 @@ public class PhotoLayout extends Fragment {
 	private View view;
 
 	private String albumName;
+	private String albumPerm;
 
 	private Integer photos[];
 	private int position;
@@ -54,6 +55,7 @@ public class PhotoLayout extends Fragment {
 		//Get bundled id
 		Bundle bundle = this.getArguments();
 		albumName = bundle.getString("albumName", "");
+		albumPerm = bundle.getString("albumPerm", "");
 		int id = bundle.getInt("photo", -1);
 		if (id == -1) {
 			Log.e("Photo error", "No such photo: " + id);
@@ -85,6 +87,9 @@ public class PhotoLayout extends Fragment {
 			}
 		});
 
+		//Set title and share link
+		((MainActivity) getActivity()).setShareLink(String.format(getString(R.string.share_with_title), albumName), GM.SHARE.GALLERY + albumPerm);
+
 		populate(id, view);
 
 		return view;
@@ -123,9 +128,8 @@ public class PhotoLayout extends Fragment {
 	 */
 	private Integer[] loadPhotos(int id){
 
-		SQLiteDatabase db = SQLiteDatabase.openDatabase(getActivity().getDatabasePath(GM.DB.NAME).getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
-
 		//Get album id for the photo
+		SQLiteDatabase db = SQLiteDatabase.openDatabase(getActivity().getDatabasePath(GM.DB.NAME).getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
 		Cursor cAlbum = db.rawQuery("SELECT album FROM photo_album WHERE photo = " + id + ";", null);
 		cAlbum.moveToFirst();
 		int album = cAlbum.getInt(0);

+ 62 - 52
app/src/main/java/com/ivalentin/margolariak/PostComment.java

@@ -1,6 +1,7 @@
 package com.ivalentin.margolariak;
 
 import android.annotation.SuppressLint;
+import android.app.Activity;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.database.sqlite.SQLiteDatabase;
@@ -15,8 +16,11 @@ import android.widget.LinearLayout;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.util.Date;
@@ -36,7 +40,7 @@ class PostComment extends AsyncTask<String, String, Integer> {
 
     private int code = 404;
 
-    public PostComment(String type, String user, String text, String language, int id, LinearLayout form, LinearLayout list, Context context) {
+    PostComment(String type, String user, String text, String language, int id, LinearLayout form, LinearLayout list, Context context) {
         super();
         this.type = type;
         this.user = user;
@@ -75,22 +79,23 @@ class PostComment extends AsyncTask<String, String, Integer> {
         String urlParams;
         try {
 
-            urlParams = "user=" + URLEncoder.encode(user) + "&text=" + URLEncoder.encode(text);
-            switch (type){
+            urlParams = "username=" + URLEncoder.encode(user) + "&text=" + URLEncoder.encode(text);
+            urlParams = urlParams + "&id=" + id;
+            switch (type) {
                 case "blog":
-                    urlParams = urlParams + "&post=" + id;
+                    urlParams = urlParams + "&target=post";
                     break;
                 case "galeria":
-                    urlParams = urlParams + "&photo=" + id;
+                    urlParams = urlParams + "&target=photo";
                     break;
                 case "actividades":
-                    urlParams = urlParams + "&activity=" + id;
+                    urlParams = urlParams + "&target=activity";
                     break;
                 default:
                     Log.e("Comment error", "Unknown section: " + type);
                     return -1;
             }
-            switch (language){
+            switch (language) {
                 case "es":
                     urlParams = urlParams + "&lang=es";
                     break;
@@ -100,53 +105,54 @@ class PostComment extends AsyncTask<String, String, Integer> {
                 default:
                     urlParams = urlParams + "&lang=en";
             }
-            urlParams = urlParams + "&from=app&code=" + userCode;
-            byte[] postData       = urlParams.getBytes("UTF-8");
-            int    postDataLength = postData.length;
-            String request        = GM.API.SERVER + "/" + type + "/comment.php";
-            url            = new URL( request );
-            HttpURLConnection conn= (HttpURLConnection) url.openConnection();
-            conn.setDoOutput( true );
-            conn.setInstanceFollowRedirects( false );
-            conn.setRequestMethod( "POST" );
-            conn.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded");
-            conn.setRequestProperty( "charset", "utf-8");
-            conn.setRequestProperty( "Content-Length", Integer.toString( postDataLength ));
-            conn.setUseCaches( false );
-            DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
-            wr.write(postData);
-            conn.connect();
-
-            code = conn.getResponseCode();
-            Log.d("Comment status", "" + code);
-
-            if (code == 200){
-                //Insert into local db
-                SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(GM.DB.NAME).getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
-                String table = "";
-                String item = "";
-                switch (type){
-                    case "blog":
-                        table = "post_comment";
-                        item = "post";
-                        break;
-                    case "galeria":
-                        table = "photo_comment";
-                        item = "photo";
-                        break;
-                    case "actividades":
-                        table = "activity_comment";
-                        item = "activity";
-                        break;
-                }
-                db.execSQL("INSERT INTO " + table + " (" + item + ", text, username, lang, dtime) VALUES (" + id + ", '" + text + "', '" + user + "', '" + language + "', datetime('NOW'));");
-                db.close();
+            urlParams = urlParams + "&client=" + GM.API.CLIENT + "&user=" + userCode;
+
+            String uri = GM.API.SERVER + GM.API.COMMENT.PATH + "?" + urlParams;
+            url = new URL(uri);
+			Log.e("URI", uri);
+
+            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+
+            code = urlConnection.getResponseCode();
+
+            switch (code) {
+                case 400:    //Client error: Bad request
+                    Log.e("COMMENT", "The server returned a 400 code (Client Error: Bad request) for the url \"" + uri + "\"");
+					return(-400);
+                case 403:    //Client error: Forbidden
+                    Log.e("COMMENT", "The server returned a 403 code (Client Error: Forbidden) for the url \"" + uri + "\"");
+					return(-403);
+                case 200:    //Success: OK
+                    Log.d("COMMENT", "The server returned a 200 code (Success: OK) for the url \"" + uri + "\".");
+					break;
+				default:
+					Log.e("COMMENT", "The server returned a " + code + " code for the url \"" + uri + "\".");
+					return(-6);
             }
 
-        } catch (Exception e) {
-            Log.e("Error posting: ", e.getMessage());
         }
-        return code;
+		catch (UnsupportedEncodingException e) {
+            Log.e("COMMENT", "Unable to post comment (UnsupportedEncodingException): " + e.toString());
+			return -2;
+        }
+		catch (ProtocolException e) {
+            Log.e("COMMENT", "Unable to post comment (ProtocolException): " + e.toString());
+			return -3;
+        }
+		catch (MalformedURLException e) {
+            Log.e("COMMENT", "Unable to post comment (MalformedURLException): " + e.toString());
+			return -4;
+        }
+		catch (IOException e) {
+            Log.e("COMMENT", "Unable to post comment (IOException): " + e.toString());
+			return -5;
+        }
+		catch (Exception e) {
+            Log.e("COMMENT", "Unable to post comment: " + e.toString());
+			return -1;
+        }
+
+		return 0;
     }
 
 
@@ -167,6 +173,10 @@ class PostComment extends AsyncTask<String, String, Integer> {
 
             //TODO: Update counter
 
+			//Perform a sync
+			((MainActivity) context).bgSync();
+
+
             //Insert comment in list
             LayoutInflater factory = LayoutInflater.from(context);
             LinearLayout entry = (LinearLayout) factory.inflate(R.layout.row_comment, null);

+ 2 - 1
app/src/main/java/com/ivalentin/margolariak/PostLayout.java

@@ -60,7 +60,7 @@ public class PostLayout extends Fragment {
         SQLiteDatabase db = SQLiteDatabase.openDatabase(getActivity().getDatabasePath(GM.DB.NAME).getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
         final Cursor cursor;
         String lang = GM.getLang();
-        cursor = db.rawQuery("SELECT id, title_" + lang+ " AS title, text_" + lang + " AS text, dtime FROM post WHERE id = " + id + ";", null);
+        cursor = db.rawQuery("SELECT id, title_" + lang+ " AS title, text_" + lang + " AS text, dtime, permalink FROM post WHERE id = " + id + ";", null);
         cursor.moveToFirst();
 
         //Get display elements
@@ -88,6 +88,7 @@ public class PostLayout extends Fragment {
         //Set fields
         tvTitle.setText(cursor.getString(1));
         ((MainActivity) getActivity()).setSectionTitle(cursor.getString(1));
+        ((MainActivity) getActivity()).setShareLink(String.format(getString(R.string.share_with_title), cursor.getString(1)), GM.SHARE.BLOG + cursor.getString(4));
         wvText.loadDataWithBaseURL(null, cursor.getString(2), "text/html", "utf-8", null);
         tvDate.setText(GM.formatDate(cursor.getString(3), lang, true));
 

+ 5 - 4
app/src/main/java/com/ivalentin/margolariak/ScheduleLayout.java

@@ -112,6 +112,7 @@ public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
 			((MainActivity) getActivity()).setSectionTitle(view.getContext().getString(R.string.menu_lablanca_schedule));
 		else
 			((MainActivity) getActivity()).setSectionTitle(view.getContext().getString(R.string.menu_lablanca_gm_schedule));
+		((MainActivity) getActivity()).setShareLink(getString(R.string.share_lablanca), GM.SHARE.LABLANCA);
 
 		//Populate the dates array
 		SQLiteDatabase db = SQLiteDatabase.openDatabase(getActivity().getDatabasePath(GM.DB.NAME).getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY);
@@ -308,7 +309,7 @@ public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
 
 			//Set description
 			tvRowDesc = (TextView) entry.findViewById(R.id.tv_row_schedule_description);
-			if (cursor.getString(2).length() <= 0 || cursor.getString(2).equals(cursor.getString(1))) {
+			if (cursor.getString(2) == null || cursor.getString(2).length() <= 0 || cursor.getString(2).equals(cursor.getString(1))) {
 				tvRowDesc.setVisibility(View.GONE);
 			} else {
 				tvRowDesc.setText(cursor.getString(2));
@@ -320,7 +321,7 @@ public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
 
 			//Set address
 			tvRowAddress = (TextView) entry.findViewById(R.id.tv_row_schedule_address);
-			if (cursor.getString(7).length() <= 0 || cursor.getString(7).equals(cursor.getString(6))) {
+			if (cursor.getString(7) == null || cursor.getString(7).length() <= 0 || cursor.getString(7).equals(cursor.getString(6))) {
 				tvRowAddress.setVisibility(View.GONE);
 			} else {
 				tvRowAddress.setText(cursor.getString(7));
@@ -410,7 +411,7 @@ public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
 			markerName = cursor.getString(1);
 			
 			//Set description
-			if (cursor.getString(2).length() > 0) {
+			if (cursor.getString(2) != null && cursor.getString(2).length() > 0) {
 				tvDescription.setText(cursor.getString(2));
 			}
 			else{
@@ -477,7 +478,7 @@ public class ScheduleLayout extends Fragment implements OnMapReadyCallback{
 			
 			//Set time
 			try{
-				if (cursor.getString(5).length() == 0) {
+				if (cursor.getString(5) == null || cursor.getString(5).length() == 0) {
 					tvTime.setText(timeFormat.format(dateFormat.parse(cursor.getString(4))));
 				}
 				else {

+ 92 - 8
app/src/main/java/com/ivalentin/margolariak/Sync.java

@@ -19,11 +19,15 @@ import android.content.SharedPreferences;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
 import android.os.AsyncTask;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.Window;
+import android.view.WindowManager;
 import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.ProgressBar;
@@ -88,7 +92,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 			doProgress = true;
 
 		}
-		Log.d("Sync", "Starting full sync");
+		Log.d("SYNC", "Starting full sync");
 	}
 	
 	/**
@@ -114,7 +118,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 			//Check db version again
 			SQLiteDatabase db = myContextRef.openOrCreateDatabase(GM.DB.NAME, Activity.MODE_PRIVATE, null);
 			if (db.isReadOnly()){
-				Log.e("Db ro", "Database is locked and in read only mode. Skipping sync.");
+				Log.e("SYNC", "Database is locked and in read only mode. Skipping sync.");
 				return;
 			}
 
@@ -128,7 +132,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 			db.close();
 
 			//If the database is on it's initial version (i.e: There is no data, new or old)
-			if (true){ //TODO dbVersion == GM.DATA.DEFAULT.DEFAULT_PREF_DB_VERSION){
+			if (dbVersion == GM.DB.INITIAL_VERSION){
 
 				Log.e("SYNC", "Full sync failed");
 
@@ -149,7 +153,17 @@ class Sync extends AsyncTask<Void, Void, Void> {
 					activity.finish();
 					}
 				});
-				
+
+				//Set dialog parameters
+				WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
+				//noinspection ConstantConditions
+				lp.copyFrom(dial.getWindow().getAttributes());
+				lp.width = WindowManager.LayoutParams.MATCH_PARENT;
+				lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
+				lp.gravity = Gravity.CENTER;
+				dial.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+				dial.getWindow().setAttributes(lp);
+
 				//Show the dialog
 				dial.show();
 			}
@@ -269,6 +283,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 	 *
 	 * @return False if there were errors, true otherwise.
 	 */
+	@SuppressWarnings("unused")
 	private boolean recreateDb(SQLiteDatabase db) {
 		boolean result = true;
 		try {
@@ -396,7 +411,9 @@ class Sync extends AsyncTask<Void, Void, Void> {
 				db.execSQL(GM.DB.QUERY.CREATE.VERSION);
 				db.execSQL(GM.DB.QUERY.EMPTY.VERSION);
 				for (int i = 0; i < totalVersions; i ++){
-					db.execSQL("INSERT INTO version VALUES ('" + keys[i] + "', " + values[i] + ");");
+					if (!"all".equals(keys[i])) {
+						db.execSQL("INSERT INTO version VALUES ('" + keys[i] + "', " + values[i] + ");");
+					}
 				}
 			}
 			else{
@@ -455,6 +472,66 @@ class Sync extends AsyncTask<Void, Void, Void> {
 		return result;
 	}
 
+	/**
+	 * When the table "settings cames up, dont make a table, but store required
+	 * values as data.
+	 *
+	 * @param settings JSON string with the contents of the "settings" table.
+	 * @return true if values could be saved, false otherwise.
+	 */
+	private boolean saveSettings(String settings){
+
+		SharedPreferences sharedData = myContextRef.getSharedPreferences(GM.DATA.DATA, Context.MODE_PRIVATE);
+		SharedPreferences.Editor editor = sharedData.edit();
+		try{
+			String value;
+			if (settings.contains("\"name\":\"comments\",\"value\":\"")){
+				value = settings.substring(settings.indexOf("\"name\":\"comments\",\"value\":\"") + 27, settings.indexOf("\"name\":\"comments\",\"value\":\"") + 28);
+				if ("0".equals(value) || "1".equals(value)){
+					Log.d("SYNC", "Setting found: comments = " + value);
+					if ("0".equals(value)) {
+						editor.putBoolean(GM.DATA.KEY.COMMENTS, false);
+					}
+					else {
+						editor.putBoolean(GM.DATA.KEY.COMMENTS, true);
+					}
+				}
+			}
+			if (settings.contains("\"name\":\"festivals\",\"value\":\"")){
+				value = settings.substring(settings.indexOf("\"name\":\"festivals\",\"value\":\"") + 28, settings.indexOf("\"name\":\"festivals\",\"value\":\"") + 29);
+				if ("0".equals(value) || "1".equals(value)){
+					Log.d("SYNC", "Setting found: lablanca = " + value);
+					if ("0".equals(value)) {
+						editor.putBoolean(GM.DATA.KEY.LABLANCA, false);
+					}
+					else {
+						editor.putBoolean(GM.DATA.KEY.LABLANCA, true);
+					}
+				}
+			}
+			if (settings.contains("\"name\":\"photos\",\"value\":\"")){
+				value = settings.substring(settings.indexOf("\"name\":\"photos\",\"value\":\"") + 25, settings.indexOf("\"name\":\"photos\",\"value\":\"") + 26);
+				if ("0".equals(value) || "1".equals(value)){
+					Log.d("SYNC" ,"Setting found: photos = " + value);
+					if ("0".equals(value)) {
+						editor.putBoolean(GM.DATA.KEY.PHOTOS, false);
+					}
+					else {
+						editor.putBoolean(GM.DATA.KEY.PHOTOS, true);
+					}
+				}
+			}
+
+			editor.apply();
+			Log.d("SYNC", "Settings saved.");
+			return true;
+		}
+		catch (Exception ex){
+			editor.apply();
+			Log.e("SYNC", "Unable to save settings: " + ex.toString());
+			return false;
+		}
+	}
 
 
 
@@ -468,6 +545,13 @@ class Sync extends AsyncTask<Void, Void, Void> {
 	 * @return False if there were errors, true otherwise.
 	 */
 	private boolean saveTable(SQLiteDatabase db, String table, String data) {
+
+		//If settings table, do something else
+		if ("settings".equals(table)){
+			Log.d("SYNC", "Got the settings table. Special treatment...");
+			return saveSettings(data);
+		}
+
 		int type, i;
 		JSONObject jsonObj;
 		String[] values = new String[99];
@@ -552,11 +636,11 @@ class Sync extends AsyncTask<Void, Void, Void> {
 
 			}
 			catch (JSONException e) {
-				Log.e("SYNC", "Error parsing table '" + table + "': " + e.toString());
+				Log.e("SYNC", "Error parsing table '" + table + "' (JSONException): " + e.toString());
 				return false;
 			}
 			catch (Exception ex) {
-				Log.e("SYNC", "Error inserting data from remote table " + table + " into the local db: " + ex.toString());
+				Log.e("SYNC", "Error parsing table '" + table + "': " + ex.toString());
 				return false;
 			}
 
@@ -571,7 +655,7 @@ class Sync extends AsyncTask<Void, Void, Void> {
 				db.execSQL(queries.get(i));
 			}
 		} catch (Exception ex) {
-			Log.e("SYNC", "Error inserting data from remote table " + table + " into the local db: " + ex.toString().substring(18 * ex.toString().length() / 20));
+			Log.e("SYNC", "Error inserting data from remote table " + table + " into the local db: " + ex.toString());
 
 			//I don't put a 'return false;' here because I dont want to loose the whole table for just one row.
 		}

+ 11 - 10
app/src/main/res/layout/dialog_sync.xml

@@ -1,9 +1,10 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="fill_parent"
-              android:layout_height="wrap_content"
-              android:background="@drawable/section"
-              android:orientation="vertical"
-              android:layout_margin="20dp">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/section"
+    android:orientation="vertical"
+    android:layout_margin="20dp">
 
     <TextView
         android:id="@+id/textView1"
@@ -24,7 +25,7 @@
     <LinearLayout
         android:orientation="vertical"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:layout_margin="8dp"
         android:padding="7dp"
         android:background="@drawable/entry">
@@ -32,10 +33,10 @@
         <ProgressBar
             android:id="@+id/pb_sync_dialog"
             style="?android:attr/progressBarStyleLarge"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
             android:layout_gravity="center_horizontal"
-            android:layout_marginTop="20dp"/>
+            android:layout_marginTop="20dp"
+            android:layout_height="60dp"/>
 
         <TextView
             android:id="@+id/tv_dialog_sync_text"

+ 21 - 21
app/src/main/res/layout/dialog_sync_failed.xml

@@ -4,31 +4,31 @@
     android:layout_height="wrap_content"
     android:background="@drawable/section"
     android:orientation="vertical"
-    android:paddingBottom="10dp" >
+    android:layout_margin="20dp">
 
-    <LinearLayout
+    <TextView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:padding="7dp">
-
-        <TextView
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/dialog_sync_failed_title"
-            android:textAppearance="@android:style/TextAppearance.Large"
-            android:layout_marginBottom="10dp"
-            android:textStyle="bold"/>
-
-        <TextView
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:text="@string/dialog_sync_failed_text"
-            android:background="@drawable/entry"
-            android:padding="7dp"
-            android:textAppearance="@android:style/TextAppearance.Medium"/>
+        android:text="@string/dialog_sync_failed_title"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:textStyle="bold"
+        android:background="@drawable/section_title"
+        android:paddingBottom="4dp"
+        android:paddingEnd="10dp"
+        android:paddingLeft="20dp"
+        android:paddingRight="10dp"
+        android:paddingStart="20dp"
+        android:paddingTop="4dp"
+        android:textColor="@color/section_title"/>
 
-    </LinearLayout>
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="@android:style/TextAppearance.Medium"
+        android:text="@string/dialog_sync_failed_text"
+        android:layout_margin="8dp"
+        android:padding="7dp"
+        android:background="@drawable/entry"/>
 
     <Button
         android:id="@+id/bt_dialog_sync_failed_close"

+ 3 - 0
app/src/main/res/menu/menu.xml

@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/pop_menu_share"
+        android:title="@string/pop_menu_share" />
     <item
         android:id="@+id/pop_menu_about"
         android:title="@string/pop_menu_about" />

+ 12 - 1
app/src/main/res/values-en/strings.xml

@@ -65,7 +65,7 @@
 	<string name="settings_about">About us</string>
 	<string name="settings_transparency">Transparency</string>
 	<string name="settings_license_content">Copyright 2016 Iñigo Valentin&lt;br/>&lt;br/>This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.&lt;br/>&lt;br/>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at http://www.gnu.org/licenses/.&lt;br/>&lt;br/>The name "Gasteizko Margolariak" and its logotype are property of Gasteizko Margolariak.&lt;br/>&lt;br/>&lt;br/>&lt;div style="background-color:#bbbbbb;padding:6px;border-radius:5px;border-style:solid;border-width:2px;border-color:#333333;text-align:center;">You can get the source code for this project at &lt;a href="https://github.com/Seavenois/GM">Github&lt;/a>&lt;/div></string>
-	<string name="settings_privacy_content"><![CDATA[In Gasteizko Margolariak we respect your privacy. We don\'t collect ANY data from our users, including personal information, location, shopping habits, sexual preferences, favourite colour, first love\'s name… ANY.<br/><br/>In order of making you believe us, we\'ll explain what we DO store:<br/><br/><ul><li>A randomly generated user code, unique to your device. This is necessary to sync content with aur database, so you can get info about our post, activities... But it\'s done in a way that won\'t allow un to identify you as a person with that number.</li><li>When commenting on a photo ar an entry, we store your current IP address. This is incredibly useful for us to know how many actual people are posting comments, and it also makes imposible for us to identify you as a person.</li></ul>]]></string>
+	<string name="settings_privacy_content"><![CDATA[In Gasteizko Margolariak we respect your privacy. We don\'t collect ANY data from our users, including personal information, location, shopping habits, sexual preferences, favourite colour, first love\'s name… ANY.<br/><br/>In order of making you believe us, we\'ll explain what we DO store:<br/><br/><ul><li>A randomly generated user code, unique to your device. This is necessary to sync content with aur database, so you can get info about our post, activities But it\'s done in a way that won\'t allow un to identify you as a person with that number.</li><li>When commenting on a photo ar an entry, we store your current IP address. This is incredibly useful for us to know how many actual people are posting comments, and it also makes imposible for us to identify you as a person.</li></ul>]]></string>
 	<string name="settings_about_content">La Asociación Cultural Gasteizko Margolariak nace en el año 2013 con la idea de estimular la participación ciudadana y fortalecer la cultura y las tradiciones de Vitoria-Gasteiz.&lt;br/>&lt;br/>En nuestro nombre se refleja un barrio en el que las calles nos recuerdan a grandes pintores: el barrio de San Martín. Estamos representados en los barrios, y creemos que son la esencia de esta ciudad.&lt;br/>&lt;br/>Nos convertimos en Cuadrilla de Blusas y Neskas en 2013, y en ese mismo año, miembros de la Comisión de Blusas y Neskas.&lt;br/>&lt;br/>Desde entonces no hemos hecho más que crecer junto con todos los que han decidido, año tras año, apostar por nosotros.</string>
 	<string name="settings_transparency_content">¿Te preocupa saber dónde va tu dinero? En Gasteizko Margolariak queremos que estés tranquilo.&lt;br/>&lt;br/>Muchas de nuestras actividades son gratuitas. Otras, como las fiestas de La Blanca, tienen una cuota de inscripción. Gasteizko Margolariak no es una empresa, es una Asociación Cultural, y como tal, no tenemos beneficios.&lt;br/>&lt;br/>Queremos ser transparentes, y por eso, empezando en 2016, pondremos a tu disposición nuestras cuentas de manera online, para que sepas que cada euro se reinvierte en tí.</string>
 
@@ -161,6 +161,7 @@
 	<string name="dialog_sync_failed_close">Close</string>
 	<string name="lablanca_nofestivals">Las Fiestas de La Blanca. Esos días, del 4 al 9 de agosto, en los que Vitoria-Gasteiz se transforma. Se llena de color y alegría, y en cada esquina puedes encontrar actividades y espectáculos. Todos las estamos esperando.\n\nPor desgracia, aún hay que esperar más.\n\nNosotros ya estamos trabajando en ello. Tan pronto como vayamos sabiendo más, aquí iremos publicando nuestro programa y otra información sobre las fiestas.</string>
 	<string name="home_section_location_text_calculating">Calculating distance…</string>
+	<string name="pop_menu_share">Share</string>
 	<string name="pop_menu_about">About us</string>
 	<string name="pop_menu_settings">Settings</string>
 	<string name="pop_menu_sponsors">-</string>
@@ -182,4 +183,14 @@
 	<string name="preferences_sync_sync_off">Background sync is disabled</string>
 	<string name="changelog">Changelog</string>
 
+	<!-- Share menu -->
+	<string name="share">Share</string>
+	<string name="share_with">Share using…</string>
+	<string name="share_home">Gasteizko Margolariak</string>
+	<string name="share_lablanca">La Blanca - Gasteizko Margolariak</string>
+	<string name="share_activities">Activities - Gasteizko Margolariak</string>
+	<string name="share_blog">Blog - Gasteizko Margolariak</string>
+	<string name="share_gallery">Gallery - Gasteizko Margolariak</string>
+	<string name="share_with_title">%s - Gasteizko Margolariak</string>
+
 </resources>

+ 13 - 2
app/src/main/res/values-eu-rES/strings.xml

@@ -150,7 +150,7 @@
 	<string name="settings_license_content"><![CDATA[Copyright 2016 Iñigo Valentin<br/><br/>This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation.<br/><br/>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at http://www.gnu.org/licenses/.<br/><br/>The name "Gasteizko Margolariak" and its logotype are property of Gasteizko Margolariak.<br/><br/><br/><div style="background-color:#bbbbbb;padding:6px;border-radius:5px;border-style:solid;border-width:2px;border-color:#333333;text-align:center;">You can get the source code for this project at <a href="https://github.com/Seavenois/GM">Github</a></div>]]></string>
 	<string name="settings_privacy">Pribazitatea</string>
 	<string name="settings_transparency">Transparentzia</string>
-	<string name="settings_privacy_content"><![CDATA[En Gasteizko Margolariak respetamos tu privacidad. No guardamos NINGÚN dato de nuestros usuarios, incluyendo información personal, localización, hábitos de compra, preferencias sexuales, color favorito, nombre de su primer amor… NINGUNO.<br/><br/>Para que nos creas, te explicamos lo que sí almacenamos:<br/><br/><ul><li>Un código de usuario, generado aleatoriamente, único para tu dispositivo. Esto es necesario para sincronizar la aplicación con nuestra base de datos y poder descargar los últimos posts, actividades... Pero esta hecho de tal manera que no podamos identificarte como persona a través de ese código.</li><li>Al publicar un comentario en una entrada o una foto, guardaremos temporalmente (120 minutos, lo justo para procesar información) tu dirección IP. Esto nos es súper útil para saber cuántas personas diferentes publican comentarios, y tampoco nos permite identificarte como persona.</li></ul>]]></string>
+	<string name="settings_privacy_content"><![CDATA[En Gasteizko Margolariak respetamos tu privacidad. No guardamos NINGÚN dato de nuestros usuarios, incluyendo información personal, localización, hábitos de compra, preferencias sexuales, color favorito, nombre de su primer amor… NINGUNO.<br/><br/>Para que nos creas, te explicamos lo que sí almacenamos:<br/><br/><ul><li>Un código de usuario, generado aleatoriamente, único para tu dispositivo. Esto es necesario para sincronizar la aplicación con nuestra base de datos y poder descargar los últimos posts, actividades Pero esta hecho de tal manera que no podamos identificarte como persona a través de ese código.</li><li>Al publicar un comentario en una entrada o una foto, guardaremos temporalmente (120 minutos, lo justo para procesar información) tu dirección IP. Esto nos es súper útil para saber cuántas personas diferentes publican comentarios, y tampoco nos permite identificarte como persona.</li></ul>]]></string>
 	<string name="settings_transparency_content"><![CDATA[¿Te preocupa saber dónde va tu dinero? En Gasteizko Margolariak queremos que estés tranquilo.<br/><br/>Muchas de nuestras actividades son gratuitas. Otras, como las fiestas de La Blanca, tienen una cuota de inscripción. Gasteizko Margolariak no es una empresa, es una Asociación Cultural, y como tal, no tenemos beneficios.<br/><br/>Queremos ser transparentes, y por eso, empezando en 2016, pondremos a tu disposición nuestras cuentas de manera online, para que sepas que cada euro se reinvierte en tí.]]></string>
 	<string name="dialog_sync_text_0">Locating Don Margolo&#8230;</string>
 	<string name="dialog_sync_text_1">Starting up the van&#8230;</string>
@@ -166,7 +166,8 @@
 	<string name="settings_notification_off">No recibir notificaciones</string>
 	<string name="settings_notification_on">Recibir notificaciones</string>
 	<string name="home_section_location_text_calculating">Calculando distancia…</string>
-	<string name="pop_menu_about">About us</string>
+	<string name="pop_menu_share">Bitarte</string>
+	<string name="pop_menu_about">Gu</string>
 	<string name="pop_menu_settings">Ajustes</string>
 	<string name="pop_menu_sponsors">-</string>
 	<string name="preferences_info">Informazioa</string>
@@ -187,4 +188,14 @@
 	<string name="preferences_sync_sync_off">Sincronización desactivada</string>
 	<string name="changelog">Changelog</string>
 
+	<!-- Share menu -->
+	<string name="share">Compartir</string>
+	<string name="share_with">Enviar con…</string>
+	<string name="share_home">Gasteizko Margolariak</string>
+	<string name="share_lablanca">Andre Zuria - Gasteizko Margolariak</string>
+	<string name="share_activities">Aktibitateak - Gasteizko Margolariak</string>
+	<string name="share_blog">La Blanca - Gasteizko Margolariak</string>
+	<string name="share_gallery">Galeria - Gasteizko Margolariak</string>
+	<string name="share_with_title">%s - Gasteizko Margolariak</string>
+
 </resources>

+ 12 - 1
app/src/main/res/values/strings.xml

@@ -201,12 +201,23 @@
 	<string name="preferences_info_feedback">Feedback</string>
 	<string name="preferences_info_feedback_summary">Enviar información anónima al desarrollador</string>
 
+	<!-- Share menu -->
+	<string name="share">Comartir</string>
+	<string name="share_with">Enviar con…</string>
+	<string name="share_home">Gasteizko Margolariak</string>
+	<string name="share_lablanca">La Blanca - Gasteizko Margolariak</string>
+	<string name="share_activities">Actividades - Gasteizko Margolariak</string>
+	<string name="share_blog">Blog - Gasteizko Margolariak</string>
+	<string name="share_gallery">Galería - Gasteizko Margolariak</string>
+	<string name="share_with_title">%s - Gasteizko Margolariak</string>
+
 	<string name="eur" translatable="false">€</string>
 	<string name="Kb" translatable="false"> Kb</string>
 	<string name="Mb" translatable="false"> Mb</string>
+	<string name="pop_menu_share">Compartir</string>
 	<string name="pop_menu_about">Sobre nosotros</string>
 	<string name="preferences_info_source">Código fuente</string>
 	<string name="changelog">Changelog</string>
-	<string name="empty" translatable="false"></string>
+	<string name="empty" translatable="false"> </string>
 
 </resources>