From: Calin Crisan Date: Sat, 16 Nov 2013 13:43:02 +0000 (+0200) Subject: added media previews grouping support X-Git-Url: http://www.vanbest.org/gitweb/?a=commitdiff_plain;h=531993663b5cf5568ae37a1736535d44cf06efc4;p=motioneye-debian added media previews grouping support --- diff --git a/doc/todo.txt b/doc/todo.txt index 0b11b32..d9bf545 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -1,7 +1,4 @@ --> add support for picture resizing --> add a loading progress for media previews --> add a pager for media files --> add a download option in media list +-> layout seems to be too wide for a modern mobile phone -> add a previewer for movies -> make camera frames positions configurable -> add a view log functionality diff --git a/src/mediafiles.py b/src/mediafiles.py index f5cd3a3..c346b36 100644 --- a/src/mediafiles.py +++ b/src/mediafiles.py @@ -120,6 +120,7 @@ def list_pictures(camera_config): picture_files.append({ 'path': path, 'momentStr': utils.pretty_date_time(datetime.datetime.fromtimestamp(os.path.getmtime(p))), + 'sizeStr': utils.pretty_size(os.path.getsize(p)), 'timestamp': os.path.getmtime(p) }) @@ -135,6 +136,7 @@ def list_movies(camera_config): movie_files = [{ 'path': p[len(target_dir):], 'momentStr': utils.pretty_date_time(datetime.datetime.fromtimestamp(os.path.getmtime(p))), + 'sizeStr': utils.pretty_size(os.path.getsize(p)), 'timestamp': os.path.getmtime(p) } for p in full_paths] diff --git a/src/utils.py b/src/utils.py index 25c9d65..d6fff8a 100644 --- a/src/utils.py +++ b/src/utils.py @@ -169,6 +169,22 @@ def pretty_duration(duration): return format.format(d=days, h=hours, m=minutes, s=seconds) +def pretty_size(size): + if size < 1024: # less than 1kB + size, unit = size, 'B' + + elif size < 1024 * 1024: # less than 1MB + size, unit = size / 1024.0, 'kB' + + elif size < 1024 * 1024 * 1024: # less than 1GB + size, unit = size / 1024.0 / 1024, 'MB' + + else: # greater than or equal to 1GB + size, unit = size / 1024.0 / 1024 / 1024, 'GB' + + return '%.1f %s' % (size, unit) + + def get_disk_usage(path): logging.debug('getting disk usage for path %(path)s...' % { 'path': path}) diff --git a/static/css/main.css b/static/css/main.css index d90e787..100a041 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -356,6 +356,48 @@ table.add-camera-dialog input[type=password] { div.media-dialog { +} + +div.media-dialog-groups { + text-align: center; +} + +div.media-dialog-group-button { + display: inline-block; + height: 1.5em; + line-height: 1.5em; + text-align: center; + margin: 0em 0.2em 0.3em 0.2em; + padding: 0px 0.5em; + background-color: #414141; + color: #3498db; + border-radius: 3px; + transition: all 0.1s linear; + cursor: pointer; +} + +div.media-dialog-group-button:HOVER { + background-color: #515151; +} + +div.media-dialog-group-button:ACTIVE { + background-color: #414141; +} + +div.media-dialog-group-button.current { + background-color: #317CAD; + color: white; +} + +div.media-dialog-group-button.current:HOVER { + background-color: #3498db; +} + +div.media-dialog-group-button.current:ACTIVE { + background-color: #317CAD; +} + +div.media-dialog-list { overflow: auto; } @@ -398,7 +440,7 @@ div.media-list-entry-name { white-space: nowrap; } -div.media-list-entry-moment { +div.media-list-entry-details { font-size: 1em; text-align: center; white-space: nowrap; diff --git a/static/js/main.js b/static/js/main.js index f1fd325..e07616f 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -1043,6 +1043,7 @@ function runPictureDialog(entries, pos) { nextArrow.css('display', pos < entries.length - 1 ? '' : 'none'); $('div.modal-container').find('span.modal-title:last').html(entry.name); + updateModalDialogPosition(); } prevArrow.click(function () { @@ -1295,58 +1296,24 @@ function runAddCameraDialog() { function runMediaDialog(cameraId, mediaType) { - var dialogDiv = $( - '
' + - '
'); + var dialogDiv = $('
'); + var mediaListDiv = $('
'); + var groupsDiv = $('
'); + + dialogDiv.append(groupsDiv); + dialogDiv.append(mediaListDiv); var windowWidth = $(window).width(); if (windowWidth <= 1000) { - dialogDiv.width(parseInt(windowWidth * 0.9)); - dialogDiv.height(parseInt(windowWidth * 0.9 * 480 / 640)); + mediaListDiv.width(parseInt(windowWidth * 0.9)); + groupsDiv.width(parseInt(windowWidth * 0.9)); + mediaListDiv.height(parseInt(windowWidth * 0.9 * 480 / 640)); } else { - dialogDiv.width(parseInt(windowWidth * 0.5)); - dialogDiv.height(parseInt(windowWidth * 0.5 * 480 / 640)); - } - - function fetchMedia() { - var progress = $('
'); - - cameraSelect.hide(); - cameraSelect.before(progress); - cameraSelect.parent().find('div').remove(); /* remove any previous progress div */ - - var data = { - host: hostEntry.val(), - port: portEntry.val(), - username: usernameEntry.val(), - password: passwordEntry.val() - }; - - ajax('GET', '/config/list/', data, function (data) { - if (data == null || data.error) { - progress.remove(); - if (passwordEntry.val()) { /* only show an error message when a password is supplied */ - showErrorMessage(data && data.error); - } - - return; - } - - cameraSelect.html(''); - progress.remove(); - - if (data.error || !data.cameras) { - return; - } - - data.cameras.forEach(function (info) { - cameraSelect.append(''); - }); - - cameraSelect.show(); - }); + mediaListDiv.width(parseInt(windowWidth * 0.5)); + groupsDiv.width(parseInt(windowWidth * 0.5)); + mediaListDiv.height(parseInt(windowWidth * 0.45 * 480 / 640)); } showModalDialog(''); @@ -1374,6 +1341,7 @@ function runMediaDialog(cameraId, mediaType) { 'name': parts[parts.length - 1], 'cameraId': cameraId, 'momentStr': media.momentStr, + 'sizeStr': media.sizeStr, 'timestamp': media.timestamp }); }); @@ -1387,20 +1355,17 @@ function runMediaDialog(cameraId, mediaType) { var height = tempDiv.height(); tempDiv.remove(); + /* prepare the entries within each group */ keys.forEach(function (key) { - if (key) { - var groupDiv = $('
' + key + '
'); - dialogDiv.append(groupDiv); - } - var entries = groups[key]; entries.sortKey(function (e) {return e.timestamp;}); entries.forEach(function (entry, pos) { var entryDiv = $('
'); - var previewImg = $(''); + var previewImg = $(''); entryDiv.append(previewImg); + previewImg[0]._src = '/' + mediaType + '/' + cameraId + '/preview' + entry.path + '?height=' + height; var downloadButton = $('
download
'); entryDiv.append(downloadButton); @@ -1408,29 +1373,81 @@ function runMediaDialog(cameraId, mediaType) { var nameDiv = $('
' + entry.name + '
'); entryDiv.append(nameDiv); - var momentDiv = $('
' + entry.momentStr + '
'); - entryDiv.append(momentDiv); + var detailsDiv = $('
'); + detailsDiv.html(entry.momentStr + ' | ' + entry.sizeStr); + entryDiv.append(detailsDiv); - downloadButton.click(function () { + downloadButton[0]._onClick = function () { window.location.href = '/picture/' + cameraId + '/download' + entry.path; return false; - }); + }; - entryDiv.click(function () { + entryDiv[0]._onClick = function () { if (mediaType === 'picture') { runPictureDialog(entries, pos); } - }); + }; - dialogDiv.append(entryDiv); + entry.div = entryDiv; }); }); - /* scroll to bottom */ - dialogDiv.find('img.media-list-preview:last').load(function () { - dialogDiv.scrollTop(dialogDiv.prop('scrollHeight')); - }); + function showGroup(key) { + groupsDiv.find('div.media-dialog-group-button').each(function () { + var $this = $(this); + if (this.key == key) { + $this.addClass('current'); + } + else { + $this.removeClass('current'); + } + }); + + mediaListDiv.html(''); + +// var groupDiv = $('
' + (key || '(ungrouped)') + '
'); +// dialogDiv.append(groupDiv); + + var entries = groups[key]; + entries.forEach(function (entry) { + mediaListDiv.append(entry.div); + entry.div.click(entry.div[0]._onClick); + + var downloadButton = entry.div.find('div.media-list-download-button'); + downloadButton.click(downloadButton[0]._onClick); + }); + + setTimeout(function () { + mediaListDiv.find('img.media-list-preview').each(function () { + if (this._src) { + this.src = this._src; + } + + delete this._src; + }); + }, 1000); + } + + if (keys.length) { + keys.forEach(function (key) { + var groupButton = $('
'); + groupButton.text(key || '(ungrouped)'); + groupButton[0].key = key; + + groupButton.click(function () { + showGroup(key); + }); + + groupsDiv.append(groupButton); + }); + + showGroup(keys[0]); + } + else { + groupsDiv.html('(no media files)'); + mediaListDiv.remove(); + } var title; if (mediaType === 'picture') { diff --git a/static/js/ui.js b/static/js/ui.js index 88198bb..2b188b4 100644 --- a/static/js/ui.js +++ b/static/js/ui.js @@ -687,6 +687,9 @@ function makeModalDialogTitleBar(options) { var titleSpan = $(''); titleSpan.html(options.title || ''); + if (options.closeButton) { + titleSpan.css('margin', '0px 1.5em'); + } titleBar.append(titleSpan);