fix event info hiding after activity restore (closes #23), add comments
This commit is contained in:
parent
ce790763fd
commit
9e81e3d74a
|
@ -60,6 +60,10 @@ public class EventAdapter extends
|
|||
// Set item views based on your views and data model
|
||||
holder.text_view_event_name.setText(event.name);
|
||||
|
||||
/*
|
||||
* initialize all text views with event information
|
||||
* hide fields and image views if no information is available
|
||||
*/
|
||||
if (!event.location.equals("")) {
|
||||
holder.text_view_event_location.setText(event.location);
|
||||
} else {
|
||||
|
@ -86,7 +90,6 @@ public class EventAdapter extends
|
|||
}
|
||||
|
||||
|
||||
|
||||
if (!event.description.equals("")) {
|
||||
holder.text_view_event_description.setText(event.description);
|
||||
} else {
|
||||
|
@ -120,13 +123,14 @@ public class EventAdapter extends
|
|||
};
|
||||
holder.image_view_event_location.setOnClickListener(location_click_listener);
|
||||
holder.text_view_event_location.setOnClickListener(location_click_listener);
|
||||
|
||||
/*
|
||||
* Add to calendar button: launch calendar application with current event
|
||||
*/
|
||||
holder.button_add_to_calendar.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
// calendar event intent expects epoch time format
|
||||
Long start_epoch = dateTimeToEpoch(event.start_date);
|
||||
Long end_epoch = dateTimeToEpoch(event.end_date);
|
||||
|
||||
|
@ -163,7 +167,7 @@ public class EventAdapter extends
|
|||
});
|
||||
|
||||
/*
|
||||
* Image dialog
|
||||
* Image preview click creates fullscreen dialog
|
||||
*/
|
||||
|
||||
View.OnClickListener listener = new View.OnClickListener() {
|
||||
|
@ -198,7 +202,6 @@ public class EventAdapter extends
|
|||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
holder.image_view_event_image.setOnClickListener(listener);
|
||||
|
@ -212,6 +215,9 @@ public class EventAdapter extends
|
|||
return events.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* access item view elements via holder class
|
||||
*/
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
protected TextView text_view_event_name;
|
||||
|
|
|
@ -163,6 +163,7 @@ public class FbEventScraper extends AsyncTask<Void, Void, Void> {
|
|||
|
||||
JSONObject reader = new JSONObject(json);
|
||||
|
||||
// get all fields from json event information
|
||||
name = readFromJson(reader, "name");
|
||||
start_date = parseToDate(readFromJson(reader, "startDate"));
|
||||
end_date = parseToDate(readFromJson(reader, "endDate"));
|
||||
|
@ -170,6 +171,7 @@ public class FbEventScraper extends AsyncTask<Void, Void, Void> {
|
|||
location = fixLocation(readFromJson(reader, "location"));
|
||||
image_url = readFromJson(reader, "image");
|
||||
|
||||
// try to find a high-res image
|
||||
try {
|
||||
image_url = document.select("div[id=event_header_primary]")
|
||||
.select("img").first().attr("src");
|
||||
|
@ -177,6 +179,7 @@ public class FbEventScraper extends AsyncTask<Void, Void, Void> {
|
|||
}
|
||||
|
||||
} catch (JSONException | NullPointerException e) {
|
||||
// json event information mot found. get at least title and image
|
||||
name = document.title();
|
||||
description = scraper.main.get().getString(R.string.error_scraping);
|
||||
try {
|
||||
|
@ -186,9 +189,6 @@ public class FbEventScraper extends AsyncTask<Void, Void, Void> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
this.event = new FbEvent(url, name, start_date, end_date, description, location, image_url);
|
||||
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -22,7 +22,7 @@ public class FbPageScraper extends AsyncTask<Void, Void, Void> {
|
|||
private FbScraper scraper;
|
||||
private int error;
|
||||
private String url;
|
||||
private List<String> event_links = new ArrayList<String>();
|
||||
private List<String> event_links = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructor with reference to scraper to return results.
|
||||
|
@ -58,6 +58,9 @@ public class FbPageScraper extends AsyncTask<Void, Void, Void> {
|
|||
throw new IOException();
|
||||
}
|
||||
|
||||
/*
|
||||
* get all event id's from current url and add to the list
|
||||
*/
|
||||
String regex = "(/events/[0-9]*)(/\\?event_time_id=[0-9]*)?";
|
||||
|
||||
List<String> event_links_href = document
|
||||
|
@ -68,13 +71,16 @@ public class FbPageScraper extends AsyncTask<Void, Void, Void> {
|
|||
this.event_links.add("https://www.facebook.com" + link);
|
||||
}
|
||||
|
||||
/*
|
||||
* check if more events should scraped
|
||||
*/
|
||||
SharedPreferences shared_prefs = PreferenceManager
|
||||
.getDefaultSharedPreferences(scraper.main.get());
|
||||
|
||||
int max = shared_prefs.getInt("page_event_max", 5);
|
||||
|
||||
if (event_links.size() < max) {
|
||||
|
||||
// find "next page
|
||||
try {
|
||||
String next_url = document
|
||||
.getElementsByAttributeValueMatching("href", "has_more=1")
|
||||
|
|
|
@ -14,15 +14,12 @@ import java.util.List;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.akdev.nofbeventscraper.FbEvent.createEventList;
|
||||
|
||||
public class FbScraper {
|
||||
|
||||
protected List<FbEvent> events;
|
||||
protected List<AsyncTask> tasks;
|
||||
protected WeakReference<MainActivity> main; // no context leak with WeakReference
|
||||
url_type_enum url_type = url_type_enum.EVENT;
|
||||
private String input_url;
|
||||
protected WeakReference<MainActivity> main; // no context leak with WeakReference
|
||||
|
||||
/**
|
||||
* Constructor with WeakReference to the main activity, to add events.
|
||||
|
@ -33,10 +30,18 @@ public class FbScraper {
|
|||
FbScraper(WeakReference<MainActivity> main, String input_url) {
|
||||
this.main = main;
|
||||
this.input_url = input_url;
|
||||
this.events = createEventList();
|
||||
this.tasks = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if valid URL,
|
||||
* strips the facebook page id from the input link and create an URL that can be scraped from.
|
||||
*
|
||||
* @param url input URL
|
||||
* @return new mbasic url that can be scraped for event id's
|
||||
* @throws URISyntaxException if page not found
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
protected String getPageUrl(String url) throws URISyntaxException, MalformedURLException {
|
||||
|
||||
// check for url format
|
||||
|
@ -48,10 +53,11 @@ public class FbScraper {
|
|||
Matcher matcher = pattern.matcher(url);
|
||||
|
||||
if (matcher.find()) {
|
||||
|
||||
//only mbasic does have event ids displayed in HTML
|
||||
String url_prefix = "https://mbasic.facebook.com/";
|
||||
String url_suffix = "?v=events";
|
||||
|
||||
// create URL
|
||||
return url_prefix + matcher.group(3) + url_suffix;
|
||||
|
||||
} else {
|
||||
|
@ -60,7 +66,7 @@ public class FbScraper {
|
|||
}
|
||||
|
||||
/**
|
||||
* Strips the facebook event link of the input url.
|
||||
* Strips the facebook event link from the input event url.
|
||||
*
|
||||
* @param url input url
|
||||
* @return facebook event url String if one was found
|
||||
|
@ -98,12 +104,40 @@ public class FbScraper {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* cancel vestigial async tasks
|
||||
*/
|
||||
void killAllTasks() {
|
||||
|
||||
if (!tasks.isEmpty()) {
|
||||
for (AsyncTask task : tasks) {
|
||||
try {
|
||||
task.cancel(true);
|
||||
task = null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* start an EventScraper async task and add to tasks list
|
||||
*
|
||||
* @param event_url
|
||||
*/
|
||||
void scrapeEvent(String event_url) {
|
||||
FbEventScraper scraper = new FbEventScraper(this, event_url);
|
||||
tasks.add(scraper);
|
||||
scraper.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for finished EventSCraper async task
|
||||
*
|
||||
* @param event Contains event information if scraping successful
|
||||
* @param error resId for error message
|
||||
*/
|
||||
void scrapeEventResultCallback(FbEvent event, int error) {
|
||||
|
||||
if (event != null) {
|
||||
|
@ -115,20 +149,10 @@ public class FbScraper {
|
|||
}
|
||||
|
||||
/**
|
||||
* cancel vestigial async tasks
|
||||
* start a page scraper and add to list of tasks
|
||||
*
|
||||
* @param page_url
|
||||
*/
|
||||
void killAllTasks() {
|
||||
|
||||
try {
|
||||
for (AsyncTask task : tasks) {
|
||||
task.cancel(true);
|
||||
task = null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
void scrapePage(String page_url) {
|
||||
FbPageScraper scraper = new FbPageScraper(this, page_url);
|
||||
|
||||
|
@ -136,6 +160,12 @@ public class FbScraper {
|
|||
scraper.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for page scraper async task
|
||||
*
|
||||
* @param event_urls List of event urls scraped from the event
|
||||
* @param error resId of error message if task list is empty
|
||||
*/
|
||||
protected void scrapePageResultCallback(List<String> event_urls, int error) {
|
||||
|
||||
if (event_urls.size() > 0) {
|
||||
|
@ -153,8 +183,12 @@ public class FbScraper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start scraping input url
|
||||
*/
|
||||
void run() {
|
||||
|
||||
// check if input url is an event
|
||||
try {
|
||||
String event_url = getEventUrl(input_url);
|
||||
url_type = url_type_enum.EVENT;
|
||||
|
@ -165,7 +199,7 @@ public class FbScraper {
|
|||
} catch (URISyntaxException | MalformedURLException e) {
|
||||
url_type = url_type_enum.INVALID;
|
||||
}
|
||||
|
||||
// check if input url is a page
|
||||
try {
|
||||
String page_url = getPageUrl(input_url);
|
||||
url_type = url_type_enum.PAGE;
|
||||
|
@ -177,6 +211,6 @@ public class FbScraper {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// enum for storing url type in this class
|
||||
enum url_type_enum {EVENT, PAGE, INVALID}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
package com.akdev.nofbeventscraper;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class IntentReceiver extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.ClipboardManager;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
|
@ -65,17 +64,24 @@ public class MainActivity extends AppCompatActivity {
|
|||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for Restoring data
|
||||
/*
|
||||
* On resume from other activities, e.g. settings
|
||||
*/
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
events.clear();
|
||||
events.addAll(getSavedEvents());
|
||||
adapter.notifyDataSetChanged();
|
||||
/*
|
||||
* Clear events after saved events deleted from settings
|
||||
*/
|
||||
if (getSavedEvents().isEmpty()) {
|
||||
events.clear();
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/*
|
||||
* Intent from IntentReceiver - read only once
|
||||
*/
|
||||
Intent intent = getIntent();
|
||||
String data = intent.getStringExtra("InputLink");
|
||||
|
||||
|
@ -209,7 +215,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
/**
|
||||
* launch the FbScraper asynchronous task with the current text in the input text field.
|
||||
* launch the FbScraper with the current text in the input text field.
|
||||
*/
|
||||
public void startScraping() {
|
||||
|
||||
|
@ -222,6 +228,12 @@ public class MainActivity extends AppCompatActivity {
|
|||
scraper.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* manage Helper text on uri_input
|
||||
*
|
||||
* @param str What should be displayed
|
||||
* @param error True if should be displayed as error
|
||||
*/
|
||||
public void input_helper(String str, boolean error) {
|
||||
|
||||
if (str == null) {
|
||||
|
@ -255,14 +267,21 @@ public class MainActivity extends AppCompatActivity {
|
|||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
|
||||
/*
|
||||
* Display icons, restricted API, maybe find other solution?
|
||||
*/
|
||||
if (menu instanceof MenuBuilder) {
|
||||
MenuBuilder m = (MenuBuilder) menu;
|
||||
//noinspection RestrictedApi
|
||||
m.setOptionalIconsVisible(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch menu item to new activity
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
package com.akdev.nofbeventscraper;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity {
|
||||
|
||||
|
@ -37,6 +32,9 @@ public class SettingsActivity extends AppCompatActivity {
|
|||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
setPreferencesFromResource(R.xml.root_preferences, rootKey);
|
||||
|
||||
/*
|
||||
* reset events click action: delete saved events and display snackbar
|
||||
*/
|
||||
Preference button = findPreference("event_reset");
|
||||
if (button != null) {
|
||||
button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
|
@ -52,11 +50,11 @@ public class SettingsActivity extends AppCompatActivity {
|
|||
getString(R.string.preferences_event_snackbar), Snackbar.LENGTH_SHORT)
|
||||
.setAction(R.string.undo, new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
prefs.edit().putString("events", undo).apply();
|
||||
}
|
||||
}).show();
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
prefs.edit().putString("events", undo).apply();
|
||||
}
|
||||
}).show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue