diff --git a/MANIFEST.in b/MANIFEST.in index edb9348..87eea17 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,5 @@ include README.md include requirements.txt -include nhentai/doujinshi.html +include nhentai/viewer/index.html +include nhentai/viewer/styles.css +include nhentai/viewer/scripts.js diff --git a/nhentai/doujinshi.html b/nhentai/doujinshi.html deleted file mode 100644 index eae0e25..0000000 --- a/nhentai/doujinshi.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - {TITLE} - - - - - - -
-{IMAGES}
-
-
- - - -
-
- - - - \ No newline at end of file diff --git a/nhentai/utils.py b/nhentai/utils.py index fe73730..3cddd50 100644 --- a/nhentai/utils.py +++ b/nhentai/utils.py @@ -30,10 +30,14 @@ def urlparse(url): return urlparse(url) +def readfile(path): + loc = os.path.dirname(__file__) + + with open(os.path.join(loc, path), 'r') as file: + return file.read() def generate_html(output_dir='.', doujinshi_obj=None): image_html = '' - previous = '' if doujinshi_obj is not None: doujinshi_dir = os.path.join(output_dir, format_filename('%s-%s' % (doujinshi_obj.id, @@ -44,28 +48,23 @@ def generate_html(output_dir='.', doujinshi_obj=None): file_list = os.listdir(doujinshi_dir) file_list.sort() - for index, image in enumerate(file_list): + for image in file_list: if not os.path.splitext(image)[1] in ('.jpg', '.png'): continue - try: - next_ = file_list[file_list.index(image) + 1] - except IndexError: - next_ = '' + image_html += '\n'\ + .format(image) - image_html += '\n'\ - .format(image, 'current' if index == 0 else '', previous, next_) - previous = image - - with open(os.path.join(os.path.dirname(__file__), 'doujinshi.html'), 'r') as template: - html = template.read() + html = readfile('viewer/index.html') + css = readfile('viewer/styles.css') + js = readfile('viewer/scripts.js') if doujinshi_obj is not None: title = doujinshi_obj.name else: title = 'nHentai HTML Viewer' - data = html.format(TITLE=title, IMAGES=image_html) + data = html.format(TITLE=title, IMAGES=image_html, SCRIPTS=js, STYLES=css) with open(os.path.join(doujinshi_dir, 'index.html'), 'w') as f: f.write(data) diff --git a/nhentai/viewer/index.html b/nhentai/viewer/index.html new file mode 100644 index 0000000..e7cb006 --- /dev/null +++ b/nhentai/viewer/index.html @@ -0,0 +1,24 @@ + + + + + {TITLE} + + + + + + +
+ +
+
+ + + + \ No newline at end of file diff --git a/nhentai/viewer/scripts.js b/nhentai/viewer/scripts.js new file mode 100644 index 0000000..721f45a --- /dev/null +++ b/nhentai/viewer/scripts.js @@ -0,0 +1,62 @@ +const pages = Array.from(document.querySelectorAll('img.image-item')); +let currentPage = 0; + +function changePage(pageNum) { + const previous = pages[currentPage]; + const current = pages[pageNum]; + + if (current == null) { + return; + } + + previous.classList.remove('current'); + current.classList.add('current'); + + currentPage = pageNum; + + const display = document.getElementById('dest'); + display.style.backgroundImage = `url("${current.src}")`; + + document.getElementById('page-num') + .innerText = [ + (pageNum + 1).toLocaleString(), + pages.length.toLocaleString() + ].join('\u200a/\u200a'); +} + +changePage(0); + +document.getElementById('list').onclick = event => { + if (pages.includes(event.target)) { + changePage(pages.indexOf(event.target)); + } +}; + +document.getElementById('image-container').onclick = event => { + const width = document.getElementById('image-container').clientWidth; + const clickPos = event.clientX / width; + + if (clickPos < 0.5) { + changePage(currentPage - 1); + } else { + changePage(currentPage + 1); + } +}; + +document.onkeypress = event => { + switch (event.key.toLowerCase()) { + // Previous Image + case 'arrowleft': + case 'a': + changePage(currentPage - 1); + break; + + // Next Image + case ' ': + case 'enter': + case 'arrowright': + case 'd': + changePage(currentPage + 1); + break; + } +}; \ No newline at end of file diff --git a/nhentai/viewer/styles.css b/nhentai/viewer/styles.css new file mode 100644 index 0000000..4de6fd9 --- /dev/null +++ b/nhentai/viewer/styles.css @@ -0,0 +1,69 @@ +*, *::after, *::before { + box-sizing: border-box; +} + +img { + vertical-align: middle; +} + +html, body { + display: flex; + background-color: #e8e6e6; + height: 100%; + width: 100%; + padding: 0; + margin: 0; + font-family: sans-serif; +} + +#list { + height: 100%; + overflow: auto; + width: 260px; + text-align: center; +} + +#list img { + width: 200px; + padding: 10px; + border-radius: 10px; + margin: 15px 0; + cursor: pointer; +} + +#list img.current { + background: #0003; +} + +#image-container { + flex: auto; + height: 100vh; + background: #222; + color: #fff; + text-align: center; + cursor: pointer; + -webkit-user-select: none; + user-select: none; + position: relative; +} + +#image-container #dest { + height: 100%; + width: 100%; + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} + +#image-container #page-num { + position: absolute; + font-size: 18pt; + left: 10px; + bottom: 5px; + font-weight: bold; + opacity: 0.75; + text-shadow: /* Duplicate the same shadow to make it very strong */ + 0 0 2px #222, + 0 0 2px #222, + 0 0 2px #222; +} \ No newline at end of file