1414import android .support .v4 .content .FileProvider ;
1515import android .support .v7 .app .ActionBar ;
1616import android .support .v7 .app .AlertDialog ;
17+ import android .util .SparseBooleanArray ;
1718import android .view .Menu ;
1819import android .view .MenuItem ;
1920import android .view .View ;
2526import java .io .File ;
2627import java .io .FileOutputStream ;
2728import java .io .IOException ;
29+ import java .util .ArrayList ;
2830import java .util .Date ;
31+ import java .util .regex .Matcher ;
32+ import java .util .regex .Pattern ;
2933
3034import de .nilsfo .lockscreennotes .data .Note ;
3135import de .nilsfo .lockscreennotes .sql .DBAdapter ;
3640
3741public class EditNoteActivity extends NotesActivity {
3842
43+ //public static final String URL_REGEX = "(?:(?:https?|ftp|file):\\/\\/|www\\.|ftp\.)(?:\\([-A-Z0-9+&@#\\/%=~_|$?!:,.]*\\)|[-A-Z0-9+&@#\\/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#\\/%=~_|$?!:,.]*\)|[A-Z0-9+&@#\\/%=~_|$])";
44+ //private static final String URL_REGEX = "((?:https\\:\\/\\/)|(?:http\\:\\/\\/)|(?:www\\.))?([a-zA-Z0-9\\-\\.]+\\.[a-zA-Z]{2,3}(?:\\??)[a-zA-Z0-9\\-\\._\\?\\,\\'\\/\\\\\\+&%\\$#\\=~]+)";
45+ private static final String URL_REGEX = "(https?:\\ /\\ /)?([\\ da-z\\ .-]+\\ .[a-z\\ .]{2,6}|[\\ d\\ .]+)([\\ /:?=&#]{1}[\\ da-z\\ .-]+)*[\\ /\\ ?]?" ;
46+
3947 public static final String NOTE_ACTIVITY_NOTE_ID = "EditNoteActivity_note_id" ;
4048 public static final int QR_IMAGE_SIZE = 512 ;
4149 public static final long ILLEGAL_NOTE_ID = -1 ;
@@ -245,25 +253,137 @@ public void onClick(DialogInterface dialog, int which) {
245253 builder .show ();
246254 }
247255
256+ public ArrayList <String > getURLsInNote () {
257+ Matcher m = applyRegexToNote (URL_REGEX );
258+ if (m == null ) {
259+ return null ;
260+ }
261+
262+ ArrayList <String > list = new ArrayList <>();
263+ while (m .find ()) {
264+ String match = m .group ();
265+ Timber .i ("Found a match: " + m .group ());
266+
267+ boolean add = true ;
268+ for (String s : list ) {
269+ if (s .equals (match )) {
270+ add =false ;
271+ }
272+ }
273+
274+ if (add ){
275+ list .add (match );
276+ }
277+ }
278+
279+ return list ;
280+ }
281+
282+ public void actionOpenWeblinks () {
283+ final ArrayList <String > list = getURLsInNote ();
284+ if (list == null ) {
285+ return ;
286+ }
287+
288+ if (list .isEmpty ()) {
289+ Toast .makeText (this , R .string .error_no_weblings , Toast .LENGTH_LONG ).show ();
290+ return ;
291+ }
292+
293+ if (list .size () == 1 ) {
294+ browseURL (list .get (0 ));
295+ return ;
296+ }
297+
298+ boolean [] sel = new boolean [list .size ()];
299+ String [] urls = new String [list .size ()];
300+ for (int i = 0 ; i < list .size (); i ++) {
301+ urls [i ] = list .get (i );
302+ sel [i ] = false ;
303+ }
304+ AlertDialog .Builder b = new AlertDialog .Builder (this );
305+ b .setTitle (R .string .info_choose_url );
306+ b .setIcon (R .mipmap .ic_launcher );
307+ b .setMultiChoiceItems (urls , sel , new DialogInterface .OnMultiChoiceClickListener () {
308+ @ Override
309+ public void onClick (DialogInterface dialog , int which , boolean isChecked ) {
310+ SparseBooleanArray sel = ((AlertDialog ) dialog ).getListView ().getCheckedItemPositions ();
311+ Timber .v ("URLs selected: " + sel );
312+ }
313+ });
314+ b .setNegativeButton (android .R .string .cancel , new DialogInterface .OnClickListener () {
315+ @ Override
316+ public void onClick (DialogInterface dialog , int which ) {
317+ dialog .cancel ();
318+ }
319+ });
320+ b .setPositiveButton (R .string .action_browse_selected , new DialogInterface .OnClickListener () {
321+ @ Override
322+ public void onClick (DialogInterface dialog , int which ) {
323+ dialog .dismiss ();
324+ SparseBooleanArray sel = ((AlertDialog ) dialog ).getListView ().getCheckedItemPositions ();
325+ Timber .i ("URLs to browse selected: " + sel );
326+ for (int i = 0 ; i < list .size (); i ++) {
327+ if (sel .get (i )) {
328+ String url = list .get (i );
329+ browseURL (url );
330+ Timber .i ("Browsing URL '" + url + "'. " + (i + 1 ) + "/" + list .size ());
331+ }
332+ }
333+ }
334+ });
335+ b .setNeutralButton (R .string .action_browse_all , new DialogInterface .OnClickListener () {
336+ @ Override
337+ public void onClick (DialogInterface dialog , int which ) {
338+ for (String s : list ) {
339+ browseURL (s );
340+ }
341+ }
342+ });
343+
344+ b .show ();
345+ }
346+
347+ private void browseURL (String url ) {
348+ if (!url .toLowerCase ().startsWith ("http://" ) && !url .toLowerCase ().startsWith ("https://" )) {
349+ url = "http://" + url ;
350+ }
351+
352+ Intent i = new Intent (Intent .ACTION_VIEW );
353+ i .setData (Uri .parse (url ));
354+ startActivity (i );
355+ }
356+
357+ private Matcher applyRegexToNote (String regex ) {
358+ String text = String .valueOf (noteTF .getText ());
359+ Timber .i ("Applying Regex: " + regex );
360+ Timber .i ("Text to apply it to: " + text );
361+
362+ if (text == null || text .trim ().equals ("" )) return null ;
363+
364+ Pattern p = Pattern .compile (regex , Pattern .CASE_INSENSITIVE | Pattern .MULTILINE );
365+ return p .matcher (text );
366+ }
367+
248368 private void shareQRImage (Bitmap image ) {
249- File imageFile = null ;
369+ File imageFile = null ;
250370 try {
251371 File cachePath = new File (getCacheDir (), "images" );
252372 cachePath .mkdirs ();
253- imageFile = new File (cachePath + File .separator + getString (R .string .qr_cache_name )+ ".png" );
373+ imageFile = new File (cachePath + File .separator + getString (R .string .qr_cache_name ) + ".png" );
254374 FileOutputStream stream = new FileOutputStream (imageFile ); // overwrites this image every time
255375 image .compress (Bitmap .CompressFormat .PNG , 100 , stream );
256376 stream .close ();
257377 } catch (IOException e ) {
258378 e .printStackTrace ();
259379 Timber .e (e , "Failed to share QR Code!" );
260380
261- Toast .makeText (this , R .string .error_qr_generation_failed ,Toast .LENGTH_LONG ).show ();
381+ Toast .makeText (this , R .string .error_qr_generation_failed , Toast .LENGTH_LONG ).show ();
262382 return ;
263383 }
264384
265385 if (imageFile == null || !imageFile .exists ()) {
266- Toast .makeText (this , R .string .error_qr_generation_failed ,Toast .LENGTH_LONG ).show ();
386+ Toast .makeText (this , R .string .error_qr_generation_failed , Toast .LENGTH_LONG ).show ();
267387 return ;
268388 }
269389
@@ -279,8 +399,8 @@ private void shareQRImage(Bitmap image) {
279399 shareIntent .setDataAndType (contentUri , getContentResolver ().getType (contentUri ));
280400 shareIntent .putExtra (Intent .EXTRA_STREAM , contentUri );
281401 startActivity (Intent .createChooser (shareIntent , getString (R .string .share_using )));
282- }else {
283- Toast .makeText (this , R .string .error_qr_generation_failed ,Toast .LENGTH_LONG ).show ();
402+ } else {
403+ Toast .makeText (this , R .string .error_qr_generation_failed , Toast .LENGTH_LONG ).show ();
284404 }
285405 }
286406
@@ -316,6 +436,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
316436 case R .id .action_to_qr_code :
317437 actionToQR ();
318438 return true ;
439+
440+ case R .id .action_open_weblinks :
441+ actionOpenWeblinks ();
442+ return true ;
319443 }
320444 return super .onOptionsItemSelected (item );
321445 }
0 commit comments