Merge remote-tracking branch 'adv/bookmarks'
This commit is contained in:
commit
c9f36a4d1a
38
cps/static/js/reading/epub.js
Normal file
38
cps/static/js/reading/epub.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* global $, calibre, EPUBJS, ePubReader */
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
EPUBJS.filePath = calibre.filePath;
|
||||||
|
EPUBJS.cssPath = calibre.cssPath;
|
||||||
|
|
||||||
|
var reader = ePubReader(calibre.bookUrl, {
|
||||||
|
restore: true,
|
||||||
|
bookmarks: [calibre.bookmark]
|
||||||
|
});
|
||||||
|
reader.on("reader:bookmarked", updateBookmark.bind(reader, "add"));
|
||||||
|
reader.on("reader:unbookmarked", updateBookmark.bind(reader, "remove"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} action - Add or remove bookmark
|
||||||
|
* @param {string|int} location - Location or zero
|
||||||
|
*/
|
||||||
|
function updateBookmark(action, location) {
|
||||||
|
// Remove other bookmarks (there can only be one)
|
||||||
|
if (action === "add") {
|
||||||
|
this.settings.bookmarks.filter(function (bookmark) {
|
||||||
|
return bookmark !== location;
|
||||||
|
}).map(function (bookmark) {
|
||||||
|
this.removeBookmark(bookmark);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save to database
|
||||||
|
$.ajax(calibre.bookmarkUrl, {
|
||||||
|
method: "post",
|
||||||
|
data: { bookmark: location || "" }
|
||||||
|
}).fail(function (xhr, status, error) {
|
||||||
|
alert(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
|
@ -11,59 +11,6 @@
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/libs/normalize.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/libs/normalize.css') }}">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/popup.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/popup.css') }}">
|
||||||
<script src="{{ url_for('static', filename='js/libs/jquery.min.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/libs/zip.min.js') }}"></script>
|
|
||||||
|
|
||||||
<!-- Full Screen -->
|
|
||||||
<script src="{{ url_for('static', filename='js/libs/screenfull.min.js') }}"></script>
|
|
||||||
|
|
||||||
<!-- Render -->
|
|
||||||
<script src="{{ url_for('static', filename='js/libs/epub.min.js') }}"></script>
|
|
||||||
|
|
||||||
<!-- Hooks -->
|
|
||||||
<script src="{{ url_for('static', filename='js/libs/hooks.min.js') }}"></script>
|
|
||||||
|
|
||||||
<!-- Reader -->
|
|
||||||
<script src="{{ url_for('static', filename='js/libs/reader.min.js') }}"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
"use strict";
|
|
||||||
document.onreadystatechange = function () {
|
|
||||||
if (document.readyState == "complete") {
|
|
||||||
EPUBJS.filePath = "{{ url_for('static', filename='js/libs/') }}";
|
|
||||||
EPUBJS.cssPath = "{{ url_for('static', filename='css/') }}";
|
|
||||||
|
|
||||||
window.reader = ePubReader("{{ url_for('static', filename=bookid) }}/");
|
|
||||||
//keybind
|
|
||||||
/*$(document).keydown(function(event){
|
|
||||||
if(event.keyCode == 37){
|
|
||||||
//window.reader.book.prevPage();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
if(event.keyCode == 39){
|
|
||||||
//swindow.reader.book.nextPage();
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//bind mouse
|
|
||||||
$(window).bind('DOMMouseScroll mousewheel', function(event) {
|
|
||||||
var delta = 0;
|
|
||||||
if (event.originalEvent.wheelDelta) {
|
|
||||||
delta = event.originalEvent.wheelDelta;
|
|
||||||
}else if (event.originalEvent.detail) {
|
|
||||||
delta = event.originalEvent.detail*-1;
|
|
||||||
}
|
|
||||||
if (delta >= 0) {
|
|
||||||
window.reader.book.prevPage();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
window.reader.book.nextPage();
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="sidebar">
|
<div id="sidebar">
|
||||||
|
@ -129,5 +76,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overlay"></div>
|
<div class="overlay"></div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.calibre = {
|
||||||
|
filePath: "{{ url_for('static', filename='js/libs/') }}",
|
||||||
|
cssPath: "{{ url_for('static', filename='css/') }}",
|
||||||
|
bookUrl: "{{ url_for('static', filename=bookid) }}/",
|
||||||
|
bookmarkUrl: "{{ url_for('bookmark', book_id=bookid, book_format='EPUB') }}",
|
||||||
|
bookmark: "{{ bookmark.bookmark_key if bookmark != None }}"
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script src="{{ url_for('static', filename='js/libs/jquery.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/libs/zip.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/libs/screenfull.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/libs/epub.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/libs/hooks.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/libs/reader.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/reading/epub.js') }}"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
19
cps/ub.py
19
cps/ub.py
|
@ -212,15 +212,26 @@ class BookShelf(Base):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Book %r>' % self.id
|
return '<Book %r>' % self.id
|
||||||
|
|
||||||
|
|
||||||
class ReadBook(Base):
|
class ReadBook(Base):
|
||||||
__tablename__ = 'book_read_link'
|
__tablename__ = 'book_read_link'
|
||||||
|
|
||||||
id=Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
book_id = Column(Integer, unique=False)
|
book_id = Column(Integer, unique=False)
|
||||||
user_id =Column(Integer, ForeignKey('user.id'), unique=False)
|
user_id = Column(Integer, ForeignKey('user.id'), unique=False)
|
||||||
is_read = Column(Boolean, unique=False)
|
is_read = Column(Boolean, unique=False)
|
||||||
|
|
||||||
|
|
||||||
|
class Bookmark(Base):
|
||||||
|
__tablename__ = 'bookmark'
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
user_id = Column(Integer, ForeignKey('user.id'))
|
||||||
|
book_id = Column(Integer)
|
||||||
|
format = Column(String(collation='NOCASE'))
|
||||||
|
bookmark_key = Column(String)
|
||||||
|
|
||||||
|
|
||||||
# Baseclass representing Downloads from calibre-web in app.db
|
# Baseclass representing Downloads from calibre-web in app.db
|
||||||
class Downloads(Base):
|
class Downloads(Base):
|
||||||
__tablename__ = 'downloads'
|
__tablename__ = 'downloads'
|
||||||
|
@ -396,7 +407,9 @@ class Config:
|
||||||
# rows with SQL commands
|
# rows with SQL commands
|
||||||
def migrate_Database():
|
def migrate_Database():
|
||||||
if not engine.dialect.has_table(engine.connect(), "book_read_link"):
|
if not engine.dialect.has_table(engine.connect(), "book_read_link"):
|
||||||
ReadBook.__table__.create(bind = engine)
|
ReadBook.__table__.create(bind=engine)
|
||||||
|
if not engine.dialect.has_table(engine.connect(), "bookmark"):
|
||||||
|
Bookmark.__table__.create(bind=engine)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session.query(exists().where(User.locale)).scalar()
|
session.query(exists().where(User.locale)).scalar()
|
||||||
|
|
102
cps/web.py
102
cps/web.py
|
@ -1316,6 +1316,26 @@ def show_book(book_id):
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/ajax/bookmark/<int:book_id>/<book_format>", methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def bookmark(book_id, book_format):
|
||||||
|
bookmark_key = request.form["bookmark"]
|
||||||
|
ub.session.query(ub.Bookmark).filter(ub.and_(ub.Bookmark.user_id == int(current_user.id),
|
||||||
|
ub.Bookmark.book_id == book_id,
|
||||||
|
ub.Bookmark.format == book_format)).delete()
|
||||||
|
if not bookmark_key:
|
||||||
|
ub.session.commit()
|
||||||
|
return "", 204
|
||||||
|
|
||||||
|
bookmark = ub.Bookmark(user_id=current_user.id,
|
||||||
|
book_id=book_id,
|
||||||
|
format=book_format,
|
||||||
|
bookmark_key=bookmark_key)
|
||||||
|
ub.session.merge(bookmark)
|
||||||
|
ub.session.commit()
|
||||||
|
return "", 201
|
||||||
|
|
||||||
|
|
||||||
@app.route("/admin")
|
@app.route("/admin")
|
||||||
@login_required
|
@login_required
|
||||||
def admin_forbidden():
|
def admin_forbidden():
|
||||||
|
@ -1750,49 +1770,51 @@ def unread_books(page):
|
||||||
@login_required_if_no_ano
|
@login_required_if_no_ano
|
||||||
def read_book(book_id, book_format):
|
def read_book(book_id, book_format):
|
||||||
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
|
||||||
if book:
|
if not book:
|
||||||
book_dir = os.path.join(config.get_main_dir, "cps", "static", str(book_id))
|
|
||||||
if not os.path.exists(book_dir):
|
|
||||||
os.mkdir(book_dir)
|
|
||||||
if book_format.lower() == "epub":
|
|
||||||
# check if mimetype file is exists
|
|
||||||
mime_file = str(book_id) + "/mimetype"
|
|
||||||
if not os.path.exists(mime_file):
|
|
||||||
epub_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".epub"
|
|
||||||
if not os.path.isfile(epub_file):
|
|
||||||
raise ValueError('Error opening eBook. File does not exist: ', epub_file)
|
|
||||||
zfile = zipfile.ZipFile(epub_file)
|
|
||||||
for name in zfile.namelist():
|
|
||||||
(dirName, fileName) = os.path.split(name)
|
|
||||||
newDir = os.path.join(book_dir, dirName)
|
|
||||||
if not os.path.exists(newDir):
|
|
||||||
try:
|
|
||||||
os.makedirs(newDir)
|
|
||||||
except OSError as exception:
|
|
||||||
if not exception.errno == errno.EEXIST:
|
|
||||||
raise
|
|
||||||
if fileName:
|
|
||||||
fd = open(os.path.join(newDir, fileName), "wb")
|
|
||||||
fd.write(zfile.read(name))
|
|
||||||
fd.close()
|
|
||||||
zfile.close()
|
|
||||||
return render_title_template('read.html', bookid=book_id, title=_(u"Read a Book"))
|
|
||||||
elif book_format.lower() == "pdf":
|
|
||||||
return render_title_template('readpdf.html', pdffile=book_id, title=_(u"Read a Book"))
|
|
||||||
elif book_format.lower() == "txt":
|
|
||||||
return render_title_template('readtxt.html', txtfile=book_id, title=_(u"Read a Book"))
|
|
||||||
elif book_format.lower() == "cbr":
|
|
||||||
all_name = str(book_id) + "/" + book.data[0].name + ".cbr"
|
|
||||||
tmp_file = os.path.join(book_dir, book.data[0].name) + ".cbr"
|
|
||||||
if not os.path.exists(all_name):
|
|
||||||
cbr_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".cbr"
|
|
||||||
copyfile(cbr_file, tmp_file)
|
|
||||||
return render_title_template('readcbr.html', comicfile=all_name, title=_(u"Read a Book"))
|
|
||||||
|
|
||||||
else:
|
|
||||||
flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error")
|
flash(_(u"Error opening eBook. File does not exist or file is not accessible:"), category="error")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
|
book_dir = os.path.join(config.get_main_dir, "cps", "static", str(book_id))
|
||||||
|
if not os.path.exists(book_dir):
|
||||||
|
os.mkdir(book_dir)
|
||||||
|
bookmark = ub.session.query(ub.Bookmark).filter(ub.and_(ub.Bookmark.user_id == int(current_user.id),
|
||||||
|
ub.Bookmark.book_id == book_id,
|
||||||
|
ub.Bookmark.format == book_format.upper())).first()
|
||||||
|
if book_format.lower() == "epub":
|
||||||
|
# check if mimetype file is exists
|
||||||
|
mime_file = str(book_id) + "/mimetype"
|
||||||
|
if not os.path.exists(mime_file):
|
||||||
|
epub_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".epub"
|
||||||
|
if not os.path.isfile(epub_file):
|
||||||
|
raise ValueError('Error opening eBook. File does not exist: ', epub_file)
|
||||||
|
zfile = zipfile.ZipFile(epub_file)
|
||||||
|
for name in zfile.namelist():
|
||||||
|
(dirName, fileName) = os.path.split(name)
|
||||||
|
newDir = os.path.join(book_dir, dirName)
|
||||||
|
if not os.path.exists(newDir):
|
||||||
|
try:
|
||||||
|
os.makedirs(newDir)
|
||||||
|
except OSError as exception:
|
||||||
|
if not exception.errno == errno.EEXIST:
|
||||||
|
raise
|
||||||
|
if fileName:
|
||||||
|
fd = open(os.path.join(newDir, fileName), "wb")
|
||||||
|
fd.write(zfile.read(name))
|
||||||
|
fd.close()
|
||||||
|
zfile.close()
|
||||||
|
return render_title_template('read.html', bookid=book_id, title=_(u"Read a Book"), bookmark=bookmark)
|
||||||
|
elif book_format.lower() == "pdf":
|
||||||
|
return render_title_template('readpdf.html', pdffile=book_id, title=_(u"Read a Book"))
|
||||||
|
elif book_format.lower() == "txt":
|
||||||
|
return render_title_template('readtxt.html', txtfile=book_id, title=_(u"Read a Book"))
|
||||||
|
elif book_format.lower() == "cbr":
|
||||||
|
all_name = str(book_id) + "/" + book.data[0].name + ".cbr"
|
||||||
|
tmp_file = os.path.join(book_dir, book.data[0].name) + ".cbr"
|
||||||
|
if not os.path.exists(all_name):
|
||||||
|
cbr_file = os.path.join(config.config_calibre_dir, book.path, book.data[0].name) + ".cbr"
|
||||||
|
copyfile(cbr_file, tmp_file)
|
||||||
|
return render_title_template('readcbr.html', comicfile=all_name, title=_(u"Read a Book"))
|
||||||
|
|
||||||
|
|
||||||
@app.route("/download/<int:book_id>/<book_format>")
|
@app.route("/download/<int:book_id>/<book_format>")
|
||||||
@login_required_if_no_ano
|
@login_required_if_no_ano
|
||||||
|
|
Loading…
Reference in New Issue
Block a user