mirror of
https://github.com/lrsjng/h5ai.git
synced 2025-05-30 06:55:16 -04:00
Clean preview code.
This commit is contained in:
parent
9e0b1698fc
commit
8a4ccd098c
10 changed files with 266 additions and 481 deletions
|
@ -1,4 +1,4 @@
|
|||
#pv-aud-audio {
|
||||
#pv-content-aud {
|
||||
.raised;
|
||||
|
||||
position: absolute;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pv-img-image {
|
||||
#pv-content-img {
|
||||
.raised;
|
||||
|
||||
@check-white: #f8f8f8;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pv-txt-text {
|
||||
#pv-content-txt {
|
||||
.raised;
|
||||
|
||||
max-width: 960px;
|
||||
|
@ -8,101 +8,27 @@
|
|||
padding: 8px;
|
||||
overflow: auto;
|
||||
|
||||
a, a:active, a:visited {
|
||||
color: #2080FF;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #68A9FF;
|
||||
}
|
||||
}
|
||||
|
||||
&.highlighted {
|
||||
|
||||
code {
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
a, a:active, a:visited {
|
||||
color: #2080FF;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #68A9FF;
|
||||
}
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.builtin {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string,
|
||||
.token.variable {
|
||||
color: #a67f59;
|
||||
background: hsla(0,0%,100%,.5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
}
|
||||
|
||||
&.markdown {
|
||||
font-size: 1.1em;
|
||||
padding: 8px 24px;
|
||||
|
||||
a, a:active, a:visited {
|
||||
color: #2080FF;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #68A9FF;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
color: #008200;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pv-vid-video {
|
||||
#pv-content-vid {
|
||||
.raised;
|
||||
|
||||
position: absolute;
|
||||
|
@ -7,7 +7,7 @@
|
|||
max-height: 100%;
|
||||
}
|
||||
|
||||
#pv-vid-video:-webkit-full-screen {
|
||||
#pv-content-vid:-webkit-full-screen {
|
||||
top: auto !important;
|
||||
left: auto !important;
|
||||
}
|
||||
|
|
|
@ -1,104 +1,57 @@
|
|||
const {each, includes, compact, dom} = require('../../util');
|
||||
const {win} = require('../../globals');
|
||||
const {each, dom} = require('../../util');
|
||||
const event = require('../../core/event');
|
||||
const format = require('../../core/format');
|
||||
const allsettings = require('../../core/settings');
|
||||
const preview = require('./preview');
|
||||
const previewX = require('./preview-x');
|
||||
|
||||
const settings = Object.assign({
|
||||
enabled: false,
|
||||
types: []
|
||||
}, allsettings['preview-aud']);
|
||||
const tpl = '<audio id="pv-content-aud"/>';
|
||||
|
||||
const preloadAudio = (src, callback) => {
|
||||
const $audio = dom('<audio/>')
|
||||
.on('loadedmetadata', () => callback($audio))
|
||||
.attr('autoplay', 'autoplay')
|
||||
.attr('controls', 'controls')
|
||||
.attr('src', src);
|
||||
};
|
||||
let state;
|
||||
|
||||
const onAdjustSize = () => {
|
||||
const $audio = dom('#pv-aud-audio');
|
||||
if (!$audio.length) {
|
||||
const el = dom('#pv-content-aud')[0];
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elContent = dom('#pv-content')[0];
|
||||
const contentW = elContent.offsetWidth;
|
||||
const contentH = elContent.offsetHeight;
|
||||
const audioW = $audio[0].offsetWidth;
|
||||
const audioH = $audio[0].offsetHeight;
|
||||
const elW = el.offsetWidth;
|
||||
const elH = el.offsetHeight;
|
||||
|
||||
$audio.css({
|
||||
left: (contentW - audioW) * 0.5 + 'px',
|
||||
top: (contentH - audioH) * 0.5 + 'px'
|
||||
dom(el).css({
|
||||
left: (contentW - elW) * 0.5 + 'px',
|
||||
top: (contentH - elH) * 0.5 + 'px'
|
||||
});
|
||||
|
||||
preview.setLabels([
|
||||
state.item.label,
|
||||
format.formatDate(dom('#pv-content-aud')[0].duration * 1000, 'm:ss')
|
||||
]);
|
||||
};
|
||||
|
||||
const loadAudio = item => {
|
||||
return new Promise(resolve => {
|
||||
const $el = dom(tpl)
|
||||
.on('loadedmetadata', () => resolve($el))
|
||||
// .attr('autoplay', 'autoplay')
|
||||
.attr('controls', 'controls')
|
||||
.attr('src', item.absHref);
|
||||
});
|
||||
// .then(x => new Promise(resolve => setTimeout(() => resolve(x), 1000)));
|
||||
};
|
||||
|
||||
const onEnter = (items, idx) => {
|
||||
const currentItems = items;
|
||||
let currentIdx = idx;
|
||||
let currentItem = items[idx];
|
||||
let spinnerTimeout;
|
||||
|
||||
const updateMeta = () => {
|
||||
preview.setLabels([
|
||||
currentItem.label,
|
||||
format.formatDate(dom('#pv-aud-audio')[0].duration * 1000, 'm:ss')
|
||||
]);
|
||||
|
||||
preview.setIndex(currentIdx + 1, currentItems.length);
|
||||
preview.setRawLink(currentItem.absHref);
|
||||
};
|
||||
|
||||
const onReady = $preloadedContent => {
|
||||
win.clearTimeout(spinnerTimeout);
|
||||
preview.showSpinner(false);
|
||||
|
||||
dom('#pv-content')
|
||||
.hide()
|
||||
.clr()
|
||||
.app($preloadedContent.attr('id', 'pv-aud-audio'))
|
||||
.show();
|
||||
|
||||
updateMeta();
|
||||
onAdjustSize();
|
||||
};
|
||||
|
||||
const onIdxChange = rel => {
|
||||
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
|
||||
currentItem = currentItems[currentIdx];
|
||||
|
||||
spinnerTimeout = win.setTimeout(() => preview.showSpinner(true), 200);
|
||||
|
||||
if (dom('#pv-aud-audio').length) {
|
||||
dom('#pv-aud-audio')[0].pause();
|
||||
}
|
||||
preloadAudio(currentItem.absHref, onReady);
|
||||
};
|
||||
|
||||
onIdxChange(0);
|
||||
preview.setOnIndexChange(onIdxChange);
|
||||
preview.setOnAdjustSize(onAdjustSize);
|
||||
preview.enter();
|
||||
};
|
||||
|
||||
const initItem = item => {
|
||||
if (item.$view && includes(settings.types, item.type)) {
|
||||
item.$view.find('a').on('click', ev => {
|
||||
ev.preventDefault();
|
||||
|
||||
const matchedItems = compact(dom('#items .item').map(el => {
|
||||
const matchedItem = el._item;
|
||||
return includes(settings.types, matchedItem.type) ? matchedItem : null;
|
||||
}));
|
||||
|
||||
onEnter(matchedItems, matchedItems.indexOf(item));
|
||||
});
|
||||
}
|
||||
state = previewX.pvState(items, idx, loadAudio, onAdjustSize);
|
||||
};
|
||||
|
||||
const initItem = previewX.initItemFn(settings.types, onEnter);
|
||||
const onViewChanged = added => each(added, initItem);
|
||||
|
||||
const init = () => {
|
||||
|
|
|
@ -1,27 +1,47 @@
|
|||
const {each, includes, compact, dom} = require('../../util');
|
||||
const {win} = require('../../globals');
|
||||
const {each, dom} = require('../../util');
|
||||
const server = require('../../server');
|
||||
const event = require('../../core/event');
|
||||
const allsettings = require('../../core/settings');
|
||||
const preview = require('./preview');
|
||||
const previewX = require('./preview-x');
|
||||
|
||||
const settings = Object.assign({
|
||||
enabled: false,
|
||||
size: null,
|
||||
types: []
|
||||
}, allsettings['preview-img']);
|
||||
const spinnerThreshold = 200;
|
||||
let spinnerTimeoutId;
|
||||
let currentItems;
|
||||
let currentIdx;
|
||||
let currentItem;
|
||||
const tpl = '<img id="pv-content-img"/>';
|
||||
|
||||
let state;
|
||||
|
||||
const requestSample = href => {
|
||||
if (!settings.size) {
|
||||
return Promise.resolve(href);
|
||||
const onAdjustSize = () => {
|
||||
const el = dom('#pv-content-img')[0];
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elContent = dom('#pv-content')[0];
|
||||
const contentW = elContent.offsetWidth;
|
||||
const contentH = elContent.offsetHeight;
|
||||
const elW = el.offsetWidth;
|
||||
const elH = el.offsetHeight;
|
||||
|
||||
dom(el).css({
|
||||
left: (contentW - elW) * 0.5 + 'px',
|
||||
top: (contentH - elH) * 0.5 + 'px'
|
||||
});
|
||||
|
||||
const labels = [state.item.label];
|
||||
if (!settings.size) {
|
||||
const elNW = el.naturalWidth;
|
||||
const elNH = el.naturalHeight;
|
||||
labels.push(String(elNW) + 'x' + String(elNH));
|
||||
labels.push(String((100 * elW / elNW).toFixed(0)) + '%');
|
||||
}
|
||||
preview.setLabels(labels);
|
||||
};
|
||||
|
||||
const requestSample = href => {
|
||||
return server.request({
|
||||
action: 'get',
|
||||
thumbs: [{
|
||||
|
@ -35,107 +55,25 @@ const requestSample = href => {
|
|||
});
|
||||
};
|
||||
|
||||
const preloadImage = (item, callback) => {
|
||||
return requestSample(item.absHref).then(src => {
|
||||
const $img = dom('<img/>')
|
||||
.on('load', () => {
|
||||
callback(item, $img);
|
||||
|
||||
// for testing
|
||||
// win.setTimeout(() => callback(item, $img), 1000);
|
||||
})
|
||||
.attr('src', src);
|
||||
});
|
||||
};
|
||||
|
||||
const onAdjustSize = () => {
|
||||
const $content = dom('#pv-content');
|
||||
const $img = dom('#pv-img-image');
|
||||
|
||||
const contentW = $content[0].offsetWidth;
|
||||
const contentH = $content[0].offsetHeight;
|
||||
const imgW = ($img[0] || {}).offsetWidth;
|
||||
const imgH = ($img[0] || {}).offsetHeight;
|
||||
|
||||
if ($img.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$img.css({
|
||||
left: (contentW - imgW) * 0.5 + 'px',
|
||||
top: (contentH - imgH) * 0.5 + 'px'
|
||||
});
|
||||
|
||||
const labels = [currentItem.label];
|
||||
if (!settings.size) {
|
||||
const imgNW = $img[0].naturalWidth;
|
||||
const imgNH = $img[0].naturalHeight;
|
||||
labels.push(String(imgNW) + 'x' + String(imgNH));
|
||||
labels.push(String((100 * imgW / imgNW).toFixed(0)) + '%');
|
||||
}
|
||||
preview.setLabels(labels);
|
||||
};
|
||||
|
||||
const onIdxChange = rel => {
|
||||
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
|
||||
currentItem = currentItems[currentIdx];
|
||||
|
||||
preview.setLabels([currentItem.label]);
|
||||
preview.setIndex(currentIdx + 1, currentItems.length);
|
||||
preview.setRawLink(currentItem.absHref);
|
||||
|
||||
dom('#pv-content').hide();
|
||||
if (preview.isSpinnerVisible()) {
|
||||
preview.showSpinner(true, currentItem.thumbSquare);
|
||||
} else {
|
||||
win.clearTimeout(spinnerTimeoutId);
|
||||
spinnerTimeoutId = win.setTimeout(() => {
|
||||
preview.showSpinner(true, currentItem.thumbSquare);
|
||||
}, spinnerThreshold);
|
||||
}
|
||||
|
||||
preloadImage(currentItem, (item, preloadedImage) => {
|
||||
if (item !== currentItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
win.clearTimeout(spinnerTimeoutId);
|
||||
preview.showSpinner(false);
|
||||
dom('#pv-content')
|
||||
.clr()
|
||||
.app(dom(preloadedImage).attr('id', 'pv-img-image'))
|
||||
.show();
|
||||
onAdjustSize();
|
||||
});
|
||||
const loadImage = item => {
|
||||
return Promise.resolve(item.absHref)
|
||||
.then(href => {
|
||||
return settings.size ? requestSample(href) : href;
|
||||
})
|
||||
.then(href => new Promise(resolve => {
|
||||
const $img = dom(tpl)
|
||||
.on('load', () => resolve($img))
|
||||
.attr('src', href);
|
||||
}));
|
||||
// .then(x => new Promise(resolve => setTimeout(() => resolve(x), 1000)));
|
||||
};
|
||||
|
||||
const onEnter = (items, idx) => {
|
||||
currentItems = items;
|
||||
currentIdx = idx;
|
||||
preview.setOnIndexChange(onIdxChange);
|
||||
preview.setOnAdjustSize(onAdjustSize);
|
||||
preview.enter();
|
||||
onIdxChange(0);
|
||||
state = previewX.pvState(items, idx, loadImage, onAdjustSize);
|
||||
};
|
||||
|
||||
const initItem = item => {
|
||||
if (item.$view && includes(settings.types, item.type)) {
|
||||
item.$view.find('a').on('click', ev => {
|
||||
ev.preventDefault();
|
||||
|
||||
const matchedItems = compact(dom('#items .item').map(el => {
|
||||
const matchedItem = el._item;
|
||||
return includes(settings.types, matchedItem.type) ? matchedItem : null;
|
||||
}));
|
||||
|
||||
onEnter(matchedItems, matchedItems.indexOf(item));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onViewChanged = added => {
|
||||
each(added, initItem);
|
||||
};
|
||||
const initItem = previewX.initItemFn(settings.types, onEnter);
|
||||
const onViewChanged = added => each(added, initItem);
|
||||
|
||||
const init = () => {
|
||||
if (!settings.enabled) {
|
||||
|
@ -145,5 +83,4 @@ const init = () => {
|
|||
event.sub('view.changed', onViewChanged);
|
||||
};
|
||||
|
||||
|
||||
init();
|
||||
|
|
|
@ -1,26 +1,39 @@
|
|||
const lolight = require('lolight');
|
||||
const marked = require('marked');
|
||||
const {each, keys, includes, compact, dom} = require('../../util');
|
||||
const {each, keys, dom} = require('../../util');
|
||||
const {win} = require('../../globals');
|
||||
const event = require('../../core/event');
|
||||
const allsettings = require('../../core/settings');
|
||||
const preview = require('./preview');
|
||||
|
||||
const previewX = require('./preview-x');
|
||||
|
||||
const XHR = win.XMLHttpRequest;
|
||||
const settings = Object.assign({
|
||||
enabled: false,
|
||||
styles: {}
|
||||
}, allsettings['preview-txt']);
|
||||
const tplText = '<pre id="pv-txt-text" class="highlighted"/>';
|
||||
const tplMarkdown = '<div id="pv-txt-text" class="markdown"/>';
|
||||
const spinnerThreshold = 200;
|
||||
const tplText = '<pre id="pv-content-txt" class="highlighted"></pre>';
|
||||
const tplMarkdown = '<div id="pv-content-txt" class="markdown"></div>';
|
||||
|
||||
let spinnerTimeoutId;
|
||||
let currentItems;
|
||||
let currentIdx;
|
||||
let currentItem;
|
||||
let state;
|
||||
|
||||
const onAdjustSize = () => {
|
||||
const el = dom('#pv-content-txt')[0];
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elContent = dom('#pv-content')[0];
|
||||
|
||||
dom(el).css({
|
||||
height: elContent.offsetHeight - 16 + 'px'
|
||||
});
|
||||
|
||||
preview.setLabels([
|
||||
state.item.label,
|
||||
state.item.size + ' bytes'
|
||||
]);
|
||||
};
|
||||
|
||||
const requestTextContent = href => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -28,7 +41,7 @@ const requestTextContent = href => {
|
|||
const callback = () => {
|
||||
if (xhr.readyState === XHR.DONE) {
|
||||
try {
|
||||
resolve(xhr.responseText);
|
||||
resolve(xhr.responseText || '');
|
||||
} catch (err) {
|
||||
reject(String(err));
|
||||
}
|
||||
|
@ -41,104 +54,37 @@ const requestTextContent = href => {
|
|||
});
|
||||
};
|
||||
|
||||
const preloadText = (item, callback) => {
|
||||
requestTextContent(item.absHref)
|
||||
const loadText = item => {
|
||||
return requestTextContent(item.absHref)
|
||||
.catch(err => '[ajax error] ' + err)
|
||||
.then(content => {
|
||||
callback(item, content);
|
||||
const style = settings.styles[state.item.type];
|
||||
let $text;
|
||||
|
||||
// for testing
|
||||
// win.setTimeout(() => callback(item, content), 1000);
|
||||
})
|
||||
.catch(err => callback(item, '[ajax error] ' + err));
|
||||
};
|
||||
if (style === 1) {
|
||||
$text = dom(tplText).text(content);
|
||||
} else if (style === 2) {
|
||||
$text = dom(tplMarkdown).html(marked(content));
|
||||
} else if (style === 3) {
|
||||
$text = dom(tplText);
|
||||
const $code = dom('<code/>').text(content).appTo($text);
|
||||
win.setTimeout(() => {
|
||||
lolight.el($code[0]);
|
||||
}, content.length < 20000 ? 0 : 500);
|
||||
} else {
|
||||
$text = dom(tplMarkdown).text(content);
|
||||
}
|
||||
|
||||
const onAdjustSize = () => {
|
||||
const $content = dom('#pv-content');
|
||||
const $text = dom('#pv-txt-text');
|
||||
|
||||
if ($text.length) {
|
||||
$text[0].style.height = $content[0].offsetHeight - 16 + 'px';
|
||||
}
|
||||
};
|
||||
|
||||
const onIdxChange = rel => {
|
||||
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
|
||||
currentItem = currentItems[currentIdx];
|
||||
|
||||
preview.setLabels([
|
||||
currentItem.label,
|
||||
String(currentItem.size) + ' bytes'
|
||||
]);
|
||||
preview.setIndex(currentIdx + 1, currentItems.length);
|
||||
preview.setRawLink(currentItem.absHref);
|
||||
|
||||
dom('#pv-content').hide();
|
||||
if (preview.isSpinnerVisible()) {
|
||||
preview.showSpinner(true, currentItem.icon);
|
||||
} else {
|
||||
win.clearTimeout(spinnerTimeoutId);
|
||||
spinnerTimeoutId = win.setTimeout(() => {
|
||||
preview.showSpinner(true, currentItem.icon);
|
||||
}, spinnerThreshold);
|
||||
}
|
||||
|
||||
preloadText(currentItem, (item, textContent) => {
|
||||
if (item !== currentItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
const style = settings.styles[currentItem.type];
|
||||
let $text;
|
||||
|
||||
if (style === 1) {
|
||||
$text = dom(tplText).text(textContent);
|
||||
} else if (style === 2) {
|
||||
$text = dom(tplMarkdown).html(marked(textContent));
|
||||
} else if (style === 3) {
|
||||
$text = dom(tplText);
|
||||
const $code = dom('<code/>').text(textContent).appTo($text);
|
||||
win.setTimeout(() => {
|
||||
lolight.el($code[0]);
|
||||
}, textContent.length < 20000 ? 0 : 500);
|
||||
} else {
|
||||
$text = dom(tplMarkdown).text(textContent);
|
||||
}
|
||||
|
||||
win.clearTimeout(spinnerTimeoutId);
|
||||
preview.showSpinner(false);
|
||||
dom('#pv-content')
|
||||
.clr()
|
||||
.app($text)
|
||||
.show();
|
||||
onAdjustSize();
|
||||
});
|
||||
return $text;
|
||||
});
|
||||
// .then(x => new Promise(resolve => setTimeout(() => resolve(x), 1000)));
|
||||
};
|
||||
|
||||
const onEnter = (items, idx) => {
|
||||
currentItems = items;
|
||||
currentIdx = idx;
|
||||
currentItem = items[idx];
|
||||
preview.setOnIndexChange(onIdxChange);
|
||||
preview.setOnAdjustSize(onAdjustSize);
|
||||
preview.enter();
|
||||
onIdxChange(0);
|
||||
};
|
||||
|
||||
const initItem = item => {
|
||||
if (item.$view && includes(keys(settings.styles), item.type)) {
|
||||
item.$view.find('a').on('click', ev => {
|
||||
ev.preventDefault();
|
||||
|
||||
const matchedItems = compact(dom('#items .item').map(el => {
|
||||
const matchedItem = el._item;
|
||||
return includes(keys(settings.styles), matchedItem.type) ? matchedItem : null;
|
||||
}));
|
||||
|
||||
onEnter(matchedItems, matchedItems.indexOf(item));
|
||||
});
|
||||
}
|
||||
state = previewX.pvState(items, idx, loadText, onAdjustSize);
|
||||
};
|
||||
|
||||
const initItem = previewX.initItemFn(keys(settings.styles), onEnter);
|
||||
const onViewChanged = added => each(added, initItem);
|
||||
|
||||
const init = () => {
|
||||
|
@ -149,5 +95,4 @@ const init = () => {
|
|||
event.sub('view.changed', onViewChanged);
|
||||
};
|
||||
|
||||
|
||||
init();
|
||||
|
|
|
@ -1,112 +1,61 @@
|
|||
const {each, includes, compact, dom} = require('../../util');
|
||||
const {win} = require('../../globals');
|
||||
const {each, dom} = require('../../util');
|
||||
const event = require('../../core/event');
|
||||
const allsettings = require('../../core/settings');
|
||||
const preview = require('./preview');
|
||||
const previewX = require('./preview-x');
|
||||
|
||||
const settings = Object.assign({
|
||||
enabled: false,
|
||||
types: []
|
||||
}, allsettings['preview-vid']);
|
||||
const tpl = '<video id="pv-content-vid"/>';
|
||||
|
||||
const preloadVideo = (src, callback) => {
|
||||
const $video = dom('<video/>')
|
||||
.on('loadedmetadata', () => {
|
||||
callback($video);
|
||||
// win.setTimeout(() => {callback($video);}, 1000); // for testing
|
||||
})
|
||||
.attr('autoplay', 'autoplay')
|
||||
.attr('controls', 'controls')
|
||||
.attr('src', src);
|
||||
let state;
|
||||
|
||||
const onAdjustSize = () => {
|
||||
const el = dom('#pv-content-vid')[0];
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elContent = dom('#pv-content')[0];
|
||||
const contentW = elContent.offsetWidth;
|
||||
const contentH = elContent.offsetHeight;
|
||||
const elW = el.offsetWidth;
|
||||
const elH = el.offsetHeight;
|
||||
|
||||
dom(el).css({
|
||||
left: (contentW - elW) * 0.5 + 'px',
|
||||
top: (contentH - elH) * 0.5 + 'px'
|
||||
});
|
||||
|
||||
const elVW = el.videoWidth;
|
||||
const elVH = el.videoHeight;
|
||||
|
||||
preview.setLabels([
|
||||
state.item.label,
|
||||
String(elVW) + 'x' + String(elVH),
|
||||
String((100 * elW / elVW).toFixed(0)) + '%'
|
||||
]);
|
||||
};
|
||||
|
||||
const loadVideo = item => {
|
||||
return new Promise(resolve => {
|
||||
const $el = dom(tpl)
|
||||
.on('loadedmetadata', () => resolve($el))
|
||||
// .attr('autoplay', 'autoplay')
|
||||
.attr('controls', 'controls')
|
||||
.attr('src', item.absHref);
|
||||
});
|
||||
// .then(x => new Promise(resolve => setTimeout(() => resolve(x), 1000)));
|
||||
};
|
||||
|
||||
const onEnter = (items, idx) => {
|
||||
const currentItems = items;
|
||||
let currentIdx = idx;
|
||||
let currentItem = items[idx];
|
||||
|
||||
const onAdjustSize = () => {
|
||||
const $content = dom('#pv-content');
|
||||
const $vid = dom('#pv-vid-video');
|
||||
|
||||
const contentW = $content[0].offsetWidth;
|
||||
const contentH = $content[0].offsetHeight;
|
||||
const vidW = ($vid[0] || {}).offsetWidth;
|
||||
const vidH = ($vid[0] || {}).offsetHeight;
|
||||
|
||||
if ($vid.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vid.css({
|
||||
left: (contentW - vidW) * 0.5 + 'px',
|
||||
top: (contentH - vidH) * 0.5 + 'px'
|
||||
});
|
||||
|
||||
const vidVW = $vid[0].videoWidth;
|
||||
const vidVH = $vid[0].videoHeight;
|
||||
|
||||
preview.setLabels([
|
||||
currentItem.label,
|
||||
String(vidVW) + 'x' + String(vidVH),
|
||||
String((100 * vidW / vidVW).toFixed(0)) + '%'
|
||||
]);
|
||||
};
|
||||
|
||||
const onIdxChange = rel => {
|
||||
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
|
||||
currentItem = currentItems[currentIdx];
|
||||
|
||||
const spinnerTimeout = win.setTimeout(() => preview.showSpinner(true), 200);
|
||||
|
||||
if (dom('#pv-vid-video').length) {
|
||||
dom('#pv-vid-video')[0].pause();
|
||||
}
|
||||
|
||||
const updateMeta = () => {
|
||||
onAdjustSize();
|
||||
preview.setIndex(currentIdx + 1, currentItems.length);
|
||||
preview.setRawLink(currentItem.absHref);
|
||||
};
|
||||
|
||||
const onReady = $preloadedContent => {
|
||||
win.clearTimeout(spinnerTimeout);
|
||||
preview.showSpinner(false);
|
||||
|
||||
dom('#pv-content')
|
||||
.clr()
|
||||
.app($preloadedContent.attr('id', 'pv-vid-video'))
|
||||
.show();
|
||||
updateMeta();
|
||||
};
|
||||
|
||||
preloadVideo(currentItem.absHref, onReady);
|
||||
};
|
||||
|
||||
onIdxChange(0);
|
||||
preview.setOnIndexChange(onIdxChange);
|
||||
preview.setOnAdjustSize(onAdjustSize);
|
||||
preview.enter();
|
||||
state = previewX.pvState(items, idx, loadVideo, onAdjustSize);
|
||||
};
|
||||
|
||||
const initItem = item => {
|
||||
if (item.$view && includes(settings.types, item.type)) {
|
||||
item.$view.find('a').on('click', ev => {
|
||||
ev.preventDefault();
|
||||
|
||||
const matchedItems = compact(dom('#items .item').map(el => {
|
||||
const matchedItem = el._item;
|
||||
return includes(settings.types, matchedItem.type) ? matchedItem : null;
|
||||
}));
|
||||
|
||||
onEnter(matchedItems, matchedItems.indexOf(item));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onViewChanged = added => {
|
||||
each(added, initItem);
|
||||
};
|
||||
const initItem = previewX.initItemFn(settings.types, onEnter);
|
||||
const onViewChanged = added => each(added, initItem);
|
||||
|
||||
const init = () => {
|
||||
if (!settings.enabled) {
|
||||
|
|
68
src/_h5ai/public/js/lib/ext/preview/preview-x.js
Normal file
68
src/_h5ai/public/js/lib/ext/preview/preview-x.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
const {includes, compact, dom} = require('../../util');
|
||||
const preview = require('./preview');
|
||||
|
||||
const initItemFn = (types, onEnter) => {
|
||||
return item => {
|
||||
if (item.$view && includes(types, item.type)) {
|
||||
item.$view.find('a').on('click', ev => {
|
||||
ev.preventDefault();
|
||||
|
||||
const matchedItems = compact(dom('#items .item').map(el => {
|
||||
const matchedItem = el._item;
|
||||
return includes(types, matchedItem.type) ? matchedItem : null;
|
||||
}));
|
||||
|
||||
onEnter(matchedItems, matchedItems.indexOf(item));
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const pvState = (items, idx = 0, load, adjust) => {
|
||||
const inst = Object.assign(Object.create(pvState.prototype), {items, load, adjust});
|
||||
preview.setOnAdjustSize(adjust);
|
||||
preview.setOnIndexChange(delta => inst.moveIdx(delta));
|
||||
preview.enter();
|
||||
inst.setIdx(idx);
|
||||
return inst;
|
||||
};
|
||||
|
||||
pvState.prototype = {
|
||||
constructor: pvState,
|
||||
|
||||
setIdx(idx) {
|
||||
this.idx = (idx + this.items.length) % this.items.length;
|
||||
this.item = this.items[this.idx];
|
||||
preview.setLabels([this.item.label]);
|
||||
preview.setIndex(this.idx + 1, this.items.length);
|
||||
preview.setRawLink(this.item.absHref);
|
||||
this.loadContent(this.item);
|
||||
},
|
||||
|
||||
moveIdx(delta) {
|
||||
this.setIdx(this.idx + delta);
|
||||
},
|
||||
|
||||
loadContent(item) {
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
dom('#pv-content').hide().clr();
|
||||
preview.showSpinner(true, item.thumbSquare || item.icon, 200);
|
||||
})
|
||||
.then(() => this.load(item))
|
||||
.then($content => {
|
||||
if (item !== this.item) {
|
||||
return;
|
||||
}
|
||||
preview.showSpinner(false);
|
||||
|
||||
dom('#pv-content').clr().app($content).show();
|
||||
this.adjust();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initItemFn,
|
||||
pvState
|
||||
};
|
|
@ -31,7 +31,7 @@ let userAliveTimeoutId = null;
|
|||
let onIndexChange = null;
|
||||
let onAdjustSize = null;
|
||||
let spinnerVisible = false;
|
||||
|
||||
let spinnerTimeoutId;
|
||||
|
||||
const adjustSize = () => {
|
||||
const docEl = win.document.documentElement;
|
||||
|
@ -61,7 +61,7 @@ const adjustSize = () => {
|
|||
}
|
||||
|
||||
if (isFn(onAdjustSize)) {
|
||||
onAdjustSize(1);
|
||||
onAdjustSize();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -167,22 +167,29 @@ const setOnAdjustSize = fn => {
|
|||
onAdjustSize = fn;
|
||||
};
|
||||
|
||||
const showSpinner = (show, src) => {
|
||||
const showSpinner = (show, src, delay) => {
|
||||
win.clearTimeout(spinnerTimeoutId);
|
||||
const $spinner = dom('#pv-spinner');
|
||||
|
||||
if (show) {
|
||||
const $back = $spinner.find('.back');
|
||||
if (src) {
|
||||
$back.attr('src', src).show();
|
||||
} else {
|
||||
$back.hide();
|
||||
}
|
||||
spinnerVisible = true;
|
||||
$spinner.show();
|
||||
} else {
|
||||
if (!show) {
|
||||
spinnerVisible = false;
|
||||
$spinner.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!spinnerVisible && delay) {
|
||||
spinnerTimeoutId = win.setTimeout(() => showSpinner(true, src), delay);
|
||||
return;
|
||||
}
|
||||
|
||||
const $back = $spinner.find('.back');
|
||||
if (src) {
|
||||
$back.attr('src', src).show();
|
||||
} else {
|
||||
$back.hide();
|
||||
}
|
||||
spinnerVisible = true;
|
||||
$spinner.show();
|
||||
};
|
||||
|
||||
const isSpinnerVisible = () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue