add shared prefs, cleanup

This commit is contained in:
akaessens 2020-09-26 14:04:43 +02:00
parent 0506b5dfa0
commit 63de4b4a4f
10 changed files with 125 additions and 118 deletions

View File

@ -24,27 +24,30 @@ android {
}
dependencies {
'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
// androidx
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.navigation:navigation-fragment:2.3.0'
implementation 'androidx.navigation:navigation-ui:2.3.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.preference:preference:1.1.1'
implementation "androidx.webkit:webkit:1.3.0"
// jsoup HTML parser library @ https://jsoup.org/
// JSON save/restore shared preference
implementation 'com.google.code.gson:gson:2.8.5'
// Theme
implementation 'com.google.android.material:material:1.2.1'
// Scraping
implementation 'org.jsoup:jsoup:1.13.1'
// Image loading and transforming
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'jp.wasabeef:picasso-transformations:2.2.1'
implementation 'androidx.preference:preference:1.1.1'
implementation "androidx.webkit:webkit:1.3.0"
// tests
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

View File

@ -200,7 +200,6 @@ public class FbScraper extends AsyncTask<Void, Void, Void> {
Document document = Jsoup.connect(url).userAgent(user_agent).get();
if (document == null) {
throw new IOException();
}
String json = document
.select("script[type = application/ld+json]")
@ -228,10 +227,6 @@ public class FbScraper extends AsyncTask<Void, Void, Void> {
FbEvent event = new FbEvent(url, name, start_date, end_date, description, location, image_url);
this.events.add(event);
this.events.add(event);
this.events.add(new FbEvent());
this.events.add(event);
this.events.add(event);
} catch (URISyntaxException | MalformedURLException e) {
e.printStackTrace();
@ -266,10 +261,9 @@ public class FbScraper extends AsyncTask<Void, Void, Void> {
if (main != null) {
if (! this.events.isEmpty()) {
main.get().update(events);
main.get().addEvents(this.events);
} else {
main.get().error(error);
main.get().clear(false);
}
}
}

View File

@ -4,18 +4,19 @@ import android.annotation.SuppressLint;
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.text.Layout;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.menu.MenuBuilder;
import androidx.appcompat.widget.Toolbar;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -24,9 +25,11 @@ import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.squareup.picasso.Picasso;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Objects;
@ -46,23 +49,48 @@ public class MainActivity extends AppCompatActivity {
EventAdapter adapter;
LinearLayoutManager linear_layout_manager;
@Override
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
private List<FbEvent> getSavedEvents() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (!state.getBoolean("events_empty")) {
startScraping();
Gson gson = new Gson();
String json = prefs.getString("events", "");
Type event_list_type = new TypeToken<List<FbEvent>>() {
}.getType();
List<FbEvent> list = gson.fromJson(json, event_list_type);
if (list == null) {
list = createEventList();
}
return list;
}
/**
* Callback after clearing events from settings needed.
*/
@Override
public void onSaveInstanceState(Bundle state) {
public void onRestart() {
super.onRestart();
events.clear();
events.addAll(getSavedEvents());
adapter.notifyDataSetChanged();
}
/**
* Save events list to SharedPreferences as JSON
*/
@Override
public void onSaveInstanceState(@NonNull Bundle state) {
super.onSaveInstanceState(state);
state.putBoolean("events_empty", events.isEmpty());
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor prefs_edit = prefs.edit();
Gson gson = new Gson();
String json = gson.toJson(events);
prefs_edit.putString("events", json);
prefs_edit.apply();
}
@Override
@ -78,11 +106,11 @@ public class MainActivity extends AppCompatActivity {
paste_button = findViewById(R.id.paste_button);
/*
* initialize recycler view with empty list of events
* initialize recycler view with saved list of events
* scroll horizontal with snapping
*/
RecyclerView recycler_view = findViewById(R.id.recycler_view);
events = createEventList();
this.events = getSavedEvents();
adapter = new EventAdapter(events);
recycler_view.setAdapter(adapter);
linear_layout_manager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
@ -94,7 +122,6 @@ public class MainActivity extends AppCompatActivity {
* Display title only when toolbar is collapsed
*/
AppBarLayout app_bar_layout = findViewById(R.id.app_bar);
app_bar_layout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean show = true;
int scroll_range = -1;
@ -114,6 +141,7 @@ public class MainActivity extends AppCompatActivity {
}
}
});
/*
* Paste button: get last entry from clipboard
*/
@ -125,7 +153,6 @@ public class MainActivity extends AppCompatActivity {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
String str = clipboard.getPrimaryClip().getItemAt(0).getText().toString();
clear(true);
edit_text_uri_input.setText(str);
startScraping();
@ -137,16 +164,15 @@ public class MainActivity extends AppCompatActivity {
});
/*
* Clear button: delete all events
* Error in input: clear input on click
*/
View.OnClickListener listener = new View.OnClickListener() {
layout_uri_input.setErrorIconOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
clear(true);
layout_uri_input.setError(null);
edit_text_uri_input.setText(null);
}
};
layout_uri_input.setEndIconOnClickListener(listener);
layout_uri_input.setErrorIconOnClickListener(listener);
});
/*
@ -163,7 +189,6 @@ public class MainActivity extends AppCompatActivity {
}
});
/*
* Get data from intent: if launched by other application
* via "share to" or "open with"
@ -181,10 +206,6 @@ public class MainActivity extends AppCompatActivity {
edit_text_uri_input.setText(shared_text);
startScraping();
}
}
/**
@ -208,39 +229,16 @@ public class MainActivity extends AppCompatActivity {
}
/**
* Clears all event text field strings and errors and also the input field depending if wanted.
* Loads the default banner into the toolbar image view and disables unneeded buttons.
* Adds new events to the start of the events list.
*
* @param clear_uri Choose whether to clear the input uri field, too
* @param new_events the list of events that was scraped by FbScraper
*/
public void clear(boolean clear_uri) {
public void addEvents(List<FbEvent> new_events) {
if (clear_uri) {
edit_text_uri_input.setText("");
layout_uri_input.setError(null);
if (new_events != null) {
this.events.addAll(0, new_events);
this.adapter.notifyDataSetChanged();
}
if (scraper != null) {
scraper.cancel(true);
scraper = null;
}
this.events.clear();
adapter.notifyDataSetChanged();
}
/**
* Updates the text fields with the event information provided.
* If something is missing, the corresponding test field will show an error.
*
* @param events the event information that was scraped by FbScraper
*/
public void update(List<FbEvent> events) {
this.events.clear();
this.events.addAll(events);
adapter.notifyDataSetChanged();
}
@SuppressLint("RestrictedApi")
@ -259,12 +257,9 @@ public class MainActivity extends AppCompatActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_about) {
startActivity(new Intent(this, AboutActivity.class));
return true;

View File

@ -1,10 +1,20 @@
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 {
@ -26,6 +36,25 @@ public class SettingsActivity extends AppCompatActivity {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.root_preferences, rootKey);
Preference button = findPreference("event_reset");
if (button != null) {
button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
SharedPreferences prefs = preference.getSharedPreferences();
prefs.edit().remove("events").apply();
Snackbar.make(getActivity().findViewById(android.R.id.content),
getString(R.string.preferences_event_snackbar), Snackbar.LENGTH_SHORT).show();
return true;
}
});
}
}
}
}

