mirror of
https://github.com/akaessens/NoFbEventScraper
synced 2025-06-05 23:29:13 +02:00
much refactoring:
-move event formatting logic to event class -disable editing of event output, it's available in the calendar app -replace string datetimes with ZonedDateZime -move uri checking logic to scraper -update exception handling and error messages -reformatting and renaming -fix messy xml layouts -update tests -add comments
This commit is contained in:
@ -40,6 +40,6 @@ dependencies {
|
||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
}
|
||||
|
@ -1,110 +0,0 @@
|
||||
package com.akdev.nofbeventscraper;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class MainActivityUnitTest {
|
||||
|
||||
@Test
|
||||
public void TestSubdomainUrl() {
|
||||
|
||||
|
||||
Instrumentation mInstrumentation = getInstrumentation();
|
||||
// We register our interest in the activity
|
||||
Instrumentation.ActivityMonitor monitor = mInstrumentation.addMonitor(MainActivity.class.getName(), null, false);
|
||||
// We launch it
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setClassName(mInstrumentation.getTargetContext(), MainActivity.class.getName());
|
||||
mInstrumentation.startActivitySync(intent);
|
||||
|
||||
MainActivity mainActivity = (MainActivity) getInstrumentation().waitForMonitor(monitor);
|
||||
|
||||
// We register our interest in the next activity from the sequence in this use case
|
||||
mInstrumentation.removeMonitor(monitor);
|
||||
|
||||
|
||||
final String exp = "https://m.facebook.com/events/261145401687844";
|
||||
|
||||
String url = "https://www.facebook.com/events/261145401687844";
|
||||
String act = mainActivity.checkURI(url);
|
||||
assertEquals(exp, act);
|
||||
|
||||
url = "https://de-de.facebook.com/events/261145401687844";
|
||||
act = mainActivity.checkURI(url);
|
||||
assertEquals(exp, act);
|
||||
|
||||
url = "https://m.facebook.com/events/261145401687844";
|
||||
act = mainActivity.checkURI(url);
|
||||
assertEquals(exp, act);
|
||||
|
||||
url = "https://www.facebook.com/events/261145401687844/?active_tab=discussion";
|
||||
act = mainActivity.checkURI(url);
|
||||
assertEquals(exp, act);
|
||||
|
||||
url = "https://www.facebook.com/events/261145401687844?reflink_something";
|
||||
act = mainActivity.checkURI(url);
|
||||
assertEquals(exp, act);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestTimeToEpoch() {
|
||||
|
||||
|
||||
Instrumentation mInstrumentation = getInstrumentation();
|
||||
// We register our interest in the activity
|
||||
Instrumentation.ActivityMonitor monitor = mInstrumentation.addMonitor(MainActivity.class.getName(), null, false);
|
||||
// We launch it
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setClassName(mInstrumentation.getTargetContext(), MainActivity.class.getName());
|
||||
mInstrumentation.startActivitySync(intent);
|
||||
|
||||
MainActivity mainActivity = (MainActivity) getInstrumentation().waitForMonitor(monitor);
|
||||
|
||||
// We register our interest in the next activity from the sequence in this use case
|
||||
mInstrumentation.removeMonitor(monitor);
|
||||
|
||||
|
||||
String in = "2020-07-29T12:00:00+00:00";
|
||||
|
||||
Long exp = new Long(1596024000);
|
||||
exp = exp* 1000;
|
||||
Long act = mainActivity.convertTimeToEpoch(in);
|
||||
assertEquals(exp, act);
|
||||
|
||||
|
||||
in = "2020-07-29T12:00:00+02:00";
|
||||
exp = new Long(1596016800);
|
||||
exp = exp* 1000;
|
||||
act = mainActivity.convertTimeToEpoch(in);
|
||||
assertEquals(exp, act);
|
||||
|
||||
|
||||
in = "1970-01-01T00:00:00+00:00";
|
||||
exp = new Long(0);
|
||||
exp = exp* 1000;
|
||||
act = mainActivity.convertTimeToEpoch(in);
|
||||
assertEquals(exp, act);
|
||||
|
||||
in = "1970-01-01T02:00:00+02:00";
|
||||
exp = new Long(0);
|
||||
exp = exp* 1000;
|
||||
act = mainActivity.convertTimeToEpoch(in);
|
||||
assertEquals(exp, act);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -5,13 +5,19 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ScraperUnitTest {
|
||||
|
||||
@Test
|
||||
public void TestLocation() {
|
||||
public void testLocation() {
|
||||
|
||||
|
||||
FbScraper scraper = new FbScraper(null, "");
|
||||
|
||||
@ -32,37 +38,50 @@ public class ScraperUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestTimezone() {
|
||||
public void testTimezone() {
|
||||
|
||||
FbScraper scraper = new FbScraper(null, "");
|
||||
|
||||
String exp = "2020-10-23T05:00:00+02:00";
|
||||
String exp = "2020-10-23T05:00+02:00";
|
||||
String in = "2020-10-23T05:00:00+0200";
|
||||
String act = scraper.fixTimezone(in);
|
||||
String act = scraper.toZonedDateTime(in).toString();
|
||||
assertEquals(exp, act);
|
||||
|
||||
|
||||
exp = "";
|
||||
exp = null;
|
||||
in = "";
|
||||
act = scraper.fixTimezone(in);
|
||||
assertEquals(exp, act);
|
||||
|
||||
ZonedDateTime act2 = scraper.toZonedDateTime(in);
|
||||
assertEquals(exp, act2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestLinks() {
|
||||
public void testDescriptionLinks() {
|
||||
|
||||
FbScraper scraper = new FbScraper(null, "");
|
||||
|
||||
String in = "foo @[152580919265:274:MagentaMusik 360] bar";
|
||||
String exp = "foo MagentaMusik 360 [m.facebook.com/152580919265] bar";
|
||||
String act = scraper.fixLinks(in);
|
||||
String act = scraper.fixDescriptionLinks(in);
|
||||
assertEquals(exp, act);
|
||||
|
||||
in = "foo @[152580919265:274:MagentaMusik 360] bar @[666666666666:274:NoOfTheBeast]";
|
||||
exp = "foo MagentaMusik 360 [m.facebook.com/152580919265] bar NoOfTheBeast [m.facebook.com/666666666666]";
|
||||
act = scraper.fixLinks(in);
|
||||
act = scraper.fixDescriptionLinks(in);
|
||||
assertEquals(exp, act);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURI() throws MalformedURLException, URISyntaxException {
|
||||
|
||||
FbScraper scraper = new FbScraper(null, "");
|
||||
|
||||
String in = "https://www.facebook.com/events/1234324522341432?refsomething";
|
||||
String exp = "https://m.facebook.com/events/1234324522341432";
|
||||
String act = scraper.fixURI(in);
|
||||
assertEquals(exp, act);
|
||||
|
||||
in = "https://de-de.facebook.com/events/1234324522341432/?active_tab=discussion";
|
||||
act = scraper.fixURI(in);
|
||||
assertEquals(exp, act);
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,24 @@
|
||||
package com.akdev.nofbeventscraper;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
|
||||
public class FbEvent {
|
||||
|
||||
public String url;
|
||||
public String name;
|
||||
public String start_date;
|
||||
public String end_date;
|
||||
public ZonedDateTime start_date;
|
||||
public ZonedDateTime end_date;
|
||||
public String description;
|
||||
public String location;
|
||||
public String image_url;
|
||||
|
||||
public FbEvent (String name, String start_date, String end_date, String description, String location, String image_url) {
|
||||
public FbEvent() {
|
||||
|
||||
}
|
||||
|
||||
public FbEvent(String name, ZonedDateTime start_date, ZonedDateTime end_date, String description, String location, String image_url) {
|
||||
this.name = name;
|
||||
this.start_date = start_date;
|
||||
this.end_date = end_date;
|
||||
@ -16,4 +26,21 @@ public class FbEvent {
|
||||
this.location = location;
|
||||
this.image_url = image_url;
|
||||
}
|
||||
|
||||
|
||||
static Long dateTimeToEpoch(ZonedDateTime datetime) {
|
||||
try {
|
||||
return datetime.toEpochSecond() * 1000;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static String dateTimeToString(ZonedDateTime datetime) {
|
||||
try {
|
||||
return DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).format(datetime);
|
||||
} catch (Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.akdev.nofbeventscraper;
|
||||
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.text.Editable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
@ -11,69 +10,100 @@ import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class FbScraper extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private String url;
|
||||
private String error;
|
||||
private MainActivity main;
|
||||
private String input_str;
|
||||
private WeakReference<MainActivity> main; // no context leak with WeakReference
|
||||
private FbEvent event;
|
||||
|
||||
FbScraper(MainActivity main, String url) {
|
||||
this.url = url;
|
||||
FbScraper(WeakReference<MainActivity> main, String str) {
|
||||
this.main = main;
|
||||
this.input_str = str;
|
||||
}
|
||||
|
||||
protected String fixURI(String str) throws URISyntaxException, MalformedURLException {
|
||||
|
||||
// check for url format
|
||||
new URL(str).toURI();
|
||||
|
||||
Pattern pattern = Pattern.compile("(facebook.com/events/[0-9]*)");
|
||||
Matcher matcher = pattern.matcher(str);
|
||||
|
||||
if (matcher.find()) {
|
||||
// rewrite url to m.facebook and dismiss any query strings or referrals
|
||||
return "https://m." + matcher.group(1);
|
||||
} else {
|
||||
throw new URISyntaxException(str, "Does not contain event.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected String fixLocation(String location_json) {
|
||||
|
||||
String name = "";
|
||||
String location_name = "";
|
||||
|
||||
try {
|
||||
JSONObject reader = new JSONObject(location_json);
|
||||
|
||||
name = reader.getString("name");
|
||||
location_name = reader.getString("name");
|
||||
JSONObject address = reader.getJSONObject("address");
|
||||
|
||||
String type = address.getString("@type");
|
||||
|
||||
if (type.equals("PostalAddress"))
|
||||
{
|
||||
if (type.equals("PostalAddress")) {
|
||||
String postal_code = address.getString("postalCode");
|
||||
String address_locality = address.getString("addressLocality");
|
||||
String address_country = address.getString("addressCountry");
|
||||
String street_address = address.getString("streetAddress");
|
||||
// included in locality
|
||||
//String address_country = address.getString("addressCountry");
|
||||
|
||||
return name + ", " + street_address + ", " + postal_code + " " + address_locality;
|
||||
}
|
||||
else
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
return location_name + ", "
|
||||
+ street_address + ", "
|
||||
+ postal_code + " "
|
||||
+ address_locality;
|
||||
} else {
|
||||
return location_name;
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return name;
|
||||
return location_name;
|
||||
}
|
||||
}
|
||||
|
||||
protected String fixTimezone(String time_in) {
|
||||
protected ZonedDateTime toZonedDateTime(String time_in) {
|
||||
|
||||
try {
|
||||
|
||||
// time in is missing a : in the timezone offset
|
||||
Editable editable = new SpannableStringBuilder(time_in);
|
||||
String time_str = editable.insert(22, ":").toString();
|
||||
|
||||
return editable.insert(22, ":").toString();
|
||||
// parse e.g. 2011-12-03T10:15:30+01:00
|
||||
return ZonedDateTime.parse(time_str, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected String fixLinks(String description_in) {
|
||||
protected String fixDescriptionLinks(String description_in) {
|
||||
try {
|
||||
// @[152580919265:274:MagentaMusik 360] -> m.facebook.com/152580919265
|
||||
/* @[152580919265:274:SiteDescription]
|
||||
* to
|
||||
* SiteDescription [m.facebook.com/152580919265] */
|
||||
|
||||
return description_in.replaceAll("@\\[([0-9]{10,}):[0-9]{3}:([^]]*)]",
|
||||
"$2 [m.facebook.com/$1]");
|
||||
|
||||
@ -86,60 +116,45 @@ public class FbScraper extends AsyncTask<Void, Void, Void> {
|
||||
private String readFromJson(JSONObject reader, String field) {
|
||||
try {
|
||||
return reader.getString(field);
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
|
||||
Document document = null;
|
||||
|
||||
try {
|
||||
document = Jsoup.connect(url).userAgent("Mozilla").get();
|
||||
String url = fixURI(input_str);
|
||||
// useragent needed with Jsoup > 1.12
|
||||
Document document = Jsoup.connect(url).userAgent("Mozilla").get();
|
||||
String json = document
|
||||
.select("script[type = application/ld+json]")
|
||||
.first().data();
|
||||
|
||||
try {
|
||||
String json = document.select("script[type = application/ld+json]").first().data();
|
||||
JSONObject reader = new JSONObject(json);
|
||||
|
||||
JSONObject reader = new JSONObject(json);
|
||||
event = new FbEvent();
|
||||
event.url = url;
|
||||
event.name = readFromJson(reader, "name");
|
||||
event.start_date = toZonedDateTime(readFromJson(reader, "startDate"));
|
||||
event.end_date = toZonedDateTime(readFromJson(reader, "endDate"));
|
||||
event.description = fixDescriptionLinks(readFromJson(reader, "description"));
|
||||
event.location = fixLocation(readFromJson(reader, "location"));
|
||||
event.image_url = readFromJson(reader, "image");
|
||||
|
||||
String event_name = readFromJson(reader, "name");
|
||||
String event_start = fixTimezone(readFromJson(reader, "startDate"));
|
||||
String event_end = fixTimezone(readFromJson(reader, "endDate"));
|
||||
|
||||
String event_description = fixLinks(readFromJson(reader, "description"));
|
||||
String location = fixLocation(readFromJson(reader, "location"));
|
||||
|
||||
String image_url = "";
|
||||
|
||||
try {
|
||||
image_url = readFromJson(reader, "image"); // get from json
|
||||
|
||||
// get from event header
|
||||
image_url = document.getElementsByClass("scaledImageFitWidth").first().attr("src");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
this.error = "Error: no image found";
|
||||
}
|
||||
|
||||
if (event_name == null) {
|
||||
this.event = null;
|
||||
throw new Exception();
|
||||
} else {
|
||||
this.event = new FbEvent(event_name, event_start, event_end, event_description, location, image_url);
|
||||
//this.event = new FbEvent("", "", "", "", "", "");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
this.error = "Error: Scraping event data failed";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} catch (URISyntaxException | MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
this.error = "Error: URL not available";
|
||||
this.error = "Error: URL invalid.";
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
this.error = "Error: Scraping event data failed";
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
this.error = "Error: Unable to connect.";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -152,11 +167,10 @@ public class FbScraper extends AsyncTask<Void, Void, Void> {
|
||||
super.onPostExecute(aVoid);
|
||||
|
||||
if (this.event != null) {
|
||||
this.main.update(event);
|
||||
}
|
||||
else {
|
||||
main.error(error);
|
||||
this.main.clear(false);
|
||||
main.get().update(event);
|
||||
} else {
|
||||
main.get().error(error);
|
||||
main.get().clear(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.provider.CalendarContract;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
@ -19,32 +13,39 @@ import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.net.URL;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import static com.akdev.nofbeventscraper.FbEvent.dateTimeToEpoch;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private Button paste_button;
|
||||
private Button ok_button;
|
||||
protected Button ok_button;
|
||||
protected Button paste_button;
|
||||
|
||||
private TextInputEditText field_uri_input;
|
||||
private TextInputEditText field_event_name;
|
||||
private TextInputEditText field_event_start;
|
||||
private TextInputEditText field_event_end;
|
||||
private TextInputEditText field_event_location;
|
||||
private TextInputEditText field_event_description;
|
||||
private ImageView toolbar_image_view;
|
||||
private CollapsingToolbarLayout toolbar_layout;
|
||||
private TextInputLayout input_layout;
|
||||
private TextInputLayout location_layout;
|
||||
private FbScraper scraper;
|
||||
protected TextInputEditText edit_text_uri_input;
|
||||
protected TextInputEditText edit_text_event_name;
|
||||
protected TextInputEditText edit_text_event_start;
|
||||
protected TextInputEditText edit_text_event_end;
|
||||
protected TextInputEditText edit_text_event_location;
|
||||
protected TextInputEditText edit_text_event_description;
|
||||
|
||||
protected TextInputLayout layout_uri_input;
|
||||
protected TextInputLayout layout_event_location;
|
||||
|
||||
protected ImageView image_view_toolbar;
|
||||
protected CollapsingToolbarLayout layout_toolbar;
|
||||
|
||||
protected FbScraper scraper;
|
||||
protected FbEvent event;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -56,43 +57,52 @@ public class MainActivity extends AppCompatActivity {
|
||||
ok_button = (Button) findViewById(R.id.ok_button);
|
||||
paste_button = (Button) findViewById(R.id.paste_button);
|
||||
|
||||
field_uri_input = (TextInputEditText) findViewById(R.id.field_uri_input);
|
||||
input_layout = (TextInputLayout) findViewById(R.id.textInputLayout);
|
||||
location_layout = (TextInputLayout) findViewById(R.id.location_layout);
|
||||
field_event_name = (TextInputEditText) findViewById(R.id.field_event_name);
|
||||
field_event_start = (TextInputEditText) findViewById(R.id.field_event_start);
|
||||
field_event_end = (TextInputEditText) findViewById(R.id.field_event_end);
|
||||
field_event_location = (TextInputEditText) findViewById(R.id.field_event_location);
|
||||
field_event_description = (TextInputEditText) findViewById(R.id.field_event_description);
|
||||
toolbar_image_view = (ImageView) findViewById(R.id.image_view);
|
||||
toolbar_layout = (CollapsingToolbarLayout) findViewById(R.id.toolbar_layout);
|
||||
edit_text_uri_input = (TextInputEditText) findViewById(R.id.edit_text_uri_input);
|
||||
edit_text_event_name = (TextInputEditText) findViewById(R.id.edit_text_event_name);
|
||||
edit_text_event_start = (TextInputEditText) findViewById(R.id.edit_text_event_start);
|
||||
edit_text_event_end = (TextInputEditText) findViewById(R.id.edit_text_event_end);
|
||||
edit_text_event_location = (TextInputEditText) findViewById(R.id.edit_text_event_location);
|
||||
edit_text_event_description = (TextInputEditText) findViewById(R.id.edit_text_event_description);
|
||||
|
||||
layout_uri_input = (TextInputLayout) findViewById(R.id.layout_uri_input);
|
||||
layout_event_location = (TextInputLayout) findViewById(R.id.layout_event_location);
|
||||
layout_toolbar = (CollapsingToolbarLayout) findViewById(R.id.layout_toolbar);
|
||||
image_view_toolbar = (ImageView) findViewById(R.id.image_view);
|
||||
|
||||
|
||||
/*
|
||||
* Default view settings
|
||||
*/
|
||||
ok_button.setEnabled(false);
|
||||
location_layout.setEndIconVisible(false);
|
||||
|
||||
toolbar_image_view.setImageResource(R.drawable.ic_banner_foreground);
|
||||
layout_event_location.setEndIconVisible(false);
|
||||
image_view_toolbar.setImageResource(R.drawable.ic_banner_foreground);
|
||||
|
||||
/*
|
||||
* Display title only when toolbar is collapsed
|
||||
*/
|
||||
AppBarLayout app_bar_layout = (AppBarLayout) findViewById(R.id.app_bar);
|
||||
app_bar_layout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
|
||||
boolean isShow = true;
|
||||
int scrollRange = -1;
|
||||
boolean show = true;
|
||||
int scroll_range = -1;
|
||||
|
||||
@Override
|
||||
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
|
||||
if (scrollRange == -1) {
|
||||
scrollRange = appBarLayout.getTotalScrollRange();
|
||||
public void onOffsetChanged(AppBarLayout app_bar_layout, int vertical_offset) {
|
||||
if (scroll_range == -1) {
|
||||
scroll_range = app_bar_layout.getTotalScrollRange();
|
||||
}
|
||||
if (scrollRange + verticalOffset == 0) {
|
||||
toolbar_layout.setTitle(getString(R.string.app_name));
|
||||
isShow = true;
|
||||
} else if(isShow) {
|
||||
toolbar_layout.setTitle(" ");
|
||||
isShow = false;
|
||||
if (scroll_range + vertical_offset == 0) {
|
||||
layout_toolbar.setTitle(getString(R.string.app_name));
|
||||
show = true;
|
||||
} else if (show) {
|
||||
layout_toolbar.setTitle(" ");
|
||||
show = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Paste button: get last entry from clipboard
|
||||
*/
|
||||
paste_button.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
@ -102,9 +112,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
String str = clipboard.getPrimaryClip().getItemAt(0).getText().toString();
|
||||
|
||||
clear(true);
|
||||
field_uri_input.setText(str);
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
edit_text_uri_input.setText(str);
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
error("Error: Clipboard empty");
|
||||
}
|
||||
@ -112,71 +121,65 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
input_layout.setEndIconOnClickListener(new View.OnClickListener() {
|
||||
/*
|
||||
* Clear button: delete all text in all fields
|
||||
*/
|
||||
View.OnClickListener listener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
clear(true);
|
||||
}
|
||||
});
|
||||
input_layout.setErrorIconOnClickListener(new View.OnClickListener() {
|
||||
};
|
||||
layout_uri_input.setEndIconOnClickListener(listener);
|
||||
layout_uri_input.setErrorIconOnClickListener(listener);
|
||||
|
||||
/*
|
||||
* Maps button: launch maps intent
|
||||
*/
|
||||
layout_event_location.setEndIconOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
clear(true);
|
||||
}
|
||||
});
|
||||
String map_search = "geo:0,0?q=" + edit_text_event_location.getText();
|
||||
|
||||
|
||||
location_layout.setEndIconOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
String map_search = "geo:0,0?q=" + field_event_location.getText();
|
||||
|
||||
Uri gmmIntentUri = Uri.parse(map_search);
|
||||
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
|
||||
//mapIntent.setPackage("com.google.android.apps.maps");
|
||||
if (mapIntent.resolveActivity(getPackageManager()) != null) {
|
||||
startActivity(mapIntent);
|
||||
Uri intent_uri = Uri.parse(map_search);
|
||||
Intent map_intent = new Intent(Intent.ACTION_VIEW, intent_uri);
|
||||
if (map_intent.resolveActivity(getPackageManager()) != null) {
|
||||
startActivity(map_intent);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* Add to calendar button: launch calendar application
|
||||
*/
|
||||
ok_button.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
try {
|
||||
Long start_epoch = convertTimeToEpoch(field_event_start.getText().toString());
|
||||
Long end_epoch = convertTimeToEpoch(field_event_end.getText().toString());
|
||||
|
||||
String name = parseField(field_event_name);
|
||||
Long start_epoch = dateTimeToEpoch(event.start_date);
|
||||
Long end_epoch = dateTimeToEpoch(event.end_date);
|
||||
|
||||
String location = parseField(field_event_location);
|
||||
String description = parseField(field_event_description);
|
||||
String uri = parseField(field_uri_input);
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_EDIT);
|
||||
intent.setType("vnd.android.cursor.item/event");
|
||||
intent.putExtra(CalendarContract.Events.TITLE, name);
|
||||
intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, start_epoch);
|
||||
intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end_epoch);
|
||||
intent.putExtra(CalendarContract.Events.EVENT_LOCATION, location);
|
||||
intent.putExtra(CalendarContract.Events.DESCRIPTION, uri + "\n\n" + description);
|
||||
startActivity(intent);
|
||||
}
|
||||
catch (Exception e )
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
Intent intent = new Intent(Intent.ACTION_EDIT);
|
||||
intent.setType("vnd.android.cursor.item/event");
|
||||
intent.putExtra(CalendarContract.Events.TITLE, event.name);
|
||||
intent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, start_epoch);
|
||||
intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end_epoch);
|
||||
intent.putExtra(CalendarContract.Events.EVENT_LOCATION, event.location);
|
||||
|
||||
// prepend url in description
|
||||
String desc = event.url + "\n\n" + event.description;
|
||||
intent.putExtra(CalendarContract.Events.DESCRIPTION, desc);
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
field_uri_input.setOnKeyListener(new View.OnKeyListener() {
|
||||
public boolean onKey(View view, int keyCode, KeyEvent keyevent) {
|
||||
//If the keyevent is a key-down event on the "enter" button
|
||||
if ((keyevent.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
|
||||
/*
|
||||
* Enter button in uri input: start scraping
|
||||
*/
|
||||
edit_text_uri_input.setOnKeyListener(new View.OnKeyListener() {
|
||||
public boolean onKey(View view, int keycode, KeyEvent keyevent) {
|
||||
//If the key event is a key-down event on the "enter" button
|
||||
if ((keyevent.getAction() == KeyEvent.ACTION_DOWN) && (keycode == KeyEvent.KEYCODE_ENTER)) {
|
||||
startScraping();
|
||||
return true;
|
||||
}
|
||||
@ -184,175 +187,122 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
|
||||
//get data from deep link
|
||||
|
||||
/*
|
||||
* Get data from intent: if launched by other application
|
||||
* via "share to" or "open with"
|
||||
*/
|
||||
Intent intent = getIntent();
|
||||
Uri data = intent.getData();
|
||||
String shared_text = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
|
||||
if (data != null) {
|
||||
// opening external fb link
|
||||
field_uri_input.setText(data.toString());
|
||||
edit_text_uri_input.setText(data.toString());
|
||||
startScraping();
|
||||
}
|
||||
else if (shared_text != null) {
|
||||
} else if (shared_text != null) {
|
||||
//share to nofb
|
||||
field_uri_input.setText(shared_text);
|
||||
edit_text_uri_input.setText(shared_text);
|
||||
startScraping();
|
||||
}
|
||||
|
||||
}
|
||||
private String parseField(TextInputEditText field) {
|
||||
try {
|
||||
return field.getText().toString();
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Long convertTimeToEpoch(String time_str) {
|
||||
try {
|
||||
ZonedDateTime datetime = ZonedDateTime.parse(time_str, DateTimeFormatter.ISO_DATE_TIME);
|
||||
|
||||
return datetime.toEpochSecond() * 1000;
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String checkURI(String str)
|
||||
{
|
||||
try {
|
||||
|
||||
// check for a valid uri
|
||||
new URL(str).toURI();
|
||||
|
||||
Pattern pattern = Pattern.compile("(facebook.com/events/[0-9]*)");
|
||||
Matcher matcher = pattern.matcher(str);
|
||||
|
||||
if (matcher.find())
|
||||
{
|
||||
return "https://m." + matcher.group(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Error: Invalid URL");
|
||||
clear(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
error("Error: Invalid URL");
|
||||
clear(false);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public void startScraping() {
|
||||
|
||||
error(null);
|
||||
|
||||
try {
|
||||
String str = checkURI(field_uri_input.getText().toString());
|
||||
String url = edit_text_uri_input.getText().toString();
|
||||
scraper = new FbScraper(new WeakReference<>(this), url);
|
||||
scraper.execute();
|
||||
|
||||
|
||||
if (!str.equals(""))
|
||||
{
|
||||
field_uri_input.setText(str);
|
||||
scraper = new FbScraper(this, field_uri_input.getText().toString());
|
||||
scraper.execute();
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
error("Error: Invalid URL");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void error(String str) {
|
||||
//Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
|
||||
input_layout.setError(str);
|
||||
}
|
||||
public void clear(boolean clearUri) {
|
||||
if (clearUri) {
|
||||
field_uri_input.setText("");
|
||||
}
|
||||
field_event_name.setText("");
|
||||
field_event_name.setError(null);
|
||||
field_event_start.setText("");
|
||||
field_event_start.setError(null);
|
||||
field_event_end.setText("");
|
||||
field_event_end.setError(null);
|
||||
field_event_location.setText("");
|
||||
field_event_location.setError(null);
|
||||
field_event_description.setText("");
|
||||
field_event_description.setError(null);
|
||||
toolbar_image_view.setImageDrawable(null);
|
||||
|
||||
if (scraper!=null)
|
||||
{
|
||||
scraper.cancel(true);
|
||||
scraper = null;
|
||||
}
|
||||
ok_button.setEnabled(false);
|
||||
location_layout.setEndIconVisible(false);
|
||||
toolbar_image_view.setImageResource(R.drawable.ic_banner_foreground);
|
||||
layout_uri_input.setError(str);
|
||||
}
|
||||
|
||||
public void update(FbEvent event) {
|
||||
field_event_name.setText(event.name);
|
||||
input_layout.setError(null);
|
||||
public void clear(boolean clear_uri) {
|
||||
|
||||
if (event.name.equals(""))
|
||||
{
|
||||
field_event_name.setError("no event name detected");
|
||||
}
|
||||
field_event_start.setText(event.start_date);
|
||||
|
||||
if (event.start_date.equals(""))
|
||||
{
|
||||
field_event_start.setError("no event start date detected");
|
||||
}
|
||||
field_event_end.setText(event.end_date);
|
||||
|
||||
if (event.end_date.equals(""))
|
||||
{
|
||||
field_event_end.setError("no event end date detected");
|
||||
}
|
||||
|
||||
field_event_location.setText(event.location);
|
||||
|
||||
if (event.location.equals(""))
|
||||
{
|
||||
field_event_location.setError("no event location detected");
|
||||
}
|
||||
else
|
||||
{
|
||||
location_layout.setEndIconVisible(true);
|
||||
field_event_location.setError(null);
|
||||
}
|
||||
field_event_description.setText(event.description);
|
||||
|
||||
if (event.description.equals(""))
|
||||
{
|
||||
field_event_description.setError("no event description detected");
|
||||
if (clear_uri) {
|
||||
edit_text_uri_input.setText("");
|
||||
layout_uri_input.setError(null);
|
||||
}
|
||||
edit_text_event_name.setText("");
|
||||
edit_text_event_start.setText("");
|
||||
edit_text_event_end.setText("");
|
||||
edit_text_event_location.setText("");
|
||||
edit_text_event_description.setText("");
|
||||
|
||||
edit_text_event_name.setError(null);
|
||||
// edit_text_event_start.setError(null);
|
||||
edit_text_event_end.setError(null);
|
||||
edit_text_event_location.setError(null);
|
||||
edit_text_event_description.setError(null);
|
||||
|
||||
try {
|
||||
Picasso.get().load(event.image_url).into(toolbar_image_view);
|
||||
} catch (Exception e)
|
||||
{
|
||||
scraper.cancel(true);
|
||||
scraper = null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
ok_button.setEnabled(false);
|
||||
layout_event_location.setEndIconVisible(false);
|
||||
image_view_toolbar.setImageResource(R.drawable.ic_banner_foreground);
|
||||
}
|
||||
|
||||
public void update(FbEvent scraped_event) {
|
||||
|
||||
this.event = scraped_event;
|
||||
|
||||
edit_text_uri_input.setText(event.url);
|
||||
|
||||
if (event.name.equals("")) {
|
||||
edit_text_event_name.setError("no event name detected");
|
||||
} else {
|
||||
edit_text_event_name.setText(event.name);
|
||||
}
|
||||
|
||||
if (event.start_date == null) {
|
||||
edit_text_event_start.setError("no event start date detected");
|
||||
} else {
|
||||
String str = FbEvent.dateTimeToString(event.start_date);
|
||||
edit_text_event_start.setText(str);
|
||||
}
|
||||
|
||||
if (event.end_date == null) {
|
||||
edit_text_event_end.setError("no event end date detected");
|
||||
} else {
|
||||
String str = FbEvent.dateTimeToString(event.end_date);
|
||||
edit_text_event_end.setText(str);
|
||||
}
|
||||
|
||||
if (event.location.equals("")) {
|
||||
edit_text_event_location.setError("no event location detected");
|
||||
} else {
|
||||
edit_text_event_location.setText(event.location);
|
||||
layout_event_location.setEndIconVisible(true);
|
||||
}
|
||||
|
||||
if (event.description.equals("")) {
|
||||
edit_text_event_description.setError("no event description detected");
|
||||
} else {
|
||||
edit_text_event_description.setText(event.description);
|
||||
}
|
||||
|
||||
Picasso.get()
|
||||
.load(event.image_url)
|
||||
.placeholder(R.drawable.ic_banner_foreground)
|
||||
.into(image_view_toolbar);
|
||||
|
||||
ok_button.setEnabled(true);
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
@ -16,7 +17,7 @@
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@+id/toolbar_layout"
|
||||
android:id="@+id/layout_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorPrimary"
|
||||
@ -63,7 +64,7 @@
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
<com.google.android.material.bottomappbar.BottomAppBar
|
||||
android:id="@+id/bottomButtonLayout"
|
||||
android:id="@+id/bottom_appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
|
@ -1,59 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/nested_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="false"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context=".MainActivity"
|
||||
tools:showIn="@layout/activity_main"
|
||||
android:id="@+id/nested_scroll_view" >
|
||||
tools:showIn="@layout/activity_main">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/constraint_layout"
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginBottom="64dp"
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout4"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
android:divider="@drawable/divider"
|
||||
android:orientation="vertical"
|
||||
android:showDividers="middle">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textInputLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:id="@+id/layout_uri_input"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
android:layout_marginEnd="16dp"
|
||||
app:endIconCheckable="false"
|
||||
app:endIconDrawable="@drawable/ic_backspace_black"
|
||||
app:endIconMode="custom"
|
||||
app:errorIconDrawable="@drawable/ic_backspace_black"
|
||||
app:endIconMode="custom"
|
||||
|
||||
app:helperText="@string/add_link_helper"
|
||||
app:helperTextEnabled="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearLayout4">
|
||||
app:helperTextEnabled="true">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/field_uri_input"
|
||||
android:id="@+id/edit_text_uri_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
android:clickable="true"
|
||||
android:cursorVisible="true"
|
||||
android:hint="@string/add_link_hint"
|
||||
android:inputType="textNoSuggestions"
|
||||
@ -61,127 +52,94 @@
|
||||
android:textColorLink="@color/material_on_background_emphasis_high_type" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/scrollView"
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/spacer"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textInputLayout">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_text_event_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="@drawable/divider"
|
||||
android:orientation="vertical"
|
||||
android:showDividers="middle">
|
||||
android:focusable="false"
|
||||
android:cursorVisible="false"
|
||||
android:hint="Event name"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:singleLine="true"
|
||||
android:textColorLink="@color/material_on_background_emphasis_high_type" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/field_event_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:cursorVisible="true"
|
||||
android:hint="Event name"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:singleLine="true"
|
||||
android:textColorLink="@color/material_on_background_emphasis_high_type" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_text_event_start"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="false"
|
||||
android:cursorVisible="false"
|
||||
android:hint="Event start"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/field_event_start"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:cursorVisible="true"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:hint="Event start"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/field_event_end"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:cursorVisible="true"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:hint="Event end"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_text_event_end"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="false"
|
||||
android:cursorVisible="false"
|
||||
android:hint="Event end"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:id="@+id/location_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:endIconDrawable="@drawable/ic_add_location"
|
||||
app:endIconMode="custom">
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/layout_event_location"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:endIconDrawable="@drawable/ic_add_location"
|
||||
app:endIconMode="custom">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/field_event_location"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="map"
|
||||
android:clickable="true"
|
||||
android:cursorVisible="true"
|
||||
android:hint="Event location"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_text_event_location"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="map"
|
||||
android:focusable="false"
|
||||
android:cursorVisible="false"
|
||||
android:hint="Event location"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:singleLine="true" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/field_event_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
android:clickable="true"
|
||||
android:cursorVisible="true"
|
||||
android:hint="Event description"
|
||||
android:inputType="textNoSuggestions|textMultiLine"
|
||||
android:singleLine="false"
|
||||
android:textColorLink="@color/material_on_background_emphasis_high_type" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_text_event_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
android:focusable="false"
|
||||
android:cursorVisible="false"
|
||||
android:hint="Event description"
|
||||
android:inputType="textNoSuggestions|textMultiLine"
|
||||
android:singleLine="false"
|
||||
android:textColorLink="@color/material_on_background_emphasis_high_type" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<Space
|
||||
android:id="@+id/spacer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/constraint_layout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
Reference in New Issue
Block a user