mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-06 03:50:19 +02:00
BookHistory table + new style recent books request
This commit is contained in:
parent
7046eb20c0
commit
3d3e770d9f
8 changed files with 109 additions and 73 deletions
|
@ -181,7 +181,7 @@ public class LibraryService extends Service {
|
|||
}
|
||||
|
||||
public List<String> recentBooks() {
|
||||
return SerializerUtil.serializeBookList(myCollection.recentBooks());
|
||||
return recentlyOpenedBooks(12);
|
||||
}
|
||||
|
||||
public List<String> recentlyOpenedBooks(int count) {
|
||||
|
|
|
@ -29,7 +29,6 @@ import android.database.Cursor;
|
|||
|
||||
import org.geometerplus.zlibrary.core.options.Config;
|
||||
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.util.RationalNumber;
|
||||
import org.geometerplus.zlibrary.core.util.ZLColor;
|
||||
|
@ -76,7 +75,7 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
|||
|
||||
private void migrate() {
|
||||
final int version = myDatabase.getVersion();
|
||||
final int currentVersion = 29;
|
||||
final int currentVersion = 30;
|
||||
if (version >= currentVersion) {
|
||||
return;
|
||||
}
|
||||
|
@ -142,6 +141,8 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
|||
updateTables27();
|
||||
case 28:
|
||||
updateTables28();
|
||||
case 29:
|
||||
updateTables29();
|
||||
}
|
||||
myDatabase.setTransactionSuccessful();
|
||||
myDatabase.setVersion(currentVersion);
|
||||
|
@ -725,30 +726,43 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
|||
return infos;
|
||||
}
|
||||
|
||||
protected void saveRecentBookIds(final List<Long> ids) {
|
||||
@Override
|
||||
protected void addBookHistoryEvent(long bookId, int event) {
|
||||
final SQLiteStatement statement = get(
|
||||
"INSERT OR IGNORE INTO RecentBooks (book_id) VALUES (?)"
|
||||
"INSERT INTO BookHistory (book_id,timestamp,event) VALUES (?,?,?)"
|
||||
);
|
||||
executeAsTransaction(new Runnable() {
|
||||
public void run() {
|
||||
myDatabase.delete("RecentBooks", null, null);
|
||||
for (long id : ids) {
|
||||
statement.bindLong(1, id);
|
||||
statement.execute();
|
||||
synchronized (statement) {
|
||||
statement.bindLong(1, bookId);
|
||||
statement.bindLong(2, System.currentTimeMillis());
|
||||
statement.bindLong(3, event);
|
||||
statement.executeInsert();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@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(
|
||||
"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>();
|
||||
while (cursor.moveToNext()) {
|
||||
ids.add(cursor.getLong(0));
|
||||
}
|
||||
System.err.println("RESULT: " + ids);
|
||||
cursor.close();
|
||||
return ids;
|
||||
}
|
||||
|
@ -1054,6 +1068,7 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
|||
@Override
|
||||
protected void deleteBook(long bookId) {
|
||||
myDatabase.beginTransaction();
|
||||
myDatabase.execSQL("DELETE FROM BookHistory 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 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 BookUid 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 Books WHERE book_id=" + bookId);
|
||||
myDatabase.setTransactionSuccessful();
|
||||
|
@ -1165,26 +1179,6 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
|||
"CREATE TABLE IF NOT EXISTS RecentBooks(" +
|
||||
"book_index INTEGER PRIMARY KEY," +
|
||||
"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() {
|
||||
|
@ -1477,12 +1471,12 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
|||
}
|
||||
|
||||
private void updateTables26() {
|
||||
myDatabase.execSQL("DROP TABLE IF EXISTS BookSynchronizationInfo");
|
||||
myDatabase.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS BookHash(" +
|
||||
"book_id INTEGER PRIMARY KEY REFERENCES Books(book_id)," +
|
||||
"timestamp INTEGER NOT NULL," +
|
||||
"hash TEXT(40) NOT NULL)");
|
||||
"hash TEXT(40) NOT NULL)"
|
||||
);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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) {
|
||||
SQLiteStatement statement = myStatements.get(sql);
|
||||
if (statement == null) {
|
||||
|
|
|
@ -59,9 +59,4 @@ public abstract class AbstractBookCollection implements IBookCollection {
|
|||
public final Book getBookByFile(String path) {
|
||||
return getBookByFile(ZLFile.createFileByPath(path));
|
||||
}
|
||||
|
||||
// deprecated methods
|
||||
public final List<Book> recentBooks() {
|
||||
return recentlyOpenedBooks(12);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -506,6 +506,7 @@ public class Book extends TitledEntity<Book> {
|
|||
return false;
|
||||
}
|
||||
|
||||
final boolean[] result = new boolean[] { true };
|
||||
database.executeAsTransaction(new Runnable() {
|
||||
public void run() {
|
||||
if (myId >= 0) {
|
||||
|
@ -513,11 +514,16 @@ public class Book extends TitledEntity<Book> {
|
|||
database.updateBookInfo(myId, fileInfos.getId(File), myEncoding, myLanguage, getTitle());
|
||||
} else {
|
||||
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) {
|
||||
database.addVisitedHyperlink(myId, linkId);
|
||||
}
|
||||
}
|
||||
database.addBookHistoryEvent(myId, BooksDatabase.HistoryEvent.Added);
|
||||
}
|
||||
|
||||
long index = 0;
|
||||
|
@ -551,8 +557,12 @@ public class Book extends TitledEntity<Book> {
|
|||
}
|
||||
});
|
||||
|
||||
if (result[0]) {
|
||||
myIsSaved = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> myVisitedHyperlinks;
|
||||
|
|
|
@ -233,10 +233,6 @@ public class BookCollection extends AbstractBookCollection {
|
|||
myDuplicateResolver.removeFile(book.File);
|
||||
myBooksById.remove(book.getId());
|
||||
|
||||
final List<Long> ids = myDatabase.loadRecentBookIds();
|
||||
if (ids.remove(book.getId())) {
|
||||
myDatabase.saveRecentBookIds(ids);
|
||||
}
|
||||
if (deleteFromDisk) {
|
||||
book.File.getPhysicalFile().delete();
|
||||
}
|
||||
|
@ -302,13 +298,11 @@ public class BookCollection extends AbstractBookCollection {
|
|||
}
|
||||
|
||||
public List<Book> recentlyAddedBooks(int count) {
|
||||
// TODO: implement
|
||||
return books(myDatabase.loadRecentBookIds());
|
||||
return books(myDatabase.loadRecentBookIds(BooksDatabase.HistoryEvent.Added, count));
|
||||
}
|
||||
|
||||
public List<Book> recentlyOpenedBooks(int count) {
|
||||
// TODO: implement
|
||||
return books(myDatabase.loadRecentBookIds());
|
||||
return books(myDatabase.loadRecentBookIds(BooksDatabase.HistoryEvent.Opened, count));
|
||||
}
|
||||
|
||||
private List<Book> books(List<Long> ids) {
|
||||
|
@ -404,24 +398,17 @@ public class BookCollection extends AbstractBookCollection {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public void addToRecentlyOpened(Book book) {
|
||||
final List<Long> ids = myDatabase.loadRecentBookIds();
|
||||
final Long bookId = book.getId();
|
||||
ids.remove(bookId);
|
||||
ids.add(0, bookId);
|
||||
if (ids.size() > 12) {
|
||||
ids.remove(12);
|
||||
}
|
||||
myDatabase.saveRecentBookIds(ids);
|
||||
myDatabase.addBookHistoryEvent(book.getId(), BooksDatabase.HistoryEvent.Opened);
|
||||
fireBookEvent(BookEvent.Opened, book);
|
||||
}
|
||||
|
||||
public void removeFromRecentlyOpened(Book book) {
|
||||
// TODO: implement
|
||||
myDatabase.removeBookHistoryEvents(book.getId(), BooksDatabase.HistoryEvent.Opened);
|
||||
}
|
||||
|
||||
private void setStatus(Status status) {
|
||||
|
|
|
@ -29,6 +29,11 @@ import org.geometerplus.zlibrary.text.view.ZLTextFixedPosition;
|
|||
import org.geometerplus.zlibrary.text.view.ZLTextPosition;
|
||||
|
||||
public abstract class BooksDatabase {
|
||||
protected interface HistoryEvent {
|
||||
int Added = 0;
|
||||
int Opened = 1;
|
||||
}
|
||||
|
||||
public static final class NotAvailable extends Exception {
|
||||
}
|
||||
|
||||
|
@ -89,8 +94,9 @@ public abstract class BooksDatabase {
|
|||
protected abstract void removeFileInfo(long fileId);
|
||||
protected abstract void saveFileInfo(FileInfo fileInfo);
|
||||
|
||||
protected abstract List<Long> loadRecentBookIds();
|
||||
protected abstract void saveRecentBookIds(final List<Long> ids);
|
||||
protected abstract void addBookHistoryEvent(long bookId, int event);
|
||||
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 removeLabel(long bookId, String label);
|
||||
|
|
|
@ -100,9 +100,4 @@ public interface IBookCollection {
|
|||
void saveHighlightingStyle(HighlightingStyle style);
|
||||
|
||||
void rescan(String path);
|
||||
|
||||
// deprecated methods, kept for compatibility
|
||||
|
||||
// shortcut to recentlyOpenedBooks(12)
|
||||
List<Book> recentBooks();
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public class RecentBooksTree extends FirstLevelTree {
|
|||
@Override
|
||||
public void waitForOpening() {
|
||||
clear();
|
||||
for (Book book : Collection.recentBooks()) {
|
||||
for (Book book : Collection.recentlyOpenedBooks(12)) {
|
||||
new BookWithAuthorsTree(this, book);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue