add share link at /m/, add share dialog in view menu, fix preview for documents

This commit is contained in:
j 2023-07-15 12:04:04 +05:30
commit bea0d301a4
30 changed files with 2704 additions and 4 deletions

View file

@ -190,6 +190,12 @@ class MetaClip(object):
def __str__(self):
return self.public_id
def get_first_frame(self, resolution=None):
if resolution is None:
resolution = max(settings.CONFIG['video']['resolutions'])
return '/%s/%sp%0.03f.jpg' % (self.item.public_id, resolution, float(self.start))
class Meta:
unique_together = ("item", "start", "end")

View file

@ -567,7 +567,7 @@ class Document(models.Model, FulltextMixin):
if len(crop) == 4:
path = os.path.join(folder, '%s.jpg' % ','.join(map(str, crop)))
if not os.path.exists(path):
img = Image.open(src).crop(crop)
img = Image.open(src).convert('RGB').crop(crop)
img.save(path)
else:
img = Image.open(path)

View file

@ -12,9 +12,10 @@ from oxdjango.decorators import login_required_json
from oxdjango.http import HttpFileResponse
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response, HttpErrorJson
from django import forms
from django.db.models import Count, Sum
from django.conf import settings
from django.db.models import Count, Sum
from django.http import HttpResponse
from django.shortcuts import render
from item import utils
from item.models import Item
@ -512,3 +513,33 @@ def autocompleteDocuments(request, data):
response['data']['items'] = [i['value'] for i in qs]
return render_to_json_response(response)
actions.register(autocompleteDocuments)
def document(request, fragment):
context = {}
parts = fragment.split('/')
id = parts[0]
page = None
crop = None
if len(parts) == 2:
rect = parts[1].split(',')
if len(rect) == 1:
page = rect[0]
else:
crop = rect
document = models.Document.objects.filter(id=ox.fromAZ(id)).first()
if document and document.access(request.user):
context['title'] = document.data['title']
if document.data.get('description'):
context['description'] = document.data['description']
link = request.build_absolute_uri(document.get_absolute_url())
public_id = ox.toAZ(document.id)
preview = '/documents/%s/512p.jpg' % public_id
if page:
preview = '/documents/%s/512p%s.jpg' % (public_id, page)
if crop:
preview = '/documents/%s/512p%s.jpg' % (public_id, ','.join(crop))
context['preview'] = request.build_absolute_uri(preview)
context['url'] = request.build_absolute_uri('/documents/' + fragment)
context['settings'] = settings
return render(request, "document.html", context)

View file

3
pandora/mobile/admin.py Normal file
View file

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

5
pandora/mobile/apps.py Normal file
View file

@ -0,0 +1,5 @@
from django.apps import AppConfig
class MobileConfig(AppConfig):
name = 'mobile'

View file

3
pandora/mobile/models.py Normal file
View file

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

3
pandora/mobile/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

75
pandora/mobile/views.py Normal file
View file

@ -0,0 +1,75 @@
from django.conf import settings
from django.shortcuts import render
import ox
def index(request, fragment):
from item.models import Item
from edit.models import Edit
from document.models import Document
context = {}
parts = fragment.split('/')
if parts[0] in ('document', 'documents'):
type = 'document'
id = parts[1]
page = None
crop = None
if len(parts) == 3:
rect = parts[2].split(',')
if len(rect) == 1:
page = rect[0]
else:
crop = rect
document = Document.objects.filter(id=ox.fromAZ(id)).first()
if document and document.access(request.user):
context['title'] = document.data['title']
link = request.build_absolute_uri(document.get_absolute_url())
# FIXME: get preview image or fragment parse from url
public_id = ox.toAZ(document.id)
preview = '/documents/%s/512p.jpg' % public_id
if page:
preview = '/documents/%s/512p%s.jpg' % (public_id, page)
if crop:
preview = '/documents/%s/512p%s.jpg' % (public_id, ','.join(crop))
context['preview'] = request.build_absolute_uri(preview)
elif parts[0] == 'edits':
type = 'edit'
id = parts[1]
id = id.split(':')
username = id[0]
name = ":".join(id[1:])
name = name.replace('_', ' ')
edit = Edit.objects.filter(user__username=username, name=name).first()
if edit and edit.accessible(request.user):
link = request.build_absolute_uri('/m' + edit.get_absolute_url())
context['title'] = name
context['description'] = edit.description.split('\n\n')[0]
# FIXME: use sort from parts if needed
context['preview'] = request.build_absolute_uri(edit.get_clips().first().get_first_frame())
else:
type = 'item'
id = parts[0]
item = Item.objects.filter(public_id=id).first()
if item and item.accessible(request.user):
link = request.build_absolute_uri(item.get_absolute_url())
if len(parts) > 1 and parts[1] in ('editor', 'player'):
parts = [parts[0]] + parts[2:]
if len(parts) > 1:
inout = parts[1]
if '-' in inout:
inout = inout.split('-')
else:
inout = inout.split(',')
inout = [ox.parse_timecode(p) for p in inout]
if len(inout) == 3:
inout.pop(1)
context['preview'] = link + '/480p%s.jpg' % inout[0]
else:
context['preview'] = link + '/480p.jpg'
context['title'] = item.get('title')
if context:
context['url'] = request.build_absolute_uri('/m/' + fragment)
context['settings'] = settings
return render(request, "mobile/index.html", context)

View file

@ -67,7 +67,8 @@ STATICFILES_DIRS = (
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#'django.contrib.staticfiles.finders.DefaultStorageFinder',
"sass_processor.finders.CssFinder",
"compressor.finders.CompressorFinder",
)
GEOIP_PATH = normpath(join(PROJECT_ROOT, '..', 'data', 'geo'))
@ -124,6 +125,9 @@ INSTALLED_APPS = (
'django_extensions',
'django_celery_results',
'django_celery_beat',
'compressor',
'sass_processor',
'app',
'log',
'annotation',
@ -150,6 +154,7 @@ INSTALLED_APPS = (
'websocket',
'taskqueue',
'home',
'mobile',
)
AUTH_USER_MODEL = 'system.User'

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>{{head_title}}</title>
<link rel="alternate" type="application/json+oembed" href="{{base_url}}oembed?url={{current_url|urlencode}}" title="oEmbed Profile"/>
{% include "baseheader.html" %}
<meta name="title" content="{{title}}"/>
{%if description %}<meta name="description" content="{{description}}"/> {%endif%}
<meta content="{{ preview }}" name="thumbnail"/>
<meta content="{{ preview }}" name="image_src"/>
<meta property="og:title" content="{{title}}"/>
<meta property="og:url" content="{{url}}"/>
<meta property="og:image" content="{{ preview }}"/>
<meta property="og:site_name" content="{{settings.SITENAME}}"/>
{%if description %}<meta property="og:description" content="{{description}}"/>{%endif%}
</head>
<body>
<noscript>
<div style="position: fixed; left: 0; top: 0; right: 0; bottom: 0; background-color: rgb(144, 144, 144);"></div>
<div style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; text-align: center; font-family: Lucida Grande, Segoe UI, DejaVu Sans, Lucida Sans Unicode, Helvetica, Arial, sans-serif; font-size: 11px; color: rgb(0, 0, 0); -moz-user-select: none; -o-user-select: none; -webkit-user-select: none">
<img src="/{{id}}/{{icon}}128.jpg" alt="" style="padding-top: 64px; -moz-user-drag: none; -o-user-drag: none; -webkit-user-drag: none">
<div style="position: absolute; width: 512px; left: 0; right: 0; margin: auto; -moz-user-select: text; -o-user-select: text; -webkit-user-select: text">
<div style="padding: 16px 0 8px 0; font-weight: bold; font-size: 13px">{{title}}</div>
<div>{{description_html|safe}}</div>
{% for c in clips %}
<div style="clear:both; padding-top: 4px">
<img src="/{{id}}/96p{{c.in}}.jpg" alt="" style="float: left; margin-right: 8px">
{{c.annotations|safe}}
</div>
{% endfor %}
<div style="clear: both; padding-top: 16px; padding-bottom: 16px; font-style: italic">{{settings.SITENAME}} requires JavaScript.</div>
</div>
</div>
</noscript>
</body>
</html>

View file

@ -0,0 +1,45 @@
<!DOCTYPE html>{% load static sass_tags compress %}
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% if title %}
<title>{{title}}</title>
<meta name="title" content="{{title}}"/>
<meta property="og:title" content="{{title}}"/>
{% endif %}
{%if description %}
<meta name="description" content="{{description}}"/>
<meta property="og:description" content="{{description}}"/>
{%endif%}
{% if preview %}
<meta content="{{ preview }}" name="thumbnail"/>
<meta content="{{ preview }}" name="image_src"/>
<meta property="og:image" content="{{ preview }}"/>
{% endif %}
{% if url %}
<meta property="og:url" content="{{ url }}"/>
{% endif %}
<meta property="og:site_name" content="{{ settings.SITENAME }}"/>
{% compress css file m %}
<link rel="stylesheet" href="{% static 'mobile/css/reset.css' %}"></link>
<link rel="stylesheet" href="{% static 'mobile/css/style.css' %}"></link>
{% endcompress %}
<meta name="google" value="notranslate"/>
</head>
<body>
<div class="content"></div>
{% compress js file m %}
<script src="{% static 'mobile/js/utils.js' %}"></script>
<script src="{% static 'mobile/js/api.js' %}"></script>
<script src="{% static 'mobile/js/icons.js' %}"></script>
<script src="{% static 'mobile/js/VideoElement.js' %}"></script>
<script src="{% static 'mobile/js/VideoPlayer.js' %}"></script>
<script src="{% static 'mobile/js/documents.js' %}"></script>
<script src="{% static 'mobile/js/edits.js' %}"></script>
<script src="{% static 'mobile/js/item.js' %}"></script>
<script src="{% static 'mobile/js/render.js' %}"></script>
<script src="{% static 'mobile/js/main.js' %}"></script>
{% endcompress %}
</body>
</html>

View file

@ -26,6 +26,7 @@ import edit.views
import itemlist.views
import item.views
import item.site
import mobile.views
import translation.views
import urlalias.views
@ -47,6 +48,7 @@ urlpatterns = [
re_path(r'^collection/(?P<id>.*?)/icon(?P<size>\d*).jpg$', documentcollection.views.icon),
re_path(r'^documents/(?P<id>[A-Z0-9]+)/(?P<size>\d*)p(?P<page>[\d,]*).jpg$', document.views.thumbnail),
re_path(r'^documents/(?P<id>[A-Z0-9]+)/(?P<name>.*?\.[^\d]{3})$', document.views.file),
re_path(r'^documents/(?P<fragment>.*?)$', document.views.document),
re_path(r'^edit/(?P<id>.*?)/icon(?P<size>\d*).jpg$', edit.views.icon),
re_path(r'^list/(?P<id>.*?)/icon(?P<size>\d*).jpg$', itemlist.views.icon),
re_path(r'^text/(?P<id>.*?)/icon(?P<size>\d*).jpg$', text.views.icon),
@ -65,6 +67,7 @@ urlpatterns = [
re_path(r'^robots.txt$', app.views.robots_txt),
re_path(r'^sitemap.xml$', item.views.sitemap_xml),
re_path(r'^sitemap(?P<part>\d+).xml$', item.views.sitemap_part_xml),
re_path(r'm/(?P<fragment>.*?)$', mobile.views.index),
path(r'', item.site.urls),
]
#sould this not be enabled by default? nginx should handle those