wip
This commit is contained in:
commit
4712047015
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -37,8 +37,6 @@ jQuery(document).ready(function ($) {
|
||||
'padding-top': '0px'
|
||||
});
|
||||
|
||||
|
||||
|
||||
function createElement() {
|
||||
let screen = $('#screen');
|
||||
let screenWidth = screen.width();
|
||||
@ -57,7 +55,7 @@ jQuery(document).ready(function ($) {
|
||||
y = Math.round(Math.max(0, Math.min(y, screenHeight - elementHeight)));
|
||||
|
||||
let elementId = elementCounter++;
|
||||
let element = $('<div class="element" id="element-' + elementId + '" data-id="' + elementId + '"><button>Button</button></div>');
|
||||
let element = $('<div class="element" id="element-' + elementId + '" data-id="' + elementId + '"><i class="fa fa-cog"></i></div>');
|
||||
// let element = $('<div class="element" id="' + elementId + '"><button>Button</button><div class="rotate-handle"></div></div>');
|
||||
|
||||
element.css({
|
||||
@ -106,6 +104,8 @@ jQuery(document).ready(function ($) {
|
||||
setTimeout(function() {
|
||||
focusElement(element);
|
||||
}, 10);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
$(document).on('click', '.element-list-item', function(){
|
||||
@ -113,7 +113,9 @@ jQuery(document).ready(function ($) {
|
||||
})
|
||||
|
||||
$(document).on('click', '.remove-element', function(){
|
||||
if (confirm(l.js_common_are_you_sure)) {
|
||||
removeElementById($(this).attr('data-id'));
|
||||
}
|
||||
})
|
||||
|
||||
function removeElementById(elementId) {
|
||||
@ -122,8 +124,16 @@ jQuery(document).ready(function ($) {
|
||||
}
|
||||
|
||||
function addElementToList(elementId) {
|
||||
let listItem = $('<div class="element-list-item" data-id="' + elementId + '">Element ' + elementId + ' <button type="button" class="remove-element" data-id="' + elementId + '">remove</button></div>');
|
||||
$('#elementList').append(listItem);
|
||||
const listItem = `<div class="element-list-item" data-id="__ID__">
|
||||
Element __ID__
|
||||
<button type="button" class="btn btn-neutral configure-element content-explr-picker" data-id="__ID__">
|
||||
<i class="fa fa-cog"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-naked remove-element" data-id="__ID__">
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</div>`;
|
||||
$('#elementList').append($(listItem.replace(/__ID__/g, elementId)));
|
||||
updateZIndexes();
|
||||
}
|
||||
|
||||
@ -145,9 +155,11 @@ jQuery(document).ready(function ($) {
|
||||
function updateForm(element) {
|
||||
if (!element) {
|
||||
$('form#elementForm input').val('').prop('disabled', true);
|
||||
$('.form-element-properties').addClass('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
$('.form-element-properties').removeClass('hidden');
|
||||
$('form#elementForm input').prop('disabled', false);
|
||||
|
||||
let offset = element.position();
|
||||
@ -158,6 +170,8 @@ jQuery(document).ready(function ($) {
|
||||
$('#elem-width').val(element.width());
|
||||
$('#elem-height').val(element.height());
|
||||
}
|
||||
|
||||
$(element).find('i').css('font-size', Math.min(element.width(), element.height()) / 3);
|
||||
/*
|
||||
let rotation = element.css('transform');
|
||||
let values = rotation.split('(')[1].split(')')[0].split(',');
|
||||
@ -201,13 +215,19 @@ jQuery(document).ready(function ($) {
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '#addElement', function () {
|
||||
createElement();
|
||||
});
|
||||
// $(document).on('click', '#addElement', function () {
|
||||
// createElement();
|
||||
// });
|
||||
|
||||
$(document).on('click', '#removeAllElements', function () {
|
||||
if (confirm(l.js_common_are_you_sure)) {
|
||||
$('.element, .element-list-item').remove();
|
||||
updateZIndexes();
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('dblclick', '.element', function (e) {
|
||||
$('.content-explr-picker[data-id='+$(this).attr('data-id')+']').click();
|
||||
});
|
||||
|
||||
$(document).on('mousedown', function (e) {
|
||||
@ -220,7 +240,7 @@ jQuery(document).ready(function ($) {
|
||||
if (!keepFocusedElement) {
|
||||
unfocusElements();
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
$(document).on('click', '#presetGrid2x2', function () {
|
||||
let screenWidth = $('#screen').width();
|
||||
@ -252,6 +272,22 @@ jQuery(document).ready(function ($) {
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.content-explr-picker', function () {
|
||||
const elementId = $(this).attr('data-id');
|
||||
const isNew = !elementId;
|
||||
const $element = isNew ? $(createElement()) : $('#element-'+elementId);
|
||||
|
||||
showPickers('modal-content-explr-picker', function (content) {
|
||||
console.log(content);
|
||||
$element.attr('data-content-id', content.id);
|
||||
$element.attr('data-content-name', content.name);
|
||||
$element.attr('data-content-type', content.type);
|
||||
console.log($element)
|
||||
$element.find('i').get(0).classList = ['fa', content.classIcon, content.classColor].join(' ');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
function updateZIndexes() {
|
||||
const zindex = $('.element-list-item').length + 1;
|
||||
$('.element-list-item').each(function(index) {
|
||||
@ -266,6 +302,5 @@ jQuery(document).ready(function ($) {
|
||||
}
|
||||
});
|
||||
|
||||
createElement();
|
||||
updateForm(null);
|
||||
$('#presetGrid2x2').click();
|
||||
});
|
||||
|
||||
@ -155,8 +155,6 @@ form {
|
||||
color: $gscale5;
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
border-bottom: 1px solid $gscale3;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
@ -167,11 +165,8 @@ form {
|
||||
|
||||
&.disabled,
|
||||
&[disabled] {
|
||||
border: none;
|
||||
background: $gscale0;
|
||||
border-radius: $baseRadius;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,14 +45,18 @@
|
||||
|
||||
.element {
|
||||
position: absolute !important;
|
||||
background-color: #f0f0f0;
|
||||
outline: 1px solid rgba($black, .5);
|
||||
background-color: $gkscaleE;
|
||||
outline: 1px solid $gkscaleC;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&.focused {
|
||||
border: none;
|
||||
outline: 2px solid blue;
|
||||
outline: 2px solid $seaBlue;
|
||||
z-index: 89 !important;
|
||||
|
||||
.ui-resizable-handle {
|
||||
@ -60,6 +64,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 20px;
|
||||
color: $gkscaleC;
|
||||
&.fa-cog {
|
||||
text-shadow: 0 -2px $gkscaleB, 0 0px 2px $gkscaleB;
|
||||
}
|
||||
}
|
||||
|
||||
.rotate-handle {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
@ -72,8 +84,8 @@
|
||||
}
|
||||
|
||||
.ui-resizable-handle {
|
||||
background: black;
|
||||
border: 1px solid #000;
|
||||
background: $gkscaleA;
|
||||
border: 1px solid $gkscale5;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
z-index: 90;
|
||||
@ -145,25 +157,61 @@
|
||||
|
||||
|
||||
.form-element-properties {
|
||||
margin-left: 20px;
|
||||
padding: 10px;
|
||||
background-color: #f9f9f9;
|
||||
border: 1px solid #ccc;
|
||||
flex: 1;
|
||||
align-self: stretch;
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
label,
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: $gscaleD;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid $gscale2;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 10px;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
||||
label {
|
||||
flex-grow: 1;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.widget {
|
||||
flex-grow: 1;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin: 0;
|
||||
|
||||
input {
|
||||
margin-bottom: 10px;
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
|
||||
&[disabled] {
|
||||
padding: 8px 0 5px 8px;
|
||||
border: 1px solid rgba(255,255,255,.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elementList {
|
||||
h3 {
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -110,7 +110,23 @@ When you run the browser yourself, don't forget to use these flags for chromium
|
||||
```bash
|
||||
# chromium or chromium-browser or even chrome
|
||||
# replace http://localhost:5000 with your obscreen-studio instance url
|
||||
chromium --disable-features=Translate --ignore-certificate-errors --disable-web-security --disable-restore-session-state --autoplay-policy=no-user-gesture-required --start-maximized --allow-running-insecure-content --remember-cert-error-decisions --noerrdialogs --kiosk --incognito --window-position=0,0 --window-size=1920,1080 --display=:0 http://localhost:5000
|
||||
chromium \
|
||||
--disk-cache-size=2147483648 \
|
||||
--disable-features=Translate \
|
||||
--ignore-certificate-errors \
|
||||
--disable-web-security \
|
||||
--disable-restore-session-state \
|
||||
--autoplay-policy=no-user-gesture-required \
|
||||
--start-maximized \
|
||||
--allow-running-insecure-content \
|
||||
--remember-cert-error-decisions \
|
||||
--noerrdialogs \
|
||||
--kiosk \
|
||||
--incognito \
|
||||
--window-position=0,0 \
|
||||
--window-size=1920,1080 \
|
||||
--display=:0 \
|
||||
http://localhost:5000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@ -118,7 +118,23 @@ When you run the browser yourself, don't forget to use these flags for chromium
|
||||
```bash
|
||||
# chromium or chromium-browser or even chrome
|
||||
# replace http://localhost:5000 with your obscreen-studio instance url
|
||||
chromium --disable-features=Translate --ignore-certificate-errors --disable-web-security --disable-restore-session-state --autoplay-policy=no-user-gesture-required --start-maximized --allow-running-insecure-content --remember-cert-error-decisions --noerrdialogs --kiosk --incognito --window-position=0,0 --window-size=1920,1080 --display=:0 http://localhost:5000
|
||||
chromium \
|
||||
--disk-cache-size=2147483648 \
|
||||
--disable-features=Translate \
|
||||
--ignore-certificate-errors \
|
||||
--disable-web-security \
|
||||
--disable-restore-session-state \
|
||||
--autoplay-policy=no-user-gesture-required \
|
||||
--start-maximized \
|
||||
--allow-running-insecure-content \
|
||||
--remember-cert-error-decisions \
|
||||
--noerrdialogs \
|
||||
--kiosk \
|
||||
--incognito \
|
||||
--window-position=0,0 \
|
||||
--window-size=1920,1080 \
|
||||
--display=:0 \
|
||||
http://localhost:5000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@ -110,11 +110,14 @@ class ContentController(ObController):
|
||||
if not content:
|
||||
return abort(404)
|
||||
|
||||
vargs = {}
|
||||
working_folder_path, working_folder = self.get_folder_context()
|
||||
edit_view = 'slideshow/contents/edit.jinja.html'
|
||||
|
||||
if content.type == ContentType.COMPOSITION:
|
||||
edit_view = 'slideshow/contents/edit-composition.jinja.html'
|
||||
vargs['folders_tree'] = self._model_store.folder().get_folder_tree(FolderEntity.CONTENT)
|
||||
vargs['foldered_contents'] = self._model_store.content().get_all_indexed('folder_id', multiple=True)
|
||||
|
||||
return render_template(
|
||||
edit_view,
|
||||
@ -122,7 +125,8 @@ class ContentController(ObController):
|
||||
working_folder_path=working_folder_path,
|
||||
working_folder=working_folder,
|
||||
enum_content_type=ContentType,
|
||||
external_storage_mountpoint=self._model_store.config().map().get('external_storage_mountpoint')
|
||||
external_storage_mountpoint=self._model_store.config().map().get('external_storage_mountpoint'),
|
||||
**vargs
|
||||
)
|
||||
|
||||
def slideshow_content_save(self, content_id: int = 0):
|
||||
|
||||
@ -156,7 +156,7 @@ class PlayerController(ObController):
|
||||
slide = dict(slide)
|
||||
slide['id'] = hashlib.md5(str(file).encode('utf-8')).hexdigest()
|
||||
slide['position'] = position
|
||||
slide['delegate_duration'] = 1 if slide['type'] == ContentType.VIDEO.value else 0
|
||||
slide['delegate_duration'] = 1 if virtual_content.type == ContentType.VIDEO else 0
|
||||
slide['name'] = file.name
|
||||
slide['type'] = virtual_content.type.value
|
||||
slide['location'] = self._model_store.content().resolve_content_location(virtual_content)
|
||||
|
||||
@ -28,7 +28,7 @@ class ContentManager(ModelManager):
|
||||
"name CHAR(255)",
|
||||
"type CHAR(30)",
|
||||
"location TEXT",
|
||||
"duration INTEGER",
|
||||
"duration FLOAT",
|
||||
"folder_id INTEGER",
|
||||
"created_by CHAR(255)",
|
||||
"updated_by CHAR(255)",
|
||||
|
||||
@ -3,6 +3,7 @@ import os
|
||||
from typing import Dict, Optional, List, Tuple, Union
|
||||
|
||||
from src.model.entity.Playlist import Playlist
|
||||
from src.model.enum.ContentType import ContentType
|
||||
from src.util.utils import get_optional_string, get_yt_video_id, slugify, slugify_next
|
||||
from src.manager.DatabaseManager import DatabaseManager
|
||||
from src.manager.SlideManager import SlideManager
|
||||
@ -69,15 +70,17 @@ class PlaylistManager(ModelManager):
|
||||
durations = self._db.execute_read_query("""
|
||||
SELECT
|
||||
playlist_id,
|
||||
SUM(CASE
|
||||
ROUND(SUM(CASE
|
||||
WHEN s.delegate_duration = 1 THEN c.duration
|
||||
WHEN c.type = '{}' THEN s.duration
|
||||
ELSE s.duration
|
||||
END) AS total_duration
|
||||
END)) AS total_duration
|
||||
FROM {} s
|
||||
LEFT JOIN {} c ON c.id = s.content_id
|
||||
WHERE cron_schedule IS NULL {}
|
||||
WHERE cron_schedule IS NULL {} AND s.enabled is TRUE
|
||||
GROUP BY playlist_id;
|
||||
""".format(
|
||||
ContentType.EXTERNAL_STORAGE.value,
|
||||
SlideManager.TABLE_NAME,
|
||||
ContentManager.TABLE_NAME,
|
||||
"{}".format(
|
||||
|
||||
@ -9,7 +9,7 @@ from src.util.utils import str_to_enum
|
||||
|
||||
class Content:
|
||||
|
||||
def __init__(self, uuid: str = '', location: str = '', type: Union[ContentType, str] = ContentType.URL, name: str = 'Untitled', id: Optional[int] = None, duration: Optional[int] = None, created_by: Optional[str] = None, updated_by: Optional[str] = None, created_at: Optional[int] = None, updated_at: Optional[int] = None, folder_id: Optional[int] = None):
|
||||
def __init__(self, uuid: str = '', location: str = '', type: Union[ContentType, str] = ContentType.URL, name: str = 'Untitled', id: Optional[int] = None, duration: Optional[float] = None, created_by: Optional[str] = None, updated_by: Optional[str] = None, created_at: Optional[int] = None, updated_at: Optional[int] = None, folder_id: Optional[int] = None):
|
||||
self._uuid = uuid if uuid else self.generate_and_set_uuid()
|
||||
self._id = id if id else None
|
||||
self._location = location
|
||||
@ -88,11 +88,11 @@ class Content:
|
||||
self._folder_id = value
|
||||
|
||||
@property
|
||||
def duration(self) -> Optional[int]:
|
||||
def duration(self) -> Optional[float]:
|
||||
return self._duration
|
||||
|
||||
@duration.setter
|
||||
def duration(self, value: Optional[int]):
|
||||
def duration(self, value: Optional[float]):
|
||||
self._duration = value
|
||||
|
||||
@property
|
||||
|
||||
@ -10,9 +10,9 @@ def mp4_duration_with_ffprobe(filename):
|
||||
fields = json.loads(result)['streams'][0]
|
||||
|
||||
if 'tags' in fields and 'DURATION' in fields['tags']:
|
||||
return int(float(fields['tags']['DURATION']))
|
||||
return round(float(fields['tags']['DURATION']), 2)
|
||||
|
||||
if 'duration' in fields:
|
||||
return int(float(fields['duration']))
|
||||
return round(float(fields['duration']), 2)
|
||||
|
||||
return 0
|
||||
|
||||
@ -251,6 +251,7 @@ def slugify(value):
|
||||
|
||||
|
||||
def seconds_to_hhmmss(seconds):
|
||||
seconds = int(seconds)
|
||||
if not seconds:
|
||||
return ""
|
||||
hours = seconds // 3600
|
||||
|
||||
@ -16,4 +16,20 @@ WIDTH=$(echo $RESOLUTION | cut -d 'x' -f 1)
|
||||
HEIGHT=$(echo $RESOLUTION | cut -d 'x' -f 2)
|
||||
|
||||
# Start Chromium in kiosk mode
|
||||
chromium-browser --disk-cache-size=2147483648 --disable-features=Translate --ignore-certificate-errors --disable-web-security --disable-restore-session-state --autoplay-policy=no-user-gesture-required --start-maximized --allow-running-insecure-content --remember-cert-error-decisions --noerrdialogs --kiosk --incognito --window-position=0,0 --window-size=${WIDTH},${HEIGHT} --display=:0 http://localhost:5000
|
||||
chromium-browser \
|
||||
--disk-cache-size=2147483648 \
|
||||
--disable-features=Translate \
|
||||
--ignore-certificate-errors \
|
||||
--disable-web-security \
|
||||
--disable-restore-session-state \
|
||||
--autoplay-policy=no-user-gesture-required \
|
||||
--start-maximized \
|
||||
--allow-running-insecure-content \
|
||||
--remember-cert-error-decisions \
|
||||
--noerrdialogs \
|
||||
--kiosk \
|
||||
--incognito \
|
||||
--window-position=0,0 \
|
||||
--window-size=${WIDTH},${HEIGHT} \
|
||||
--display=:0 \
|
||||
http://localhost:5000
|
||||
|
||||
@ -84,6 +84,7 @@ systemctl set-default graphical.target
|
||||
mkdir -p "$WORKING_DIR/obscreen/var/run"
|
||||
curl https://raw.githubusercontent.com/jr-k/obscreen/master/system/autostart-browser-x11.sh | sed "s#/home/pi#$WORKING_DIR#g" | sed "s#=pi#=$OWNER#g" | sed "s#http://localhost:5000#$obscreen_studio_url#g" | tee "$WORKING_DIR/obscreen/var/run/play"
|
||||
chmod +x "$WORKING_DIR/obscreen/var/run/play"
|
||||
chown -R $OWNER:$OWNER "$WORKING_DIR/obscreen"
|
||||
|
||||
# ============================================================
|
||||
# Start
|
||||
|
||||
@ -25,7 +25,6 @@ apt-get install -y git python3-pip python3-venv libsqlite3-dev ntfs-3g ffmpeg
|
||||
cd $WORKING_DIR
|
||||
git clone https://github.com/jr-k/obscreen.git
|
||||
cd obscreen
|
||||
chown -R $USER:$USER ./
|
||||
|
||||
# Install application dependencies
|
||||
python3 -m venv venv
|
||||
@ -38,6 +37,9 @@ cp .env.dist .env
|
||||
# Add user to needed group
|
||||
usermod -aG plugdev $OWNER
|
||||
|
||||
# Fix permissions
|
||||
chown -R $OWNER:$OWNER ./
|
||||
|
||||
# ============================================================
|
||||
# Automount script for external storage
|
||||
# ============================================================
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
<h2>
|
||||
{{ l.common_pick_element }}
|
||||
</h2>
|
||||
|
||||
{% with use_href=False %}
|
||||
{% include 'fleet/node-players/component/explr-sidebar.jinja.html' %}
|
||||
{% endwith %}
|
||||
|
||||
|
||||
<div class="actions">
|
||||
<button type="button" class="btn btn-naked picker-close">
|
||||
<i class="fa fa-close icon-left"></i>{{ l.common_close }}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
.slide, iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding-top: 0; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; }
|
||||
.slide iframe { background: white; }
|
||||
.slide img, .slide video { height: 100%; }
|
||||
.slide video { width: 100%; height: 100%; }
|
||||
</style>
|
||||
<script type="application/javascript" src="{{ STATIC_PREFIX }}js/utils.js"></script>
|
||||
<script type="application/javascript" src="{{ STATIC_PREFIX }}js/lib/is-cron-now.js"></script>
|
||||
@ -82,6 +83,7 @@
|
||||
let curSlide = secondSlide;
|
||||
let nextSlide = firstSlide;
|
||||
let notificationItemIndex = null;
|
||||
let pausableContent = null;
|
||||
|
||||
// Functions
|
||||
const itemsLoadedProcess = function() {
|
||||
@ -126,6 +128,10 @@
|
||||
|
||||
const resume = function() {
|
||||
playState = PLAY_STATE_PLAYING;
|
||||
|
||||
if (pausableContent) {
|
||||
pausableContent.play();
|
||||
}
|
||||
};
|
||||
|
||||
const play = function() {
|
||||
@ -135,6 +141,10 @@
|
||||
const pause = function() {
|
||||
pauseClockValue = clockValue;
|
||||
playState = PLAY_STATE_PAUSE;
|
||||
|
||||
if (pausableContent) {
|
||||
pausableContent.pause();
|
||||
}
|
||||
};
|
||||
|
||||
const stop = function() {
|
||||
@ -203,7 +213,7 @@
|
||||
|
||||
let duration = item.duration;
|
||||
|
||||
if (durationsOverride[item.id]) {
|
||||
if (durationsOverride[item.id] !== undefined) {
|
||||
duration = durationsOverride[item.id];
|
||||
}
|
||||
|
||||
@ -250,17 +260,15 @@
|
||||
|
||||
if (i === curItemIndex) {
|
||||
secondsBeforeNext = accumulatedTime + safe_duration(item) - timeInCurrentLoop;
|
||||
//console.log("remaining:", secondsBeforeNext, "clock:",clockValue, curItemIndex);
|
||||
//console.log("id", item.id, "secondsBeforeNext:", secondsBeforeNext, "clock:", clockValue, "clockLoopDration", timeInCurrentLoop, "<", accumulatedTime , '+', safe_duration(item));
|
||||
}
|
||||
|
||||
if (timeInCurrentLoop < accumulatedTime + safe_duration(item)) {
|
||||
if (curItemIndex !== i) {
|
||||
//console.log('change to ', i , item.name)
|
||||
curItemIndex = i;
|
||||
|
||||
const emptySlide = getEmptySlide();
|
||||
if ((emptySlide && !hasMoveOnce) || forcePreload) {
|
||||
//console.log('init preload');
|
||||
if (!hasMoveOnce && syncWithTime) {
|
||||
if (accumulatedTime + safe_duration(item) - timeInCurrentLoop < 1) {
|
||||
// Prevent glitch when syncWithTime for first init
|
||||
@ -386,10 +394,13 @@
|
||||
delayNoisyContentJIT = lookupCurrentItem().id !== item.id ? delayNoisyContentJIT : 0;
|
||||
|
||||
video.addEventListener('loadedmetadata', function() {
|
||||
if (item.duration !== video.duration && item.delegate_duration) {
|
||||
durationsOverride[item.id] = video.duration;
|
||||
if (item.duration !== video.duration && !item.delegate_duration) {
|
||||
console.warn('Given duration ' + item.duration + 's is different from video file ' + Math.ceil(video.duration) + 's');
|
||||
}
|
||||
|
||||
if (item.delegate_duration) {
|
||||
durationsOverride[item.id] = Math.ceil(video.duration);
|
||||
}
|
||||
});
|
||||
|
||||
const autoplayLoader = function() {
|
||||
@ -401,10 +412,12 @@
|
||||
if (!previewMode) {
|
||||
setTimeout(function() {
|
||||
video.play();
|
||||
pausableContent = video;
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(autoplayLoader, delayNoisyContentJIT);
|
||||
}
|
||||
|
||||
|
||||
@ -14,10 +14,10 @@
|
||||
{{ render_folder(child) }}
|
||||
{% endfor %}
|
||||
{% for content in content_children %}
|
||||
{% set slides = slides_with_content[content.id]|default([]) %}
|
||||
{% set slides = slides_with_content[content.id]|default([]) if slides_with_content else [] %}
|
||||
{% set icon = enum_content_type.get_fa_icon(content.type) %}
|
||||
{% set color = enum_content_type.get_color_icon(content.type) %}
|
||||
<li class="explr-item" data-entity-json="{{ content.to_json() }}">
|
||||
<li class="explr-item" data-entity-json="{{ content.to_json({'classIcon': icon, 'classColor': color}) }}">
|
||||
<i class="fa {{ icon }} {{ color }}"></i>
|
||||
{% if slides|length > 0 %}
|
||||
<sub>
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block add_css %}
|
||||
<link rel="stylesheet" href="{{ STATIC_PREFIX }}css/lib/flatpickr.min.css"/>
|
||||
<link rel="stylesheet" href="{{ STATIC_PREFIX }}css/lib/jquery-explr-1.4.css"/>
|
||||
<link rel="stylesheet" href="{{ STATIC_PREFIX }}css/lib/flatpickr.min.css"/>
|
||||
{{ HOOK(H_SLIDESHOW_CONTENT_CSS) }}
|
||||
{% endblock %}
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/jquery-ui.min.js"></script>
|
||||
{# <script src="{{ STATIC_PREFIX }} js/lib/jquery-ui-rotatable.min.js"></script> #}
|
||||
<script src="{{ STATIC_PREFIX }}js/slideshow/content-composition.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/explorer.js"></script>
|
||||
{{ HOOK(H_SLIDESHOW_CONTENT_JAVASCRIPT) }}
|
||||
{% endblock %}
|
||||
|
||||
@ -109,7 +110,7 @@
|
||||
<div class="inner">
|
||||
<div class="toolbar">
|
||||
<button id="presetGrid2x2">Grid 2x2</button>
|
||||
<button id="addElement">Add Element</button>
|
||||
<button id="addElement" class="content-explr-picker">Add Element</button>
|
||||
<button id="removeAllElements">Remove All Elements</button>
|
||||
</div>
|
||||
|
||||
@ -123,23 +124,55 @@
|
||||
|
||||
|
||||
<div class="page-panel right-panel">
|
||||
<div class="form-element-properties">
|
||||
<div class="form-element-properties hidden">
|
||||
<form id="elementForm">
|
||||
<h3>Element Properties</h3>
|
||||
<label for="elem-x">X:</label>
|
||||
<input type="number" id="elem-x" name="elem-x"><br>
|
||||
<label for="elem-y">Y:</label>
|
||||
<input type="number" id="elem-y" name="elem-y"><br>
|
||||
<label for="elem-width">Width:</label>
|
||||
<input type="number" id="elem-width" name="elem-width"><br>
|
||||
<label for="elem-height">Height:</label>
|
||||
<input type="number" id="elem-height" name="elem-height"><br>
|
||||
<!--<label for="elem-rotate">Rotate (deg):</label>-->
|
||||
<!--<input type="number" id="elem-rotate" name="elem-rotate"><br>-->
|
||||
|
||||
<div class="form-group">
|
||||
<label for="elem-x">Position X</label>
|
||||
<div class="widget">
|
||||
<input type="number" id="elem-x" name="elem-x">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="elem-y">Position Y</label>
|
||||
<div class="widget">
|
||||
<input type="number" id="elem-y" name="elem-y">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="elem-width">Width</label>
|
||||
<div class="widget">
|
||||
<input type="number" id="elem-width" name="elem-width">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="elem-height">Height</label>
|
||||
<div class="widget">
|
||||
<input type="number" id="elem-height" name="elem-height">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# <div class="form-group">#}
|
||||
{# <label for="elem-rotate">Rotate (deg)</label>#}
|
||||
{# <div class="widget">#}
|
||||
{# <input type="number" id="elem-rotate" name="elem-rotate">#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pickers hidden">
|
||||
<div class="modals-outer">
|
||||
<div class="modals-inner">
|
||||
{% include 'slideshow/contents/modal/explr-picker.jinja.html' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user