mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 07:13:02 +00:00 
			
		
		
		
	Sorting for comics
Audiobook support
This commit is contained in:
		| @@ -107,7 +107,7 @@ def setup(log_file, log_level=None): | |||||||
|             return |             return | ||||||
|         r.debug("logging to %s level %s", log_file, r.level) |         r.debug("logging to %s level %s", log_file, r.level) | ||||||
|  |  | ||||||
|     if log_file == LOG_TO_STDERR: |     if 1 == 1: # log_file == LOG_TO_STDERR: | ||||||
|         file_handler = StreamHandler() |         file_handler = StreamHandler() | ||||||
|         file_handler.baseFilename = LOG_TO_STDERR |         file_handler.baseFilename = LOG_TO_STDERR | ||||||
|     else: |     else: | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								cps/static/css/libs/bar-ui.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								cps/static/css/libs/bar-ui.css
									
									
									
									
										vendored
									
									
								
							| @@ -135,7 +135,7 @@ | |||||||
|  width: 100%; |  width: 100%; | ||||||
|  height: 100%; |  height: 100%; | ||||||
|  /* for example */ |  /* for example */ | ||||||
|  /* background-image: url(../images/wood_pattern_dark.png); */ |  /* background-image: url(../image/wood_pattern_dark.png); */ | ||||||
|  /* additional opacity effects can be applied here. */ |  /* additional opacity effects can be applied here. */ | ||||||
|  opacity: 0.75; |  opacity: 0.75; | ||||||
|  |  | ||||||
| @@ -143,7 +143,7 @@ | |||||||
|  |  | ||||||
| .sm2-bar-ui.textured.dark-text .sm2-inline-texture { | .sm2-bar-ui.textured.dark-text .sm2-inline-texture { | ||||||
|  /* dark text + textured case: use light wood background (for example.) */ |  /* dark text + textured case: use light wood background (for example.) */ | ||||||
|  /* background-image: url(../images/patterns/wood_pattern.png); */ |  /* background-image: url(../image/patterns/wood_pattern.png); */ | ||||||
| } | } | ||||||
|  |  | ||||||
| .sm2-bar-ui.textured.dark-text .sm2-playlist-wrapper { | .sm2-bar-ui.textured.dark-text .sm2-playlist-wrapper { | ||||||
| @@ -704,7 +704,7 @@ | |||||||
|  height: 100%; |  height: 100%; | ||||||
|  top: 0px; |  top: 0px; | ||||||
|  left: 0px; |  left: 0px; | ||||||
|  background: none, url(../images/icomoon/free-25px-000000/SVG/spinner.svg); |  background: none, url(../image/icomoon/free-25px-000000/SVG/spinner.svg); | ||||||
|  background-size: 72%; |  background-size: 72%; | ||||||
|  background-position: 50%; |  background-position: 50%; | ||||||
|  background-repeat: no-repeat; |  background-repeat: no-repeat; | ||||||
|   | |||||||
| @@ -13,6 +13,22 @@ | |||||||
| var bitjs = bitjs || {}; | var bitjs = bitjs || {}; | ||||||
| bitjs.archive = bitjs.archive || {}; | bitjs.archive = bitjs.archive || {}; | ||||||
|  |  | ||||||
|  | function naturalCompare(a, b) { | ||||||
|  |     var ax = [], bx = []; | ||||||
|  |  | ||||||
|  |     a.filename.toLowerCase().replace(/(\d+)|(\D+)/g, function(_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) }); | ||||||
|  |     b.filename.toLowerCase().replace(/(\d+)|(\D+)/g, function(_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) }); | ||||||
|  |  | ||||||
|  |     while(ax.length && bx.length) { | ||||||
|  |         var an = ax.shift(); | ||||||
|  |         var bn = bx.shift(); | ||||||
|  |         var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]); | ||||||
|  |         if(nn) return nn; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ax.length - bx.length; | ||||||
|  | } | ||||||
|  |  | ||||||
| (function() { | (function() { | ||||||
|  |  | ||||||
|     // =========================================================================== |     // =========================================================================== | ||||||
|   | |||||||
| @@ -1333,11 +1333,12 @@ var unrar = function(arrayBuffer) { | |||||||
|  |  | ||||||
|             // now we have all information but things are unpacked |             // now we have all information but things are unpacked | ||||||
|             // TODO: unpack |             // TODO: unpack | ||||||
|             localFiles = localFiles.sort(function(a, b) { |             localFiles.sort(naturalCompare); | ||||||
|  |             /*localFiles = localFiles.sort(function(a, b) { | ||||||
|                 var aname = a.filename.toLowerCase(); |                 var aname = a.filename.toLowerCase(); | ||||||
|                 var bname = b.filename.toLowerCase(); |                 var bname = b.filename.toLowerCase(); | ||||||
|                 return aname > bname ? 1 : -1; |                 return aname > bname ? 1 : -1; | ||||||
|             }); |             });*/ | ||||||
|  |  | ||||||
|             info(localFiles.map(function(a) { |             info(localFiles.map(function(a) { | ||||||
|                 return a.filename; |                 return a.filename; | ||||||
|   | |||||||
| @@ -115,6 +115,7 @@ var TarLocalFile = function(bstream) { | |||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| var untar = function(arrayBuffer) { | var untar = function(arrayBuffer) { | ||||||
|     postMessage(new bitjs.archive.UnarchiveStartEvent()); |     postMessage(new bitjs.archive.UnarchiveStartEvent()); | ||||||
|     currentFilename = ""; |     currentFilename = ""; | ||||||
| @@ -127,14 +128,21 @@ var untar = function(arrayBuffer) { | |||||||
|  |  | ||||||
|     var bstream = new bitjs.io.ByteStream(arrayBuffer); |     var bstream = new bitjs.io.ByteStream(arrayBuffer); | ||||||
|     postProgress(); |     postProgress(); | ||||||
|     // While we don't encounter an empty block, keep making TarLocalFiles. |     /* | ||||||
|  |     // go through whole file, read header of each block and memorize, filepointer | ||||||
|  |     */ | ||||||
|     while (bstream.peekNumber(4) !== 0) { |     while (bstream.peekNumber(4) !== 0) { | ||||||
|         var oneLocalFile = new TarLocalFile(bstream); |         var localFile = new TarLocalFile(bstream); | ||||||
|  |         allLocalFiles.push(localFile); | ||||||
|  |         postProgress(); | ||||||
|  |     } | ||||||
|  |     allLocalFiles.sort(naturalCompare); | ||||||
|  |  | ||||||
|  |     allLocalFiles.forEach(function(oneLocalFile) { | ||||||
|  |         // While we don't encounter an empty block, keep making TarLocalFiles. | ||||||
|         if (oneLocalFile && oneLocalFile.isValid) { |         if (oneLocalFile && oneLocalFile.isValid) { | ||||||
|             // If we make it to this point and haven't thrown an error, we have successfully |             // If we make it to this point and haven't thrown an error, we have successfully | ||||||
|             // read in the data for a local file, so we can update the actual bytestream. |             // read in the data for a local file, so we can update the actual bytestream. | ||||||
|  |  | ||||||
|             allLocalFiles.push(oneLocalFile); |  | ||||||
|             totalUncompressedBytesInArchive += oneLocalFile.size; |             totalUncompressedBytesInArchive += oneLocalFile.size; | ||||||
|  |  | ||||||
|             // update progress |             // update progress | ||||||
| @@ -145,7 +153,7 @@ var untar = function(arrayBuffer) { | |||||||
|             postMessage(new bitjs.archive.UnarchiveExtractEvent(oneLocalFile)); |             postMessage(new bitjs.archive.UnarchiveExtractEvent(oneLocalFile)); | ||||||
|             postProgress(); |             postProgress(); | ||||||
|         } |         } | ||||||
|     } |     }); | ||||||
|     totalFilesInArchive = allLocalFiles.length; |     totalFilesInArchive = allLocalFiles.length; | ||||||
|  |  | ||||||
|     postProgress(); |     postProgress(); | ||||||
|   | |||||||
| @@ -72,19 +72,6 @@ var ZipLocalFile = function(bstream) { | |||||||
|         this.filename = bstream.readString(this.fileNameLength); |         this.filename = bstream.readString(this.fileNameLength); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     info("Zip Local File Header:"); |  | ||||||
|     info(" version=" + this.version); |  | ||||||
|     info(" general purpose=" + this.generalPurpose); |  | ||||||
|     info(" compression method=" + this.compressionMethod); |  | ||||||
|     info(" last mod file time=" + this.lastModFileTime); |  | ||||||
|     info(" last mod file date=" + this.lastModFileDate); |  | ||||||
|     info(" crc32=" + this.crc32); |  | ||||||
|     info(" compressed size=" + this.compressedSize); |  | ||||||
|     info(" uncompressed size=" + this.uncompressedSize); |  | ||||||
|     info(" file name length=" + this.fileNameLength); |  | ||||||
|     info(" extra field length=" + this.extraFieldLength); |  | ||||||
|     info(" filename = '" + this.filename + "'"); |  | ||||||
|  |  | ||||||
|     this.extraField = null; |     this.extraField = null; | ||||||
|     if (this.extraFieldLength > 0) { |     if (this.extraFieldLength > 0) { | ||||||
|         this.extraField = bstream.readString(this.extraFieldLength); |         this.extraField = bstream.readString(this.extraFieldLength); | ||||||
| @@ -107,6 +94,21 @@ var ZipLocalFile = function(bstream) { | |||||||
|         this.compressedSize = bstream.readNumber(4); |         this.compressedSize = bstream.readNumber(4); | ||||||
|         this.uncompressedSize = bstream.readNumber(4); |         this.uncompressedSize = bstream.readNumber(4); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Now that we have all the bytes for this file, we can print out some information. | ||||||
|  |     info("Zip Local File Header:"); | ||||||
|  |     info(" version=" + this.version); | ||||||
|  |     info(" general purpose=" + this.generalPurpose); | ||||||
|  |     info(" compression method=" + this.compressionMethod); | ||||||
|  |     info(" last mod file time=" + this.lastModFileTime); | ||||||
|  |     info(" last mod file date=" + this.lastModFileDate); | ||||||
|  |     info(" crc32=" + this.crc32); | ||||||
|  |     info(" compressed size=" + this.compressedSize); | ||||||
|  |     info(" uncompressed size=" + this.uncompressedSize); | ||||||
|  |     info(" file name length=" + this.fileNameLength); | ||||||
|  |     info(" extra field length=" + this.extraFieldLength); | ||||||
|  |     info(" filename = '" + this.filename + "'"); | ||||||
|  |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // determine what kind of compressed data we have and decompress | // determine what kind of compressed data we have and decompress | ||||||
| @@ -132,6 +134,7 @@ ZipLocalFile.prototype.unzip = function() { | |||||||
| // Takes an ArrayBuffer of a zip file in | // Takes an ArrayBuffer of a zip file in | ||||||
| // returns null on error | // returns null on error | ||||||
| // returns an array of DecompressedFile objects on success | // returns an array of DecompressedFile objects on success | ||||||
|  | // ToDo This function differs | ||||||
| var unzip = function(arrayBuffer) { | var unzip = function(arrayBuffer) { | ||||||
|     postMessage(new bitjs.archive.UnarchiveStartEvent()); |     postMessage(new bitjs.archive.UnarchiveStartEvent()); | ||||||
|  |  | ||||||
| @@ -159,11 +162,12 @@ var unzip = function(arrayBuffer) { | |||||||
|         totalFilesInArchive = localFiles.length; |         totalFilesInArchive = localFiles.length; | ||||||
|  |  | ||||||
|         // got all local files, now sort them |         // got all local files, now sort them | ||||||
|         localFiles.sort(function(a, b) { |         localFiles.sort(naturalCompare); | ||||||
|  |         /*localFiles.sort(function(a, b) { | ||||||
|             var aname = a.filename.toLowerCase(); |             var aname = a.filename.toLowerCase(); | ||||||
|             var bname = b.filename.toLowerCase(); |             var bname = b.filename.toLowerCase(); | ||||||
|             return aname > bname ? 1 : -1; |             return aname > bname ? 1 : -1; | ||||||
|         }); |         });*/ | ||||||
|  |  | ||||||
|         // archive extra data record |         // archive extra data record | ||||||
|         if (bstream.peekNumber(4) === zArchiveExtraDataSignature) { |         if (bstream.peekNumber(4) === zArchiveExtraDataSignature) { | ||||||
| @@ -253,9 +257,9 @@ function getHuffmanCodes(bitLengths) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Reference: http://tools.ietf.org/html/rfc1951#page-8 |     // Reference: http://tools.ietf.org/html/rfc1951#page-8 | ||||||
|     var numLengths = bitLengths.length, |     var numLengths = bitLengths.length; | ||||||
|         blCount = [], |     var blCount = []; | ||||||
|         MAX_BITS = 1; |     var MAX_BITS = 1; | ||||||
|  |  | ||||||
|     // Step 1: count up how many codes of each length we have |     // Step 1: count up how many codes of each length we have | ||||||
|     for (var i = 0; i < numLengths; ++i) { |     for (var i = 0; i < numLengths; ++i) { | ||||||
| @@ -274,8 +278,8 @@ function getHuffmanCodes(bitLengths) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Step 2: Find the numerical value of the smallest code for each code length |     // Step 2: Find the numerical value of the smallest code for each code length | ||||||
|     var nextCode = [], |     var nextCode = []; | ||||||
|         code = 0; |     var code = 0; | ||||||
|     for (var bits = 1; bits <= MAX_BITS; ++bits) { |     for (var bits = 1; bits <= MAX_BITS; ++bits) { | ||||||
|         var length2 = bits - 1; |         var length2 = bits - 1; | ||||||
|         // ensure undefined lengths are zero |         // ensure undefined lengths are zero | ||||||
| @@ -285,8 +289,8 @@ function getHuffmanCodes(bitLengths) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Step 3: Assign numerical values to all codes |     // Step 3: Assign numerical values to all codes | ||||||
|     var table = {}, |     var table = {}; | ||||||
|         tableLength = 0; |     var tableLength = 0; | ||||||
|     for (var n = 0; n < numLengths; ++n) { |     for (var n = 0; n < numLengths; ++n) { | ||||||
|         var len = bitLengths[n]; |         var len = bitLengths[n]; | ||||||
|         if (len !== 0) { |         if (len !== 0) { | ||||||
| @@ -353,7 +357,8 @@ function getFixedDistanceTable() { | |||||||
| // extract one bit at a time until we find a matching Huffman Code | // extract one bit at a time until we find a matching Huffman Code | ||||||
| // then return that symbol | // then return that symbol | ||||||
| function decodeSymbol(bstream, hcTable) { | function decodeSymbol(bstream, hcTable) { | ||||||
|     var code = 0, len = 0; |     var code = 0; | ||||||
|  |     var len = 0; | ||||||
|  |  | ||||||
|     // loop until we match |     // loop until we match | ||||||
|     for (;;) { |     for (;;) { | ||||||
| @@ -364,7 +369,6 @@ function decodeSymbol(bstream, hcTable) { | |||||||
|  |  | ||||||
|         // check against Huffman Code table and break if found |         // check against Huffman Code table and break if found | ||||||
|         if (hcTable.hasOwnProperty(code) && hcTable[code].length === len) { |         if (hcTable.hasOwnProperty(code) && hcTable[code].length === len) { | ||||||
|  |  | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         if (len > hcTable.maxLength) { |         if (len > hcTable.maxLength) { | ||||||
| @@ -500,10 +504,10 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) { | |||||||
|             if (symbol === 256) { |             if (symbol === 256) { | ||||||
|                 break; |                 break; | ||||||
|             } else { |             } else { | ||||||
|                 var lengthLookup = LengthLookupTable[symbol - 257], |                 var lengthLookup = LengthLookupTable[symbol - 257]; | ||||||
|                     length = lengthLookup[1] + bstream.readBits(lengthLookup[0]), |                 var length = lengthLookup[1] + bstream.readBits(lengthLookup[0]); | ||||||
|                     distLookup = DistLookupTable[decodeSymbol(bstream, hcDistanceTable)], |                 var distLookup = DistLookupTable[decodeSymbol(bstream, hcDistanceTable)]; | ||||||
|                     distance = distLookup[1] + bstream.readBits(distLookup[0]); |                 var distance = distLookup[1] + bstream.readBits(distLookup[0]); | ||||||
|  |  | ||||||
|                 // now apply length and distance appropriately and copy to output |                 // now apply length and distance appropriately and copy to output | ||||||
|  |  | ||||||
| @@ -634,8 +638,8 @@ function inflate(compressedData, numDecompressedBytes) { | |||||||
|             var distanceCodeLengths = literalCodeLengths.splice(numLiteralLengthCodes, numDistanceCodes); |             var distanceCodeLengths = literalCodeLengths.splice(numLiteralLengthCodes, numDistanceCodes); | ||||||
|  |  | ||||||
|             // now generate the true Huffman Code tables using these code lengths |             // now generate the true Huffman Code tables using these code lengths | ||||||
|             var hcLiteralTable = getHuffmanCodes(literalCodeLengths), |             var hcLiteralTable = getHuffmanCodes(literalCodeLengths); | ||||||
|                 hcDistanceTable = getHuffmanCodes(distanceCodeLengths); |             var hcDistanceTable = getHuffmanCodes(distanceCodeLengths); | ||||||
|             blockSize = inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer); |             blockSize = inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer); | ||||||
|         } else { |         } else { | ||||||
|             // error |             // error | ||||||
| @@ -659,3 +663,51 @@ function inflate(compressedData, numDecompressedBytes) { | |||||||
| onmessage = function(event) { | onmessage = function(event) { | ||||||
|     unzip(event.data.file, true); |     unzip(event.data.file, true); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | function naturalCompare(a, b) { | ||||||
|  |     var ax = [], bx = []; | ||||||
|  |  | ||||||
|  |     a.filename.toLowerCase().replace(/(\d+)|(\D+)/g, function(_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) }); | ||||||
|  |     b.filename.toLowerCase().replace(/(\d+)|(\D+)/g, function(_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) }); | ||||||
|  |  | ||||||
|  |     while(ax.length && bx.length) { | ||||||
|  |         var an = ax.shift(); | ||||||
|  |         var bn = bx.shift(); | ||||||
|  |         var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]); | ||||||
|  |         if(nn) return nn; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ax.length - bx.length; | ||||||
|  | }*/ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /*var re = /([a-z]+)(\d+)(.+)/i; | ||||||
|  | function naturalCompare(a, b) { | ||||||
|  |     var ma = a.match(re), | ||||||
|  |         mb = b.match(re), | ||||||
|  |         a_str = ma[1], | ||||||
|  |         b_str = mb[1], | ||||||
|  |         a_num = parseInt(ma[2],10), | ||||||
|  |         b_num = parseInt(mb[2],10), | ||||||
|  |         a_rem = ma[3], | ||||||
|  |         b_rem = mb[3]; | ||||||
|  |     return a_str > b_str ? 1 : a_str < b_str ? -1 : a_num > b_num ? 1 : a_num < b_num ? -1 : a_rem > b_rem; | ||||||
|  | }*/ | ||||||
|  |  | ||||||
|  | /*function naturalCompare(a, b) { | ||||||
|  |     var ax = [], bx = []; | ||||||
|  |  | ||||||
|  |     a.replace(/(\d+)|(\D+)/g, function(_, $1, $2) { ax.push([$1 || Infinity, $2 || ""]) }); | ||||||
|  |     b.replace(/(\d+)|(\D+)/g, function(_, $1, $2) { bx.push([$1 || Infinity, $2 || ""]) }); | ||||||
|  |  | ||||||
|  |     while(ax.length && bx.length) { | ||||||
|  |         var an = ax.shift(); | ||||||
|  |         var bn = bx.shift(); | ||||||
|  |         var nn = (an[0] - bn[0]) || an[1].localeCompare(bn[1]); | ||||||
|  |         if(nn) return nn; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ax.length - bx.length; | ||||||
|  | }*/ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -101,6 +101,35 @@ bitjs.io = bitjs.io || {}; | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * ToDo: Returns the next n bytes as a signed number and advances the stream pointer. | ||||||
|  |      * @param {number} n The number of bytes to read. | ||||||
|  |      * @return {number} The bytes interpreted as a signed number. | ||||||
|  |      */ | ||||||
|  |     bitjs.io.ByteStream.prototype.movePointer = function(n) { | ||||||
|  |         this.ptr += n; | ||||||
|  |         // end of buffer reached | ||||||
|  |         if ((this.bytes.byteLength - this.ptr) < 0 ) { | ||||||
|  |             this.ptr =  this.bytes.byteLength; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * ToDo: Returns the next n bytes as a signed number and advances the stream pointer. | ||||||
|  |      * @param {number} n The number of bytes to read. | ||||||
|  |      * @return {number} The bytes interpreted as a signed number. | ||||||
|  |      */ | ||||||
|  |     bitjs.io.ByteStream.prototype.moveTo = function(n) { | ||||||
|  |         if ( n < 0 ) { | ||||||
|  |             n = 0; | ||||||
|  |         } | ||||||
|  |         this.ptr = n; | ||||||
|  |         // end of buffer reached | ||||||
|  |         if ((this.bytes.byteLength - this.ptr) < 0 ) { | ||||||
|  |             this.ptr =  this.bytes.byteLength; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * This returns n bytes as a sub-array, advancing the pointer if movePointers |      * This returns n bytes as a sub-array, advancing the pointer if movePointers | ||||||
|      * is true. |      * is true. | ||||||
|   | |||||||
| @@ -66,9 +66,8 @@ | |||||||
|                     </ul> |                     </ul> | ||||||
|               </div> |               </div> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|               {% if reader_list  %} |             {% if audioentries|length > 0 %} | ||||||
|             {% if audioentries|length %} |               <div class="btn-group" role="group"> | ||||||
|               <!--div class="btn-group" role="group"> |  | ||||||
|                 <button id="listen-in-browser" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |                 <button id="listen-in-browser" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | ||||||
|                   <span class="glyphicon glyphicon-music"></span> {{_('Listen in browser')}} |                   <span class="glyphicon glyphicon-music"></span> {{_('Listen in browser')}} | ||||||
|                   <span class="caret"></span> |                   <span class="caret"></span> | ||||||
| @@ -86,10 +85,8 @@ | |||||||
|                     {% endif %} |                     {% endif %} | ||||||
|               {% endfor %} |               {% endfor %} | ||||||
|                   </ul> |                   </ul> | ||||||
|               </div--> |               </div> | ||||||
|             {% endif %} |             {% endif %} | ||||||
|  |  | ||||||
|           {% endif %} |  | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <h2 id="title">{{entry.title|shortentitle(40)}}</h2> |       <h2 id="title">{{entry.title|shortentitle(40)}}</h2> | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ | |||||||
|   <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"> |   <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"> | ||||||
|   <link href="{{ url_for('static', filename='css/libs/bootstrap.min.css') }}" rel="stylesheet" media="screen"> |   <link href="{{ url_for('static', filename='css/libs/bootstrap.min.css') }}" rel="stylesheet" media="screen"> | ||||||
|   <link rel="stylesheet" href="{{ url_for('static', filename='css/libs/bar-ui.css') }}" /> |   <link rel="stylesheet" href="{{ url_for('static', filename='css/libs/bar-ui.css') }}" /> | ||||||
|   <link rel="stylesheet" href="{{ url_for('static', filename='css/listen.css') }}" /> |   <!--link rel="stylesheet" href="{{ url_for('static', filename='css/listen.css') }}" /--> | ||||||
|  |  | ||||||
|   <!-- <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') }}"> | ||||||
| @@ -30,12 +30,12 @@ | |||||||
| </head> | </head> | ||||||
|  |  | ||||||
| <body> | <body> | ||||||
|   <div id="main"> |   <!--div id="main"> | ||||||
|     <div class="content"> |     <div class="content"> | ||||||
|       <h2>{{ entry.title }}</h2> |       <h2>{{ entry.title }}</h2> | ||||||
|  |  | ||||||
|       <div class="cover"> |       <div class="cover"> | ||||||
|         <img src="{{ url_for('web.get_cover', cover_path=entry.path.replace('\\','/')) }}" alt="{{ entry.title }}" /> |         <img src="{{ url_for('web.get_cover', book_id=entry.id) }}" alt="{{ entry.title }}" /> | ||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
|       {% if entry.ratings.__len__() > 0 %} |       {% if entry.ratings.__len__() > 0 %} | ||||||
| @@ -53,77 +53,178 @@ | |||||||
|  |  | ||||||
|       <h3>{{_('Description:')}}</h3> |       <h3>{{_('Description:')}}</h3> | ||||||
|       {{entry.comments[0].text|safe}} |       {{entry.comments[0].text|safe}} | ||||||
|  |     </div--> | ||||||
|  | <!--div class="sm2-bar-ui compact full-width"> | ||||||
|  |  | ||||||
|  |  <div class="bd sm2-main-controls"> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-texture"></div> | ||||||
|  |   <div class="sm2-inline-gradient"></div> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-element sm2-button-element"> | ||||||
|  |    <div class="sm2-button-bd"> | ||||||
|  |     <a href="#play" class="sm2-inline-button sm2-icon-play-pause">{{_('Play / pause')}}</a> | ||||||
|  |    </div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-element sm2-inline-status"> | ||||||
|  |  | ||||||
|  |    <div class="sm2-playlist"> | ||||||
|  |     <div class="sm2-playlist-target"> | ||||||
|  |      <!-- playlist <ul> + <li> markup will be injected here --> | ||||||
|  |      <!-- if you want default / non-JS content, you can put that here. --> | ||||||
|  |      <!--noscript><p>JavaScript is required.</p></noscript> | ||||||
|     </div> |     </div> | ||||||
|  |    </div> | ||||||
|  |  | ||||||
|     <div class="sm2-bar-ui compact flat"> |    <div class="sm2-progress"> | ||||||
|  |     <div class="sm2-row"> | ||||||
|       <div class="bd sm2-main-controls"> |     <div class="sm2-inline-time">0:00</div> | ||||||
|  |      <div class="sm2-progress-bd"> | ||||||
|         <div class="sm2-inline-texture"></div> |       <div class="sm2-progress-track"> | ||||||
|         <div class="sm2-inline-gradient"></div> |        <div class="sm2-progress-bar"></div> | ||||||
|  |        <div class="sm2-progress-ball"><div class="icon-overlay"></div></div> | ||||||
|         <div class="sm2-inline-element sm2-button-element"> |  | ||||||
|           <div class="sm2-button-bd"> |  | ||||||
|             <a href="#play" class="sm2-inline-button sm2-icon-play-pause">Play / pause</a> |  | ||||||
|           </div> |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <div class="sm2-inline-element sm2-inline-status"> |  | ||||||
|  |  | ||||||
|           <div class="sm2-playlist"> |  | ||||||
|             <div class="sm2-playlist-target"> |  | ||||||
|               <!-- playlist <ul> + <li> markup will be injected here --> |  | ||||||
|               <!-- if you want default / non-JS content, you can put that here. --> |  | ||||||
|               <noscript> |  | ||||||
|                 <p>JavaScript is required.</p> |  | ||||||
|               </noscript> |  | ||||||
|             </div> |  | ||||||
|           </div> |  | ||||||
|  |  | ||||||
|           <div class="sm2-progress"> |  | ||||||
|             <div class="sm2-row"> |  | ||||||
|               <div class="sm2-inline-time">0:00</div> |  | ||||||
|               <div class="sm2-progress-bd"> |  | ||||||
|                 <div class="sm2-progress-track"> |  | ||||||
|                   <div class="sm2-progress-bar"></div> |  | ||||||
|                   <div class="sm2-progress-ball"> |  | ||||||
|                     <div class="icon-overlay"></div> |  | ||||||
|                   </div> |  | ||||||
|                 </div> |  | ||||||
|               </div> |  | ||||||
|               <div class="sm2-inline-duration">0:00</div> |  | ||||||
|             </div> |  | ||||||
|           </div> |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <div class="sm2-inline-element sm2-button-element sm2-volume"> |  | ||||||
|           <div class="sm2-button-bd"> |  | ||||||
|             <span class="sm2-inline-button sm2-volume-control volume-shade"></span> |  | ||||||
|             <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a> |  | ||||||
|           </div> |  | ||||||
|         </div> |  | ||||||
|       </div> |  | ||||||
|  |  | ||||||
|       <div class="bd sm2-playlist-drawer sm2-element"> |  | ||||||
|  |  | ||||||
|         <div class="sm2-inline-texture"> |  | ||||||
|           <div class="sm2-box-shadow"></div> |  | ||||||
|         </div> |  | ||||||
|  |  | ||||||
|         <!-- playlist content is mirrored here --> |  | ||||||
|  |  | ||||||
|         <div class="sm2-playlist-wrapper"> |  | ||||||
|           <ul class="sm2-playlist-bd"> |  | ||||||
|             <li> |  | ||||||
|               <a href="{{ url_for('web.serve_book', book_id=mp3file,book_format=audioformat)}}"></a> |  | ||||||
|             </li> |  | ||||||
|           </ul> |  | ||||||
|         </div> |  | ||||||
|       </div> |       </div> | ||||||
|  |      </div> | ||||||
|  |      <div class="sm2-inline-duration">0:00</div> | ||||||
|     </div> |     </div> | ||||||
|  |    </div> | ||||||
|  |  | ||||||
|     <script> |   </div> | ||||||
|       window.calibre = { |  | ||||||
|  |   <div class="sm2-inline-element sm2-button-element sm2-volume"> | ||||||
|  |    <div class="sm2-button-bd"> | ||||||
|  |     <span class="sm2-inline-button sm2-volume-control volume-shade"></span> | ||||||
|  |     <a href="#volume" class="sm2-inline-button sm2-volume-control">{{_('volume')}}</a> | ||||||
|  |    </div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |  </div> | ||||||
|  |  | ||||||
|  |  <div class="bd sm2-playlist-drawer sm2-element"> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-texture"> | ||||||
|  |    <div class="sm2-box-shadow"></div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <!-- playlist content is mirrored here --> | ||||||
|  |  | ||||||
|  |   <!--div class="sm2-playlist-wrapper"> | ||||||
|  |     <ul class="sm2-playlist-bd"> | ||||||
|  |       <li><a href="{{ url_for('web.serve_book', book_id=mp3file,book_format=audioformat)}}"><b>{% for author in entry.authors %}{{author.name.replace('|',',')}} | ||||||
|  |         {% if not loop.last %} & {% endif %} {% endfor %}</b> - {{entry.title}}</a></li> | ||||||
|  |     </ul> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |  </div> | ||||||
|  |  | ||||||
|  | </div--> | ||||||
|  |  | ||||||
|  | <div class="sm2-bar-ui full-width fixed"> | ||||||
|  |  | ||||||
|  |  <div class="bd sm2-main-controls"> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-texture"></div> | ||||||
|  |   <div class="sm2-inline-gradient"></div> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-element sm2-button-element"> | ||||||
|  |    <div class="sm2-button-bd"> | ||||||
|  |     <a href="#play" class="sm2-inline-button sm2-icon-play-pause">Play / pause</a> | ||||||
|  |    </div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-element sm2-inline-status"> | ||||||
|  |  | ||||||
|  |    <div class="sm2-playlist"> | ||||||
|  |     <div class="sm2-playlist-target"> | ||||||
|  |      <noscript><p>JavaScript is required.</p></noscript> | ||||||
|  |     </div> | ||||||
|  |    </div> | ||||||
|  |  | ||||||
|  |    <div class="sm2-progress"> | ||||||
|  |     <div class="sm2-row"> | ||||||
|  |     <div class="sm2-inline-time">0:00</div> | ||||||
|  |      <div class="sm2-progress-bd"> | ||||||
|  |       <div class="sm2-progress-track"> | ||||||
|  |        <div class="sm2-progress-bar"></div> | ||||||
|  |        <div class="sm2-progress-ball"><div class="icon-overlay"></div></div> | ||||||
|  |       </div> | ||||||
|  |      </div> | ||||||
|  |      <div class="sm2-inline-duration">0:00</div> | ||||||
|  |     </div> | ||||||
|  |    </div> | ||||||
|  |  | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-element sm2-button-element sm2-volume"> | ||||||
|  |    <div class="sm2-button-bd"> | ||||||
|  |     <span class="sm2-inline-button sm2-volume-control volume-shade"></span> | ||||||
|  |     <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a> | ||||||
|  |    </div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-element sm2-button-element"> | ||||||
|  |    <div class="sm2-button-bd"> | ||||||
|  |     <a href="#prev" title="Previous" class="sm2-inline-button sm2-icon-previous">< previous</a> | ||||||
|  |    </div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-element sm2-button-element"> | ||||||
|  |    <div class="sm2-button-bd"> | ||||||
|  |     <a href="#next" title="Next" class="sm2-inline-button sm2-icon-next">> next</a> | ||||||
|  |    </div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-element sm2-button-element"> | ||||||
|  |    <div class="sm2-button-bd"> | ||||||
|  |     <a href="#repeat" title="Repeat playlist" class="sm2-inline-button sm2-icon-repeat">∞ repeat</a> | ||||||
|  |    </div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-element sm2-button-element sm2-menu"> | ||||||
|  |    <div class="sm2-button-bd"> | ||||||
|  |     <a href="#menu" class="sm2-inline-button sm2-icon-menu">menu</a> | ||||||
|  |    </div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |  </div> | ||||||
|  |  | ||||||
|  |  <div class="bd sm2-playlist-drawer sm2-element"> | ||||||
|  |  | ||||||
|  |   <div class="sm2-inline-texture"> | ||||||
|  |    <div class="sm2-box-shadow"></div> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |   <!-- playlist content is mirrored here --> | ||||||
|  |  | ||||||
|  |   <div class="sm2-playlist-wrapper"> | ||||||
|  |     <ul class="sm2-playlist-bd"> | ||||||
|  |       <li><a href="{{ url_for('web.serve_book', book_id=mp3file,book_format=audioformat)}}"><b>{% for author in entry.authors %}{{author.name.replace('|',',')}} | ||||||
|  |         {% if not loop.last %} & {% endif %} {% endfor %}</b> - {{entry.title}}</a></li> | ||||||
|  |     </ul> | ||||||
|  |   </div> | ||||||
|  |  | ||||||
|  |  </div> | ||||||
|  |  | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | soundManager.setup({ | ||||||
|  |   useHTML5Audio: true, | ||||||
|  |   preferFlash: false, | ||||||
|  |   url: '/path/to/swf-files/', | ||||||
|  |   onready: function() { | ||||||
|  |     var mySound = soundManager.createSound({ | ||||||
|  |       // id: 'aSound', | ||||||
|  |       // url: "{{ url_for('web.serve_book', book_id=mp3file,book_format=audioformat)}}" | ||||||
|  |     }); | ||||||
|  |     mySound.play(); | ||||||
|  |   }, | ||||||
|  |   ontimeout: function() { | ||||||
|  |     // Hrmm, SM2 could not start. Missing SWF? Flash blocked? Show an error, etc.? | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | window.calibre = { | ||||||
|         filePath: "{{ url_for('static', filename='js/libs/') }}", |         filePath: "{{ url_for('static', filename='js/libs/') }}", | ||||||
|         cssPath: "{{ url_for('static', filename='css/') }}", |         cssPath: "{{ url_for('static', filename='css/') }}", | ||||||
|         bookUrl: "{{ url_for('static', filename=mp3file) }}/", |         bookUrl: "{{ url_for('static', filename=mp3file) }}/", | ||||||
| @@ -131,8 +232,7 @@ | |||||||
|         bookmark: "{{ bookmark.bookmark_key if bookmark != None }}", |         bookmark: "{{ bookmark.bookmark_key if bookmark != None }}", | ||||||
|         useBookmarks: "{{ g.user.is_authenticated | tojson }}" |         useBookmarks: "{{ g.user.is_authenticated | tojson }}" | ||||||
|             }; |             }; | ||||||
|     </script> | </script> | ||||||
|   </div> |  | ||||||
| </body> | </body> | ||||||
|  |  | ||||||
| </html> | </html> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ozzieisaacs
					Ozzieisaacs