From e27cd6a147193572a4c0fafd9606ae60c80981a9 Mon Sep 17 00:00:00 2001 From: PhotonQyv Date: Fri, 1 Sep 2017 14:02:09 +0100 Subject: [PATCH 1/2] Sorting out extracts for shared URLs. --- .../mastodon/activities/TootActivity.java | 18 ++- .../etalab/mastodon/helper/ParserUtils.java | 140 ++++++++++++++++++ 2 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/fr/gouv/etalab/mastodon/helper/ParserUtils.java diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java index 2390cbccf..fad578b84 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java @@ -100,6 +100,7 @@ import fr.gouv.etalab.mastodon.client.PatchBaseImageDownloader; import fr.gouv.etalab.mastodon.drawers.AccountsSearchAdapter; import fr.gouv.etalab.mastodon.drawers.DraftsListAdapter; import fr.gouv.etalab.mastodon.helper.Helper; +import fr.gouv.etalab.mastodon.helper.ParserUtils; import fr.gouv.etalab.mastodon.interfaces.OnPostStatusActionInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveAttachmentInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearcAccountshInterface; @@ -118,7 +119,7 @@ import static fr.gouv.etalab.mastodon.helper.Helper.changeDrawableColor; * Toot activity class */ -public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAccountshInterface, OnRetrieveAttachmentInterface, OnPostStatusActionInterface { +public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAccountshInterface, OnRetrieveAttachmentInterface, OnPostStatusActionInterface, ParserUtils.ParserListener { private String visibility; @@ -241,6 +242,14 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc tootReply = b.getParcelable("tootReply"); sharedContent = b.getString("sharedContent", null); sharedSubject = b.getString("sharedSubject", null); + + // ACTION_SEND_TEXT route + if (sharedContent != null) + { + // Do Extract from URL here + final ParserUtils parser = new ParserUtils(this); + } + // ACTION_SEND route if (b.getInt("uriNumber", 0) == 1) { @@ -1313,5 +1322,12 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc } } + @Override + public void onReceiveHeaderInfo(ParserUtils.HeaderInfo headerInfo) { + } + @Override + public void onErrorHeaderInfo() { + Toast.makeText(this.getApplicationContext(), "An error has occurred.", Toast.LENGTH_SHORT).show(); + } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/ParserUtils.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ParserUtils.java new file mode 100644 index 000000000..589dea808 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ParserUtils.java @@ -0,0 +1,140 @@ +package fr.gouv.etalab.mastodon.helper; + +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; +import android.os.AsyncTask; +import android.text.TextUtils; +import android.util.Log; +import android.util.Patterns; +import android.webkit.URLUtil; + +import org.jsoup.Connection; +import org.jsoup.Jsoup; +import org.jsoup.helper.HttpConnection; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; + +import static com.keylesspalace.tusky.util.StringUtils.QUOTE; + +/** + * Inspect and get the information from a URL. + */ +public class ParserUtils { + public final static String carriageReturn = System.getProperty("line.separator"); + final private static String QUOTE = "\""; + + private static final String TAG = "ParserUtils"; + private ParserListener parserListener; + + public ParserUtils(ParserListener parserListener) { + this.parserListener = parserListener; + } + + // ComposeActivity : EditText inside the onTextChanged + public String getPastedURLText(Context context) { + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + String pasteData; + if (clipboard.hasPrimaryClip()) { + // get what is in the clipboard + ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0); + pasteData = item.getText().toString(); + + // If we share with an app, it's not only an url + List strings = extractUrl(pasteData); + if (strings.size() > 0) { + String url = strings.get(0); // we assume that the first url is the good one + if (URLUtil.isValidUrl(url)) { + new ThreadHeaderInfo().execute(url); + } + } + } + return null; + } + + public void putInClipboardManager(Context context, String string) { + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText("", string); + clipboard.setPrimaryClip(clip); + } + + /** parse the HTML page */ + private HeaderInfo parsePageHeaderInfo(String urlStr) throws Exception { + Connection con = Jsoup.connect(urlStr); + HeaderInfo headerInfo = new HeaderInfo(); + con.userAgent(HttpConnection.DEFAULT_UA); + Document doc = con.get(); + + // get info + String text; + Elements metaOgTitle = doc.select("meta[property=og:title]"); + if (metaOgTitle != null) { + text = metaOgTitle.attr("content"); + } else { + text = doc.title(); + } + + String imageUrl = null; + Elements metaOgImage = doc.select("meta[property=og:image]"); + if (metaOgImage != null) { + imageUrl = metaOgImage.attr("content"); + } + + // set info + headerInfo.baseUrl = urlStr; + if (!TextUtils.isEmpty(text)) { + headerInfo.title = QUOTE + text + QUOTE; + } + if (!TextUtils.isEmpty(imageUrl)) { + headerInfo.image = (imageUrl); + } + return headerInfo; + } + + public interface ParserListener { + void onReceiveHeaderInfo(HeaderInfo headerInfo); + + void onErrorHeaderInfo(); + } + + public class HeaderInfo { + public String baseUrl; + public String title; + public String image; + } + + private class ThreadHeaderInfo extends AsyncTask { + protected HeaderInfo doInBackground(String... urls) { + try { + String url = urls[0]; + return parsePageHeaderInfo(url); + } catch (Exception e) { + Log.e(TAG, "ThreadHeaderInfo#parsePageHeaderInfo() failed." + e.getMessage()); + return null; + } + } + + protected void onPostExecute(HeaderInfo headerInfo) { + if (headerInfo != null) { + Log.i(TAG, "ThreadHeaderInfo#parsePageHeaderInfo() success." + headerInfo.title + " " + headerInfo.image); + parserListener.onReceiveHeaderInfo(headerInfo); + } else { + parserListener.onErrorHeaderInfo(); + } + } + } + + static List extractUrl(String text) { + List links = new ArrayList<>(); + Matcher m = Patterns.WEB_URL.matcher(text); + while (m.find()) { + String url = m.group(); + links.add(url); + } + return links; + } +} From ef23418bb335a5ba8265eefffc949a962e3a198b Mon Sep 17 00:00:00 2001 From: PhotonQyv Date: Fri, 1 Sep 2017 18:11:30 +0100 Subject: [PATCH 2/2] Sorting out extracts for shared URLs. Almost got it working, just one little step to work out. --- .../mastodon/activities/TootActivity.java | 48 +++++++++++++++---- .../etalab/mastodon/helper/ParserUtils.java | 5 +- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java index fad578b84..e23a97c69 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/TootActivity.java @@ -40,6 +40,7 @@ import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.text.Editable; import android.text.Html; +import android.text.TextUtils; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.Menu; @@ -243,13 +244,6 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc sharedContent = b.getString("sharedContent", null); sharedSubject = b.getString("sharedSubject", null); - // ACTION_SEND_TEXT route - if (sharedContent != null) - { - // Do Extract from URL here - final ParserUtils parser = new ParserUtils(this); - } - // ACTION_SEND route if (b.getInt("uriNumber", 0) == 1) { @@ -307,7 +301,15 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc }}); + //TODO: In here is where I've grafted on the code from Tusky. if( sharedContent != null ){ //Shared content + + // ParserUtils is a class I borrowed from Tusky. + final ParserUtils parser = new ParserUtils(this); + + parser.putInClipboardManager(TootActivity.this, sharedContent); + String urlString = parser.getPastedURLText(TootActivity.this); + if( sharedSubject != null){ sharedContent = sharedSubject + "\n\n" + sharedContent; } @@ -317,7 +319,9 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc int charsInCw = 0; int charsInToot = 0; - uploadSharedImage(sharedUri); + if (!sharedUri.isEmpty()) { + uploadSharedImage(sharedUri); + } boolean isAccountPrivate = account.isLocked(); if(isAccountPrivate){ @@ -556,6 +560,16 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc mToast.show(); } + //TODO: This overload takes care of the single URL coming from a text share. + public void uploadSharedImage(Uri image) + { + if (image != null) { + ArrayList uri = new ArrayList<>(); + uri.add(image); + uploadSharedImage(uri); + } + } + // Handles uploading shared images public void uploadSharedImage(ArrayList uri) { @@ -568,6 +582,9 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc break; } + // TODO: Work out what needs to be done to the URL from a text URL share to allow upload. + Toast.makeText(getApplicationContext(), "in upload: " + fileUri.toString(), Toast.LENGTH_SHORT).show(); + picture_scrollview.setVisibility(View.VISIBLE); try { @@ -1322,8 +1339,23 @@ public class TootActivity extends AppCompatActivity implements OnRetrieveSearcAc } } + // TODO: These two methods are part of the interface for ParserUtils + /* + These two methods are added to handle the grafted on code from Tusky, + they are part of its interface. + */ @Override public void onReceiveHeaderInfo(ParserUtils.HeaderInfo headerInfo) { + if (!TextUtils.isEmpty(headerInfo.title)) { + Toast.makeText(getApplicationContext(), headerInfo.title, Toast.LENGTH_SHORT).show(); + + if (!TextUtils.isEmpty(headerInfo.image)) { + Toast.makeText(getApplicationContext(), "We have an image", Toast.LENGTH_SHORT).show(); + + Toast.makeText(getApplicationContext(), headerInfo.image, Toast.LENGTH_SHORT).show(); + uploadSharedImage(Uri.parse(headerInfo.image)); + } + } } @Override diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/ParserUtils.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ParserUtils.java index 589dea808..d74e06d09 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/helper/ParserUtils.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/ParserUtils.java @@ -19,7 +19,8 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; -import static com.keylesspalace.tusky.util.StringUtils.QUOTE; + +// TODO: Borrowed wholesale from Tusky /** * Inspect and get the information from a URL. @@ -35,7 +36,7 @@ public class ParserUtils { this.parserListener = parserListener; } - // ComposeActivity : EditText inside the onTextChanged + // TootActivity : EditText inside the onTextChanged public String getPastedURLText(Context context) { ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); String pasteData;