View File

@ -33,7 +33,7 @@
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/ic_banner_foreground"
app:layout_collapseMode="parallax" />
app:layout_collapseMode="pin" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"

View File

@ -12,23 +12,18 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
android:layout_marginTop="16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/layout_uri_input"
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:layout_margin="16dp"
app:endIconCheckable="false"
app:endIconDrawable="@drawable/ic_backspace_black"
app:endIconMode="custom"
app:endIconMode="clear_text"
app:errorIconDrawable="@drawable/ic_backspace_black"
app:helperText="@string/helper_add_link"
app:helperTextEnabled="true">

View File

@ -33,7 +33,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/error_no_name"
android:text="@string/event_placeholder"
android:textAppearance="?attr/textAppearanceHeadline6" />
</LinearLayout>
@ -60,7 +60,7 @@
android:id="@+id/text_view_event_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/error_no_location"
android:text="@string/event_placeholder"
android:textAppearance="?attr/textAppearanceBody1" />
</LinearLayout>
@ -92,14 +92,14 @@
android:id="@+id/text_view_event_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/error_no_start_date"
android:text="@string/event_placeholder"
android:textAppearance="?attr/textAppearanceBody2" />
<TextView
android:id="@+id/text_view_event_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/error_no_end_date"
android:text="@string/event_placeholder"
android:textAppearance="?attr/textAppearanceBody2" />
</LinearLayout>
@ -113,7 +113,7 @@
android:layout_margin="8dp"
android:ellipsize="end"
android:maxLines="5"
android:text="abc\nabc\nabc\nabc\nabc\nabc\nabc\n"
android:text="@string/event_placeholder"
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?android:attr/textColorSecondary" />

View File

