From 3429fad192f4ba8a7730b1a8cb352a4a0d50f5b8 Mon Sep 17 00:00:00 2001 From: Justy Date: Sun, 1 Dec 2019 22:54:51 +0100 Subject: [PATCH 01/32] Impl. History based on master --- .../opacclient/objects/HistoryItem.java | 231 ++++++ .../opacapp/src/main/AndroidManifest.xml | 5 + .../geeksfactory/opacclient/OpacClient.java | 6 + .../opacclient/frontend/AccountFragment.java | 12 + .../opacclient/frontend/HistoryFragment.java | 694 ++++++++++++++++++ .../opacclient/frontend/MainActivity.java | 2 +- .../opacclient/frontend/OpacActivity.java | 4 + .../storage/HistoryContentProvider.java | 214 ++++++ .../opacclient/storage/HistoryDataSource.java | 411 +++++++++++ .../opacclient/storage/HistoryDatabase.java | 111 +++ .../src/main/res/drawable/ic_clock_24dp.xml | 18 + .../main/res/drawable/ic_sort_white_24dp.xml | 9 + .../src/main/res/layout/fragment_history.xml | 25 + .../src/main/res/layout/listitem_history.xml | 39 + .../main/res/layout/listitem_history_item.xml | 111 +++ .../src/main/res/menu/activity_history.xml | 54 ++ .../src/main/res/menu/navigation_drawer.xml | 4 + .../src/main/res/values-de/strings.xml | 19 + .../opacapp/src/main/res/values/strings.xml | 19 + 19 files changed, 1987 insertions(+), 1 deletion(-) create mode 100644 opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java create mode 100644 opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java create mode 100644 opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryContentProvider.java create mode 100644 opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java create mode 100644 opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java create mode 100644 opacclient/opacapp/src/main/res/drawable/ic_clock_24dp.xml create mode 100644 opacclient/opacapp/src/main/res/drawable/ic_sort_white_24dp.xml create mode 100644 opacclient/opacapp/src/main/res/layout/fragment_history.xml create mode 100644 opacclient/opacapp/src/main/res/layout/listitem_history.xml create mode 100644 opacclient/opacapp/src/main/res/layout/listitem_history_item.xml create mode 100644 opacclient/opacapp/src/main/res/menu/activity_history.xml diff --git a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java new file mode 100644 index 000000000..f7cd32673 --- /dev/null +++ b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java @@ -0,0 +1,231 @@ +package de.geeksfactory.opacclient.objects; + +import org.joda.time.LocalDate; + +import java.io.Serializable; + +public class HistoryItem extends AccountItem implements Serializable { + + private int historyId; // Unique Id in HistoryDatabase + + private LocalDate firstDate; // firstDate the Iten was in Accout + private LocalDate lastDate; // lastDate Item was seen in Account + private boolean lending; // Is currently lent? + + private String bib; + private String homeBranch; + private String lendingBranch; + private boolean ebook; + private String barcode; + + private LocalDate deadline; + private int prolongCount = 0; + + public void setProlongCount(int count) { + prolongCount = count; + } + + public int getProlongCount() { + return prolongCount; + } + + public LocalDate getDeadline() { return deadline; } + public void setDeadline(LocalDate deadline) { + this.deadline = deadline; + } + + /** + * @return Barcode/unique identifier of a lent item. Should be set. + */ + public String getBarcode() { + return barcode; + } + + /** + * Set barcode/unique identifier of a lent item. Should be set. + */ + public void setBarcode(String barcode) { + this.barcode = barcode; + } + + /** + * @return Return firstDate for a history item. Should be set. + */ + public LocalDate getFirstDate() { + return firstDate; + } + + /** + * Set return firstDate for a history item + */ + public void setFirstDate(LocalDate firstDate) { + this.firstDate = firstDate; + } + + public boolean isLending() { + return lending; + } + + public void setLending(boolean lending) { + this.lending = lending; + } + + /** + * @return Return lastDate for a history item. Should be set. + */ + public LocalDate getLastDate() { + return lastDate; + } + + /** + * Set return lastDate for a history item + */ + public void setLastDate(LocalDate lastDate) { + this.lastDate = lastDate; + } + + /** + * @return Library branch the item belongs to. Optional. + */ + public String getHomeBranch() { + return homeBranch; + } + + /** + * Set library branch the item belongs to. Optional. + */ + public void setHomeBranch(String homeBranch) { + this.homeBranch = homeBranch; + } + + /** + * @return Library branch the item was lent from. Optional. + */ + public String getLendingBranch() { + return lendingBranch; + } + + /** + * Set library branch the item was lent from. Optional. + */ + public void setLendingBranch(String lendingBranch) { + this.lendingBranch = lendingBranch; + } + + /** + * @return Whether this item is an eBook. Optional, defaults to false. + */ + public boolean isEbook() { + return ebook; + } + + /** + * Set whether this item is an eBook. Optional, defaults to false. + */ + public void setEbook(boolean ebook) { + this.ebook = ebook; + } + + @Override + public void set(String key, String value) { + if ("".equals(value)) { + value = null; + } + switch (key) { + case "barcode": + setBarcode(value); + break; + case "homebranch": + setHomeBranch(value); + break; + case "lendingbranch": + setLendingBranch(value); + break; + default: + super.set(key, value); + break; + } + } + + public String getBib() { + return bib; + } + public void setBib(String bib) { + this.bib = bib; + } + + public int getHistoryId() { + return historyId; + } + public void setHistoryId(int historyId) { + this.historyId = historyId; + } + + // MNr wie bei Starred + public String getMNr() { + return super.getId(); + } + public void setMNr(String mnr) { + super.setId(mnr); + } + + public boolean isSameAsLentItem(LentItem lentItem) { + + if (getMediaType() == null) { + if (lentItem.getMediaType() != null) { + return false; + } + } else { + if (!this.getMediaType().equals(lentItem.getMediaType())) { + return false; + } + } + + if (getTitle() == null) { + if (lentItem.getTitle() != null) { + return false; + } + } else { + if (!this.getTitle().equals(lentItem.getTitle())) { + return false; + } + } + if (getAuthor() == null) { + if (lentItem.getAuthor() != null) { + return false; + } + } else { + if (!this.getAuthor().equals(lentItem.getAuthor())) { + return false; + } + } + + // TODO: Prüfen ob weitere Werte übereinstimmen sollten + + return true; + } + + @Override + public String toString() { + return "HistoryItem{" + + "account=" + account + + ", title='" + title + '\'' + + ", author='" + author + '\'' + + ", format='" + format + '\'' + + ", mediaType=" + mediaType + + ", firstDate='" + firstDate + '\'' + + ", lastDate='" + lastDate + '\'' + + ", lending='" + lending + '\'' + + ", id='" + id + '\'' + + ", status='" + status + '\'' + + ", historyId=" + historyId + + ", cover='" + cover + '\'' + + ", barcode='" + barcode + '\'' + + ", homeBranch='" + homeBranch + '\'' + + ", lendingBranch='" + lendingBranch + '\'' + + ", ebook=" + ebook + '\'' + + ", deadline=" + deadline + '\'' + + ", prolongCount=" + prolongCount + + '}'; + } +} diff --git a/opacclient/opacapp/src/main/AndroidManifest.xml b/opacclient/opacapp/src/main/AndroidManifest.xml index 32ab91431..c2bbbb8c4 100644 --- a/opacclient/opacapp/src/main/AndroidManifest.xml +++ b/opacclient/opacapp/src/main/AndroidManifest.xml @@ -173,6 +173,11 @@ android:authorities="${applicationId}.starprovider" android:exported="false"/> + + diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/OpacClient.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/OpacClient.java index 175eb4310..faf3b35a3 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/OpacClient.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/OpacClient.java @@ -70,6 +70,7 @@ import de.geeksfactory.opacclient.searchfields.SearchField; import de.geeksfactory.opacclient.searchfields.SearchQuery; import de.geeksfactory.opacclient.storage.AccountDataSource; +import de.geeksfactory.opacclient.storage.HistoryContentProvider; import de.geeksfactory.opacclient.storage.PreferenceDataSource; import de.geeksfactory.opacclient.storage.StarContentProvider; import de.geeksfactory.opacclient.utils.DebugTools; @@ -98,6 +99,7 @@ public class OpacClient extends Application { private static OpacClient instance; public final boolean SLIDING_MENU = true; private final Uri STAR_PROVIDER_STAR_URI = StarContentProvider.STAR_URI; + private final Uri HISTORY_PROVIDER_STAR_URI = HistoryContentProvider.HIST_URI; protected Account account; protected OpacApi api; protected Library library; @@ -175,6 +177,10 @@ public Uri getStarProviderStarUri() { return STAR_PROVIDER_STAR_URI; } + public Uri getHistoryProviderHistoryUri() { + return HISTORY_PROVIDER_STAR_URI; + } + public void addFirstAccount(Activity activity) { Intent intent = new Intent(activity, LibraryListActivity.class); intent.putExtra(LibraryListActivity.EXTRA_WELCOME, true); diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java index f343fd968..fe93e58ee 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java @@ -104,6 +104,7 @@ import de.geeksfactory.opacclient.reminder.ReminderHelper; import de.geeksfactory.opacclient.reminder.SyncAccountJobCreator; import de.geeksfactory.opacclient.storage.AccountDataSource; +import de.geeksfactory.opacclient.storage.HistoryDataSource; import de.geeksfactory.opacclient.storage.PreferenceDataSource; import de.geeksfactory.opacclient.ui.AccountDividerItemDecoration; import de.geeksfactory.opacclient.utils.ErrorReporter; @@ -1474,6 +1475,17 @@ protected AccountData doInBackground(Void... voids) { account.setPasswordKnownValid(true); adatasource.update(account); adatasource.storeCachedAccountData(adatasource.getAccount(data.getAccount()), data); + + // Update Lent-History + HistoryDataSource historyDataSource; + if (getActivity() == null && OpacClient.getEmergencyContext() != null) { + // TODO HistoryDataSource erwartet Activity + // historyDataSource = new HistoryDataSource(OpacClient.getEmergencyContext()); + } else { + historyDataSource = new HistoryDataSource(getActivity()); + historyDataSource.updateLenting(adatasource.getAccount(data.getAccount()), data); + } + } finally { new ReminderHelper(app).generateAlarms(); } diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java new file mode 100644 index 000000000..ae88e0f28 --- /dev/null +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -0,0 +1,694 @@ +/** + * Copyright (C) 2013 by Raphael Michel under the MIT license: + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software + * is furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +package de.geeksfactory.opacclient.frontend; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.graphics.Typeface; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.Html; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.style.StyleSpan; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MenuInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.material.snackbar.Snackbar; + +import org.joda.time.Days; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import androidx.cursoradapter.widget.SimpleCursorAdapter; +import androidx.fragment.app.Fragment; +import androidx.loader.app.LoaderManager.LoaderCallbacks; +import androidx.loader.content.CursorLoader; +import androidx.loader.content.Loader; +import de.geeksfactory.opacclient.OpacClient; +import de.geeksfactory.opacclient.R; +import de.geeksfactory.opacclient.frontend.OpacActivity.AccountSelectedListener; +import de.geeksfactory.opacclient.objects.Account; +import de.geeksfactory.opacclient.objects.HistoryItem; +import de.geeksfactory.opacclient.searchfields.SearchField; +import de.geeksfactory.opacclient.searchfields.SearchField.Meaning; +import de.geeksfactory.opacclient.searchfields.SearchQuery; +import de.geeksfactory.opacclient.storage.HistoryDataSource; +import de.geeksfactory.opacclient.storage.HistoryDatabase; +import de.geeksfactory.opacclient.storage.JsonSearchFieldDataSource; +import de.geeksfactory.opacclient.utils.CompatibilityUtils; + +public class HistoryFragment extends Fragment implements + LoaderCallbacks, AccountSelectedListener { + + private static final String STATE_ACTIVATED_POSITION = "activated_position"; + private static final String JSON_LIBRARY_NAME = "library_name"; + private static final String JSON_HISTORY_LIST = "history_list"; + private static final String JSON_ITEM_MNR = "item_mnr"; + private static final String JSON_ITEM_TITLE = "item_title"; + private static final String JSON_ITEM_MEDIATYPE = "item_mediatype"; + private static final int REQUEST_CODE_EXPORT = 123; + private static final int REQUEST_CODE_IMPORT = 124; + + protected View view; + protected OpacClient app; + private ItemListAdapter adapter; + private Callback callback; + private ListView listView; + private int activatedPosition = ListView.INVALID_POSITION; + private TextView tvWelcome; + private HistoryItem historyItem; + + private String sortOrder = null; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + setHasOptionsMenu(true); + + view = inflater.inflate(R.layout.fragment_history, container, false); + app = (OpacClient) getActivity().getApplication(); + + adapter = new ItemListAdapter(); + + listView = (ListView) view.findViewById(R.id.lvHistory); + tvWelcome = (TextView) view.findViewById(R.id.tvHistoryWelcome); + + listView.setOnItemClickListener(new OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, + int position, long id) { + HistoryItem item = (HistoryItem) view.findViewById(R.id.ivDelete) + .getTag(); + if (item.getMNr() == null || item.getMNr().equals("null") + || item.getMNr().equals("")) { + + SharedPreferences sp = PreferenceManager + .getDefaultSharedPreferences(getActivity()); + List query = new ArrayList<>(); + List fields = new JsonSearchFieldDataSource( + app).getSearchFields(app.getLibrary().getIdent()); + if (fields != null) { + SearchField title_field = null, free_field = null; + for (SearchField field : fields) { + if (field.getMeaning() == Meaning.TITLE) { + title_field = field; + } else if (field.getMeaning() == Meaning.FREE) { + free_field = field; + } else if (field.getMeaning() == Meaning.HOME_BRANCH) { + query.add(new SearchQuery(field, sp.getString( + OpacClient.PREF_HOME_BRANCH_PREFIX + + app.getAccount().getId(), + null))); + } + } + if (title_field != null) { + query.add(new SearchQuery(title_field, item + .getTitle())); + } else if (free_field != null) { + query.add(new SearchQuery(free_field, item + .getTitle())); + } + app.startSearch(getActivity(), query); + } else { + Toast.makeText(getActivity(), R.string.no_search_cache, + Toast.LENGTH_LONG).show(); + } + } else { + callback.showDetail(item.getMNr()); + } + } + }); + listView.setClickable(true); + listView.setTextFilterEnabled(true); + + getActivity().getSupportLoaderManager() + .initLoader(0, null, this); + listView.setAdapter(adapter); + + // Restore the previously serialized activated item position. + if (savedInstanceState != null + && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) { + setActivatedPosition(savedInstanceState + .getInt(STATE_ACTIVATED_POSITION)); + } + + setActivateOnItemClick(((OpacActivity) getActivity()).isTablet()); + + return view; + } + + @Override + public void onCreateOptionsMenu(android.view.Menu menu, + MenuInflater inflater) { + inflater.inflate(R.menu.activity_history, menu); + super.onCreateOptionsMenu(menu, inflater); + } + + @Override + public boolean onOptionsItemSelected(android.view.MenuItem item) { + if (item.getItemId() == R.id.action_export) { + share(); + return true; + } else if (item.getItemId() == R.id.action_export_to_storage) { + exportToStorage(); + return true; + } else if (item.getItemId() == R.id.action_import_from_storage) { + importFromStorage(); + return true; + } else if (item.getItemId() == R.id.action_sort_author) { + sort("author"); + return true; + } else if (item.getItemId() == R.id.action_sort_title) { + sort("title"); + return true; + } else if (item.getItemId() == R.id.action_sort_firstDate) { + sort("firstDate"); + return true; + } else if (item.getItemId() == R.id.action_sort_lastDate) { + sort("lastDate"); + return true; + } else if (item.getItemId() == R.id.action_sort_prolongCount) { + sort("prolongCount"); + return true; + } else if (item.getItemId() == R.id.action_sort_duration) { + sort("julianday(lastDate) - julianday(firstDate)"); + return true; + } + return super.onOptionsItemSelected(item); + } + + private void sort(String orderby) { + + if (sortOrder == null) { + // bisher nicht sortiert + sortOrder = orderby + " ASC"; + } else if (sortOrder.startsWith(orderby)) { + // bereits nach dieser Spalte sortiert + // d.h. ASC/DESC swappen + if (sortOrder.equals(orderby + " ASC")) { + sortOrder = orderby + " DESC"; + } else { + sortOrder = orderby + " ASC"; + } + } else { + // bisher nach anderer Spalte sortiert + // zunächst ASC + sortOrder = orderby + " ASC"; + } + + // Loader restarten + getActivity().getSupportLoaderManager().restartLoader(0, null, this); + } + + @Override + public void accountSelected(Account account) { + getActivity().getSupportLoaderManager().restartLoader(0, null, this); + } + + public void remove(HistoryItem item) { + HistoryDataSource data = new HistoryDataSource(getActivity()); + historyItem = item; + showSnackBar(); + data.remove(item); + } + + //Added code to show SnackBar when clicked on Remove button in Favorites screen + private void showSnackBar() { + Snackbar snackbar = + Snackbar.make(view, getString(R.string.history_removed), Snackbar.LENGTH_LONG); + snackbar.setAction(R.string.history_removed_undo, new OnClickListener() { + + @Override + public void onClick(View view) { + HistoryDataSource data = new HistoryDataSource(getActivity()); + // String bib = app.getLibrary().getIdent(); + data.insertHistoryItem(historyItem); + } + }); + snackbar.show(); + } + + @Override + public Loader onCreateLoader(int arg0, Bundle arg1) { + if (app.getLibrary() != null) { + return new CursorLoader(getActivity(), + app.getHistoryProviderHistoryUri(), HistoryDatabase.COLUMNS, + HistoryDatabase.HIST_WHERE_LIB, new String[]{app + .getLibrary().getIdent()}, sortOrder); + } else { + return null; + } + } + + @Override + public void onLoadFinished(Loader loader, Cursor cursor) { + adapter.swapCursor(cursor); + if (cursor.getCount() == 0) { + tvWelcome.setVisibility(View.VISIBLE); + } else { + tvWelcome.setVisibility(View.GONE); + } + } + + @Override + public void onLoaderReset(Loader arg0) { + adapter.swapCursor(null); + } + + protected void share() { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("text/plain"); + intent.addFlags(CompatibilityUtils.getNewDocumentIntentFlag()); + + StringBuilder text = new StringBuilder(); + + HistoryDataSource data = new HistoryDataSource(getActivity()); + List items = data.getAllItems(app.getLibrary().getIdent()); + for (HistoryItem item : items) { + text.append(item.getTitle()); + text.append("\n"); + String shareUrl; + try { + shareUrl = app.getApi().getShareUrl(item.getMNr(), + item.getTitle()); + } catch (OpacClient.LibraryRemovedException e) { + return; + } + if (shareUrl != null) { + text.append(shareUrl); + text.append("\n"); + } + text.append("\n"); + } + + intent.putExtra(Intent.EXTRA_TEXT, text.toString().trim()); + startActivity(Intent.createChooser(intent, + getResources().getString(R.string.share))); + } + + public void exportToStorage() { + Intent intent = null; + //android 4.4+; use Storage Access Framework + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + // Create a file with the requested MIME type. + intent.setType("application/json"); + intent.putExtra(Intent.EXTRA_TITLE, + "webopac_history_" + app.getLibrary().getIdent() + ".json"); + startActivityForResult(intent, REQUEST_CODE_EXPORT); + } else { // libItems = data.getAllItems(app.getLibrary().getIdent()); + for (HistoryItem libItem : libItems) { + JSONObject item = new JSONObject(); + item.put(JSON_ITEM_MNR, libItem.getMNr()); + item.put(JSON_ITEM_TITLE, libItem.getTitle()); + item.put(JSON_ITEM_MEDIATYPE, libItem.getMediaType()); + items.put(item); + } + history.put(JSON_HISTORY_LIST, items); + } catch (JSONException e) { + showExportError(); + } + return history; + } + + public void importFromStorage() { + //Use SAF + Intent intent; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("*/*"); + } else { //let user use a custom picker + intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("*/*"); + } + try { + startActivityForResult(intent, REQUEST_CODE_IMPORT); + } catch (ActivityNotFoundException e) { + showImportErrorNoPickerApp();//No picker app installed! + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_CODE_EXPORT && resultCode == Activity.RESULT_OK) { + Log.i("HistoryItemFragment", data.toString()); + Uri uri = data.getData(); + try { + OutputStream os = getActivity().getContentResolver().openOutputStream(uri); + if (os != null) { + JSONObject history = getEncodedHistoryItemObjects(); + PrintWriter pw = new PrintWriter(os, true); + pw.write(history.toString()); + pw.close(); + os.close(); + } else { + showExportError(); + } + } catch (FileNotFoundException e) { + showExportError(); + } catch (IOException e) { + showExportError(); + } + } else if (requestCode == REQUEST_CODE_IMPORT && resultCode == Activity.RESULT_OK) { + Uri uri = data.getData(); + InputStream is = null; + try { + HistoryDataSource dataSource = new HistoryDataSource(getActivity()); + is = getActivity().getContentResolver().openInputStream(uri); + if (is != null) { + BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); + StringBuilder builder = new StringBuilder(); + String line = ""; + + char[] chars = new char[1]; + reader.read(chars); + if (chars[0] != '{') { + throw new WrongFileFormatException(); + } + builder.append(chars); + + while ((line = reader.readLine()) != null) { + builder.append(line); + } + + String list = builder.toString(); + JSONObject savedList = new JSONObject(list); + String bib = savedList.getString(JSON_LIBRARY_NAME); + //disallow import if from different library than current library + if (bib != null && !bib.equals(app.getLibrary().getIdent())) { + Snackbar.make(getView(), R.string.info_different_library, + Snackbar.LENGTH_SHORT).show(); + return; + } + JSONArray items = savedList.getJSONArray(JSON_HISTORY_LIST); + for (int i = 0; i < items.length(); i++) { + JSONObject entry = items.getJSONObject(i); + if (entry.has(JSON_ITEM_MNR) && + !dataSource.isHistory(bib, entry.getString(JSON_ITEM_MNR)) || + !entry.has(JSON_ITEM_MNR) && !dataSource.isHistoryTitle(bib, + entry.getString(JSON_ITEM_TITLE))) { //disallow dupes + String mediatype = entry.optString(JSON_ITEM_MEDIATYPE, null); + /* TODO import + dataSource.historize(entry.optString(JSON_ITEM_MNR), + entry.getString(JSON_ITEM_TITLE), bib, + mediatype != null ? SearchResult.MediaType.valueOf(mediatype) : + null); + */ + } + } + adapter.notifyDataSetChanged(); + Snackbar.make(getView(), R.string.info_history_updated, + Snackbar.LENGTH_SHORT).show(); + } else { + showImportError(); + } + } catch (JSONException | IOException e) { + showImportError(); + } catch (WrongFileFormatException e) { + showImportWrongFormatError(); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + } + } + } + } + + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + try { + callback = (Callback) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement HistoryFragment.Callback"); + } + } + + @Override + public void onResume() { + getActivity().getSupportLoaderManager().restartLoader(0, null, this); + super.onResume(); + } + + /** + * Turns on activate-on-click mode. When this mode is on, list items will be given the + * 'activated' state when touched. + */ + private void setActivateOnItemClick(boolean activateOnItemClick) { + // When setting CHOICE_MODE_SINGLE, ListView will automatically + // give items the 'activated' state when touched. + listView.setChoiceMode(activateOnItemClick ? AbsListView.CHOICE_MODE_SINGLE + : AbsListView.CHOICE_MODE_NONE); + } + + private void setActivatedPosition(int position) { + if (position == AdapterView.INVALID_POSITION) { + listView.setItemChecked(activatedPosition, false); + } else { + listView.setItemChecked(position, true); + } + + activatedPosition = position; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + if (activatedPosition != AdapterView.INVALID_POSITION) { + // Serialize and persist the activated item position. + outState.putInt(STATE_ACTIVATED_POSITION, activatedPosition); + } + } + + public interface Callback { + public void showDetail(String mNr); + + public void removeFragment(); + } + + private class ItemListAdapter extends SimpleCursorAdapter { + + public ItemListAdapter() { + super(getActivity(), R.layout.listitem_history_item, null, + new String[]{"bib"}, null, 0); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + HistoryItem item = HistoryDataSource.cursorToItem(cursor); + + TextView tvTitleAndAuthor = (TextView) view.findViewById(R.id.tvTitleAndAuthor); + + // von AccountAdapter: + // Overview (Title/Author, Status/Deadline, Branch) + SpannableStringBuilder builder = new SpannableStringBuilder(); + if (item.getTitle() != null) { + builder.append(item.getTitle()); + builder.setSpan(new StyleSpan(Typeface.BOLD), 0, item.getTitle().length(), 0); + if (!TextUtils.isEmpty(item.getAuthor())) builder.append(". "); + } + if (!TextUtils.isEmpty(item.getAuthor())) { + builder.append(item.getAuthor().split("¬\\[",2)[0]); + } + setTextOrHide(builder, tvTitleAndAuthor); + // statt von StarFragment + /* + if (item.getTitle() != null) { + tvTitleAndAuthor.setText(Html.fromHtml(item.getTitle())); + } else { + tvTitleAndAuthor.setText(""); + } + */ + + TextView tvStatus = (TextView) view.findViewById(R.id.tvStatus); + TextView tvBranch = (TextView) view.findViewById(R.id.tvBranch); + + DateTimeFormatter fmt = DateTimeFormat.shortDate(); + + builder = new SpannableStringBuilder(); + if (item.getFirstDate() != null) { + int start = builder.length(); + builder.append(fmt.print(item.getFirstDate())); + // setSpan with a span argument is not supported before API 21 + /* + builder.setSpan(new ForegroundColorSpan(textColorPrimary), + start, start + fmt.print(item.getDeadline()).length(), 0); + */ + int countDays = 0; + if (item.getLastDate() != null) { + builder.append(" – "); + builder.append(fmt.print(item.getLastDate())); + Days daysBetween = Days.daysBetween(item.getFirstDate(), item.getLastDate()); + countDays = 1 + daysBetween.getDays(); + } + String status = "?"; + if (item.isLending()) { + status = getString(R.string.history_status_lending, item.getFirstDate(), countDays); + } else { + status = getString(R.string.history_status_finished, item.getFirstDate(), countDays); + } + setTextOrHide(status, tvStatus); + } + // setTextOrHide(builder, tvStatus); + + if (item.getHomeBranch() != null) { + setTextOrHide(Html.fromHtml(item.getHomeBranch()), tvBranch); + } + + tvBranch.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw () { + tvBranch.getViewTreeObserver().removeOnPreDrawListener(this); + // place tvBranch next to or below tvStatus to prevent overlapping + RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)tvBranch.getLayoutParams(); + if (tvStatus.getPaint().measureText(tvStatus.getText().toString()) < + tvStatus.getWidth() / 2 - 4){ + lp.addRule(RelativeLayout.BELOW, 0); //removeRule only since API 17 + lp.addRule(RelativeLayout.ALIGN_PARENT_TOP); + } else { + lp.addRule(RelativeLayout.ALIGN_PARENT_TOP,0); + lp.addRule(RelativeLayout.BELOW, R.id.tvStatus); + } + tvBranch.setLayoutParams(lp); + return true; + } + }); + + ImageView ivType = (ImageView) view.findViewById(R.id.ivMediaType); + if (item.getMediaType() != null) { + ivType.setImageResource(ResultsAdapter.getResourceByMediaType(item.getMediaType())); + } else { + ivType.setImageBitmap(null); + } + + ImageView ivDelete = (ImageView) view.findViewById(R.id.ivDelete); + if (ivDelete != null) { + ivDelete.setFocusableInTouchMode(false); + ivDelete.setFocusable(false); + ivDelete.setTag(item); + ivDelete.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + HistoryItem item = (HistoryItem) arg0.getTag(); + remove(item); + callback.removeFragment(); + } + }); + } + } + } + + protected static void setTextOrHide(CharSequence value, TextView tv) { + if (!TextUtils.isEmpty(value)) { + tv.setVisibility(View.VISIBLE); + tv.setText(value); + } else { + tv.setVisibility(View.GONE); + } + } + + private class WrongFileFormatException extends Exception { + } +} diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainActivity.java index 8aed86569..23fc0b9f4 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainActivity.java @@ -48,7 +48,7 @@ import de.geeksfactory.opacclient.storage.SearchFieldDataSource; public class MainActivity extends OpacActivity - implements SearchFragment.Callback, StarredFragment.Callback, + implements SearchFragment.Callback, StarredFragment.Callback, HistoryFragment.Callback, SearchResultDetailFragment.Callbacks { public static final String EXTRA_FRAGMENT = "fragment"; diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java index 1666a50cf..2fa8f7033 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java @@ -423,6 +423,10 @@ protected boolean selectItemById(int id) { fragment = new StarredFragment(); setTwoPane(true); setFabVisible(false); + } else if (id == R.id.nav_history) { + fragment = new HistoryFragment(); + setTwoPane(true); + setFabVisible(false); } else if (id == R.id.nav_info) { fragment = new InfoFragment(); setTwoPane(false); diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryContentProvider.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryContentProvider.java new file mode 100644 index 000000000..87b0f276a --- /dev/null +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryContentProvider.java @@ -0,0 +1,214 @@ +/** + * Copyright (C) 2013 by Raphael Michel under the MIT license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software + * is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +package de.geeksfactory.opacclient.storage; + +import android.content.ContentProvider; +import android.content.ContentUris; +import android.content.ContentValues; +import android.database.Cursor; +import android.net.Uri; + +import java.util.List; + +import de.geeksfactory.opacclient.BuildConfig; + +public class HistoryContentProvider extends ContentProvider { + public static final String HIST_TYPE = "history"; + private static final String HIST_MIME_POSTFIX = "/vnd.de.opacapp.type" + + HIST_TYPE; + public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".historyprovider"; + public static final String BASE_URI = "content://" + AUTHORITY + "/"; + public static final Uri HIST_URI = Uri.parse(BASE_URI + HIST_TYPE); + private static final String MIME_PREFIX = "vnd.android.cursor."; + private static final String HIST_DIR_MIME = MIME_PREFIX + "dir" + + HIST_MIME_POSTFIX; + private static final String HIST_ITEM_MIME = MIME_PREFIX + "item" + + HIST_MIME_POSTFIX; + private HistoryDatabase database; + + private static Mime getTypeMime(Uri uri) { + if (!AUTHORITY.equals(uri.getAuthority()) + && !uri.getAuthority().startsWith("de.opacapp.") + && !uri.getAuthority().startsWith("net.opacapp.")) { + return null; + } + List segments = uri.getPathSegments(); + if (segments == null || segments.size() == 0) { + return null; + } + + String type = segments.get(0); + if (HIST_TYPE.equals(type)) { + switch (segments.size()) { + case 1: + return Mime.HIST_DIR; + case 2: + return Mime.HIST_ITEM; + default: + return null; + } + } else { + return null; + } + } + + @Override + public boolean onCreate() { + database = new HistoryDatabase(getContext()); + return true; + } + + @Override + public String getType(Uri uri) { + switch (getTypeMime(uri)) { + case HIST_DIR: + return HIST_DIR_MIME; + case HIST_ITEM: + return HIST_ITEM_MIME; + default: + return null; + } + } + + private int deleteInDatabase(String table, String whereClause, + String[] whereArgs) { + return database.getWritableDatabase().delete(table, whereClause, whereArgs); + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + int rowsAffected; + switch (getTypeMime(uri)) { + case HIST_DIR: + rowsAffected = deleteInDatabase(HistoryDatabase.HIST_TABLE, selection, selectionArgs); + break; + case HIST_ITEM: + rowsAffected = deleteInDatabase(HistoryDatabase.HIST_TABLE, + HistoryDatabase.HIST_WHERE_HISTORY_ID, selectionForUri(uri)); + break; + default: + rowsAffected = 0; + break; + } + + if (rowsAffected > 0) { + notifyUri(uri); + } + return rowsAffected; + } + + private long insertIntoDatabase(String table, ContentValues values) { + return database.getWritableDatabase() + .insertOrThrow(table, null, values); + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + Uri itemUri; + long id; + switch (getTypeMime(uri)) { + case HIST_DIR: + id = insertIntoDatabase(HistoryDatabase.HIST_TABLE, values); + itemUri = ContentUris.withAppendedId(uri, id); + notifyUri(uri); + break; + case HIST_ITEM: + default: + itemUri = null; + break; + } + if (itemUri != null) { + notifyUri(uri); + } + return itemUri; + } + + private Cursor queryDatabase(String table, String[] projection, + String selection, String[] selectionArgs, String groupBy, + String having, String orderBy) { + return database.getReadableDatabase().query(table, projection, + selection, selectionArgs, groupBy, having, orderBy); + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + Cursor cursor; + switch (getTypeMime(uri)) { + case HIST_DIR: + cursor = queryDatabase(HistoryDatabase.HIST_TABLE, projection, + selection, selectionArgs, null, null, sortOrder); + break; + case HIST_ITEM: + cursor = queryDatabase(HistoryDatabase.HIST_TABLE, projection, + HistoryDatabase.HIST_WHERE_HISTORY_ID, selectionForUri(uri), null, + null, sortOrder); + break; + default: + return null; + } + cursor.setNotificationUri(getContext().getContentResolver(), uri); + return cursor; + } + + private int updateInDatabase(String table, ContentValues values, + String selection, String[] selectionArgs) { + return database.getWritableDatabase().update(table, values, selection, + selectionArgs); + } + + @Override + public int update(Uri uri, ContentValues values, String selection, + String[] selectionArgs) { + int rowsAffected; + switch (getTypeMime(uri)) { + case HIST_DIR: + rowsAffected = updateInDatabase(HistoryDatabase.HIST_TABLE, values, + selection, selectionArgs); + break; + case HIST_ITEM: + rowsAffected = updateInDatabase(HistoryDatabase.HIST_TABLE, values, + HistoryDatabase.HIST_WHERE_HISTORY_ID, selectionForUri(uri)); + break; + default: + rowsAffected = 0; + break; + } + + if (rowsAffected > 0) { + notifyUri(uri); + } + return rowsAffected; + } + + private void notifyUri(Uri uri) { + getContext().getContentResolver().notifyChange(uri, null); + } + + private String[] selectionForUri(Uri uri) { + return new String[]{String.valueOf(ContentUris.parseId(uri))}; + } + + private enum Mime { + HIST_ITEM, HIST_DIR + } +} \ No newline at end of file diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java new file mode 100644 index 000000000..d32d0f54e --- /dev/null +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -0,0 +1,411 @@ +/** + * Copyright (C) 2013 by Raphael Michel under the MIT license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software + * is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +package de.geeksfactory.opacclient.storage; + +import android.app.Activity; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.text.BoringLayout; + +import org.joda.time.LocalDate; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import de.geeksfactory.opacclient.OpacClient; +import de.geeksfactory.opacclient.objects.Account; +import de.geeksfactory.opacclient.objects.AccountData; +import de.geeksfactory.opacclient.objects.AccountItem; +import de.geeksfactory.opacclient.objects.LentItem; +import de.geeksfactory.opacclient.objects.SearchResult; +import de.geeksfactory.opacclient.objects.HistoryItem; + +public class HistoryDataSource { + + // Database fields + private SQLiteDatabase database; + private String[] allColumns = HistoryDatabase.COLUMNS; + +// private Context context; +// public HistoryDataSource(Context context) { + + private Activity context; + public HistoryDataSource(Activity context) { + this.context = context; + } + + public void updateLenting(Account account, AccountData adata) { + String library = account.getLibrary(); + + /* Account yes / no + History +---------------+----------- + / still / ended + yes / update / update + / lastDate / lending + --------+---------------+----------- + no / new / - + / insert / + --------+---------------+----------- + */ + List historyItems = getAllLendingItems(account.getLibrary()); + for (LentItem lentItem : adata.getLent()) { + HistoryItem foundItem = null; + for (HistoryItem historyItem: historyItems ) { + if (historyItem.isSameAsLentItem(lentItem)) { + foundItem = historyItem; + break; + } + } + if (foundItem != null) { + // immer noch ausgeliehen + // -> update lastDate = currentDate + if (!LocalDate.now().equals(foundItem.getLastDate())) { + foundItem.setLastDate(LocalDate.now()); + } + if (!lentItem.getDeadline().equals(foundItem.getDeadline())) { + int count = foundItem.getProlongCount(); + count++; + foundItem.setProlongCount(count); + } + + this.updateHistoryItem(foundItem); + } else { + // neu ausgeliehen + // -> insert + this.insertLentItem(library, lentItem); + } + } + + for (HistoryItem historyItem: historyItems ) { + boolean isLending = false; + for (LentItem lentItem : adata.getLent()) { + if (historyItem.isSameAsLentItem(lentItem)) { + isLending = true; + break; + } + } + if (isLending) { + // bereits oben behandelt + } else { + // nicht mehr ausgeliehen + // -> update lending = false + historyItem.setLending(false); + this.updateHistoryItem(historyItem); + } + } + } + + public static HistoryItem cursorToItem(Cursor cursor) { + HistoryItem item = new HistoryItem(); + int i=0; + item.setHistoryId(cursor.getInt(i++)); + String ds = cursor.getString(i++); + if ( ds!=null) { + item.setFirstDate(LocalDate.parse(ds)); + } + ds = cursor.getString(i++); + if ( ds!=null) { + item.setLastDate(LocalDate.parse(ds)); + } + item.setLending(cursor.getInt(i++) > 0); + item.setMNr(cursor.getString(i++)); + item.setBib(cursor.getString(i++)); + item.setTitle(cursor.getString(i++)); + item.setAuthor(cursor.getString(i++)); + item.setFormat(cursor.getString(i++)); + item.setStatus(cursor.getString(i++)); + item.setCover(cursor.getString(i++)); + String mds = cursor.getString(i++); + if (mds!=null) { + try { + SearchResult.MediaType mediaType = SearchResult.MediaType.valueOf(mds); + item.setMediaType(mediaType); + } catch (IllegalArgumentException e) { + // TODO log invalid MediaType + } + } + item.setHomeBranch(cursor.getString(i++)); + item.setLendingBranch(cursor.getString(i++)); + boolean ebook = cursor.getInt(i++) > 0; + item.setEbook(ebook); + item.setBarcode(cursor.getString(i++)); + + ds = cursor.getString(i++); + if ( ds!=null) { + item.setDeadline(LocalDate.parse(ds)); + } + int count = cursor.getInt(i++); + item.setProlongCount(count); + + return item; + } + + private void addAccountItemValues(ContentValues values, AccountItem item ) { + putOrNull(values,"medianr", item.getId()); + putOrNull(values,"title", item.getTitle()); + putOrNull(values,"author", item.getAuthor()); + putOrNull(values,"format", item.getFormat()); + putOrNull(values,"status", item.getStatus()); + putOrNull(values,"cover", item.getCover()); + SearchResult.MediaType mediaType = item.getMediaType(); + putOrNull(values,"mediatype", mediaType != null ? mediaType.toString() : null); + } + + private ContentValues createContentValues(HistoryItem historyItem) { + ContentValues values = new ContentValues(); + addAccountItemValues(values, historyItem); + + putOrNull(values,"firstDate", historyItem.getFirstDate()); + putOrNull(values,"lastDate", historyItem.getLastDate()); + putOrNull(values,"lending", historyItem.isLending()); + putOrNull(values,"bib", historyItem.getBib()); + putOrNull(values,"homeBranch", historyItem.getHomeBranch()); + putOrNull(values,"lendingBranch", historyItem.getLendingBranch()); + putOrNull(values,"ebook", historyItem.isEbook()); + putOrNull(values,"barcode", historyItem.getBarcode()); + putOrNull(values,"deadline", historyItem.getDeadline()); + values.put("prolongCount", historyItem.getProlongCount()); + + return values; + } + + private void updateHistoryItem(HistoryItem historyItem ) { + ContentValues values = createContentValues(historyItem); + String where = "historyId = ?"; + context.getContentResolver() + .update(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri() + , values, where, new String[]{Integer.toString(historyItem.getHistoryId())} ); + } + + public void insertHistoryItem(HistoryItem historyItem ) { + ContentValues values = createContentValues(historyItem); + context.getContentResolver() + .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), values); + } + + private void insertLentItem(String bib, LentItem lentItem ) { + ContentValues values = new ContentValues(); + addAccountItemValues(values, lentItem); + + putOrNull(values, "firstDate", LocalDate.now()); + putOrNull(values, "lastDate", LocalDate.now()); + putOrNull(values, "lending", true); + + putOrNull(values, "bib", bib); + putOrNull(values, "homeBranch", lentItem.getHomeBranch()); + putOrNull(values, "lendingBranch", lentItem.getLendingBranch()); + putOrNull(values, "ebook", lentItem.isEbook()); + putOrNull(values, "barcode", lentItem.getBarcode()); + putOrNull(values, "deadline", lentItem.getDeadline()); + + context.getContentResolver() + .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), values); + } + + private void putOrNull(ContentValues cv, String key, String value) { + if (value != null) { + cv.put(key, value); + } else { + cv.putNull(key); + } + } + private void putOrNull(ContentValues cv, String key, LocalDate value) { + if (value != null) { + cv.put(key, value.toString()); + } else { + cv.putNull(key); + } + } + private void putOrNull(ContentValues cv, String key, boolean value) { + cv.put(key, value ? Boolean.TRUE : Boolean.FALSE); + } + + public List getAllItems(String bib) { + List items = new ArrayList<>(); + String[] selA = {bib}; + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB, + selA, null); + + cursor.moveToFirst(); + while (!cursor.isAfterLast()) { + HistoryItem item = cursorToItem(cursor); + items.add(item); + cursor.moveToNext(); + } + // Make sure to close the cursor + cursor.close(); + return items; + } + + public void sort(String bib, String sortOrder) { + String[] selA = {bib}; + context.getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB, + selA, sortOrder); + } + + public List getAllLendingItems(String bib) { + List items = new ArrayList<>(); + String[] selA = {bib}; + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_LENDING, + selA, null); + + cursor.moveToFirst(); + while (!cursor.isAfterLast()) { + HistoryItem item = cursorToItem(cursor); + items.add(item); + cursor.moveToNext(); + } + + // Make sure to close the cursor + cursor.close(); + return items; + } + + public HistoryItem getItemByTitle(String bib, String title) { + String[] selA = {bib, title}; + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, + HistoryDatabase.HIST_WHERE_TITLE_LIB, selA, null); + HistoryItem item = null; + + cursor.moveToFirst(); + if (!cursor.isAfterLast()) { + item = cursorToItem(cursor); + cursor.moveToNext(); + } + // Make sure to close the cursor + cursor.close(); + return item; + } + + public HistoryItem getItem(String bib, String id) { + String[] selA = {bib, id}; + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_NR_LIB, + selA, null); + HistoryItem item = null; + + cursor.moveToFirst(); + if (!cursor.isAfterLast()) { + item = cursorToItem(cursor); + cursor.moveToNext(); + } + // Make sure to close the cursor + cursor.close(); + return item; + } + + public HistoryItem getItem(long id) { + String[] selA = {String.valueOf(id)}; + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_HISTORY_ID, selA, + null); + HistoryItem item = null; + + cursor.moveToFirst(); + if (!cursor.isAfterLast()) { + item = cursorToItem(cursor); + cursor.moveToNext(); + } + // Make sure to close the cursor + cursor.close(); + return item; + } + + public boolean isHistory(String bib, String id) { + if (id == null) { + return false; + } + String[] selA = {bib, id}; + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_NR_LIB, + selA, null); + int c = cursor.getCount(); + cursor.close(); + return (c > 0); + } + + public boolean isHistoryTitle(String bib, String title) { + if (title == null) { + return false; + } + String[] selA = {bib, title}; + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, + HistoryDatabase.HIST_WHERE_TITLE_LIB, selA, null); + int c = cursor.getCount(); + cursor.close(); + return (c > 0); + } + + public void remove(HistoryItem item) { + String[] selA = {"" + item.getHistoryId()}; + context.getContentResolver() + .delete(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.HIST_WHERE_HISTORY_ID, selA); + } + + public void renameLibraries(Map map) { + for (Entry entry : map.entrySet()) { + ContentValues cv = new ContentValues(); + cv.put("bib", entry.getValue()); + + context.getContentResolver() + .update(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + cv, HistoryDatabase.HIST_WHERE_LIB, + new String[]{entry.getKey()}); + } + } +} diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java new file mode 100644 index 000000000..a5b8f60cf --- /dev/null +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java @@ -0,0 +1,111 @@ +/** + * Copyright (C) 2013 by Raphael Michel under the MIT license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software + * is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +package de.geeksfactory.opacclient.storage; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +public class HistoryDatabase extends SQLiteOpenHelper { + + public static final String HIST_TABLE = "historyTable"; + + // CHANGE THIS + public static final String HIST_WHERE_HISTORY_ID = "historyId = ?"; + public static final String HIST_WHERE_LIB = "bib = ?"; + public static final String HIST_WHERE_LIB_LENDING = "bib = ? AND lending = 1"; + public static final String HIST_WHERE_TITLE_LIB = "bib = ? AND medianr IS NULL AND title = ?"; + public static final String HIST_WHERE_NR_LIB = "bib = ? AND medianr = ?"; + public static final String[] COLUMNS = {"historyId AS _id", // wg. android.widget.CursorAdapter + // siehe https://developer.android.com/reference/android/widget/CursorAdapter.html + "firstDate", + "lastDate", + "lending", + "medianr", + "bib", + "title", + "author", + "format", + "status", + "cover", + "mediatype", + "homeBranch", + "lendingBranch", + "ebook", + "barcode", + "deadline", + "prolongCount" + }; + + private static final String DATABASE_CREATE = "create table historyTable (\n" + + "\thistoryId integer primary key autoincrement,\n" + + "\tfirstDate date,\n" + + "\tlastDate date,\n" + + "\tlending boolean,\n" + + "\tmedianr text,\n" + + "\tbib text,\n" + + "\ttitle text,\n" + + "\tauthor text,\n" + + "\tformat text,\n" + + "\tstatus text,\n" + + "\tcover text,\n" + + "\tmediatype text,\n" + + "\thomeBranch text,\n" + + "\tlendingBranch text,\n" + + "\tebook boolean,\n" + + "\tbarcode text,\n" + + "\tdeadline date,\n" + + "\tprolongCount integer\n" + + ");"; + + + private static final String DATABASE_NAME = "history.db"; + private static final int DATABASE_VERSION = 1; // REPLACE ONUPGRADE IF YOU + + public HistoryDatabase(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(DATABASE_CREATE); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + + Log.w(HistoryDatabase.class.getName(), "Upgrading database from version " + + oldVersion + " to " + newVersion + + ", which will destroy all old data"); + + db.execSQL( + "create table temp ( id integer primary key autoincrement, medianr text, " + + "bib text, title text );"); + db.execSQL("insert into temp select * from " + HIST_TABLE + ";"); + db.execSQL("drop table " + HIST_TABLE + ";"); + onCreate(db); + db.execSQL("insert into " + HIST_TABLE + " select * from temp;"); + db.execSQL("drop table temp;"); + } + +} diff --git a/opacclient/opacapp/src/main/res/drawable/ic_clock_24dp.xml b/opacclient/opacapp/src/main/res/drawable/ic_clock_24dp.xml new file mode 100644 index 000000000..ef5dfb463 --- /dev/null +++ b/opacclient/opacapp/src/main/res/drawable/ic_clock_24dp.xml @@ -0,0 +1,18 @@ + + + + diff --git a/opacclient/opacapp/src/main/res/drawable/ic_sort_white_24dp.xml b/opacclient/opacapp/src/main/res/drawable/ic_sort_white_24dp.xml new file mode 100644 index 000000000..a0c153ad0 --- /dev/null +++ b/opacclient/opacapp/src/main/res/drawable/ic_sort_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/opacclient/opacapp/src/main/res/layout/fragment_history.xml b/opacclient/opacapp/src/main/res/layout/fragment_history.xml new file mode 100644 index 000000000..3544f03ba --- /dev/null +++ b/opacclient/opacapp/src/main/res/layout/fragment_history.xml @@ -0,0 +1,25 @@ + + + + + + + + + \ No newline at end of file diff --git a/opacclient/opacapp/src/main/res/layout/listitem_history.xml b/opacclient/opacapp/src/main/res/layout/listitem_history.xml new file mode 100644 index 000000000..12c4b08b2 --- /dev/null +++ b/opacclient/opacapp/src/main/res/layout/listitem_history.xml @@ -0,0 +1,39 @@ + + + + + + + + + + \ No newline at end of file diff --git a/opacclient/opacapp/src/main/res/layout/listitem_history_item.xml b/opacclient/opacapp/src/main/res/layout/listitem_history_item.xml new file mode 100644 index 000000000..315403b24 --- /dev/null +++ b/opacclient/opacapp/src/main/res/layout/listitem_history_item.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opacclient/opacapp/src/main/res/menu/activity_history.xml b/opacclient/opacapp/src/main/res/menu/activity_history.xml new file mode 100644 index 000000000..3c99ea533 --- /dev/null +++ b/opacclient/opacapp/src/main/res/menu/activity_history.xml @@ -0,0 +1,54 @@ + +

+ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opacclient/opacapp/src/main/res/menu/navigation_drawer.xml b/opacclient/opacapp/src/main/res/menu/navigation_drawer.xml index d1b71d128..02db808a2 100644 --- a/opacclient/opacapp/src/main/res/menu/navigation_drawer.xml +++ b/opacclient/opacapp/src/main/res/menu/navigation_drawer.xml @@ -15,6 +15,10 @@ android:id="@+id/nav_starred" android:icon="@drawable/ic_star_24dp" android:title="@string/nav_starred"/> + mehr Infos + Importieren + Aus dem Verlauf gelöscht + Rückgängig + Sortieren + nach Author + nach Dauer + nach Beginn + nach Ende + Verlängerungen + Titel + Import des Verlaufs abgeschlossen + Verlauf + Teilen + Exportieren + Dies ist deine Verlaufsliste. Die Liste wird für jede Bibliothek, die du benutzt, separat geführt. + vom %s für %d Tage + seit %s für %d Tage + vom %s für 1 Tag + seit %s für 1 Tag diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index f8c1ed486..4dfc00923 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -105,6 +105,7 @@ Please wait for the details to load. We could not obtain enough information about this item to add it to your list. This is your favorites list. You can add items by clicking the star on a detail page. The list is saved separately for every library you use. + This is your history list. You can The list is saved separately for every library you use. Share Please wait for the details to load. Not supported in this library. @@ -116,6 +117,7 @@ We don\'t have any information about this library to show. Selected list is from another library! Try switching to the correct library Import complete. + History import complete. The connection to the library server failed. Please check your internet connection. If the problem persists, there may have been a problem on the library server or the app was unable to parse the server\'s response. The connection to the library server failed. Please check your internet connection. If the problem persists, there may have been a problem on the library server. @@ -138,6 +140,7 @@ Search Account Favorites + History Information Miscellaneous Settings @@ -179,6 +182,16 @@ Share Export Import + Share + Export + Import + Sort + by Title + by Author + by date start + by date end + by duration + by prolongation Share as text An error occurred during export. Please try again later. @@ -307,6 +320,12 @@ Got it Removed from favorites Undo + Removed from history + Undo + since %s for %d days + since %s for 1 day + from %s for %d days + from %s for 1 day Print Please wait for details to load Library data From bf53793ce3ff7607076ef14bdf972c948629e050 Mon Sep 17 00:00:00 2001 From: Justy Date: Mon, 2 Dec 2019 17:31:39 +0100 Subject: [PATCH 02/32] History - treat 1 day Add index to String.format-Parameter --- .../opacclient/frontend/HistoryFragment.java | 9 ++++++--- opacclient/opacapp/src/main/res/values-de/strings.xml | 8 ++++---- opacclient/opacapp/src/main/res/values/strings.xml | 8 ++++---- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index ae88e0f28..b16a86605 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -624,11 +624,14 @@ public void bindView(View view, Context context, Cursor cursor) { countDays = 1 + daysBetween.getDays(); } String status = "?"; - if (item.isLending()) { - status = getString(R.string.history_status_lending, item.getFirstDate(), countDays); + int resId = 0; + String fmtFirstDate = fmt.print(item.getFirstDate()); + if (countDays == 1) { + resId = item.isLending() ? R.string.history_status_lending_1 : R.string.history_status_finished_1; } else { - status = getString(R.string.history_status_finished, item.getFirstDate(), countDays); + resId = item.isLending() ? R.string.history_status_lending : R.string.history_status_finished; } + status = getString(resId, fmtFirstDate, countDays); setTextOrHide(status, tvStatus); } // setTextOrHide(builder, tvStatus); diff --git a/opacclient/opacapp/src/main/res/values-de/strings.xml b/opacclient/opacapp/src/main/res/values-de/strings.xml index 375a92e5c..f9f4ee074 100644 --- a/opacclient/opacapp/src/main/res/values-de/strings.xml +++ b/opacclient/opacapp/src/main/res/values-de/strings.xml @@ -356,8 +356,8 @@ Teilen Exportieren Dies ist deine Verlaufsliste. Die Liste wird für jede Bibliothek, die du benutzt, separat geführt. - vom %s für %d Tage - seit %s für %d Tage - vom %s für 1 Tag - seit %s für 1 Tag + vom %1$s für %2$d Tage + seit %1$s für %2$d Tage + vom %1$s für 1 Tag + seit %1$s für 1 Tag diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index 4dfc00923..351ff7bfd 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -322,10 +322,10 @@ Undo Removed from history Undo - since %s for %d days - since %s for 1 day - from %s for %d days - from %s for 1 day + since %1$s for %2$d days + since %1$s for 1 day + from %1$s for %2$d days + from %1$s for 1 day Print Please wait for details to load Library data From af7041fa0522a1479d5ac6d362e826f5b1457ee3 Mon Sep 17 00:00:00 2001 From: Justy Date: Mon, 2 Dec 2019 21:41:21 +0100 Subject: [PATCH 03/32] =?UTF-8?q?showDetailActivity=20f=C3=BCr=20HistoryFr?= =?UTF-8?q?agment/Item?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/AccountItemDetailActivity.java | 39 ++++++++++++++++- .../opacclient/frontend/HistoryFragment.java | 43 ++++++++++++++++--- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java index 766ee201b..3797f22bb 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java @@ -25,6 +25,7 @@ import de.geeksfactory.opacclient.apis.OpacApi; import de.geeksfactory.opacclient.databinding.AccountItemDetailActivityBinding; import de.geeksfactory.opacclient.objects.AccountItem; +import de.geeksfactory.opacclient.objects.HistoryItem; import de.geeksfactory.opacclient.objects.LentItem; import de.geeksfactory.opacclient.objects.ReservedItem; import de.geeksfactory.opacclient.objects.SearchResult; @@ -154,6 +155,23 @@ public boolean onCreateOptionsMenu(Menu menu) { cancel.setVisible(false); booking.setVisible(false); } + } else if (item instanceof HistoryItem) { + final HistoryItem i = (HistoryItem) item; + download.setVisible(false); + cancel.setVisible(false); // cancel reservation + if (i.isLending() ) { + booking.setVisible(false); + + prolong.setVisible(true); + // solange beo HistoryFragment nicht implementierr + prolong.setVisible(false); + } else { + prolong.setVisible(false); + + booking.setVisible(true); + // solange beo HistoryFragment nicht implementierr + booking.setVisible(false); + } } return true; @@ -197,15 +215,32 @@ public static CharSequence getBranch(AccountItem item, String format) { } else { return null; } - } else { + } else if (item instanceof ReservedItem) { return fromHtml(((ReservedItem) item).getBranch()); + } else if (item instanceof HistoryItem) { + HistoryItem historyItem = (HistoryItem) item; + if (historyItem.getLendingBranch() != null && historyItem.getHomeBranch() != null) { + return fromHtml(String.format(format, historyItem.getLendingBranch(), + historyItem.getHomeBranch())); + } else if (historyItem.getLendingBranch() != null) { + return fromHtml(historyItem.getLendingBranch()); + } else if (historyItem.getHomeBranch() != null) { + return fromHtml(historyItem.getHomeBranch()); + } else { + return null; + } + } else { + return null; } } public static boolean hasBranch(AccountItem item) { return ((item instanceof LentItem && (((LentItem) item).getHomeBranch() != null || ((LentItem) item).getLendingBranch() != null)) || - (item instanceof ReservedItem && ((ReservedItem) item).getBranch() != null)); + (item instanceof ReservedItem && ((ReservedItem) item).getBranch() != null) || + (item instanceof HistoryItem && (((HistoryItem) item).getHomeBranch() != null || + ((HistoryItem) item).getLendingBranch() != null)) + ); } private static CharSequence fromHtml(@Nullable String text) { diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index b16a86605..fdb00ba07 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -70,6 +70,8 @@ import java.util.ArrayList; import java.util.List; +import androidx.core.app.ActivityCompat; +import androidx.core.app.ActivityOptionsCompat; import androidx.cursoradapter.widget.SimpleCursorAdapter; import androidx.fragment.app.Fragment; import androidx.loader.app.LoaderManager.LoaderCallbacks; @@ -78,7 +80,9 @@ import de.geeksfactory.opacclient.OpacClient; import de.geeksfactory.opacclient.R; import de.geeksfactory.opacclient.frontend.OpacActivity.AccountSelectedListener; +import de.geeksfactory.opacclient.frontend.adapter.AccountAdapter; import de.geeksfactory.opacclient.objects.Account; +import de.geeksfactory.opacclient.objects.AccountItem; import de.geeksfactory.opacclient.objects.HistoryItem; import de.geeksfactory.opacclient.searchfields.SearchField; import de.geeksfactory.opacclient.searchfields.SearchField.Meaning; @@ -100,6 +104,8 @@ public class HistoryFragment extends Fragment implements private static final int REQUEST_CODE_EXPORT = 123; private static final int REQUEST_CODE_IMPORT = 124; + private static int REQUEST_CODE_DETAIL = 1; // siehe AccountFragment.REQUEST_DETAIL + protected View view; protected OpacClient app; private ItemListAdapter adapter; @@ -166,7 +172,8 @@ public void onItemClick(AdapterView parent, View view, Toast.LENGTH_LONG).show(); } } else { - callback.showDetail(item.getMNr()); +// callback.showDetail(item.getMNr()); + showDetailActivity(item, view); } } }); @@ -189,6 +196,17 @@ public void onItemClick(AdapterView parent, View view, return view; } + private void showDetailActivity(AccountItem item, View view) { + Intent intent = new Intent(getContext(), AccountItemDetailActivity.class); + intent.putExtra(AccountItemDetailActivity.EXTRA_ITEM, item); + ActivityOptionsCompat options = ActivityOptionsCompat + .makeSceneTransitionAnimation(getActivity(), view, + getString(R.string.transition_background)); + + ActivityCompat + .startActivityForResult(getActivity(), intent, REQUEST_CODE_DETAIL, options.toBundle()); + } + @Override public void onCreateOptionsMenu(android.view.Menu menu, MenuInflater inflater) { @@ -233,7 +251,7 @@ private void sort(String orderby) { if (sortOrder == null) { // bisher nicht sortiert - sortOrder = orderby + " ASC"; + sortOrder = orderby + " DESC"; } else if (sortOrder.startsWith(orderby)) { // bereits nach dieser Spalte sortiert // d.h. ASC/DESC swappen @@ -426,10 +444,10 @@ public void importFromStorage() { } @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { + public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == REQUEST_CODE_EXPORT && resultCode == Activity.RESULT_OK) { - Log.i("HistoryItemFragment", data.toString()); - Uri uri = data.getData(); + Log.i("HistoryItemFragment", intent.toString()); + Uri uri = intent.getData(); try { OutputStream os = getActivity().getContentResolver().openOutputStream(uri); if (os != null) { @@ -447,7 +465,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { showExportError(); } } else if (requestCode == REQUEST_CODE_IMPORT && resultCode == Activity.RESULT_OK) { - Uri uri = data.getData(); + Uri uri = intent.getData(); InputStream is = null; try { HistoryDataSource dataSource = new HistoryDataSource(getActivity()); @@ -511,8 +529,19 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { } } } + } else if ((requestCode == REQUEST_CODE_DETAIL) && (intent != null)) { + String data = intent.getStringExtra(AccountItemDetailActivity.EXTRA_DATA); + switch (resultCode) { + case AccountItemDetailActivity.RESULT_PROLONG: + // TODO implement prolong from History + // prolong(data); + break; + case AccountItemDetailActivity.RESULT_BOOKING: + // TODO implement booking from History + // bookingStart(data); + break; + } } - } @Override From 826f9ce3bdf17d9ce5bb2859a6d7a1ef3366bd81 Mon Sep 17 00:00:00 2001 From: Justy Date: Mon, 2 Dec 2019 22:23:45 +0100 Subject: [PATCH 04/32] =?UTF-8?q?Detailanzeige=20accountitem=20f=C3=BCr=20?= =?UTF-8?q?HistoryItem=20erweitert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/drawable/ic_start_date_24dp.xml | 18 ++++++ .../res/layout/content_accountitem_detail.xml | 62 +++++++++++++++++++ .../src/main/res/values-de/strings.xml | 2 + .../opacapp/src/main/res/values/strings.xml | 2 + 4 files changed, 84 insertions(+) create mode 100644 opacclient/opacapp/src/main/res/drawable/ic_start_date_24dp.xml diff --git a/opacclient/opacapp/src/main/res/drawable/ic_start_date_24dp.xml b/opacclient/opacapp/src/main/res/drawable/ic_start_date_24dp.xml new file mode 100644 index 000000000..97edd365c --- /dev/null +++ b/opacclient/opacapp/src/main/res/drawable/ic_start_date_24dp.xml @@ -0,0 +1,18 @@ + + + + diff --git a/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml b/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml index f56f131df..fe7a8fc2b 100644 --- a/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml +++ b/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml @@ -11,6 +11,8 @@ + + @@ -176,6 +178,66 @@ tools:text="01.01.2017"/> + + + + + + + + + + + + + + + + + + seit %1$s für %2$d Tage vom %1$s für 1 Tag seit %1$s für 1 Tag + Beginndatum + Endedatum diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index 351ff7bfd..dcc52aac3 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -326,6 +326,8 @@ since %1$s for 1 day from %1$s for %2$d days from %1$s for 1 day + Start date + Last date Print Please wait for details to load Library data From dae2a1c4b087eb8a738fd80d5afe50201fea361f Mon Sep 17 00:00:00 2001 From: Justy Date: Mon, 9 Dec 2019 21:48:12 +0100 Subject: [PATCH 05/32] Export/Import History via JSON implementiert --- .../opacclient/frontend/HistoryFragment.java | 26 +++-- .../opacclient/storage/HistoryDataSource.java | 94 +++++++++++++++++++ 2 files changed, 106 insertions(+), 14 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index fdb00ba07..c4e3d7a21 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -98,9 +98,9 @@ public class HistoryFragment extends Fragment implements private static final String STATE_ACTIVATED_POSITION = "activated_position"; private static final String JSON_LIBRARY_NAME = "library_name"; private static final String JSON_HISTORY_LIST = "history_list"; - private static final String JSON_ITEM_MNR = "item_mnr"; - private static final String JSON_ITEM_TITLE = "item_title"; - private static final String JSON_ITEM_MEDIATYPE = "item_mediatype"; + private static final String JSON_ITEM_MNR = "medianr"; + private static final String JSON_ITEM_TITLE = "title"; + private static final String JSON_ITEM_MEDIATYPE = "mediatype"; private static final int REQUEST_CODE_EXPORT = 123; private static final int REQUEST_CODE_IMPORT = 124; @@ -406,9 +406,10 @@ private void showImportWrongFormatError() { private JSONObject getEncodedHistoryItemObjects() { JSONObject history = new JSONObject(); try { - history.put(JSON_LIBRARY_NAME, app.getLibrary().getIdent()); - JSONArray items = new JSONArray(); HistoryDataSource data = new HistoryDataSource(getActivity()); + JSONArray items = data.getAllItemsAsJson(app.getLibrary().getIdent()); + /* + JSONArray items = new JSONArray(); List libItems = data.getAllItems(app.getLibrary().getIdent()); for (HistoryItem libItem : libItems) { JSONObject item = new JSONObject(); @@ -417,6 +418,8 @@ private JSONObject getEncodedHistoryItemObjects() { item.put(JSON_ITEM_MEDIATYPE, libItem.getMediaType()); items.put(item); } + */ + history.put(JSON_LIBRARY_NAME, app.getLibrary().getIdent()); history.put(JSON_HISTORY_LIST, items); } catch (JSONException e) { showExportError(); @@ -500,15 +503,10 @@ public void onActivityResult(int requestCode, int resultCode, Intent intent) { JSONObject entry = items.getJSONObject(i); if (entry.has(JSON_ITEM_MNR) && !dataSource.isHistory(bib, entry.getString(JSON_ITEM_MNR)) || - !entry.has(JSON_ITEM_MNR) && !dataSource.isHistoryTitle(bib, - entry.getString(JSON_ITEM_TITLE))) { //disallow dupes - String mediatype = entry.optString(JSON_ITEM_MEDIATYPE, null); - /* TODO import - dataSource.historize(entry.optString(JSON_ITEM_MNR), - entry.getString(JSON_ITEM_TITLE), bib, - mediatype != null ? SearchResult.MediaType.valueOf(mediatype) : - null); - */ + !entry.has(JSON_ITEM_MNR) /* && !dataSource.isHistoryTitle(bib, + entry.getString(JSON_ITEM_TITLE))*/) { //disallow dupes + // String mediatype = entry.optString(JSON_ITEM_MEDIATYPE, null); + dataSource.insertHistoryItem(entry); } } adapter.notifyDataSetChanged(); diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index d32d0f54e..e2749baac 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -29,9 +29,13 @@ import android.text.BoringLayout; import org.joda.time.LocalDate; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -119,6 +123,58 @@ public void updateLenting(Account account, AccountData adata) { } } + public JSONArray getAllItemsAsJson(String bib) throws + JSONException { + + String[] selA = {bib}; + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB, + selA, null); + + cursor.moveToFirst(); + JSONArray items = new JSONArray(); + while (!cursor.isAfterLast()) { + JSONObject item = cursorToJson(HistoryDatabase.COLUMNS, cursor); + items.put(item); + + cursor.moveToNext(); + } + // Make sure to close the cursor + cursor.close(); + return items; + } + + private static JSONObject cursorToJson(String[] columns, Cursor cursor) throws + JSONException { + JSONObject jsonItem = new JSONObject(); + int i=0; + for (String col : columns) { + switch (col) { + case "lending": + case "ebook": + // boolean wie int + case "prolongCount": + // Integer + jsonItem.put(col, Integer.toString(cursor.getInt(i++))); + break; + case "historyId AS _id": + col = "historyId"; + case "firstDate": + case "lastDate": + case "deadline": + // date wie String + default: + // String + jsonItem.put(col, cursor.getString(i++)); + } + } + + return jsonItem; + } + public static HistoryItem cursorToItem(Cursor cursor) { HistoryItem item = new HistoryItem(); int i=0; @@ -207,6 +263,44 @@ public void insertHistoryItem(HistoryItem historyItem ) { .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), values); } + public void insertHistoryItem(JSONObject item ) throws JSONException { + ContentValues values = new ContentValues(); + Iterator keys = item.keys(); + while(keys.hasNext()) { + String key = keys.next(); + switch (key) { + case "lending": + case "ebook": + // boolean + boolean b = (1 == item.getInt(key)); + putOrNull(values, key, b ); + break; + case "prolongCount": + // Integer + try { + int i = item.getInt(key); + values.put(key, i); + } catch (JSONException e) { + values.putNull(key); + } + break; + case "historyId AS _id": + // putOrNull(values,"historyId", item.getString(key) ); + // key wird neu vergeben. + break; + case "firstDate": + case "lastDate": + case "deadline": + // date wird als String inserted + default: + // String + putOrNull(values,key, item.getString(key) ); + } + } + context.getContentResolver() + .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), values); + } + private void insertLentItem(String bib, LentItem lentItem ) { ContentValues values = new ContentValues(); addAccountItemValues(values, lentItem); From 3f6af95750fdd3d027622fb5562c791967491bd5 Mon Sep 17 00:00:00 2001 From: Justy Date: Mon, 23 Dec 2019 15:15:48 +0100 Subject: [PATCH 06/32] Import History: Import mit merge, Insert or update Rows --- .../opacclient/frontend/HistoryFragment.java | 29 ++-- .../opacclient/storage/HistoryDataSource.java | 158 +++++++++++++++--- .../opacclient/storage/HistoryDatabase.java | 89 +++++++--- .../src/main/res/values-de/strings.xml | 1 + .../opacapp/src/main/res/values/strings.xml | 1 + 5 files changed, 219 insertions(+), 59 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index c4e3d7a21..cf963f700 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -98,9 +98,6 @@ public class HistoryFragment extends Fragment implements private static final String STATE_ACTIVATED_POSITION = "activated_position"; private static final String JSON_LIBRARY_NAME = "library_name"; private static final String JSON_HISTORY_LIST = "history_list"; - private static final String JSON_ITEM_MNR = "medianr"; - private static final String JSON_ITEM_TITLE = "title"; - private static final String JSON_ITEM_MEDIATYPE = "mediatype"; private static final int REQUEST_CODE_EXPORT = 123; private static final int REQUEST_CODE_IMPORT = 124; @@ -492,26 +489,34 @@ public void onActivityResult(int requestCode, int resultCode, Intent intent) { String list = builder.toString(); JSONObject savedList = new JSONObject(list); String bib = savedList.getString(JSON_LIBRARY_NAME); + //disallow import if from different library than current library if (bib != null && !bib.equals(app.getLibrary().getIdent())) { Snackbar.make(getView(), R.string.info_different_library, Snackbar.LENGTH_SHORT).show(); return; } + + int countUpdate = 0; + int countInsert = 0; JSONArray items = savedList.getJSONArray(JSON_HISTORY_LIST); for (int i = 0; i < items.length(); i++) { JSONObject entry = items.getJSONObject(i); - if (entry.has(JSON_ITEM_MNR) && - !dataSource.isHistory(bib, entry.getString(JSON_ITEM_MNR)) || - !entry.has(JSON_ITEM_MNR) /* && !dataSource.isHistoryTitle(bib, - entry.getString(JSON_ITEM_TITLE))*/) { //disallow dupes - // String mediatype = entry.optString(JSON_ITEM_MEDIATYPE, null); - dataSource.insertHistoryItem(entry); + HistoryDataSource.ChangeType ct = dataSource.insertOrUpdate(bib, entry); + switch (ct) { + case UPDATE: countUpdate++; break; + case INSERT: countInsert++; break; } } - adapter.notifyDataSetChanged(); - Snackbar.make(getView(), R.string.info_history_updated, - Snackbar.LENGTH_SHORT).show(); + if(countInsert>0 || countUpdate>0) { + adapter.notifyDataSetChanged(); + Snackbar.make(getView(), + getString(R.string.info_history_updated_count, countInsert, countUpdate), + Snackbar.LENGTH_LONG).show(); + } else { + Snackbar.make(getView(), R.string.info_history_updated, + Snackbar.LENGTH_SHORT).show(); + } } else { showImportError(); } diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index e2749baac..1d8ddb233 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -27,6 +27,7 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.text.BoringLayout; +import android.util.Log; import org.joda.time.LocalDate; import org.json.JSONArray; @@ -54,8 +55,7 @@ public class HistoryDataSource { private SQLiteDatabase database; private String[] allColumns = HistoryDatabase.COLUMNS; -// private Context context; -// public HistoryDataSource(Context context) { + public enum ChangeType { NOTHING, UPDATE, INSERT}; private Activity context; public HistoryDataSource(Activity context) { @@ -147,6 +147,73 @@ public JSONArray getAllItemsAsJson(String bib) throws return items; } + public ChangeType insertOrUpdate(String bib, JSONObject entry) throws JSONException { + + final String methodName = "insertOrUpdate"; + + // - same id/medianr or same (title, author and type) + // - and Zeitraum=(first bis last) überschneiden sich + LocalDate firstDate = LocalDate.parse(entry.getString(HistoryDatabase.HIST_COL_FIRST_DATE)); + LocalDate lastDate = LocalDate.parse(entry.getString(HistoryDatabase.HIST_COL_LAST_DATE)); + + Log.d(methodName, String.format("bib: %s, json: dates %s - %s", bib, firstDate, lastDate)); + + HistoryItem item = null; + + if (entry.has(HistoryDatabase.HIST_COL_MEDIA_NR)) { + // + String id = entry.getString(HistoryDatabase.HIST_COL_MEDIA_NR); + Log.d(methodName, String.format("json: medianr %s", id)); + item = isHistory(bib, id, firstDate, lastDate); + } else { + // title, type and author + String title = entry.getString(HistoryDatabase.HIST_COL_TITLE); + String author = entry.getString(HistoryDatabase.HIST_COL_AUTHOR); + String mediatype = entry.getString(HistoryDatabase.HIST_COL_MEDIA_TYPE); + Log.d(methodName, String.format("json: title %s, author %s, mediatype %s" + ,title, author, mediatype)); + item = isHistory(bib, title, author, mediatype , firstDate, lastDate); + } + Log.d(methodName, String.format("HistoryItem: %s", item)); + + ChangeType changeType = ChangeType.NOTHING; + if (item==null) { + // noch kein entsprechender Satz in Datenbank + Log.d(methodName, "call insertHistoryItem(...)"); + insertHistoryItem(bib, entry); + changeType = ChangeType.INSERT; + } else { + // Satz vorhanden, ev. updaten + + // firstDate, lastDate und count 'mergen' + if (firstDate.compareTo(item.getFirstDate())<0) { + Log.d(methodName, "firstDate changed"); + changeType = ChangeType.UPDATE; + item.setFirstDate(firstDate); + } + if (lastDate.compareTo(item.getLastDate())>0) { + Log.d(methodName, "lastDate changed"); + changeType = ChangeType.UPDATE; + item.setLastDate(lastDate); + } + int prolongCount = entry.getInt(HistoryDatabase.HIST_COL_PROLONG_COUNT); + if (prolongCount > item.getProlongCount()) { + Log.d(methodName, "prolongCount changed"); + changeType = ChangeType.UPDATE; + item.setProlongCount(prolongCount); + } + + if (changeType == ChangeType.UPDATE) { + Log.d(methodName, "call updateHistoryItem(...)"); + updateHistoryItem(item); + } else { + Log.d(methodName, "nothing changed"); + } + } + + return changeType; + } + private static JSONObject cursorToJson(String[] columns, Cursor cursor) throws JSONException { JSONObject jsonItem = new JSONObject(); @@ -162,8 +229,8 @@ private static JSONObject cursorToJson(String[] columns, Cursor cursor) throws break; case "historyId AS _id": col = "historyId"; - case "firstDate": - case "lastDate": + case HistoryDatabase.HIST_COL_FIRST_DATE: + case HistoryDatabase.HIST_COL_LAST_DATE: case "deadline": // date wie String default: @@ -235,8 +302,8 @@ private ContentValues createContentValues(HistoryItem historyItem) { ContentValues values = new ContentValues(); addAccountItemValues(values, historyItem); - putOrNull(values,"firstDate", historyItem.getFirstDate()); - putOrNull(values,"lastDate", historyItem.getLastDate()); + putOrNull(values,HistoryDatabase.HIST_COL_FIRST_DATE, historyItem.getFirstDate()); + putOrNull(values,HistoryDatabase.HIST_COL_LAST_DATE, historyItem.getLastDate()); putOrNull(values,"lending", historyItem.isLending()); putOrNull(values,"bib", historyItem.getBib()); putOrNull(values,"homeBranch", historyItem.getHomeBranch()); @@ -254,17 +321,21 @@ private void updateHistoryItem(HistoryItem historyItem ) { String where = "historyId = ?"; context.getContentResolver() .update(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri() - , values, where, new String[]{Integer.toString(historyItem.getHistoryId())} ); + , values, where, new String[]{Integer.toString(historyItem.getHistoryId()) + } ); } public void insertHistoryItem(HistoryItem historyItem ) { ContentValues values = createContentValues(historyItem); context.getContentResolver() - .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), values); + .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), + values); } - public void insertHistoryItem(JSONObject item ) throws JSONException { + public void insertHistoryItem(String bib, JSONObject item ) throws JSONException { ContentValues values = new ContentValues(); + values.put("bib", bib); + Iterator keys = item.keys(); while(keys.hasNext()) { String key = keys.next(); @@ -284,12 +355,16 @@ public void insertHistoryItem(JSONObject item ) throws JSONException { values.putNull(key); } break; + case HistoryDatabase.HIST_COL_HISTORY_ID: case "historyId AS _id": + // egal was für eine historyId der Eintrag (in einer anderen HistoryDB) + // hatte, hier wird die historyId neu vergeben (auch wg Duplicat Key) + // putOrNull(values,"historyId", item.getString(key) ); // key wird neu vergeben. break; - case "firstDate": - case "lastDate": + case HistoryDatabase.HIST_COL_FIRST_DATE: + case HistoryDatabase.HIST_COL_LAST_DATE: case "deadline": // date wird als String inserted default: @@ -298,15 +373,16 @@ public void insertHistoryItem(JSONObject item ) throws JSONException { } } context.getContentResolver() - .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), values); + .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), + values); } private void insertLentItem(String bib, LentItem lentItem ) { ContentValues values = new ContentValues(); addAccountItemValues(values, lentItem); - putOrNull(values, "firstDate", LocalDate.now()); - putOrNull(values, "lastDate", LocalDate.now()); + putOrNull(values, HistoryDatabase.HIST_COL_FIRST_DATE, LocalDate.now()); + putOrNull(values, HistoryDatabase.HIST_COL_LAST_DATE, LocalDate.now()); putOrNull(values, "lending", true); putOrNull(values, "bib", bib); @@ -317,7 +393,8 @@ private void insertLentItem(String bib, LentItem lentItem ) { putOrNull(values, "deadline", lentItem.getDeadline()); context.getContentResolver() - .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), values); + .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), + values); } private void putOrNull(ContentValues cv, String key, String value) { @@ -416,7 +493,7 @@ public HistoryItem getItem(String bib, String id) { .getContentResolver() .query(((OpacClient) context.getApplication()) .getHistoryProviderHistoryUri(), - HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_NR_LIB, + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_NR, selA, null); HistoryItem item = null; @@ -450,20 +527,59 @@ public HistoryItem getItem(long id) { return item; } - public boolean isHistory(String bib, String id) { + public HistoryItem isHistory(String bib, String id, LocalDate firstDate, LocalDate lastDate) { if (id == null) { - return false; + return null; } + String[] selA = {bib, id}; Cursor cursor = context .getContentResolver() .query(((OpacClient) context.getApplication()) .getHistoryProviderHistoryUri(), - HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_NR_LIB, + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_NR, selA, null); - int c = cursor.getCount(); + cursor.moveToFirst(); + HistoryItem item = foo(cursor, firstDate, lastDate); cursor.close(); - return (c > 0); + + return item; + } + + public HistoryItem isHistory(String bib, String title, String author, String mediatype + , LocalDate firstDate, LocalDate lastDate) { + + String[] selA = {bib, title, author, mediatype}; + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_TITLE_AUTHOR_TYPE, + selA, null); + cursor.moveToFirst(); + HistoryItem item = foo(cursor, firstDate, lastDate); + cursor.close(); + return item; + } + + private HistoryItem foo(Cursor cursor, LocalDate firstDate, LocalDate lastDate) { + while (!cursor.isAfterLast()) { + HistoryItem item = cursorToItem(cursor); + + if (firstDate.compareTo(item.getLastDate())>0) { + // firstDate > item.lastDate: Zeitraum überschneidet sich nicht + } else if (item.getFirstDate().compareTo(lastDate)>0) { + // item.firstDate > lastDate: Zeitraum überschneidet sich nicht + item = null; + } else { + // Zeitraum überschneidet sich + return item; + } + + cursor.moveToNext(); + } + + return null; } public boolean isHistoryTitle(String bib, String title) { diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java index a5b8f60cf..44fccdad5 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java @@ -30,52 +30,69 @@ public class HistoryDatabase extends SQLiteOpenHelper { public static final String HIST_TABLE = "historyTable"; - // CHANGE THIS - public static final String HIST_WHERE_HISTORY_ID = "historyId = ?"; + public static final String HIST_COL_HISTORY_ID = "historyId"; + public static final String HIST_COL_MEDIA_NR = "medianr"; + public static final String HIST_COL_TITLE = "title"; + public static final String HIST_COL_AUTHOR = "author"; + public static final String HIST_COL_MEDIA_TYPE = "mediatype"; + public static final String HIST_COL_FIRST_DATE = "firstDate"; + public static final String HIST_COL_LAST_DATE = "lastDate"; + public static final String HIST_COL_PROLONG_COUNT = "prolongCount"; + + public static final String HIST_WHERE_HISTORY_ID = HIST_COL_HISTORY_ID +" = ?"; public static final String HIST_WHERE_LIB = "bib = ?"; + public static final String HIST_WHERE_LIB_LENDING = "bib = ? AND lending = 1"; - public static final String HIST_WHERE_TITLE_LIB = "bib = ? AND medianr IS NULL AND title = ?"; - public static final String HIST_WHERE_NR_LIB = "bib = ? AND medianr = ?"; - public static final String[] COLUMNS = {"historyId AS _id", // wg. android.widget.CursorAdapter + public static final String HIST_WHERE_TITLE_LIB = "bib = ? AND " + + HIST_COL_MEDIA_NR + " IS NULL AND " + + HIST_COL_TITLE + " = ?"; + public static final String HIST_WHERE_LIB_NR = "bib = ? AND " + + HIST_COL_MEDIA_NR + " = ?"; + public static final String HIST_WHERE_LIB_TITLE_AUTHOR_TYPE = "bib = ? AND " + + HIST_COL_TITLE + " = ? AND " + + HIST_COL_AUTHOR + " = ? AND " + + HIST_COL_MEDIA_TYPE + " = ?" + ; + public static final String[] COLUMNS = {HIST_COL_HISTORY_ID +" AS _id", // wg. android.widget.CursorAdapter // siehe https://developer.android.com/reference/android/widget/CursorAdapter.html - "firstDate", - "lastDate", + HIST_COL_FIRST_DATE, + HIST_COL_LAST_DATE, "lending", - "medianr", + HIST_COL_MEDIA_NR, "bib", - "title", - "author", + HIST_COL_TITLE, + HIST_COL_AUTHOR, "format", "status", "cover", - "mediatype", + HIST_COL_MEDIA_TYPE, "homeBranch", "lendingBranch", "ebook", "barcode", "deadline", - "prolongCount" + HIST_COL_PROLONG_COUNT }; private static final String DATABASE_CREATE = "create table historyTable (\n" + - "\thistoryId integer primary key autoincrement,\n" + - "\tfirstDate date,\n" + - "\tlastDate date,\n" + + "\t" + HIST_COL_HISTORY_ID +" integer primary key autoincrement,\n" + + "\t" + HIST_COL_FIRST_DATE + " date,\n" + + "\t" + HIST_COL_LAST_DATE + " date,\n" + "\tlending boolean,\n" + - "\tmedianr text,\n" + + "\t" + HIST_COL_MEDIA_NR + " text,\n" + "\tbib text,\n" + - "\ttitle text,\n" + - "\tauthor text,\n" + + "\t" + HIST_COL_TITLE + " text,\n" + + "\t" + HIST_COL_AUTHOR + " text,\n" + "\tformat text,\n" + "\tstatus text,\n" + "\tcover text,\n" + - "\tmediatype text,\n" + + "\t" + HIST_COL_MEDIA_TYPE + " text,\n" + "\thomeBranch text,\n" + "\tlendingBranch text,\n" + "\tebook boolean,\n" + "\tbarcode text,\n" + "\tdeadline date,\n" + - "\tprolongCount integer\n" + + "\t" + HIST_COL_PROLONG_COUNT + " integer\n" + ");"; @@ -98,14 +115,34 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + oldVersion + " to " + newVersion + ", which will destroy all old data"); - db.execSQL( - "create table temp ( id integer primary key autoincrement, medianr text, " + - "bib text, title text );"); - db.execSQL("insert into temp select * from " + HIST_TABLE + ";"); + final String createTemp = + "create table tempTable (\n" + + "\t" + HIST_COL_HISTORY_ID +" integer primary key autoincrement,\n" + + "\t" + HIST_COL_FIRST_DATE + " date,\n" + + "\t" + HIST_COL_LAST_DATE + " date,\n" + + "\tlending boolean,\n" + + "\t" + HIST_COL_MEDIA_NR + " text,\n" + + "\tbib text,\n" + + "\t" + HIST_COL_TITLE + " text,\n" + + "\t" + HIST_COL_AUTHOR + " text,\n" + + "\tformat text,\n" + + "\tstatus text,\n" + + "\tcover text,\n" + + "\t" + HIST_COL_MEDIA_TYPE + " text,\n" + + "\thomeBranch text,\n" + + "\tlendingBranch text,\n" + + "\tebook boolean,\n" + + "\tbarcode text,\n" + + "\tdeadline date,\n" + + "\t" + HIST_COL_PROLONG_COUNT + " integer\n" + + ");"; + + db.execSQL(createTemp); + db.execSQL("insert into tempTable select * from " + HIST_TABLE + ";"); db.execSQL("drop table " + HIST_TABLE + ";"); onCreate(db); - db.execSQL("insert into " + HIST_TABLE + " select * from temp;"); - db.execSQL("drop table temp;"); + db.execSQL("insert into " + HIST_TABLE + " select * from tempTable;"); + db.execSQL("drop table tempTable;"); } } diff --git a/opacclient/opacapp/src/main/res/values-de/strings.xml b/opacclient/opacapp/src/main/res/values-de/strings.xml index f501ac981..7028e52a3 100644 --- a/opacclient/opacapp/src/main/res/values-de/strings.xml +++ b/opacclient/opacapp/src/main/res/values-de/strings.xml @@ -362,4 +362,5 @@ seit %1$s für 1 Tag Beginndatum Endedatum + Import abgeschlossen, %1$d Einträge hinzugefügt, %2$d geändert diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index dcc52aac3..8f2bb4126 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -118,6 +118,7 @@ Selected list is from another library! Try switching to the correct library Import complete. History import complete. + History import complete. %1$d new items, %2$d changed items The connection to the library server failed. Please check your internet connection. If the problem persists, there may have been a problem on the library server or the app was unable to parse the server\'s response. The connection to the library server failed. Please check your internet connection. If the problem persists, there may have been a problem on the library server. From ab3813e162722abad4fd0a7509fd42bf693670b2 Mon Sep 17 00:00:00 2001 From: Justy Date: Thu, 26 Dec 2019 17:09:49 +0100 Subject: [PATCH 07/32] Columns lending und deadline Konstanten definiert. --- .../opacclient/storage/HistoryDataSource.java | 22 +++++++++---------- .../opacclient/storage/HistoryDatabase.java | 12 +++++----- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index 1d8ddb233..b6034b32d 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -220,7 +220,7 @@ private static JSONObject cursorToJson(String[] columns, Cursor cursor) throws int i=0; for (String col : columns) { switch (col) { - case "lending": + case HistoryDatabase.HIST_COL_LENDING: case "ebook": // boolean wie int case "prolongCount": @@ -231,7 +231,7 @@ private static JSONObject cursorToJson(String[] columns, Cursor cursor) throws col = "historyId"; case HistoryDatabase.HIST_COL_FIRST_DATE: case HistoryDatabase.HIST_COL_LAST_DATE: - case "deadline": + case HistoryDatabase.HIST_COL_DEADLINE: // date wie String default: // String @@ -288,9 +288,9 @@ public static HistoryItem cursorToItem(Cursor cursor) { } private void addAccountItemValues(ContentValues values, AccountItem item ) { - putOrNull(values,"medianr", item.getId()); - putOrNull(values,"title", item.getTitle()); - putOrNull(values,"author", item.getAuthor()); + putOrNull(values,HistoryDatabase.HIST_COL_MEDIA_NR, item.getId()); + putOrNull(values,HistoryDatabase.HIST_COL_TITLE, item.getTitle()); + putOrNull(values,HistoryDatabase.HIST_COL_AUTHOR, item.getAuthor()); putOrNull(values,"format", item.getFormat()); putOrNull(values,"status", item.getStatus()); putOrNull(values,"cover", item.getCover()); @@ -304,13 +304,13 @@ private ContentValues createContentValues(HistoryItem historyItem) { putOrNull(values,HistoryDatabase.HIST_COL_FIRST_DATE, historyItem.getFirstDate()); putOrNull(values,HistoryDatabase.HIST_COL_LAST_DATE, historyItem.getLastDate()); - putOrNull(values,"lending", historyItem.isLending()); + putOrNull(values,HistoryDatabase.HIST_COL_LENDING, historyItem.isLending()); putOrNull(values,"bib", historyItem.getBib()); putOrNull(values,"homeBranch", historyItem.getHomeBranch()); putOrNull(values,"lendingBranch", historyItem.getLendingBranch()); putOrNull(values,"ebook", historyItem.isEbook()); putOrNull(values,"barcode", historyItem.getBarcode()); - putOrNull(values,"deadline", historyItem.getDeadline()); + putOrNull(values,HistoryDatabase.HIST_COL_DEADLINE, historyItem.getDeadline()); values.put("prolongCount", historyItem.getProlongCount()); return values; @@ -340,7 +340,7 @@ public void insertHistoryItem(String bib, JSONObject item ) throws JSONException while(keys.hasNext()) { String key = keys.next(); switch (key) { - case "lending": + case HistoryDatabase.HIST_COL_LENDING: case "ebook": // boolean boolean b = (1 == item.getInt(key)); @@ -365,7 +365,7 @@ public void insertHistoryItem(String bib, JSONObject item ) throws JSONException break; case HistoryDatabase.HIST_COL_FIRST_DATE: case HistoryDatabase.HIST_COL_LAST_DATE: - case "deadline": + case HistoryDatabase.HIST_COL_DEADLINE: // date wird als String inserted default: // String @@ -383,14 +383,14 @@ private void insertLentItem(String bib, LentItem lentItem ) { putOrNull(values, HistoryDatabase.HIST_COL_FIRST_DATE, LocalDate.now()); putOrNull(values, HistoryDatabase.HIST_COL_LAST_DATE, LocalDate.now()); - putOrNull(values, "lending", true); + putOrNull(values, HistoryDatabase.HIST_COL_LENDING, true); putOrNull(values, "bib", bib); putOrNull(values, "homeBranch", lentItem.getHomeBranch()); putOrNull(values, "lendingBranch", lentItem.getLendingBranch()); putOrNull(values, "ebook", lentItem.isEbook()); putOrNull(values, "barcode", lentItem.getBarcode()); - putOrNull(values, "deadline", lentItem.getDeadline()); + putOrNull(values, HistoryDatabase.HIST_COL_DEADLINE, lentItem.getDeadline()); context.getContentResolver() .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java index 44fccdad5..aa07a16e8 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java @@ -38,6 +38,8 @@ public class HistoryDatabase extends SQLiteOpenHelper { public static final String HIST_COL_FIRST_DATE = "firstDate"; public static final String HIST_COL_LAST_DATE = "lastDate"; public static final String HIST_COL_PROLONG_COUNT = "prolongCount"; + public static final String HIST_COL_DEADLINE = "deadline"; + public static final String HIST_COL_LENDING = "lending"; public static final String HIST_WHERE_HISTORY_ID = HIST_COL_HISTORY_ID +" = ?"; public static final String HIST_WHERE_LIB = "bib = ?"; @@ -57,7 +59,7 @@ public class HistoryDatabase extends SQLiteOpenHelper { // siehe https://developer.android.com/reference/android/widget/CursorAdapter.html HIST_COL_FIRST_DATE, HIST_COL_LAST_DATE, - "lending", + HIST_COL_LENDING, HIST_COL_MEDIA_NR, "bib", HIST_COL_TITLE, @@ -70,7 +72,7 @@ public class HistoryDatabase extends SQLiteOpenHelper { "lendingBranch", "ebook", "barcode", - "deadline", + HIST_COL_DEADLINE, HIST_COL_PROLONG_COUNT }; @@ -91,7 +93,7 @@ public class HistoryDatabase extends SQLiteOpenHelper { "\tlendingBranch text,\n" + "\tebook boolean,\n" + "\tbarcode text,\n" + - "\tdeadline date,\n" + + "\t" + HIST_COL_DEADLINE + " date,\n" + "\t" + HIST_COL_PROLONG_COUNT + " integer\n" + ");"; @@ -120,7 +122,7 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { "\t" + HIST_COL_HISTORY_ID +" integer primary key autoincrement,\n" + "\t" + HIST_COL_FIRST_DATE + " date,\n" + "\t" + HIST_COL_LAST_DATE + " date,\n" + - "\tlending boolean,\n" + + "\t" + HIST_COL_LENDING + " boolean,\n" + "\t" + HIST_COL_MEDIA_NR + " text,\n" + "\tbib text,\n" + "\t" + HIST_COL_TITLE + " text,\n" + @@ -133,7 +135,7 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { "\tlendingBranch text,\n" + "\tebook boolean,\n" + "\tbarcode text,\n" + - "\tdeadline date,\n" + + "\t" + HIST_COL_DEADLINE + " date,\n" + "\t" + HIST_COL_PROLONG_COUNT + " integer\n" + ");"; From 447e90559fcf0e71ef5eb343690295d44ab2699b Mon Sep 17 00:00:00 2001 From: Justy Date: Tue, 31 Dec 2019 17:56:49 +0100 Subject: [PATCH 08/32] Verlauf nach Chronik umbenannt in de/strings.xml --- opacclient/opacapp/src/main/res/values-de/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opacclient/opacapp/src/main/res/values-de/strings.xml b/opacclient/opacapp/src/main/res/values-de/strings.xml index 7028e52a3..6eb42eda5 100644 --- a/opacclient/opacapp/src/main/res/values-de/strings.xml +++ b/opacclient/opacapp/src/main/res/values-de/strings.xml @@ -342,7 +342,7 @@ behoben. mehr Infos Importieren - Aus dem Verlauf gelöscht + Aus der Chronik gelöscht Rückgängig Sortieren nach Author @@ -351,11 +351,11 @@ nach Ende Verlängerungen Titel - Import des Verlaufs abgeschlossen - Verlauf + Import der Chronik abgeschlossen + Chronik Teilen Exportieren - Dies ist deine Verlaufsliste. Die Liste wird für jede Bibliothek, die du benutzt, separat geführt. + Dies ist deine Leih-Chronik. Die Liste wird für jede Bibliothek, die du benutzt, separat geführt. vom %1$s für %2$d Tage seit %1$s für %2$d Tage vom %1$s für 1 Tag From 6bfb730e2cc12df9b92591980aacbf96e6676fa7 Mon Sep 17 00:00:00 2001 From: Justy Date: Mon, 6 Jan 2020 21:09:21 +0100 Subject: [PATCH 09/32] refactoring: Methodennamen, mediaId bei Abgleich History-/LentItem nutzen --- .../opacclient/objects/HistoryItem.java | 21 +++++++---- .../opacclient/frontend/HistoryFragment.java | 6 +-- .../opacclient/storage/HistoryDataSource.java | 37 +++++++++---------- .../opacclient/storage/HistoryDatabase.java | 2 +- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java index f7cd32673..b81cac647 100644 --- a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java +++ b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java @@ -161,16 +161,21 @@ public void setHistoryId(int historyId) { this.historyId = historyId; } - // MNr wie bei Starred - public String getMNr() { - return super.getId(); - } - public void setMNr(String mnr) { - super.setId(mnr); - } - public boolean isSameAsLentItem(LentItem lentItem) { + // Id/MediaNr + if (getId() == null) { + if (lentItem.getId() != null) { + return false; + } + } else { + if (!getId().equals(lentItem.getId())) { + return false; + } + // Id/MediaNr are equal + // return true; ?? + } + if (getMediaType() == null) { if (lentItem.getMediaType() != null) { return false; diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index cf963f700..576a392a7 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -134,8 +134,8 @@ public void onItemClick(AdapterView parent, View view, int position, long id) { HistoryItem item = (HistoryItem) view.findViewById(R.id.ivDelete) .getTag(); - if (item.getMNr() == null || item.getMNr().equals("null") - || item.getMNr().equals("")) { + if (item.getId() == null || item.getId().equals("null") + || item.getId().equals("")) { SharedPreferences sp = PreferenceManager .getDefaultSharedPreferences(getActivity()); @@ -336,7 +336,7 @@ protected void share() { text.append("\n"); String shareUrl; try { - shareUrl = app.getApi().getShareUrl(item.getMNr(), + shareUrl = app.getApi().getShareUrl(item.getId(), item.getTitle()); } catch (OpacClient.LibraryRemovedException e) { return; diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index b6034b32d..b58e69d09 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -161,10 +161,10 @@ public ChangeType insertOrUpdate(String bib, JSONObject entry) throws JSONExcep HistoryItem item = null; if (entry.has(HistoryDatabase.HIST_COL_MEDIA_NR)) { - // + // mediaNr eindeutig String id = entry.getString(HistoryDatabase.HIST_COL_MEDIA_NR); Log.d(methodName, String.format("json: medianr %s", id)); - item = isHistory(bib, id, firstDate, lastDate); + item = findItem(bib, id, firstDate, lastDate); } else { // title, type and author String title = entry.getString(HistoryDatabase.HIST_COL_TITLE); @@ -172,7 +172,7 @@ public ChangeType insertOrUpdate(String bib, JSONObject entry) throws JSONExcep String mediatype = entry.getString(HistoryDatabase.HIST_COL_MEDIA_TYPE); Log.d(methodName, String.format("json: title %s, author %s, mediatype %s" ,title, author, mediatype)); - item = isHistory(bib, title, author, mediatype , firstDate, lastDate); + item = findItem(bib, title, author, mediatype , firstDate, lastDate); } Log.d(methodName, String.format("HistoryItem: %s", item)); @@ -255,7 +255,7 @@ public static HistoryItem cursorToItem(Cursor cursor) { item.setLastDate(LocalDate.parse(ds)); } item.setLending(cursor.getInt(i++) > 0); - item.setMNr(cursor.getString(i++)); + item.setId(cursor.getString(i++)); item.setBib(cursor.getString(i++)); item.setTitle(cursor.getString(i++)); item.setAuthor(cursor.getString(i++)); @@ -487,13 +487,13 @@ public HistoryItem getItemByTitle(String bib, String title) { return item; } - public HistoryItem getItem(String bib, String id) { - String[] selA = {bib, id}; + public HistoryItem getItem(String bib, String mediaNr) { + String[] selA = {bib, mediaNr}; Cursor cursor = context .getContentResolver() .query(((OpacClient) context.getApplication()) .getHistoryProviderHistoryUri(), - HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_NR, + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_MEDIA_NR, selA, null); HistoryItem item = null; @@ -507,8 +507,8 @@ public HistoryItem getItem(String bib, String id) { return item; } - public HistoryItem getItem(long id) { - String[] selA = {String.valueOf(id)}; + public HistoryItem getItem(long historyId) { + String[] selA = {String.valueOf(historyId)}; Cursor cursor = context .getContentResolver() .query(((OpacClient) context.getApplication()) @@ -527,26 +527,25 @@ public HistoryItem getItem(long id) { return item; } - public HistoryItem isHistory(String bib, String id, LocalDate firstDate, LocalDate lastDate) { - if (id == null) { + private HistoryItem findItem(String bib, String mediaNr, LocalDate firstDate, LocalDate lastDate) { + if (mediaNr == null) { return null; } - String[] selA = {bib, id}; + String[] selA = {bib, mediaNr}; Cursor cursor = context .getContentResolver() .query(((OpacClient) context.getApplication()) .getHistoryProviderHistoryUri(), - HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_NR, + HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_MEDIA_NR, selA, null); - cursor.moveToFirst(); - HistoryItem item = foo(cursor, firstDate, lastDate); + HistoryItem item = findItemToDates(cursor, firstDate, lastDate); cursor.close(); return item; } - public HistoryItem isHistory(String bib, String title, String author, String mediatype + private HistoryItem findItem(String bib, String title, String author, String mediatype , LocalDate firstDate, LocalDate lastDate) { String[] selA = {bib, title, author, mediatype}; @@ -556,13 +555,13 @@ public HistoryItem isHistory(String bib, String title, String author, String med .getHistoryProviderHistoryUri(), HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_TITLE_AUTHOR_TYPE, selA, null); - cursor.moveToFirst(); - HistoryItem item = foo(cursor, firstDate, lastDate); + HistoryItem item = findItemToDates(cursor, firstDate, lastDate); cursor.close(); return item; } - private HistoryItem foo(Cursor cursor, LocalDate firstDate, LocalDate lastDate) { + private HistoryItem findItemToDates(Cursor cursor, LocalDate firstDate, LocalDate lastDate) { + cursor.moveToFirst(); while (!cursor.isAfterLast()) { HistoryItem item = cursorToItem(cursor); diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java index aa07a16e8..ae3d669d3 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java @@ -48,7 +48,7 @@ public class HistoryDatabase extends SQLiteOpenHelper { public static final String HIST_WHERE_TITLE_LIB = "bib = ? AND " + HIST_COL_MEDIA_NR + " IS NULL AND " + HIST_COL_TITLE + " = ?"; - public static final String HIST_WHERE_LIB_NR = "bib = ? AND " + public static final String HIST_WHERE_LIB_MEDIA_NR = "bib = ? AND " + HIST_COL_MEDIA_NR + " = ?"; public static final String HIST_WHERE_LIB_TITLE_AUTHOR_TYPE = "bib = ? AND " + HIST_COL_TITLE + " = ? AND " From f85c002768e427d1555d8db4781d56698fdb9102 Mon Sep 17 00:00:00 2001 From: Justy Date: Mon, 6 Jan 2020 21:11:59 +0100 Subject: [PATCH 10/32] =?UTF-8?q?case=20history=20bei=20fixNavigationSelec?= =?UTF-8?q?tion=20und=20getItem=20erg=C3=A4nzt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../de/geeksfactory/opacclient/frontend/OpacActivity.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java index 2fa8f7033..a7a980c8a 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java @@ -380,6 +380,8 @@ protected void fixNavigationSelection() { drawer.setCheckedItem(R.id.nav_search); } else if (fragment instanceof AccountFragment) { drawer.setCheckedItem(R.id.nav_account); + } else if (fragment instanceof HistoryFragment) { + drawer.setCheckedItem(R.id.nav_history); } else if (fragment instanceof StarredFragment) { drawer.setCheckedItem(R.id.nav_starred); } else if (fragment instanceof InfoFragment) { @@ -494,6 +496,9 @@ protected void selectItem(String tag) { case "starred": id = R.id.nav_starred; break; + case "history": + id = R.id.nav_history; + break; case "info": id = R.id.nav_info; break; From 5a1ee330c7ac1e0f36e65b83e7559284db589c5b Mon Sep 17 00:00:00 2001 From: Justy Date: Mon, 6 Jan 2020 21:17:10 +0100 Subject: [PATCH 11/32] Preference history_maintain. --- .../opacclient/frontend/AccountFragment.java | 20 ++++++++++++------ .../frontend/MainPreferenceFragment.java | 21 +++++++++++++++++++ .../storage/PreferenceDataSource.java | 4 ++++ .../src/main/res/values-de/strings.xml | 3 +++ .../opacapp/src/main/res/values/strings.xml | 3 +++ .../opacapp/src/main/res/xml/settings.xml | 7 +++++++ 6 files changed, 52 insertions(+), 6 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java index fe93e58ee..890087da4 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java @@ -1476,14 +1476,22 @@ protected AccountData doInBackground(Void... voids) { adatasource.update(account); adatasource.storeCachedAccountData(adatasource.getAccount(data.getAccount()), data); - // Update Lent-History - HistoryDataSource historyDataSource; + PreferenceDataSource prefs = null; if (getActivity() == null && OpacClient.getEmergencyContext() != null) { - // TODO HistoryDataSource erwartet Activity - // historyDataSource = new HistoryDataSource(OpacClient.getEmergencyContext()); + prefs = new PreferenceDataSource(OpacClient.getEmergencyContext()); } else { - historyDataSource = new HistoryDataSource(getActivity()); - historyDataSource.updateLenting(adatasource.getAccount(data.getAccount()), data); + prefs = new PreferenceDataSource(getActivity()); + } + if (prefs.isHistoryMaintain()) { + // Update Lent-History + HistoryDataSource historyDataSource; + if (getActivity() == null && OpacClient.getEmergencyContext() != null) { + // TODO HistoryDataSource erwartet Activity, Context reicht nicht + // historyDataSource = new HistoryDataSource(OpacClient.getEmergencyContext()); + } else { + historyDataSource = new HistoryDataSource(getActivity()); + historyDataSource.updateLenting(adatasource.getAccount(data.getAccount()), data); + } } } finally { diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainPreferenceFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainPreferenceFragment.java index e3237495f..e0fc1438d 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainPreferenceFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainPreferenceFragment.java @@ -134,6 +134,27 @@ public boolean onPreferenceClick(Preference arg0) { }); } + Preference historyMaintain = findPreference("history_maintain"); + if (historyMaintain != null) { + historyMaintain.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean newHistoryMaintain = ((Boolean) newValue).booleanValue(); + if (newHistoryMaintain) { + // nothing more to do + return true; + } + + // false, no History. Maybe delete historyDb? + // TODO historyDb löschen? Ask first (AlertDialog.Builder? + // HistoryDataSource hdata = new HistoryDataSource(context); + // hdata.deleteAll(); + + return true; + } + }); + } + Preference meta = findPreference("meta_clear"); if (meta != null) { meta.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/PreferenceDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/PreferenceDataSource.java index 1a63f5339..47949adc7 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/PreferenceDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/PreferenceDataSource.java @@ -102,6 +102,10 @@ public boolean isLoadCoversOnDataPreferenceSet() { return sp.getBoolean("on_data_load_covers", true); } + public boolean isHistoryMaintain() { + return sp.getBoolean("history_maintain", false); + } + public void setAccountPtrHintShown(int number) { sp.edit().putInt(ACCOUNT_PTR_HINT_SHOWN, number).apply(); } diff --git a/opacclient/opacapp/src/main/res/values-de/strings.xml b/opacclient/opacapp/src/main/res/values-de/strings.xml index 6eb42eda5..c0719a45e 100644 --- a/opacclient/opacapp/src/main/res/values-de/strings.xml +++ b/opacclient/opacapp/src/main/res/values-de/strings.xml @@ -363,4 +363,7 @@ Beginndatum Endedatum Import abgeschlossen, %1$d Einträge hinzugefügt, %2$d geändert + Führe Chronik aller ausgeliehenen Medien + Speicher keine Liste aller jemals ausgeliehenen Medien + Speichere eine Liste aller jemals ausgeliehenen Medien diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index 8f2bb4126..ff82aaf22 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -329,6 +329,9 @@ from %1$s for 1 day Start date Last date + Maintain history lent items + Store title, author, begin-date, end-date ... of all lent items + Do not store a history off all lent items Print Please wait for details to load Library data diff --git a/opacclient/opacapp/src/main/res/xml/settings.xml b/opacclient/opacapp/src/main/res/xml/settings.xml index 6e0e79d8a..a5801e2a3 100644 --- a/opacclient/opacapp/src/main/res/xml/settings.xml +++ b/opacclient/opacapp/src/main/res/xml/settings.xml @@ -28,6 +28,13 @@ android:title="@string/load_covers_mobile_data" android:summaryOn="@string/load_covers_mobile_data_on" android:summaryOff="@string/load_covers_mobile_data_off"/> + + Date: Tue, 7 Jan 2020 21:29:04 +0100 Subject: [PATCH 12/32] Remove History --- .../opacclient/frontend/HistoryFragment.java | 31 ++++++++++++++ .../frontend/MainPreferenceFragment.java | 41 +++++++++++++++++-- .../opacclient/storage/HistoryDataSource.java | 39 ++++++++++++++++++ .../src/main/res/menu/activity_history.xml | 5 +++ .../src/main/res/values-de/strings.xml | 3 ++ .../opacapp/src/main/res/values/strings.xml | 5 ++- 6 files changed, 119 insertions(+), 5 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index 576a392a7..da2c2ab21 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -24,6 +24,7 @@ import android.app.Activity; import android.content.ActivityNotFoundException; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; @@ -70,6 +71,7 @@ import java.util.ArrayList; import java.util.List; +import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityOptionsCompat; import androidx.cursoradapter.widget.SimpleCursorAdapter; @@ -240,6 +242,9 @@ public boolean onOptionsItemSelected(android.view.MenuItem item) { } else if (item.getItemId() == R.id.action_sort_duration) { sort("julianday(lastDate) - julianday(firstDate)"); return true; + } else if (item.getItemId() == R.id.action_remove_all) { + removeAll(); + return true; } return super.onOptionsItemSelected(item); } @@ -279,6 +284,32 @@ public void remove(HistoryItem item) { data.remove(item); } + public void removeAll() { + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which){ + case DialogInterface.BUTTON_POSITIVE: + // Yes button clicked + HistoryDataSource data = new HistoryDataSource(getActivity()); + String bib = app.getLibrary().getIdent(); + data.removeAll(bib); + break; + + case DialogInterface.BUTTON_NEGATIVE: + // No button clicked + break; + } + } + }; + AlertDialog.Builder builder = new AlertDialog.Builder( + getActivity()); + builder.setMessage(R.string.history_remove_all_sure) + .setPositiveButton(R.string.yes, dialogClickListener) + .setNegativeButton(R.string.no, dialogClickListener) + .show(); + } + //Added code to show SnackBar when clicked on Remove button in Favorites screen private void showSnackBar() { Snackbar snackbar = diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainPreferenceFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainPreferenceFragment.java index e0fc1438d..38e08094c 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainPreferenceFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/MainPreferenceFragment.java @@ -21,6 +21,7 @@ import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; @@ -32,6 +33,7 @@ import org.joda.time.DateTime; +import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; @@ -47,6 +49,7 @@ import de.geeksfactory.opacclient.reminder.ReminderHelper; import de.geeksfactory.opacclient.reminder.SyncAccountJob; import de.geeksfactory.opacclient.storage.AccountDataSource; +import de.geeksfactory.opacclient.storage.HistoryDataSource; import de.geeksfactory.opacclient.storage.JsonSearchFieldDataSource; import de.geeksfactory.opacclient.storage.PreferenceDataSource; import de.geeksfactory.opacclient.storage.SearchFieldDataSource; @@ -136,6 +139,25 @@ public boolean onPreferenceClick(Preference arg0) { Preference historyMaintain = findPreference("history_maintain"); if (historyMaintain != null) { + + // OnClickListener für Sicherheitsfrage vor dem Löschen + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which){ + case DialogInterface.BUTTON_POSITIVE: + // Yes button clicked + HistoryDataSource data = new HistoryDataSource(getActivity()); + data.removeAll(); + break; + + case DialogInterface.BUTTON_NEGATIVE: + // No button clicked + break; + } + } + }; + historyMaintain.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { @@ -145,10 +167,21 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { return true; } - // false, no History. Maybe delete historyDb? - // TODO historyDb löschen? Ask first (AlertDialog.Builder? - // HistoryDataSource hdata = new HistoryDataSource(context); - // hdata.deleteAll(); + HistoryDataSource data = new HistoryDataSource(getActivity()); + if (data.getCountItems() == 0) { + // HistoryDb leer, muss nicht gelöschte werden + return true; + } + + // Sicherheitsnachfrage + AlertDialog.Builder builder = new AlertDialog.Builder( + getActivity()); + builder.setMessage(R.string.history_remove_all_prefs) + .setPositiveButton(R.string.yes, dialogClickListener) + .setNegativeButton(R.string.no, dialogClickListener) + .show(); + + // Behandlung im OnClickListener oben return true; } diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index b58e69d09..4f488834e 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -605,6 +605,45 @@ public void remove(HistoryItem item) { HistoryDatabase.HIST_WHERE_HISTORY_ID, selA); } + /** + * Löscht alle Einträge zu einer Bibliothek + * + * @param bib Name der Bibliothek/Library + */ + public void removeAll(String bib) { + String[] selA = {bib}; + context.getContentResolver() + .delete(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + HistoryDatabase.HIST_WHERE_LIB, selA); + } + + /** + * Löscht alle Einträge zu allen Bibliothekcn in der Database + */ + public void removeAll() { + context.getContentResolver() + .delete(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + null, null); + } + + public int getCountItems() { + Cursor cursor = context + .getContentResolver() + .query(((OpacClient) context.getApplication()) + .getHistoryProviderHistoryUri(), + new String[]{"count(*)"}, + null, null, null); + cursor.moveToFirst(); + int count = 0; + if (!cursor.isAfterLast()) { + count = cursor.getInt(0); + } + cursor.close(); + return count; + } + public void renameLibraries(Map map) { for (Entry entry : map.entrySet()) { ContentValues cv = new ContentValues(); diff --git a/opacclient/opacapp/src/main/res/menu/activity_history.xml b/opacclient/opacapp/src/main/res/menu/activity_history.xml index 3c99ea533..e144c4236 100644 --- a/opacclient/opacapp/src/main/res/menu/activity_history.xml +++ b/opacclient/opacapp/src/main/res/menu/activity_history.xml @@ -50,5 +50,10 @@ app:showAsAction="never" android:title="@string/import_starred_from_storage"> + + \ No newline at end of file diff --git a/opacclient/opacapp/src/main/res/values-de/strings.xml b/opacclient/opacapp/src/main/res/values-de/strings.xml index c0719a45e..38f8acd0e 100644 --- a/opacclient/opacapp/src/main/res/values-de/strings.xml +++ b/opacclient/opacapp/src/main/res/values-de/strings.xml @@ -366,4 +366,7 @@ Führe Chronik aller ausgeliehenen Medien Speicher keine Liste aller jemals ausgeliehenen Medien Speichere eine Liste aller jemals ausgeliehenen Medien + Alle löschen + Bist du sicher? (Kein rückgängig möglich) + Sollen die Verleich-Chroniken zu allen Bibliotheken gelöscht werden? (Kein rückgängig möglich) diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index ff82aaf22..e51a00a64 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -105,7 +105,7 @@ Please wait for the details to load. We could not obtain enough information about this item to add it to your list. This is your favorites list. You can add items by clicking the star on a detail page. The list is saved separately for every library you use. - This is your history list. You can The list is saved separately for every library you use. + This is your history list. The list is saved separately for every library you use. Share Please wait for the details to load. Not supported in this library. @@ -332,6 +332,9 @@ Maintain history lent items Store title, author, begin-date, end-date ... of all lent items Do not store a history off all lent items + Delete All + Are you sure? (No undo possible) + Do you want to delete the history of all libraries? (No undo possible) Print Please wait for details to load Library data From 6930ec7ea7947d0b42838be428f21a9d9d2c036b Mon Sep 17 00:00:00 2001 From: Justy Date: Sat, 11 Jan 2020 00:09:37 +0100 Subject: [PATCH 13/32] =?UTF-8?q?history-Texte=20=C3=BCberarbeitet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/res/values-de/strings.xml | 23 +++++++++---------- .../opacapp/src/main/res/values/strings.xml | 18 +++++++-------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/opacclient/opacapp/src/main/res/values-de/strings.xml b/opacclient/opacapp/src/main/res/values-de/strings.xml index 38f8acd0e..18cb72e98 100644 --- a/opacclient/opacapp/src/main/res/values-de/strings.xml +++ b/opacclient/opacapp/src/main/res/values-de/strings.xml @@ -1,4 +1,3 @@ - Web Opac Web Opac @@ -345,28 +344,28 @@ Aus der Chronik gelöscht Rückgängig Sortieren - nach Author - nach Dauer - nach Beginn - nach Ende - Verlängerungen - Titel + nach Autor + nach Leihdauer + nach Beginn Ausleihe + nach Ende Ausleihe + nach Anzahl Verlängerungen + nach Titel Import der Chronik abgeschlossen Chronik Teilen Exportieren - Dies ist deine Leih-Chronik. Die Liste wird für jede Bibliothek, die du benutzt, separat geführt. + Hier werden alle Medien gespeichert, die du in der Vergangenheit entliehen hast. Die Liste wird für jede Bibliothek, die du benutzt, separat geführt. vom %1$s für %2$d Tage seit %1$s für %2$d Tage vom %1$s für 1 Tag seit %1$s für 1 Tag - Beginndatum - Endedatum + Beginn Ausleihe + Ende Ausleihe Import abgeschlossen, %1$d Einträge hinzugefügt, %2$d geändert Führe Chronik aller ausgeliehenen Medien - Speicher keine Liste aller jemals ausgeliehenen Medien + Speichere keine Liste aller jemals ausgeliehenen Medien Speichere eine Liste aller jemals ausgeliehenen Medien Alle löschen Bist du sicher? (Kein rückgängig möglich) - Sollen die Verleich-Chroniken zu allen Bibliotheken gelöscht werden? (Kein rückgängig möglich) + Sollen die Verleih-Chroniken zu allen Bibliotheken gelöscht werden? (Kein rückgängig möglich) diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index e51a00a64..f67b176fd 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -105,7 +105,7 @@ Please wait for the details to load. We could not obtain enough information about this item to add it to your list. This is your favorites list. You can add items by clicking the star on a detail page. The list is saved separately for every library you use. - This is your history list. The list is saved separately for every library you use. + This is lending history. It keeps a list of all items you have lent in the past. The list is saved separately for every library you use. Share Please wait for the details to load. Not supported in this library. @@ -187,12 +187,12 @@ Export Import Sort - by Title - by Author - by date start - by date end - by duration - by prolongation + by title + by author + by start lending + by return date + by lending duration + by no. of renewals Share as text An error occurred during export. Please try again later. @@ -327,8 +327,8 @@ since %1$s for 1 day from %1$s for %2$d days from %1$s for 1 day - Start date - Last date + Start lending + Return date Maintain history lent items Store title, author, begin-date, end-date ... of all lent items Do not store a history off all lent items From d2f60a16df1c7ddde83e1d9a9bc9b9f710d7fa2a Mon Sep 17 00:00:00 2001 From: Justy Date: Sat, 11 Jan 2020 00:12:50 +0100 Subject: [PATCH 14/32] HistoryItem aus libopac/objects nach opacapp/storage verschoben. HistoryFragment: initLoader mit id=1 (!=0 wie bei StarFragment) wg. Datenbankverwechslung bei Wechsel Favorits --> History --- .../geeksfactory/opacclient/OpacClient.java | 4 +-- .../opacclient/frontend/AccountFragment.java | 2 +- .../frontend/AccountItemDetailActivity.java | 2 +- .../opacclient/frontend/HistoryFragment.java | 26 ++++++++++++------- .../opacclient/storage/HistoryDataSource.java | 6 +---- .../opacclient/storage}/HistoryItem.java | 5 +++- .../res/layout/content_accountitem_detail.xml | 2 +- 7 files changed, 26 insertions(+), 21 deletions(-) rename opacclient/{libopac/src/main/java/de/geeksfactory/opacclient/objects => opacapp/src/main/java/de/geeksfactory/opacclient/storage}/HistoryItem.java (97%) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/OpacClient.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/OpacClient.java index faf3b35a3..1da880d9e 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/OpacClient.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/OpacClient.java @@ -99,7 +99,7 @@ public class OpacClient extends Application { private static OpacClient instance; public final boolean SLIDING_MENU = true; private final Uri STAR_PROVIDER_STAR_URI = StarContentProvider.STAR_URI; - private final Uri HISTORY_PROVIDER_STAR_URI = HistoryContentProvider.HIST_URI; + private final Uri HISTORY_PROVIDER_HIST_URI = HistoryContentProvider.HIST_URI; protected Account account; protected OpacApi api; protected Library library; @@ -178,7 +178,7 @@ public Uri getStarProviderStarUri() { } public Uri getHistoryProviderHistoryUri() { - return HISTORY_PROVIDER_STAR_URI; + return HISTORY_PROVIDER_HIST_URI; } public void addFirstAccount(Activity activity) { diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java index 890087da4..7491d8cd6 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java @@ -1490,7 +1490,7 @@ protected AccountData doInBackground(Void... voids) { // historyDataSource = new HistoryDataSource(OpacClient.getEmergencyContext()); } else { historyDataSource = new HistoryDataSource(getActivity()); - historyDataSource.updateLenting(adatasource.getAccount(data.getAccount()), data); + historyDataSource.updateLending(adatasource.getAccount(data.getAccount()), data); } } diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java index 3797f22bb..d23648fe3 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java @@ -25,7 +25,7 @@ import de.geeksfactory.opacclient.apis.OpacApi; import de.geeksfactory.opacclient.databinding.AccountItemDetailActivityBinding; import de.geeksfactory.opacclient.objects.AccountItem; -import de.geeksfactory.opacclient.objects.HistoryItem; +import de.geeksfactory.opacclient.storage.HistoryItem; import de.geeksfactory.opacclient.objects.LentItem; import de.geeksfactory.opacclient.objects.ReservedItem; import de.geeksfactory.opacclient.objects.SearchResult; diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index da2c2ab21..08d216510 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -82,10 +82,9 @@ import de.geeksfactory.opacclient.OpacClient; import de.geeksfactory.opacclient.R; import de.geeksfactory.opacclient.frontend.OpacActivity.AccountSelectedListener; -import de.geeksfactory.opacclient.frontend.adapter.AccountAdapter; import de.geeksfactory.opacclient.objects.Account; import de.geeksfactory.opacclient.objects.AccountItem; -import de.geeksfactory.opacclient.objects.HistoryItem; +import de.geeksfactory.opacclient.storage.HistoryItem; import de.geeksfactory.opacclient.searchfields.SearchField; import de.geeksfactory.opacclient.searchfields.SearchField.Meaning; import de.geeksfactory.opacclient.searchfields.SearchQuery; @@ -180,7 +179,7 @@ public void onItemClick(AdapterView parent, View view, listView.setTextFilterEnabled(true); getActivity().getSupportLoaderManager() - .initLoader(0, null, this); + .initLoader(1, null, this); listView.setAdapter(adapter); // Restore the previously serialized activated item position. @@ -251,10 +250,7 @@ public boolean onOptionsItemSelected(android.view.MenuItem item) { private void sort(String orderby) { - if (sortOrder == null) { - // bisher nicht sortiert - sortOrder = orderby + " DESC"; - } else if (sortOrder.startsWith(orderby)) { + if ((sortOrder != null ) && sortOrder.startsWith(orderby)) { // bereits nach dieser Spalte sortiert // d.h. ASC/DESC swappen if (sortOrder.equals(orderby + " ASC")) { @@ -263,9 +259,19 @@ private void sort(String orderby) { sortOrder = orderby + " ASC"; } } else { - // bisher nach anderer Spalte sortiert - // zunächst ASC - sortOrder = orderby + " ASC"; + // bisher nicht sortiert oder + // nach anderer Spalte sortiert + switch (orderby) { + case "author": + case "title": + // zunächst ASC + sortOrder = orderby + " ASC"; + break; + + default: + // Datum, Anzahl + sortOrder = orderby + " DESC"; + } } // Loader restarten diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index 4f488834e..be2bd8836 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -23,10 +23,8 @@ import android.app.Activity; import android.content.ContentValues; -import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; -import android.text.BoringLayout; import android.util.Log; import org.joda.time.LocalDate; @@ -34,7 +32,6 @@ import org.json.JSONException; import org.json.JSONObject; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -47,7 +44,6 @@ import de.geeksfactory.opacclient.objects.AccountItem; import de.geeksfactory.opacclient.objects.LentItem; import de.geeksfactory.opacclient.objects.SearchResult; -import de.geeksfactory.opacclient.objects.HistoryItem; public class HistoryDataSource { @@ -62,7 +58,7 @@ public HistoryDataSource(Activity context) { this.context = context; } - public void updateLenting(Account account, AccountData adata) { + public void updateLending(Account account, AccountData adata) { String library = account.getLibrary(); /* Account yes / no diff --git a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryItem.java similarity index 97% rename from opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java rename to opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryItem.java index b81cac647..84fadefa0 100644 --- a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/objects/HistoryItem.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryItem.java @@ -1,9 +1,12 @@ -package de.geeksfactory.opacclient.objects; +package de.geeksfactory.opacclient.storage; import org.joda.time.LocalDate; import java.io.Serializable; +import de.geeksfactory.opacclient.objects.AccountItem; +import de.geeksfactory.opacclient.objects.LentItem; + public class HistoryItem extends AccountItem implements Serializable { private int historyId; // Unique Id in HistoryDatabase diff --git a/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml b/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml index fe7a8fc2b..de6c54858 100644 --- a/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml +++ b/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml @@ -11,7 +11,7 @@ - + From b0d1d9ad2738bf912eaa47a6a2d7ecf5e1e1ad8e Mon Sep 17 00:00:00 2001 From: Justy Date: Sat, 11 Jan 2020 00:30:26 +0100 Subject: [PATCH 15/32] =?UTF-8?q?Reformat=20code=20bzgl.=20History-=C3=84n?= =?UTF-8?q?derungen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/AccountItemDetailActivity.java | 4 +- .../opacclient/frontend/HistoryFragment.java | 132 ++++++++++-------- .../storage/HistoryContentProvider.java | 30 ++-- .../opacclient/storage/HistoryDataSource.java | 127 +++++++++-------- .../opacclient/storage/HistoryDatabase.java | 116 ++++++++------- .../opacclient/storage/HistoryItem.java | 7 +- 6 files changed, 214 insertions(+), 202 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java index d23648fe3..954c6d7e5 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountItemDetailActivity.java @@ -25,10 +25,10 @@ import de.geeksfactory.opacclient.apis.OpacApi; import de.geeksfactory.opacclient.databinding.AccountItemDetailActivityBinding; import de.geeksfactory.opacclient.objects.AccountItem; -import de.geeksfactory.opacclient.storage.HistoryItem; import de.geeksfactory.opacclient.objects.LentItem; import de.geeksfactory.opacclient.objects.ReservedItem; import de.geeksfactory.opacclient.objects.SearchResult; +import de.geeksfactory.opacclient.storage.HistoryItem; public class AccountItemDetailActivity extends AppCompatActivity { public static final String EXTRA_ITEM = "item"; @@ -159,7 +159,7 @@ public boolean onCreateOptionsMenu(Menu menu) { final HistoryItem i = (HistoryItem) item; download.setVisible(false); cancel.setVisible(false); // cancel reservation - if (i.isLending() ) { + if (i.isLending()) { booking.setVisible(false); prolong.setVisible(true); diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index 08d216510..811cb3ccd 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -1,23 +1,20 @@ /** * Copyright (C) 2013 by Raphael Michel under the MIT license: *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software - * is furnished to do so, subject to the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: *

- * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package de.geeksfactory.opacclient.frontend; @@ -84,12 +81,12 @@ import de.geeksfactory.opacclient.frontend.OpacActivity.AccountSelectedListener; import de.geeksfactory.opacclient.objects.Account; import de.geeksfactory.opacclient.objects.AccountItem; -import de.geeksfactory.opacclient.storage.HistoryItem; import de.geeksfactory.opacclient.searchfields.SearchField; import de.geeksfactory.opacclient.searchfields.SearchField.Meaning; import de.geeksfactory.opacclient.searchfields.SearchQuery; import de.geeksfactory.opacclient.storage.HistoryDataSource; import de.geeksfactory.opacclient.storage.HistoryDatabase; +import de.geeksfactory.opacclient.storage.HistoryItem; import de.geeksfactory.opacclient.storage.JsonSearchFieldDataSource; import de.geeksfactory.opacclient.utils.CompatibilityUtils; @@ -134,7 +131,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, public void onItemClick(AdapterView parent, View view, int position, long id) { HistoryItem item = (HistoryItem) view.findViewById(R.id.ivDelete) - .getTag(); + .getTag(); if (item.getId() == null || item.getId().equals("null") || item.getId().equals("")) { @@ -202,7 +199,8 @@ private void showDetailActivity(AccountItem item, View view) { getString(R.string.transition_background)); ActivityCompat - .startActivityForResult(getActivity(), intent, REQUEST_CODE_DETAIL, options.toBundle()); + .startActivityForResult(getActivity(), intent, REQUEST_CODE_DETAIL, + options.toBundle()); } @Override @@ -250,7 +248,7 @@ public boolean onOptionsItemSelected(android.view.MenuItem item) { private void sort(String orderby) { - if ((sortOrder != null ) && sortOrder.startsWith(orderby)) { + if ((sortOrder != null) && sortOrder.startsWith(orderby)) { // bereits nach dieser Spalte sortiert // d.h. ASC/DESC swappen if (sortOrder.equals(orderby + " ASC")) { @@ -291,23 +289,24 @@ public void remove(HistoryItem item) { } public void removeAll() { - DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which){ - case DialogInterface.BUTTON_POSITIVE: - // Yes button clicked - HistoryDataSource data = new HistoryDataSource(getActivity()); - String bib = app.getLibrary().getIdent(); - data.removeAll(bib); - break; - - case DialogInterface.BUTTON_NEGATIVE: - // No button clicked - break; - } - } - }; + DialogInterface.OnClickListener dialogClickListener = + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + // Yes button clicked + HistoryDataSource data = new HistoryDataSource(getActivity()); + String bib = app.getLibrary().getIdent(); + data.removeAll(bib); + break; + + case DialogInterface.BUTTON_NEGATIVE: + // No button clicked + break; + } + } + }; AlertDialog.Builder builder = new AlertDialog.Builder( getActivity()); builder.setMessage(R.string.history_remove_all_sure) @@ -541,14 +540,19 @@ public void onActivityResult(int requestCode, int resultCode, Intent intent) { JSONObject entry = items.getJSONObject(i); HistoryDataSource.ChangeType ct = dataSource.insertOrUpdate(bib, entry); switch (ct) { - case UPDATE: countUpdate++; break; - case INSERT: countInsert++; break; + case UPDATE: + countUpdate++; + break; + case INSERT: + countInsert++; + break; } } - if(countInsert>0 || countUpdate>0) { + if (countInsert > 0 || countUpdate > 0) { adapter.notifyDataSetChanged(); Snackbar.make(getView(), - getString(R.string.info_history_updated_count, countInsert, countUpdate), + getString(R.string.info_history_updated_count, countInsert, + countUpdate), Snackbar.LENGTH_LONG).show(); } else { Snackbar.make(getView(), R.string.info_history_updated, @@ -659,7 +663,7 @@ public void bindView(View view, Context context, Cursor cursor) { if (!TextUtils.isEmpty(item.getAuthor())) builder.append(". "); } if (!TextUtils.isEmpty(item.getAuthor())) { - builder.append(item.getAuthor().split("¬\\[",2)[0]); + builder.append(item.getAuthor().split("¬\\[", 2)[0]); } setTextOrHide(builder, tvTitleAndAuthor); // statt von StarFragment @@ -696,9 +700,11 @@ public void bindView(View view, Context context, Cursor cursor) { int resId = 0; String fmtFirstDate = fmt.print(item.getFirstDate()); if (countDays == 1) { - resId = item.isLending() ? R.string.history_status_lending_1 : R.string.history_status_finished_1; + resId = item.isLending() ? R.string.history_status_lending_1 : + R.string.history_status_finished_1; } else { - resId = item.isLending() ? R.string.history_status_lending : R.string.history_status_finished; + resId = item.isLending() ? R.string.history_status_lending : + R.string.history_status_finished; } status = getString(resId, fmtFirstDate, countDays); setTextOrHide(status, tvStatus); @@ -709,24 +715,26 @@ public void bindView(View view, Context context, Cursor cursor) { setTextOrHide(Html.fromHtml(item.getHomeBranch()), tvBranch); } - tvBranch.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw () { - tvBranch.getViewTreeObserver().removeOnPreDrawListener(this); - // place tvBranch next to or below tvStatus to prevent overlapping - RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)tvBranch.getLayoutParams(); - if (tvStatus.getPaint().measureText(tvStatus.getText().toString()) < - tvStatus.getWidth() / 2 - 4){ - lp.addRule(RelativeLayout.BELOW, 0); //removeRule only since API 17 - lp.addRule(RelativeLayout.ALIGN_PARENT_TOP); - } else { - lp.addRule(RelativeLayout.ALIGN_PARENT_TOP,0); - lp.addRule(RelativeLayout.BELOW, R.id.tvStatus); - } - tvBranch.setLayoutParams(lp); - return true; - } - }); + tvBranch.getViewTreeObserver() + .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + tvBranch.getViewTreeObserver().removeOnPreDrawListener(this); + // place tvBranch next to or below tvStatus to prevent overlapping + RelativeLayout.LayoutParams lp = + (RelativeLayout.LayoutParams) tvBranch.getLayoutParams(); + if (tvStatus.getPaint().measureText(tvStatus.getText().toString()) < + tvStatus.getWidth() / 2 - 4) { + lp.addRule(RelativeLayout.BELOW, 0); //removeRule only since API 17 + lp.addRule(RelativeLayout.ALIGN_PARENT_TOP); + } else { + lp.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0); + lp.addRule(RelativeLayout.BELOW, R.id.tvStatus); + } + tvBranch.setLayoutParams(lp); + return true; + } + }); ImageView ivType = (ImageView) view.findViewById(R.id.ivMediaType); if (item.getMediaType() != null) { @@ -748,7 +756,7 @@ public void onClick(View arg0) { callback.removeFragment(); } }); - } + } } } diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryContentProvider.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryContentProvider.java index 87b0f276a..c0995ff23 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryContentProvider.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryContentProvider.java @@ -1,23 +1,20 @@ /** * Copyright (C) 2013 by Raphael Michel under the MIT license: * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software - * is furnished to do so, subject to the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package de.geeksfactory.opacclient.storage; @@ -99,7 +96,8 @@ public int delete(Uri uri, String selection, String[] selectionArgs) { int rowsAffected; switch (getTypeMime(uri)) { case HIST_DIR: - rowsAffected = deleteInDatabase(HistoryDatabase.HIST_TABLE, selection, selectionArgs); + rowsAffected = + deleteInDatabase(HistoryDatabase.HIST_TABLE, selection, selectionArgs); break; case HIST_ITEM: rowsAffected = deleteInDatabase(HistoryDatabase.HIST_TABLE, diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index be2bd8836..138f3bba3 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -1,23 +1,20 @@ /** * Copyright (C) 2013 by Raphael Michel under the MIT license: * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software - * is furnished to do so, subject to the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package de.geeksfactory.opacclient.storage; @@ -51,9 +48,12 @@ public class HistoryDataSource { private SQLiteDatabase database; private String[] allColumns = HistoryDatabase.COLUMNS; - public enum ChangeType { NOTHING, UPDATE, INSERT}; + public enum ChangeType {NOTHING, UPDATE, INSERT} + + ; private Activity context; + public HistoryDataSource(Activity context) { this.context = context; } @@ -74,7 +74,7 @@ public void updateLending(Account account, AccountData adata) { List historyItems = getAllLendingItems(account.getLibrary()); for (LentItem lentItem : adata.getLent()) { HistoryItem foundItem = null; - for (HistoryItem historyItem: historyItems ) { + for (HistoryItem historyItem : historyItems) { if (historyItem.isSameAsLentItem(lentItem)) { foundItem = historyItem; break; @@ -100,7 +100,7 @@ public void updateLending(Account account, AccountData adata) { } } - for (HistoryItem historyItem: historyItems ) { + for (HistoryItem historyItem : historyItems) { boolean isLending = false; for (LentItem lentItem : adata.getLent()) { if (historyItem.isSameAsLentItem(lentItem)) { @@ -143,14 +143,14 @@ public JSONArray getAllItemsAsJson(String bib) throws return items; } - public ChangeType insertOrUpdate(String bib, JSONObject entry) throws JSONException { + public ChangeType insertOrUpdate(String bib, JSONObject entry) throws JSONException { final String methodName = "insertOrUpdate"; // - same id/medianr or same (title, author and type) // - and Zeitraum=(first bis last) überschneiden sich LocalDate firstDate = LocalDate.parse(entry.getString(HistoryDatabase.HIST_COL_FIRST_DATE)); - LocalDate lastDate = LocalDate.parse(entry.getString(HistoryDatabase.HIST_COL_LAST_DATE)); + LocalDate lastDate = LocalDate.parse(entry.getString(HistoryDatabase.HIST_COL_LAST_DATE)); Log.d(methodName, String.format("bib: %s, json: dates %s - %s", bib, firstDate, lastDate)); @@ -167,13 +167,13 @@ public ChangeType insertOrUpdate(String bib, JSONObject entry) throws JSONExcep String author = entry.getString(HistoryDatabase.HIST_COL_AUTHOR); String mediatype = entry.getString(HistoryDatabase.HIST_COL_MEDIA_TYPE); Log.d(methodName, String.format("json: title %s, author %s, mediatype %s" - ,title, author, mediatype)); - item = findItem(bib, title, author, mediatype , firstDate, lastDate); + , title, author, mediatype)); + item = findItem(bib, title, author, mediatype, firstDate, lastDate); } Log.d(methodName, String.format("HistoryItem: %s", item)); ChangeType changeType = ChangeType.NOTHING; - if (item==null) { + if (item == null) { // noch kein entsprechender Satz in Datenbank Log.d(methodName, "call insertHistoryItem(...)"); insertHistoryItem(bib, entry); @@ -182,12 +182,12 @@ public ChangeType insertOrUpdate(String bib, JSONObject entry) throws JSONExcep // Satz vorhanden, ev. updaten // firstDate, lastDate und count 'mergen' - if (firstDate.compareTo(item.getFirstDate())<0) { + if (firstDate.compareTo(item.getFirstDate()) < 0) { Log.d(methodName, "firstDate changed"); changeType = ChangeType.UPDATE; item.setFirstDate(firstDate); } - if (lastDate.compareTo(item.getLastDate())>0) { + if (lastDate.compareTo(item.getLastDate()) > 0) { Log.d(methodName, "lastDate changed"); changeType = ChangeType.UPDATE; item.setLastDate(lastDate); @@ -213,7 +213,7 @@ public ChangeType insertOrUpdate(String bib, JSONObject entry) throws JSONExcep private static JSONObject cursorToJson(String[] columns, Cursor cursor) throws JSONException { JSONObject jsonItem = new JSONObject(); - int i=0; + int i = 0; for (String col : columns) { switch (col) { case HistoryDatabase.HIST_COL_LENDING: @@ -240,14 +240,14 @@ private static JSONObject cursorToJson(String[] columns, Cursor cursor) throws public static HistoryItem cursorToItem(Cursor cursor) { HistoryItem item = new HistoryItem(); - int i=0; + int i = 0; item.setHistoryId(cursor.getInt(i++)); String ds = cursor.getString(i++); - if ( ds!=null) { + if (ds != null) { item.setFirstDate(LocalDate.parse(ds)); } ds = cursor.getString(i++); - if ( ds!=null) { + if (ds != null) { item.setLastDate(LocalDate.parse(ds)); } item.setLending(cursor.getInt(i++) > 0); @@ -259,7 +259,7 @@ public static HistoryItem cursorToItem(Cursor cursor) { item.setStatus(cursor.getString(i++)); item.setCover(cursor.getString(i++)); String mds = cursor.getString(i++); - if (mds!=null) { + if (mds != null) { try { SearchResult.MediaType mediaType = SearchResult.MediaType.valueOf(mds); item.setMediaType(mediaType); @@ -274,7 +274,7 @@ public static HistoryItem cursorToItem(Cursor cursor) { item.setBarcode(cursor.getString(i++)); ds = cursor.getString(i++); - if ( ds!=null) { + if (ds != null) { item.setDeadline(LocalDate.parse(ds)); } int count = cursor.getInt(i++); @@ -283,64 +283,64 @@ public static HistoryItem cursorToItem(Cursor cursor) { return item; } - private void addAccountItemValues(ContentValues values, AccountItem item ) { - putOrNull(values,HistoryDatabase.HIST_COL_MEDIA_NR, item.getId()); - putOrNull(values,HistoryDatabase.HIST_COL_TITLE, item.getTitle()); - putOrNull(values,HistoryDatabase.HIST_COL_AUTHOR, item.getAuthor()); - putOrNull(values,"format", item.getFormat()); - putOrNull(values,"status", item.getStatus()); - putOrNull(values,"cover", item.getCover()); + private void addAccountItemValues(ContentValues values, AccountItem item) { + putOrNull(values, HistoryDatabase.HIST_COL_MEDIA_NR, item.getId()); + putOrNull(values, HistoryDatabase.HIST_COL_TITLE, item.getTitle()); + putOrNull(values, HistoryDatabase.HIST_COL_AUTHOR, item.getAuthor()); + putOrNull(values, "format", item.getFormat()); + putOrNull(values, "status", item.getStatus()); + putOrNull(values, "cover", item.getCover()); SearchResult.MediaType mediaType = item.getMediaType(); - putOrNull(values,"mediatype", mediaType != null ? mediaType.toString() : null); + putOrNull(values, "mediatype", mediaType != null ? mediaType.toString() : null); } private ContentValues createContentValues(HistoryItem historyItem) { ContentValues values = new ContentValues(); addAccountItemValues(values, historyItem); - putOrNull(values,HistoryDatabase.HIST_COL_FIRST_DATE, historyItem.getFirstDate()); - putOrNull(values,HistoryDatabase.HIST_COL_LAST_DATE, historyItem.getLastDate()); - putOrNull(values,HistoryDatabase.HIST_COL_LENDING, historyItem.isLending()); - putOrNull(values,"bib", historyItem.getBib()); - putOrNull(values,"homeBranch", historyItem.getHomeBranch()); - putOrNull(values,"lendingBranch", historyItem.getLendingBranch()); - putOrNull(values,"ebook", historyItem.isEbook()); - putOrNull(values,"barcode", historyItem.getBarcode()); - putOrNull(values,HistoryDatabase.HIST_COL_DEADLINE, historyItem.getDeadline()); + putOrNull(values, HistoryDatabase.HIST_COL_FIRST_DATE, historyItem.getFirstDate()); + putOrNull(values, HistoryDatabase.HIST_COL_LAST_DATE, historyItem.getLastDate()); + putOrNull(values, HistoryDatabase.HIST_COL_LENDING, historyItem.isLending()); + putOrNull(values, "bib", historyItem.getBib()); + putOrNull(values, "homeBranch", historyItem.getHomeBranch()); + putOrNull(values, "lendingBranch", historyItem.getLendingBranch()); + putOrNull(values, "ebook", historyItem.isEbook()); + putOrNull(values, "barcode", historyItem.getBarcode()); + putOrNull(values, HistoryDatabase.HIST_COL_DEADLINE, historyItem.getDeadline()); values.put("prolongCount", historyItem.getProlongCount()); return values; } - private void updateHistoryItem(HistoryItem historyItem ) { + private void updateHistoryItem(HistoryItem historyItem) { ContentValues values = createContentValues(historyItem); String where = "historyId = ?"; context.getContentResolver() .update(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri() , values, where, new String[]{Integer.toString(historyItem.getHistoryId()) - } ); + }); } - public void insertHistoryItem(HistoryItem historyItem ) { + public void insertHistoryItem(HistoryItem historyItem) { ContentValues values = createContentValues(historyItem); context.getContentResolver() .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), - values); + values); } - public void insertHistoryItem(String bib, JSONObject item ) throws JSONException { + public void insertHistoryItem(String bib, JSONObject item) throws JSONException { ContentValues values = new ContentValues(); values.put("bib", bib); Iterator keys = item.keys(); - while(keys.hasNext()) { + while (keys.hasNext()) { String key = keys.next(); switch (key) { case HistoryDatabase.HIST_COL_LENDING: case "ebook": // boolean boolean b = (1 == item.getInt(key)); - putOrNull(values, key, b ); + putOrNull(values, key, b); break; case "prolongCount": // Integer @@ -365,15 +365,15 @@ public void insertHistoryItem(String bib, JSONObject item ) throws JSONException // date wird als String inserted default: // String - putOrNull(values,key, item.getString(key) ); + putOrNull(values, key, item.getString(key)); } } context.getContentResolver() .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), - values); + values); } - private void insertLentItem(String bib, LentItem lentItem ) { + private void insertLentItem(String bib, LentItem lentItem) { ContentValues values = new ContentValues(); addAccountItemValues(values, lentItem); @@ -390,7 +390,7 @@ private void insertLentItem(String bib, LentItem lentItem ) { context.getContentResolver() .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), - values); + values); } private void putOrNull(ContentValues cv, String key, String value) { @@ -400,6 +400,7 @@ private void putOrNull(ContentValues cv, String key, String value) { cv.putNull(key); } } + private void putOrNull(ContentValues cv, String key, LocalDate value) { if (value != null) { cv.put(key, value.toString()); @@ -407,6 +408,7 @@ private void putOrNull(ContentValues cv, String key, LocalDate value) { cv.putNull(key); } } + private void putOrNull(ContentValues cv, String key, boolean value) { cv.put(key, value ? Boolean.TRUE : Boolean.FALSE); } @@ -523,7 +525,8 @@ public HistoryItem getItem(long historyId) { return item; } - private HistoryItem findItem(String bib, String mediaNr, LocalDate firstDate, LocalDate lastDate) { + private HistoryItem findItem(String bib, String mediaNr, LocalDate firstDate, + LocalDate lastDate) { if (mediaNr == null) { return null; } @@ -561,9 +564,9 @@ private HistoryItem findItemToDates(Cursor cursor, LocalDate firstDate, LocalDat while (!cursor.isAfterLast()) { HistoryItem item = cursorToItem(cursor); - if (firstDate.compareTo(item.getLastDate())>0) { + if (firstDate.compareTo(item.getLastDate()) > 0) { // firstDate > item.lastDate: Zeitraum überschneidet sich nicht - } else if (item.getFirstDate().compareTo(lastDate)>0) { + } else if (item.getFirstDate().compareTo(lastDate) > 0) { // item.firstDate > lastDate: Zeitraum überschneidet sich nicht item = null; } else { diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java index ae3d669d3..1f35bac95 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java @@ -1,23 +1,20 @@ /** * Copyright (C) 2013 by Raphael Michel under the MIT license: * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software - * is furnished to do so, subject to the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT + * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package de.geeksfactory.opacclient.storage; @@ -41,7 +38,7 @@ public class HistoryDatabase extends SQLiteOpenHelper { public static final String HIST_COL_DEADLINE = "deadline"; public static final String HIST_COL_LENDING = "lending"; - public static final String HIST_WHERE_HISTORY_ID = HIST_COL_HISTORY_ID +" = ?"; + public static final String HIST_WHERE_HISTORY_ID = HIST_COL_HISTORY_ID + " = ?"; public static final String HIST_WHERE_LIB = "bib = ?"; public static final String HIST_WHERE_LIB_LENDING = "bib = ? AND lending = 1"; @@ -53,31 +50,32 @@ public class HistoryDatabase extends SQLiteOpenHelper { public static final String HIST_WHERE_LIB_TITLE_AUTHOR_TYPE = "bib = ? AND " + HIST_COL_TITLE + " = ? AND " + HIST_COL_AUTHOR + " = ? AND " - + HIST_COL_MEDIA_TYPE + " = ?" - ; - public static final String[] COLUMNS = {HIST_COL_HISTORY_ID +" AS _id", // wg. android.widget.CursorAdapter - // siehe https://developer.android.com/reference/android/widget/CursorAdapter.html - HIST_COL_FIRST_DATE, - HIST_COL_LAST_DATE, - HIST_COL_LENDING, - HIST_COL_MEDIA_NR, - "bib", - HIST_COL_TITLE, - HIST_COL_AUTHOR, - "format", - "status", - "cover", - HIST_COL_MEDIA_TYPE, - "homeBranch", - "lendingBranch", - "ebook", - "barcode", - HIST_COL_DEADLINE, - HIST_COL_PROLONG_COUNT - }; + + HIST_COL_MEDIA_TYPE + " = ?"; + public static final String[] COLUMNS = + {HIST_COL_HISTORY_ID + " AS _id", // wg. android.widget.CursorAdapter + // siehe https://developer.android.com/reference/android/widget/CursorAdapter + // .html + HIST_COL_FIRST_DATE, + HIST_COL_LAST_DATE, + HIST_COL_LENDING, + HIST_COL_MEDIA_NR, + "bib", + HIST_COL_TITLE, + HIST_COL_AUTHOR, + "format", + "status", + "cover", + HIST_COL_MEDIA_TYPE, + "homeBranch", + "lendingBranch", + "ebook", + "barcode", + HIST_COL_DEADLINE, + HIST_COL_PROLONG_COUNT + }; private static final String DATABASE_CREATE = "create table historyTable (\n" + - "\t" + HIST_COL_HISTORY_ID +" integer primary key autoincrement,\n" + + "\t" + HIST_COL_HISTORY_ID + " integer primary key autoincrement,\n" + "\t" + HIST_COL_FIRST_DATE + " date,\n" + "\t" + HIST_COL_LAST_DATE + " date,\n" + "\tlending boolean,\n" + @@ -118,26 +116,26 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + ", which will destroy all old data"); final String createTemp = - "create table tempTable (\n" + - "\t" + HIST_COL_HISTORY_ID +" integer primary key autoincrement,\n" + - "\t" + HIST_COL_FIRST_DATE + " date,\n" + - "\t" + HIST_COL_LAST_DATE + " date,\n" + - "\t" + HIST_COL_LENDING + " boolean,\n" + - "\t" + HIST_COL_MEDIA_NR + " text,\n" + - "\tbib text,\n" + - "\t" + HIST_COL_TITLE + " text,\n" + - "\t" + HIST_COL_AUTHOR + " text,\n" + - "\tformat text,\n" + - "\tstatus text,\n" + - "\tcover text,\n" + - "\t" + HIST_COL_MEDIA_TYPE + " text,\n" + - "\thomeBranch text,\n" + - "\tlendingBranch text,\n" + - "\tebook boolean,\n" + - "\tbarcode text,\n" + - "\t" + HIST_COL_DEADLINE + " date,\n" + - "\t" + HIST_COL_PROLONG_COUNT + " integer\n" + - ");"; + "create table tempTable (\n" + + "\t" + HIST_COL_HISTORY_ID + " integer primary key autoincrement,\n" + + "\t" + HIST_COL_FIRST_DATE + " date,\n" + + "\t" + HIST_COL_LAST_DATE + " date,\n" + + "\t" + HIST_COL_LENDING + " boolean,\n" + + "\t" + HIST_COL_MEDIA_NR + " text,\n" + + "\tbib text,\n" + + "\t" + HIST_COL_TITLE + " text,\n" + + "\t" + HIST_COL_AUTHOR + " text,\n" + + "\tformat text,\n" + + "\tstatus text,\n" + + "\tcover text,\n" + + "\t" + HIST_COL_MEDIA_TYPE + " text,\n" + + "\thomeBranch text,\n" + + "\tlendingBranch text,\n" + + "\tebook boolean,\n" + + "\tbarcode text,\n" + + "\t" + HIST_COL_DEADLINE + " date,\n" + + "\t" + HIST_COL_PROLONG_COUNT + " integer\n" + + ");"; db.execSQL(createTemp); db.execSQL("insert into tempTable select * from " + HIST_TABLE + ";"); diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryItem.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryItem.java index 84fadefa0..67630149e 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryItem.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryItem.java @@ -32,7 +32,10 @@ public int getProlongCount() { return prolongCount; } - public LocalDate getDeadline() { return deadline; } + public LocalDate getDeadline() { + return deadline; + } + public void setDeadline(LocalDate deadline) { this.deadline = deadline; } @@ -153,6 +156,7 @@ public void set(String key, String value) { public String getBib() { return bib; } + public void setBib(String bib) { this.bib = bib; } @@ -160,6 +164,7 @@ public void setBib(String bib) { public int getHistoryId() { return historyId; } + public void setHistoryId(int historyId) { this.historyId = historyId; } From ed9952c9932eae7c052fec0a58e927833b9ee90e Mon Sep 17 00:00:00 2001 From: Justy Date: Sun, 12 Jan 2020 11:53:20 +0100 Subject: [PATCH 16/32] LoaderId 1 als Konstante definiert und an weiteren Stellen verwendet --- .../opacclient/frontend/HistoryFragment.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index 811cb3ccd..ebae61b20 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -100,6 +100,7 @@ public class HistoryFragment extends Fragment implements private static final int REQUEST_CODE_IMPORT = 124; private static int REQUEST_CODE_DETAIL = 1; // siehe AccountFragment.REQUEST_DETAIL + private static int LOADER_ID = 1; // !=0 wie bei Star protected View view; protected OpacClient app; @@ -176,7 +177,7 @@ public void onItemClick(AdapterView parent, View view, listView.setTextFilterEnabled(true); getActivity().getSupportLoaderManager() - .initLoader(1, null, this); + .initLoader(LOADER_ID, null, this); listView.setAdapter(adapter); // Restore the previously serialized activated item position. @@ -273,12 +274,12 @@ private void sort(String orderby) { } // Loader restarten - getActivity().getSupportLoaderManager().restartLoader(0, null, this); + getActivity().getSupportLoaderManager().restartLoader(LOADER_ID, null, this); } @Override public void accountSelected(Account account) { - getActivity().getSupportLoaderManager().restartLoader(0, null, this); + getActivity().getSupportLoaderManager().restartLoader(LOADER_ID, null, this); } public void remove(HistoryItem item) { @@ -601,7 +602,7 @@ public void onAttach(Activity activity) { @Override public void onResume() { - getActivity().getSupportLoaderManager().restartLoader(0, null, this); + getActivity().getSupportLoaderManager().restartLoader(LOADER_ID, null, this); super.onResume(); } From a8aef4d81c4c5e0345b6240ce8409ee6b42a194c Mon Sep 17 00:00:00 2001 From: Justy Date: Sun, 12 Jan 2020 11:54:05 +0100 Subject: [PATCH 17/32] menuitem nav_history disablen wenn history_maintain = false --- .../de/geeksfactory/opacclient/frontend/OpacActivity.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java index a7a980c8a..2cdfbaac6 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java @@ -74,6 +74,7 @@ import de.geeksfactory.opacclient.objects.Account; import de.geeksfactory.opacclient.reminder.ReminderHelper; import de.geeksfactory.opacclient.storage.AccountDataSource; +import de.geeksfactory.opacclient.storage.PreferenceDataSource; import de.geeksfactory.opacclient.ui.AccountSwitcherNavigationView; import de.geeksfactory.opacclient.utils.Utils; @@ -329,6 +330,13 @@ public void run() { }, 500); } + + // entweder über PreferenceDataSource, type-safe + PreferenceDataSource prefs = new PreferenceDataSource(this); + boolean historyMaintain = prefs.isHistoryMaintain(); + // oder über SharedPreferences mit "string" + // boolean historyMaintain = sp.getBoolean("history_maintain", true); + drawer.getMenu().findItem(R.id.nav_history).setEnabled(historyMaintain); } } From c0f97c8b7519ff3b2f8406fb9973b5e98c73dfdd Mon Sep 17 00:00:00 2001 From: Justy Date: Sun, 12 Jan 2020 20:05:41 +0100 Subject: [PATCH 18/32] history_header mit Anzahl und Infos zur Sortierung umgesetzt --- .../opacclient/frontend/HistoryFragment.java | 138 +++++++++++++----- .../src/main/res/layout/fragment_history.xml | 11 ++ .../src/main/res/values-de/strings.xml | 4 + .../opacapp/src/main/res/values/strings.xml | 5 +- 4 files changed, 118 insertions(+), 40 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index ebae61b20..404baf47f 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -109,9 +109,73 @@ public class HistoryFragment extends Fragment implements private ListView listView; private int activatedPosition = ListView.INVALID_POSITION; private TextView tvWelcome; + private TextView tvHistoryHeader; private HistoryItem historyItem; - private String sortOrder = null; + private enum EnumSortDirection { + + DESC("DESC", R.string.sort_direction_desc) + ,ASC("ASC", R.string.sort_direction_asc) + ; + + String sqlText; + int textId; + + private EnumSortDirection(String sqlText, int textId) { + this.sqlText = sqlText; + this.textId = textId; + } + + public EnumSortDirection swap() { + if (this==ASC) { + return DESC; + } else { + return ASC; + } + } + } + EnumSortDirection currentSortDirection = null; + + private enum EnumSortOption { + + AUTOR(R.id.action_sort_author, R.string.sort_history_author, HistoryDatabase.HIST_COL_AUTHOR, EnumSortDirection.ASC) + ,TITLE(R.id.action_sort_title, R.string.sort_history_title, HistoryDatabase.HIST_COL_TITLE, EnumSortDirection.ASC) + ,FIRST_DATE(R.id.action_sort_firstDate, R.string.sort_history_firstDate, HistoryDatabase.HIST_COL_FIRST_DATE) + ,LAST_DATE(R.id.action_sort_lastDate, R.string.sort_history_lastDate, HistoryDatabase.HIST_COL_LAST_DATE) + ,PROLONG_COUNT(R.id.action_sort_prolongCount, R.string.sort_history_prolongCount, HistoryDatabase.HIST_COL_PROLONG_COUNT) + ,DURATION(R.id.action_sort_duration, R.string.sort_history_duration, "julianday(lastDate) - julianday(firstDate)") + ; + + int menuId; + int textId; + String column; + EnumSortDirection initialSortDirection; + + private EnumSortOption(int menuId, int textId, String column) { + this.menuId = menuId; + this.textId = textId; + this.column = column; + + // SortDirection Default ist DESC + this.initialSortDirection = EnumSortDirection.DESC; + } + + private EnumSortOption(int menuId, int textId, String column, EnumSortDirection sortDirection) { + this(menuId, textId, column); + this.initialSortDirection = sortDirection; + } + + public static EnumSortOption fromMenuId(int menuId) { + for (EnumSortOption value: EnumSortOption.values()) + { + if(value.menuId == menuId) { + return value; + } + } + return null; + } + } + private EnumSortOption currentSortOption = null; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -126,6 +190,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, listView = (ListView) view.findViewById(R.id.lvHistory); tvWelcome = (TextView) view.findViewById(R.id.tvHistoryWelcome); + tvHistoryHeader = (TextView) view.findViewById(R.id.tvHistoryHeader); listView.setOnItemClickListener(new OnItemClickListener() { @Override @@ -192,6 +257,20 @@ public void onItemClick(AdapterView parent, View view, return view; } + private void updateHeader() { + String text = null; + int countItems = adapter.getCount(); + if (currentSortOption == null) { + text = getString(R.string.history_header, countItems); + } else { + String sortColumnText = getString(currentSortOption.textId); + String sortDirectionText = getString(currentSortDirection.textId); + text = getString(R.string.history_header_sort, countItems, + sortColumnText, sortDirectionText); + } + tvHistoryHeader.setText(text); + } + private void showDetailActivity(AccountItem item, View view) { Intent intent = new Intent(getContext(), AccountItemDetailActivity.class); intent.putExtra(AccountItemDetailActivity.EXTRA_ITEM, item); @@ -222,59 +301,35 @@ public boolean onOptionsItemSelected(android.view.MenuItem item) { } else if (item.getItemId() == R.id.action_import_from_storage) { importFromStorage(); return true; - } else if (item.getItemId() == R.id.action_sort_author) { - sort("author"); - return true; - } else if (item.getItemId() == R.id.action_sort_title) { - sort("title"); - return true; - } else if (item.getItemId() == R.id.action_sort_firstDate) { - sort("firstDate"); - return true; - } else if (item.getItemId() == R.id.action_sort_lastDate) { - sort("lastDate"); - return true; - } else if (item.getItemId() == R.id.action_sort_prolongCount) { - sort("prolongCount"); - return true; - } else if (item.getItemId() == R.id.action_sort_duration) { - sort("julianday(lastDate) - julianday(firstDate)"); - return true; } else if (item.getItemId() == R.id.action_remove_all) { removeAll(); return true; + } else { + EnumSortOption sortOption = EnumSortOption.fromMenuId(item.getItemId()); + if (sortOption != null) { + sort(sortOption); + return true; + } } return super.onOptionsItemSelected(item); } - private void sort(String orderby) { + private void sort(EnumSortOption sortOption) { - if ((sortOrder != null) && sortOrder.startsWith(orderby)) { + if (currentSortOption == sortOption) { // bereits nach dieser Spalte sortiert // d.h. ASC/DESC swappen - if (sortOrder.equals(orderby + " ASC")) { - sortOrder = orderby + " DESC"; - } else { - sortOrder = orderby + " ASC"; - } + currentSortDirection = currentSortDirection.swap(); } else { - // bisher nicht sortiert oder - // nach anderer Spalte sortiert - switch (orderby) { - case "author": - case "title": - // zunächst ASC - sortOrder = orderby + " ASC"; - break; - - default: - // Datum, Anzahl - sortOrder = orderby + " DESC"; - } + currentSortOption = sortOption; + currentSortDirection = sortOption.initialSortDirection; } // Loader restarten getActivity().getSupportLoaderManager().restartLoader(LOADER_ID, null, this); + + // Header aktualisieren + // updateHeader(); unnötig, wird via onLoadFinished aufgerufen } @Override @@ -335,6 +390,10 @@ public void onClick(View view) { @Override public Loader onCreateLoader(int arg0, Bundle arg1) { if (app.getLibrary() != null) { + String sortOrder = null; + if (currentSortOption != null) { + sortOrder = currentSortOption.column + " " + currentSortDirection.sqlText; + } return new CursorLoader(getActivity(), app.getHistoryProviderHistoryUri(), HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB, new String[]{app @@ -351,6 +410,7 @@ public void onLoadFinished(Loader loader, Cursor cursor) { tvWelcome.setVisibility(View.VISIBLE); } else { tvWelcome.setVisibility(View.GONE); + updateHeader(); } } diff --git a/opacclient/opacapp/src/main/res/layout/fragment_history.xml b/opacclient/opacapp/src/main/res/layout/fragment_history.xml index 3544f03ba..836325624 100644 --- a/opacclient/opacapp/src/main/res/layout/fragment_history.xml +++ b/opacclient/opacapp/src/main/res/layout/fragment_history.xml @@ -16,6 +16,17 @@ android:textAppearance="?android:attr/textAppearanceMedium" android:visibility="gone"/> + + Alle löschen Bist du sicher? (Kein rückgängig möglich) Sollen die Verleih-Chroniken zu allen Bibliotheken gelöscht werden? (Kein rückgängig möglich) + %1$d Medien + %1$d Medien, %2$s %3$s sortiert + aufsteigend + absteigend diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index f67b176fd..24ec8bff8 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -119,7 +119,8 @@ Import complete. History import complete. History import complete. %1$d new items, %2$d changed items - + %1$d items + %1$d items, sorted %2$s %3$s The connection to the library server failed. Please check your internet connection. If the problem persists, there may have been a problem on the library server or the app was unable to parse the server\'s response. The connection to the library server failed. Please check your internet connection. If the problem persists, there may have been a problem on the library server. Try again @@ -193,6 +194,8 @@ by return date by lending duration by no. of renewals + descending + ascending Share as text An error occurred during export. Please try again later. From 86106361a8650e3dcaff6ba01233e147e60e00a9 Mon Sep 17 00:00:00 2001 From: Justy Date: Sun, 12 Jan 2020 22:55:23 +0100 Subject: [PATCH 19/32] member-variablen bereinigt: nur context und historyProviderUri merken, statt Activity --- .../opacclient/storage/HistoryDataSource.java | 70 ++++++++----------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index 138f3bba3..e80db28df 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -20,8 +20,9 @@ import android.app.Activity; import android.content.ContentValues; +import android.content.Context; import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; import android.util.Log; import org.joda.time.LocalDate; @@ -44,18 +45,18 @@ public class HistoryDataSource { - // Database fields - private SQLiteDatabase database; - private String[] allColumns = HistoryDatabase.COLUMNS; - public enum ChangeType {NOTHING, UPDATE, INSERT} - ; + final private Context context; + final private Uri historyProviderUri; - private Activity context; + public HistoryDataSource(Activity activity) { + this(activity, (OpacClient) activity.getApplication()); + } - public HistoryDataSource(Activity context) { + public HistoryDataSource(Context context, OpacClient app) { this.context = context; + historyProviderUri = app.getHistoryProviderHistoryUri(); } public void updateLending(Account account, AccountData adata) { @@ -125,8 +126,7 @@ public JSONArray getAllItemsAsJson(String bib) throws String[] selA = {bib}; Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB, selA, null); @@ -316,7 +316,7 @@ private void updateHistoryItem(HistoryItem historyItem) { ContentValues values = createContentValues(historyItem); String where = "historyId = ?"; context.getContentResolver() - .update(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri() + .update(historyProviderUri , values, where, new String[]{Integer.toString(historyItem.getHistoryId()) }); } @@ -324,7 +324,7 @@ private void updateHistoryItem(HistoryItem historyItem) { public void insertHistoryItem(HistoryItem historyItem) { ContentValues values = createContentValues(historyItem); context.getContentResolver() - .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), + .insert(historyProviderUri, values); } @@ -369,7 +369,7 @@ public void insertHistoryItem(String bib, JSONObject item) throws JSONException } } context.getContentResolver() - .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), + .insert(historyProviderUri, values); } @@ -389,7 +389,7 @@ private void insertLentItem(String bib, LentItem lentItem) { putOrNull(values, HistoryDatabase.HIST_COL_DEADLINE, lentItem.getDeadline()); context.getContentResolver() - .insert(((OpacClient) context.getApplication()).getHistoryProviderHistoryUri(), + .insert(historyProviderUri, values); } @@ -418,8 +418,7 @@ public List getAllItems(String bib) { String[] selA = {bib}; Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB, selA, null); @@ -437,8 +436,7 @@ public List getAllItems(String bib) { public void sort(String bib, String sortOrder) { String[] selA = {bib}; context.getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB, selA, sortOrder); } @@ -448,8 +446,7 @@ public List getAllLendingItems(String bib) { String[] selA = {bib}; Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_LENDING, selA, null); @@ -469,8 +466,7 @@ public HistoryItem getItemByTitle(String bib, String title) { String[] selA = {bib, title}; Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_TITLE_LIB, selA, null); HistoryItem item = null; @@ -489,8 +485,7 @@ public HistoryItem getItem(String bib, String mediaNr) { String[] selA = {bib, mediaNr}; Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_MEDIA_NR, selA, null); HistoryItem item = null; @@ -509,8 +504,7 @@ public HistoryItem getItem(long historyId) { String[] selA = {String.valueOf(historyId)}; Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_HISTORY_ID, selA, null); HistoryItem item = null; @@ -534,8 +528,7 @@ private HistoryItem findItem(String bib, String mediaNr, LocalDate firstDate, String[] selA = {bib, mediaNr}; Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_MEDIA_NR, selA, null); HistoryItem item = findItemToDates(cursor, firstDate, lastDate); @@ -550,8 +543,7 @@ private HistoryItem findItem(String bib, String title, String author, String med String[] selA = {bib, title, author, mediatype}; Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB_TITLE_AUTHOR_TYPE, selA, null); HistoryItem item = findItemToDates(cursor, firstDate, lastDate); @@ -587,8 +579,7 @@ public boolean isHistoryTitle(String bib, String title) { String[] selA = {bib, title}; Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_TITLE_LIB, selA, null); int c = cursor.getCount(); @@ -599,8 +590,7 @@ public boolean isHistoryTitle(String bib, String title) { public void remove(HistoryItem item) { String[] selA = {"" + item.getHistoryId()}; context.getContentResolver() - .delete(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .delete(historyProviderUri, HistoryDatabase.HIST_WHERE_HISTORY_ID, selA); } @@ -612,8 +602,7 @@ public void remove(HistoryItem item) { public void removeAll(String bib) { String[] selA = {bib}; context.getContentResolver() - .delete(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .delete(historyProviderUri, HistoryDatabase.HIST_WHERE_LIB, selA); } @@ -622,16 +611,14 @@ public void removeAll(String bib) { */ public void removeAll() { context.getContentResolver() - .delete(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .delete(historyProviderUri, null, null); } public int getCountItems() { Cursor cursor = context .getContentResolver() - .query(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .query(historyProviderUri, new String[]{"count(*)"}, null, null, null); cursor.moveToFirst(); @@ -649,8 +636,7 @@ public void renameLibraries(Map map) { cv.put("bib", entry.getValue()); context.getContentResolver() - .update(((OpacClient) context.getApplication()) - .getHistoryProviderHistoryUri(), + .update(historyProviderUri, cv, HistoryDatabase.HIST_WHERE_LIB, new String[]{entry.getKey()}); } From a3edb10a36c48c9efa780a90c06c318e7666e9f4 Mon Sep 17 00:00:00 2001 From: Justy Date: Sun, 12 Jan 2020 22:58:20 +0100 Subject: [PATCH 20/32] item.status = null vor showDetail, da sinnlos bei HistoryItem --- .../opacclient/frontend/HistoryFragment.java | 64 ++++++++++--------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index 404baf47f..c40cf88fd 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -114,12 +114,10 @@ public class HistoryFragment extends Fragment implements private enum EnumSortDirection { - DESC("DESC", R.string.sort_direction_desc) - ,ASC("ASC", R.string.sort_direction_asc) - ; + DESC("DESC", R.string.sort_direction_desc), ASC("ASC", R.string.sort_direction_asc); - String sqlText; - int textId; + final String sqlText; + final int textId; private EnumSortDirection(String sqlText, int textId) { this.sqlText = sqlText; @@ -127,54 +125,59 @@ private EnumSortDirection(String sqlText, int textId) { } public EnumSortDirection swap() { - if (this==ASC) { + if (this == ASC) { return DESC; } else { return ASC; } } } + EnumSortDirection currentSortDirection = null; private enum EnumSortOption { - AUTOR(R.id.action_sort_author, R.string.sort_history_author, HistoryDatabase.HIST_COL_AUTHOR, EnumSortDirection.ASC) - ,TITLE(R.id.action_sort_title, R.string.sort_history_title, HistoryDatabase.HIST_COL_TITLE, EnumSortDirection.ASC) - ,FIRST_DATE(R.id.action_sort_firstDate, R.string.sort_history_firstDate, HistoryDatabase.HIST_COL_FIRST_DATE) - ,LAST_DATE(R.id.action_sort_lastDate, R.string.sort_history_lastDate, HistoryDatabase.HIST_COL_LAST_DATE) - ,PROLONG_COUNT(R.id.action_sort_prolongCount, R.string.sort_history_prolongCount, HistoryDatabase.HIST_COL_PROLONG_COUNT) - ,DURATION(R.id.action_sort_duration, R.string.sort_history_duration, "julianday(lastDate) - julianday(firstDate)") - ; - - int menuId; - int textId; - String column; - EnumSortDirection initialSortDirection; + AUTOR(R.id.action_sort_author, R.string.sort_history_author, + HistoryDatabase.HIST_COL_AUTHOR, EnumSortDirection.ASC), + TITLE(R.id.action_sort_title, R.string.sort_history_title, HistoryDatabase.HIST_COL_TITLE, + EnumSortDirection.ASC), + FIRST_DATE(R.id.action_sort_firstDate, R.string.sort_history_firstDate, + HistoryDatabase.HIST_COL_FIRST_DATE), + LAST_DATE(R.id.action_sort_lastDate, R.string.sort_history_lastDate, + HistoryDatabase.HIST_COL_LAST_DATE), + PROLONG_COUNT(R.id.action_sort_prolongCount, R.string.sort_history_prolongCount, + HistoryDatabase.HIST_COL_PROLONG_COUNT), + DURATION(R.id.action_sort_duration, R.string.sort_history_duration, + "julianday(lastDate) - julianday(firstDate)"); + + final int menuId; + final int textId; + final String column; + final EnumSortDirection initialSortDirection; private EnumSortOption(int menuId, int textId, String column) { - this.menuId = menuId; - this.textId = textId; - this.column = column; - // SortDirection Default ist DESC - this.initialSortDirection = EnumSortDirection.DESC; + this(menuId, textId, column, EnumSortDirection.DESC); } - private EnumSortOption(int menuId, int textId, String column, EnumSortDirection sortDirection) { - this(menuId, textId, column); + private EnumSortOption(int menuId, int textId, String column, + EnumSortDirection sortDirection) { + this.menuId = menuId; + this.textId = textId; + this.column = column; this.initialSortDirection = sortDirection; } public static EnumSortOption fromMenuId(int menuId) { - for (EnumSortOption value: EnumSortOption.values()) - { - if(value.menuId == menuId) { - return value; - } + for (EnumSortOption value : EnumSortOption.values()) { + if (value.menuId == menuId) { + return value; + } } return null; } } + private EnumSortOption currentSortOption = null; @Override @@ -234,6 +237,7 @@ public void onItemClick(AdapterView parent, View view, } } else { // callback.showDetail(item.getMNr()); + item.setStatus(null); showDetailActivity(item, view); } } From 64b48f86d650f916d1da5da792b7928a989cb14f Mon Sep 17 00:00:00 2001 From: Justy Date: Sun, 12 Jan 2020 23:00:27 +0100 Subject: [PATCH 21/32] Update History auch ohne Activity Update History auch aus SyncAccountJob --- .../opacclient/frontend/AccountFragment.java | 18 ++++++++++++------ .../opacclient/reminder/SyncAccountJob.java | 9 ++++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java index 7491d8cd6..aefab509c 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/AccountFragment.java @@ -1482,15 +1482,21 @@ protected AccountData doInBackground(Void... voids) { } else { prefs = new PreferenceDataSource(getActivity()); } + + // Update Lent-History? if (prefs.isHistoryMaintain()) { - // Update Lent-History - HistoryDataSource historyDataSource; - if (getActivity() == null && OpacClient.getEmergencyContext() != null) { - // TODO HistoryDataSource erwartet Activity, Context reicht nicht - // historyDataSource = new HistoryDataSource(OpacClient.getEmergencyContext()); + HistoryDataSource historyDataSource = null; + if (getActivity() == null) { + if (OpacClient.getEmergencyContext() != null) { + historyDataSource = + new HistoryDataSource(OpacClient.getEmergencyContext(), app); + } } else { historyDataSource = new HistoryDataSource(getActivity()); - historyDataSource.updateLending(adatasource.getAccount(data.getAccount()), data); + } + if (historyDataSource != null) { + historyDataSource + .updateLending(adatasource.getAccount(data.getAccount()), data); } } diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/reminder/SyncAccountJob.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/reminder/SyncAccountJob.java index 2355fba27..e94f06a0b 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/reminder/SyncAccountJob.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/reminder/SyncAccountJob.java @@ -44,6 +44,7 @@ import de.geeksfactory.opacclient.objects.AccountData; import de.geeksfactory.opacclient.objects.Library; import de.geeksfactory.opacclient.storage.AccountDataSource; +import de.geeksfactory.opacclient.storage.HistoryDataSource; import de.geeksfactory.opacclient.storage.JsonSearchFieldDataSource; import de.geeksfactory.opacclient.storage.PreferenceDataSource; import de.geeksfactory.opacclient.webservice.LibraryConfigUpdateService; @@ -213,11 +214,17 @@ boolean syncAccounts(OpacClient app, AccountDataSource data, SharedPreferences s try { data.update(account); data.storeCachedAccountData(account, res); + + // Update Lent-History + if (sp.getBoolean("history_maintain", false)) { + HistoryDataSource historyDataSource = new HistoryDataSource(getContext(), app); + historyDataSource.updateLending(account, res); + } + } finally { helper.generateAlarms(); } } return failed; } - } From 7b032a374e3147fb38e480cc97d03c5a63b20a7f Mon Sep 17 00:00:00 2001 From: Justy Date: Sun, 19 Jan 2020 12:34:16 +0100 Subject: [PATCH 22/32] =?UTF-8?q?History=20Liste:=20Cover/MediaType=20ausb?= =?UTF-8?q?lenden,=20falls=20nie=20gef=C3=BCllt=20History=20Liste:=20Save/?= =?UTF-8?q?Restore=20Sortierung=20aus=20InstanceState=20Details:=20bei=20H?= =?UTF-8?q?istory=20status=20nicht=20anzeigen;=20prolongCount=20erg=C3=A4n?= =?UTF-8?q?zt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../opacclient/frontend/HistoryFragment.java | 56 +++++++++++++++++-- .../opacclient/frontend/OpacActivity.java | 4 ++ .../opacclient/storage/HistoryDataSource.java | 37 +++++++++++- .../opacclient/storage/HistoryDatabase.java | 5 +- .../res/layout/content_accountitem_detail.xml | 32 ++++++++++- .../src/main/res/values-de/strings.xml | 3 +- .../opacapp/src/main/res/values/strings.xml | 5 +- 7 files changed, 129 insertions(+), 13 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index c40cf88fd..422aa6dc5 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -94,6 +94,9 @@ public class HistoryFragment extends Fragment implements LoaderCallbacks, AccountSelectedListener { private static final String STATE_ACTIVATED_POSITION = "activated_position"; + private static final String STATE_SORT_DIRECTION = "sort_direction"; + private static final String STATE_SORT_OPTION = "sort_option"; + private static final String JSON_LIBRARY_NAME = "library_name"; private static final String JSON_HISTORY_LIST = "history_list"; private static final int REQUEST_CODE_EXPORT = 123; @@ -112,6 +115,9 @@ public class HistoryFragment extends Fragment implements private TextView tvHistoryHeader; private HistoryItem historyItem; + private boolean showMediatype = true; + private boolean showCover = true; + private enum EnumSortDirection { DESC("DESC", R.string.sort_direction_desc), ASC("ASC", R.string.sort_direction_asc); @@ -249,11 +255,22 @@ public void onItemClick(AdapterView parent, View view, .initLoader(LOADER_ID, null, this); listView.setAdapter(adapter); - // Restore the previously serialized activated item position. - if (savedInstanceState != null - && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) { - setActivatedPosition(savedInstanceState - .getInt(STATE_ACTIVATED_POSITION)); + if (savedInstanceState != null) { + // Restore the previously serialized activated item position. + if (savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) { + setActivatedPosition(savedInstanceState + .getInt(STATE_ACTIVATED_POSITION)); + } + + // Restore the previously serialized sorting of the items + if (savedInstanceState.containsKey(STATE_SORT_DIRECTION)) { + currentSortDirection = EnumSortDirection.valueOf(savedInstanceState + .getString(STATE_SORT_DIRECTION)); + } + if (savedInstanceState.containsKey(STATE_SORT_OPTION)) { + currentSortOption = EnumSortOption.valueOf(savedInstanceState + .getString(STATE_SORT_OPTION)); + } } setActivateOnItemClick(((OpacActivity) getActivity()).isTablet()); @@ -398,6 +415,12 @@ public Loader onCreateLoader(int arg0, Bundle arg1) { if (currentSortOption != null) { sortOrder = currentSortOption.column + " " + currentSortDirection.sqlText; } + + HistoryDataSource data = new HistoryDataSource(getActivity()); + showMediatype = (data.getCountItemsWithMediatype() > 0); + showCover = (data.getCountItemsWithCover() > 0); + // Hinweis: listitem_history_item ivCover.visibility default ist GONE + return new CursorLoader(getActivity(), app.getHistoryProviderHistoryUri(), HistoryDatabase.COLUMNS, HistoryDatabase.HIST_WHERE_LIB, new String[]{app @@ -698,6 +721,13 @@ public void onSaveInstanceState(Bundle outState) { // Serialize and persist the activated item position. outState.putInt(STATE_ACTIVATED_POSITION, activatedPosition); } + + if (currentSortDirection != null) { + outState.putString(STATE_SORT_DIRECTION, currentSortDirection.name()); + } + if (currentSortOption != null) { + outState.putString(STATE_SORT_OPTION, currentSortOption.name()); + } } public interface Callback { @@ -740,6 +770,22 @@ public void bindView(View view, Context context, Cursor cursor) { } */ + // Spalte Cover ausblenden, wenn alle HistoryItems ohne MediaType sind + ImageView ivCover = (ImageView) view.findViewById(R.id.ivCover); + if ( showCover ) { + ivCover.setVisibility(View.VISIBLE); + } else { + ivCover.setVisibility(View.GONE); + } + + // Spalte Mediatype ausblenden, wenn alle HistoryItems ohne MediaType sind + ImageView ivMediaType = (ImageView) view.findViewById(R.id.ivMediaType); + if ( showMediatype ) { + ivMediaType.setVisibility(View.VISIBLE); + } else { + ivMediaType.setVisibility(View.GONE); + } + TextView tvStatus = (TextView) view.findViewById(R.id.tvStatus); TextView tvBranch = (TextView) view.findViewById(R.id.tvBranch); diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java index 2cdfbaac6..4f333a882 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java @@ -336,7 +336,11 @@ public void run() { boolean historyMaintain = prefs.isHistoryMaintain(); // oder über SharedPreferences mit "string" // boolean historyMaintain = sp.getBoolean("history_maintain", true); + + // item disablen drawer.getMenu().findItem(R.id.nav_history).setEnabled(historyMaintain); + // oder ganz verstecken? + // drawer.getMenu().findItem(R.id.nav_history).setVisible(historyMaintain); } } diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index e80db28df..b54242454 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -115,6 +115,7 @@ public void updateLending(Account account, AccountData adata) { // nicht mehr ausgeliehen // -> update lending = false historyItem.setLending(false); + historyItem.setStatus(null); this.updateHistoryItem(historyItem); } } @@ -289,9 +290,9 @@ private void addAccountItemValues(ContentValues values, AccountItem item) { putOrNull(values, HistoryDatabase.HIST_COL_AUTHOR, item.getAuthor()); putOrNull(values, "format", item.getFormat()); putOrNull(values, "status", item.getStatus()); - putOrNull(values, "cover", item.getCover()); + putOrNull(values, HistoryDatabase.HIST_COL_COVER, item.getCover()); SearchResult.MediaType mediaType = item.getMediaType(); - putOrNull(values, "mediatype", mediaType != null ? mediaType.toString() : null); + putOrNull(values, HistoryDatabase.HIST_COL_MEDIA_TYPE, mediaType != null ? mediaType.toString() : null); } private ContentValues createContentValues(HistoryItem historyItem) { @@ -630,6 +631,38 @@ public int getCountItems() { return count; } + public int getCountItemsWithMediatype() { + Cursor cursor = context + .getContentResolver() + .query(historyProviderUri, + new String[]{"count(*)"}, + HistoryDatabase.HIST_COL_MEDIA_TYPE + " is not null" + , null, null); + cursor.moveToFirst(); + int count = 0; + if (!cursor.isAfterLast()) { + count = cursor.getInt(0); + } + cursor.close(); + return count; + } + + public int getCountItemsWithCover() { + Cursor cursor = context + .getContentResolver() + .query(historyProviderUri, + new String[]{"count(*)"}, + HistoryDatabase.HIST_COL_COVER + " is not null" + , null, null); + cursor.moveToFirst(); + int count = 0; + if (!cursor.isAfterLast()) { + count = cursor.getInt(0); + } + cursor.close(); + return count; + } + public void renameLibraries(Map map) { for (Entry entry : map.entrySet()) { ContentValues cv = new ContentValues(); diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java index 1f35bac95..a7ecc5863 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java @@ -31,6 +31,7 @@ public class HistoryDatabase extends SQLiteOpenHelper { public static final String HIST_COL_MEDIA_NR = "medianr"; public static final String HIST_COL_TITLE = "title"; public static final String HIST_COL_AUTHOR = "author"; + public static final String HIST_COL_COVER = "cover"; public static final String HIST_COL_MEDIA_TYPE = "mediatype"; public static final String HIST_COL_FIRST_DATE = "firstDate"; public static final String HIST_COL_LAST_DATE = "lastDate"; @@ -64,7 +65,7 @@ public class HistoryDatabase extends SQLiteOpenHelper { HIST_COL_AUTHOR, "format", "status", - "cover", + HIST_COL_COVER, HIST_COL_MEDIA_TYPE, "homeBranch", "lendingBranch", @@ -85,7 +86,7 @@ public class HistoryDatabase extends SQLiteOpenHelper { "\t" + HIST_COL_AUTHOR + " text,\n" + "\tformat text,\n" + "\tstatus text,\n" + - "\tcover text,\n" + + "\t" + HIST_COL_COVER + " text,\n" + "\t" + HIST_COL_MEDIA_TYPE + " text,\n" + "\thomeBranch text,\n" + "\tlendingBranch text,\n" + diff --git a/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml b/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml index de6c54858..2dcb60c59 100644 --- a/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml +++ b/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml @@ -122,7 +122,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" - android:visibility="@{item.status != null ? View.VISIBLE : View.GONE}"> + android:visibility="@{ (item instanceof HistoryItem || item.status == null) ? View.GONE : View.VISIBLE}"> + + + + + + + + + vom %1$s für 1 Tag seit %1$s für 1 Tag Beginn Ausleihe - Ende Ausleihe + Rückgabedatum Import abgeschlossen, %1$d Einträge hinzugefügt, %2$d geändert Führe Chronik aller ausgeliehenen Medien Speichere keine Liste aller jemals ausgeliehenen Medien @@ -372,4 +372,5 @@ %1$d Medien, %2$s %3$s sortiert aufsteigend absteigend + Anzahl Verlängerungen diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index 24ec8bff8..1cf1f4b14 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -105,7 +105,7 @@ Please wait for the details to load. We could not obtain enough information about this item to add it to your list. This is your favorites list. You can add items by clicking the star on a detail page. The list is saved separately for every library you use. - This is lending history. It keeps a list of all items you have lent in the past. The list is saved separately for every library you use. + This is your lending history. It keeps a list of all items you have lent in the past. The list is saved separately for every library you use. Share Please wait for the details to load. Not supported in this library. @@ -190,7 +190,7 @@ Sort by title by author - by start lending + by start date by return date by lending duration by no. of renewals @@ -332,6 +332,7 @@ from %1$s for 1 day Start lending Return date + no. of renewals Maintain history lent items Store title, author, begin-date, end-date ... of all lent items Do not store a history off all lent items From bb1fab31d2cf7e0cb1a4f97bbe1729e04dc71064 Mon Sep 17 00:00:00 2001 From: Justy Date: Fri, 24 Jan 2020 19:03:45 +0100 Subject: [PATCH 23/32] Status HistoryFragment sichern mit Hilfe SupportFragmentManager NPE bei UpdateHeader ohne Context vermeiden --- .../opacclient/frontend/HistoryFragment.java | 52 +++++++++++++------ .../opacclient/frontend/OpacActivity.java | 11 +++- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index 422aa6dc5..524467ac3 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -256,21 +256,7 @@ public void onItemClick(AdapterView parent, View view, listView.setAdapter(adapter); if (savedInstanceState != null) { - // Restore the previously serialized activated item position. - if (savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) { - setActivatedPosition(savedInstanceState - .getInt(STATE_ACTIVATED_POSITION)); - } - - // Restore the previously serialized sorting of the items - if (savedInstanceState.containsKey(STATE_SORT_DIRECTION)) { - currentSortDirection = EnumSortDirection.valueOf(savedInstanceState - .getString(STATE_SORT_DIRECTION)); - } - if (savedInstanceState.containsKey(STATE_SORT_OPTION)) { - currentSortOption = EnumSortOption.valueOf(savedInstanceState - .getString(STATE_SORT_OPTION)); - } + restoreState(savedInstanceState); } setActivateOnItemClick(((OpacActivity) getActivity()).isTablet()); @@ -278,7 +264,33 @@ public void onItemClick(AdapterView parent, View view, return view; } + // Restores the previously serialized state (position and sorting) + private void restoreState(Bundle savedInstanceState) { + + if (savedInstanceState == null) return; + + // Restores the previously serialized item position + if (savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) { + setActivatedPosition(savedInstanceState + .getInt(STATE_ACTIVATED_POSITION)); + } + + // Restore the previously serialized sorting of the items + if (savedInstanceState.containsKey(STATE_SORT_DIRECTION)) { + currentSortDirection = EnumSortDirection.valueOf(savedInstanceState + .getString(STATE_SORT_DIRECTION)); + } + if (savedInstanceState.containsKey(STATE_SORT_OPTION)) { + currentSortOption = EnumSortOption.valueOf(savedInstanceState + .getString(STATE_SORT_OPTION)); + } + } private void updateHeader() { + // getString needs context + if (getContext() == null) { + return; + } + String text = null; int countItems = adapter.getCount(); if (currentSortOption == null) { @@ -714,6 +726,16 @@ private void setActivatedPosition(int position) { activatedPosition = position; } + // siehe https://stackoverflow.com/questions/15313598/how-to-correctly-save-instance-state-of-fragments-in-back-stack + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + if (savedInstanceState != null) { + //Restore the fragment's state here + restoreState(savedInstanceState); + } + } + @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java index 4f333a882..0ca80edfb 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java @@ -93,6 +93,7 @@ public abstract class OpacActivity extends AppCompatActivity protected CharSequence title; protected Fragment fragment; + protected Fragment historyFragment; protected boolean hasDrawer = false; protected Toolbar toolbar; private boolean twoPane; @@ -157,6 +158,7 @@ public void onCreate(Bundle savedInstanceState) { getSupportFragmentManager().beginTransaction() .replace(R.id.content_frame, fragment).commit(); } + historyFragment = getSupportFragmentManager().getFragment(savedInstanceState, "historyFragment"); } fixStatusBarFlashing(); } @@ -438,7 +440,10 @@ protected boolean selectItemById(int id) { setTwoPane(true); setFabVisible(false); } else if (id == R.id.nav_history) { - fragment = new HistoryFragment(); + if (historyFragment == null) { + historyFragment = new HistoryFragment(); + } + fragment = historyFragment; setTwoPane(true); setFabVisible(false); } else if (id == R.id.nav_info) { @@ -720,6 +725,10 @@ public void onSaveInstanceState(Bundle outState) { getSupportFragmentManager().putFragment(outState, "fragment", fragment); } + if (historyFragment != null) { + getSupportFragmentManager().putFragment(outState, "historyFragment", + fragment); + } if (title != null) { outState.putCharSequence("title", title); } From 41a09e33ea604708dd3eb201cc1f677de3001136 Mon Sep 17 00:00:00 2001 From: Justy Date: Fri, 24 Jan 2020 22:22:28 +0100 Subject: [PATCH 24/32] =?UTF-8?q?Bugs=20bei=20Nutzung=20FragmentManager=20?= =?UTF-8?q?f=C3=BCr=20historyFragment=20gefixt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../geeksfactory/opacclient/frontend/OpacActivity.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java index 0ca80edfb..e1aa5171a 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java @@ -94,6 +94,7 @@ public abstract class OpacActivity extends AppCompatActivity protected Fragment fragment; protected Fragment historyFragment; + private final static String HISTORY_FRAGMENT = "historyFragment"; protected boolean hasDrawer = false; protected Toolbar toolbar; private boolean twoPane; @@ -158,7 +159,10 @@ public void onCreate(Bundle savedInstanceState) { getSupportFragmentManager().beginTransaction() .replace(R.id.content_frame, fragment).commit(); } - historyFragment = getSupportFragmentManager().getFragment(savedInstanceState, "historyFragment"); + if (savedInstanceState.containsKey(HISTORY_FRAGMENT)) { + historyFragment = getSupportFragmentManager() + .getFragment(savedInstanceState, HISTORY_FRAGMENT); + } } fixStatusBarFlashing(); } @@ -726,8 +730,8 @@ public void onSaveInstanceState(Bundle outState) { fragment); } if (historyFragment != null) { - getSupportFragmentManager().putFragment(outState, "historyFragment", - fragment); + getSupportFragmentManager().putFragment(outState, HISTORY_FRAGMENT, + historyFragment); } if (title != null) { outState.putCharSequence("title", title); From 454ef13345eb51e5a90035f4cd54339ef0e35bdc Mon Sep 17 00:00:00 2001 From: Justy Date: Fri, 24 Jan 2020 23:27:14 +0100 Subject: [PATCH 25/32] HistoryFragment state ohne FragmentManager store/restore --- .../opacclient/frontend/HistoryFragment.java | 29 ++++++++++++------- .../opacclient/frontend/OpacActivity.java | 20 ++++++------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index 524467ac3..199c4d572 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -264,8 +264,24 @@ public void onItemClick(AdapterView parent, View view, return view; } + public void storeState(Bundle outState) { + + if (outState == null) return; + + if (activatedPosition != AdapterView.INVALID_POSITION) { + // Serialize and persist the activated item position. + outState.putInt(STATE_ACTIVATED_POSITION, activatedPosition); + } + + if (currentSortDirection != null) { + outState.putString(STATE_SORT_DIRECTION, currentSortDirection.name()); + } + if (currentSortOption != null) { + outState.putString(STATE_SORT_OPTION, currentSortOption.name()); + } + } // Restores the previously serialized state (position and sorting) - private void restoreState(Bundle savedInstanceState) { + public void restoreState(Bundle savedInstanceState) { if (savedInstanceState == null) return; @@ -739,17 +755,8 @@ public void onActivityCreated(Bundle savedInstanceState) { @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - if (activatedPosition != AdapterView.INVALID_POSITION) { - // Serialize and persist the activated item position. - outState.putInt(STATE_ACTIVATED_POSITION, activatedPosition); - } - if (currentSortDirection != null) { - outState.putString(STATE_SORT_DIRECTION, currentSortDirection.name()); - } - if (currentSortOption != null) { - outState.putString(STATE_SORT_OPTION, currentSortOption.name()); - } + storeState(outState); } public interface Callback { diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java index e1aa5171a..0be7c7d41 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/OpacActivity.java @@ -93,8 +93,7 @@ public abstract class OpacActivity extends AppCompatActivity protected CharSequence title; protected Fragment fragment; - protected Fragment historyFragment; - private final static String HISTORY_FRAGMENT = "historyFragment"; + protected HistoryFragment historyFragment; protected boolean hasDrawer = false; protected Toolbar toolbar; private boolean twoPane; @@ -145,6 +144,10 @@ public void onCreate(Bundle savedInstanceState) { setupDrawer(); setupAccountSwitcher(); + if (historyFragment == null) { + historyFragment = new HistoryFragment(); + } + if (savedInstanceState != null) { setTwoPane(savedInstanceState.getBoolean("twoPane")); setFabVisible(savedInstanceState.getBoolean("fabVisible")); @@ -159,10 +162,8 @@ public void onCreate(Bundle savedInstanceState) { getSupportFragmentManager().beginTransaction() .replace(R.id.content_frame, fragment).commit(); } - if (savedInstanceState.containsKey(HISTORY_FRAGMENT)) { - historyFragment = getSupportFragmentManager() - .getFragment(savedInstanceState, HISTORY_FRAGMENT); - } + + historyFragment.restoreState(savedInstanceState); } fixStatusBarFlashing(); } @@ -729,13 +730,12 @@ public void onSaveInstanceState(Bundle outState) { getSupportFragmentManager().putFragment(outState, "fragment", fragment); } - if (historyFragment != null) { - getSupportFragmentManager().putFragment(outState, HISTORY_FRAGMENT, - historyFragment); - } if (title != null) { outState.putCharSequence("title", title); } + if (historyFragment != null) { + historyFragment.storeState(outState); + } } @Override From 1016cc56e27ba2519047797788dde4b8215a68af Mon Sep 17 00:00:00 2001 From: Justy Date: Sat, 25 Jan 2020 22:42:39 +0100 Subject: [PATCH 26/32] Column status aus HistoryTable entfernt, OnUpgrade 1-2 implementiert --- .../opacclient/frontend/HistoryFragment.java | 1 - .../opacclient/storage/HistoryDataSource.java | 19 +++-- .../opacclient/storage/HistoryDatabase.java | 70 +++++++++---------- 3 files changed, 42 insertions(+), 48 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index 199c4d572..35435545a 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -243,7 +243,6 @@ public void onItemClick(AdapterView parent, View view, } } else { // callback.showDetail(item.getMNr()); - item.setStatus(null); showDetailActivity(item, view); } } diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index b54242454..c7b500e5c 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -115,7 +115,6 @@ public void updateLending(Account account, AccountData adata) { // nicht mehr ausgeliehen // -> update lending = false historyItem.setLending(false); - historyItem.setStatus(null); this.updateHistoryItem(historyItem); } } @@ -220,7 +219,7 @@ private static JSONObject cursorToJson(String[] columns, Cursor cursor) throws case HistoryDatabase.HIST_COL_LENDING: case "ebook": // boolean wie int - case "prolongCount": + case HistoryDatabase.HIST_COL_PROLONG_COUNT: // Integer jsonItem.put(col, Integer.toString(cursor.getInt(i++))); break; @@ -257,7 +256,6 @@ public static HistoryItem cursorToItem(Cursor cursor) { item.setTitle(cursor.getString(i++)); item.setAuthor(cursor.getString(i++)); item.setFormat(cursor.getString(i++)); - item.setStatus(cursor.getString(i++)); item.setCover(cursor.getString(i++)); String mds = cursor.getString(i++); if (mds != null) { @@ -288,8 +286,7 @@ private void addAccountItemValues(ContentValues values, AccountItem item) { putOrNull(values, HistoryDatabase.HIST_COL_MEDIA_NR, item.getId()); putOrNull(values, HistoryDatabase.HIST_COL_TITLE, item.getTitle()); putOrNull(values, HistoryDatabase.HIST_COL_AUTHOR, item.getAuthor()); - putOrNull(values, "format", item.getFormat()); - putOrNull(values, "status", item.getStatus()); + putOrNull(values, HistoryDatabase.HIST_COL_FORMAT, item.getFormat()); putOrNull(values, HistoryDatabase.HIST_COL_COVER, item.getCover()); SearchResult.MediaType mediaType = item.getMediaType(); putOrNull(values, HistoryDatabase.HIST_COL_MEDIA_TYPE, mediaType != null ? mediaType.toString() : null); @@ -302,13 +299,13 @@ private ContentValues createContentValues(HistoryItem historyItem) { putOrNull(values, HistoryDatabase.HIST_COL_FIRST_DATE, historyItem.getFirstDate()); putOrNull(values, HistoryDatabase.HIST_COL_LAST_DATE, historyItem.getLastDate()); putOrNull(values, HistoryDatabase.HIST_COL_LENDING, historyItem.isLending()); - putOrNull(values, "bib", historyItem.getBib()); + putOrNull(values, HistoryDatabase.HIST_COL_BIB, historyItem.getBib()); putOrNull(values, "homeBranch", historyItem.getHomeBranch()); putOrNull(values, "lendingBranch", historyItem.getLendingBranch()); putOrNull(values, "ebook", historyItem.isEbook()); putOrNull(values, "barcode", historyItem.getBarcode()); putOrNull(values, HistoryDatabase.HIST_COL_DEADLINE, historyItem.getDeadline()); - values.put("prolongCount", historyItem.getProlongCount()); + values.put(HistoryDatabase.HIST_COL_PROLONG_COUNT, historyItem.getProlongCount()); return values; } @@ -331,7 +328,7 @@ public void insertHistoryItem(HistoryItem historyItem) { public void insertHistoryItem(String bib, JSONObject item) throws JSONException { ContentValues values = new ContentValues(); - values.put("bib", bib); + values.put(HistoryDatabase.HIST_COL_BIB, bib); Iterator keys = item.keys(); while (keys.hasNext()) { @@ -343,7 +340,7 @@ public void insertHistoryItem(String bib, JSONObject item) throws JSONException boolean b = (1 == item.getInt(key)); putOrNull(values, key, b); break; - case "prolongCount": + case HistoryDatabase.HIST_COL_PROLONG_COUNT: // Integer try { int i = item.getInt(key); @@ -382,7 +379,7 @@ private void insertLentItem(String bib, LentItem lentItem) { putOrNull(values, HistoryDatabase.HIST_COL_LAST_DATE, LocalDate.now()); putOrNull(values, HistoryDatabase.HIST_COL_LENDING, true); - putOrNull(values, "bib", bib); + putOrNull(values, HistoryDatabase.HIST_COL_BIB, bib); putOrNull(values, "homeBranch", lentItem.getHomeBranch()); putOrNull(values, "lendingBranch", lentItem.getLendingBranch()); putOrNull(values, "ebook", lentItem.isEbook()); @@ -666,7 +663,7 @@ public int getCountItemsWithCover() { public void renameLibraries(Map map) { for (Entry entry : map.entrySet()) { ContentValues cv = new ContentValues(); - cv.put("bib", entry.getValue()); + cv.put(HistoryDatabase.HIST_COL_BIB, entry.getValue()); context.getContentResolver() .update(historyProviderUri, diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java index a7ecc5863..2b6b1b03c 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDatabase.java @@ -29,8 +29,10 @@ public class HistoryDatabase extends SQLiteOpenHelper { public static final String HIST_COL_HISTORY_ID = "historyId"; public static final String HIST_COL_MEDIA_NR = "medianr"; + public static final String HIST_COL_BIB = "bib"; public static final String HIST_COL_TITLE = "title"; public static final String HIST_COL_AUTHOR = "author"; + public static final String HIST_COL_FORMAT = "format"; public static final String HIST_COL_COVER = "cover"; public static final String HIST_COL_MEDIA_TYPE = "mediatype"; public static final String HIST_COL_FIRST_DATE = "firstDate"; @@ -60,11 +62,10 @@ public class HistoryDatabase extends SQLiteOpenHelper { HIST_COL_LAST_DATE, HIST_COL_LENDING, HIST_COL_MEDIA_NR, - "bib", + HIST_COL_BIB, HIST_COL_TITLE, HIST_COL_AUTHOR, - "format", - "status", + HIST_COL_FORMAT, HIST_COL_COVER, HIST_COL_MEDIA_TYPE, "homeBranch", @@ -79,13 +80,12 @@ public class HistoryDatabase extends SQLiteOpenHelper { "\t" + HIST_COL_HISTORY_ID + " integer primary key autoincrement,\n" + "\t" + HIST_COL_FIRST_DATE + " date,\n" + "\t" + HIST_COL_LAST_DATE + " date,\n" + - "\tlending boolean,\n" + + "\t" + HIST_COL_LENDING + " boolean,\n" + "\t" + HIST_COL_MEDIA_NR + " text,\n" + - "\tbib text,\n" + + "\t" + HIST_COL_BIB + " text,\n" + "\t" + HIST_COL_TITLE + " text,\n" + "\t" + HIST_COL_AUTHOR + " text,\n" + - "\tformat text,\n" + - "\tstatus text,\n" + + "\t" + HIST_COL_FORMAT + " text,\n" + "\t" + HIST_COL_COVER + " text,\n" + "\t" + HIST_COL_MEDIA_TYPE + " text,\n" + "\thomeBranch text,\n" + @@ -98,7 +98,8 @@ public class HistoryDatabase extends SQLiteOpenHelper { private static final String DATABASE_NAME = "history.db"; - private static final int DATABASE_VERSION = 1; // REPLACE ONUPGRADE IF YOU +// private static final int DATABASE_VERSION = 1; // initial + private static final int DATABASE_VERSION = 2; // Column status removed public HistoryDatabase(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); @@ -116,34 +117,31 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + oldVersion + " to " + newVersion + ", which will destroy all old data"); - final String createTemp = - "create table tempTable (\n" + - "\t" + HIST_COL_HISTORY_ID + " integer primary key autoincrement,\n" + - "\t" + HIST_COL_FIRST_DATE + " date,\n" + - "\t" + HIST_COL_LAST_DATE + " date,\n" + - "\t" + HIST_COL_LENDING + " boolean,\n" + - "\t" + HIST_COL_MEDIA_NR + " text,\n" + - "\tbib text,\n" + - "\t" + HIST_COL_TITLE + " text,\n" + - "\t" + HIST_COL_AUTHOR + " text,\n" + - "\tformat text,\n" + - "\tstatus text,\n" + - "\tcover text,\n" + - "\t" + HIST_COL_MEDIA_TYPE + " text,\n" + - "\thomeBranch text,\n" + - "\tlendingBranch text,\n" + - "\tebook boolean,\n" + - "\tbarcode text,\n" + - "\t" + HIST_COL_DEADLINE + " date,\n" + - "\t" + HIST_COL_PROLONG_COUNT + " integer\n" + - ");"; - - db.execSQL(createTemp); - db.execSQL("insert into tempTable select * from " + HIST_TABLE + ";"); - db.execSQL("drop table " + HIST_TABLE + ";"); + // 1. rename historyTable to oldTable + db.execSQL("alter table " + HIST_TABLE + " rename to oldTable ;"); + + // 2. historyTable neu anlegen onCreate(db); - db.execSQL("insert into " + HIST_TABLE + " select * from tempTable;"); - db.execSQL("drop table tempTable;"); - } + // insert/select der relevanten Spalten vorbereiten + StringBuffer sb = new StringBuffer("insert into " + HIST_TABLE + " select "); + sb.append(HIST_COL_HISTORY_ID); + sb.append(", "); + // i = 1, damit "as _id" nicht verwendet wird + for (int i = 1; i < COLUMNS.length; i++) { + sb.append(COLUMNS[i]); + sb.append(", "); + } + // letztes Komma entfernen + sb.setLength(sb.length()-2); + sb.append(" from oldTable ;"); + final String insertHistory = sb.toString(); + Log.i(HistoryDatabase.class.getName(), "insert history: " + insertHistory); + + // 3. Daten von oldTable nach (neuem) historyTable kopieren + db.execSQL(insertHistory); + + // 4. drop oldTable + db.execSQL("drop table oldTable;"); + } } From 2fa6348c8a093e118fd234419bb5a615da9688d2 Mon Sep 17 00:00:00 2001 From: Justy Date: Tue, 28 Jan 2020 19:51:24 +0100 Subject: [PATCH 27/32] Share im HistoryMenu nach hinten verschoben --- .../opacapp/src/main/res/menu/activity_history.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/opacclient/opacapp/src/main/res/menu/activity_history.xml b/opacclient/opacapp/src/main/res/menu/activity_history.xml index e144c4236..7981b5f48 100644 --- a/opacclient/opacapp/src/main/res/menu/activity_history.xml +++ b/opacclient/opacapp/src/main/res/menu/activity_history.xml @@ -34,12 +34,6 @@ - - + + Date: Tue, 28 Jan 2020 19:53:09 +0100 Subject: [PATCH 28/32] Share als Kommaseparierte Liste; Sort-Status in SharedPref sichern --- .../opacclient/frontend/HistoryFragment.java | 96 ++++++++++++++++--- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index 35435545a..e2a3fc28a 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -250,6 +250,17 @@ public void onItemClick(AdapterView parent, View view, listView.setClickable(true); listView.setTextFilterEnabled(true); + SharedPreferences sp = PreferenceManager + .getDefaultSharedPreferences(getContext()); + String sortOptionS = sp.getString(STATE_SORT_OPTION, null); + if (sortOptionS != null) { + currentSortOption = EnumSortOption.valueOf(sortOptionS); + } + String sortDirectionS = sp.getString(STATE_SORT_DIRECTION, null); + if (sortDirectionS != null) { + currentSortDirection = EnumSortDirection.valueOf(sortDirectionS); + } + getActivity().getSupportLoaderManager() .initLoader(LOADER_ID, null, this); listView.setAdapter(adapter); @@ -263,6 +274,27 @@ public void onItemClick(AdapterView parent, View view, return view; } + @Override + public void onPause() { + + if (getContext() != null) { + SharedPreferences sp = PreferenceManager + .getDefaultSharedPreferences(getContext()); + SharedPreferences.Editor editor = sp.edit(); + + if (currentSortOption != null) { + editor.putString(STATE_SORT_OPTION, currentSortOption.name()); + } + if (currentSortDirection != null) { + editor.putString(STATE_SORT_DIRECTION, currentSortDirection.name()); + } + editor.apply(); + } + + super.onPause(); + } + + public void storeState(Bundle outState) { if (outState == null) return; @@ -478,30 +510,64 @@ protected void share() { intent.setType("text/plain"); intent.addFlags(CompatibilityUtils.getNewDocumentIntentFlag()); + HistoryDataSource data = new HistoryDataSource(getActivity()); + boolean withMediatype = (0 items = data.getAllItems(app.getLibrary().getIdent()); for (HistoryItem item : items) { - text.append(item.getTitle()); - text.append("\n"); - String shareUrl; - try { - shareUrl = app.getApi().getShareUrl(item.getId(), - item.getTitle()); - } catch (OpacClient.LibraryRemovedException e) { - return; - } - if (shareUrl != null) { - text.append(shareUrl); - text.append("\n"); + + appendColumn(text, item.getTitle()); + appendColumn(text, item.getAuthor()); + if (withMediatype) { + if (item.getMediaType() == null) { + appendColumn(text, ""); + } else { + appendColumn(text, item.getMediaType().toString()); + } } + appendColumn(text, item.getHomeBranch()); + appendColumn(text, fmt.print(item.getFirstDate())); + appendColumn(text, fmt.print(item.getLastDate())); + appendColumn(text, fmt.print(item.getProlongCount())); + text.append("\n"); } intent.putExtra(Intent.EXTRA_TEXT, text.toString().trim()); - startActivity(Intent.createChooser(intent, - getResources().getString(R.string.share))); + startActivity(Intent.createChooser(intent, getResources().getString(R.string.share))); + } + + private void appendColumn(StringBuilder text, String value) { + if (value != null) { + text.append(value); + } + text.append(";"); } public void exportToStorage() { From 770c8ae2d0c0622d4b355cc33323db68b8361da8 Mon Sep 17 00:00:00 2001 From: Justy Date: Tue, 28 Jan 2020 20:31:28 +0100 Subject: [PATCH 29/32] Bugfix ProlongCount/Deadline --- .../de/geeksfactory/opacclient/storage/HistoryDataSource.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java index c7b500e5c..89f0e79ee 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/storage/HistoryDataSource.java @@ -88,9 +88,12 @@ public void updateLending(Account account, AccountData adata) { foundItem.setLastDate(LocalDate.now()); } if (!lentItem.getDeadline().equals(foundItem.getDeadline())) { + // Deadline hat sich geändert, d.h. verlängert int count = foundItem.getProlongCount(); count++; foundItem.setProlongCount(count); + // neue Deadline übernehmen + foundItem.setDeadline(lentItem.getDeadline()); } this.updateHistoryItem(foundItem); From add9e9bda8f20f4e679a371ee5058a76ae4d5274 Mon Sep 17 00:00:00 2001 From: Justy Date: Thu, 30 Jan 2020 20:03:22 +0100 Subject: [PATCH 30/32] history_last_date nur anzeigen wenn Ausleihe beendet, d.h. !isLending --- .../opacapp/src/main/res/layout/content_accountitem_detail.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml b/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml index 2dcb60c59..74b5a1e84 100644 --- a/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml +++ b/opacclient/opacapp/src/main/res/layout/content_accountitem_detail.xml @@ -212,7 +212,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" - android:visibility="@{item instanceof HistoryItem && ((HistoryItem) item).lastDate != null ? View.VISIBLE : View.GONE}"> + android:visibility="@{(item instanceof HistoryItem) && (((HistoryItem) item).lastDate != null) && (!((HistoryItem) item).lending) ? View.VISIBLE : View.GONE}"> Date: Wed, 13 May 2020 23:13:42 +0200 Subject: [PATCH 31/32] export-history-strings statt starred-strings verwenden in history-menu --- opacclient/opacapp/src/main/res/menu/activity_history.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opacclient/opacapp/src/main/res/menu/activity_history.xml b/opacclient/opacapp/src/main/res/menu/activity_history.xml index 7981b5f48..d2f8795d6 100644 --- a/opacclient/opacapp/src/main/res/menu/activity_history.xml +++ b/opacclient/opacapp/src/main/res/menu/activity_history.xml @@ -37,18 +37,18 @@ + android:title="@string/export_history_to_storage"> + android:title="@string/import_history_from_storage"> + android:title="@string/share_history"> Date: Wed, 13 May 2020 23:14:37 +0200 Subject: [PATCH 32/32] fix: prolong-count als int (nicht date) behandeln --- .../de/geeksfactory/opacclient/frontend/HistoryFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java index e2a3fc28a..cd7852a57 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/frontend/HistoryFragment.java @@ -554,7 +554,7 @@ protected void share() { appendColumn(text, item.getHomeBranch()); appendColumn(text, fmt.print(item.getFirstDate())); appendColumn(text, fmt.print(item.getLastDate())); - appendColumn(text, fmt.print(item.getProlongCount())); + appendColumn(text, Integer.toString(item.getProlongCount())); text.append("\n"); }