added viewnext and viewprev routes and plumbed these in to the file viewer code. Viewer code now works has a prev/next button, and handles videos

This commit is contained in:
2021-07-15 20:23:02 +10:00
parent d03f5c99b0
commit f30ca16552
4 changed files with 174 additions and 14 deletions

6
TODO
View File

@@ -1,8 +1,9 @@
## GENERAL
* allow rotate of image (permanently on FS, so its right everywhere)
* file browser:
- maybe back feature/button?
* improve photo browser -> view file, rather than just allowing browser to show image
* allow rotate of image (permanently on FS, so its right everywhere)
* face locations:
START FORM SCRATCH so all images have face_locn data
@@ -16,6 +17,7 @@
* refimg
- remove AI menu from top-level -> make a sub-of Person, and just have Match or AI
* remove dirs after the duplicate cleanup removes all its content
* fix up logging in general
* comment your code
* more OO goodness :)

View File

@@ -450,6 +450,37 @@ def move_files():
st.SetMessage( f"Created&nbsp;<a href=/job/{job.id}>Job #{job.id}</a>&nbsp;to move selected file(s)")
return render_template("base.html")
@app.route("/viewnext", methods=["GET","POST"])
@login_required
def viewnext():
if request.method=="POST":
id = request.form['current']
eids=request.form['eids']
lst = eids.split(',')
new_id = lst[lst.index(id)+1]
obj = Entry.query.join(File).filter(Entry.id==new_id).first()
return render_template("viewer.html", obj=obj, eids=eids)
@app.route("/viewprev", methods=["GET","POST"])
@login_required
def viewprev():
if request.method=="POST":
id = request.form['current']
eids=request.form['eids']
lst = eids.split(',')
new_id = lst[lst.index(id)-1]
obj = Entry.query.join(File).filter(Entry.id==new_id).first()
return render_template("viewer.html", obj=obj, eids=eids)
@app.route("/view/<id>", methods=["GET","POST"])
@login_required
def view_img(id):
obj = Entry.query.join(File).filter(Entry.id==id).first()
if request.method=="POST":
eids=request.form['eids']
else:
eids=''
return render_template("viewer.html", obj=obj, eids=eids)
################################################################################
# /static -> returns the contents of any file referenced inside /static.

View File

@@ -111,6 +111,14 @@
<input id="offset" type="hidden" name="offset" value="{{offset}}">
<input id="size" type="hidden" name="size" value="{{size}}">
</div class="form-row">
{% set eids=namespace( str="" ) %}
{# gather all the file eids and collect them in case we go gallery mode #}
{% for obj in entry_data %}
{% if obj.type.name != "Directory" %}
{% set eids.str = eids.str + obj.id|string +"," %}
{% endif %}
{% endfor %}
<input name="eids" id="eids" type="hidden" value="{{eids.str}}">
</form>
{% set last = namespace(printed=0) %}
@@ -122,7 +130,7 @@
{% if folders and entry_data|length == 0 %}
{% if cwd != root %}
<figure class="px-1 dir entry" ecnt="1" dir="{{cwd|ParentPath}}">
<span style="font-size:{{(size|int-22)/2}}" class="fa-stack">
<span style="font-size:{{(size|int-22)/2}}px" class="fa-stack">
<i style="color:grey" class="fas fa-folder fa-stack-2x"></i>
<i class="fas fa-level-up-alt fa-flip-horizontal fa-stack-1x fa-inverse"></i>
</span>
@@ -130,7 +138,7 @@
</figure class="figure">
{% else %}
{# create an even lighter-grey, unclickable back button - so folders dont jump around when you go into them #}
<span style="font-size:{{(size|int-22)/2}}" class="mx-1 fa-stack">
<span style="font-size:{{(size|int-22)/2}}px" class="mx-1 fa-stack">
<i style="color:lightgrey" class="fas fa-folder fa-stack-2x"></i>
<i class="fas fa-level-up-alt fa-flip-horizontal fa-stack-1x fa-inverse"></i>
</span>
@@ -140,7 +148,7 @@
{% if loop.index==1 and folders %}
{% if cwd != root %}
<figure class="px-1 dir entry" ecnt="{{loop.index}}" dir="{{cwd|ParentPath}}">
<span style="font-size:{{(size|int-22)/2}}" class="fa-stack">
<span style="font-size:{{(size|int-22)/2}}px" class="fa-stack">
<i style="color:grey" class="fas fa-folder fa-stack-2x"></i>
<i class="fas fa-level-up-alt fa-flip-horizontal fa-stack-1x fa-inverse"></i>
</span>
@@ -148,7 +156,7 @@
</figure class="figure">
{% else %}
{# create an even lighter-grey, unclickable back button - so folders dont jump around when you go into them #}
<span style="font-size:{{(size|int-22)/2}}" class="mx-1 fa-stack">
<span style="font-size:{{(size|int-22)/2}}px" class="mx-1 fa-stack">
<i style="color:lightgrey" class="fas fa-folder fa-stack-2x"></i>
<i class="fas fa-level-up-alt fa-flip-horizontal fa-stack-1x fa-inverse"></i>
</span>
@@ -193,7 +201,7 @@
<a href="{{obj.in_dir.in_path.path_prefix}}/{{obj.in_dir.rel_path}}/{{obj.name}}"><img class="thumb" height="{{size}}" src="data:image/jpeg;base64,{{obj.file_details.thumbnail}}"></img></a>
{% if search_term is defined %}
<div style="position:absolute; bottom: 2; left: 2;">
<i style="font-size:16;background-color:black;color:white" class="fas {{LocationIcon(obj)}}"></i>
<i style="font-size:16px;background-color:black;color:white" class="fas {{LocationIcon(obj)}}"></i>
</div>
{% endif %}
</div>
@@ -201,11 +209,11 @@
<div style="position:relative; width:100%">
<a href="{{obj.in_dir.in_path.path_prefix}}/{{obj.in_dir.rel_path}}/{{obj.name}}"><img class="thumb" style="display:block" height="{{size}}" src="data:image/jpeg;base64,{{obj.file_details.thumbnail}}"></img></a>
<div style="position:absolute; top: 2; left: 2;">
<i style="font-size:32;background-color:black;color:white" class="fas fa-film"></i>
<i style="font-size:32px;background-color:black;color:white" class="fas fa-film"></i>
</div>
{% if search_term is defined %}
<div style="position:absolute; bottom: 2; left: 2;">
<i style="font-size:16;background-color:black;color:white" class="fas {{LocationIcon(obj)}}"></i>
<i style="font-size:16px;background-color:black;color:white" class="fas {{LocationIcon(obj)}}"></i>
</div>
{% endif %}
</div>
@@ -223,7 +231,7 @@
{# if this dir is the toplevel of the cwd, show the folder icon #}
{% if dirname| TopLevelFolderOf(cwd) %}
<figure class="px-1 dir entry" id={{obj.id}} ecnt={{loop.index}} dir="{{dirname}}">
<i style="font-size:{{size|int-22}};" class="fas fa-folder"></i>
<i style="font-size:{{size|int-22}}px" class="fas fa-folder"></i>
<figcaption class="figure-caption text-center text-wrap text-break">{{obj.name}}</figcaption>
</figure class="figure">
{% endif %}
@@ -382,12 +390,12 @@ function ChangeSize(clicked_button,sz)
{
$('.sz-but.btn-info').removeClass('btn-info').addClass('btn-outline-info')
$(clicked_button).addClass('btn-info').removeClass('btn-outline-info')
$('.thumb').attr( {height: sz, style: 'font-size:'+sz } )
$('.thumb').attr( {height: sz, style: 'font-size:'+sz+'px' } )
$('#size').val(sz)
sz=sz-22
$('.fa-folder').attr( {style: 'font-size:'+sz } )
$('.fa-folder').attr( {style: 'font-size:'+sz+'px' } )
sz=sz/2
$('.fa-stack').attr( {style: 'color:grey;font-size:'+sz} )
$('.fa-stack').attr( {style: 'color:grey;font-size:'+sz+'px'} )
}
// e == event (can see if shift/ctrl held down while left-clicking
@@ -488,6 +496,13 @@ function NoSel() {
$('.figure').click( function(e) { DoSel(e, this ); SetButtonState(); return false; });
$(document).on('click', function(e) { $('.highlight').removeClass('highlight') ; SetButtonState() });
$('.figure').dblclick(
function() {
s='<form id="_fm" method="POST" action="/view/' + $(this).attr("id");
s+='"><input type="hidden" name="eids" value="'+$("#eids").val() + '"></form>'
$(s).appendTo('body').submit(); }
);
// different context menu on files
$.contextMenu({
@@ -529,7 +544,11 @@ $.contextMenu({
return {
callback: function( key, options) {
if( key == "details" ) { DetailsDBox() }
if( key == "view" ) { document.location.href = $(this).find('a').attr('href'); }
if( key == "view" ) {
s='<form id="_fm" method="POST" action="/view/' + $(this).attr("id");
s+='"><input type="hidden" name="eids" value="'+$("#eids").val() + '"></form>'
$(s).appendTo('body').submit();
}
if( key == "move" ) { MoveDBox() }
if( key == "del" ) { DelDBox('Delete') }
if( key == "undel" ) { DelDBox('Restore') }

108
templates/viewer.html Normal file
View File

@@ -0,0 +1,108 @@
{% extends "base.html" %} {% block main_content %}
<script>
var gap=0.8
function NewWidth()
{
w_r=im.width/(window.innerWidth*gap)
h_r=im.height/(window.innerHeight*gap)
if( w_r > h_r )
return window.innerWidth*gap
else
return im.width*gap / (im.height/window.innerHeight)
}
function NewHeight()
{
w_r=im.width/(window.innerWidth*gap)
h_r=im.height/(window.innerHeight*gap)
if( h_r > w_r )
return window.innerHeight*gap
else
return im.height*gap / (im.width/window.innerWidth)
}
// Define this once and before it will be called, hence at the top of this file
function DrawImg()
{
// another call to this func will occur on load, so skip this one
if( im.width == 0 )
return
canvas.width=NewWidth(im)
canvas.height=NewHeight(im)
// actually draw the pixel images to the canvas at the right size
context.drawImage(im, 0, 0, canvas.width, canvas.height )
/* need a for loop
context.beginPath();
new_x=(orig_face.x/orig_face.orig_w)*img.width/(img.height/canvas.height)
new_y=(orig_face.y/orig_face.orig_h)*thumbsize/(img.height/canvas.height)
new_w=(orig_face.w/orig_face.orig_w)*img.width/(img.height/canvas.height)
new_h=(orig_face.h/orig_face.orig_h)*thumbsize/(img.height/canvas.height)
context.rect(new_x, new_y, new_w, new_h)
context.lineWidth = 2;
context.strokeStyle = 'green';
context.stroke();
*/
}
function ResizeVideo()
{
$('#_v').height(window.innerHeight*gap)
}
</script>
<div class="container-fluid">
{% set max=eids.split(',')|length %}
<br>
<center>
<input type="hidden" name="eids" value={{eids}}>
<div class="form-row col-lg-12">
{% if eids.find(obj.id|string) > 0 %}
<form id="prev" class="form form-inline" action="/viewprev" method="POST">
<input type="hidden" name="current" value="{{obj.id}}">
<input type="hidden" name="eids" value="{{eids}}">
<button class="btn btn-outline-info h-75" id="la"><i class="fas fa-angle-double-left"></i></button>
</form id="prev">
{% endif %}
{% if obj.type.name == "Image" %}
<figure style="border: 1px solid #5bc0de; border-radius: 3px;">
<canvas id="canvas"></canvas>
<script>
var im=new Image();
im.onload=DrawImg
im.src="/{{obj.in_dir.in_path.path_prefix}}/{{obj.in_dir.rel_path}}/{{obj.name}}"
var context = canvas.getContext('2d')
window.addEventListener('resize', DrawImg, false);
</script>
<figcaption class="figure-caption text-center text-wrap text-break">{{obj.name}}</figcaption>
</figure>
{% elif obj.type.name == "Video" %}
<video id="_v" controls>
<source src="/{{obj.in_dir.in_path.path_prefix}}/{{obj.in_dir.rel_path}}/{{obj.name}}" type="video/mp4">
Your browser does not support the video tag.
</video>
<script>
window.addEventListener('resize', ResizeVideo, false);
ResizeVideo()
</script>
{% endif %}
{% for eid in eids.split(',') %}
{% if loop.index == max-1 %}
{% if eid|int != obj.id %}
<form id="next" class="form form-inline" action="/viewnext" method="POST">
<input type="hidden" name="current" value="{{obj.id}}">
<input type="hidden" name="eids" value="{{eids}}">
<button class="btn btn-outline-info h-75" id="ra"><i class="fas fa-angle-double-right"></i></button>
</form id="next">
{% endif %}
{% endif %}
{% endfor %}
</div id="/form-row">
</div class="form-row col-lg-12">
</center>
</div class="container">
{% endblock main_content %}