Automatically request updates for new fields (genre and description)
This commit is contained in:
parent
0ac51c0c4f
commit
bc4c8543b4
3
README
3
README
@ -44,7 +44,8 @@ Features include;
|
||||
New in v3.1
|
||||
* The audiobook checkbox has been replaced with a format selector (inc. paperback, hardcover, companion etc)
|
||||
* When adding books the current bookshelf will be selected as the default bookshelf
|
||||
* Genre/Subject and Description fields have been added (Requested by Tosh)
|
||||
* Genre/Subject and Description fields have been added (Requested by Tosh) and will automatically populate based on Google Books and Amazon information
|
||||
* The save button will always be visible on the edit book screen
|
||||
|
||||
New in v3.0.1
|
||||
* Export bug fixed
|
||||
|
@ -90,8 +90,8 @@
|
||||
<string name="list_price">List Price</string>
|
||||
<string name="date_started_reading">Date Started Reading</string>
|
||||
<string name="date_finished_reading">Date Finished Reading</string>
|
||||
<string name="update_thumbnails">Update Thumbnails</string>
|
||||
<string name="overwrite_thumbnail">Do you want to overwrite all existing thumbnails. Warning, this may take a long time. </string>
|
||||
<string name="update_thumbnails">Automatically Update Fields and Thumbnails</string>
|
||||
<string name="overwrite_thumbnail">This will update the following fields (only if blank) \n* Genre \n* Description \n* Thumbnails\n\nThumbnails Only: Do you want to overwrite all existing. Warning, this may take a long time. </string>
|
||||
<string name="yes">Yes</string>
|
||||
<string name="no">No</string>
|
||||
<string name="ok">OK</string>
|
||||
@ -214,4 +214,5 @@
|
||||
<string name="guide">Guide / Companion</string>
|
||||
<string name="description">Description</string>
|
||||
<string name="genre">Genre</string>
|
||||
<string name="auto_update">Would you like to automatically update the following fields now \n* Genre \n* Description \n* Thumbnails\n\n If you select Cancel you can always run this again from the Administration page</string>
|
||||
</resources>
|
||||
|
@ -110,9 +110,9 @@ public class AdministrationFunctions extends Activity {
|
||||
if (extras.getString(DOAUTO).equals("export")) {
|
||||
finish_after = true;
|
||||
exportData();
|
||||
//} else if (extras.getString(DOAUTO).equals("import")) {
|
||||
// finish_after = true;
|
||||
// importData();
|
||||
} else if (extras.getString(DOAUTO).equals("update_fields")) {
|
||||
finish_after = true;
|
||||
updateThumbnails(false);
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
//do nothing
|
||||
@ -262,7 +262,7 @@ public class AdministrationFunctions extends Activity {
|
||||
mHandler.sendMessage(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Looper.prepare();
|
||||
@ -281,9 +281,35 @@ public class AdministrationFunctions extends Activity {
|
||||
int num = 0;
|
||||
try {
|
||||
while (books.moveToNext()) {
|
||||
int id = books.getInt(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ROWID));
|
||||
long id = books.getLong(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ROWID));
|
||||
String isbn = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ISBN));
|
||||
String title = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_TITLE));
|
||||
String genre = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_GENRE));
|
||||
String description = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DESCRIPTION));
|
||||
|
||||
String author = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_AUTHOR_FORMATTED));
|
||||
String publisher = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_PUBLISHER));
|
||||
String date_published = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DATE_PUBLISHED));
|
||||
String series = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SERIES));
|
||||
String series_num = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SERIES_NUM));
|
||||
String list_price = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LIST_PRICE));
|
||||
int pages = books.getInt(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_PAGES));
|
||||
String format = books.getString(books.getColumnIndex(CatalogueDBAdapter.KEY_FORMAT));
|
||||
int anthology = books.getInt(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ANTHOLOGY));
|
||||
float rating = books.getFloat(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_RATING));
|
||||
|
||||
//Display the selected bookshelves
|
||||
Cursor bookshelves = mDbHelper.fetchAllBookshelvesByBook(id);
|
||||
String bookshelf = "";
|
||||
while (bookshelves.moveToNext()) {
|
||||
bookshelf += bookshelves.getString(bookshelves.getColumnIndex(CatalogueDBAdapter.KEY_BOOKSHELF)) + BookEditFields.BOOKSHELF_SEPERATOR;
|
||||
}
|
||||
boolean read = (books.getInt(books.getColumnIndex(CatalogueDBAdapter.KEY_READ))==0 ? false:true);
|
||||
String notes = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_NOTES));
|
||||
String location = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LOCATION));
|
||||
String read_start = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_START));
|
||||
String read_end = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_END));
|
||||
boolean signed = (books.getInt(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SIGNED))==0 ? false:true);
|
||||
|
||||
num++;
|
||||
// delete any tmp thumbnails //
|
||||
@ -294,25 +320,42 @@ public class AdministrationFunctions extends Activity {
|
||||
// do nothing - this is the expected behaviour
|
||||
}
|
||||
|
||||
String[] book = null;
|
||||
File thumb = CatalogueDBAdapter.fetchThumbnail(id);
|
||||
if ((overwrite == true || !thumb.exists()) && !isbn.equals("")) {
|
||||
if (isbn.equals("")) {
|
||||
// Must have an ISBN to be able to search
|
||||
sendMessage(num, "Skip - " + title);
|
||||
} else if (overwrite == true || !thumb.exists() || genre.equals("") || description.equals("")) {
|
||||
sendMessage(num, title);
|
||||
BookISBNSearch bis = new BookISBNSearch();
|
||||
bis.searchAmazon(isbn);
|
||||
//String[] book = {0=author, 1=title, 2=isbn, 3=publisher, 4=date_published, 5=rating, 6=bookshelf,
|
||||
// 7=read, 8=series, 9=pages, 10=series_num, 11=list_price, 12=anthology, 13=location, 14=read_start,
|
||||
// 15=read_end, 16=audiobook, 17=signed, 18=description, 19=genre};
|
||||
book = bis.searchAmazon(isbn);
|
||||
File tmpthumb = CatalogueDBAdapter.fetchThumbnail(0);
|
||||
/* If amazon fails, try google books */
|
||||
if (!tmpthumb.exists()) {
|
||||
bis.searchGoogle(isbn);
|
||||
book = bis.searchGoogle(isbn);
|
||||
tmpthumb = CatalogueDBAdapter.fetchThumbnail(0);
|
||||
}
|
||||
|
||||
/* Copy tmpthumb over realthumb */
|
||||
try {
|
||||
tmpthumb.renameTo(thumb);
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
if (overwrite == true || !thumb.exists()) {
|
||||
try {
|
||||
tmpthumb.renameTo(thumb);
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
|
||||
if (description.equals("")) {
|
||||
description = book[18];
|
||||
}
|
||||
if (genre.equals("")) {
|
||||
genre = book[19];
|
||||
}
|
||||
mDbHelper.updateBook(id, author, title, isbn, publisher, date_published, rating, bookshelf, read, series, pages, series_num, notes, list_price, anthology, location, read_start, read_end, format, signed, description, genre);
|
||||
|
||||
} else {
|
||||
sendMessage(num, "Skip - " + title);
|
||||
}
|
||||
|
@ -1,180 +0,0 @@
|
||||
/*
|
||||
* @copyright 2010 Evan Leybourn
|
||||
* @license GNU General Public License
|
||||
*
|
||||
* This file is part of Book Catalogue.
|
||||
*
|
||||
* Book Catalogue is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Book Catalogue is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Book Catalogue. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.eleybourn.bookcatalogue;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.database.Cursor;
|
||||
|
||||
/*
|
||||
* A book catalogue application that integrates with Google Books.
|
||||
*/
|
||||
/* THIS DOES NOT WORK YET */
|
||||
public class BookBackup extends Activity {
|
||||
public int mCount = 0;
|
||||
public CatalogueDBAdapter mDbHelper;
|
||||
|
||||
public void onCreate() {
|
||||
mDbHelper = new CatalogueDBAdapter(this);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.app.backup.BackupAgent#onBackup(android.os.ParcelFileDescriptor, android.app.backup.BackupDataOutput, android.os.ParcelFileDescriptor)
|
||||
*/
|
||||
public void backup() {
|
||||
// Write structured data
|
||||
Cursor books = mDbHelper.exportBooks();
|
||||
|
||||
// TODO: Fix this
|
||||
// This code is duplicated here and in exportData in AdministrationFunctions
|
||||
// I can't just call exportData as it is encapsulated in a progress bar
|
||||
String export =
|
||||
CatalogueDBAdapter.KEY_ROWID + "\t" + //0
|
||||
CatalogueDBAdapter.KEY_FAMILY_NAME + "\t" + //1
|
||||
CatalogueDBAdapter.KEY_GIVEN_NAMES + "\t" + //2
|
||||
CatalogueDBAdapter.KEY_AUTHOR + "\t" + //3
|
||||
CatalogueDBAdapter.KEY_TITLE + "\t" + //4
|
||||
CatalogueDBAdapter.KEY_ISBN + "\t" + //5
|
||||
CatalogueDBAdapter.KEY_PUBLISHER + "\t" + //6
|
||||
CatalogueDBAdapter.KEY_DATE_PUBLISHED + "\t" + //7
|
||||
CatalogueDBAdapter.KEY_RATING + "\t" + //8
|
||||
"bookshelf_id\t" + //9
|
||||
CatalogueDBAdapter.KEY_BOOKSHELF + "\t" + //10
|
||||
CatalogueDBAdapter.KEY_READ + "\t" + //11
|
||||
CatalogueDBAdapter.KEY_SERIES + "\t" + //12
|
||||
CatalogueDBAdapter.KEY_SERIES_NUM + "\t" + //13
|
||||
CatalogueDBAdapter.KEY_PAGES + "\t" + //14
|
||||
CatalogueDBAdapter.KEY_NOTES + "\t" + //15
|
||||
CatalogueDBAdapter.KEY_LIST_PRICE + "\t" + //16
|
||||
CatalogueDBAdapter.KEY_ANTHOLOGY+ "\t" + //17
|
||||
CatalogueDBAdapter.KEY_LOCATION+ "\t" + //18
|
||||
CatalogueDBAdapter.KEY_READ_START+ "\t" + //19
|
||||
CatalogueDBAdapter.KEY_READ_END+ "\t" + //20
|
||||
CatalogueDBAdapter.KEY_FORMAT+ "\t" + //21
|
||||
CatalogueDBAdapter.KEY_SIGNED+ "\t" + //22
|
||||
CatalogueDBAdapter.KEY_LOANED_TO+ "\t" + //23
|
||||
"anthology_titles\t" + //24
|
||||
CatalogueDBAdapter.KEY_DESCRIPTION+ "\t" + //25
|
||||
CatalogueDBAdapter.KEY_GENRE+ "\t" + //26
|
||||
"\n";
|
||||
if (books.moveToFirst()) {
|
||||
do {
|
||||
long id = books.getLong(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ROWID));
|
||||
String dateString = "";
|
||||
try {
|
||||
String[] date = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DATE_PUBLISHED)).split("-");
|
||||
int yyyy = Integer.parseInt(date[0]);
|
||||
int mm = Integer.parseInt(date[1])+1;
|
||||
int dd = Integer.parseInt(date[2]);
|
||||
dateString = yyyy + "-" + mm + "-" + dd;
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
}
|
||||
String dateReadStartString = "";
|
||||
try {
|
||||
String[] date = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_START)).split("-");
|
||||
int yyyy = Integer.parseInt(date[0]);
|
||||
int mm = Integer.parseInt(date[1])+1;
|
||||
int dd = Integer.parseInt(date[2]);
|
||||
dateReadStartString = yyyy + "-" + mm + "-" + dd;
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
}
|
||||
String dateReadEndString = "";
|
||||
try {
|
||||
String[] date = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ_END)).split("-");
|
||||
int yyyy = Integer.parseInt(date[0]);
|
||||
int mm = Integer.parseInt(date[1])+1;
|
||||
int dd = Integer.parseInt(date[2]);
|
||||
dateReadEndString = yyyy + "-" + mm + "-" + dd;
|
||||
} catch (Exception e) {
|
||||
//do nothing
|
||||
}
|
||||
String anthology = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ANTHOLOGY));
|
||||
String anthology_titles = "";
|
||||
if (anthology.equals(CatalogueDBAdapter.ANTHOLOGY_MULTIPLE_AUTHORS + "") || anthology.equals(CatalogueDBAdapter.ANTHOLOGY_SAME_AUTHOR + "")) {
|
||||
Cursor titles = mDbHelper.fetchAnthologyTitlesByBook(id);
|
||||
if (titles.moveToFirst()) {
|
||||
do {
|
||||
String anth_title = titles.getString(titles.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_TITLE));
|
||||
String anth_author = titles.getString(titles.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_AUTHOR));
|
||||
anthology_titles += anth_title + " * " + anth_author + "|";
|
||||
} while (titles.moveToNext());
|
||||
}
|
||||
}
|
||||
String title = books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_TITLE));
|
||||
|
||||
String row = "";
|
||||
row += id + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_FAMILY_NAME)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_GIVEN_NAMES)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_AUTHOR)) + "\t";
|
||||
row += title + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_ISBN)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_PUBLISHER)) + "\t";
|
||||
row += dateString + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_RATING)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow("bookshelf_id")) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_BOOKSHELF)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_READ)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SERIES)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SERIES_NUM)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_PAGES)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_NOTES)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LIST_PRICE)) + "\t";
|
||||
row += anthology + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LOCATION)) + "\t";
|
||||
row += dateReadStartString + "\t";
|
||||
row += dateReadEndString + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_FORMAT)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_SIGNED)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_LOANED_TO)) + "\t";
|
||||
row += anthology_titles + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_DESCRIPTION)) + "\t";
|
||||
row += books.getString(books.getColumnIndexOrThrow(CatalogueDBAdapter.KEY_GENRE)) + "\t";
|
||||
row += "\n";
|
||||
export += row;
|
||||
}
|
||||
while (books.moveToNext());
|
||||
}
|
||||
|
||||
/* write to the SDCard */
|
||||
try {
|
||||
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(AdministrationFunctions.filePath), AdministrationFunctions.UTF8), AdministrationFunctions.BUFFER_SIZE);
|
||||
out.write(export);
|
||||
out.close();
|
||||
//Toast.makeText(this, R.string.export_complete, Toast.LENGTH_LONG).show();
|
||||
} catch (IOException e) {
|
||||
//Log.e("Book Catalogue", "Could not write to the SDCard");
|
||||
//Toast.makeText(this, R.string.export_failed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void restore() {
|
||||
//use restore from administrationfunction
|
||||
}
|
||||
|
||||
}
|
@ -148,6 +148,25 @@ public class BookCatalogue extends ExpandableListActivity {
|
||||
if (!CatalogueDBAdapter.message.equals("")) {
|
||||
upgradePopup(CatalogueDBAdapter.message);
|
||||
}
|
||||
if (CatalogueDBAdapter.do_action.equals(CatalogueDBAdapter.DO_UPDATE_FIELDS)) {
|
||||
AlertDialog alertDialog = new AlertDialog.Builder(BookCatalogue.this).setMessage(R.string.auto_update).create();
|
||||
alertDialog.setTitle(R.string.import_data);
|
||||
alertDialog.setIcon(android.R.drawable.ic_menu_info_details);
|
||||
alertDialog.setButton(BookCatalogue.this.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
adminPage("update_fields", ACTIVITY_ADMIN);
|
||||
return;
|
||||
}
|
||||
});
|
||||
alertDialog.setButton2(BookCatalogue.this.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
//do nothing
|
||||
return;
|
||||
}
|
||||
});
|
||||
alertDialog.show();
|
||||
return;
|
||||
}
|
||||
registerForContextMenu(getExpandableListView());
|
||||
} catch (Exception e) {
|
||||
//Log.e("Book Catalogue", "Unknown Exception - BC onCreate - " + e.getMessage() );
|
||||
|
@ -218,7 +218,7 @@ public class BookISBNSearch extends Activity {
|
||||
}
|
||||
|
||||
/* Format the output
|
||||
* String[] book = {author, title, isbn, publisher, date_published, rating, bookshelf, read, series, pages, series_num, list_price, anthology, location, read_start, read_end, audiobook, signed};
|
||||
* String[] book = {author, title, isbn, publisher, date_published, rating, bookshelf, read, series, pages, series_num, list_price, anthology, location, read_start, read_end, audiobook, signed, description, genre};
|
||||
*/
|
||||
if (book[0] == "" && book[1] == "") {
|
||||
Toast.makeText(this, R.string.book_not_found, Toast.LENGTH_LONG).show();
|
||||
|
@ -85,6 +85,8 @@ public class CatalogueDBAdapter {
|
||||
private static final String DB_TB_ANTHOLOGY = "anthology";
|
||||
private static final String DB_TB_BOOK_BOOKSHELF_WEAK = "book_bookshelf_weak";
|
||||
public static String message = "";
|
||||
public static String do_action = "";
|
||||
public static String DO_UPDATE_FIELDS = "do_update_fields";
|
||||
|
||||
public static final int ANTHOLOGY_NO = 0;
|
||||
public static final int ANTHOLOGY_SAME_AUTHOR = 1;
|
||||
@ -201,7 +203,7 @@ public class CatalogueDBAdapter {
|
||||
|
||||
|
||||
private final Context mCtx;
|
||||
public static final int DATABASE_VERSION = 47;
|
||||
public static final int DATABASE_VERSION = 48;
|
||||
|
||||
/**
|
||||
* This is a specific version of the SQLiteOpenHelper class. It handles onCreate and onUpgrade events
|
||||
@ -583,6 +585,15 @@ public class CatalogueDBAdapter {
|
||||
db.execSQL("ALTER TABLE " + DB_TB_BOOKS + " ADD " + KEY_DESCRIPTION + " text");
|
||||
db.execSQL("ALTER TABLE " + DB_TB_BOOKS + " ADD " + KEY_GENRE + " text");
|
||||
}
|
||||
if (curVersion == 47) {
|
||||
curVersion++;
|
||||
do_action = DO_UPDATE_FIELDS;
|
||||
message += "New in v3.1\n\n";
|
||||
message += "* The audiobook checkbox has been replaced with a format selector (inc. paperback, hardcover, companion etc)\n\n";
|
||||
message += "* When adding books the current bookshelf will be selected as the default bookshelf\n\n";
|
||||
message += "* Genre/Subject and Description fields have been added (Requested by Tosh) and will automatically populate based on Google Books and Amazon information\n\n";
|
||||
message += "* The save button will always be visible on the edit book screen\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user