@ -5,24 +5,17 @@
<string name="action_help">Hilfe</string>
<string name="action_settings">Einstellungen</string>
<string name="hint_add_link">Veranstaltungslink</string>
<string name="hint_event_name">Veranstaltungsname</string>
<string name="hint_event_start">Veranstaltungsbeginn</string>
<string name="hint_event_end">Veranstantungsende</string>
<string name="hint_event_location">Veranstaltungsort</string>
<string name="hint_event_description">Veranstaltungsbeschreibung</string>
<string name="helper_add_link">Facebook-Link zur Veranstaltung einfügen</string>
<string name="button_add">Zum Kalender hinzufügen</string>
<string name="tooltip_paste">Einfügen von Inhalten aus der Zwischenablage in das URL-Eingabefeld</string>
<string name="preferences_url_setting">Welcher URL-Präfix ist zu verwenden?</string>
<string name="preferences_url_setting_summary">Die Nutzung von m.facebook.com ist stabiler und schneller. Die Verwendung von www.facebook.com funktioniert besser bei Ereignissen mit mehreren Instanzen und zeigt eine hochauflösende Vorschau an, geht aber irgendwann kaputt, wenn Facebook das klassische Design deaktiviert.</string>
<string name="error_clipboard_empty">Fehler: Zwischenablage leer</string>
<string name="error_no_name">Fehler: Veranstaltungsname nicht verfügbar</string>
<string name="error_no_start_date">Fehler: Veranstaltungsbeginn nicht verfügbar</string>
<string name="error_no_end_date">Fehler: Veranstaltungsende nicht verfügbar</string>
<string name="error_no_location">Fehler: Veranstaltungsort nicht verfügbar</string>
<string name="error_no_description">Fehler: Veranstaltungsbeschreibung nicht verfügbar</string>
<string name="error_scraping">Fehler: Veranstaltungsdaten nicht gefunden</string>
<string name="error_url">Fehler: URL ungültig</string>
<string name="error_connection">Fehler: Keine Verbindung möglich</string>
<string name="error_unknown">Fehler: Unbekannter Fehler</string>
<string name="preferences_events_header">Veranstaltungen</string>
<string name="preferences_event_setting">Veranstaltungsliste löschen</string>
<string name="preferences_event_snackbar">"Veranstaltungen gelöscht "</string>
</resources>

View File

@ -8,11 +8,6 @@
<!-- Input hints -->
<string name="hint_add_link">Event link</string>
<string name="hint_event_name">Event name</string>
<string name="hint_event_start">Event start</string>
<string name="hint_event_end">Event end</string>
<string name="hint_event_location">Event location</string>
<string name="hint_event_description">Event description</string>
<string name="helper_add_link">Paste Facebook link to the event</string>
@ -21,11 +16,6 @@
<!-- Errors -->
<string name="error_clipboard_empty">Error: clipboard empty</string>
<string name="error_no_name">Error: Event name unavailable</string>
<string name="error_no_start_date">Error: Event start date unavailable</string>
<string name="error_no_end_date">Error: Event end date unavailable</string>
<string name="error_no_location">Error: Event location unavailable</string>
<string name="error_no_description">Error: Event description unavailable</string>
<string name="error_scraping">Error: Scraping event data failed</string>
<string name="error_url">Error: URL invalid</string>
<string name="error_connection">Error: Unable to connect</string>
@ -33,10 +23,12 @@
<!-- Preferences -->
<string name="preferences_scraper_header" translatable="false">Scraper</string>
<string name="preferences_url_setting">Which URL prefix to use</string>
<string name="preferences_url_setting_summary">"Using m.facebook.com is more stable and faster. Using www.facebook.com works better with multiple instance events and will display a high resolution preview but will eventually break when Facebook disables the classic design. "</string>
<string name="preferences_events_header">Events</string>
<string name="preferences_event_setting">Clear event list</string>
<string name="preferences_event_snackbar">Events list cleared</string>
<string name="event_placeholder" translatable="false">Placeholder</string>
</resources>

View File

@ -5,17 +5,23 @@
<ListPreference
android:summary="@string/preferences_url_setting_summary"
app:defaultValue="https://m."
app:entries="@array/url_to_scrape"
app:entryValues="@array/url_prefix"
app:key="url_preference"
app:title="@string/preferences_url_setting"
android:summary="@string/preferences_url_setting_summary"/>
app:title="@string/preferences_url_setting" />
</PreferenceCategory>
<PreferenceCategory app:title="@string/preferences_events_header">
<Preference
android:key="event_reset"
android:title="@string/preferences_event_setting" />
</PreferenceCategory>
</PreferenceScreen>