mirror of
https://github.com/9001/copyparty.git
synced 2025-11-01 20:43:42 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd7df5c952 | ||
|
|
a270019147 | ||
|
|
55e0209901 | ||
|
|
2b255fbbed | ||
|
|
8a2345a0fb | ||
|
|
bfa9f535aa | ||
|
|
f757623ad8 | ||
|
|
3c7465e268 |
10
README.md
10
README.md
@@ -200,10 +200,16 @@ the browser has the following hotkeys
|
||||
* `G` toggle list / grid view
|
||||
* `T` toggle thumbnails / icons
|
||||
* when playing audio:
|
||||
* `0..9` jump to 10%..90%
|
||||
* `U/O` skip 10sec back/forward
|
||||
* `J/L` prev/next song
|
||||
* `U/O` skip 10sec back/forward
|
||||
* `0..9` jump to 10%..90%
|
||||
* `P` play/pause (also starts playing the folder)
|
||||
* when viewing images / playing videos:
|
||||
* `J/L, Left/Right` prev/next file
|
||||
* `Home/End` first/last file
|
||||
* `U/O` skip 10sec back/forward
|
||||
* `P/K/Space` play/pause video
|
||||
* `Esc` close viewer
|
||||
* when tree-sidebar is open:
|
||||
* `A/D` adjust tree width
|
||||
* in the grid view:
|
||||
|
||||
@@ -258,31 +258,32 @@ def run_argparse(argv, formatter):
|
||||
),
|
||||
)
|
||||
# fmt: off
|
||||
u = unicode
|
||||
ap2 = ap.add_argument_group('general options')
|
||||
ap2.add_argument("-c", metavar="PATH", type=str, action="append", help="add config file")
|
||||
ap2.add_argument("-c", metavar="PATH", type=u, action="append", help="add config file")
|
||||
ap2.add_argument("-nc", metavar="NUM", type=int, default=64, help="max num clients")
|
||||
ap2.add_argument("-j", metavar="CORES", type=int, default=1, help="max num cpu cores")
|
||||
ap2.add_argument("-a", metavar="ACCT", type=str, action="append", help="add account, USER:PASS; example [ed:wark")
|
||||
ap2.add_argument("-v", metavar="VOL", type=str, action="append", help="add volume, SRC:DST:FLAG; example [.::r], [/mnt/nas/music:/music:r:aed")
|
||||
ap2.add_argument("-a", metavar="ACCT", type=u, action="append", help="add account, USER:PASS; example [ed:wark")
|
||||
ap2.add_argument("-v", metavar="VOL", type=u, action="append", help="add volume, SRC:DST:FLAG; example [.::r], [/mnt/nas/music:/music:r:aed")
|
||||
ap2.add_argument("-ed", action="store_true", help="enable ?dots")
|
||||
ap2.add_argument("-emp", action="store_true", help="enable markdown plugins")
|
||||
ap2.add_argument("-mcr", metavar="SEC", type=int, default=60, help="md-editor mod-chk rate")
|
||||
ap2.add_argument("--dotpart", action="store_true", help="dotfile incomplete uploads")
|
||||
ap2.add_argument("--sparse", metavar="MiB", type=int, default=4, help="up2k min.size threshold (mswin-only)")
|
||||
ap2.add_argument("--urlform", metavar="MODE", type=str, default="print,get", help="how to handle url-forms; examples: [stash], [save,get]")
|
||||
ap2.add_argument("--urlform", metavar="MODE", type=u, default="print,get", help="how to handle url-forms; examples: [stash], [save,get]")
|
||||
|
||||
ap2 = ap.add_argument_group('network options')
|
||||
ap2.add_argument("-i", metavar="IP", type=str, default="0.0.0.0", help="ip to bind (comma-sep.)")
|
||||
ap2.add_argument("-p", metavar="PORT", type=str, default="3923", help="ports to bind (comma/range)")
|
||||
ap2.add_argument("-i", metavar="IP", type=u, default="0.0.0.0", help="ip to bind (comma-sep.)")
|
||||
ap2.add_argument("-p", metavar="PORT", type=u, default="3923", help="ports to bind (comma/range)")
|
||||
ap2.add_argument("--rproxy", metavar="DEPTH", type=int, default=1, help="which ip to keep; 0 = tcp, 1 = origin (first x-fwd), 2 = cloudflare, 3 = nginx, -1 = closest proxy")
|
||||
|
||||
ap2 = ap.add_argument_group('SSL/TLS options')
|
||||
ap2.add_argument("--http-only", action="store_true", help="disable ssl/tls")
|
||||
ap2.add_argument("--https-only", action="store_true", help="disable plaintext")
|
||||
ap2.add_argument("--ssl-ver", metavar="LIST", type=str, help="set allowed ssl/tls versions; [help] shows available versions; default is what your python version considers safe")
|
||||
ap2.add_argument("--ciphers", metavar="LIST", help="set allowed ssl/tls ciphers; [help] shows available ciphers")
|
||||
ap2.add_argument("--ssl-ver", metavar="LIST", type=u, help="set allowed ssl/tls versions; [help] shows available versions; default is what your python version considers safe")
|
||||
ap2.add_argument("--ciphers", metavar="LIST", type=u, help="set allowed ssl/tls ciphers; [help] shows available ciphers")
|
||||
ap2.add_argument("--ssl-dbg", action="store_true", help="dump some tls info")
|
||||
ap2.add_argument("--ssl-log", metavar="PATH", help="log master secrets")
|
||||
ap2.add_argument("--ssl-log", metavar="PATH", type=u, help="log master secrets")
|
||||
|
||||
ap2 = ap.add_argument_group('opt-outs')
|
||||
ap2.add_argument("-nw", action="store_true", help="disable writes (benchmark)")
|
||||
@@ -291,16 +292,16 @@ def run_argparse(argv, formatter):
|
||||
ap2.add_argument("--no-zip", action="store_true", help="disable download as zip/tar")
|
||||
|
||||
ap2 = ap.add_argument_group('safety options')
|
||||
ap2.add_argument("--ls", metavar="U[,V[,F]]", help="scan all volumes; arguments USER,VOL,FLAGS; example [**,*,ln,p,r]")
|
||||
ap2.add_argument("--salt", type=str, default="hunter2", help="up2k file-hash salt")
|
||||
ap2.add_argument("--ls", metavar="U[,V[,F]]", type=u, help="scan all volumes; arguments USER,VOL,FLAGS; example [**,*,ln,p,r]")
|
||||
ap2.add_argument("--salt", type=u, default="hunter2", help="up2k file-hash salt")
|
||||
|
||||
ap2 = ap.add_argument_group('logging options')
|
||||
ap2.add_argument("-q", action="store_true", help="quiet")
|
||||
ap2.add_argument("-lo", metavar="PATH", type=str, help="logfile, example: cpp-%%Y-%%m%%d-%%H%%M%%S.txt.xz")
|
||||
ap2.add_argument("-lo", metavar="PATH", type=u, help="logfile, example: cpp-%%Y-%%m%%d-%%H%%M%%S.txt.xz")
|
||||
ap2.add_argument("--log-conn", action="store_true", help="print tcp-server msgs")
|
||||
ap2.add_argument("--log-htp", action="store_true", help="print http-server threadpool scaling")
|
||||
ap2.add_argument("--ihead", metavar="HEADER", action='append', help="dump incoming header")
|
||||
ap2.add_argument("--lf-url", metavar="RE", type=str, default=r"^/\.cpr/|\?th=[wj]$", help="dont log URLs matching")
|
||||
ap2.add_argument("--ihead", metavar="HEADER", type=u, action='append', help="dump incoming header")
|
||||
ap2.add_argument("--lf-url", metavar="RE", type=u, default=r"^/\.cpr/|\?th=[wj]$", help="dont log URLs matching")
|
||||
|
||||
ap2 = ap.add_argument_group('admin panel options')
|
||||
ap2.add_argument("--no-rescan", action="store_true", help="disable ?scan (volume reindexing)")
|
||||
@@ -315,9 +316,9 @@ def run_argparse(argv, formatter):
|
||||
ap2.add_argument("--th-no-webp", action="store_true", help="disable webp output")
|
||||
ap2.add_argument("--th-ff-jpg", action="store_true", help="force jpg for video thumbs")
|
||||
ap2.add_argument("--th-poke", metavar="SEC", type=int, default=300, help="activity labeling cooldown")
|
||||
ap2.add_argument("--th-clean", metavar="SEC", type=int, default=43200, help="cleanup interval")
|
||||
ap2.add_argument("--th-clean", metavar="SEC", type=int, default=43200, help="cleanup interval; 0=disabled")
|
||||
ap2.add_argument("--th-maxage", metavar="SEC", type=int, default=604800, help="max folder age")
|
||||
ap2.add_argument("--th-covers", metavar="N,N", type=str, default="folder.png,folder.jpg,cover.png,cover.jpg", help="folder thumbnails to stat for")
|
||||
ap2.add_argument("--th-covers", metavar="N,N", type=u, default="folder.png,folder.jpg,cover.png,cover.jpg", help="folder thumbnails to stat for")
|
||||
|
||||
ap2 = ap.add_argument_group('database options')
|
||||
ap2.add_argument("-e2d", action="store_true", help="enable up2k database")
|
||||
@@ -326,25 +327,25 @@ def run_argparse(argv, formatter):
|
||||
ap2.add_argument("-e2t", action="store_true", help="enable metadata indexing")
|
||||
ap2.add_argument("-e2ts", action="store_true", help="enable metadata scanner, sets -e2t")
|
||||
ap2.add_argument("-e2tsr", action="store_true", help="rescan all metadata, sets -e2ts")
|
||||
ap2.add_argument("--hist", metavar="PATH", type=str, help="where to store volume state")
|
||||
ap2.add_argument("--hist", metavar="PATH", type=u, help="where to store volume state")
|
||||
ap2.add_argument("--no-hash", action="store_true", help="disable hashing during e2ds folder scans")
|
||||
ap2.add_argument("--no-mutagen", action="store_true", help="use ffprobe for tags instead")
|
||||
ap2.add_argument("--no-mtag-mt", action="store_true", help="disable tag-read parallelism")
|
||||
ap2.add_argument("-mtm", metavar="M=t,t,t", action="append", type=str, help="add/replace metadata mapping")
|
||||
ap2.add_argument("-mte", metavar="M,M,M", type=str, help="tags to index/display (comma-sep.)",
|
||||
ap2.add_argument("-mtm", metavar="M=t,t,t", type=u, action="append", help="add/replace metadata mapping")
|
||||
ap2.add_argument("-mte", metavar="M,M,M", type=u, help="tags to index/display (comma-sep.)",
|
||||
default="circle,album,.tn,artist,title,.bpm,key,.dur,.q,.vq,.aq,ac,vc,res,.fps")
|
||||
ap2.add_argument("-mtp", metavar="M=[f,]bin", action="append", type=str, help="read tag M using bin")
|
||||
ap2.add_argument("-mtp", metavar="M=[f,]bin", type=u, action="append", help="read tag M using bin")
|
||||
ap2.add_argument("--srch-time", metavar="SEC", type=int, default=30, help="search deadline")
|
||||
|
||||
ap2 = ap.add_argument_group('appearance options')
|
||||
ap2.add_argument("--css-browser", metavar="L", help="URL to additional CSS to include")
|
||||
ap2.add_argument("--css-browser", metavar="L", type=u, help="URL to additional CSS to include")
|
||||
|
||||
ap2 = ap.add_argument_group('debug options')
|
||||
ap2.add_argument("--no-sendfile", action="store_true", help="disable sendfile")
|
||||
ap2.add_argument("--no-scandir", action="store_true", help="disable scandir")
|
||||
ap2.add_argument("--no-fastboot", action="store_true", help="wait for up2k indexing")
|
||||
ap2.add_argument("--no-htp", action="store_true", help="disable httpserver threadpool, create threads as-needed instead")
|
||||
ap2.add_argument("--stackmon", metavar="P,S", help="write stacktrace to Path every S second")
|
||||
ap2.add_argument("--stackmon", metavar="P,S", type=u, help="write stacktrace to Path every S second")
|
||||
|
||||
return ap.parse_args(args=argv[1:])
|
||||
# fmt: on
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
|
||||
VERSION = (0, 11, 34)
|
||||
VERSION = (0, 11, 35)
|
||||
CODENAME = "the grid"
|
||||
BUILD_DT = (2021, 7, 9)
|
||||
BUILD_DT = (2021, 7, 11)
|
||||
|
||||
S_VERSION = ".".join(map(str, VERSION))
|
||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||
|
||||
@@ -49,7 +49,7 @@ except:
|
||||
# https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html
|
||||
# ffmpeg -formats
|
||||
FMT_PIL = "bmp dib gif icns ico jpg jpeg jp2 jpx pcx png pbm pgm ppm pnm sgi tga tif tiff webp xbm dds xpm"
|
||||
FMT_FF = "av1 asf avi flv m4v mkv mjpeg mjpg mpg mpeg mpg2 mpeg2 h264 avc h265 hevc mov 3gp mp4 ts mpegts nut ogv ogm rm vob webm wmv"
|
||||
FMT_FF = "av1 asf avi flv m4v mkv mjpeg mjpg mpg mpeg mpg2 mpeg2 h264 avc mts h265 hevc mov 3gp mp4 ts mpegts nut ogv ogm rm vob webm wmv"
|
||||
|
||||
if HAVE_HEIF:
|
||||
FMT_PIL += " heif heifs heic heics"
|
||||
@@ -130,9 +130,10 @@ class ThumbSrv(object):
|
||||
msg += ", ".join(missing)
|
||||
self.log(msg, c=3)
|
||||
|
||||
t = threading.Thread(target=self.cleaner, name="thumb-cleaner")
|
||||
t.daemon = True
|
||||
t.start()
|
||||
if self.args.th_clean:
|
||||
t = threading.Thread(target=self.cleaner, name="thumb-cleaner")
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
def log(self, msg, c=0):
|
||||
self.log_func("thumb", msg, c)
|
||||
|
||||
@@ -284,13 +284,11 @@ def alltrace():
|
||||
|
||||
def min_ex():
|
||||
et, ev, tb = sys.exc_info()
|
||||
tb = traceback.extract_tb(tb, 2)
|
||||
ex = [
|
||||
"{} @ {} <{}>: {}".format(fp.split(os.sep)[-1], ln, fun, txt)
|
||||
for fp, ln, fun, txt in tb
|
||||
]
|
||||
ex.append("{}: {}".format(et.__name__, ev))
|
||||
return "\n".join(ex)
|
||||
tb = traceback.extract_tb(tb)
|
||||
fmt = "{} @ {} <{}>: {}"
|
||||
ex = [fmt.format(fp.split(os.sep)[-1], ln, fun, txt) for fp, ln, fun, txt in tb]
|
||||
ex.append("[{}] {}".format(et.__name__, ev))
|
||||
return "\n".join(ex[-8:])
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
|
||||
@@ -28,7 +28,8 @@ window.baguetteBox = (function () {
|
||||
isOverlayVisible = false,
|
||||
touch = {}, // start-pos
|
||||
touchFlag = false, // busy
|
||||
regex = /.+\.(gif|jpe?g|png|webp)/i,
|
||||
re_i = /.+\.(gif|jpe?g|png|webp)/i,
|
||||
re_v = /.+\.(webm|mp4)/i,
|
||||
data = {}, // all galleries
|
||||
imagesElements = [],
|
||||
documentLastFocus = null;
|
||||
@@ -96,10 +97,6 @@ window.baguetteBox = (function () {
|
||||
data[selector] = selectorData;
|
||||
|
||||
[].forEach.call(galleryNodeList, function (galleryElement) {
|
||||
if (userOptions && userOptions.filter) {
|
||||
regex = userOptions.filter;
|
||||
}
|
||||
|
||||
var tagsNodeList = [];
|
||||
if (galleryElement.tagName === 'A') {
|
||||
tagsNodeList = [galleryElement];
|
||||
@@ -109,7 +106,7 @@ window.baguetteBox = (function () {
|
||||
|
||||
tagsNodeList = [].filter.call(tagsNodeList, function (element) {
|
||||
if (element.className.indexOf(userOptions && userOptions.ignoreClass) === -1) {
|
||||
return regex.test(element.href);
|
||||
return re_i.test(element.href) || re_v.test(element.href);
|
||||
}
|
||||
});
|
||||
if (tagsNodeList.length === 0) {
|
||||
@@ -209,24 +206,36 @@ window.baguetteBox = (function () {
|
||||
bindEvents();
|
||||
}
|
||||
|
||||
function keyDownHandler(event) {
|
||||
switch (event.keyCode) {
|
||||
case 37: // Left
|
||||
showPreviousImage();
|
||||
break;
|
||||
case 39: // Right
|
||||
showNextImage();
|
||||
break;
|
||||
case 27: // Esc
|
||||
hideOverlay();
|
||||
break;
|
||||
case 36: // Home
|
||||
showFirstImage(event);
|
||||
break;
|
||||
case 35: // End
|
||||
showLastImage(event);
|
||||
break;
|
||||
}
|
||||
function keyDownHandler(e) {
|
||||
if (e.ctrlKey || e.altKey || e.metaKey || e.isComposing)
|
||||
return;
|
||||
|
||||
var k = e.code + '';
|
||||
|
||||
if (k == "ArrowLeft" || k == "KeyJ")
|
||||
showPreviousImage();
|
||||
else if (k == "ArrowRight" || k == "KeyL")
|
||||
showNextImage();
|
||||
else if (k == "Escape")
|
||||
hideOverlay();
|
||||
else if (k == "Home")
|
||||
showFirstImage(e);
|
||||
else if (k == "End")
|
||||
showLastImage(e);
|
||||
else if (k == "Space" || k == "KeyP" || k == "KeyK")
|
||||
playpause();
|
||||
else if (k == "KeyU" || k == "KeyO")
|
||||
relseek(k == "KeyU" ? -10 : 10);
|
||||
}
|
||||
|
||||
function keyUpHandler(e) {
|
||||
if (e.ctrlKey || e.altKey || e.metaKey || e.isComposing)
|
||||
return;
|
||||
|
||||
var k = e.code + '';
|
||||
|
||||
if (k == "Space")
|
||||
ev(e);
|
||||
}
|
||||
|
||||
var passiveSupp = false;
|
||||
@@ -325,6 +334,7 @@ window.baguetteBox = (function () {
|
||||
}
|
||||
|
||||
bind(document, 'keydown', keyDownHandler);
|
||||
bind(document, 'keyup', keyUpHandler);
|
||||
currentIndex = chosenImageIndex;
|
||||
touch = {
|
||||
count: 0,
|
||||
@@ -366,6 +376,7 @@ window.baguetteBox = (function () {
|
||||
|
||||
function hideOverlay(e) {
|
||||
ev(e);
|
||||
playvid(false);
|
||||
if (options.noScrollbars) {
|
||||
document.documentElement.style.overflowY = 'auto';
|
||||
document.body.style.overflowY = 'auto';
|
||||
@@ -375,6 +386,7 @@ window.baguetteBox = (function () {
|
||||
}
|
||||
|
||||
unbind(document, 'keydown', keyDownHandler);
|
||||
unbind(document, 'keyup', keyUpHandler);
|
||||
// Fade out and hide the overlay
|
||||
overlay.className = '';
|
||||
setTimeout(function () {
|
||||
@@ -398,8 +410,8 @@ window.baguetteBox = (function () {
|
||||
return; // out-of-bounds or gallery dirty
|
||||
}
|
||||
|
||||
if (imageContainer.getElementsByTagName('img')[0]) {
|
||||
// image is loaded, cb and bail
|
||||
if (imageContainer.querySelector('img, video')) {
|
||||
// was loaded, cb and bail
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
@@ -408,7 +420,7 @@ window.baguetteBox = (function () {
|
||||
|
||||
var imageElement = galleryItem.imageElement,
|
||||
imageSrc = imageElement.href,
|
||||
thumbnailElement = imageElement.getElementsByTagName('img')[0],
|
||||
thumbnailElement = imageElement.querySelector('img, video'),
|
||||
imageCaption = typeof options.captions === 'function' ?
|
||||
options.captions.call(currentGallery, imageElement) :
|
||||
imageElement.getAttribute('data-caption') || imageElement.title;
|
||||
@@ -428,16 +440,20 @@ window.baguetteBox = (function () {
|
||||
}
|
||||
imageContainer.appendChild(figure);
|
||||
|
||||
var image = mknod('img');
|
||||
image.onload = function () {
|
||||
var is_vid = re_v.test(imageSrc),
|
||||
image = mknod(is_vid ? 'video' : 'img');
|
||||
|
||||
clmod(imageContainer, 'vid', is_vid);
|
||||
|
||||
image.addEventListener(is_vid ? 'loadedmetadata' : 'load', function () {
|
||||
// Remove loader element
|
||||
var spinner = document.querySelector('#baguette-img-' + index + ' .baguetteBox-spinner');
|
||||
figure.removeChild(spinner);
|
||||
if (!options.async && callback) {
|
||||
if (!options.async && callback)
|
||||
callback();
|
||||
}
|
||||
};
|
||||
});
|
||||
image.setAttribute('src', imageSrc);
|
||||
image.setAttribute('controls', 'controls');
|
||||
image.alt = thumbnailElement ? thumbnailElement.alt || '' : '';
|
||||
if (options.titleTag && imageCaption) {
|
||||
image.title = imageCaption;
|
||||
@@ -498,6 +514,7 @@ window.baguetteBox = (function () {
|
||||
return false;
|
||||
}
|
||||
|
||||
playvid(false);
|
||||
currentIndex = index;
|
||||
loadImage(currentIndex, function () {
|
||||
preloadNext(currentIndex);
|
||||
@@ -512,6 +529,26 @@ window.baguetteBox = (function () {
|
||||
return true;
|
||||
}
|
||||
|
||||
function vid() {
|
||||
return imagesElements[currentIndex].querySelector('video');
|
||||
}
|
||||
|
||||
function playvid(play) {
|
||||
if (vid())
|
||||
vid()[play ? 'play' : 'pause']();
|
||||
}
|
||||
|
||||
function playpause() {
|
||||
var v = vid();
|
||||
if (v)
|
||||
v[v.paused ? "play" : "pause"]();
|
||||
}
|
||||
|
||||
function relseek(sec) {
|
||||
if (vid())
|
||||
vid().currentTime += sec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the bounce animation
|
||||
* @param {('left'|'right')} direction - Direction of the movement
|
||||
@@ -534,6 +571,8 @@ window.baguetteBox = (function () {
|
||||
} else {
|
||||
slider.style.transform = 'translate3d(' + offset + ',0,0)';
|
||||
}
|
||||
playvid(false);
|
||||
playvid(true);
|
||||
}
|
||||
|
||||
function preloadNext(index) {
|
||||
@@ -566,6 +605,7 @@ window.baguetteBox = (function () {
|
||||
unbindEvents();
|
||||
clearCachedData();
|
||||
unbind(document, 'keydown', keyDownHandler);
|
||||
unbind(document, 'keyup', keyUpHandler);
|
||||
document.getElementsByTagName('body')[0].removeChild(ebi('baguetteBox-overlay'));
|
||||
data = {};
|
||||
currentGallery = [];
|
||||
@@ -577,6 +617,8 @@ window.baguetteBox = (function () {
|
||||
show: show,
|
||||
showNext: showNextImage,
|
||||
showPrevious: showPreviousImage,
|
||||
relseek: relseek,
|
||||
playpause: playpause,
|
||||
hide: hideOverlay,
|
||||
destroy: destroyPlugin
|
||||
};
|
||||
|
||||
@@ -1174,7 +1174,8 @@ html.light #tree::-webkit-scrollbar {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
#baguetteBox-overlay .full-image img {
|
||||
#baguetteBox-overlay .full-image img,
|
||||
#baguetteBox-overlay .full-image video {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
height: auto;
|
||||
@@ -1183,6 +1184,9 @@ html.light #tree::-webkit-scrollbar {
|
||||
vertical-align: middle;
|
||||
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
#baguetteBox-overlay .full-image video {
|
||||
background: #333;
|
||||
}
|
||||
#baguetteBox-overlay .full-image figcaption {
|
||||
display: block;
|
||||
position: absolute;
|
||||
|
||||
@@ -1756,7 +1756,7 @@ document.onkeydown = function (e) {
|
||||
if (e.ctrlKey || e.altKey || e.metaKey || e.isComposing)
|
||||
return;
|
||||
|
||||
var k = (e.code + ''), pos = -1, n;
|
||||
var k = e.code + '', pos = -1, n;
|
||||
|
||||
if (e.shiftKey && k != 'KeyA' && k != 'KeyD')
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user