1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-06 12:00:17 +02:00

BookHistory table + new style recent books request

This commit is contained in:
Nikolay Pultsin 2015-01-13 15:09:39 +01:00
parent 7046eb20c0
commit 3d3e770d9f
8 changed files with 109 additions and 73 deletions

View file

@ -181,7 +181,7 @@ public class LibraryService extends Service {
} }
public List<String> recentBooks() { public List<String> recentBooks() {
return SerializerUtil.serializeBookList(myCollection.recentBooks()); return recentlyOpenedBooks(12);
} }
public List<String> recentlyOpenedBooks(int count) { public List<String> recentlyOpenedBooks(int count) {

View file

@ -29,7 +29,6 @@ import android.database.Cursor;
import org.geometerplus.zlibrary.core.options.Config; import org.geometerplus.zlibrary.core.options.Config;
import org.geometerplus.zlibrary.core.filesystem.ZLFile; import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.options.ZLStringOption;
import org.geometerplus.zlibrary.core.options.ZLIntegerOption; import org.geometerplus.zlibrary.core.options.ZLIntegerOption;
import org.geometerplus.zlibrary.core.util.RationalNumber; import org.geometerplus.zlibrary.core.util.RationalNumber;
import org.geometerplus.zlibrary.core.util.ZLColor; import org.geometerplus.zlibrary.core.util.ZLColor;
@ -76,7 +75,7 @@ final class SQLiteBooksDatabase extends BooksDatabase {
private void migrate() { private void migrate() {
final int version = myDatabase.getVersion(); final int version = myDatabase.getVersion();
final int currentVersion = 29; final int currentVersion = 30;
if (version >= currentVersion) { if (version >= currentVersion) {
return; return;
} }
@ -142,6 +141,8 @@ final class SQLiteBooksDatabase extends BooksDatabase {
updateTables27(); updateTables27();
case 28: case 28:
updateTables28(); updateTables28();
case 29:
updateTables29();
} }
myDatabase.setTransactionSuccessful(); myDatabase.setTransactionSuccessful();
myDatabase.setVersion(currentVersion); myDatabase.setVersion(currentVersion);
@ -725,30 +726,43 @@ final class SQLiteBooksDatabase extends BooksDatabase {
return infos; return infos;
} }
protected void saveRecentBookIds(final List<Long> ids) { @Override
protected void addBookHistoryEvent(long bookId, int event) {
final SQLiteStatement statement = get( final SQLiteStatement statement = get(
"INSERT OR IGNORE INTO RecentBooks (book_id) VALUES (?)" "INSERT INTO BookHistory (book_id,timestamp,event) VALUES (?,?,?)"
); );
executeAsTransaction(new Runnable() { synchronized (statement) {
public void run() { statement.bindLong(1, bookId);
myDatabase.delete("RecentBooks", null, null); statement.bindLong(2, System.currentTimeMillis());
for (long id : ids) { statement.bindLong(3, event);
statement.bindLong(1, id); statement.executeInsert();
statement.execute();
} }
} }
});
}
@Override @Override
protected List<Long> loadRecentBookIds() { protected void removeBookHistoryEvents(long bookId, int event) {
final SQLiteStatement statement = get(
"DELETE FROM BookHistory WHERE book_id=? and event=?"
);
synchronized (statement) {
statement.bindLong(1, bookId);
statement.bindLong(2, event);
statement.executeInsert();
}
}
@Override
protected List<Long> loadRecentBookIds(int event, int limit) {
System.err.println("REQUESTED: " + event + " LIMIT " + limit);
final Cursor cursor = myDatabase.rawQuery( final Cursor cursor = myDatabase.rawQuery(
"SELECT book_id FROM RecentBooks ORDER BY book_index", null "SELECT book_id FROM BookHistory WHERE event=? GROUP BY book_id ORDER BY timestamp DESC LIMIT ?",
new String[] { String.valueOf(event), String.valueOf(limit) }
); );
final LinkedList<Long> ids = new LinkedList<Long>(); final LinkedList<Long> ids = new LinkedList<Long>();
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
ids.add(cursor.getLong(0)); ids.add(cursor.getLong(0));
} }
System.err.println("RESULT: " + ids);
cursor.close(); cursor.close();
return ids; return ids;
} }
@ -1054,6 +1068,7 @@ final class SQLiteBooksDatabase extends BooksDatabase {
@Override @Override
protected void deleteBook(long bookId) { protected void deleteBook(long bookId) {
myDatabase.beginTransaction(); myDatabase.beginTransaction();
myDatabase.execSQL("DELETE FROM BookHistory WHERE book_id=" + bookId);
myDatabase.execSQL("DELETE FROM BookHash WHERE book_id=" + bookId); myDatabase.execSQL("DELETE FROM BookHash WHERE book_id=" + bookId);
myDatabase.execSQL("DELETE FROM BookAuthor WHERE book_id=" + bookId); myDatabase.execSQL("DELETE FROM BookAuthor WHERE book_id=" + bookId);
myDatabase.execSQL("DELETE FROM BookLabel WHERE book_id=" + bookId); myDatabase.execSQL("DELETE FROM BookLabel WHERE book_id=" + bookId);
@ -1063,7 +1078,6 @@ final class SQLiteBooksDatabase extends BooksDatabase {
myDatabase.execSQL("DELETE FROM BookTag WHERE book_id=" + bookId); myDatabase.execSQL("DELETE FROM BookTag WHERE book_id=" + bookId);
myDatabase.execSQL("DELETE FROM BookUid WHERE book_id=" + bookId); myDatabase.execSQL("DELETE FROM BookUid WHERE book_id=" + bookId);
myDatabase.execSQL("DELETE FROM Bookmarks WHERE book_id=" + bookId); myDatabase.execSQL("DELETE FROM Bookmarks WHERE book_id=" + bookId);
myDatabase.execSQL("DELETE FROM RecentBooks WHERE book_id=" + bookId);
myDatabase.execSQL("DELETE FROM VisitedHyperlinks WHERE book_id=" + bookId); myDatabase.execSQL("DELETE FROM VisitedHyperlinks WHERE book_id=" + bookId);
myDatabase.execSQL("DELETE FROM Books WHERE book_id=" + bookId); myDatabase.execSQL("DELETE FROM Books WHERE book_id=" + bookId);
myDatabase.setTransactionSuccessful(); myDatabase.setTransactionSuccessful();
@ -1165,26 +1179,6 @@ final class SQLiteBooksDatabase extends BooksDatabase {
"CREATE TABLE IF NOT EXISTS RecentBooks(" + "CREATE TABLE IF NOT EXISTS RecentBooks(" +
"book_index INTEGER PRIMARY KEY," + "book_index INTEGER PRIMARY KEY," +
"book_id INTEGER REFERENCES Books(book_id))"); "book_id INTEGER REFERENCES Books(book_id))");
final ArrayList<Long> ids = new ArrayList<Long>();
final SQLiteStatement statement = myDatabase.compileStatement(
"SELECT book_id FROM Books WHERE file_name = ?"
);
for (int i = 0; i < 20; ++i) {
final ZLStringOption option = new ZLStringOption("LastOpenedBooks", "Book" + i, "");
final String fileName = option.getValue();
option.setValue("");
try {
statement.bindString(1, fileName);
final long bookId = statement.simpleQueryForLong();
if (bookId != -1) {
ids.add(bookId);
}
} catch (SQLException e) {
}
}
saveRecentBookIds(ids);
} }
private void updateTables5() { private void updateTables5() {
@ -1477,12 +1471,12 @@ final class SQLiteBooksDatabase extends BooksDatabase {
} }
private void updateTables26() { private void updateTables26() {
myDatabase.execSQL("DROP TABLE IF EXISTS BookSynchronizationInfo");
myDatabase.execSQL( myDatabase.execSQL(
"CREATE TABLE IF NOT EXISTS BookHash(" + "CREATE TABLE IF NOT EXISTS BookHash(" +
"book_id INTEGER PRIMARY KEY REFERENCES Books(book_id)," + "book_id INTEGER PRIMARY KEY REFERENCES Books(book_id)," +
"timestamp INTEGER NOT NULL," + "timestamp INTEGER NOT NULL," +
"hash TEXT(40) NOT NULL)"); "hash TEXT(40) NOT NULL)"
);
} }
private void updateTables27() { private void updateTables27() {
@ -1493,6 +1487,55 @@ final class SQLiteBooksDatabase extends BooksDatabase {
myDatabase.execSQL("ALTER TABLE HighlightingStyle ADD COLUMN fg_color INTEGER NOT NULL DEFAULT -1"); myDatabase.execSQL("ALTER TABLE HighlightingStyle ADD COLUMN fg_color INTEGER NOT NULL DEFAULT -1");
} }
private void updateTables29() {
myDatabase.execSQL("DROP TABLE IF EXISTS BookHistory");
myDatabase.execSQL(
"CREATE TABLE IF NOT EXISTS BookHistory(" +
"book_id INTEGER REFERENCES Books(book_id)," +
"timestamp INTEGER NOT NULL," +
"event INTEGER NOT NULL)"
);
Cursor cursor = myDatabase.rawQuery(
"SELECT book_id FROM RecentBooks ORDER BY book_index", null
);
SQLiteStatement insert = myDatabase.compileStatement(
"INSERT INTO BookHistory(book_id,timestamp,event) VALUES (?,?,?)"
);
insert.bindLong(3, HistoryEvent.Opened);
int count = -1;
while (cursor.moveToNext()) {
insert.bindLong(1, cursor.getLong(0));
insert.bindLong(2, count);
insert.executeInsert();
--count;
}
cursor.close();
cursor = myDatabase.rawQuery(
"SELECT book_id FROM Books ORDER BY book_id DESC", null
);
insert = myDatabase.compileStatement(
"INSERT INTO BookHistory(book_id,timestamp,event) VALUES (?,?,?)"
);
insert.bindLong(3, HistoryEvent.Added);
while (cursor.moveToNext()) {
insert.bindLong(1, cursor.getLong(0));
insert.bindLong(2, count);
insert.executeInsert();
--count;
}
cursor.close();
cursor = myDatabase.rawQuery(
"SELECT book_id,timestamp,event FROM BookHistory", null
);
while (cursor.moveToNext()) {
System.err.println("HISTORY RECORD: " + cursor.getLong(0) + " : " + cursor.getLong(1) + " : " + cursor.getLong(2));
}
cursor.close();
}
private SQLiteStatement get(String sql) { private SQLiteStatement get(String sql) {
SQLiteStatement statement = myStatements.get(sql); SQLiteStatement statement = myStatements.get(sql);
if (statement == null) { if (statement == null) {

View file

@ -59,9 +59,4 @@ public abstract class AbstractBookCollection implements IBookCollection {
public final Book getBookByFile(String path) { public final Book getBookByFile(String path) {
return getBookByFile(ZLFile.createFileByPath(path)); return getBookByFile(ZLFile.createFileByPath(path));
} }
// deprecated methods
public final List<Book> recentBooks() {
return recentlyOpenedBooks(12);
}
} }

View file

@ -506,6 +506,7 @@ public class Book extends TitledEntity<Book> {
return false; return false;
} }
final boolean[] result = new boolean[] { true };
database.executeAsTransaction(new Runnable() { database.executeAsTransaction(new Runnable() {
public void run() { public void run() {
if (myId >= 0) { if (myId >= 0) {
@ -513,11 +514,16 @@ public class Book extends TitledEntity<Book> {
database.updateBookInfo(myId, fileInfos.getId(File), myEncoding, myLanguage, getTitle()); database.updateBookInfo(myId, fileInfos.getId(File), myEncoding, myLanguage, getTitle());
} else { } else {
myId = database.insertBookInfo(File, myEncoding, myLanguage, getTitle()); myId = database.insertBookInfo(File, myEncoding, myLanguage, getTitle());
if (myId != -1 && myVisitedHyperlinks != null) { if (myId == -1) {
result[0] = false;
return;
}
if (myVisitedHyperlinks != null) {
for (String linkId : myVisitedHyperlinks) { for (String linkId : myVisitedHyperlinks) {
database.addVisitedHyperlink(myId, linkId); database.addVisitedHyperlink(myId, linkId);
} }
} }
database.addBookHistoryEvent(myId, BooksDatabase.HistoryEvent.Added);
} }
long index = 0; long index = 0;
@ -551,8 +557,12 @@ public class Book extends TitledEntity<Book> {
} }
}); });
if (result[0]) {
myIsSaved = true; myIsSaved = true;
return true; return true;
} else {
return false;
}
} }
private Set<String> myVisitedHyperlinks; private Set<String> myVisitedHyperlinks;

View file

@ -233,10 +233,6 @@ public class BookCollection extends AbstractBookCollection {
myDuplicateResolver.removeFile(book.File); myDuplicateResolver.removeFile(book.File);
myBooksById.remove(book.getId()); myBooksById.remove(book.getId());
final List<Long> ids = myDatabase.loadRecentBookIds();
if (ids.remove(book.getId())) {
myDatabase.saveRecentBookIds(ids);
}
if (deleteFromDisk) { if (deleteFromDisk) {
book.File.getPhysicalFile().delete(); book.File.getPhysicalFile().delete();
} }
@ -302,13 +298,11 @@ public class BookCollection extends AbstractBookCollection {
} }
public List<Book> recentlyAddedBooks(int count) { public List<Book> recentlyAddedBooks(int count) {
// TODO: implement return books(myDatabase.loadRecentBookIds(BooksDatabase.HistoryEvent.Added, count));
return books(myDatabase.loadRecentBookIds());
} }
public List<Book> recentlyOpenedBooks(int count) { public List<Book> recentlyOpenedBooks(int count) {
// TODO: implement return books(myDatabase.loadRecentBookIds(BooksDatabase.HistoryEvent.Opened, count));
return books(myDatabase.loadRecentBookIds());
} }
private List<Book> books(List<Long> ids) { private List<Book> books(List<Long> ids) {
@ -404,24 +398,17 @@ public class BookCollection extends AbstractBookCollection {
} }
public Book getRecentBook(int index) { public Book getRecentBook(int index) {
final List<Long> recentIds = myDatabase.loadRecentBookIds(); final List<Long> recentIds = myDatabase.loadRecentBookIds(BooksDatabase.HistoryEvent.Opened, index + 1);
return recentIds.size() > index ? getBookById(recentIds.get(index)) : null; return recentIds.size() > index ? getBookById(recentIds.get(index)) : null;
} }
public void addToRecentlyOpened(Book book) { public void addToRecentlyOpened(Book book) {
final List<Long> ids = myDatabase.loadRecentBookIds(); myDatabase.addBookHistoryEvent(book.getId(), BooksDatabase.HistoryEvent.Opened);
final Long bookId = book.getId();
ids.remove(bookId);
ids.add(0, bookId);
if (ids.size() > 12) {
ids.remove(12);
}
myDatabase.saveRecentBookIds(ids);
fireBookEvent(BookEvent.Opened, book); fireBookEvent(BookEvent.Opened, book);
} }
public void removeFromRecentlyOpened(Book book) { public void removeFromRecentlyOpened(Book book) {
// TODO: implement myDatabase.removeBookHistoryEvents(book.getId(), BooksDatabase.HistoryEvent.Opened);
} }
private void setStatus(Status status) { private void setStatus(Status status) {

View file

@ -29,6 +29,11 @@ import org.geometerplus.zlibrary.text.view.ZLTextFixedPosition;
import org.geometerplus.zlibrary.text.view.ZLTextPosition; import org.geometerplus.zlibrary.text.view.ZLTextPosition;
public abstract class BooksDatabase { public abstract class BooksDatabase {
protected interface HistoryEvent {
int Added = 0;
int Opened = 1;
}
public static final class NotAvailable extends Exception { public static final class NotAvailable extends Exception {
} }
@ -89,8 +94,9 @@ public abstract class BooksDatabase {
protected abstract void removeFileInfo(long fileId); protected abstract void removeFileInfo(long fileId);
protected abstract void saveFileInfo(FileInfo fileInfo); protected abstract void saveFileInfo(FileInfo fileInfo);
protected abstract List<Long> loadRecentBookIds(); protected abstract void addBookHistoryEvent(long bookId, int event);
protected abstract void saveRecentBookIds(final List<Long> ids); protected abstract void removeBookHistoryEvents(long bookId, int event);
protected abstract List<Long> loadRecentBookIds(int event, int limit);
protected abstract void setLabel(long bookId, String label); protected abstract void setLabel(long bookId, String label);
protected abstract void removeLabel(long bookId, String label); protected abstract void removeLabel(long bookId, String label);

View file

@ -100,9 +100,4 @@ public interface IBookCollection {
void saveHighlightingStyle(HighlightingStyle style); void saveHighlightingStyle(HighlightingStyle style);
void rescan(String path); void rescan(String path);
// deprecated methods, kept for compatibility
// shortcut to recentlyOpenedBooks(12)
List<Book> recentBooks();
} }

View file

@ -34,7 +34,7 @@ public class RecentBooksTree extends FirstLevelTree {
@Override @Override
public void waitForOpening() { public void waitForOpening() {
clear(); clear();
for (Book book : Collection.recentBooks()) { for (Book book : Collection.recentlyOpenedBooks(12)) {
new BookWithAuthorsTree(this, book); new BookWithAuthorsTree(this, book);
} }
} }